The build, as it goes

Started 2026-09-30, the evening the flash chips reached the bench. The plan is calibration-plan.md (the part side of C0), the recipe is section 8 of build-the-cal-cart.md, and the blank boards are in cart-blanks.md. This page is the record of the build itself: what was done, in order, what each step said back, and what is still open. It grows as the build goes, and a step is marked held only when something was measured.

Where the build stands

stepwhat it provesstate
The programmer answersthe bench can write a chip at allheld 2026-09-30
Chip 1 identifies, and is blankthe part is an SST39SF040 and not a relabelled oneheld 2026-09-30
Chip 1 carries prg.binthe program image is on the part, wholeheld 2026-09-30
Chip 2 identifies, is blank, and carries chr.binthe tile image likewiseheld 2026-09-30
The first board: five bridges, three capacitors, two chipsa cart existsbuilt 2026-10-01; a gray screen in the console
Both chips read whole after the first boardthe gray screen is not the chipsheld 2026-10-01
The second boarda cart whose soldering is not in questionbuilt 2026-10-03, with sockets; the reader's dump below holds it
The console's lockout is defeateda cart with no lockout chip can run at allheld 2026-10-03: a cart with no lockout chip runs (the row below); the reset line itself is still unmeasured (lockout.md)
The reader's dumpwhat the console will see is cal.nes: body crc32 21091B99held 2026-10-03: the reader showed 21091B99, chip side to the reader's front, 5 V, mapper 0 with PRG 32 KB and CHR 8 KB set by hand (its "Not Found" is its database, which has no homebrew)
The cart in the consolethe strip reads off a grabbed frame (tools/cal.py grab)held 2026-10-03: six grabbed frames, twelve fields, every strip read (screens 2 to 7 in order, each field's counter one past the other's); the region scores are a first reading, not yet a verdict

The programmer is on the bench Pi, driven by minipro

The tutorial was written for the vendor's Windows program. What was used is minipro, on the Pi that already sits on the bench, because that is where the programmer's USB lead reaches and it keeps the burn a command that can be read back afterwards.

  • The programmer enumerates as a TL866II Plus (MEASURED 2026-09-30, off its USB descriptor), firmware 04.2.83. minipro expects 04.2.132 and says so on every run; it is a warning, and every read and write below went through on the older firmware.
  • minipro is 0.7.4, built on the Pi from gitlab.com/DavidGriffith/minipro. The repository of the same name on GitHub is an older tree (it calls itself 0.2-dev) that does not know this programmer or this chip; it builds, installs and then answers "Unknown device", which reads like a fault in the bench.
  • The device name is the bare SST39SF040. The names with a suffix are the PLCC and TSOP packages.
minipro -p SST39SF040 -D                 # the chip's ID; the part's is 0xBFB7
minipro -p SST39SF040 -b                 # blank check, the whole chip
minipro -p SST39SF040 -w prg.bin         # erase, write, verify
minipro -p SST39SF040 -r readback.bin    # then sha256sum it beside the image

minipro -t is the programmer's self-test and must be run with the socket empty: it drives the programming voltage onto the pins one at a time. It was run here with chip 1 seated, because its warning was lost in a pipe. The chip identified, erased, wrote and verified afterwards, so nothing shows for it, but that is luck and not a procedure.

The first chip: two wrong seatings, then the part's own ID

Seated the first time, every ID read tripped the programmer's overcurrent protection (four of four, MEASURED 2026-09-30), and the one blank check that got further read an ID of 0x0000. Reseated, the overcurrent was gone and the ID read 0xFFFF three times; a read of the whole chip returned 524,288 bytes of 0xFF. Reseated again, the ID read 0xBFB7 twice and the blank check passed over the whole chip.

Two things worth keeping from that:

  • A full read of 0xFF cannot tell a blank chip from an empty socket. Only the ID can, because the part answers the ID command whether or not it is blank. Read the ID first and believe nothing else until it is right.
  • Overcurrent on the ID read is a seating fault until proven otherwise. The chip that tripped it four times is the chip that now carries the program. What exactly was wrong with each seating was not recorded; the rule that ended it is the tutorial's: the chip in the 32 positions farthest from the lever, the notch toward the lever, the eight positions nearest the lever empty.

The first chip carries the program image

tools/nesprep.py roms/cal.nes wrote the two images, and their sha256 are the ones in the tutorial's table (checked before anything was written). Chip 1 was written with prg.bin: the programmer's own verify passed, a separate read of the whole chip hashed equal to the image (MEASURED 2026-09-30), and the ID read 0xBFB7 afterwards. It is the PRG chip and goes in U4.

Why the whole chip is compared and not the first 32 KiB: the image is tiled sixteen times to fill the part, so a short or relabelled die verifies in the low pages and fails only higher up.

The second chip carries the tile image

