It is currently Mon May 20, 2019 8:50 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 9 posts ] 
Author Message
PostPosted: Sat May 11, 2019 1:05 am 
Offline

Joined: Fri Mar 23, 2018 8:58 pm
Posts: 22
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:
           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:
.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


Top
 Profile  
 
PostPosted: Sat May 11, 2019 8:13 am 
Offline
User avatar

Joined: Fri Feb 27, 2009 2:35 pm
Posts: 352
Location: Fort Wayne, Indiana
What's the delay loop for? The switch would happen immediately wouldn't it?


Top
 Profile  
 
PostPosted: Sat May 11, 2019 8:50 am 
Offline

Joined: Fri Mar 23, 2018 8:58 pm
Posts: 22
Yes, indeed. The NOPs are not nessessary.


Top
 Profile  
 
PostPosted: Sat May 11, 2019 10:16 am 
Offline

Joined: Thu Apr 18, 2019 9:13 am
Posts: 97
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:
  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.


Top
 Profile  
 
PostPosted: Sat May 11, 2019 10:35 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8360
Location: Seattle
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.


Top
 Profile  
 
PostPosted: Sun May 12, 2019 7:31 pm 
Offline

Joined: Fri Mar 23, 2018 8:58 pm
Posts: 22
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:
           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.


Top
 Profile  
 
PostPosted: Sun May 12, 2019 8:17 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8360
Location: Seattle
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.


Top
 Profile  
 
PostPosted: Sun May 12, 2019 10:05 pm 
Offline

Joined: Thu Apr 18, 2019 9:13 am
Posts: 97
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.


Top
 Profile  
 
PostPosted: Sun May 12, 2019 10:21 pm 
Offline

Joined: Fri Mar 23, 2018 8:58 pm
Posts: 22
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!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group