Maximal retrievable state of NES?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Post Reply
User avatar
Posts: 965
Joined: Sat Jul 12, 2014 3:04 pm

Maximal retrievable state of NES?

Post by Myask » Wed Aug 13, 2014 3:31 am

Rambling thoughts, made more timely to release by viewtopic.php?f=22&t=11520

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.)

The APU appears to be mostly write-only; the one we can read will let us know whether the interaction between it and the controller registers is about to pop up- one should prevent this ASAP, so as to avoid losing any bits to such.
IRC wrote: thefox the APU resets to all channels silenced
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: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
One can at least get five bits off the bus by reading PPUSTATUS...and so one must.

While MASK would be partially-readable by a testpattern, you need the enables in it first. Catch-22.
IRC wrote: thefox you can rely on the PPU rendering being off, for example
OAMADDR and PPUADDR are going to be swiftly clobbered anyway if the video was left on.If NMIs are active, that will be discoverable merely by waiting.
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] wrote:various cleared on reset/power
Which leaves only OAMADDR and PPUADDR.
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
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')

One will likely have to scroll around...which leads us to the next problem area.

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.

User avatar
Site Admin
Posts: 3864
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis

Re: Maximal retrievable state of NES?

Post by Memblers » Wed Aug 13, 2014 5:41 pm

If you can use the cartridge port, then I believe you could just watch all reads/writes to PPU registers on the bus. I imagine the Game Action Replay had to do something similar.

For the OAM, if you only cared about DMA sprites, a cheap way would be to watch writes to $4014 and that will give you the address in CPU space.

Post Reply