Chip 2 went in seated right the first time: ID 0xBFB7, blank over the whole chip, then chr.bin written, the programmer's verify passed, a separate read of the whole chip compared equal to the image byte for byte and hashed to the tutorial's figure, and the ID read 0xBFB7 afterwards (all MEASURED 2026-09-30). It is the CHR chip and goes in U3. Here the image is tiled sixty-four times, so the whole-chip comparison matters more than it did for the program.

Both chips are now what the tutorial's table says they should be. They are identical to look at, so each is marked before it leaves the programmer: PRG for U4, CHR for U3.

The board takes five solder bridges for NROM

the discrete mapper board, component side

The board is the v3.3 discrete mapper board. Its letters are on its own back, in a legend: A is AxROM, B is BNROM, U is UxROM (the three with CHR RAM), C is CNROM, G is GNROM, N is NROM (the three with CHR ROM). The calibration ROM is NROM, so every jumper whose label carries an N is made, and every one whose label does not is left open. READ OFF THE SILKSCREEN 2026-09-30; not yet proven on the part. What proves it is the reader's dump.

sidejumper, as labelledfor this cart
frontH, V (mirroring)middle pad to H
frontB/C/G/N/U (two pads)bridge
frontU against A/B/C G/N (three pads)middle pad to the A/B/C G/N side
frontBRIDGE IF 28-PIN (two pads inside U4's outline, starred)open: the chip has 32 pins
frontA (two pads, above CHR)open
frontG, G (four pads, above PRG)open
frontEXP0open
backC/G/N against A/B/U, two columns of three padsmiddle pad to the C/G/N side, on both columns
backC/G, A/B, U (two blocks of three two-pad jumpers)open, all six
backA/B against U (the block by the CHR rows)open
backA (two pads by pin 32)open
backR0 to R7leave the traces as they are

the mirroring jumper

The mirroring letters are backwards, and the board says so in words. cal.nes has vertical mirroring. The pad marked H has "VERTICAL Mirroring" printed beside it and the pad marked V has "HORIZONTAL Mirroring", and the board's guide admits it: "Solder the middle pad to either H (for vertical mirroring) or V (for horizontal mirroring). Yes, I know it's backwards". So it is H, by the words and not by the letter. The picture never scrolls and uses one nametable, so the wrong pad would show the same screens; the board and the file should agree anyway.

the jumpers beside the program ROM

the back of the board

the back's jumper blocks, top to bottom as in the table

The close-up runs down the back between the ROM rows: the A/B against U block, the two blocks of C/G, A/B and U, and at the bottom the one that matters here, C/G/N over A/B/U, whose two columns each get their middle pad joined to the upper one.

On the back, the resistor positions R0 to R7 carry a note: if sprites glitch, cut the middle traces and add 100 ohm resistors. That is a repair for a fault not yet seen, so nothing is cut.

The parts the board takes for this cart

From the board's guide (https://mousebitelabs.com/2020/09/11/nes-reproduction-quick-guide-custom-pcb/) and its silkscreen. The values are the guide's; none has been measured.

positionpartfor this cart
U4SST39SF040 carrying prg.binfit: chip 1
U3SST39SF040 carrying chr.binfit: chip 2
C1about 22 uF electrolytic, 10 V or more, polarised (the + is marked)fit
C3, C4about 0.1 uF ceramic, 10 V or more, one beside each ROMfit
C2about 0.1 uF ceramic, beside the lockout chip's positionfit, or leave with U2
U2the lockout chip (a CIC, or an ATtiny13 programmed as one)empty: the console's lockout is said to be defeated, and lockout.md is how that gets measured
U5, U6, U774'32, 74'161, 74'02empty: marked for UxROM, "all but NROM" and AxROM
C5, C6, C7their capacitorsempty with them

The capacitors are not in the pile photographed on the day; they come from stock. A pair of 32-pin sockets at U3 and U4 would let a chip go back to the programmer when the ROM is revised; whether a socketed chip clears the shell has not been checked.

The first board gave a gray screen, and it was not the chips

The first board was assembled on 2026-10-01 and went into the console bare, without a shell. Which way up a bare board goes: chip side up. In a front-loader the cartridge goes in label up, "pins 01-36 are the top side of the connector", and on an NES cartridge "most chips and components appear on the label side" (nesdev, Cartridge connector, read 2026-10-01). This board agrees with that: its edge is numbered 5 to 35 on the chip side and 40 to 70 on the back. A bare board has no shell to key it, so it fits upside down and a pin to either side, and pin 36 is +5 V with ground at 72 across from it.

Powered on, the screen was gray: steady, not blinking (the owner's report the next day).

Both chips then came off the board and back to the programmer. Each identified (0xBFB7), and each read back with no byte differing from its image: the one in U4 was prg.bin, the one in U3 was chr.bin (MEASURED 2026-10-01). So the chips were right, in the right positions, and unharmed by the board or the console. The program image's reset vector reads $8000 at the top of every one of its sixteen copies, which is where the console starts.

That leaves two things, and they are being taken separately:

  • The board. Its builder's verdict on the soldering was that it was poor, and a second board is being built. The two bridges beside the program ROM are the ones that would stop the program being read at all.
  • The console. This cart has no lockout chip, so it runs only on a console whose lock is out of the way, and that had been taken on trust. What the lock does to a keyless cart, how to tell by eye, and a measurement of the reset line are in lockout.md. A steady gray is not the lock's signature: a live lock blinks. This one was steady, so the lock is not what stopped the cart, and the board is.

The step the tutorial puts before the console was skipped here and should not be next time: the reader's dump reads the two halves separately and takes the console's connector out of the question.

The second board, in the order it is soldered

The two tables above, as one list to work down at the bench. Nothing here is new; it is the jumper table and the parts table in the order that makes the work easier, and the checks that come before a chip goes in.

partpositionnote
32-pin socket, then the PRG chipU4notch to the outline's notch
32-pin socket, then the CHR chipU3notch to the outline's notch
about 22 uF electrolytic, 10 V or moreC1long leg in the hole marked +
0.1 uF ceramicC3beside CHR
0.1 uF ceramicC4beside PRG
nothingU2, U5, U6, U7, C2, C5, C6, C7left empty

Five bridges are made:

sidejumper, as labelleddo
frontH, Vmiddle pad to H
frontB/C/G/N/Ujoin the two pads
frontU against A/B/C G/Nmiddle pad to the A/B/C G/N side
backC/G/N over A/B/U, left columnmiddle pad to the C/G/N pad
backC/G/N over A/B/U, right columnmiddle pad to the C/G/N pad

Left open: the starred BRIDGE IF 28-PIN pads inside U4's outline, the front A and G G pads, EXP0, and every other jumper block on the back. Nothing is cut; the R0 to R7 traces stay as they are.

The order:

  1. The five bridges first, while the board lies flat. Look at the starred pads inside U4's outline before going on: the socket covers them, and they have to be clean.
  2. The two ceramics.
  3. The sockets. Tack two diagonal corner pins, check the socket sits flush and its notch is the right way, then the rest.
  4. The electrolytic last, long leg to the +.
  5. Before a chip goes in, the meter. Pin 32 to pin 16 of each socket is +5 V to ground and must read open. Each of the five bridges reads closed, and on each three-pad jumper the side that was not made reads open.
  6. Chips in, PRG in U4 and CHR in U3, then the reader before the console.

On a three-pad jumper, flux both pads and use one small blob, kept away from the third pad. If a blob will not span the gap, a clipped piece of component lead laid across and soldered does.

The iron, as advice and not as anything measured here: a temperature-controlled iron of 60 to 70 W and not a soldering gun (the wattage is for holding temperature against this board's copper, not for running hotter); 320 to 350 C with leaded 63/37 rosin-core solder, 350 to 380 C with lead-free; a small chisel tip, about 1.6 to 2.4 mm, because a needle point passes heat poorly; solder of 0.6 to 0.8 mm; two to three seconds a joint, heating pad and pin together and feeding the solder into the joint.

The rest of the pile is for other builds

itemmarkingwhat it iswhere it belongs
Mapper 30 boardNES CART PCB (MAPPER 30) v1.2a flash and CHR RAM boardnot this cart (cart-blanks.md)
SxROM boardNES CART PCB (SxROM) v3.1an MMC1 game board with save RAMnot this cart (cart-blanks.md)
24-pin chipAX5904the part the SxROM board names at its mapper position, beside MMC1the SxROM board's U5
Black adapterTL866, mousebitelabs v3.2seats 40 and 42-pin EPROMs in the programmernot needed: a 32-pin chip sits in the programmer's own socket
Green adapterNES CARTRIDGE ROM ADAPTER, NES MASK ROMcarries a 27C or 39SF part into a mask ROM's position on an original boarda donor-board build, not this one
40-pin chipWDC W65C02S6TPG-14a CMOS 6502 processornot an NES part; a 65C02 computer's
40-pin chipWDC W65C22S6TPG-14a 65C22 interface adapter: two ports and two timersthe same computer's
28-pin chipCY62256NL-70PC32 KiB of static RAM, 70 nsthe CHR position of a CHR RAM board (both purple boards list 62256 there); not this cart, whose tiles are ROM
14-pin chipSN74LS00Nfour two-input NAND gatesnone of these boards: the discrete board takes '02, '161 and '32

a 65C22 above a 65C02

the static RAM and the NAND

the AX5904

the mask ROM adapter

The processor, the interface adapter, the RAM and the NAND are the usual set for a breadboard 65C02 computer (a reading of the pile, not something anyone said). The W65C02 is the CMOS part and not the NMOS 6502 whose die the simulator runs.

What is open

  • The lockout off the reset line: it is answered by eye, and tools/lockout-check.py would make it a record (lockout.md).
  • The second board: five bridges, the capacitors, the two chips.
  • The reader's dump of the finished cart, whose body crc32 must be 21091B99. It is also what proves the jumper table above.
  • The cart in the console, and the strip read off a grabbed frame.

Pulled at build time from nes-bench/docs/cal-cart-build.md; the repository is the one copy. The reports use some working words of their own: Words the reports use.