It is currently Mon Dec 11, 2017 12:07 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Fri Jul 28, 2017 5:09 pm 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 254
Location: Poland
I got Rinco famiclone (which looks just like Famicom) to fix it. It has one additional 60 pin cartridge socket underneath with multi-game cartridge inserted. I decided to reverse-engineer it because it looks funny (PAL, so many diodes and some mysterious pads with missing chips & resistors)
Image

The cartridge was probably projectted to be put in two-slot consoles, because it is really narrow (nothing to lock against clips in cartridge shell) and was done on 1.5 mm laminate - requires so much force to put it inside.

I dumped the menu (CPU $8000-$FFFF + PPU $0000-$1FFF), which can be done with help of kazzo to almost any multicart cartridge without knowledge how it works - except those which start messing with banks at startup.

Cartridge contains 200 000 games, but in fact, only: Mario, Lunar ball, Duck Hunt, Wild gunman, Hogans Alley, Bomber man, Tank, Sky destroyer, Binary land, Ice climber. Programmers divided the menu into 1-5000, 5001-10000, etc for easier navigation.
Image Image Image

First i desoldered chips and rev-ed all tracks
Image Image

Those glob-tobs have pins in almost same order like ordinary ROMs:
Image Image

PRG-ROM is 256k, CHR-ROM is 128 kB. CHR-ROM has only one chip enable line.

Then I rev-ed schematics:
Image

Some notes:
* There is 74273 8 bit latch (adress bits A0-A7 are latched, but A4 & A5 are not used)
* ROM is not turned off during writes at $8000-$FFFF (bus conflicts),
* There is R-C-D reset circuitry which sets latch's bits to 0 on startup,
* Two diodes + resistors were used as poor man's OR gate (ORing PPU-A13 & PPU-!RD to feed the result into CHR-ROM's !CE),
* PAL16L8's is configured to serve as 12 input & 6 output combinational logic.

Then I dumped the PAL to binary using my home-made flash reader.
Then I wrote simple program to convert the binary file into espresso text description:
Code:
.i 12
.o 6
.ilb PPU-A11 PPU-A10 REG.A7 REG.A6 CPU-A14 CPU-A13 CPU-A12 REG.A2 REG.A1 REG.A0 CPU-!ROMSEL! CPU-R/!W!
.ob REG.WR PRG-A14 PRG-A15 PRG-A16 BUF-!OE! CIRAM-A10
000000000000 000010
000000000001 000010
000000000010 000010
000000000011 000010
000000000100 010010
000000000101 010010
000000000110 010010
000000000111 010010
...


Then I ran espresso on this file to generate logic formulas for each output:
Code:
REG.WR = (CPU-A14 & not CPU-A13 & CPU-A12 & CPU-!ROMSEL! & not CPU-R/!W!);
PRG-A14 = (not REG.A6 & CPU-A14 & not REG.A1) | (not REG.A6 & CPU-A14 & not REG.A2) | (REG.A0);
PRG-A15 = (not REG.A6 & REG.A2 & REG.A0) | (not REG.A6 & CPU-A14 & not REG.A2) | (REG.A1);
PRG-A16 = (not REG.A6 & CPU-A14 & notREG.A2) | (REG.A2);
BUF-!OE! = (CPU-A14 & not CPU-A13 & CPU-A12 & CPU-!ROMSEL! & not CPU-R/!W!) | (not CPU-!ROMSEL!) | (notCPU-A12) | (CPU-A13) | (not CPU-A14);
CIRAM-A10 = (PPU-A10 & not REG.A7) | (PPU-A11 & REG.A7);


Data is latched on rising edge of REG.WR signal, which corresponds to writes at $5000-$5FFF (beginning of cycle) or $D000-$DFFF (end of cycle). In fact, first region is used because it does not produce bus conflicts with ROM.

Generally:
* PRG-A14 <- A0, PRG-A15 <- A1, PRG-A16 <- A2, PRG-A17 <= A3 (at $8000-$b000),
* A6 controls 16 KB / 32 KB banking mode,
* at $c000-$ffff there is some magic,
* A7 controls mirroring

