Breaking NES apart (WARNING: traffic)

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

Moderators: B00daW, Moderators

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Breaking NES apart (WARNING: traffic)

Post by org » Tue Aug 07, 2012 12:42 pm

Hi.

I'm going to reverse engineer NES chips, including 2A03 (CPU) and 2C02 (PPU), both revision G and write its truly cycle-accurate emulator.

Die photos are available around (visual6502, quietust site). I do chip tracing by my own.

You can find my 6502-related topic on 6502.org board: http://forum.6502.org/viewtopic.php?f=8&t=2208

My current progress on APU:
Image

PPU:
Image

User avatar
cpow
NESICIDE developer
Posts: 1097
Joined: Mon Oct 13, 2008 7:55 pm
Location: Minneapolis, MN
Contact:

Re: Breaking NES apart (WARNING: traffic)

Post by cpow » Tue Aug 07, 2012 12:48 pm

Yay. There'll finally be an emulator with worse performance than mine! :shock:

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Re: Breaking NES apart (WARNING: traffic)

Post by org » Tue Aug 07, 2012 12:48 pm

Todays speccy: APU address pin

Image

Address pin use tri-state logic to disconnect address bus, while NC/A line is high.

Note: I will use 6502-like bus and control lines notation. For example, "1/A0" mean "put 1 on A0 line". And A0 mean simply "bit 0 of address bus".

cpow, performance doesn't matter on modern PC's :mrgreen:

lidnariq
Posts: 9307
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Breaking NES apart (WARNING: traffic)

Post by lidnariq » Tue Aug 07, 2012 3:56 pm

You might consider trying to get a hold of Quietust, who's done a lot of inspecting the CPU's die before, and took the visual6502 code to make visual2a03. He's apparently also been responsible for some back-end changes in Visual6502 to make setting up simulations of non-cpus like the 2c02 easier and more sensical.

User avatar
rainwarrior
Posts: 7804
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Breaking NES apart (WARNING: traffic)

Post by rainwarrior » Tue Aug 07, 2012 4:04 pm

Also one page up, he has a nice collection of layer and label images: http://www.qmtpro.com/~nes/chipimages/

User avatar
kyuusaku
Posts: 1665
Joined: Mon Sep 27, 2004 2:13 pm

Re: Breaking NES apart (WARNING: traffic)

Post by kyuusaku » Tue Aug 07, 2012 5:37 pm

I seriously need to work on my skills... How do you determine anything from the plain layered die photo? Is image processing being employed? (Or are you actually compositing the layers?)

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Re: Breaking NES apart (WARNING: traffic)

Post by org » Tue Aug 07, 2012 10:14 pm

rainwarrior, I've seen those layers and images but when I tried to compose them in photoshop, it doesn't look suitable. So I do by my own.

kyuusaku, search on youtube "Tracing 6502". I captured real-time video, while tracing 6502. This is quite simple :)

User avatar
kyuusaku
Posts: 1665
Joined: Mon Sep 27, 2004 2:13 pm

Re: Breaking NES apart (WARNING: traffic)

Post by kyuusaku » Wed Aug 08, 2012 12:48 am

Ahh, I thought you were working only from the die photo... Still impressive!

I took the easy way out and extracted the node and transistor list.

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Re: Breaking NES apart (WARNING: traffic)

Post by org » Wed Aug 08, 2012 5:27 am

Todays speccy: PPU OAM row decoder.

Image

Code: Select all

 1 2 3 4   abcdefghi
--------------------
 0 0 0 0 | 000000010 
 0 0 0 1 | 000000100
 0 0 1 0 | 000001000
 0 0 1 1 | 000010000
 0 1 0 0 | 000100000
 0 1 0 1 | 001000000
 0 1 1 0 | 010000000
 0 1 1 1 | 100000000
 1 x x x | 000000001
Input: row group number. Output selects one of 9 OAM row groups.

OAM layout (see attached pic):
Top part: 34 rows by 32 cells
Bottom part: 32 rows by 32 cells
Rows are aranged in groups, 9 groups total.
Number of rows in each group : 8, 8, 5, 8, 8, 8, 5, 8, 8
This gives 1792 + 320 = 2112 bits (264 bytes)
Attachments
OAM_overview.png

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Re: Breaking NES apart (WARNING: traffic)

Post by org » Thu Aug 09, 2012 5:50 am

Todays speccy: PPU data bus (D0...D7)

This is CPU-side data pin.

Each pin has 3 connects: RD, WR and DBn.

RD and WR controls read and write tri-state logic.
When RD is high write logic goes to "not connected" state and otherwise.
RD and WR cannot be in combinations 0/0. Both RD and WR are high, when /CE = 1 ("chip not enabled")

DBn wire transfers actual data in both directions.
Attachments
DATA_trans.png

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Re: Breaking NES apart (WARNING: traffic)

Post by org » Thu Aug 09, 2012 6:47 am

Bonus: PPU R/W decode logic

Image

Output RD and WR, based on R/W and /CE lines:

RD = ~R/W
WR = R/W

RD = WR = 1, when /CE = 1.

From Brad Taylor's "NTSC 2C02 technical reference":
R/W, D0-D7, A2-A0, /CS: these are the PPU's control bus signals responsible
for programming the 2C02's internal registers. R/W controls data direction
(write data into PPU reg on zero), A0-A2 selects the internal PPU register
to read/write, and while /CS is set to zero, D0-D7 is used to transfer the
data bits to/from the selected register (if /CS=1, D0-D7 float).
/CS is mentioned as /DBE (NOT data bus enabled) in PPU US patent 4824106.
Last edited by org on Fri Aug 10, 2012 6:42 am, edited 2 times in total.

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Re: Breaking NES apart (WARNING: traffic)

