User File #638209644050588377

Upload All User Files

#638209644050588377 (unlisted) - Fairy Movement Manipulation

FairyMovementManipulation.lua
35 downloads
Uploaded 5/29/2023 1:40 PM by SBD (see all 61)
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)