Mysterious DIL14 chip, resistors and jumpers
In those mysterious 14 pads probably 74125 tri state buffer should be placed:
Image Image

Its four inputs are combination of GND/VCC (according to jumpers), which are placed on D0-D3 bus when BUF_!OE goes low, which corresponds to reading from $5000-$5FFF. Probably that could be used for reading some magic value and displaying different game sets, based on that (manufacturer could produce just one type of PCB with same glop-tops and create pseudo-different cartridges according to jumpers)


Kazzo script for dumping whole set would be:
for (a = 0x5000; a < 0x5010; ++a) {
cpu_w(a, 0x00);
cpu_r(0x8000, 0xbfff);
ppu_r(0x0000, 0x1fff);
}
During whole operation, m2 must have 1.7 MHz clock, otherwise register will reset.


Attachments:
pal.bin [4 KiB]
Downloaded 33 times
only_menu.nes [40.02 KiB]
Downloaded 31 times
Top
 Profile  
 
PostPosted: Fri Jul 28, 2017 5:33 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1393
Probably shouldn't attach the full multicart ROM, since those games are technically copyrighted (even if the copyright text has been edited out) - the menu-only ROM is probably fine, though.

_________________
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.


Top
 Profile  
 
PostPosted: Fri Jul 28, 2017 6:29 pm 
Offline

Joined: Mon Dec 12, 2011 8:15 pm
Posts: 362
krzysiobal wrote:
I got Rinco famiclone (which looks just like Famicom) to fix it. It has one additional 60 pin cartridge socket underneath with multi-game cartridge inserted. I decided to reverse-engineer it because it looks funny (PAL, so many diodes and some mysterious pads with missing chips & resistors)
Image

The cartridge was probably projectted to be put in two-slot consoles, because it is really narrow (nothing to lock against clips in cartridge shell) and was done on 1.5 mm laminate - requires so much force to put it inside.

I dumped the menu (CPU $8000-$FFFF + PPU $0000-$1FFF), which can be done with help of kazzo to almost any multicart cartridge without knowledge how it works - except those which start messing with banks at startup.

Cartridge contains 200 000 games, but in fact, only: Mario, Lunar ball, Duck Hunt, Wild gunman, Hogans Alley, Bomber man, Tank, Sky destroyer, Binary land, Ice climber. Programmers divided the menu into 1-5000, 5001-10000, etc for easier navigation.
Image Image Image

First i desoldered chips and rev-ed all tracks
Image Image

Those glob-tobs have pins in almost same order like ordinary ROMs:
Image Image

PRG-ROM is 256k, CHR-ROM is 128 kB. CHR-ROM has only one chip enable line.

Then I rev-ed schematics:
Image

Some notes:
* There is 74273 8 bit latch (adress bits A0-A7 are latched, but A4 & A5 are not used)
* ROM is not turned off during writes at $8000-$FFFF (bus conflicts),
* There is R-C-D reset circuitry which sets latch's bits to 0 on startup,
* Two diodes + resistors were used as poor man's OR gate (ORing PPU-A13 & PPU-!RD to feed the result into CHR-ROM's !CE),
* PAL16L8's is configured to serve as 12 input & 6 output combinational logic.

Then I dumped the PAL to binary using my home-made flash reader.
Then I wrote simple program to convert the binary file into espresso text description:
Code:
.i 12
.o 6
.ilb PPU-A11 PPU-A10 REG.A7 REG.A6 CPU-A14 CPU-A13 CPU-A12 REG.A2 REG.A1 REG.A0 CPU-!ROMSEL! CPU-R/!W!
.ob REG.WR PRG-A14 PRG-A15 PRG-A16 BUF-!OE! CIRAM-A10
000000000000 000010
000000000001 000010
000000000010 000010
000000000011 000010
000000000100 010010
000000000101 010010
000000000110 010010
000000000111 010010
...


