Reputation: 662
I'm not sure if this is the right community for this, but figured I'd give it a try.
FCEUX is an amazing emulator for the NES, which is feature rich with debugging tools. It also offers the ability for users to run Lua scripts which have access to various emulator functions. However, I can't seem to figure out how to access the PPU memory of the NES. It offers direct access to the CPU memory and the ROM data, but doesn't seem to have direct access to the PPU memory. Since the NES uses memory-mapped I/O, it is possible - in theory - to get the data from special CPU memory addresses, but this seems cumbersome, and also like it might interfere with emulation.
Does anyone know of a way to programmatically extract the PPU memory via FCEUX's Lua API? If not, does anyone know of an emulator which features an API to extract PPU memory programmatically?
Upvotes: 2
Views: 937
Reputation: 139
As of FCEUX 2.3.0, you can use ppu.readbyte(int address)
and ppu.readbyterange(int address, int length)
. Still nothing for writing bytes, though.
To add onto SpiderDave's answer, you might have better luck if you call his writebyteppu
hack from a registerexec
callback at an address just after the game has finished writing its graphics for the frame.
-- For Rockman 2. Directly after all graphics update routines finish.
memory.registerexec(0xD031, function()
local paletteBase = 0x3F00
-- Make all BG colors pink
for i = 0x00, 0x0F do
memory.writebyteppu(paletteBase + i, 0x35)
end
end)
Upvotes: 1
Reputation: 41
Here's what I use:
function memory.readbyteppu(a)
memory.writebyte(0x2001,0x00) -- Turn off rendering
memory.readbyte(0x2002) -- PPUSTATUS (reset address latch)
memory.writebyte(0x2006,math.floor(a/0x100)) -- PPUADDR high byte
memory.writebyte(0x2006,a % 0x100) -- PPUADDR low byte
if a < 0x3f00 then
dummy=memory.readbyte(0x2007) -- PPUDATA (discard contents of internal buffer if not reading palette area)
end
ret=memory.readbyte(0x2007) -- PPUDATA
memory.writebyte(0x2001,0x1e) -- Turn on rendering
return ret
end
function memory.readbytesppu(a,l)
memory.writebyte(0x2001,0x00) -- Turn off rendering
local ret
local i
ret=""
for i=0,l-1 do
memory.readbyte(0x2002) -- PPUSTATUS (reset address latch)
memory.writebyte(0x2006,math.floor((a+i)/0x100)) -- PPUADDR high byte
memory.writebyte(0x2006,(a+i) % 0x100) -- PPUADDR low byte
if (a+i) < 0x3f00 then
dummy=memory.readbyte(0x2007) -- PPUDATA (discard contents of internal buffer if not reading palette area)
end
ret=ret..string.char(memory.readbyte(0x2007)) -- PPUDATA
end
memory.writebyte(0x2001,0x1e) -- Turn on rendering
return ret
end
function memory.writebyteppu(a,v)
memory.writebyte(0x2001,0x00) -- Turn off rendering
memory.readbyte(0x2002) -- PPUSTATUS (reset address latch)
memory.writebyte(0x2006,math.floor(a/0x100)) -- PPUADDR high byte
memory.writebyte(0x2006,a % 0x100) -- PPUADDR low byte
memory.writebyte(0x2007,v) -- PPUDATA
memory.writebyte(0x2001,0x1e) -- Turn on rendering
end
function memory.writebytesppu(a,str)
memory.writebyte(0x2001,0x00) -- Turn off rendering
local i
for i = 0, #str-1 do
memory.readbyte(0x2002) -- PPUSTATUS (reset address latch)
memory.writebyte(0x2006,math.floor((a+i)/0x100)) -- PPUADDR high byte
memory.writebyte(0x2006,(a+i) % 0x100) -- PPUADDR low byte
memory.writebyte(0x2007,string.byte(str,i+1)) -- PPUDATA
end
memory.writebyte(0x2001,0x1e) -- Turn on rendering
end
In 2.2.3 it doesn't seem to work on the old PPU core, but on 2.2.2 it does. Works with new ppu core on both versions.
Upvotes: 4
Reputation: 662
After having the realization that "Oh wait, I'm a programmer, and FCEUX is open source! So maybe I should take the time to look at their source/repository to see if I can answer the question myself!", I found the answer I was looking for:
Commit [r3327] on 22-Dec-2016: add ppu lua library, only has readbyte and readbyterange so far
So it would seem that as of the time of this writing, PPU memory access via Lua is not possible in the current release version (2.2.3 released 28-Jul-2016), but will likely be available in a future release.
Also, after checking out Nestopia and Jnes (two of the other seemingly most popular NES emulators), it seems that these emulators do not offer such functionality. As to whether or not there are any other emulators out there that offers this functionality is still an open question, since there are currently many other emulators in existence to check.
Upvotes: 1