Page 1 of 1

Bevahior of NES/Famicom with no cartridge present

Posted: Sat Oct 01, 2016 8:19 pm
by Jarhmander
It's a bit of a tricky question, but I was wondering if it can be guaranteed that the NES/Famicom would eventually execute one of the KIL instructions and stop upon starting up without a cartridge inserted. Specifically, I'm asking if it's impossible that the NES/Famicom runs continuously without executing a KIL and stop. (I do not consider the CIC in the NES case)

I have a sense that it's an impossible question but I ask nevertheless, because sometimes people here have answers to impossible questions ;)

As I see it:
- I do not quite know what power-on open bus looks like, but if the 2A03 reset is short enough, then I think the databus will get all 0s, but over time the bits will flip to 1s, and not simultaneously, which will complicate tremendously the study;
- let's suppose PC points to an area that is open bus and the databus is $FF, then it executes ISC $FFFF,X. I'm not sure of the operation of unofficial instructions, but I guess it ends on a write. With X = 0, it will fetch $FF and then final write is 0. This write will set the databus and if the next PC is still open bus the next opcode will be BRK. The last push on the stack is the status register; thus the next PC will depend upon the value of the pushed status register. If the address is still open bus, then there is an high chance that the same value (status register) will be interpreted as an opcode.
- Executing code in uninitialised RAM is unpredictable, but it would be next to impossible to encounter any JMP/branch instruction that jump back into an already executed instruction, and thus create a code loop.

Re: Bevahior of NES/Famicom with no cartridge present

Posted: Sat Oct 01, 2016 8:29 pm
by Dwedit
Think of an open bus read as returning the lowest byte of the address, which it usually does.
So it reads from the reset vector, FFFC and FFFD and jumps to FDFC. Then it executes instruction FC (NOP abs,x). Then PC = FDFF, and it executes FF (ISB abs, x). Then it's at FE02, and executes 02 (CPU jam).

Re: Bevahior of NES/Famicom with no cartridge present

Posted: Sat Oct 01, 2016 10:41 pm
by lidnariq
But the data bus isn't multiplexed, so it doesn't fetch the address bytes unless it's part of the encoding. (e.g. LDA $4016 finds $40 on the data bus because the ROM drove it there on the preceding cycle)

The reset vector instead reads three bytes from the stack, so the specific address it'll jump to is a function of what memory is in the NES; most likely RAM powers up with either $00 or $FF in it, so it'll either jump to $FFFF or $0000.

If it's RAM that usually powers up with zeroes, and it's jumped to $0000, it's likely that the next instruction is $00 = BRK, so it'll push the return address ($0002) to the stack, and then the status value ... which it then fetches as the IRQ vector location. The status value on power-up is $34, so it'll jump to $3434 ... and then read some random byte from OAM, followed by reading up to two copies of it from the PPU's internal open bus. At this point, we can't really track it any further.

If the RAM instead usually powers up with $FFs, the first instruction will be ISC $FFFF,X ... X usually powers up holding 0, so it'll spend the entire 8 KiB of address space for the NES's internal RAM repeating that over and over, until it slides into executing from the PPU registers. Once again, I'm not certain how to track it beyond this point.

And of course, the latter case assumes that RAM is uniform; since that's not a good assumption, it could do something else altogether.

Re: Bevahior of NES/Famicom with no cartridge present

Posted: Sun Oct 02, 2016 9:15 pm
by Jarhmander
Oh yeah right, I somehow forgot the reset reads from stack, even though I thought of the inhibited writes, I just didn't think that there would be reads from RAM, so it drives the databus. Silly me.

So the RAM contents at the end of page 1 would determine where PC lands, so the unpredictability comes from the power up contents of RAM, not analog effects on the databus. That mades me realize it's quite possible to control the behavior of a soft reset without a cartridge: fill the entire page 1 with a constant, < $20, put your code at that address. For example: fill page 1 with $1F, put jmp $71F at $71F, and the next soft reset with cartridge removed will be predictable and will do an infinite loop. A cold boot done sufficiently shortly after power off should have the same effect. That exercise was not an attempt to do something useful with that "feature" but to show there can be interesting side effects a game can do with the RAM that can alter the no-cart code execution.

Re: Bevahior of NES/Famicom with no cartridge present

Posted: Sun Oct 02, 2016 10:32 pm
by lidnariq
You don't even need to fill the entire stack, as long as you can control the value of the stack pointer before the console is reset. Just make sure that the byte at $00FE,s contains your desired fake reset vector.

It'd be hard to use the PPU like this, but if I had a little ditty to play it'd make a nice tiny demo.

Re: Bevahior of NES/Famicom with no cartridge present

Posted: Mon Oct 03, 2016 5:46 am
by Jarhmander
I suggested filling the stack because I don't know if the reset signal from the reset button is "clean" enough; you might be screwed by one extra reset.

Slightly related, would putting a pull down on CIRAM /CE and a resistor between PPU A13 and CIRAM A10 have any undesirable side effects? I know that some games rely on the open bus values in the 2A03 addressing space, so I wouldn't put any pull-down/pull-up on the 2A03 databus, but for CIRAM A10 and CIRAM /CE... they're never, ever, left floating. Depending on the signal, they're either grounded, connected to a PPU signal or mapper-controlled. I don't think that can affect any game, and that would do something useful: use first 1k of CIRAM for pattern table, second 1k for nametable by default, if there is no cartridge (or a custom cart doesn't connect anything to these signals).

Re: Bevahior of NES/Famicom with no cartridge present

Posted: Mon Oct 03, 2016 10:07 am
by lidnariq
Jarhmander wrote:I suggested filling the stack because I don't know if the reset signal from the reset button is "clean" enough; you might be screwed by one extra reset.
Well, in the Famicom there's the capacitor C1 (0.47µF), so that should be relatively clean. We don't have a schematic of the top-loader, but I'd assume it's similar? In a front-loader with a confused CIC, I previously measured the amount of time from "5V stabilizes" to "/RESET released"—it's about 1/10th of a second.
Slightly related, would putting a pull down on CIRAM /CE and a resistor between PPU A13 and CIRAM A10 have any undesirable side effects?
As long as the resistor is large enough (≥5kΩ?) , the pulldown is definitely safe.

There might be timing problems with the other resistor, though.

Re: Bevahior of NES/Famicom with no cartridge present

Posted: Mon Oct 03, 2016 4:29 pm
by Jarhmander
1/10th of a second? It's quite slow. The reset button won't cause any problems.

As for the resistor between PPU A13 and CIRAM A10, yeah it bother me too. The thing is, what capacitance can I expect on the PPU address bus? 20pF? 50pF? 100pF?!?

Re: Bevahior of NES/Famicom with no cartridge present

Posted: Thu Dec 08, 2016 1:47 am
by lidnariq
Here's a very simple noodly harmony example. I have tested it on my NES-001.

It will only work correctly on a front-loader with a functioning CIC! On each warm boot it advances the song pointer, so it plays one chord until the next time the CIC reboots the 2A03. (On a famicom, toploader, or frontloader with a disabled CIC, you can advance it by hand by pressing the reset button)

It completely ignores the PPU. It's ready to go (i.e. for you to pull the cartridge and watch what happens when there's no ROM attached) after it plays the high-low pair of tones.

You have to pull the cartridge for it do anything. (You probably want to hold reset while you're doing so). Otherwise it'll just copy the same 2 KiB from ROM to RAM every time it boots.

Source is included. Released to public domain/under WTFPL/CC0 as necessary.