Then I ran espresso on this file to generate logic formulas for each output:
Code:
REG.WR = (CPU-A14 & not CPU-A13 & CPU-A12 & CPU-!ROMSEL! & not CPU-R/!W!);
PRG-A14 = (not REG.A6 & CPU-A14 & not REG.A1) | (not REG.A6 & CPU-A14 & not REG.A2) | (REG.A0);
PRG-A15 = (not REG.A6 & REG.A2 & REG.A0) | (not REG.A6 & CPU-A14 & not REG.A2) | (REG.A1);
PRG-A16 = (not REG.A6 & CPU-A14 & notREG.A2) | (REG.A2);
BUF-!OE! = (CPU-A14 & not CPU-A13 & CPU-A12 & CPU-!ROMSEL! & not CPU-R/!W!) | (not CPU-!ROMSEL!) | (notCPU-A12) | (CPU-A13) | (not CPU-A14);
CIRAM-A10 = (PPU-A10 & not REG.A7) | (PPU-A11 & REG.A7);


Data is latched on rising edge of REG.WR signal, which corresponds to writes at $5000-$5FFF (beginning of cycle) or $D000-$DFFF (end of cycle). In fact, first region is used because it does not produce bus conflicts with ROM.

Generally:
* PRG-A14 <- A0, PRG-A15 <- A1, PRG-A16 <- A2, PRG-A17 <= A3 (at $8000-$b000),
* A6 controls 16 KB / 32 KB banking mode,
* at $c000-$ffff there is some magic,
* A7 controls mirroring

Mysterious DIL14 chip, resistors and jumpers
In those mysterious 14 pads probably 74125 tri state buffer should be placed:
Image Image

Its four inputs are combination of GND/VCC (according to jumpers), which are placed on D0-D3 bus when BUF_!OE goes low, which corresponds to reading from $5000-$5FFF. Probably that could be used for reading some magic value and displaying different game sets, based on that (manufacturer could produce just one type of PCB with same glop-tops and create pseudo-different cartridges according to jumpers)


Kazzo script for dumping whole set would be:
for (a = 0x5000; a < 0x5010; ++a) {
cpu_w(a, 0x00);
cpu_r(0x8000, 0xbfff);
ppu_r(0x0000, 0x1fff);
}
During whole operation, m2 must have 1.7 MHz clock, otherwise register will reset.



dump bad! I think!


Top
 Profile  
 
PostPosted: Fri Jul 28, 2017 7:22 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6503
Location: Seattle
krzysiobal wrote:
Data is latched on rising edge of REG.WR signal, which corresponds to writes at $5000-$5FFF (beginning of cycle) or $D000-$DFFF (end of cycle). In fact, first region is used because it does not produce bus conflicts with ROM.
Due to only relying on /ROMSEL (and not M2), it's actually a little weirder/better. For both addresses, /ROMSEL is high for the first half cycle, and so ROM is also not driving for the first half cycle.
The ≈20ns latency due to the 74'139 on the mainboard means that the write ends up being latched on the rising edge of the previous /ROMSEL, at which point all the other signals are stable.

