I'd been thinking about the theoretical restrictions and requirements for retrieving maximal in-place state of the NES.
As the OAM is quite volatile, it would need some kind of special trickery to catch before it goes. If you're using some kind of special entry method to do so, this will be when you need to hook the PC. Interrupts are undesirable, as then you have some writes to the stack.
Beyond that, in order to run a program, you need at least one register and the status flags. Similarly, you need an index register to be able to loop over addresses. Then you need an index to use indexed or indirect addressing modes, which are effectively required for a dump. (Storage of state in the PC is possible, but painful...however, it is the easiest way to read bits off of P without a stack operation.)
Now, to get anything out of it, you're going to either be using I/O trickery with a controller or expansion port, a cart-based port, or the video (or audio) out. Either of the former require a hardware trick, so a straight ROM-to-devcart won't do. Audio, well, I don't think people will have acoustic modems handy, nor would it be easy to convey the data in a short time. Which leaves us video.IRC wrote: thefox the APU resets to all channels silenced
One can at least get five bits off the bus by reading PPUSTATUS...and so one must.IRC wrote:Myask Can you [meaningfully] read the non-data PPU registers? PPUCTRL, PPUMASK, OAMADDR, PPUSCROLL, PPUADDR
thefox btw it's not possible to read PPUCTRL/PPUMASK/OAMADDR/PPUSCROLL/PPUADDR like you asked
OAMADDR and PPUADDR are going to be swiftly clobbered anyway if the video was left on.IRC wrote: thefox you can rely on the PPU rendering being off, for example
Now, if we have a mapper/cartside handling all of [non-palette] VRAM, we can generate patterns without clobbering that of the original. (I'm uncertain if it is possible to both do this and still be able to read from the NES's VRAM later.) If the PPU was left in a usable state, most of PPUCTRL and PPUSCROLL will be visible by using appropriate CHR and differentiating your pattern tables. Two writes to PPUDATA will reveal to the cart what d2 of CTRL is. A single write to PPUADDR($20 seems easiest) followed by a data write will reveal what the state of the address latch of the PPU was. [/s]
Which leaves only OAMADDR and PPUADDR.http://wiki.nesdev.com/w/index.php/PPU_power_up_state wrote:various cleared on reset/power
Well, that would make it available to the program. If you just do the fill-and-one-variant, then you could choose values that make it potentially visible on-screen which sprite it is...lessee, a tile on 0 that is not symmetrical ("UP" would do), and one on 128 that is distinguishable (DN?). If you get a flipped UP, it was in the tile attribute. If you get it in the middle of the top row, it was on X. if you get it in the middle of the left edge of screen, it was on Y. One could then use read/writes to skip over OAM we're not touching (so the sprite is distinct to the user in a way different than our 'current sprite')IRC wrote: thefox one possible way i can think of is to write 256x zeroes to OAMDATA, then write a single one, then reset OAMADDR to 0, and then read it until you find the 1
The controller registers, out in the controllers, may still have state; several bytes' worth, potentially. (Excepting when a Four Score is attached, figuring out WHERE in the sequence it was interrupted will be painful if at all possible. As we've dealt with the APU already, we won't have to worry about that anymore.
Once you have learned the data, of course, you can write to where they were in order to test other data. Once you have the PPU regs learned, you can set them to a simple state to dump VRAM to screen. One can do this simply by CHR and palette manipulation, once you've read the palette data. (Non-overscanning monitors will help.) If OAM isn't dead yet, you can read it. If it is, then you can use it as a storage in a pinch, but odds are you can just use cart-side stuff; far easier nowadays.
one can then dump the real RAM to screen, and just about anything else one desires. One should probably start with the stack page; this allows finally getting the last pieces of processor registers: the decimal flag and the stack pointer (As one has to push and pull the Status byte to get at D, as its effects on instructions are disabled,
Pseudo-edit: Above was written with the "swap out, swap in" notion including a power-off/reset. Some cart-side shenanigans suggest themselves to gain some of those data rather than having them reset to known values--somehow involve triggering a switch of ROM bank to our dumping program, and resetting the PC appropriately, or, if we're being mapper-level dedicated, we can just ignore the PC for when the trigger hits, using that to record what it was, giving it a JMP to wherever we want-- but at the moment I've had enough of adding strikethroughs and provisos.