Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- this outputs some information related to the map loading procedure when the screen scrolls,
- -- hopefully helpful for researching and recreating the scroll bug
- -- script by mugg ; with help from ais523, Sand
- ----- CONFIGURATION -----
- local PRINT_INFO = false
- local PAUSE_WHEN_BUG_HAPPENS = true
- local TRY_RUN_TESTS = true
- local run_test = -- only set one of these true
- {
- [1] = false, -- unpause test
- [2] = false, -- idle into B press/jumprun test
- [3] = false, -- keep running and repress B test
- [4] = false, -- keep running and repress right test
- [5] = false, -- custom probability input test
- [6] = true -- custom probability input test 2
- }
- ----- CONFIGURATION END -----
- console.clear()
- memory.usememorydomain("System Bus")
- local cycles_at_frame_start = emu.totalexecutedcycles()
- local cycles_at_frame_end = emu.totalexecutedcycles()
- local print_after_this_frame = emu.framecount() + 1
- local game_version = "-"
- local t = ""
- local t_frame_info = ""
- local frames_processed = 0
- -- these have to happen in the same frame
- local requirement1 = false -- timer interrupt happens while ffea is 0x01
- local requirement2 = false -- ffea gets set to 0x03
- local bugframe_tbl = {}
- local double_timer_interrupt_tbl = {}
- local timer_interrupts_same_frame = 0
- local waitframes = emu.framecount() +1 -- used by testing code, to bruteforce for the bug
- local vary3 = math.random(21,46)
- local vary4 = math.random(0,4)
- local vary5 = math.random(0,13)
- if gameinfo.getromhash() == "3A4DDB39B234A67FFB361EE7ABC3D23E0A8B1C89" then
- game_version = "1.0"
- elseif gameinfo.getromhash() == "418203621B887CAA090215D97E3F509B79AFFD3E" then
- game_version = "1.1"
- else
- print("This script will work only with GB Super Mario Land v1.0 or v1.1.")
- return
- end
- function text(x, y, text, color, backcolor)
- gui.pixelText(x, y, text, color, backcolor)
- end
- event.onframestart(function()
- cycles_at_frame_start = emu.totalexecutedcycles()
- if emu.framecount() > print_after_this_frame then
- local prefix = ""
- if frames_processed > 1 then
- prefix = "\n"
- end
- t_frame_info = prefix .. " FRAME " .. emu.framecount() + 1
- end
- end)
- event.onframeend(function()
- if emu.framecount()-1 > print_after_this_frame then
- t_frame_info = t_frame_info .. " Cy:" .. emu.totalexecutedcycles() - cycles_at_frame_end
- end
- if emu.islagged()
- and emu.framecount()-1 > print_after_this_frame then
- t_frame_info = t_frame_info .. " **LAG**"
- end
- cycles_at_frame_end = emu.totalexecutedcycles()
- -- only print if the string isn't empty
- if PRINT_INFO then
- if #t_frame_info > 0 and #t > 0 then
- print(t_frame_info .. "\n" .. t)
- elseif #t_frame_info > 0 then
- print(t_frame_info)
- end
- end
- -- bugframe happened, save framecount and pixel pos
- if requirement1 and requirement2 then
- print("Bug frame!!!")
- local bugframe_info = {emu.framecount(), memory.read_u8(0xFFE9)*8}
- table.insert(bugframe_tbl, bugframe_info)
- end
- -- reset values
- requirement1 = false
- requirement2 = false
- t = ""
- t_frame_info = ""
- timer_interrupts_same_frame = 0
- frames_processed = frames_processed + 1
- end)
- tastudio.onbranchload(function()
- print_after_this_frame = emu.framecount() + 1
- frames_processed = -1
- console.clear()
- bugframe_tbl = {}
- double_timer_interrupt_tbl = {}
- vary3 = math.random(22,45)
- vary4 = math.random(0,3)
- vary5 = math.random(0,7)
- end)
- event.onloadstate(function()
- print_after_this_frame = emu.framecount() + 1
- frames_processed = -1
- console.clear()
- bugframe_tbl = {}
- double_timer_interrupt_tbl = {}
- vary3 = math.random(22,45)
- vary4 = math.random(0,3)
- vary5 = math.random(0,7)
- end)
- -- Write to $FFEA
- -- passed val is always 0, it seems, hinting that this hook is not fully implemented
- event.on_bus_write(function(addr, val, flags)
- if emu.framecount() > print_after_this_frame then
- local raw_val = memory.read_u8(0xFFEA)
- local val = string.upper(string.format("%02x",raw_val))
- local myname = "Write $FFEA (" .. val .. ")"
- t = t .. "\n" .. string.format("%-32s", myname) .. " cycle: " .. emu.totalexecutedcycles() - cycles_at_frame_start
- if raw_val == 0x03 then
- requirement2 = true
- end
- end
- end, 0xFFEA)
- -- Write to $FFE9
- event.on_bus_write(function(addr, val, flags)
- if emu.framecount() > print_after_this_frame then
- local val = string.upper(string.format("%02x",memory.read_u8(0xFFE9)))
- local myname = "Write $FFE9 (" .. val .. ")"
- t = t .. "\n" .. string.format("%-32s", myname) .. " cycle: " .. emu.totalexecutedcycles() - cycles_at_frame_start
- end
- end, 0xFFE9)
- -- Exec $0040
- event.on_bus_exec(function(addr, val, flags)
- if emu.framecount() > print_after_this_frame then
- local myname = "Execu $0040 (VBLANK INTERRUPT)"
- t = t .. "\n" .. string.format("%-32s", myname) .. " cycle: " .. emu.totalexecutedcycles() - cycles_at_frame_start
- end
- end, 0x0040)
- -- Exec $0050
- event.on_bus_exec(function(addr, val, flags)
- if emu.framecount() > print_after_this_frame then
- local myname = "Execu $0050 (TIMER INTERRUPT)"
- t = t .. "\n" .. string.format("%-32s", myname) .. " cycle: " .. emu.totalexecutedcycles() - cycles_at_frame_start
- local ffea = memory.read_u8(0xFFEA)
- if ffea == 0x01 then
- requirement1 = true
- end
- timer_interrupts_same_frame = timer_interrupts_same_frame + 1
- if timer_interrupts_same_frame >= 2 then
- --t = t .. "\nTwo Timer Interrupts!"
- table.insert(double_timer_interrupt_tbl, emu.framecount()+1)
- end
- end
- end, 0x0050)
- -- Exec $0060
- --[[
- event.on_bus_exec(function(addr, val, flags)
- if emu.framecount() > print_after_this_frame then
- local myname = "Execu $0060 (JOYPAD INTERRUPT)"
- t = t .. "\n" .. string.format("%-32s", myname) .. " cycle: " .. emu.totalexecutedcycles() - cycles_at_frame_start
- end
- end, 0x0060)
- --]]
- -- game version dependent execs
- if game_version == "1.0" then
- event.on_bus_exec(function(addr, val, flags)
- if emu.framecount() > print_after_this_frame then
- local myname = "Execu $2258 (READ $FFEA)"
- t = t .. "\n" .. string.format("%-32s", myname) .. " cycle: " .. emu.totalexecutedcycles() - cycles_at_frame_start
- end
- end, 0x224F)
- event.on_bus_exec(function(addr, val, flags)
- if emu.framecount() > print_after_this_frame then
- local myname = "Execu $2254 (READ $FFE9)"
- t = t .. "\n" .. string.format("%-32s", myname) .. " cycle: " .. emu.totalexecutedcycles() - cycles_at_frame_start
- end
- end, 0x2254)
- elseif game_version == "1.1" then
- event.on_bus_exec(function(addr, val, flags)
- if emu.framecount() > print_after_this_frame then
- local myname = "Execu $2258 (READ $FFEA)"
- t = t .. "\n" .. string.format("%-32s", myname) .. " cycle: " .. emu.totalexecutedcycles() - cycles_at_frame_start
- end
- end, 0x2258)
- event.on_bus_exec(function(addr, val, flags)
- if emu.framecount() > print_after_this_frame then
- local myname = "Execu $225D (READ $FFE9)"
- t = t .. "\n" .. string.format("%-32s", myname) .. " cycle: " .. emu.totalexecutedcycles() - cycles_at_frame_start
- end
- end, 0x225D)
- end
- while true do
- gui.clearGraphics()
- if #bugframe_tbl > 0 then
- for i=1, #bugframe_tbl, 1 do
- local bugframe_entry = bugframe_tbl[i]
- if bugframe_entry ~= nil then
- local bugframe_framecount = bugframe_entry[1]
- local bugframe_pixel = bugframe_entry[2]
- local current_pixel = memory.read_u8(0xFFE9) * 8
- local display_pixel = (bugframe_pixel - current_pixel) - memory.read_u8(0xFF43)%8 + 216
- text(10, 10 + i*8, "bug Frame " .. bugframe_framecount, 0xFF00FF00, 0x80000000)
- if display_pixel > 160 then
- text(136,10 + i*8, "--->", 0xFFFF0000, 0x80000000)
- else
- gui.drawLine(display_pixel, 17, display_pixel, 144, 0xFFFF0000)
- end
- if PAUSE_WHEN_BUG_HAPPENS then client.pause() end
- if display_pixel < 0 then
- bugframe_tbl[i] = nil
- end
- end
- end
- end
- --[[
- if #double_timer_interrupt_tbl > 0 then
- for j=1, #double_timer_interrupt_tbl, 1 do
- local frame = double_timer_interrupt_tbl[j]
- text(10, 80 + j*8, "two timer interrupts frame " .. frame, 0xFF00FF00, 0x80000000)
- end
- end
- --]]
- if TRY_RUN_TESTS then
- if run_test[1] then
- -- Pause, then let this run while keeping previous input in tastudio
- -- script will attempt unpause at increasing framecounts
- tastudio.submitinputchange(emu.framecount(), "Right", true)
- tastudio.submitinputchange(emu.framecount(), "A", true)
- if emu.framecount() == waitframes then
- tastudio.submitinputchange(emu.framecount()+1, "Start", true)
- end
- if emu.framecount() > waitframes + 120 then
- savestate.loadslot(5)
- waitframes = waitframes + 1
- end
- tastudio.applyinputchanges()
- end
- if run_test[2] then
- -- Have Mario on the ground, clear upcoming 200 frames in tastudio
- -- script will attempt increasing amounts of idleframes then run+jump.
- if emu.framecount() >= waitframes then
- tastudio.submitinputchange(emu.framecount(), "Right", true)
- tastudio.submitinputchange(emu.framecount(), "B", true)
- end
- if emu.framecount() > waitframes+6 then
- tastudio.submitinputchange(emu.framecount(), "A", true)
- end
- if emu.framecount() > waitframes + 120 then
- savestate.loadslot(5)
- waitframes = waitframes + 1
- end
- tastudio.applyinputchanges()
- end
- if run_test[3] then
- -- Have Mario on the ground, clear upcoming 200 frames in tastudio
- -- script will keep running right and repress B at increasingly later times
- if emu.framecount() == waitframes then
- tastudio.submitinputchange(emu.framecount(), "Right", true)
- tastudio.submitinputchange(emu.framecount(), "B", false)
- else
- tastudio.submitinputchange(emu.framecount(), "Right", true)
- tastudio.submitinputchange(emu.framecount(), "B", true)
- end
- if emu.framecount() > 86570 then
- -- tastudio.submitinputchange(emu.framecount(), "A", true)
- end
- if emu.framecount() > waitframes + 120 then
- savestate.loadslot(5)
- waitframes = waitframes + 1
- end
- tastudio.applyinputchanges()
- end
- if run_test[4] then
- -- Have Mario on the ground, clear upcoming 200 frames in tastudio
- -- script will keep running right and not hold 1 for one frame at increasing framecounts
- if emu.framecount() == waitframes then
- tastudio.submitinputchange(emu.framecount(), "Right", false)
- tastudio.submitinputchange(emu.framecount(), "B", true)
- else
- tastudio.submitinputchange(emu.framecount(), "Right", true)
- tastudio.submitinputchange(emu.framecount(), "B", true)
- end
- if emu.framecount() > waitframes + 120 then
- savestate.loadslot(5)
- waitframes = waitframes + 1
- end
- tastudio.applyinputchanges()
- end
- if run_test[5] then
- -- Have Mario on the ground, clear upcoming 200 frames in tastudio
- -- script will do inputs at set chance
- local not_here = false
- --[[(memory.read_u8(0xFFF3) > 0x83 and memory.read_u8(0xFFF3) < 0x8B)
- or (memory.read_u8(0xFFF3) > 0x93 and memory.read_u8(0xFFF3) < 0x9B)
- or (memory.read_u8(0xFFF3) > 0xa3 and memory.read_u8(0xFFF3) < 0xaB)
- or (memory.read_u8(0xFFF3) > 0xb3 and memory.read_u8(0xFFF3) < 0xbB)
- or (memory.read_u8(0xFFF3) > 0xc3 and memory.read_u8(0xFFF3) < 0xcB)
- or (memory.read_u8(0xFFF3) > 0xd3 and memory.read_u8(0xFFF3) < 0xdB)
- --]]
- local vary1 = math.random(1,80)
- local vary2 = math.random(1,40)
- local vary3 = math.random(28,42)
- if math.random(1,1000) < (980-vary1) or not_here then
- tastudio.submitinputchange(emu.framecount(), "Right", true)
- else
- tastudio.submitinputchange(emu.framecount(), "Right", false)
- end
- if (math.random(1,1000) < (979-vary2) and emu.framecount() > waitframes + vary3) or not_here then
- tastudio.submitinputchange(emu.framecount(), "B", true)
- else
- tastudio.submitinputchange(emu.framecount(), "B", false)
- end
- if emu.framecount() > waitframes + 95 then
- savestate.loadslot(5)
- end
- tastudio.applyinputchanges()
- end
- if run_test[6] then
- -- Have Mario on the ground, clear upcoming 200 frames in tastudio
- -- script will do inputs at set chance
- -- start this at 86282
- local vary1 = math.random(1,80)
- local vary2 = math.random(1,50)
- local press_b = true
- local press_a = false
- local press_right = true
- -- star block jump
- if emu.framecount() >= waitframes + vary4 and emu.framecount() < waitframes + vary4 + 10 then
- press_a = true
- else
- press_a = false
- end
- -- ending jump
- if memory.read_u8(0xFFF3) > 0x83 then
- press_a = true
- end
- -- b kill
- if emu.framecount() == waitframes + 17 + vary5 then
- press_b = false
- end
- -- random
- if not press_a then
- if not (math.random(1,1000) < (980-vary1)) then
- if emu.framecount() > waitframes + 10 then
- press_right = false
- end
- end
- if emu.framecount() > waitframes + 17 + vary5 then
- if math.random(1,1000) > (980-vary2) and (emu.framecount() > waitframes + 16 + vary3) then
- press_b = false
- end
- end
- end
- tastudio.submitinputchange(emu.framecount(), "A", press_a)
- tastudio.submitinputchange(emu.framecount(), "B", press_b)
- tastudio.submitinputchange(emu.framecount(), "Right", press_right)
- if emu.framecount() > waitframes + 155 or emu.lagcount() > 407 then
- savestate.loadslot(5)
- end
- tastudio.applyinputchanges()
- end
- end
- emu.frameadvance()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement