This is next part of photos of interesting/rare mapper cartridges.
31 in 1 multi-cart with 5 switches: 31 NROM games (30 x 16K + 1 * 32K)
I bet tepple's was wondering in one of previous posts if there ever was a cartridge with switches. So yes, it was and even they did the shell
for that with factory created holes with bevels for the switches. So it was not something done in low quantity.
Switches control both PRG & CHR upper address lines and few logic gates set proper mirroring & 16/32K mode upon them.
Games: Super Mario Bros, Moby Demo, Star Force, F-1 Race, Lode Runner, Raid on Bungeling Bay, NES Tutor 101, Kinnikuman - Muscle Tag Match, Chou Jikuu Yousai, - Macross, Chack 'n Pop, Ikki, Championship Lode Runner, Lunar Ball, Duck Hunt, Wild Gunman, Urban Champion, Ice Climber, Battle City, Pac-Man, Galaxian, Popeye, Devil World, Exerion, Donkey Kong, Donkey Kong Jr., Tennis, Field Combat, Golf, Space Invaders, Front Line, Zippy Race, Super Arabian
What is also interesting is that the ROMs have uncommon pinout: HN62304 = 4 Mbit, HN62312 = 2 Mbit
#########################################################################################################################################
Princess maker
This is the oonly cartridge I ever saw in my life that has PLCC ROMs (which are EPROMS with windows!). One of them lost its content so I simply replaced it with 29F040. The mapper is just MMC3, but bit 7 and 6 of CHR registers are used as bit 7 and 6 of PRG, enhancing maximum possible PRG ROM size from 512 kB to 2048 kB (all 8 CHR registers must have the same bit 7 and 6, otherwise PRG banks will be switched during rendering).
This game has PRG capacity of 6 * 256 kB = 1536 kB
CHR-RAM is 32 kB and is bankable and it is battery backed!
BLOB chip is ordinary MMC3, with WRAM CE/WRAM !CE/WRAM WE / CHR A15 lines not connected externally to anything.
When CPU accesses $c000-$ffff, always first outer bank (first 512 kB of memory) is enabled.
$e000-$ffff will point to -1 bank in first 512 kB
$c000-$dfff:
* if $8000.6 = 0 -> will point to -2 bank in first 512 kB
* if $8000.6 = 1 -> this bank will be swappable but only always within first 512 kB
When CPU accesses $8000-$ffff, CHR-A17 and CHR-A16 selects outer bank
Below is full logic table of which memory is enabled when:
#########################################################################################################################################
4 in 1 multicart with 2 switches (FDS Port + 3 UNROM games)
This is quite interesting cartridge (also with switches), which has 4 games: SMB2J + Brave Soldier + Phoenix + Bobby Kids. They used HN62304 512 kB as PRG ROM (same as mentioned above). But what is more interesting is the SPCN 2810 mapper chip, which has pinout almost identical to typical JEDEC memories. At first I thought it is just simple ROM used as some kind of lookup table, but not. After spending many hours on analyzing it, I got the following results. The SMB2J is very similar to Mapper 43 with scrambling pattern as the one uncommented in FCEUX source code:
#########################################################################################################################################
Batman 2 J
Normally when I see DIP40 mapper chip + PAL16L8, I am 99% sure that this is some port from VRC4 or MMC3 to VRC2 with PAL enhancing mirroring and adding IRQs. But not this time - this is port from FME7 to VRC4. The logic chip (HY18CV8S-30) isn't PAL - datasheet says it is CMOS EEPLD. It makes it hard to analyze, because if it would be PAL, any latched bits would be presents on outputs pin. Here, they are internally stored and output on I/O pins at certain conditions.
What I tested so far is that the EEPLD's O0 (which is externally wired to I0) is
#########################################################################################################################################
Super Mario Bros 16
What is funny in this Mario's hack is that the PRG/CHR chips have all address/data lines scrambled. Even the MMC3 has A3 connected to its A0 input, making registers $x000/$x008, instead of $x000/$x001. ROM chips were OK, but the mapper blob was fried (getting hot very quickly), so I created new PCB for AX5202P with proper wiring so I could reuse those weird ROMs.
#########################################################################################################################################
JY-120 45 in 1
This is the famous cartridge which can be sell for some crazy dudes even for 600 pounds. As any mapper 90 cart, it is blob. But what is interesting is that the PRG is 2048 kB and CHR is 1024 kB (no idea why the ROM, floating on internet, has CHR 2045 kB).
PRG blob pinout is identical to 16 bit memories, like 27C800, and CHR is like 27c080. Unfortunately some PRG/CHR address lines of the mapper chip are floating and the PRG-ROM seems to be broken too.
#########################################################################################################################################
Rockman 6 in 1
All RockMans (probably ported to MMC3) in one (4 blobs: PRG-ROM, mapper, CHR-ROM and CHR-RAM). Mapper chip is broken so currently no further analysis.
#########################################################################################################################################
Wario Land 2
This is Kirby's adventure hack witch Kirby's sprites changed. Mapper is 90 (with CHR-RAM), but what is interesting is that CHR-A17 line behaves weird, producing messed graphic (it is said that starting the game with console's RESET pressed helps, but not in my case)
#########################################################################################################################################
SMB2j small
Ahh, this is real nightmare. I spent so many hours on analyzing this shit. One of the PRG-mask ROMs was broken (non-repeatable readback contents). I quickly figured out that other ROMs have contents very similar (with few bytes difference) to Super Mario Bros 2 (LF36) (which is mapper 43). So I tried replacing the broken ROM with programmed EPROM with proper content. But I got frozen title screen, without ability to start game. So I started analyzing the cartridge.
This PAL16L8 is pain in the ass, because it contains 4 latched outputs and also many outputs, which are feedback ones (depends on inputs and the latched ones). After hacking out the logic equations for everything:
Then I analysed to what memory map all those equations lead and I could get the final results (I used 4096 banking granularity, because PAL chips takes CPU-A12 into account). But every bank value can be divided by 2 to make 8192 granularity banks are used (except for $5000-$5fff), which yields that it is exactly mapper 043, without swap feature, but this time - it is the first, commented out scrambling pattern in FCEUX source:
So why after replacing the EPROM contents, I got only frozen screen? Because Super Mario Bros 2 (LF36) uses $8122 as IRQ register. After patching the rom in 2 locations to $4122 and reproramming EPROM, I got the cartridge working!
#########################################################################################################################################
SMB2j big
Another quite interesting cartridge. From the final ROM contents & emulation point, it is indentical to SMB2j Small, but the whole game was splitted quite differently over the chips:
They also needed 2 PALs to store the whole logic. The small 2k EPROM should be put into $5000. However, for some unknown reason, pin 12 of 7432 was not connected to anything, making this ROM never be activated and causing the cartridge to not work. Connecting both pin 12 & 13 solved the problem.
Next interesting fact is that the place under this 2k EPROM has been also prepared for soldering 6116 2k RAM memory (there is CPU R/!W wired to corresponding R/!W pin, which goes to Vpp if 2k EPROM is soldered). Probably this cartridge was prepared also for other game with RAM at $5000 or they maybe considered putting RAM at $5000 and filling it contents, instead of putting EPROM.
Also, M2 divided by 2048 is tied to 74*139 which one of outputs decoder is tied to this ROM's pin, which is also unknown:
Some logic equations:
31 in 1 multi-cart with 5 switches: 31 NROM games (30 x 16K + 1 * 32K)
I bet tepple's was wondering in one of previous posts if there ever was a cartridge with switches. So yes, it was and even they did the shell
for that with factory created holes with bevels for the switches. So it was not something done in low quantity.
Switches control both PRG & CHR upper address lines and few logic gates set proper mirroring & 16/32K mode upon them.
Games: Super Mario Bros, Moby Demo, Star Force, F-1 Race, Lode Runner, Raid on Bungeling Bay, NES Tutor 101, Kinnikuman - Muscle Tag Match, Chou Jikuu Yousai, - Macross, Chack 'n Pop, Ikki, Championship Lode Runner, Lunar Ball, Duck Hunt, Wild Gunman, Urban Champion, Ice Climber, Battle City, Pac-Man, Galaxian, Popeye, Devil World, Exerion, Donkey Kong, Donkey Kong Jr., Tennis, Field Combat, Golf, Space Invaders, Front Line, Zippy Race, Super Arabian
Code:
SW1 SW2 SW3 SW4 SW4 (top position=1, bottom position = 0)
s s s s s
| | | | |
+---+---+---+---+- select 8kB CHR
+---+---+---+---+- select 16 kB PRG (*)
+----------------- mirroring (0=V, 1=H)
(*) when sssss=00000/00001 -> $8000=00000, $c0000=00001
else -> $8000=sssss, $c0000=sssss
s s s s s
| | | | |
+---+---+---+---+- select 8kB CHR
+---+---+---+---+- select 16 kB PRG (*)
+----------------- mirroring (0=V, 1=H)
(*) when sssss=00000/00001 -> $8000=00000, $c0000=00001
else -> $8000=sssss, $c0000=sssss
What is also interesting is that the ROMs have uncommon pinout: HN62304 = 4 Mbit, HN62312 = 2 Mbit
Code:
.--v---.
A8 |01 31| A9
A7 |02 31| A10
A6 |03 30| A11
A5 |04 29| A12
A4 |05 28| A13
A3 |06 27| A14
A2 |07 26| A15
A1 |08 25| A16
!CE |09 24| A17
GND |10 23| A18 (NC in HN62312)
!OE |11 22| GND
D0 |12 21| A0
D1 |13 20| D7
D2 |14 19| D6
D3 |15 18| D5
VCC |16 17| D4
'------'
A8 |01 31| A9
A7 |02 31| A10
A6 |03 30| A11
A5 |04 29| A12
A4 |05 28| A13
A3 |06 27| A14
A2 |07 26| A15
A1 |08 25| A16
!CE |09 24| A17
GND |10 23| A18 (NC in HN62312)
!OE |11 22| GND
D0 |12 21| A0
D1 |13 20| D7
D2 |14 19| D6
D3 |15 18| D5
VCC |16 17| D4
'------'
#########################################################################################################################################
Princess maker
This is the oonly cartridge I ever saw in my life that has PLCC ROMs (which are EPROMS with windows!). One of them lost its content so I simply replaced it with 29F040. The mapper is just MMC3, but bit 7 and 6 of CHR registers are used as bit 7 and 6 of PRG, enhancing maximum possible PRG ROM size from 512 kB to 2048 kB (all 8 CHR registers must have the same bit 7 and 6, otherwise PRG banks will be switched during rendering).
This game has PRG capacity of 6 * 256 kB = 1536 kB
CHR-RAM is 32 kB and is bankable and it is battery backed!
BLOB chip is ordinary MMC3, with WRAM CE/WRAM !CE/WRAM WE / CHR A15 lines not connected externally to anything.
When CPU accesses $c000-$ffff, always first outer bank (first 512 kB of memory) is enabled.
$e000-$ffff will point to -1 bank in first 512 kB
$c000-$dfff:
* if $8000.6 = 0 -> will point to -2 bank in first 512 kB
* if $8000.6 = 1 -> this bank will be swappable but only always within first 512 kB
When CPU accesses $8000-$ffff, CHR-A17 and CHR-A16 selects outer bank
Code:
CHR CHR outer
A17 A16 bank
0 0 0
0 1 1
1 0 2
1 1 invalid (two memories are active at this time, which might damage them)
A17 A16 bank
0 0 0
0 1 1
1 0 2
1 1 invalid (two memories are active at this time, which might damage them)
Below is full logic table of which memory is enabled when:
Code:
CPU CHR CHR PRG | U1- U2- U3- LO- HI- | enabled
A14 A17 A16 A18 | !OE !OE !OE !CE !CE | memory
----------------+---------------------+-------
0 0 0 0 | 0 1 1 0 1 | U1L
0 0 0 1 | 0 1 1 1 0 | U1H
0 0 1 0 | 1 1 0 0 1 | U3L
0 0 1 1 | 1 1 0 1 0 | U3H
0 1 0 0 | 1 0 1 0 1 | U2L
0 1 0 1 | 1 0 1 1 0 | U2H
0 1 1 0 | 1 0 0 0 1 | U2L U3L
0 1 1 1 | 1 0 0 1 0 | U2H U3H
1 0 0 0 | 0 1 1 0 1 | U1L
1 0 0 1 | 0 1 1 1 0 | U1H
1 0 1 0 | 0 1 1 0 1 | U1L
1 0 1 1 | 0 1 1 1 0 | U1H
1 1 0 0 | 0 1 1 0 1 | U1L
1 1 0 1 | 0 1 1 1 0 | U1H
1 1 1 0 | 0 1 1 0 1 | U1L
1 1 1 1 | 0 1 1 1 0 | U1H
A14 A17 A16 A18 | !OE !OE !OE !CE !CE | memory
----------------+---------------------+-------
0 0 0 0 | 0 1 1 0 1 | U1L
0 0 0 1 | 0 1 1 1 0 | U1H
0 0 1 0 | 1 1 0 0 1 | U3L
0 0 1 1 | 1 1 0 1 0 | U3H
0 1 0 0 | 1 0 1 0 1 | U2L
0 1 0 1 | 1 0 1 1 0 | U2H
0 1 1 0 | 1 0 0 0 1 | U2L U3L
0 1 1 1 | 1 0 0 1 0 | U2H U3H
1 0 0 0 | 0 1 1 0 1 | U1L
1 0 0 1 | 0 1 1 1 0 | U1H
1 0 1 0 | 0 1 1 0 1 | U1L
1 0 1 1 | 0 1 1 1 0 | U1H
1 1 0 0 | 0 1 1 0 1 | U1L
1 1 0 1 | 0 1 1 1 0 | U1H
1 1 1 0 | 0 1 1 0 1 | U1L
1 1 1 1 | 0 1 1 1 0 | U1H
#########################################################################################################################################
4 in 1 multicart with 2 switches (FDS Port + 3 UNROM games)
This is quite interesting cartridge (also with switches), which has 4 games: SMB2J + Brave Soldier + Phoenix + Bobby Kids. They used HN62304 512 kB as PRG ROM (same as mentioned above). But what is more interesting is the SPCN 2810 mapper chip, which has pinout almost identical to typical JEDEC memories. At first I thought it is just simple ROM used as some kind of lookup table, but not. After spending many hours on analyzing it, I got the following results. The SMB2J is very similar to Mapper 43 with scrambling pattern as the one uncommented in FCEUX source code:
Code:
static DECLFW(M43Write) {
// int transo[8]={4,3,4,4,4,7,5,6};
int transo[8] = { 4, 3, 5, 3, 6, 3, 7, 3 }; // According to hardware tests
switch (A & 0xf1ff) {
...
// int transo[8]={4,3,4,4,4,7,5,6};
int transo[8] = { 4, 3, 5, 3, 6, 3, 7, 3 }; // According to hardware tests
switch (A & 0xf1ff) {
...
Code:
SPCN 2810 (from 8752, DIL28-600)
.---v--.
!RESET-> |01 28| +5V
CPU A12-> |02 27| <- CPU A14
CPU A7 -> |03 26| <- CPU A13
CPU A6 -> |04 25| <- CPU A8
CPU A5 -> |05 24| <- CPU R/!W
CPU A4 -> |06 23| -> !IRQ
CPU A3 -> |07 22| <- !ROMSEL
CPU A2 -> |08 21| <- MODE
CPU A1 -> |09 20| -> ROM !CE
CPU A0 -> |10 19| <- M2
CPU D0 -> |11 18| -> PRG A16
CPU D1 -> |12 17| -> PRG A15
CPU D2 -> |13 16| -> PRG A14
GND |14 15| -> PRG A13
'------'
Registers:
mask power-up
$4022 [.... .BBB] - bank select (for mode 0) $71ff 3 (when 4120.0 = 0) / 1 (when 4120.0 = 1)
$4120 [.... ...S] - bank swapping $71ff 0
$4122 [.... ...I] - IRQ off/on $f1ff 0
$8000 [.... .BBB] - bank select (for mode 1) $8000 0
MODE - sets the chip to two different modes:
WHen MODE = 0:
| $6000 | $8000 | $a000 | $c000 | $e000 |
$2 $1 $0 {$4022} $a (when $4120.0 = 0)
$0 $0 $0 {$4022} $8 (when $4120.0 = 1)
Bank at $c000 is switchable and can be changed by writing to $4022
written value : 0 1 2 3 4 5 6 7
bank will be switched to when $4120.0=0 : 4 3 5 3 6 3 7 3
bank will be switched to when $4120.0=1 : 1 1 5 1 4 1 5 1
$4122.0: when 0, irqs are disabled (any pending irq is acknowledged), when 1 - irqs are enabled
When IRQs are enabled, after 4096 rising edges of M2, IRQ is triggered (if it is not acknowledged, after another 4096 rising edges of M2, it will be automatically acknowledged)
---------------
When MODE = 1
| $6000 | $8000 | $c000 |
OPEN {$8000} $7
Value written at $8000 is directly stored in the register (without any scrabling)
----------------------------------------------------------------------------------
.---v--.
!RESET-> |01 28| +5V
CPU A12-> |02 27| <- CPU A14
CPU A7 -> |03 26| <- CPU A13
CPU A6 -> |04 25| <- CPU A8
CPU A5 -> |05 24| <- CPU R/!W
CPU A4 -> |06 23| -> !IRQ
CPU A3 -> |07 22| <- !ROMSEL
CPU A2 -> |08 21| <- MODE
CPU A1 -> |09 20| -> ROM !CE
CPU A0 -> |10 19| <- M2
CPU D0 -> |11 18| -> PRG A16
CPU D1 -> |12 17| -> PRG A15
CPU D2 -> |13 16| -> PRG A14
GND |14 15| -> PRG A13
'------'
Registers:
mask power-up
$4022 [.... .BBB] - bank select (for mode 0) $71ff 3 (when 4120.0 = 0) / 1 (when 4120.0 = 1)
$4120 [.... ...S] - bank swapping $71ff 0
$4122 [.... ...I] - IRQ off/on $f1ff 0
$8000 [.... .BBB] - bank select (for mode 1) $8000 0
MODE - sets the chip to two different modes:
WHen MODE = 0:
| $6000 | $8000 | $a000 | $c000 | $e000 |
$2 $1 $0 {$4022} $a (when $4120.0 = 0)
$0 $0 $0 {$4022} $8 (when $4120.0 = 1)
Bank at $c000 is switchable and can be changed by writing to $4022
written value : 0 1 2 3 4 5 6 7
bank will be switched to when $4120.0=0 : 4 3 5 3 6 3 7 3
bank will be switched to when $4120.0=1 : 1 1 5 1 4 1 5 1
$4122.0: when 0, irqs are disabled (any pending irq is acknowledged), when 1 - irqs are enabled
When IRQs are enabled, after 4096 rising edges of M2, IRQ is triggered (if it is not acknowledged, after another 4096 rising edges of M2, it will be automatically acknowledged)
---------------
When MODE = 1
| $6000 | $8000 | $c000 |
OPEN {$8000} $7
Value written at $8000 is directly stored in the register (without any scrabling)
----------------------------------------------------------------------------------
#########################################################################################################################################
Batman 2 J
Normally when I see DIP40 mapper chip + PAL16L8, I am 99% sure that this is some port from VRC4 or MMC3 to VRC2 with PAL enhancing mirroring and adding IRQs. But not this time - this is port from FME7 to VRC4. The logic chip (HY18CV8S-30) isn't PAL - datasheet says it is CMOS EEPLD. It makes it hard to analyze, because if it would be PAL, any latched bits would be presents on outputs pin. Here, they are internally stored and output on I/O pins at certain conditions.
What I tested so far is that the EEPLD's O0 (which is externally wired to I0) is
Code:
O0 <= '0' when M2=1 and !ROMSEL='0' and R/!W = '0' and A14=0 and A13=0 else '1'
#########################################################################################################################################
Super Mario Bros 16
What is funny in this Mario's hack is that the PRG/CHR chips have all address/data lines scrambled. Even the MMC3 has A3 connected to its A0 input, making registers $x000/$x008, instead of $x000/$x001. ROM chips were OK, but the mapper blob was fried (getting hot very quickly), so I created new PCB for AX5202P with proper wiring so I could reuse those weird ROMs.
#########################################################################################################################################
JY-120 45 in 1
This is the famous cartridge which can be sell for some crazy dudes even for 600 pounds. As any mapper 90 cart, it is blob. But what is interesting is that the PRG is 2048 kB and CHR is 1024 kB (no idea why the ROM, floating on internet, has CHR 2045 kB).
PRG blob pinout is identical to 16 bit memories, like 27C800, and CHR is like 27c080. Unfortunately some PRG/CHR address lines of the mapper chip are floating and the PRG-ROM seems to be broken too.
#########################################################################################################################################
Rockman 6 in 1
All RockMans (probably ported to MMC3) in one (4 blobs: PRG-ROM, mapper, CHR-ROM and CHR-RAM). Mapper chip is broken so currently no further analysis.
#########################################################################################################################################
Wario Land 2
This is Kirby's adventure hack witch Kirby's sprites changed. Mapper is 90 (with CHR-RAM), but what is interesting is that CHR-A17 line behaves weird, producing messed graphic (it is said that starting the game with console's RESET pressed helps, but not in my case)
#########################################################################################################################################
SMB2j small
Ahh, this is real nightmare. I spent so many hours on analyzing this shit. One of the PRG-mask ROMs was broken (non-repeatable readback contents). I quickly figured out that other ROMs have contents very similar (with few bytes difference) to Super Mario Bros 2 (LF36) (which is mapper 43). So I tried replacing the broken ROM with programmed EPROM with proper content. But I got frozen title screen, without ability to start game. So I started analyzing the cartridge.
This PAL16L8 is pain in the ass, because it contains 4 latched outputs and also many outputs, which are feedback ones (depends on inputs and the latched ones). After hacking out the logic equations for everything:
Code:
O1 <=
'0' when (!ASEL0 & CPU_D0 & !CPU_D1 & !CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) else
'1' when (!ASEL0 & !CPU_D0 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL0 & CPU_D1 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL0 & CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL);
O2 <=
'0' when (!ASEL0 & CPU_D0 & CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) else
'1' when (!ASEL0 & !CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL0 & !CPU_D0 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL);
O3 <=
'0' when (!ASEL0 & CPU_D1 & CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) else
'1' when (!ASEL0 & !CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL0 & !CPU_D1 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL);
RESET <=
'0' when (!ASEL1 & CPU_D0 & CPU_D1 & !CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) else
'1' when (!ASEL1 & !CPU_D1 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL1 & !CPU_D0 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL1 & CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL);
PRG_A13 = (O3 & !O2 & O1 & !CPU_A13) |
(!O3 & O2 & O1 & !CPU_A13) |
(O3 & O2 & CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O3 & O2 & !O1 & !CPU_A13) |
(O1 & CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O3 & O2 & !CPU_A14 & CPU_nROMSEL) |
(O1 & !CPU_A14 & CPU_nROMSEL) |
(O1 & !CPU_A13 & !CPU_A14) |
(O1 & !CPU_A13 & CPU_nROMSEL);
PRGSEL0 = (O1 & !CPU_A12 & !CPU_A13 & CPU_nROMSEL) |
(O3 & O2 & !CPU_A14 & CPU_nROMSEL) |
(O1 & !CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O3 & O2 & !CPU_A12 & !CPU_A13 & CPU_nROMSEL) |
(O1 & !CPU_A14 & CPU_nROMSEL);
PRGSEL1 = (O3 & O2 & CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O1 & CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O3 & O2 & !CPU_A14 & CPU_nROMSEL) |
(O3 & O2 & !CPU_A13 & CPU_nROMSEL) |
(O1 & !CPU_A14 & CPU_nROMSEL) |
(O1 & !CPU_A13 & CPU_nROMSEL);
PRG_A14 = (O3 & O2 & !O1 & CPU_A14) |
(O3 & O2 & CPU_nROMSEL) |
(!O2 & O1 & CPU_A14) |
( O1 & CPU_nROMSEL) |
(O1 & CPU_A13 & CPU_A14);
'0' when (!ASEL0 & CPU_D0 & !CPU_D1 & !CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) else
'1' when (!ASEL0 & !CPU_D0 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL0 & CPU_D1 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL0 & CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL);
O2 <=
'0' when (!ASEL0 & CPU_D0 & CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) else
'1' when (!ASEL0 & !CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL0 & !CPU_D0 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL);
O3 <=
'0' when (!ASEL0 & CPU_D1 & CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) else
'1' when (!ASEL0 & !CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL0 & !CPU_D1 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL);
RESET <=
'0' when (!ASEL1 & CPU_D0 & CPU_D1 & !CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) else
'1' when (!ASEL1 & !CPU_D1 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL1 & !CPU_D0 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL) |
(!ASEL1 & CPU_D2 & !CPU_RnW & !CPU_A12 & !CPU_A13 & CPU_A14 & CPU_nROMSEL);
PRG_A13 = (O3 & !O2 & O1 & !CPU_A13) |
(!O3 & O2 & O1 & !CPU_A13) |
(O3 & O2 & CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O3 & O2 & !O1 & !CPU_A13) |
(O1 & CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O3 & O2 & !CPU_A14 & CPU_nROMSEL) |
(O1 & !CPU_A14 & CPU_nROMSEL) |
(O1 & !CPU_A13 & !CPU_A14) |
(O1 & !CPU_A13 & CPU_nROMSEL);
PRGSEL0 = (O1 & !CPU_A12 & !CPU_A13 & CPU_nROMSEL) |
(O3 & O2 & !CPU_A14 & CPU_nROMSEL) |
(O1 & !CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O3 & O2 & !CPU_A12 & !CPU_A13 & CPU_nROMSEL) |
(O1 & !CPU_A14 & CPU_nROMSEL);
PRGSEL1 = (O3 & O2 & CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O1 & CPU_A13 & CPU_A14 & !CPU_nROMSEL) |
(O3 & O2 & !CPU_A14 & CPU_nROMSEL) |
(O3 & O2 & !CPU_A13 & CPU_nROMSEL) |
(O1 & !CPU_A14 & CPU_nROMSEL) |
(O1 & !CPU_A13 & CPU_nROMSEL);
PRG_A14 = (O3 & O2 & !O1 & CPU_A14) |
(O3 & O2 & CPU_nROMSEL) |
(!O2 & O1 & CPU_A14) |
( O1 & CPU_nROMSEL) |
(O1 & CPU_A13 & CPU_A14);
Then I analysed to what memory map all those equations lead and I could get the final results (I used 4096 banking granularity, because PAL chips takes CPU-A12 into account). But every bank value can be divided by 2 to make 8192 granularity banks are used (except for $5000-$5fff), which yields that it is exactly mapper 043, without swap feature, but this time - it is the first, commented out scrambling pattern in FCEUX source:
Code:
static DECLFW(M43Write) {
// int transo[8]={4,3,4,4,4,7,5,6};
int transo[8] = { 4, 3, 5, 3, 6, 3, 7, 3 }; // According to hardware tests
switch (A & 0xf1ff) {
...
// int transo[8]={4,3,4,4,4,7,5,6};
int transo[8] = { 4, 3, 5, 3, 6, 3, 7, 3 }; // According to hardware tests
switch (A & 0xf1ff) {
...
Code:
Memory map:
$5000 | $6000 | $7000 | $8000 | $9000 | $a000 | $b000 | $c000 | $d000 | $e000 | $f000
$11 $4 $5 $2 $3 $0 $1 {$4022} {$4022} $12 $13
+ 1
when 8kB granularity:
$5000 | $6000 | $8000 | $a000 | $c000 | $e000
$17 $2 $1 $0 {$4022} $9
Registers (all have mask $f1ff)
$4022 [.... ..PPP] - set PRG bank, note that this reg is scrambled so that:
written value at D2-D0: 0 1 2 3 4 5 6 7
value latched at O3-O1: 7 6 7 7 7 5 3 1
bank set to $c000 : $8 $6 $8 $8 $8 $e $a $c
$4122 [.... ..III] - enable (3) or disable+ack (0/1/2/4/5/6/7) interrupt
When enabled, interrupt is triggered after 4096 rising edges of M2 (when not acked, it will be
automatically acked after another 4096 rising edges)
$5000 | $6000 | $7000 | $8000 | $9000 | $a000 | $b000 | $c000 | $d000 | $e000 | $f000
$11 $4 $5 $2 $3 $0 $1 {$4022} {$4022} $12 $13
+ 1
when 8kB granularity:
$5000 | $6000 | $8000 | $a000 | $c000 | $e000
$17 $2 $1 $0 {$4022} $9
Registers (all have mask $f1ff)
$4022 [.... ..PPP] - set PRG bank, note that this reg is scrambled so that:
written value at D2-D0: 0 1 2 3 4 5 6 7
value latched at O3-O1: 7 6 7 7 7 5 3 1
bank set to $c000 : $8 $6 $8 $8 $8 $e $a $c
$4122 [.... ..III] - enable (3) or disable+ack (0/1/2/4/5/6/7) interrupt
When enabled, interrupt is triggered after 4096 rising edges of M2 (when not acked, it will be
automatically acked after another 4096 rising edges)
So why after replacing the EPROM contents, I got only frozen screen? Because Super Mario Bros 2 (LF36) uses $8122 as IRQ register. After patching the rom in 2 locations to $4122 and reproramming EPROM, I got the cartridge working!
#########################################################################################################################################
SMB2j big
Another quite interesting cartridge. From the final ROM contents & emulation point, it is indentical to SMB2j Small, but the whole game was splitted quite differently over the chips:
Code:
SMB2j big:
PRG1 = 32k = 3C B5 58 49 ...
PRG2 = 32k = 72 07 8D A2 ...
PRG3 = 2k = 03 04 00 23 ...
PRG4 = 16k = 00 18 4C C6 ... (first 8k)
00 18 4C C6 ... (second 8k)
SMB2j small:
PRG1 = 32k = 3C B5 58 49 ...
PRG2 = 32k = 72 07 8D A2 ...
PRG3 = 16k = 03 04 00 23 ... (first 2k - offset $735 = $00)
03 04 00 23 ... (second 2k - offset $735 = $01, other bytes like first)
03 04 00 23 ... (third 2k - differ in many bytes from previous, probably removed the title screen)
03 04 00 23 ... (fourth 2k - offset $75 = $03, other bytes like first)
00 18 4C C6 ... (like in SMB2j big PRG4, but offset $e43 = $81, in smb2j big was $41, so probably high byte of IRQ register address)
PRG1 = 32k = 3C B5 58 49 ...
PRG2 = 32k = 72 07 8D A2 ...
PRG3 = 2k = 03 04 00 23 ...
PRG4 = 16k = 00 18 4C C6 ... (first 8k)
00 18 4C C6 ... (second 8k)
SMB2j small:
PRG1 = 32k = 3C B5 58 49 ...
PRG2 = 32k = 72 07 8D A2 ...
PRG3 = 16k = 03 04 00 23 ... (first 2k - offset $735 = $00)
03 04 00 23 ... (second 2k - offset $735 = $01, other bytes like first)
03 04 00 23 ... (third 2k - differ in many bytes from previous, probably removed the title screen)
03 04 00 23 ... (fourth 2k - offset $75 = $03, other bytes like first)
00 18 4C C6 ... (like in SMB2j big PRG4, but offset $e43 = $81, in smb2j big was $41, so probably high byte of IRQ register address)
They also needed 2 PALs to store the whole logic. The small 2k EPROM should be put into $5000. However, for some unknown reason, pin 12 of 7432 was not connected to anything, making this ROM never be activated and causing the cartridge to not work. Connecting both pin 12 & 13 solved the problem.
Next interesting fact is that the place under this 2k EPROM has been also prepared for soldering 6116 2k RAM memory (there is CPU R/!W wired to corresponding R/!W pin, which goes to Vpp if 2k EPROM is soldered). Probably this cartridge was prepared also for other game with RAM at $5000 or they maybe considered putting RAM at $5000 and filling it contents, instead of putting EPROM.
Also, M2 divided by 2048 is tied to 74*139 which one of outputs decoder is tied to this ROM's pin, which is also unknown:
Some logic equations:
Code:
### pal b8636 ###
n5000 = (!CPU_A14) | (!CPU-A12) | (!CPU_nROMSEL) | (CPU_A13);
PRG1_nCE = (!CPU_A13 & CPU_A14 & SIG33) | (!CPU_nROMSEL & CPU_A13 & CPU_A14) | (CPU_nROMSEL & !CPU_A14) | (CPU_nROMSEL & !CPU_A13) | (!CPU_RnW);
PRG1_A14 = (CPU_nROMSEL) | (CPU_A14);
PRG1_A13 = (CPU_nROMSEL & !CPU_A14) | (!CPU_nROMSEL & CPU_A14) | (!CPU_A13);
n4022 = (!CPU-A5) | (!CPU-A1) | (!CPU_A14) | (!CPU_nROMSEL) | (CPU-A12) | (CPU_A13) | (CPU_RnW) | (A6_OR_A7) | (A2_OR_A0) | (A4_OR_A3) | (CPU-A8);
n4122 = (!CPU-A8) | (!CPU-A5) | (!CPU-A1) | (!CPU_A14) | (!CPU_nROMSEL) | (CPU-A12) | (CPU_A13) | (CPU_RnW) | (A6_OR_A7) | (A2_OR_A0) | (A4_OR_A3);
// n4022: 0 when cpu_write @ 0100xxx000100010 else '1' ;$4022, mask=$f1ff
// n4122: 0 when cpu_write @ 0100xxx100100010 else '1' ;$4122, mask=$f1ff
// n5000: 0 when cpu_r/w @ 0101xxxxxxxxxxxx else '1' ;$5000-5fff
### pal b8632 #
O4 <=
'0' when (CPU_D1 & CPU_D2 & !n4022) else
'1' when (!CPU_D2 & !n4022) | (!CPU_D1 & !n4022);
O5 <=
'0' when (CPU_D0 & CPU_D2 & !n4022) else
'1' when (!CPU_D2 & !n4022) | (!CPU_D0 & !n4022);
SIG33 <=
'0' when (CPU_D0 & !CPU_D1 & !CPU_D2 & !n4022) else
'1' when (!CPU_D0 & !n4022) | (CPU_D1 & !n4022) | (CPU_D2 & !n4022);
RESET <=
'0' when (CPU_D0 & CPU_D1 & !CPU_D2 & !n4122) else
'1' when (!CPU_D1 & !n4122) | (!CPU_D0 & !n4122) | (CPU_D2 & !n4122);
PRG2_nCE = (O5 & O4 & !SIG33) | (SIG33 & !PRG1_nCE) | (SIG33 & !CPU_A14) | (
SIG33 & CPU_nROMSEL);
PRG2_A14 = (O5 & O4 & !SIG33) | (!O5 & SIG33) | (SIG33 & !PRG1_nCE) | (SIG33
& !CPU_A14) | (SIG33 & !n5000) | (SIG33 & CPU_nROMSEL);
PRG2_A13 = (O5 & O4 & !SIG33) | (SIG33 & !PRG1_nCE) | (SIG33 & !CPU_A14) | (
SIG33 & !n5000) | (SIG33 & CPU_nROMSEL) | (O5 & !O4 & SIG33) | (!O5 & O4 & SIG33);
nIRQ = (!CPU_D0) | (!M2_8192) | (RESET);
---
Value written at $4022: 0 1 2 3 4 5 6 7
Value stored at O4: 1 1 1 1 1 1 0 0
Value stored at O5: 1 1 1 1 1 0 1 0
Value stored at SIG33: 1 0 1 1 1 1 1 1
Value written at $4122: 0 1 2 3 4 5 6 7
Value stored at RESET: 1 1 1 0 1 1 1 1
n5000 = (!CPU_A14) | (!CPU-A12) | (!CPU_nROMSEL) | (CPU_A13);
PRG1_nCE = (!CPU_A13 & CPU_A14 & SIG33) | (!CPU_nROMSEL & CPU_A13 & CPU_A14) | (CPU_nROMSEL & !CPU_A14) | (CPU_nROMSEL & !CPU_A13) | (!CPU_RnW);
PRG1_A14 = (CPU_nROMSEL) | (CPU_A14);
PRG1_A13 = (CPU_nROMSEL & !CPU_A14) | (!CPU_nROMSEL & CPU_A14) | (!CPU_A13);
n4022 = (!CPU-A5) | (!CPU-A1) | (!CPU_A14) | (!CPU_nROMSEL) | (CPU-A12) | (CPU_A13) | (CPU_RnW) | (A6_OR_A7) | (A2_OR_A0) | (A4_OR_A3) | (CPU-A8);
n4122 = (!CPU-A8) | (!CPU-A5) | (!CPU-A1) | (!CPU_A14) | (!CPU_nROMSEL) | (CPU-A12) | (CPU_A13) | (CPU_RnW) | (A6_OR_A7) | (A2_OR_A0) | (A4_OR_A3);
// n4022: 0 when cpu_write @ 0100xxx000100010 else '1' ;$4022, mask=$f1ff
// n4122: 0 when cpu_write @ 0100xxx100100010 else '1' ;$4122, mask=$f1ff
// n5000: 0 when cpu_r/w @ 0101xxxxxxxxxxxx else '1' ;$5000-5fff
### pal b8632 #
O4 <=
'0' when (CPU_D1 & CPU_D2 & !n4022) else
'1' when (!CPU_D2 & !n4022) | (!CPU_D1 & !n4022);
O5 <=
'0' when (CPU_D0 & CPU_D2 & !n4022) else
'1' when (!CPU_D2 & !n4022) | (!CPU_D0 & !n4022);
SIG33 <=
'0' when (CPU_D0 & !CPU_D1 & !CPU_D2 & !n4022) else
'1' when (!CPU_D0 & !n4022) | (CPU_D1 & !n4022) | (CPU_D2 & !n4022);
RESET <=
'0' when (CPU_D0 & CPU_D1 & !CPU_D2 & !n4122) else
'1' when (!CPU_D1 & !n4122) | (!CPU_D0 & !n4122) | (CPU_D2 & !n4122);
PRG2_nCE = (O5 & O4 & !SIG33) | (SIG33 & !PRG1_nCE) | (SIG33 & !CPU_A14) | (
SIG33 & CPU_nROMSEL);
PRG2_A14 = (O5 & O4 & !SIG33) | (!O5 & SIG33) | (SIG33 & !PRG1_nCE) | (SIG33
& !CPU_A14) | (SIG33 & !n5000) | (SIG33 & CPU_nROMSEL);
PRG2_A13 = (O5 & O4 & !SIG33) | (SIG33 & !PRG1_nCE) | (SIG33 & !CPU_A14) | (
SIG33 & !n5000) | (SIG33 & CPU_nROMSEL) | (O5 & !O4 & SIG33) | (!O5 & O4 & SIG33);
nIRQ = (!CPU_D0) | (!M2_8192) | (RESET);
---
Value written at $4022: 0 1 2 3 4 5 6 7
Value stored at O4: 1 1 1 1 1 1 0 0
Value stored at O5: 1 1 1 1 1 0 1 0
Value stored at SIG33: 1 0 1 1 1 1 1 1
Value written at $4122: 0 1 2 3 4 5 6 7
Value stored at RESET: 1 1 1 0 1 1 1 1