Finds all possible positions that jump either to the filename at $C602 or to the sword object at $D600.
-- This is a stand-alone script that simulates the fairy's movement
-- and checks if the conditions for a jump to the filename are met.
local MAXFRAMES = 100 -- search depth; increasing this increases computation time exponentially
local MINX, MAXX, MINY, MAXY = 5, 0x9B, 2, 0x79 -- boundaries of where the fairy can spawn
local function RNG (low,high) -- simulates the ingame RNG
low = 3 * low
if high > 85 then low = low + 1
if high > 170 then low = low + 1 end
end
low = low % 0x100
high = high + low
high = high % 0x100
return low, high
end
local function move(speed, angle, SubY, Y, SubX, X) -- moves the fairy for one frame
local DeltaX, DeltaY
if speed == 0x0A then
if angle == 0x00 then
DeltaY, DeltaX = -0x40, 0x00
elseif angle == 0x02 then
DeltaY, DeltaX = -0x3B, 0x18
elseif angle == 0x04 then
DeltaY, DeltaX = -0x2D, 0x2D
elseif angle == 0x06 then
DeltaY, DeltaX = -0x18, 0x3B
elseif angle == 0x08 then
DeltaY, DeltaX = 0x00, 0x40
elseif angle == 0x0A then
DeltaY, DeltaX = 0x18, 0x3B
elseif angle == 0x0C then
DeltaY, DeltaX = 0x2D, 0x2D
elseif angle == 0x0E then
DeltaY, DeltaX = 0x3B, 0x18
elseif angle == 0x10 then
DeltaY, DeltaX = 0x40, 0x00
elseif angle == 0x12 then
DeltaY, DeltaX = 0x3B, -0x18
elseif angle == 0x14 then
DeltaY, DeltaX = 0x2D, -0x2D
elseif angle == 0x16 then
DeltaY, DeltaX = 0x18, -0x3B
elseif angle == 0x18 then
DeltaY, DeltaX = 0x00, -0x40
elseif angle == 0x1A then
DeltaY, DeltaX = -0x18, -0x3B
elseif angle == 0x1C then
DeltaY, DeltaX = -0x2D, -0x2D
elseif angle == 0x1E then
DeltaY, DeltaX = -0x3B, -0x18
end
elseif speed == 0x14 then
if angle == 0x00 then
DeltaY, DeltaX = -0x80, 0x00
elseif angle == 0x02 then
DeltaY, DeltaX = -0x76, 0x30
elseif angle == 0x04 then
DeltaY, DeltaX = -0x5A, 0x5A
elseif angle == 0x06 then
DeltaY, DeltaX = -0x30, 0x76
elseif angle == 0x08 then
DeltaY, DeltaX = 0x00, 0x80
elseif angle == 0x0A then
DeltaY, DeltaX = 0x30, 0x76
elseif angle == 0x0C then
DeltaY, DeltaX = 0x5A, 0x5A
elseif angle == 0x0E then
DeltaY, DeltaX = 0x76, 0x30
elseif angle == 0x10 then
DeltaY, DeltaX = 0x80, 0x00
elseif angle == 0x12 then
DeltaY, DeltaX = 0x76, -0x30
elseif angle == 0x14 then
DeltaY, DeltaX = 0x5A, -0x5A
elseif angle == 0x16 then
DeltaY, DeltaX = 0x30, -0x76
elseif angle == 0x18 then
DeltaY, DeltaX = 0x00, -0x80
elseif angle == 0x1A then
DeltaY, DeltaX = -0x30, -0x76
elseif angle == 0x1C then
DeltaY, DeltaX = -0x5A, -0x5A
elseif angle == 0x1E then
DeltaY, DeltaX = -0x76, -0x30
end
elseif speed == 0x1E then
if angle == 0x00 then
DeltaY, DeltaX = -0xC0, 0x00
elseif angle == 0x02 then
DeltaY, DeltaX = -0xB1, 0x49
elseif angle == 0x04 then
DeltaY, DeltaX = -0x87, 0x87
elseif angle == 0x06 then
DeltaY, DeltaX = -0x49, 0xB1
elseif angle == 0x08 then
DeltaY, DeltaX = 0x00, 0xC0
elseif angle == 0x0A then
DeltaY, DeltaX = 0x49, 0xB1
elseif angle == 0x0C then
DeltaY, DeltaX = 0x87, 0x87
elseif angle == 0x0E then
DeltaY, DeltaX = 0xB1, 0x49
elseif angle == 0x10 then
DeltaY, DeltaX = 0xC0, 0x00
elseif angle == 0x12 then
DeltaY, DeltaX = 0xB1, -0x49
elseif angle == 0x14 then
DeltaY, DeltaX = 0x87, -0x87
elseif angle == 0x16 then
DeltaY, DeltaX = 0x49, -0xB1
elseif angle == 0x18 then
DeltaY, DeltaX = 0x00, -0xC0
elseif angle == 0x1A then
DeltaY, DeltaX = -0x49, -0xB1
elseif angle == 0x1C then
DeltaY, DeltaX = -0x87, -0x87
elseif angle == 0x1E then
DeltaY, DeltaX = -0xB1, -0x49
end
elseif speed == 0x28 then
if angle == 0x00 then
DeltaY, DeltaX = -0x100, 0x00
elseif angle == 0x02 then
DeltaY, DeltaX = -0xEC, 0x61
elseif angle == 0x04 then
DeltaY, DeltaX = -0xB5, 0xB5
elseif angle == 0x06 then
DeltaY, DeltaX = -0x61, 0xEC
elseif angle == 0x08 then
DeltaY, DeltaX = 0x00, 0x100
elseif angle == 0x0A then
DeltaY, DeltaX = 0x61, 0xEC
elseif angle == 0x0C then
DeltaY, DeltaX = 0xB5, 0xB5
elseif angle == 0x0E then
DeltaY, DeltaX = 0xEC, 0x61
elseif angle == 0x10 then
DeltaY, DeltaX = 0x100, 0x00
elseif angle == 0x12 then
DeltaY, DeltaX = 0xEC, -0x61
elseif angle == 0x14 then
DeltaY, DeltaX = 0xB5, -0xB5
elseif angle == 0x16 then
DeltaY, DeltaX = 0x61, -0xEC
elseif angle == 0x18 then
DeltaY, DeltaX = 0x00, -0x100
elseif angle == 0x1A then
DeltaY, DeltaX = -0x61, -0xEC
elseif angle == 0x1C then
DeltaY, DeltaX = -0xB5, -0xB5
elseif angle == 0x1E then
DeltaY, DeltaX = -0xEC, -0x61
end
end
SubY, SubX = SubY + DeltaY, SubX + DeltaX
if SubY < 0 then
Y = Y - 1
SubY = SubY + 0x100
end
if SubX < 0 then
X = X - 1
SubX = SubX + 0x100
end
if SubY > 0xFF then
Y = Y + 1
SubY = SubY - 0x100
end
if SubX > 0xFF then
X = X + 1
SubX = SubX - 0x100
end
return SubY, Y, SubX, X
end
local function change(low, high) -- determines new direction for the fairy
low1, high1 = RNG(low, high)
low2, high2 = RNG(low1, high1)
low3, high3 = RNG(low2, high2)
local counter = ((high1 % 0x40) - (high1 % 2)) + 8
local speed = ((high2 % 4) + 1) * 0x0A
local angle = (high3 % 0x20) - (high3 % 2)
return counter, speed, angle, low3, high3
end
local function edge(angle, Y, X) -- checks if the fairy is against the edge of the screen
if (Y <= -1 and (angle <= 0x08 or angle >= 0x16))
or (Y <= 0x04 and (angle <= 0x04 or angle >= 0x1A))
or (Y >= 0x80 and angle >= 0x06 and angle <= 0x18)
or (Y >= 0x7C and angle >= 0x0A and angle <= 0x14)
or (X <= -1 and (angle >= 0x0E or angle == 0x00))
or (X <= 0x04 and angle >= 0x12 and angle <= 0x1C)
or (X >= 0xA0 and (angle <= 0x10 or angle == 0x1E))
or (X >= 0x9C and angle >= 0x02 and angle <= 0x0C) then
return true
else
return false
end
end
-- the next functions are implementations of GameBoy opcodes
local function RLC(A)
local zero, carry = false, false
A = A << 1
if A > 0xFF then
A = A + 1 - 0x100
carry = true
end
if A == 0 then
zero = true
end
return A, zero, carry
end
local function RL(A, oldcarry)
local zero, carry = false, false
A = A << 1
if oldcarry then
A = A + 1
end
if A > 0xFF then
A = A - 0x100
carry = true
end
if A == 0 then
zero = true
end
return A, zero, carry
end
local function RRC(A)
local zero, carry = false, false
if A % 2 == 1 then
carry = true
end
A = A >> 1
if carry then
A = A + 0x80
end
if A == 0 then
zero = true
end
return A, zero, carry
end
local function RR(A, oldcarry)
local zero, carry = false, false
if A % 2 == 1 then
carry = true
end
A = A >> 1
if oldcarry then
A = A + 0x80
end
if A == 0 then
zero = true
end
return A, zero, carry
end
local function SLA(A)
local zero, carry = false, false
A = A << 1
if A > 0xFF then
A = A - 0x100
carry = true
end
if A == 0 then
zero = true
end
return A, zero, carry
end
local function SRA(A)
local zero, carry = false, false
if A % 2 == 1 then
carry = true
end
if A >= 0x80 then
A = (A >> 1) + 0x80
else
A = A >> 1
end
if A == 0 then
zero = true
end
return A, zero, carry
end
local function SWAP(A)
local zero, carry = false, false
A = ((A%0x10) << 4) + (A >> 4)
if A == 0 then
zero = true
end
return A, zero, carry
end
local function SRL(A)
local zero, carry = false, false
if A % 2 == 1 then
carry = true
end
A = A >> 1
if A == 0 then
zero = true
end
return A, zero, carry
end
local function BIT(r, A)
A = A >> r
if A % 2 == 0 then
return true
else
return false
end
end
--local function RES(r, A)
-- if (A >> r) % 2 == 0 then
-- return A
-- else
-- return A - 2 ^ r
-- end
--end
--local function SET(r, A)
-- if (A >> r) % 2 == 1 then
-- return A
-- else
-- return A + 2 ^ r
-- end
--end
local function check(globalcounter, counter, angle, SubY, Y, SubX) -- checks if the assembly code written by the fairy will cause a jump to the filename
if (SubY == 0xC2 or SubY == 0xC3 or SubY == 0xC4 or SubY == 0xCA or SubY == 0xCC or SubY == 0xCD or SubY == 0xD2 or SubY == 0xD4 or SubY ==0xDA or SubY == 0xDC) and (
(SubX >= 0xD0 and SubX <= 0xD5)
or (SubX >= 0xF0 and SubX <= 0xF5)
or ((SubX == 0xD6 or SubX == 0xF6) and Y <= 0x0A)
or ((SubX == 0xC6 or SubX == 0xE6) and Y <= 0x02) ) then
local A, zero, carry = 0xD5, false, false
local B,C = 0x00,0x01
local D,E = 0xCC,0xDB
local H,L = 0xFA,0xD5
local StackH, StackL = 0x61, 0xF5
local BC, DE = 0xE1, 0x00
if globalcounter == 0x80 then
elseif globalcounter == 0x81 then
A = 0xD6
elseif globalcounter == 0x82 then
A = 0xA1
carry = true
elseif globalcounter == 0x83 then
A = 0xB0
carry = true
elseif globalcounter == 0x84 then
A = 0xCF
carry = true
elseif globalcounter == 0x85 then
A = 0xAA
carry = true
elseif globalcounter == 0x86 then
elseif globalcounter == 0x87 then
A = 0xAA
carry = true
elseif globalcounter == 0x88 then
elseif globalcounter == 0x89 then
A = 0xD6
elseif globalcounter == 0x8A then
A = 0xA1
carry = true
elseif globalcounter == 0x8B then
A = 0xB0
carry = true
elseif globalcounter == 0x8C then
A = 0xCF
carry = true
elseif globalcounter == 0x8D then
A = 0xAA
carry = true
elseif globalcounter == 0x8E then
elseif globalcounter == 0x8F then
A = 0xAA
carry = true
elseif globalcounter == 0x90 then
elseif globalcounter == 0x91 then
A = 0xD4
elseif globalcounter == 0x92 then
A = 0x09
elseif globalcounter == 0x93 then
A = 0xFA
carry = true
elseif globalcounter == 0x94 then
A = 0xDB
carry = true
elseif globalcounter == 0x95 then
A = 0x00
zero = true
elseif globalcounter == 0x96 then
elseif globalcounter == 0x97 then
A = 0x00
zero = true
elseif globalcounter == 0x98 then
elseif globalcounter == 0x99 then
A = 0xD4
elseif globalcounter == 0x9A then
A = 0x09
elseif globalcounter == 0x9B then
A = 0xFA
carry = true
elseif globalcounter == 0x9C then
A = 0xDB
carry = true
elseif globalcounter == 0x9D then
A = 0x00
zero = true
elseif globalcounter == 0x9E then
elseif globalcounter == 0x9F then
A = 0x00
zero = true
elseif globalcounter == 0xA0 then
A = 0x00
zero = true
elseif globalcounter == 0xA1 then
A = 0x01
elseif globalcounter == 0xA2 then
A = 0xC4
elseif globalcounter == 0xA3 then
A = 0xD1
elseif globalcounter == 0xA4 then
A = 0xD0
elseif globalcounter == 0xA5 then
elseif globalcounter == 0xA6 then
A = 0x00
zero = true
elseif globalcounter == 0xA7 then
elseif globalcounter == 0xA8 then
elseif globalcounter == 0xA9 then
A = 0xD4
elseif globalcounter == 0xAA then
A = 0x19
elseif globalcounter == 0xAB then
A = 0x0E
elseif globalcounter == 0xAC then
A = 0x2F
elseif globalcounter == 0xAD then
A = 0x00
zero = true
elseif globalcounter == 0xAE then
elseif globalcounter == 0xAF then
A = 0x00
zero = true
elseif globalcounter == 0xB0 then
elseif globalcounter == 0xB1 then
elseif globalcounter == 0xB2 then
A = 0xDD
elseif globalcounter == 0xB3 then
A = 0xDF
elseif globalcounter == 0xB4 then
A = 0xFF
elseif globalcounter == 0xB5 then
elseif globalcounter == 0xB6 then
elseif globalcounter == 0xB7 then
elseif globalcounter == 0xB8 then
elseif globalcounter == 0xB9 then
elseif globalcounter == 0xBA then
elseif globalcounter == 0xBB then
carry = true
elseif globalcounter == 0xBC then
carry = true
elseif globalcounter == 0xBD then
zero = true
elseif globalcounter == 0xBE then
elseif globalcounter == 0xBF then
zero = true
elseif globalcounter == 0xC0 then
return false
elseif globalcounter == 0xC1 then
B, C = StackH, StackL
BC = 0x21
elseif globalcounter == 0xC2 then
return false
elseif globalcounter == 0xC3 then
return false
elseif globalcounter == 0xC4 then
return false
elseif globalcounter == 0xC5 then
elseif globalcounter == 0xC6 then
A = A + counter
if A == 0 then zero = true end
if A > 0xFF then
carry = true
A = A - 0x100
end
goto byte3
elseif globalcounter == 0xC7 then
return false
elseif globalcounter == 0xC8 then
elseif globalcounter == 0xC9 then
return false
elseif globalcounter == 0xCA then
goto byte3
elseif globalcounter == 0xCB then
goto prefix
elseif globalcounter == 0xCC then
goto byte3
elseif globalcounter == 0xCD then
return false
elseif globalcounter == 0xCE then
A = A + counter
if A == 0 then zero = true end
if A > 0xFF then
carry = true
A = A - 0x100
end
goto byte3
elseif globalcounter == 0xCF then
return false
elseif globalcounter == 0xD0 then
return false
elseif globalcounter == 0xD1 then
D, E = StackH, StackL
DE = 0x21
elseif globalcounter == 0xD2 then
return false
elseif globalcounter == 0xD3 then
return false
elseif globalcounter == 0xD4 then
return false
elseif globalcounter == 0xD5 then
elseif globalcounter == 0xD6 then
A = A - counter
goto byte3
elseif globalcounter == 0xD7 then
A = 0xAA
H, L = 0xFB, 0xAA
carry = true
elseif globalcounter == 0xD8 then
elseif globalcounter == 0xD9 then
return false
elseif globalcounter == 0xDA then
goto byte3
elseif globalcounter == 0xDB then
return false
elseif globalcounter == 0xDC then
goto byte3
elseif globalcounter == 0xDD then
return false
elseif globalcounter == 0xDE then
A = A - counter
goto byte3
elseif globalcounter == 0xDF then
H, L = 0xFC, 0x7F
elseif globalcounter == 0xE0 then
goto byte3
elseif globalcounter == 0xE1 then
H, L = StackH, StackL
elseif globalcounter == 0xE2 then
elseif globalcounter == 0xE3 then
return false
elseif globalcounter == 0xE4 then
return false
elseif globalcounter == 0xE5 then
elseif globalcounter == 0xE6 then
A = A & counter
if A == 0 then zero = true end
goto byte3
elseif globalcounter == 0xE7 then
return false
elseif globalcounter == 0xE8 then
goto byte3 --might crash
elseif globalcounter == 0xE9 then
return false
elseif globalcounter == 0xEA then
goto byte3
elseif globalcounter == 0xEB then
return false
elseif globalcounter == 0xEC then
return false
elseif globalcounter == 0xED then
return false
elseif globalcounter == 0xEE then
A = A ~ counter
goto byte3
elseif globalcounter == 0xEF then
return false
elseif globalcounter == 0xF0 then
goto F0
else
print(string.format("Error: globalcounter = %02X", globalcounter)); return
end
if counter == 0x01 then
goto byte4
elseif counter == 0x02 then
elseif counter == 0x03 then
C = C + 1
elseif counter == 0x04 then
B = B + 1
zero = false
elseif counter == 0x05 then
B = B - 1
if B < 0 then B = 0xFF end
zero = false
elseif counter == 0x06 then
B = 0x00
elseif counter == 0x07 then
A = A << 1
if A > 0xFF then
A = A + 1 - 0x100
carry = true
else
carry = false
end
zero = false
elseif counter == 0x08 then
return false
elseif counter == 0x09 then
H, L = H + B, L + C
if L > 0xFF then
L = L - 0x100
H = H + 1
end
if H > 0xFF then
H = H - 0x100
carry = true
else
carry = false
end
elseif counter == 0x0A then
A = BC
elseif counter == 0x0B then
C = C - 1
elseif counter == 0x0C then
C = C + 1
zero = false
elseif counter == 0x0D then
C = C - 1
if C == 0 then
zero = true
else
zero = false
end
elseif counter == 0x0E then
C = 0
elseif counter == 0x0F then
if A % 2 == 1 then
carry = true
else
carry = false
end
A = A >> 1
if carry then A = A + 0x80 end
zero = false
elseif counter == 0x10 then
return false
elseif counter == 0x11 then
goto byte4
elseif counter == 0x12 then
elseif counter == 0x13 then
E = E + 1
elseif counter == 0x14 then
D = D + 1
zero = false
elseif counter == 0x15 then
D = D - 1
zero = false
elseif counter == 0x16 then
D = 0
elseif counter == 0x17 then
A = A << 1
if carry then
A = A + 1
end
if A > 0xFF then
A = A - 0x100
carry = true
else
carry = false
end
zero = false
elseif counter == 0x18 then
elseif counter == 0x19 then
H, L = H + D, L + E
if L > 0xFF then
L = L - 0x100
H = H + 1
end
if H > 0xFF then
H = H - 0x100
carry = true
else
carry = false
end
elseif counter == 0x1A then
A = DE
elseif counter == 0x1B then
E = E - 1
elseif counter == 0x1C then
E = E + 1
zero = false
elseif counter == 0x1D then
E = E - 1
zero = false
elseif counter == 0x1E then
E = 0
elseif counter == 0x1F then
if carry then
if not (A % 2 == 1) then
carry = false
end
A = (A >> 1) + 0x80
else
if A % 2 == 1 then
carry = false
end
A = A >> 1
end
zero = false
elseif counter == 0x20 then
elseif counter == 0x21 then
goto byte4
elseif counter == 0x22 then
L = L + 1
elseif counter == 0x23 then
L = L + 1
elseif counter == 0x24 then
H = H + 1
zero = false
elseif counter == 0x25 then
H = H - 1
zero = false
elseif counter == 0x26 then
H = 0
elseif counter == 0x27 then
return true --might not work
elseif counter == 0x28 then
elseif counter == 0x29 then
H, L = 2 * H, 2 * L
if L > 0xFF then
L = L - 0x100
H = H + 1
end
if H > 0xFF then
H = H - 0x100
carry = true
else
carry = false
end
elseif counter == 0x2A then
if (H == 0xFA and L == 0xD5) or (H == 0xFB and L == 0xAA) or (H == 0xFC and L == 0x7F) then
A = 0x00
elseif H == StackH and L == StackL then
A = 0x21
else print(string.format("Error: counter = 2A, H = %02X, L = %02X", H, L))
end
L = L + 1
elseif counter == 0x2B then
L = L - 1
elseif counter == 0x2C then
L = L + 1
zero = false
elseif counter == 0x2D then
L = L - 1
zero = false
elseif counter == 0x2E then
L = 0
elseif counter == 0x2F then
A = A ~ 0xFF
elseif counter == 0x30 then
elseif counter == 0x31 then
return false
elseif counter == 0x32 then
L = L - 1
elseif counter == 0x33 then
return false
elseif counter == 0x34 then
zero = false
elseif counter == 0x35 then
zero = false
elseif counter == 0x36 then
elseif counter == 0x37 then
carry = true
elseif counter == 0x38 then
elseif counter == 0x39 then
H, L = H + 0xC2, L + 0x14
if L > 0xFF then
L = L - 0x100
H = H + 1
end
if H > 0xFF then
H = H - 0x100
carry = true
else
carry = false
end
elseif counter == 0x3A then
if (H == 0xFA and L == 0xD5) or (H == 0xFB and L == 0xAA) or (H == 0xFC and L == 0x7F) then
A = 0x00
elseif H == StackH and L == StackL then
A = 0x21
else print(string.format("Error: counter = 3A, H = %02X, L = %02X", H, L))
end
L = L - 1
elseif counter == 0x3B then
return false
elseif counter == 0x3C then
A = A + 1
if A == 0x100 then
A = 0
zero = true
else
zero = false
end
elseif counter == 0x3D then
A = A - 1
if A < 0 then
A = 0xFF
else
if A == 0 then
zero = true
else
zero = false
end
end
elseif counter == 0x3E then
A = 0
elseif counter == 0x3F then
if counter then
counter = false
else
counter = true
end
elseif counter == 0x40 then
elseif counter == 0x41 then
B = C
elseif counter == 0x42 then
B = D
elseif counter == 0x43 then
B = E
elseif counter == 0x44 then
B = H
elseif counter == 0x45 then
B = L
elseif counter == 0x46 then
if (H == 0xFA and L == 0xD5) or (H == 0xFB and L == 0xAA) or (H == 0xFC and L == 0x7F) then
B = 0x00
elseif H == StackH and L == StackL then
B = 0x21
else print(string.format("Error: counter = 46, H = %02X, L = %02X", H, L)); return
end
else
print(string.format("Error: counter = %02X", counter)); return
end
::byte3::
if angle == 0x00 then
elseif angle == 0x01 then
return false
elseif angle == 0x02 then
elseif angle == 0x03 then
elseif angle == 0x04 then
if B == 0xFF then
zero = true
else
zero = false
end
elseif angle == 0x05 then
if B == 0x01 then
zero = true
else
zero = false
end
elseif angle == 0x06 then
return false
elseif angle == 0x07 then
if A >= 0x80 then
carry = true
else
carry = false
end
zero = false
elseif angle == 0x08 then
return false
elseif angle == 0x09 then
H, L = H + B, L + C
if L > 0xFF then
H = H + 1
end
if H > 0xFF then
carry = true
else
carry = false
end
elseif angle == 0x0A then
elseif angle == 0x0B then
elseif angle == 0x0C then
if C == 0xFF then
zero = true
else
zero = false
end
elseif angle == 0x0D then
if C == 0x01 then
zero = true
else
zero = false
end
elseif angle == 0x0E then
return false
elseif angle == 0x0F then
if A % 2 == 1 then
carry = true
else
carry = false
end
zero = false
elseif angle == 0x10 then
return false
elseif angle == 0x11 then
return false
elseif angle == 0x12 then
elseif angle == 0x13 then
elseif angle == 0x14 then
if D == 0xFF then
zero = true
else
zero = false
end
elseif angle == 0x15 then
if D == 0x01 then
zero = true
else
zero = false
end
elseif angle == 0x16 then
return false
elseif angle == 0x17 then
if A >= 0x80 then
carry = true
else
carry = false
end
zero = false
elseif angle == 0x18 then
return false
elseif angle == 0x19 then
H, L = H + D, L + E
if L > 0xFF then
H = H + 1
end
if H > 0xFF then
carry = true
else
carry = false
end
elseif angle == 0x1A then
elseif angle == 0x1B then
elseif angle == 0x1C then
if E == 0xFF then
zero = true
else
zero = false
end
elseif angle == 0x1D then
if E == 0x01 then
zero = true
else
zero = false
end
elseif angle == 0x1E then
return false
end
::byte4::
if SubY == 0xC2 then
if not zero then
return true
else
return false
end
elseif SubY == 0xC3 then
return true
elseif SubY == 0xC4 then
if not zero then
return true
else
return false
end
elseif SubY == 0xCA then
if zero then
return true
else
return false
end
elseif SubY == 0xCC then
if zero then
return true
else
return false
end
elseif SubY == 0xCD then
return true
elseif SubY == 0xD2 then
if not carry then
return true
else
return false
end
elseif SubY == 0xD4 then
if not carry then
return true
else
return false
end
elseif SubY == 0xDA then
if carry then
return true
else
return false
end
elseif SubY == 0xDC then
if carry then
return true
else
return false
end
else print(string.format("Error: SubY = %02X", SubY))
end
::prefix::
--if counter == 0x00 then
-- B, zero, carry = RLC(B)
if counter == 0x01 then
C, zero, carry = RLC(C)
elseif counter == 0x02 then
D, zero, carry = RLC(D)
elseif counter == 0x03 then
E, zero, carry = RLC(E)
elseif counter == 0x04 then
H, zero, carry = RLC(H)
elseif counter == 0x05 then
L, zero, carry = RLC(L)
elseif counter == 0x06 then
zero, carry = true, false
elseif counter == 0x07 then
A, zero, carry = RLC(A)
elseif counter == 0x08 then
B, zero, carry = RRC(B)
elseif counter == 0x09 then
C, zero, carry = RRC(C)
elseif counter == 0x0A then
D, zero, carry = RRC(D)
elseif counter == 0x0B then
E, zero, carry = RRC(E)
elseif counter == 0x0C then
H, zero, carry = RRC(H)
elseif counter == 0x0D then
L, zero, carry = RRC(L)
elseif counter == 0x0E then
zero, carry = true, false
elseif counter == 0x0F then
A, zero, carry = RRC(A)
elseif counter == 0x10 then
B, zero, carry = RL(B, carry)
elseif counter == 0x11 then
C, zero, carry = RL(C, carry)
elseif counter == 0x12 then
D, zero, carry = RL(D, carry)
elseif counter == 0x13 then
E, zero, carry = RL(E, carry)
elseif counter == 0x14 then
H, zero, carry = RL(H, carry)
elseif counter == 0x15 then
L, zero, carry = RL(L, carry)
elseif counter == 0x16 then
zero, carry = true, false
elseif counter == 0x17 then
A, zero, carry = RL(A, carry)
elseif counter == 0x18 then
B, zero, carry = RR(B, carry)
elseif counter == 0x19 then
C, zero, carry = RR(C, carry)
elseif counter == 0x1A then
D, zero, carry = RR(D, carry)
elseif counter == 0x1B then
E, zero, carry = RR(E, carry)
elseif counter == 0x1C then
H, zero, carry = RR(H, carry)
elseif counter == 0x1D then
L, zero, carry = RR(L, carry)
elseif counter == 0x1E then
zero, carry = true, false
elseif counter == 0x1F then
A, zero, carry = RR(A, carry)
elseif counter == 0x20 then
B, zero, carry = SLA(B)
elseif counter == 0x21 then
C, zero, carry = SLA(C)
elseif counter == 0x22 then
D, zero, carry = SLA(D)
elseif counter == 0x23 then
E, zero, carry = SLA(E)
elseif counter == 0x24 then
H, zero, carry = SLA(H)
elseif counter == 0x25 then
L, zero, carry = SLA(L)
elseif counter == 0x26 then
zero, carry = true, false
elseif counter == 0x27 then
A, zero, carry = SLA(A)
elseif counter == 0x28 then
B, zero, carry = SRA(B)
elseif counter == 0x29 then
C, zero, carry = SRA(C)
elseif counter == 0x2A then
D, zero, carry = SRA(D)
elseif counter == 0x2B then
E, zero, carry = SRA(E)
elseif counter == 0x2C then
H, zero, carry = SRA(H)
elseif counter == 0x2D then
L, zero, carry = SRA(L)
elseif counter == 0x2E then
zero, carry = true, false
elseif counter == 0x2F then
A, zero, carry = SRA(A)
elseif counter == 0x30 then
B, zero, carry = SWAP(B)
elseif counter == 0x31 then
C, zero, carry = SWAP(C)
elseif counter == 0x32 then
D, zero, carry = SWAP(D)
elseif counter == 0x33 then
E, zero, carry = SWAP(E)
elseif counter == 0x34 then
H, zero, carry = SWAP(H)
elseif counter == 0x35 then
L, zero, carry = SWAP(L)
elseif counter == 0x36 then
zero, carry = true, false
elseif counter == 0x37 then
A, zero, carry = SWAP(A)
elseif counter == 0x38 then
B, zero, carry = SRL(B)
elseif counter == 0x39 then
C, zero, carry = SRL(C)
elseif counter == 0x3A then
D, zero, carry = SRL(D)
elseif counter == 0x3B then
E, zero, carry = SRL(E)
elseif counter == 0x3C then
H, zero, carry = SRL(H)
elseif counter == 0x3D then
L, zero, carry = SRL(L)
elseif counter == 0x3E then
zero, carry = true, false
elseif counter == 0x3F then
A, zero, carry = SRL(A)
elseif counter == 0x40 then
zero = BIT(0, B)
elseif counter == 0x41 then
zero = BIT(0, C)
elseif counter == 0x42 then
zero = BIT(0, D)
elseif counter == 0x43 then
zero = BIT(0, E)
elseif counter == 0x44 then
zero = BIT(0, H)
elseif counter == 0x45 then
zero = BIT(0, L)
elseif counter == 0x46 then
zero = true
else print(string.format("Error: counter = %02X", counter)); return
end
goto byte3
::F0::
if counter == 0x01 then
A = 0x00
elseif counter == 0x02 then
A = 0x00
elseif counter == 0x03 then
A = 0x00
elseif counter == 0x04 then
A = 0x01
elseif counter == 0x05 then
A = 0x00
elseif counter == 0x06 then
A = 0x00
elseif counter == 0x07 then
A = 0x00
elseif counter == 0x08 then
A = 0x00
elseif counter == 0x09 then
A = 0xFF
elseif counter == 0x0A then
A = 0x00
elseif counter == 0x0B then
A = 0x4F
elseif counter == 0x0C then
A = 0x00
elseif counter == 0x0D then
A = 0x7B
elseif counter == 0x0E then
A = 0x00
elseif counter == 0x0F then
A = 0x00
elseif counter == 0x10 then
A = 0x00
elseif counter == 0x11 then
A = 0x28
elseif counter == 0x12 then
A = 0x00
elseif counter == 0x13 then
A = 0x00
elseif counter == 0x14 then
A = 0x00
elseif counter == 0x15 then
A = 0x00
elseif counter == 0x16 then
A = 0x00
elseif counter == 0x17 then
A = 0x00
elseif counter == 0x18 then
A = 0x00
elseif counter == 0x19 then
A = 0x00
elseif counter == 0x1A then
A = 0xC1
elseif counter == 0x1B then
A = 0x08
elseif counter == 0x1C then
A = 0x08
elseif counter == 0x1D then
A = 0x70
elseif counter == 0x1E then
A = 0x00
elseif counter == 0x1F then
A = 0x00
elseif counter == 0x20 then
A = 0x02
elseif counter == 0x21 then
A = 0x00
elseif counter == 0x22 then
A = 0x06
elseif counter == 0x23 then
A = 0x5F
elseif counter == 0x24 then
A = 0x80
elseif counter == 0x25 then
A = 0x00
elseif counter == 0x26 then
A = 0x06
elseif counter == 0x27 then
A = 0x06
elseif counter == 0x28 then
A = 0x00
elseif counter == 0x29 then
A = 0x01
elseif counter == 0x2A then
A = 0x00
elseif counter == 0x2B then
A = 0x00
elseif counter == 0x2C then
A = 0x00
elseif counter == 0x2D then
A = 0x00
elseif counter == 0x2E then
A = 0x00
elseif counter == 0x2F then
A = 0x00
elseif counter == 0x30 then
A = 0x10
elseif counter == 0x31 then
A = 0x54
elseif counter == 0x32 then
A = 0x54
elseif counter == 0x33 then
A = 0x00
elseif counter == 0x34 then
A = 0x00
elseif counter == 0x35 then
A = 0x00
elseif counter == 0x36 then
A = 0x00
elseif counter == 0x37 then
A = 0x00
elseif counter == 0x38 then
A = 0x00
elseif counter == 0x39 then
A = 0x00
elseif counter == 0x3A then
A = 0x00
elseif counter == 0x3B then
A = 0x00
elseif counter == 0x3C then
A = 0x00
elseif counter == 0x3D then
A = 0x00
elseif counter == 0x3E then
A = 0x00
elseif counter == 0x3F then
A = 0x00
elseif counter == 0x40 then
A = 0x00
elseif counter == 0x41 then
A = 0x00
elseif counter == 0x42 then
A = 0x00
elseif counter == 0x43 then
A = 0x00
elseif counter == 0x44 then
A = 0x00
elseif counter == 0x45 then
A = 0x00
elseif counter == 0x46 then
A = 0x00
end
goto byte3
else
return false
end
end
local lowlist, highlist = {}, {} -- a list of all possible RNG seeds in the game
local low, high = 0x0D, 0x37 -- initial seed after boot-up
for i = 1, 43534 do
lowlist[i], highlist[i] = low, high
low, high = RNG(low, high)
end
local reverseRNG = {} -- takes a seed and returns the index in the list
for i = 0, 0xFFFF do
reverseRNG[i] = {}
end
for i = 1, 43534 do
reverseRNG[lowlist[i]][highlist[i]] = i
end
local function main (InitialCounter, InitialSpeed, InitialAngle, InitialLo, InitialHi, Index)
local m1, m2, m3 = {}, {}, {} -- lists to store all the hits
local RNis, frames, slashes, maxslashes, SubYs, Ys, SubXs, Xs = {}, {}, {}, {}, {}, {}, {}, {}
for InitialX = MINX, MAXX do
for InitialY = MINY, MAXY do
local SubY, Y, SubX, X = 0, InitialY, 0, InitialX
local counter, speed, angle = InitialCounter, InitialSpeed, InitialAngle
local oldcounter = InitialCounter + 6
local low, high = InitialLo, InitialHi
-- first the fairy moves in the initial direction for 6 frames
for i = 1, 6 do
if edge(angle, Y, X) then -- if the fairy hits the edge of the screen here, it simply waits until the 6 frames are over
break
end
SubY, Y, SubX, X = move(speed, angle, SubY, Y, SubX, X)
end
local framesum = 0 -- how much time has passed
local i = 0
while true do
if counter == 1 or edge(angle, Y, X) then
i = i + 1
slashes[i] = -1
frames[i] = oldcounter - counter + 1
maxslashes[i] = math.ceil(frames[i] / 4) -- one slash takes 4 frames; rounding up here may overestimate the max number of slashes
if i > 1 then
for j = math.max(i-3, 1), i-1 do
local framesum, slashsum = 0, 0
for k = j, i-1 do
framesum = framesum + frames[k]
slashsum = slashsum + slashes[k]
end
if 4 * slashsum > framesum then
maxslashes[i] = maxslashes[i] - 1 -- the overestimation is corrected here
break
end
end
end
RNi = reverseRNG[low][high]
RNis[i] = RNi
SubYs[i], Ys[i], SubXs[i], Xs[i] = SubY, Y, SubX, X
::redo::
slashes[i] = slashes[i] + 1 -- try one more slash at the given index
RNi = RNis[i] + slashes[i]
low, high = lowlist[RNi], highlist[RNi]
SubY, Y, SubX, X = SubYs[i], Ys[i], SubXs[i], Xs[i]
counter, speed, angle, low, high = change(low, high)
oldcounter = counter
framesum = 0
for j = 1, i do
framesum = framesum + frames[j]
end
if slashes[i] > maxslashes[i] or framesum > MAXFRAMES then
i = i - 1
if i <= 0 then
goto continue
else
goto redo
end
end
else
counter = counter - 1
SubY, Y, SubX, X = move(speed, angle, SubY, Y, SubX, X)
framesum = framesum + 1
end
if framesum <= 14 then globalcounter1, globalcounter2 = 0xF0, 0xF0 -- globalcounter only decreases after some initial time
else globalcounter1, globalcounter2 = 0xF7 - math.ceil(framesum / 2), 0xF7 - math.floor(framesum / 2) end
if check(globalcounter1, counter, angle, SubY, Y, SubX) or check(globalcounter2, counter, angle, SubY, Y % 0x100, SubX) then --globalcounter only decreases when the ingame clock is even, so there can be two possible values for it
local s = string.format("%3d %02X %02X %02X %02X %02X %02X %02X %02X %02X:", framesum, InitialX, InitialY, globalcounter1, globalcounter2, counter, angle, SubY, Y % 0x100, SubX)
for j = 1, i do
s = s .. string.format("%2d ", slashes[j])
end
m1[#m1 + 1] = s
if SubX == 0xD6 or SubX == 0xF6 or SubX == 0xC6 or SubX == 0xE6 then
m2[#m2 + 1] = s
end
if SubX == 0xC6 or SubX == 0xE6 then
m3[#m3 + 1] = s
end
end
end
::continue::
end
end
table.sort(m1)
table.sort(m2)
table.sort(m3)
local file = io.open(string.format("FairyManipulation%1d.txt", Index), "w") -- file for all possible hits
for i = 1, #m1 do
file:write(string.format("%s\n", m1[i]))
end
io.close(file)
local file = io.open(string.format("BetterFairyManipulation%1d.txt", Index), "w") -- file for all hits that don't require collecting any extra drops
for i = 1, #m2 do
file:write(string.format("%s\n", m2[i]))
end
io.close(file)
local file = io.open(string.format("EvenBetterFairyManipulation%1d.txt", Index), "w") -- file for all hits that jump to the filename directly
for i = 1, #m3 do
file:write(string.format("%s\n", m3[i]))
end
io.close(file)
print(string.format("completed group %1d", Index))
end
main(0x32, 0x28, 0x1A, 0x6C, 0x7B, 1)
main(0x16, 0x28, 0x00, 0x45, 0xC0, 2)