QB64 Phoenix Edition
Zelda 64 (Zelda Clone by Cobalt) - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://qb64phoenix.com/forum/forumdisplay.php?fid=3)
+---- Forum: Games (https://qb64phoenix.com/forum/forumdisplay.php?fid=57)
+---- Thread: Zelda 64 (Zelda Clone by Cobalt) (/showthread.php?tid=2287)



Zelda 64 (Zelda Clone by Cobalt) - SMcNeill - 12-23-2023

After taking a peek at Craz1000's Master Sword game (based on the NES game Zelda) reminded me of my Zelda Clone I started in March 2018! So I brought it up, deleted all the code and started from scratch!
And here is my past Weeks worth of work on it!

Temporary controls(Defaults)

Letter controls are UPPER CASE!

A - Start Button
B - Select Button (change selection(option) in game selection screen)
Space Bar - Button A (attack)
Enter - Button B(not used yet)
Arrow Keys - Map navigation, letter selection

The Title Scroll works!
The Game Selection menus all work, Pick a game to resume, Register a name, and Elimination Mode.
Once Registering and picking your character you can Explore the map.
At the moment the map is empty, no creatures to combat, No caves or dungeons to enter. You do start with the first sword so blast and slash away!

took me a few hours to get the map traversing done, took 4 DAYS to get the title screen and game selection screens working!

Really putting this up here to see what people think of the Title screen and Selection screens, and to see if anyone can break those parts.

I should warn you it is possible to get stuck, if you change map screens and the next screen bottle necks down you can wind up stuck in rock. There is no way to undo this yet, you have to quit.

As I do not have the OPTIONS screen done yet, there is one option you can manually play with if you like, the Scale option. There are 3 settings; LINE 116:G.Scale_Factor = 1
1- Small(actual game size) 256x224px
2- Normal 512x448px
3- Large 768x672px

at scale 1 a debugging map of the game is displayed at the top of the screen, the yellow square is you.

(developed in 2.0.2, but tested on 1.4,1.5,and 1.6 all work[should work with all versions back to 1.1build82])



Code: (Select All)
'Zelda Clone take 2

Type ControllerKeys
KBCon_Up As Long
KBCon_Down As Long
KBCon_Left As Long
KBCon_Right As Long
KBCon_Select As Long
KBCon_Start As Long
KBCon_A_Button As Long
KBCon_B_Button As Long
End Type

Type Game_Data
Impactflag As _Byte
Scale_Factor As _Byte
Scale_X As _Byte
Scale_Y As _Byte
NextScreen As _Byte
Wtime As _Byte
Atime As _Byte
Wframe As _Byte
Aframe As _Byte
Projectile_Count As _Byte
LoadedGame As _Byte 'which game is loaded?(1-3)
End Type

Type Projectile_Data
Id As _Byte ' Kind of projectile; Sword\Arrow\Rock\Ball
Xloc As Integer ' Projectile location
Yloc As Integer '
Direction As _Byte 'Direction Projectile is traveling
Hits As _Byte ' Hits per projectile\(AKA:damage) in half heart increments
Owner As _Byte ' Who shot the projectile
End Type

Type Links_Data
'-----Position data-----
World As _Byte ' Player in Overworld or Underworld
World_X As _Byte ' Overworld X position
World_Y As _Byte ' Overworld Y position
Tile_X As _Unsigned _Byte 'Array X location:for Collision\entrances
Tile_Y As _Byte ' Array Y location:for Collision\entrances
Screen_X As Integer ' X Position on screen
Screen_Y As Integer ' Y Position on screen
Direction As _Byte ' Direction player is moving\facing
'-----------------------
'------Status Data------
Hearts As _Byte ' Units of health: 2 units(halves) per heart
Containers As _Byte 'Max number of health: total full hearts
Hits As _Byte ' Used when Link has defence rings;Blue = 2 hits per 1\2 heart, Red = 4 hits per 1\2 heart
'-----------------------
'------Items Data-------
Sword As _Byte ' which Sword does player have? Wooden-1,Silver-2,Magical-3
Weapon As _Byte 'Which Weapon is in hand A? Wooden-1,Silver-2,Magical-3,Wand-4
Ring As _Byte 'which does player have? 0-none, 1-blue,2-red
'-----------------------
'------Extra Data-------
Action As _Byte ' is player; using an item, Aquiring an item\sword, or aquiring a piece of the triforce?
Shot As _Byte ' player has shot sword
Projectile_id As _Byte '
Played As _Unsigned _Byte 'how many times has player played?
Beaten As _Byte ' Has player beaten Game 1? Game 2?
'-----------------------
End Type

Type Map_Data
Id As _Unsigned _Byte 'Tile id
Hidden As _Byte ' is there something under the tile?
Burnable As _Byte ' can the tile be burnt with candle?
Pushable As _Byte ' can the tile be moved by pushing?
PushableXtra As _Byte 'can the tile be moved by pushing with braclet?
Is_Shop As _Byte ' is there a shop here?(shop\gift\gamble)
Walkable As _Byte ' can the tile be walk upon?
End Type


Const TRUE = -1, FALSE = Not TRUE, None = 0
Const Up = 3, Right = 2, Left = 1, Down = 0, SELECT_BUTTON = 4, START_BUTTON = 5, BUTTON_B = 6, BUTTON_A = 7
Const OverWorld = 0, UnderWorld = 1
Const Walking = 1, Useing = 2, GetItem = 3, GetTriforce = 4, Attack = 5
Const Key_Right = 19712, Key_Left = 19200, Key_Up = 18432, Key_Down = 20480
Const Key_Space = 32, Key_Enter = 13
Const Default_Key_Right = 19712, Default_Key_Left = 19200, Default_Key_Up = 18432, Default_Key_Down = 20480
Const Default_A_Button = 32, Default_B_Button = 13, Default_Start_Button = 65, Default_Select_Button = 66
Const Sword = 1, Arrow = 2, Rock = 3, Ball = 4, Boomerang = 5
Const Player = 1, Monster = 2
Const Item = 0, Slash = 1, Stairs = 2, SwordShot = 3

Dim Shared Layer(16) As Long, Hyrule(255, 87) As Map_Data, Link As Links_Data, Reset_Link As Links_Data
Dim Shared C As ControllerKeys, G As Game_Data, P(16) As Projectile_Data, Letter(44) As String * 1
Dim Shared Offset_X(3) As Integer, Offset_Y(3) As Integer, Cave(15, 10) As Map_Data
Dim Shared BGM(8) As Long, SFX(10) As Long, FFX(1) As Long
Dim Shared Records(3) As Links_Data, Nick(3) As String * 8 'loading\registering\elimination

Screen _NewImage(800, 600, 32)

Layer(0) = _Display
Layer(1) = _NewImage(800, 600, 32) 'temp layer
Layer(2) = _NewImage(640, 480, 256) 'palettized sprite sheet for color shifting
Layer(3) = _NewImage(800, 600, 32) 'Map background prebuild layer
Layer(4) = _NewImage(800, 600, 32) 'Mob layer
Layer(5) = _NewImage(800, 600, 32) 'Sprite layer, moveable\burnable items + bomb holes + pickups
Layer(6) = _NewImage(12288, 4224, 32) 'PreBuilt Map, upto 300%, for easier map scrolling.
Layer(8) = _NewImage(800, 600, 32) 'debug map display
Layer(16) = _NewImage(800, 600, 32) 'temp

MFI_Loader "Zelda.MFI"

_ClearColor _RGB32(31), Layer(7)
_ClearColor _RGB32(116), Layer(12)
_ScreenMove 10, 10


'==================================
G.Scale_Factor = 1
G.Scale_X = 16 * G.Scale_Factor - 1
G.Scale_Y = 16 * G.Scale_Factor - 1
Link.Screen_X = Offset_X(G.Scale_Factor) + (16 * G.Scale_Factor * 7) + 8 * G.Scale_Factor '392
Link.Screen_Y = Offset_Y(G.Scale_Factor) + (16 * G.Scale_Factor * 5) '292
Nick(0) = "": Nick(1) = "": Nick(2) = "": Nick(3) = ""
'==================================

'OPEN "debug.txt" FOR OUTPUT AS #6
Build_Map_Screen 16 * Link.World_X, 11 * Link.World_Y
ClearLayer Layer(6)
Build_Map_in_Totallity 'prebuild the entire map at the current scale factor
ClearLayer Layer(1)
_Font FFX(0), Layer(1)
_Font FFX(0), Layer(16)
Title_Screen
Select_Screen

Do
Select Case Get_Input
Case BUTTON_A
If G.Aframe = 0 And G.Atime = 0 Then _SndPlay SFX(Slash): Link.Action = Attack: Press = Press + 1
Check_Link_Sword_Shot
Case Up
If Link.Action <> Attack Then Link.Direction = Up: Link.Action = Walking
Case Down
If Link.Action <> Attack Then Link.Direction = Down: Link.Action = Walking
Case Right
If Link.Action <> Attack Then Link.Direction = Right: Link.Action = Walking
Case Left
If Link.Action <> Attack Then Link.Direction = Left: Link.Action = Walking
Case Else
If Link.Action = Walking Then Link.Action = None
End Select

If Link.Action = GetItem Or Link.Action = GetTriforce Then
If Not _SndPlaying(Temp&) Then Link.Action = None
End If
'------Graphx build------
_PutImage , Layer(3), Layer(1)
If Link.Action = Walking Then Move_Link
If Link.Shot Then Move_Sword_Shot
If G.Impactflag Then Impact 0, 0
Place_Link
' _PRINTSTRING (0, 0), STR$(Link.Tile_X) + STR$(Link.Tile_Y) + STR$(G.Projectile_Count), Layer(1)
If G.Scale_Factor = 1 Then _PutImage , Layer(8), Layer(1)
_Dest Layer(1)
Line (100 + 2 * Link.Tile_X, 0 + 2 * Link.Tile_Y)-Step(1, 1), _RGB32(255, 255, 0), BF
_PutImage , Layer(1), Layer(0)
ClearLayer Layer(1)
'------------------------
If InKey$ = Chr$(27) Then ExitFlag%% = TRUE
_Limit 60
Loop Until ExitFlag%%


Sub Add_Projectile (What%%, Who%%)
Select Case What%%
Case Sword
P(G.Projectile_Count).Owner = Who%%
P(G.Projectile_Count).Id = Sword
P(G.Projectile_Count).Direction = Link.Direction
If Who%% = Player Then
P(G.Projectile_Count).Xloc = Link.Screen_X
P(G.Projectile_Count).Yloc = Link.Screen_Y
Else
End If
G.Projectile_Count = G.Projectile_Count + 1
End Select
End Sub

Sub Remove_Projectile (What%%, Who%%)
Select Case What%%
Case Sword
If Who%% = Player Then
G.Projectile_Count = G.Projectile_Count - 1
End If
End Select
End Sub

Sub Build_Cave_Screen
For Y%% = 0 To 10
For X%% = 0 To 15
Place_Tile_On_Screen (16 * G.Scale_Factor) * X%%, (16 * G.Scale_Factor) * Y%%, Cave(X%%, Y%%).Id, Layer(3)
Next
Next
End Sub

Sub Build_Map_Screen (Map_X~%%, Map_Y%%)
_Dest Layer(8)
For Y%% = 0 To 10
For X%% = 0 To 15
Place_Tile_On_Screen (16 * G.Scale_Factor) * X%%, (16 * G.Scale_Factor) * Y%%, Hyrule(Map_X~%% + X%%, Map_Y%% + Y%%).Id, Layer(3)
Next
Next
For Y%% = 0 To 87
For x~%% = 0 To 255
If Hyrule(x~%%, Y%%).Walkable = FALSE Then Line (100 + 2 * x~%%, 0 + 2 * Y%%)-Step(1, 1), _RGB32(255), BF
Next
Next
_Dest Layer(0)
End Sub

Sub Build_Map_in_Totallity
For Y%% = 0 To 87
For X~%% = 0 To 255
tile~%% = Hyrule(X~%%, Y%%).Id
Gy% = 17 * (tile~%% \ 20) 'get which row it comes from
Gx% = 17 * (tile~%% Mod 20) 'which column position
_PutImage ((16 * G.Scale_Factor) * X~%%, (16 * G.Scale_Factor) * Y%%)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(6), (1 + Gx%, 1 + Gy%)-Step(15, 15)
Next
Next
End Sub

Sub Check_Link_Location
Ax% = Link.World_X * 16 * (16 * G.Scale_Factor) 'gets the Left most pixel point for the current map screen
Ay% = Link.World_Y * 11 * (16 * G.Scale_Factor) 'gets the Top most pixel point for the current map screen
Tx~%% = (Ax% + Link.Screen_X - Offset_X(G.Scale_Factor) + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent x-offset+50% sprite size
Ty%% = (Ay% + Link.Screen_Y - Offset_Y(G.Scale_Factor) - 2 + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent y-offset+50% sprite size
If Hyrule(Tx~%%, Ty%%).Is_Shop Then Enter_Shop Hyrule(Tx~%%, Ty%%).Is_Shop

End Sub

Sub Enter_Shop (Which%%)
End Sub

Sub Check_Link_Sword_Shot 'Can Link shoot his sword?
If Link.Hearts = Link.Containers * 2 Then 'Link has full hearts and can shoot
If Not _SndPlaying(SFX(SwordShot)) Then 'Link did not just shoot
If Not G.Impactflag Then 'Link's last shot has finished
If Not Link.Shot Then
_SndPlay SFX(SwordShot)
Link.Shot = TRUE
Add_Projectile Sword, Player
End If
End If
End If
End If
End Sub

Sub ClearLayer (L&)
_Dest L&
Cls
_Dest _Display
End Sub

Sub ClearLayerTrans (L&)
_Dest L&
Cls , 0
_Dest _Display
End Sub

Sub DarkenImage (Image As Long, Value_From_0_To_1 As Single)
If Value_From_0_To_1 <= 0 Or Value_From_0_To_1 >= 1 Or _PixelSize(Image) <> 4 Then Exit Sub
Dim Buffer As _MEM: Buffer = _MemImage(Image) 'Get a memory reference to our image
Dim Frac_Value As Long: Frac_Value = Value_From_0_To_1 * 65536 'Used to avoid slow floating point calculations
Dim O As _Offset, O_Last As _Offset
O = Buffer.OFFSET 'We start at this offset
O_Last = Buffer.OFFSET + _Width(Image) * _Height(Image) * 4 'We stop when we get to this offset
'use on error free code ONLY!
$Checking:Off
Do
_MemPut Buffer, O, _MemGet(Buffer, O, _Unsigned _Byte) * Frac_Value \ 65536 As _UNSIGNED _BYTE
_MemPut Buffer, O + 1, _MemGet(Buffer, O + 1, _Unsigned _Byte) * Frac_Value \ 65536 As _UNSIGNED _BYTE
_MemPut Buffer, O + 2, _MemGet(Buffer, O + 2, _Unsigned _Byte) * Frac_Value \ 65536 As _UNSIGNED _BYTE
O = O + 4
Loop Until O = O_Last
'turn checking back on when done!
$Checking:On
_MemFree Buffer
End Sub

Sub Fade_Out (L&)
For n! = 1 To 0.5 Step -0.05
i2& = _CopyImage(L&)
DarkenImage i2&, n!
_PutImage (0, 0), i2&, Layer(0)
_FreeImage i2&
_Delay .03
Next
End Sub

Sub Fade_In (L&)
For n! = 0.01 To 1 Step 0.05
i2& = _CopyImage(L&)
DarkenImage i2&, n!
_PutImage (0, 0), i2&, Layer(0)
_FreeImage i2&
_Delay .03
Next
End Sub

Function Find_First_Available%% (Which%%, Start%%)
Selection%% = Start%% 'always start at the first saved game slot then check
Do 'lets find the first available selection (if there are any saved games)
If Selection%% < 4 Then
If Which%% = 0 Then If RTrim$(Nick(Selection%%)) = "" Then Selection%% = Selection%% + 1 Else Good_Selection%% = TRUE
If Which%% = 1 Then If RTrim$(Nick(Selection%%)) = "" Then Good_Selection%% = TRUE Else Selection%% = Selection%% + 1
Else '4 and 5 are always good selections
Good_Selection%% = TRUE
End If
Loop Until Good_Selection%%
Find_First_Available = Selection%%
End Function

Function Get_Input%% ()
Result%% = TRUE '-1 for no input
' SELECT CASE G.ControlType
' CASE TRUE 'Keyboard input
If _KeyDown(C.KBCon_Up) Then Result%% = Up
If _KeyDown(C.KBCon_Down) Then Result%% = Down
If _KeyDown(C.KBCon_Left) Then Result%% = Left
If _KeyDown(C.KBCon_Right) Then Result%% = Right
If _KeyDown(C.KBCon_Select) Then Result%% = SELECT_BUTTON: ' DO: LOOP WHILE _KEYDOWN(C.KBCon_Select)
If _KeyDown(C.KBCon_Start) Then Result%% = START_BUTTON: ' DO: LOOP WHILE _KEYDOWN(C.KBCon_Start)
If _KeyDown(C.KBCon_A_Button) Then Result%% = BUTTON_A: ' DO: LOOP WHILE _KEYDOWN(C.KBCon_A_Button)
If _KeyDown(C.KBCon_B_Button) Then Result%% = BUTTON_B: ' DO: LOOP WHILE _KEYDOWN(C.KBCon_B_Button)
' CASE FALSE 'joystick input
'IF C.Control_Pad THEN
'IF NOT G.Flag THEN DO: LOOP WHILE _DEVICEINPUT(C.Control_Pad)
'IF NOT C.BAD_Pad THEN
' nul%% = AxisPower(CJR%%, CJL%%, CJU%%, CJD%%) 'read directional axis values
' IF CJU%% THEN Result%% = Up
' IF CJD%% THEN Result%% = Down
' IF CJL%% THEN Result%% = Left
' IF CJR%% THEN Result%% = Right
'ELSE
' IF _BUTTON(C.Joy_Button_Up) THEN Result%% = Up ': Joy_Lock_Button (C.Joy_Button_Up)
' IF _BUTTON(C.Joy_Button_Down) THEN Result%% = Down ': Joy_Lock_Button (C.Joy_Button_Down)
' IF _BUTTON(C.Joy_Button_Left) THEN Result%% = Left ': Joy_Lock_Button (C.Joy_Button_Left)
' IF _BUTTON(C.Joy_Button_Right) THEN Result%% = Right ': Joy_Lock_Button (C.Joy_Button_Right)
' END IF
' IF _BUTTON(C.Joy_Select) THEN Result%% = SELECT_BUTTON: Joy_Lock_Button (C.Joy_Select)
' IF _BUTTON(C.Joy_Start) THEN Result%% = START_BUTTON: Joy_Lock_Button (C.Joy_Start)
' IF _BUTTON(C.Joy_A_Button) THEN Result%% = BUTTON_A: Joy_Lock_Button (C.Joy_A_Button)
' IF _BUTTON(C.Joy_B_Button) THEN Result%% = BUTTON_B: Joy_Lock_Button (C.Joy_B_Button)
' END IF
' END SELECT
Get_Input = Result%%
End Function

Sub Link_Attack
Select Case Link.Direction
Case Up
Ox%% = 0: Oy%% = -14 * G.Scale_Factor
Case Down
Ox%% = 0: Oy%% = 14 * G.Scale_Factor
Case Left
Ox%% = -14 * G.Scale_Factor + G.Aframe * (4 * G.Scale_Factor): Oy%% = 0
Case Right
Ox%% = 14 * G.Scale_Factor - G.Aframe * (4 * G.Scale_Factor): Oy%% = 0
End Select
Select Case G.Aframe
Case 0
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 17 * (Link.Direction + 8), 137)-Step(15, 15)
Case 1
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 17 * (Link.Direction + 8), 137)-Step(15, 15)
_PutImage (Link.Screen_X + Ox%%, Link.Screen_Y + Oy%%)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 51 * Link.Weapon, 171 + 17 * Link.Direction)-Step(15, 15)
Case 2
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 34 * Link.Direction + 17, 137)-Step(15, 15)
_PutImage (Link.Screen_X + Ox%%, Link.Screen_Y + Oy%%)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 51 * Link.Weapon + 17, 171 + 17 * Link.Direction)-Step(15, 15)
Case 3
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 34 * Link.Direction + 0, 137)-Step(15, 15)
_PutImage (Link.Screen_X + Ox%%, Link.Screen_Y + Oy%%)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 51 * Link.Weapon + 34, 171 + 17 * Link.Direction)-Step(15, 15)
Case Else 'attack animation finished
G.Atime = 0: G.Aframe = 0: Link.Action = None
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 34 * Link.Direction + 17 * Frame%%, 137)-Step(15, 15)
End Select
_KeyClear
End Sub

