From bc41bc80ee6d5f10f359f2f5d27670a5a22327fd Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Mon, 21 Jan 2019 20:29:23 -0500 Subject: [PATCH] LUA script for sprite debugging (#35) Useful script adapted from one created by tokumaru (with permission) --- output/luaScripts/Sprites.lua | 110 ++++++++++++++---------- output/luaScripts/SpritesSimple.lua | 45 ++++++++++ web/help/OverviewofIncludedScripts.html | 1 + 3 files changed, 111 insertions(+), 45 deletions(-) create mode 100644 output/luaScripts/SpritesSimple.lua diff --git a/output/luaScripts/Sprites.lua b/output/luaScripts/Sprites.lua index 2f309134..87a4a16f 100644 --- a/output/luaScripts/Sprites.lua +++ b/output/luaScripts/Sprites.lua @@ -1,45 +1,65 @@ --- Simple sprite visualizer --- Draws a box around all sprites on screen. --- rainwarrior 8/23/2016 - -sprite_color = "#FF00FF" -- change to customize color - -sprite_height_last = 8 -sprite_height = 8 - -function oam_dma(a,s,v) - local oam = v * 256 - for i=1,64 do - local is = (i-1) * 4 - local x0 = memory.readbyte(oam + is + 3) - local x1 = x0 + 7 - local y0 = memory.readbyte(oam + is + 0) + 1 - local y1 = y0 + (sprite_height_last - 1) - gui.box(x0,y0,x1,y1,"",sprite_color) - end -end - -function ppu_ctrl(a,s,v) - if AND(v,0x20) == 0 then - sprite_height = 8 - else - sprite_height = 16 - end -end - -function frame_end() - -- information about sprite height will be behind by 1 frame - -- (or potentially wrong if changed before the end of the frame) - -- in most games this doesn't change from frame to frame, though - sprite_height_last = sprite_height -end - --- main - -memory.registerwrite(0x4014,1,oam_dma) -memory.registerwrite(0x2000,1,ppu_ctrl) -emu.registerafter(frame_end) - -while (true) do - emu.frameadvance() -end +-- Sprite visualizer +-- +-- Draws a box around all sprites on screen, +-- hover with the mouse to inspect data. +-- +-- Original by tokumaru 2016-10-08: +-- https://forums.nesdev.com/viewtopic.php?p=181008#p181008 + +numSpriteHeight = 8 +strFillColor = "#ffffff3f" +strOutlineColor = "#ff0000bf" +strHighlightColor = "#ffffffbf" + +function readSpriteAttributes(a,s,v) + local numAddress = v * 256 + tabSpriteAttributes = {} + for numIndex = 0, 255 do + table.insert(tabSpriteAttributes, memory.readbyte(numAddress + numIndex)) + end +end + +function setSpriteHeight(a,s,v) + if AND(a, 7) == 0 then + numSpriteHeight = AND((v / 4), 8) + 8 + end +end + +function drawBoxes() + local tabInput, numSpriteX, numSpriteY, numDetailsBase, numTextY = input.read() + if tabSpriteAttributes ~= nill then + for numBase = 252, 0, -4 do + numSpriteX0 = tabSpriteAttributes[numBase + 4] + numSpriteY0 = tabSpriteAttributes[numBase + 1] + 1 + numSpriteX1 = numSpriteX0 + 7 + numSpriteY1 = numSpriteY0 + numSpriteHeight - 1 + if (tabInput.xmouse >= numSpriteX0) and (tabInput.xmouse <= numSpriteX1) and (tabInput.ymouse >= numSpriteY0) and (tabInput.ymouse <= numSpriteY1) then + gui.box(numSpriteX0, numSpriteY0, numSpriteX1, numSpriteY1, strHighlightColor, strOutlineColor) + numDetailsBase = numBase + else + gui.box(numSpriteX0, numSpriteY0, numSpriteX1, numSpriteY1, strFillColor, strOutlineColor) + end + end + end + if numDetailsBase ~= nil then + numTextY = (1 - math.floor(tabInput.ymouse / 120)) * 127 + 16 + gui.text(16, numTextY, string.format("OAM Slot: %d", numDetailsBase / 4)); numTextY = numTextY + 9 + gui.text(16, numTextY, string.format("OAM Offset: $%02X", numDetailsBase)); numTextY = numTextY + 9 + gui.text(16, numTextY, string.format("Sprite X: $%02X", tabSpriteAttributes[numDetailsBase + 4])); numTextY = numTextY + 9 + gui.text(16, numTextY, string.format("Sprite Y: $%02X", tabSpriteAttributes[numDetailsBase + 1])); numTextY = numTextY + 9 + gui.text(16, numTextY, string.format("Tile ID: $%02X", tabSpriteAttributes[numDetailsBase + 2])); numTextY = numTextY + 9 + gui.text(16, numTextY, string.format("Palette: %d", AND(tabSpriteAttributes[numDetailsBase + 3], 0x03))); numTextY = numTextY + 9 + gui.text(16, numTextY, string.format("Behind Background: %d", AND(tabSpriteAttributes[numDetailsBase + 3], 0x20) / 0x20)); numTextY = numTextY + 9 + gui.text(16, numTextY, string.format("Flip X: %d", AND(tabSpriteAttributes[numDetailsBase + 3], 0x40) / 0x40)); numTextY = numTextY + 9 + gui.text(16, numTextY, string.format("Flip Y: %d", AND(tabSpriteAttributes[numDetailsBase + 3], 0x80) / 0x80)); numTextY = numTextY + 9 + end + gui.box(tabInput.xmouse - 2, tabInput.ymouse - 2, tabInput.xmouse + 2, tabInput.ymouse + 2, strHighlightColor, strOutlineColor) +end + +memory.registerwrite(0x4014, 0x0001, readSpriteAttributes) +memory.registerwrite(0x2000, 0x2000, setSpriteHeight) +gui.register(drawBoxes) + +while (true) do + emu.frameadvance() +end diff --git a/output/luaScripts/SpritesSimple.lua b/output/luaScripts/SpritesSimple.lua new file mode 100644 index 00000000..db1c2226 --- /dev/null +++ b/output/luaScripts/SpritesSimple.lua @@ -0,0 +1,45 @@ +-- Simple sprite visualizer +-- Draws a box around all sprites on screen. +-- rainwarrior 8/23/2016 + +sprite_color = "#FF00FF" -- change to customize color + +sprite_height_last = 8 +sprite_height = 8 + +function oam_dma(a,s,v) + local oam = v * 256 + for i=1,64 do + local is = (i-1) * 4 + local x0 = memory.readbyte(oam + is + 3) + local x1 = x0 + 7 + local y0 = memory.readbyte(oam + is + 0) + 1 + local y1 = y0 + (sprite_height_last - 1) + gui.box(x0,y0,x1,y1,"",sprite_color) + end +end + +function ppu_ctrl(a,s,v) + if AND(v,0x20) == 0 then + sprite_height = 8 + else + sprite_height = 16 + end +end + +function frame_end() + -- information about sprite height will be behind by 1 frame + -- (or potentially wrong if changed before the end of the frame) + -- in most games this doesn't change from frame to frame, though + sprite_height_last = sprite_height +end + +-- main + +memory.registerwrite(0x4014,1,oam_dma) +memory.registerwrite(0x2000,1,ppu_ctrl) +emu.registerafter(frame_end) + +while (true) do + emu.frameadvance() +end diff --git a/web/help/OverviewofIncludedScripts.html b/web/help/OverviewofIncludedScripts.html index f58bf0f6..f8587344 100644 --- a/web/help/OverviewofIncludedScripts.html +++ b/web/help/OverviewofIncludedScripts.html @@ -74,6 +74,7 @@
  • Mutlitrack2.lua        -        Tracks future input that FCEUX promptly loses on state-load, for TAS
  • Subtitler.lua                -        For easier use of FCEUX's built-in subtitles for .fm2 files
  • Rewinder.lua        -        A way to rewind backwards by pressing a button
  • +
  • Sprites.lua        -        Sprite debugging highlights all sprites on screen, with mouse hover to inspect.