When /ROMSEL falls on a write to $D000, the rising edge has already happened; there will be no bus conflicts for the latch to care about. (There'll still be a fight between the ROM and the CPU). When /ROMSEL rises again on the following cycle, the other checked values will have already changed.

I used Minilog to see if I can could a clearer explanation of what the banking logic is, but it only sorta helped.
PRG-A16 can be simplified: (/Q6 & CPUA14) | Q2
BUF-/OE can be simplified also: /R/W | //ROMSEL | /A12 | /A14 | A13.

In conclusion, the only idea I can think of is to make a table:
Code:
 reg&$47 bank$8000 bank$C000
  00         0         7
  01         1         7
  02         2         7
  03         3         7
  04         4         5
  05         7         7
  06         6         3
  07         7         7
  40         0         0 ; vv- the already-identified 16K mode
  41         1         1
  42         2         2
  43         3         3
  44         4         4
  45         5         5
  46         6         6
  47         7         7


So, when Q6 is low ... there's room for one 64K UNROM game across 16K banks 0,1,2,7, and two 32K NROM games in banks 4,5, and 6,3. (in each 128K half of the 256K PRG)


Top
 Profile  
 
PostPosted: Sat Jul 29, 2017 10:48 am 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 254
Location: Poland
Quote:
The ≈20ns latency due to the 74'139 on the mainboard means that the write ends up being latched on the rising edge of the previous /ROMSEL, at which point all the other signals are stable.

There is huge 10nF capacitor on latch's clock to ground, so it probably will block such spikes.

Quote:
So, when Q6 is low ... there's room for one 64K UNROM game across 16K banks 0,1,2,7, and two 32K NROM games in banks 4,5, and 6,3. (in each 128K half of the 256K PRG)

Maybe there is also Contra, because there are entries like `jungale, base1, waterfall, base2, snow field, energy zone` which corrsponds to level names (I forgot to check it, now the cart is no longer in my hands),

I think the 'jumpers' are rather intended to be used with some kind of switch, rather than jumpers (otherwise they would not put places for resistors).

The menu just before start indeed reads $5000-$5fff (even twice and copares the values, if they are not equal, it ends in infinite loop). Thanks to open bus capacitance, 0x50 is read.

Code:
 01:CC80:AD 00 50  LDA $5000 = #$EA
 01:CC83:85 12     STA $0012 = #$50
 01:CC85:EA        NOP
 01:CC86:EA        NOP
>01:CC87:AD 01 50  LDA $5001 = #$EA
 01:CC8A:C5 12     CMP $0012 = #$50
 01:CC8C:D0 F2     BNE $CC80
 01:CC8E:A5 12     LDA $0012 = #$50
 01:CC90:29 0F     AND #$0F
 01:CC92:C9 01     CMP #$01
 01:CC94:90 0B     BCC $CCA1
 01:CC96:C9 03     CMP #$03
 01:CC98:90 0A     BCC $CCA4
 01:CC9A:C9 06     CMP #$06
 01:CC9C:90 0C     BCC $CCAA
 01:CC9E:4C B0 CC  JMP $CCB0
 01:CCA1:4C 00 80  JMP $8000
 01:CCA4:8D 01 50  STA $5001 = #$EA
 01:CCA7:4C 00 80  JMP $8000
 01:CCAA:8D 02 50  STA $5002 = #$EA
 01:CCAD:4C 00 80  JMP $8000
 01:CCB0:8D 03 50  STA $5003 = #$EA
 01:CCB3:4C 00 80  JMP $8000


Top
 Profile  
 
PostPosted: Sat Jul 29, 2017 11:19 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6503
Location: Seattle
krzysiobal wrote:
There is huge 10nF capacitor on latch's clock to ground, so it probably will block such spikes.
Even better.

Thinking about it a little more, I realized there could be bus conflicts during the moment of transition. Adding the capacitor helps protect against that.

Code:
                        v bus conflict while /ROMSEL still low and R/W low
 A0-A15 < ROM          >< $5 or $D xxx >
  D0-D7 ><HiZ ><   ROM  ◇  CPU         >
    R/W ^^^^^^^^^^^^^^^^________________
     M2 ______^^^^^^^^^^______^^^^^^^^^^
/ROMSEL _^^^^^^__________^^^^^^=========
                        >< latch would happen here without added capacitor; ROM hasn't gotten off the bus yet


Quote:
I think the 'jumpers' are rather intended to be used with some kind of switch, rather than jumpers (otherwise they would not put places for resistors).
Maybe pre-populated jumpers and resistors, and the person doing the customization just needs a diagonal cutter instead of a soldering iron?

Quote:
Code:
 01:CC80:AD 00 50  LDA $5000 = #$EA
[...]
 01:CCA4:8D 01 50  STA $5001 = #$EA
 01:CCAA:8D 02 50  STA $5002 = #$EA
 01:CCB0:8D 03 50  STA $5003 = #$EA
So it ultimately switches between one of three different stubs, all of which have access to the same bank at $C000, depending on the value from the jumper pack. Odd.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: bazza and 7 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