Function Link_Collision%% (Dir%%)
Result%% = FALSE 'start at no collision
'get links center point x\y tile position to check for collision
Ax% = Link.World_X * 16 * (16 * G.Scale_Factor) 'gets the Left most pixel point for the current map screen
Ay% = Link.World_Y * 11 * (16 * G.Scale_Factor) 'gets the Top most pixel point for the current map screen
'we now have the tile that Links center pixel is in!
Select Case Dir%%
Case Up
Tx~%% = (Ax% + Link.Screen_X - Offset_X(G.Scale_Factor) + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent x-offset+50% sprite size
Ty%% = (Ay% + Link.Screen_Y - Offset_Y(G.Scale_Factor) - 2 + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent y-offset+50% sprite size
If Not Hyrule(Tx~%%, Ty%%).Walkable Then Result%% = TRUE
Case Down
Tx~%% = (Ax% + Link.Screen_X - Offset_X(G.Scale_Factor) + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent x-offset+50% sprite size
Ty%% = (2 + Ay% + Link.Screen_Y - Offset_Y(G.Scale_Factor) + 2 + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent y-offset+50% sprite size
If Not Hyrule(Tx~%%, Ty%%).Walkable Then Result%% = TRUE
Case Left
Tx~%% = (Ax% + Link.Screen_X - Offset_X(G.Scale_Factor) - 2 + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent x-offset+50% sprite size
Ty%% = (Ay% + Link.Screen_Y - Offset_Y(G.Scale_Factor) + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent y-offset+50% sprite size
If Not Hyrule(Tx~%%, Ty%%).Walkable Then Result%% = TRUE
Case Right
Tx~%% = (2 + Ax% + Link.Screen_X - Offset_X(G.Scale_Factor) + 2 + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent x-offset+50% sprite size
Ty%% = (Ay% + Link.Screen_Y - Offset_Y(G.Scale_Factor) + (16 * G.Scale_Factor \ 2)) \ 16 * G.Scale_Factor 'now add curent y-offset+50% sprite size
If Not Hyrule(Tx~%%, Ty%%).Walkable Then Result%% = TRUE
End Select
Link.Tile_X = Tx~%%
Link.Tile_Y = Ty%%
Link_Collision = Result%%
End Function

Sub Move_Link
Select Case Link.Direction
Case Up
If Not Link_Collision(Up) Then 'nothing blocking Link
If Link.Screen_Y > Offset_Y(G.Scale_Factor) Then 'Link is not at the edge of the screen
Link.Screen_Y = Link.Screen_Y - 2 * G.Scale_Factor
Else 'player is at edge of screen to shift to next one.
G.NextScreen = Up
Shift_New_Map_Screen
End If
End If
Case Down
If Not Link_Collision(Down) Then 'nothing blocking Link
If Link.Screen_Y < (Offset_Y(G.Scale_Factor) + (16 * G.Scale_Factor * 10)) Then 'Link is not at the edge of the screen
Link.Screen_Y = Link.Screen_Y + 2 * G.Scale_Factor
Else 'player is at edge of screen to shift to next one.
G.NextScreen = Down
Shift_New_Map_Screen
End If
End If
Case Left
If Not Link_Collision(Left) Then 'nothing blocking Link
If Link.Screen_X > Offset_X(G.Scale_Factor) Then 'Link is not at the edge of the screen
Link.Screen_X = Link.Screen_X - 2 * G.Scale_Factor
Else 'player is at edge of screen to shift to next one.
G.NextScreen = Left
Shift_New_Map_Screen
End If
End If
Case Right
If Not Link_Collision(Right) Then 'nothing blocking Link
If Link.Screen_X < (Offset_X(G.Scale_Factor) + (16 * G.Scale_Factor * 15)) Then 'Link is not at the edge of the screen
Link.Screen_X = Link.Screen_X + 2 * G.Scale_Factor
Else 'player is at edge of screen to shift to next one.
G.NextScreen = Right
Shift_New_Map_Screen
End If
End If
End Select
End Sub

Sub Move_Sword_Shot
Static Xloc As Integer, Yloc As Integer, Direction As _Byte, Fstp As _Byte, Frame As _Byte
If Direction = -1 Or Xloc = 0 Then 'if no direction assigned then assign one
Direction = Link.Direction
Xloc = Link.Screen_X
Yloc = Link.Screen_Y
End If
Select Case Direction
Case Up
Yloc = Yloc - 4 * G.Scale_Factor
Case Down
Yloc = Yloc + 4 * G.Scale_Factor
Case Left
Xloc = Xloc - 4 * G.Scale_Factor
Case Right
Xloc = Xloc + 4 * G.Scale_Factor
End Select
_PutImage (Xloc, Yloc)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 17 * Frame + 68 * Direction, 239)-Step(15, 15)
Select Case G.Scale_Factor
Case 1
If Xloc <= 272 Or Xloc >= 514 Or Yloc <= 212 Or Yloc >= 372 Then Done%% = TRUE
Case 2
If Xloc <= 140 Or Xloc >= 630 Or Yloc <= 100 Or Yloc >= 430 Then Done%% = TRUE
Case 3
If Xloc <= 16 Or Xloc >= 744 Or Yloc <= 96 Or Yloc >= 559 Then Done%% = TRUE
End Select
If Done%% Then Link.Shot = FALSE: G.Impactflag = TRUE: Impact Xloc, Yloc: Direction = -1: Remove_Projectile Sword, Player
Fstp = Fstp + 1
If Fstp = 2 Then Fstp = 0: Frame = Frame + 1
If Frame = 4 Then Frame = 0
End Sub

Sub Impact (X%, Y%)
Static Frame As _Byte, Fstp As _Byte, Xloc(3) As Integer, Yloc(3) As Integer
If Frame = -1 Or Xloc(2) = 0 Then
Fstp = 0
For i%% = 0 To 3: Xloc(i%%) = X% + 8 * G.Scale_Factor: Yloc(i%%) = Y% + 8 * G.Scale_Factor: Next i%%
End If
Xloc(0) = Xloc(0) - G.Scale_Factor: Yloc(0) = Yloc(0) - G.Scale_Factor
Xloc(1) = Xloc(1) + G.Scale_Factor: Yloc(1) = Yloc(1) - G.Scale_Factor
Xloc(2) = Xloc(2) + G.Scale_Factor: Yloc(2) = Yloc(2) + G.Scale_Factor
Xloc(3) = Xloc(3) - G.Scale_Factor: Yloc(3) = Yloc(3) + G.Scale_Factor
For i%% = 0 To 3
Select Case i%%
Case 0
_PutImage (Xloc(i%%) - 16, Yloc(i%%) - 16)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (205 + 17 * Frame, 205)-Step(15, 15)
Case 1
_PutImage (Xloc(i%%) + 16, Yloc(i%%) - 16)-Step(-G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (205 + 17 * Frame, 205)-Step(15, 15)
Case 2
_PutImage (Xloc(i%%) + 16, Yloc(i%%) + 16)-Step(-G.Scale_X, -G.Scale_Y), Layer(7), Layer(1), (205 + 17 * Frame, 205)-Step(15, 15)
Case 3
_PutImage (Xloc(i%%) - 16, Yloc(i%%) + 16)-Step(G.Scale_X, -G.Scale_Y), Layer(7), Layer(1), (205 + 17 * Frame, 205)-Step(15, 15)
End Select
Next i%%
Fstp = Fstp + 1
Frame = Frame + 1
If Frame = 4 Then Frame = 0
If Fstp = 16 Then Frame = -1: G.Impactflag = FALSE
End Sub

Sub Place_Link
Static Ftime As _Byte, Frame As _Byte
If Link.Action = Walking Then 'while Link is moving
G.Wtime = G.Wtime + 1 'Increment frame time
If G.Wtime = 8 Then
If G.Wframe Then G.Wframe = 0 Else G.Wframe = 1 'change frame
G.Wtime = 0 'reset frame time
End If
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 34 * Link.Direction + 17 * G.Wframe, 137)-Step(15, 15)
ElseIf Link.Action = Useing Then 'when Link uses an item
Ftime = Ftime + 1 'Increment frame time
If Ftime = 32 Then Link.Action = None: Ftime = 0 'action is done
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 17 * (Link.Direction + 8), 137)-Step(15, 15)
ElseIf Link.Action = GetItem Then 'When Link gets a sword\item or buys something
'Held while music plays
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 17 * 12, 137)-Step(15, 15)
ElseIf Link.Action = GetTriforce Then 'When Link recovers a Triforce piece
'Held while music plays
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 17 * 13, 137)-Step(15, 15)
ElseIf Link.Action = Attack Then
G.Atime = G.Atime + 1 'Increment frame time
If G.Atime = 4 Then G.Aframe = G.Aframe + 1: G.Atime = 0 'change frame:reset frame time
Link_Attack
Else 'Link is standing Still(Action=None)
G.Atime = 0: G.Aframe = 0
G.Wtime = 0: G.Wframe = 0
_PutImage (Link.Screen_X, Link.Screen_Y)-Step(G.Scale_X, G.Scale_Y), Layer(7), Layer(1), (1 + 34 * Link.Direction + 17 * Frame%%, 137)-Step(15, 15)
End If
End Sub

Sub Place_Player_Record (I%%, Where%)
Select Case Where%
Case 0
If Records(I%% + 1).Beaten Then _PutImage (260, 228 + 48 * I%%)-Step(15, 31), Layer(12), Layer(16), (64, 247)-Step(7, 15) 'Player 1 Sword
_PutImage (236, 234 + 48 * I%%)-Step(31, 31), Layer(12), Layer(16), (1 + 17 * Records(I%% + 1).Ring, 230)-Step(15, 15) 'Player 1 Link (green)
_PrintString (284, 232 + 48 * I%%), RTrim$(Nick(I%% + 1)), Layer(16) 'player 1 name
_PrintString (284, 248 + 48 * I%%), Left$(" ", 3 - Len(LTrim$(RTrim$(Str$(Records(I%% + 1).Played))))) + LTrim$(Str$(Records(I%% + 1).Played)), Layer(16) 'player 1 tries
For j%% = 1 To Records(I%% + 1).Containers
If j%% < 4 Then 'first 3 hearts are red
_PutImage (428 + 16 * j%%, 232 + 48 * I%%)-Step(15, 15), Layer(12), Layer(16), (52, 230)-Step(7, 7) 'Player 1 hearts red
Else
If j%% < 9 Then
_PutImage (428 + 16 * j%%, 232 + 48 * I%%)-Step(15, 15), Layer(12), Layer(16), (73, 267)-Step(7, 7) 'Player 1 hearts white
Else
_PutImage (428 + 16 * (j%% - 8), 232 + 64 * I%%)-Step(15, 15), Layer(12), Layer(16), (73, 267)-Step(7, 7) 'Player 1 hearts white
End If
End If
Next j%%
Case 1
If Records(I%% + 1).Beaten Then _PutImage (326, 148 + 48 * (I%% - 1))-Step(15, 31), Layer(12), Layer(16), (64, 247)-Step(7, 15) 'Player 1 Sword
_PutImage (300, 154 + 48 * (I%%))-Step(31, 31), Layer(12), Layer(16), (1 + 17 * Records(I%% + 1).Ring, 230)-Step(15, 15) 'Player 1 Link (green)
_PrintString (364, 152 + 48 * (I%%)), RTrim$(Nick(I%% + 1)), Layer(1)

End Select
End Sub

Sub Place_Tile_On_Screen (X%, Y%, Tile~%%, L&)
Gy% = 17 * (Tile~%% \ 20) 'get which row it comes from
Gx% = 17 * (Tile~%% Mod 20) 'which column position
_PutImage (Offset_X(G.Scale_Factor) + X%, Offset_Y(G.Scale_Factor) + Y%)-Step(G.Scale_X, G.Scale_Y), Layer(7), L&, (1 + Gx%, 1 + Gy%)-Step(15, 15)
End Sub

Sub Scroll_Screen_II (Dir%%)
Cx% = Offset_X(G.Scale_Factor) 'top left corner location of map displayed
Cy% = Offset_Y(G.Scale_Factor)
Sfx% = 16 * 16 * G.Scale_Factor 'size of the map display
Sfy% = 11 * 16 * G.Scale_Factor
Lwx% = 16 * 16 * G.Scale_Factor * Link.World_X 'map area link is in
Lwy% = 11 * 16 * G.Scale_Factor * Link.World_Y
Select Case Dir%%
Case Up
For y% = 0 To Sfy% Step 2 * G.Scale_Factor
_PutImage (Cx%, Cy%)-Step(Sfx%, Sfy%), Layer(6), Layer(1), (Lwx%, Lwy% - y%)-Step(Sfx%, Sfy%)
If y% > 16 * G.Scale_Factor Then Link.Screen_Y = Link.Screen_Y + 2 * G.Scale_Factor
Place_Link
_Limit 60
_PutImage , Layer(1), Layer(0)
Next
Link.World_Y = Link.World_Y - 1
Case Down
For y% = 0 To Sfy% Step 2 * G.Scale_Factor
_PutImage (Cx%, Cy%)-Step(Sfx%, Sfy%), Layer(6), Layer(1), (Lwx%, Lwy% + y%)-Step(Sfx%, Sfy%)
If y% > 16 * G.Scale_Factor Then Link.Screen_Y = Link.Screen_Y - 2 * G.Scale_Factor
Place_Link
_Limit 60
_PutImage , Layer(1), Layer(0)
Next
Link.World_Y = Link.World_Y + 1
Case Left
For x% = 0 To Sfx% Step 2 * G.Scale_Factor
_PutImage (Cx%, Cy%)-Step(Sfx%, Sfy%), Layer(6), Layer(1), (Lwx% - x%, Lwy%)-Step(Sfx%, Sfy%)
If x% > 16 * G.Scale_Factor Then Link.Screen_X = Link.Screen_X + 2 * G.Scale_Factor
Place_Link
_Limit 60
_PutImage , Layer(1), Layer(0)
Next
Link.World_X = Link.World_X - 1
Case Right
For x% = 0 To Sfx% Step 2 * G.Scale_Factor
_PutImage (Cx%, Cy%)-Step(Sfx%, Sfy%), Layer(6), Layer(1), (Lwx% + x%, Lwy%)-Step(Sfx%, Sfy%)
If x% > 16 * G.Scale_Factor Then Link.Screen_X = Link.Screen_X - 2 * G.Scale_Factor
Place_Link
_Limit 60
_PutImage , Layer(1), Layer(0)
Next
Link.World_X = Link.World_X + 1
End Select
Place_Link
Lwx% = 16 * 16 * G.Scale_Factor * Link.World_X
Lwy% = 11 * 16 * G.Scale_Factor * Link.World_Y
_PutImage (Cx%, Cy%)-Step(Sfx%, Sfy%), Layer(6), Layer(3), (Lwx%, Lwy%)-Step(Sfx%, Sfy%) 'move new screen to layer(3)
End Sub

Sub Shift_New_Map_Screen
Select Case G.NextScreen
Case Up
Scroll_Screen_II Up
Case Down
Scroll_Screen_II Down
Case Left
Scroll_Screen_II Left
Case Right
Scroll_Screen_II Right
End Select
G.NextScreen = -1
End Sub

Sub Title_Screen
_ClearColor _RGB32(21), Layer(9)
_ClearColor _RGB32(21), Layer(10)
_SndVol BGM(0), .33
_SndLoop BGM(0)
Do
F%% = 0: F% = 0: ExitFlag%% = FALSE
Do: _Limit 60: Loop While _SndGetPos(BGM(0)) > 10
Do
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (0, 0)-Step(255, 223)
Select Case F%%
Case 12 To 18
_PutImage (400 - 74, 300 - 128)-Step(143, 143), Layer(9), Layer(1), (289, 0)-Step(71, 71)
Case 19 To 24
_PutImage (400 - 74, 300 - 128)-Step(143, 143), Layer(9), Layer(1), (289, 0 + 72)-Step(71, 71)
Case 25 To 36
_PutImage (400 - 74, 300 - 128)-Step(143, 143), Layer(9), Layer(1), (289, 0 + 144)-Step(71, 71)
Case 37 To 52
_PutImage (400 - 74, 300 - 128)-Step(143, 143), Layer(9), Layer(1), (289, 0 + 72)-Step(71, 71)
Case 53 To 59
_PutImage (400 - 74, 300 - 128)-Step(143, 143), Layer(9), Layer(1), (289, 0 + 0)-Step(71, 71)
End Select
_PutImage (304, 523 - 112), Layer(10), Layer(1), (0 + 64 * wave%%, 0)-Step(63, 111)
_PutImage , Layer(1), Layer(0)
_Limit 90
F%% = F%% + 1
If F%% = 60 Then F%% = 0
If F%% Mod 2 = 0 Then wave%% = wave%% + 1
If wave%% = 16 Then wave%% = 0
If Get_Input = START_BUTTON Then ExitFlag%% = TRUE
Loop Until _SndGetPos(BGM(0)) > 8.4 Or ExitFlag%%

If Not ExitFlag%% Then
'start the title fade
_Dest Layer(1)
F%% = 0
Do
Select Case F%
Case 0 To 13
Line (144, 76)-Step(511, 447), _RGB32(202, 241, 159), BF
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (361, 0)-Step(255, 223)
Case 13 To 24
Line (144, 76)-Step(511, 447), _RGB32(182, 216, 255), BF
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (361, 0)-Step(255, 223)
Case 25 To 34
Line (144, 76)-Step(511, 447), _RGB32(166, 229, 255), BF
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (361, 0)-Step(255, 223)
Case 35 To 42
Line (144, 76)-Step(511, 447), _RGB32(165, 238, 223), BF
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (617, 0)-Step(255, 223)
Case 43 To 48
Line (144, 76)-Step(511, 447), _RGB32(37, 190, 255), BF
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (617, 0)-Step(255, 223)
Case 49 To 52
Line (144, 76)-Step(511, 447), _RGB32(0, 109, 181), BF
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (617, 0)-Step(255, 223)
Case 53 To 57
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (873, 0)-Step(255, 223)
Wf% = 112
Case 58 To 61
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (1129, 0)-Step(255, 223)
Wf% = 224
Case 62 To 363
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (1385, 0)-Step(255, 223)
Wf% = 336
Case 364 To 385
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (1641, 0)-Step(255, 223)
Wf% = 448
Case 386 To 393
_PutImage ((800 - 512) \ 2, (600 - 448) \ 2)-Step(511, 447), Layer(9), Layer(1), (1897, 0)-Step(255, 223)
Wf% = 560
End Select
_PutImage (304, 523 - 112), Layer(10), Layer(1), (0 + 64 * wave%%, 0 + Wf%)-Step(63, 111)
_PutImage , Layer(1), Layer(0)
_Limit 90
F% = F% + 1
If F% = 394 Then ExitFlag%% = TRUE
If F% Mod 2 = 0 Then wave%% = wave%% + 1
If wave%% = 16 Then wave%% = 0
If Get_Input = START_BUTTON Then ExitFlag%% = TRUE
Loop Until ExitFlag%%
ExitFlag%% = FALSE
End If
ClearLayer Layer(0)
ClearLayer Layer(1)
If Not ExitFlag%% Then
'Title scroll
Do: _Limit 60: If Get_Input = START_BUTTON Then ExitFlag%% = TRUE
Loop Until _SndGetPos(BGM(0)) > 16 Or ExitFlag%%
F% = 0
If Not ExitFlag%% Then
Do
Select Case F%
Case 0 To 223
_PutImage (144, 76)-Step(511, 447), Layer(11), Layer(1), (0, -223 + F%)-Step(255, 223)
Case Is >= 354
If blink% Then
_PutImage (72, 332)-Step(7, 15), Layer(7), Layer(11), (247, 154)-Step(7, 15) 'heart
_PutImage (72, 464)-Step(7, 15), Layer(7), Layer(11), (213, 171)-Step(7, 15) 'Ruby
_PutImage (120, 1432)-Step(15, 15), Layer(7), Layer(11), (239, 188)-Step(15, 15) 'Triforce
Else
_PutImage (72, 332)-Step(7, 15), Layer(7), Layer(11), (239, 154)-Step(7, 15) 'heart
_PutImage (72, 464)-Step(7, 15), Layer(7), Layer(11), (205, 171)-Step(7, 15) 'Ruby
_PutImage (120, 1432)-Step(15, 15), Layer(7), Layer(11), (222, 188)-Step(15, 15) 'Triforce
End If
If Fblink% Then
_PutImage (72, 400)-Step(7, 15), Layer(7), Layer(11), (256, 188)-Step(7, 15) 'fairy blank
_PutImage (72, 400)-Step(7, 15), Layer(7), Layer(11), (281, 154)-Step(7, 15) 'fairy
Else
_PutImage (72, 400)-Step(7, 15), Layer(7), Layer(11), (256, 188)-Step(7, 15) 'fairy blank
_PutImage (72, 400)-Step(7, 15), Layer(7), Layer(11), (273, 154)-Step(7, 15) 'fairy
End If
_PutImage (144, 76)-Step(511, 447), Layer(11), Layer(1), (0, F% - 354)-Step(255, 223)
End Select
_PutImage , Layer(1), Layer(0)
_Limit 30
F% = F% + 1
If F% = 1762 Then F% = F% - 1 'ExitFlag%% = TRUE
B% = B% + 1
If B% = 4 Then blink% = Not blink%: B% = 0
If B% Mod 2 = 0 Then Fblink% = Not Fblink%
If Get_Input = START_BUTTON Then ExitFlag%% = TRUE
Loop Until _SndGetPos(BGM(0)) >= 79.75 Or ExitFlag%%
ExitFlag%% = FALSE
End If
End If

Loop Until ExitFlag%%
_Dest Layer(0)
_SndStop BGM(0)
Do: Loop Until Get_Input%% = -1

End Sub

Function Projectile_Collision%%
Result%% = FALSE
For i%% = 0 To G.Projectile_Count
Next
Projectile_Collision = Result%%
End Function

Sub Select_Screen
ClearLayer Layer(16)
If _FileExists("Zelda.MSF") Then 'load saved data
Open "Zelda.MSF" For Binary As #1
For I%% = 1 To 3 'load all 3 records
Get #1, , Nick(I%%)
Get #1, , Records(I%%)
If Selection%% = 0 Then If RTrim$(Nick(I%%)) <> "" Then Selection%% = I%%
Next I%%
Close #1
Else 'file doesn't exist so make it.
Reset_Record 1
Reset_Record 2
Reset_Record 3
Save_Records
End If
_PutImage (140, 72)-Step(511, 447), Layer(12), Layer(16), (1, 1)-Step(255, 223) 'background
For I%% = 1 To 3
If RTrim$(Nick(I%%)) <> "" Then Place_Player_Record I%% - 1, 0
Next I%%
If Record_Count%% = 0 Then Selection%% = 4 Else Selection%% = 1
Selection%% = Find_First_Available(0, 1)
Do
_PutImage , Layer(16), Layer(1)
Select Case Get_Input%%
Case START_BUTTON
Select Case Selection%%
Case 1 To 3
Link = Records(Selection%%)
Exitflag%% = TRUE
Case 4
Do: Loop Until Get_Input%% = -1
nul%% = Register(nul%%)
Open "Zelda.MSF" For Binary As #1 'update records
For I%% = 1 To 3
Put #1, , Nick(I%%)
Put #1, , Link
If RTrim$(Nick(I%%)) <> "" Then Place_Player_Record I%% - 1, 0
Next I%%
Close #1
Case 5
Do: Loop Until Get_Input%% = -1
Elimination_Mode
nul%% = Register(nul%%) 'go straight to register mode after elimination
End Select
Case SELECT_BUTTON
Selection%% = Selection%% + 1
If Selection%% = 6 Then Selection%% = 1
Selection%% = Find_First_Available(0, Selection%%)
Do: Loop Until Get_Input%% = -1
Case Else
_PrintString (0, 20), Str$(SELECT_BUTTON), Layer(1)
End Select

Select Case Selection%%
Case 1
_PutImage (220, 242)-Step(15, 15), Layer(12), Layer(1), (73, 247)-Step(7, 7) 'Player 1
Case 2
_PutImage (220, 290)-Step(15, 15), Layer(12), Layer(1), (73, 247)-Step(7, 7) 'Player 2
Case 3
_PutImage (220, 338)-Step(15, 15), Layer(12), Layer(1), (73, 247)-Step(7, 7) 'Player 3
Case 4
_PutImage (220, 394)-Step(15, 15), Layer(12), Layer(1), (73, 247)-Step(7, 7) 'register
Case 5
_PutImage (220, 426)-Step(15, 15), Layer(12), Layer(1), (73, 247)-Step(7, 7) 'Elimination
End Select
_PrintString (0, 0), Str$(Selection%%), Layer(1)
_PutImage , Layer(1), Layer(0)
_Limit 60
If InKey$ = Chr$(27) Then Exitflag%% = TRUE
Loop Until Exitflag%%
End Sub

Function Register%% (Records%%)
Dim Names(2, 8) As String * 1
Result%% = Records%%
Tmp& = _CopyImage(Layer(16))
ClearLayer Layer(16)
ClearLayer Layer(1)
_PutImage (140, 72)-Step(511, 447), Layer(12), Layer(16), (258, 1)-Step(255, 223) 'background
For i%% = 1 To 3
If RTrim$(Nick(i%%)) <> "" Then Place_Player_Record i%% - 1, 1
Next i%%
If i%% > 0 Then Selection%% = i%% Else Selection%% = 1
For i%% = 1 To 3
If RTrim$(Nick(i%%)) = "" Then _PutImage (300, 154 + 48 * (i%% - 1))-Step(31, 31), Layer(12), Layer(16), (1, 230)-Step(15, 15) 'Player 1 Link (green)
Next i%%
_ClearColor _RGB32(0), Layer(16)
_PutImage , Layer(16), Layer(1)
_Dest Layer(1)
_PrintMode _KeepBackground , Layer(1)
Current_Letter%% = 1
Selection%% = Find_First_Available(1, 1)
Do

Select Case Get_Input%%
Case Up
_PutImage (236 + 32 * Lx%, 328 + 32 * Ly%)-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'Current selected Letter
Ly% = Ly% - 1
If Ly% = -1 Then Ly% = 3
Current_Letter%% = Current_Letter%% - 11
If Current_Letter%% < 0 Then Current_Letter%% = 44 - Abs(Current_Letter%%)
Case Down
_PutImage (236 + 32 * Lx%, 328 + 32 * Ly%)-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'Current selected Letter
Ly% = Ly% + 1
If Ly% = 4 Then Ly% = 0
Current_Letter%% = Current_Letter%% + 11
If Current_Letter%% > 44 Then Current_Letter%% = Current_Letter%% - 44
Case Left
_PutImage (236 + 32 * Lx%, 328 + 32 * Ly%)-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'Current selected Letter
Lx% = Lx% - 1
If Lx% = -1 Then Lx% = 10: Ly% = Ly% - 1: If Ly% = -1 Then Ly% = 3
Current_Letter%% = Current_Letter%% - 1
If Current_Letter%% = 0 Then Current_Letter%% = 44
Case Right
_PutImage (236 + 32 * Lx%, 328 + 32 * Ly%)-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'Current selected Letter
Lx% = Lx% + 1
If Lx% = 11 Then Lx% = 0: Ly% = Ly% + 1: If Ly% = 4 Then Ly% = 0
Current_Letter%% = Current_Letter%% + 1
If Current_Letter%% = 45 Then Current_Letter%% = 1
Case BUTTON_A Or BUTTON_B
If Selection%% <> 4 Then 'only allow buttons if valid name entry selection
_PutImage (364 + 16 * Length%%, 152 + 48 * (Selection%% - 1))-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'Current Nick Letter
Names(Selection%% - 1, Length%%) = Letter(Current_Letter%%)
Length%% = Length%% + 1
If Length%% = 8 Then Length%% = 0
End If
Case START_BUTTON
Select Case Selection%%
Case 4 'end
For j%% = 0 To 2
a$ = ""
If RTrim$(Nick(j%% + 1)) = "" Then
For i%% = 0 To 7
If Asc(Names(j%%, i%%)) > 31 Then a$ = a$ + Names(j%%, i%%)
Next
Nick(j%% + 1) = a$
End If
Next
ExitFlag%% = TRUE
End Select
Case SELECT_BUTTON 'Change to different name or end registration
_PutImage (364 + 16 * Length%%, 152 + 48 * (Selection%% - 1))-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'Current Nick Letter
_PutImage (274, 152 + 48 * (Selection%% - 1))-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'heart selection
Selection%% = Selection%% + 1: Length%% = 0 'reset the name position when changing.
If Selection%% = 5 Then Selection%% = 1
_PrintString (0, 0), Str$(Selection%%), Layer(1)
Selection%% = Find_First_Available(1, Selection%%)
Case Else
Line (0, 0)-Step(160, 40), _RGB32(0), BF
_PrintString (0, 20), Str$(Selection%%), Layer(1)
End Select
Do: Loop Until Get_Input%% = -1

_PutImage (274, 152 + 48 * (Selection%% - 1))-Step(15, 15), Layer(12), Layer(1), (73, 247)-Step(7, 7) 'heart selection
If Selection%% <> 4 Then
For j%% = 0 To 8
If Names(Selection%% - 1, j%%) > Chr$(31) Then _PrintString (364 + 16 * j%%, 152 + 48 * (Selection%% - 1)), Names(Selection%% - 1, j%%), Layer(1)
Next j%%
End If
_PutImage , Layer(1), Layer(0)
If blink%% And Selection%% <> 4 Then
_PutImage (364 + 16 * Length%%, 152 + 48 * (Selection%% - 1))-Step(15, 15), Layer(12), Layer(1), (61, 230)-Step(7, 7) 'Current Nick Letter
_PutImage (236 + 32 * Lx%, 328 + 32 * Ly%)-Step(15, 15), Layer(12), Layer(1), (61, 230)-Step(7, 7) 'Current selected Letter
Else
_PutImage (364 + 16 * Length%%, 152 + 48 * (Selection%% - 1))-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'Current Nick Letter
_PutImage (236 + 32 * Lx%, 328 + 32 * Ly%)-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'Current selected Letter
End If
_PutImage , Layer(16), Layer(1)
b%% = b%% + 1
If b%% = 8 Then blink%% = Not blink%%: b%% = 0
_Limit 60
If InKey$ = Chr$(27) Then ExitFlag%% = TRUE
Loop Until ExitFlag%%
ClearLayer Layer(16)
_PutImage , Tmp&, Layer(16)
_FreeImage Tmp&
Save_Records
For i%% = 1 To 3
If RTrim$(Nick(i%%)) <> "" Then Place_Player_Record i%% - 1, 0
Next i%%
Register = Result%%
End Function

Sub Elimination_Mode
Tmp& = _CopyImage(Layer(16))
ClearLayer Layer(16)
ClearLayer Layer(1)
_PutImage (140, 72)-Step(511, 447), Layer(12), Layer(16), (515, 1)-Step(255, 223) 'background
For i%% = 1 To 3
If RTrim$(Nick(i%%)) <> "" Then Place_Player_Record i%% - 1, 1
Next i%%
_PutImage , Layer(16), Layer(0)
If i%% > 0 Then Selection%% = i%% Else Selection%% = 1
For i%% = 1 To 3 'remove the erased game from the background screens
If RTrim$(Nick(i%%)) = "" Then _PutImage (300, 154 + 48 * (i%% - 1))-Step(31, 31), Layer(12), Layer(16), (1, 230)-Step(15, 15) 'Player 1 Link (green)
Next i%%
_ClearColor _RGB32(0), Layer(16)
_PutImage , Layer(16), Layer(1)
_Dest Layer(1)
_PrintMode _KeepBackground , Layer(1)
Current_Letter%% = 1
Selection%% = 1
Do
_PutImage , Layer(16), Layer(1)
Select Case Get_Input%%
Case START_BUTTON
Select Case Selection%%
Case 1 To 3
Nick(Selection%%) = ""
Reset_Record Selection%%
_PutImage (364, 152 + 48 * (Selection%% - 1))-Step(159, 31), Layer(12), Layer(16), (86, 240)-Step(7, 7) 'black out
_PutImage (236, 232 + 48 * (Selection%% - 1))-Step(159, 33), Layer(12), Tmp&, (86, 240)-Step(7, 7) 'black out name
_PutImage (428, 232 + 48 * (Selection%% - 1))-Step(127, 31), Layer(12), Tmp&, (86, 240)-Step(7, 7) 'black out hearts
Case 4
ExitFlag%% = TRUE
End Select
Case SELECT_BUTTON
_PutImage (274, 152 + 48 * (Selection%% - 1))-Step(15, 15), Layer(12), Layer(1), (86, 240)-Step(7, 7) 'heart selection black out
Selection%% = Selection%% + 1
If Selection%% = 5 Then Selection%% = 1
Case Else
_PrintString (0, 20), Str$(SELECT_BUTTON), Layer(1)
End Select
Do: Loop Until Get_Input%% = -1
_PutImage (274, 152 + 48 * (Selection%% - 1))-Step(15, 15), Layer(12), Layer(1), (73, 267)-Step(7, 7) 'heart selection
_PutImage , Layer(1), Layer(0)
_Limit 60
If InKey$ = Chr$(27) Then ExitFlag%% = TRUE
Loop Until ExitFlag%%
ClearLayer Layer(16)
_PutImage , Tmp&, Layer(16)
_FreeImage Tmp&
End Sub

Sub Reset_Record (Which%%)
Records(Which%%) = Reset_Link
End Sub

Sub Save_Records
Open "Zelda.MSF" For Binary As #1
For I%% = 1 To 3
Put #1, , Nick(I%%)
Put #1, , Records(I%%)
Next I%%
Close #1
End Sub

Sub MFI_Loader (FN$)
Dim Size(128) As Long, FOffset(128) As Long
Open FN$ For Binary As #1
Get #1, , c~%% 'retrieve number of files
For I~%% = 1 To c~%%
Get #1, , FOffset(I~%%)
Get #1, , Size(I~%%)
FOffset&(I~%%) = FOffset&(I~%%) + 1
Next I~%%
Layer(7) = LoadGFX(FOffset(1), Size(1)) '_LOADIMAGE("overworldtiles.bmp", 32)
Layer(9) = LoadGFX(FOffset(2), Size(2)) '_LOADIMAGE("TitleScreen.bmp", 32)
Layer(10) = LoadGFX(FOffset(3), Size(3)) '_LOADIMAGE("Titlefalls.bmp", 32)
Layer(11) = LoadGFX(FOffset(4), Size(4)) '_LOADIMAGE("Titlescroll.bmp", 32)
Layer(12) = LoadGFX(FOffset(5), Size(5)) '_LOADIMAGE("selectionscreen.bmp", 32)

SFX(0) = LoadSFX(FOffset(6), Size(6))
SFX(1) = LoadSFX(FOffset(7), Size(7))
SFX(2) = LoadSFX(FOffset(8), Size(8))
SFX(3) = LoadSFX(FOffset(9), Size(9))
BGM(0) = LoadSFX(FOffset(10), Size(10))
FFX(0) = LoadFFX(FOffset(11), Size(11), 16)
LoadData FOffset(12), Size(12)

Close #1
If _FileExists("temp.dat") Then Kill "temp.dat"
End Sub

Function LoadGFX& (Foff&, Size&)
If _FileExists("temp.dat") Then Kill "temp.dat"
Open "temp.dat" For Binary As #3
dat$ = Space$(Size&)
Get #1, Foff&, dat$
Put #3, , dat$
Close #3
LoadGFX& = _LoadImage("temp.dat", 32)
End Function

Function LoadFFX& (Foff&, Size&, Fize%%)
If _FileExists("temp.dat") Then Kill "temp.dat"
Open "temp.dat" For Binary As #3
dat$ = Space$(Size&)
Get #1, Foff&, dat$
Put #3, , dat$
Close #3
LoadFFX& = _LoadFont("temp.dat", Fize%%, "monospace")
End Function

Function LoadSFX& (Foff&, Size&)
If _FileExists("temp.dat") Then Kill "temp.dat"
Open "temp.dat" For Binary As #3
dat$ = Space$(Size&)
Get #1, Foff&, dat$
Put #3, , dat$
Close #3
LoadSFX& = _SndOpen("temp.dat")
End Function

Sub LoadData (Foff&, Size&)
If _FileExists("temp.dat") Then Kill "temp.dat"
Open "temp.dat" For Binary As #3
dat$ = Space$(Size&)
Get #1, Foff&, dat$
Put #3, , dat$
Close #3

F1 = FreeFile
Open "temp.dat" For Binary As #F1
Get #F1, , Hyrule()
Get #F1, , Link
Get #F1, , C
Get #F1, , G
Get #F1, , Offset_X()
Get #F1, , Offset_Y()
For I%% = 1 To 44
Get #F1, , Letter(I%%)
Next I%%
Close #F1

End Sub


.mfi   Zelda.MFI (Size: 1.74 MB / Downloads: 60)


RE: Zelda 64 (Zelda Clone by Cobalt) - SMcNeill - 12-23-2023

@Cobalt Again, can you share the latest version of this with us?   This is the version I had bookmarked, and it's well out of date.  This needs a nice spot to sit highlighted as well, as it's also one impressive piece of work with porting a NES game over to QB64.  Wink


RE: Zelda 64 (Zelda Clone by Cobalt) - grymmjack - 07-20-2024

Please post screenshots. For crying out loud.


RE: Zelda 64 (Zelda Clone by Cobalt) - Circlotron - 07-21-2024

When I try to run it I get the error

Line: 1002 (in main module)
Bad record number
Continue?

So the file "zelda.MSF" does not yet exist but it is expecting it to?

Using version 3.13.1 on Linux.