Placing register at PPU memory for multi-cart, possible?

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderator: Moderators

Post Reply
Haruka
Posts: 53
Joined: Fri Mar 23, 2018 8:58 pm

Placing register at PPU memory for multi-cart, possible?

Post by Haruka »

I've noticed that all multi-carts place their game switching registers at CPU memory region (usually at $8000~$FFFF, sometimes $6000~7FFF, rarely $4000~$5FFF).
But if the games already have registers at these regions, the addresses of the game switching registers have to be intentionally manipulated to avoid conflicts, involving address multiplexers or some more complex logics.
However if the cart has no CHR RAM, I wonder if it is possible to place the registers at PPU memory region (i.e. $0000~$1FFF)?
Without CHR RAM, CPU won't write to $0000~$1FFF. So there will be no conflicts. No complex logics needed, just a single 74'161 or 74'273 or similar is enough for the register.

Here is my assumption:

Code: Select all

           GND
           | |
           R C
     Diode | |  -------\/-------
M2 ---|>|--+-+--|/CLEAR     VCC|- VCC
PPU A13 --------|CLK         CO|-
PPU D0 ---------|D0          Q0|-------- PRG & CHR A16
PPU D1 ---------|D1          Q1|-------- PRG & CHR A17
PPU D2 ---------|D2  74'161  Q2|-------- PRG & CHR A18
PPU D3 ---------|D3          Q3|-------- PRG & CHR A19
         GND ---|CNT         CI|--- GND
         GND ---|GND      /LOAD|--- PPU /WR
                ----------------
Assume I'm making a 16-in-1 multi-cart, every game has the same size.
Code for switching games:

Code: Select all

.proc	_switchGame: near
	; A is the selected game index
	
	ldx #$00
	stx PPU_MASK	; disable rendering so that writing to PPU is safe
	
	ldx #$00
	stx PPU_ADDR	; select PPU address $0000
	ldx #$00
	stx PPU_ADDR
	sta PPU_DATA	; write game index to PPU address $0000
	
	ldy #$00
@dummyWait:
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	iny
	bne @dummyWait
	
	jmp ($FFFC)		; reset!
	
	rts
.endproc
User avatar
NovaSquirrel
Posts: 483
Joined: Fri Feb 27, 2009 2:35 pm
Location: Fort Wayne, Indiana
Contact:

Re: Placing register at PPU memory for multi-cart, possible?

Post by NovaSquirrel »

What's the delay loop for? The switch would happen immediately wouldn't it?
Haruka
Posts: 53
Joined: Fri Mar 23, 2018 8:58 pm

Re: Placing register at PPU memory for multi-cart, possible?

Post by Haruka »

Yes, indeed. The NOPs are not nessessary.
supercat
Posts: 161
Joined: Thu Apr 18, 2019 9:13 am

Re: Placing register at PPU memory for multi-cart, possible?

Post by supercat »

The signal on /LOAD needs to become valid after the signal on CLK, so I think you have the roles of /PPUWR and PPUA13 reversed. While what you drew could work, it would preclude the use of CHRAM. I think I'd favor triggering on addresses in the range $3000-$3FFF. If you're only using this thing for multi-cart selection, you could exploit the fact that (if I'm remembering right) the part has two active-high carry count-enable inputs so that writes to 0x3xxx would advance the count and nothing else would do anything (if I recall, CPU writes to palette memory are stifled so they don't hit the bus). Have the multi-cart copy a small piece of code into the NES internal RAM, load X with a value 1-15, and then jump to the internal RAM code:

Code: Select all

  lda #$30 ; Not $3F, which would be palette
  sta $2006
  sta $2006
@lp:
  sta $2007
  dex
  bne @lp
  jmp ($FFFC)
The first eight bytes could be in the cart-select ROM if desired (run before jumping to RAM) but are shown here for simplicity.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Placing register at PPU memory for multi-cart, possible?

Post by lidnariq »

Haruka wrote:Without CHR RAM, CPU won't write to $0000~$1FFF.
It turns out a number of games assume they can write to CHR ROM and have the write be ignored... hence why the pirate multicarts sometimes added a "write-protect" bit in their configuration register. (one example), nesdevwiki:Tricky-to-emulate games; scroll down to "B-Wings".

You may find something like Farid's UNROM and SLROM multicarts useful for ideas.
Haruka
Posts: 53
Joined: Fri Mar 23, 2018 8:58 pm

Re: Placing register at PPU memory for multi-cart, possible?

Post by Haruka »

supercat wrote:The signal on /LOAD needs to become valid after the signal on CLK, so I think you have the roles of /PPUWR and PPUA13 reversed.
Yes, you are right. PPU A13 and PPU /WR should be swapped on my schematic.
supercat wrote:I think I'd favor triggering on addresses in the range $3000-$3FFF. If you're only using this thing for multi-cart selection, you could exploit the fact that (if I'm remembering right) the part has two active-high carry count-enable inputs so that writes to 0x3xxx would advance the count and nothing else would do anything (if I recall, CPU writes to palette memory are stifled so they don't hit the bus).
PPU memory $3000~$3EFF is the mirror of $2000~$2EFF, which is usually the nametable of the screen. So placing the register here will be conflicting with nametables.
supercat wrote:Have the multi-cart copy a small piece of code into the NES internal RAM, load X with a value 1-15, and then jump to the internal RAM code:
Code:
lda #$30 ; Not $3F, which would be palette
sta $2006
sta $2006
@lp:
sta $2007
dex
bne @lp
jmp ($FFFC)

