Mak
I have a crazy idea of making a game-genie adapter with second (external) PPU. Why? That would allow to generate RGB video without any modification inside the console - one would plug cartridge inside the adapter and adapter inside the console and voila. Adapter would have video output jack and maybe even joypad ports to connect exernal joypads.
There are some issues that I know about:
* Internal PPU cannot be disconnected from of the bus $2000-$2007,
* Internal PPU cannot be disconnected from the /NMI line and external PPU cannot be connected to it (because it's not present in the cartridge connector).
But here are my solution:
* Let's first concentrate on the Famicom, so the external PPU will be RP2C02 (or UA6528), clocked by external 21 MHz crystal.
* There will be also 74373, external CIRAM and some FPGA chip in the adapter.
* All PPU signal lines from the console connector will be ignored
* FPGA inside adapter is constantly snooping the CPU bus, remembering internally all three last data values that appear on the bus.
* All CPU writes to $2000-$3fff can be without harm executed by both internal and external PPUs
* If CPU is reading from $2000-$3fff then first it gets byte from the internal PPU. The values that appeared on the bus before had to be like:
This will add 4 cycle delay and will not work if the original PPU read was executed under from $0000..$7fff (unfortunately). Some games execute code from RAM, but I did not spot any that would execute PPU read opcodes from RAM.
* If the internal PPU pulls /NMI down (which can be guessed by the FPGA when $FFFA read occur), FPGA starts injecting constantly $4C (jmp $4c4c) opcode.
But FPGA also monitors /NMI of external PPU and when it sees that it goes down, it stops injecting $4c and injects $jmp (fffa) opcode
* If the external PPU pulls /NMI down (but the internal one doesn't), I think the only possible approach is just to ignore it and wait the /NMI to be pulled by internal one too.
Because both internal & external PPUs works (almost) exactly the same, the timing difference by them probably is only around a few cycles every frame (caused by the 21 MHz clock jitter) but it will equalize in every NMI.
What do you think?
I used similar approach to replace CPU reads from $4016/4017 to connect external PS/2 keyboard which can be used instead of joypads and it worked:
https://www.youtube.com/watch?v=Z0_mR2494M0
I have a crazy idea of making a game-genie adapter with second (external) PPU. Why? That would allow to generate RGB video without any modification inside the console - one would plug cartridge inside the adapter and adapter inside the console and voila. Adapter would have video output jack and maybe even joypad ports to connect exernal joypads.
Code:
+-------------------+
| Regular cartridge |
| |
|||||||||||||||||||||
|
\ /
_____________________
\___________________/
| PPU + RAM + FPGA |
| |
|||||||||||||||||||||
| Regular cartridge |
| |
|||||||||||||||||||||
|
\ /
_____________________
\___________________/
| PPU + RAM + FPGA |
| |
|||||||||||||||||||||
There are some issues that I know about:
* Internal PPU cannot be disconnected from of the bus $2000-$2007,
* Internal PPU cannot be disconnected from the /NMI line and external PPU cannot be connected to it (because it's not present in the cartridge connector).
But here are my solution:
* Let's first concentrate on the Famicom, so the external PPU will be RP2C02 (or UA6528), clocked by external 21 MHz crystal.
* There will be also 74373, external CIRAM and some FPGA chip in the adapter.
* All PPU signal lines from the console connector will be ignored
* FPGA inside adapter is constantly snooping the CPU bus, remembering internally all three last data values that appear on the bus.
* All CPU writes to $2000-$3fff can be without harm executed by both internal and external PPUs
* If CPU is reading from $2000-$3fff then first it gets byte from the internal PPU. The values that appeared on the bus before had to be like:
Code:
R/W Address Data Info
--- ----------- ---- -----
1 x d1
1 x + 1 d2 =$00-$07
1 x + 2 d3 =$20
1 $2000-$2007 * Data read from the internal PPU
But then FPGA injects those cycles:
1 x + 3 d1 driven by FPGA
1 x + 4 d2 drigen by FPGA
1 x + 5 $80 driven FPGA
1 $8000-$8007 This will force a read cycle from $8000-$8007,
and FPGA will put cartridge /ROMSEL=1 and enable external PPU for that cycle,
making the value read from internal PPU to be replaced with the one from external
(no matter if that was LDA, LDX, LDY or BIT opcode)
1 x + 6 $F0/$D0 (now FPGA injects BEQor BNE opcode, depending if the previous
value read from data bus was zero or non-zero)
1 x + 7 -4 to branch to x + 3 so that execution of regular code continues
--- ----------- ---- -----
1 x d1
1 x + 1 d2 =$00-$07
1 x + 2 d3 =$20
1 $2000-$2007 * Data read from the internal PPU
But then FPGA injects those cycles:
1 x + 3 d1 driven by FPGA
1 x + 4 d2 drigen by FPGA
1 x + 5 $80 driven FPGA
1 $8000-$8007 This will force a read cycle from $8000-$8007,
and FPGA will put cartridge /ROMSEL=1 and enable external PPU for that cycle,
making the value read from internal PPU to be replaced with the one from external
(no matter if that was LDA, LDX, LDY or BIT opcode)
1 x + 6 $F0/$D0 (now FPGA injects BEQor BNE opcode, depending if the previous
value read from data bus was zero or non-zero)
1 x + 7 -4 to branch to x + 3 so that execution of regular code continues
This will add 4 cycle delay and will not work if the original PPU read was executed under from $0000..$7fff (unfortunately). Some games execute code from RAM, but I did not spot any that would execute PPU read opcodes from RAM.
* If the internal PPU pulls /NMI down (which can be guessed by the FPGA when $FFFA read occur), FPGA starts injecting constantly $4C (jmp $4c4c) opcode.
But FPGA also monitors /NMI of external PPU and when it sees that it goes down, it stops injecting $4c and injects $jmp (fffa) opcode
* If the external PPU pulls /NMI down (but the internal one doesn't), I think the only possible approach is just to ignore it and wait the /NMI to be pulled by internal one too.
Because both internal & external PPUs works (almost) exactly the same, the timing difference by them probably is only around a few cycles every frame (caused by the 21 MHz clock jitter) but it will equalize in every NMI.
What do you think?
I used similar approach to replace CPU reads from $4016/4017 to connect external PS/2 keyboard which can be used instead of joypads and it worked:
https://www.youtube.com/watch?v=Z0_mR2494M0