AlienX wrote:
using sound.get() creates a one frame delay. This is why I want to be able to get information directly from the APU's RAM addresses, so that my script can update along with them.
I think sound.get itself is accessing the register values directly without any delay, but I could be wrong.
(I have previously looked at the FCEUX source code of the lua sound.get function for another project. It looks like FCEUX uses an array called PSG to store the sound register values, and sound.get is just dumping values directly out of this array.)
But there might still be a problem of how to get the script to run the sound.get call when you want. That is, maybe emu.frameadvance, emu.registerbefore, emu.registerafter, or gui.register are introducing unwanted delays before sound.get ever runs.
Maybe you could use a memory.registerwrite to catch writes to addresses in the the sound register range, then in the callback function, just use sound.get to look at the sound register information.
If you still need to capture the exact address and value written, here is a start on that idea:
- - -
I originally thought when the memory.registerwrite triggers, the program counter would be at the beginning of the instruction that preforms the write, and you could just read that byte and next few bytes to reconstruct the address and value. But it appears when the memory.registerwrite triggers, the program counter is at the instruction after the write is preformed. That means we have to look back a few bytes and check if there is an instruction that makes sense.
I looked over the
instruction set and made a list of instructions that can write to memory:
ASL DEC INC LSR ROL ROR STA STX STY
Some of these instructions have to read the current value from memory to modify it:
ASL DEC INC LSR ROL ROR
Since you can't read a useful value from the sound register addresses, the NES program is unlikely to use these instructions with the sound registers, so I reduced the list to the following:
STA STX STY
Then I made a list of the addressing mode variations of these instructions that apply to a non-zeropage memory value:
Code:
opcode bytes instruction pseudocode
8C 3 STY MM Mem[MM] := Y
8D 3 STA MM Mem[MM] := A
8E 3 STX MM Mem[MM] := X
99 3 STA MM,Y Mem[MM+Y] := A
9D 3 STA MM,X Mem[MM+X] := A
81 2 STA (M,X) Mem[ Mem{M+X} + 256*Mem{M+X+1} ] := A
91 2 STA (M),Y Mem[ Mem{M} + 256*Mem{M+1} + Y ] := A
{} = mod 256, [] = mod 65536
In "write catcher 1.lua" I print out the detected instructions. I used this script with a few NES ROMs to check if there were cases of ambiguous instruction possibilities or if I was missing a case. In the few ROMs I looked at, I didn't see any indirect addressing used with these sound register writes.
In "write catcher 2.lua", I print out the address and value that get written. For now, I didn't complete the cases for the indirect addressing modes. If you see indirect modes getting used in "write catcher 1.lua", then we'll need to fill out "write catcher 2.lua" with those cases.