The first eight bytes could be in the cart-select ROM if desired (run before jumping to RAM) but are shown here for simplicity.
Yes, I placed the whole function in RAM.
lidnariq wrote:It turns out a number of games assume they can write to CHR ROM and have the write be ignored...
Luckily I'm making a VRC6 multi-cart. Neither of the three games (Mouryou Senki MADARA, Esper Dreams 2, Akumajo Densetsu) writes to CHR ROM.
(Off-topic) There is a bug found on the VRC6 pinout page when I'm trying to wire the circuit. Pin 19 of VRC6 is PPU A13 rather than PPU /A13 appearently. Neither of the three games connects PPU /A13 of edge connector to Pin 19 of VRC6.
lidnariq wrote:hence why the pirate multicarts sometimes added a "write-protect" bit in their configuration register.
Actually I've also read this document; scroll down to "4. Protect registers from accidental writing" and finally built this circuit:

Code: Select all

           GND
           | |
           R C
     Diode | |                    -------\/-------
M2 ---|>|--+-+--------------------|/CLEAR     VCC|- VCC
PPU /WR -------|>|---+------------|CLK         CO|-
PPU D0 --------------|------------|D0          Q0|-------- PRG & CHR A18
PPU D1 --------------|------------|D1          Q1|-------- PRG & CHR A19
                     |           -|D2  74'161  Q2|-
PPU D3 --------------|------------|D3          Q3|---------------.
                     |     GND ---|CNT         CI|--- GND        |
                     |     GND ---|GND      /LOAD|--- PPU A13    |
                     |            ----------------               |
                     +----|<|------------------------------------+
                     |
                     R
                     |
                    GND
I'm using two AM29F080, each game (plus the bootloader ROM itself) takes 256K + 256K so it is perfectly to switch games using only A18 & A19. Here I'm using two diodes and a pull-down resistor as a poor-man's OR gate. When switching games, I write (gameIndex | (1 << 3)) to PPU $0000. Here PPU D3 acts as the "LOCK bit".
BUT IT DIDN'T WORK! I watched the Q0~Q3 of 74'161 using LEDs to show the status and noticed that:
1. Data latched successfully.
2. Once switched to the selected game, data on Q0~Q3 disappeard immediately(all 0). Then the game crashed.

Removed the OR gate and tried again:
1. Data latched successfully.
2. Once switched to the selected game, data on Q0~Q3 disappeard immediately(all 0). Bootloader ran again.

I don't understand why this happened.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Placing register at PPU memory for multi-cart, possible?

Post by lidnariq »

Haruka wrote:BUT IT DIDN'T WORK! I watched the Q0~Q3 of 74'161 using LEDs to show the status and noticed that:
1. Data latched successfully.
2. Once switched to the selected game, data on Q0~Q3 disappeared immediately(all 0). Then the game crashed.

Removed the OR gate and tried again:
1. Data latched successfully.
2. Once switched to the selected game, data on Q0~Q3 disappeared immediately(all 0). Bootloader ran again.
That sounds like scary analog weirdness. If you have an oscilloscope, I'd check things - especially the 74'161 power supply and /Clear inputs.
supercat
Posts: 161
Joined: Thu Apr 18, 2019 9:13 am

Re: Placing register at PPU memory for multi-cart, possible?

Post by supercat »

lidnariq wrote:
Haruka wrote:BUT IT DIDN'T WORK! I watched the Q0~Q3 of 74'161 using LEDs to show the status and noticed that:
1. Data latched successfully.
2. Once switched to the selected game, data on Q0~Q3 disappeared immediately(all 0). Then the game crashed.

Removed the OR gate and tried again:
1. Data latched successfully.
2. Once switched to the selected game, data on Q0~Q3 disappeared immediately(all 0). Bootloader ran again.
That sounds like scary analog weirdness. If you have an oscilloscope, I'd check things - especially the 74'161 power supply and /Clear inputs.
My guess is that the RC on the /CLR signal isn't sized properly so as to trigger only on reset, and consequently the data is latching but then getting knackered by the clear signal. Or else there's a wiring problem that has similar effect.
Haruka
Posts: 53
Joined: Fri Mar 23, 2018 8:58 pm

Re: Placing register at PPU memory for multi-cart, possible?

Post by Haruka »

lidnariq wrote:
Haruka wrote:BUT IT DIDN'T WORK! I watched the Q0~Q3 of 74'161 using LEDs to show the status and noticed that:
1. Data latched successfully.
2. Once switched to the selected game, data on Q0~Q3 disappeared immediately(all 0). Then the game crashed.

Removed the OR gate and tried again:
1. Data latched successfully.
2. Once switched to the selected game, data on Q0~Q3 disappeared immediately(all 0). Bootloader ran again.
That sounds like scary analog weirdness. If you have an oscilloscope, I'd check things - especially the 74'161 power supply and /Clear inputs.
supercat wrote:My guess is that the RC on the /CLR signal isn't sized properly so as to trigger only on reset, and consequently the data is latching but then getting knackered by the clear signal. Or else there's a wiring problem that has similar effect.
I rebuilt the circuit with better soldering work and it worked like a charm! Maybe the previous failure was caused by some bad soldering.

Thanks to you and all the friends. I'm very grateful!
Post Reply