Post by org » Thu Aug 09, 2012 12:36 pm

APU reset pin

Simply inverted /RST input, no any latches or something.

RST is connected to NC/A address bus input. This mean address bus is float during reset.
Attachments
RST_trans.png

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Re: Breaking NES apart (WARNING: traffic)

Post by org » Fri Aug 10, 2012 6:05 am

Todays speccy: PPU register select PLA.

I partially decoded obscured area of register select PLA :

Image

As you can see diffusion layer is totally hidden under metall crosspassings.

I took original picture, maxed contrast and removed saturation:
Image

Noticed the difference between red and green circles? :mrgreen: Humain brain is a miracle :D

Although I didn't managed to recover top 3 lines of PLA, I still happy :) Now I can find PPU registers.

Image

PLA feeds A0-A3 and R/W lines and connect specific register with data bus (D0...D7), when condition met (actually it output "disconnect" drive signals, leaving only single register to be connected)
If condition is not met, then neither register is not connected to the data bus.

A0-A2 lines are mentioned as RS0-2 (register select) in PPU US patent 4824106.

Enjoy)

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Re: Breaking NES apart (WARNING: traffic)

Post by org » Sat Aug 11, 2012 8:05 am

Todays speccy: APU register decode

First take a look on oveview:
Image

Register address decode is done in 3 steps:
- predecode: determine whenever address is belongs to register memory area (4000 ... 401F)
- R/W decode: determine what we gonna do - read or write
- PLA: connects appropriate register with data bus

Predecode:
Image
It simply grounds output, if address is not "0x00 0000 000x xxxx" (where "x" mean any bit)
Two PDSEL outpus are identical to each other.
Ricoh missed two pullups here, so PDSEL is just "not connected", instead of high level, if address is match.

R/W decode:
Image
Feeds R/W line from CPU and PDSEL (which is grounded or just not-connected)
2 outputs goes to PLA.
Register write is performed when R/W is low and PDSEL is not connected.
Register read is performed when R/W is high and PDSEL is not connected.

PLA:
Image
Most interesting part.
This scheme has a lot of output control wires, which connect different registers with data bus.
Write PLA outputs are grounded during 6502 PHI1 phase.

I found undocumented registers : 4018, 4019 (both read only) and 401A (read/write).
Access to these registers is controlled by yet unkown (UNK) control line.

EDIT: UNK line is actually DEBUG input (pin 30). And 4018-401A are debug readback registers.

Some links from Quietust:
http://wiki.nesdev.com/w/index.php/Talk ... escription
http://wiki.nesdev.com/w/index.php/File:Apu_address.jpg
Last edited by org on Mon Aug 13, 2012 7:09 am, edited 1 time in total.

User avatar
org
Posts: 59
Joined: Tue Aug 07, 2012 12:27 pm

Re: Breaking NES apart (WARNING: traffic)

Post by org » Sun Aug 12, 2012 2:42 pm

Todays LSD trip: Master clock divider.

CLK input pin:
Image
Not sure if output is inverted or not :P I do not understand how does it work, when diffusion cross poly :?:
So I assume its not inverted.

6-stage Johnson counter:
Image Image

I placed two images: one for color and another is just trans-level.
You can find some artifacts on color schematics, I believe this is parts of PAL-version of 2A03.

Input CLK is divided by 12.
Additional duty compensation is need to make high level of PHI2 more wider. Without such compensation output PHI2 would be only 50% duty.

Also I wrote small program on C, to test Johnson counter:
[spoiler]

Code: Select all

// 2A03 master clock divider simulation.
#include <stdio.h>

int CounterOut;
int InLatch[6], OutLatch[6];
int DutyOut;

void step_count (int CLK)
{
    int i;
    CounterOut = OutLatch[5];
    for (i=0; i<6; i++) {
        if ((CLK & 1) == 0) InLatch[i] = CounterOut & 1;
        if ((CLK & 1) == 1) OutLatch[i] = ~InLatch[i] & 1;
        if ( i < 4) CounterOut = ~OutLatch[i] & ~(~OutLatch[5] & OutLatch[4]);
        else CounterOut = ~OutLatch[i];
    }
    CounterOut &= 1;
    DutyOut = ~InLatch[4] & 1;

    // Dump counter
#if 0
    printf ( "Counter (CLK: %i): ", CLK);
    for (i=0; i<6; i++) printf ( " %i", ~OutLatch[i] & 1 );
    printf ( "\n" );
#endif
}

main ()
{
    int i, CLK;

    // initial conditions
    CounterOut = 0;
    for (i=0; i<6; i++) InLatch[i] = OutLatch[i] = 0;

    // Display master CLK steps
    CLK = 0;
    printf ( "CLK : " );
    for (i=0; i<50; i++) {
        printf ("%i", CLK );
        CLK ^= 1;
    }
    printf ( "\n" );

    // Display iterations of PHI2 output
    CLK = 0;
    printf ( "PHI2: " );
    for (i=0; i<50; i++) {
        step_count (CLK);
        printf ("%i", ~(CounterOut & ~DutyOut) & 1 );
        CLK ^= 1;
    }
    printf ( "\n" );
}

CLK : 01010101010101010101010101010101010101010101010101
PHI2: 00000000111111111111111000000000111111111111111000
[/spoiler]

Admins: please allow to attach txt/c files, or add spoiler bb-code.

EDIT: found some errors, now fixed )

Post Reply