Skip to content
GuimliPublic

About

A diagnostic BIOS ROM for SEGA Naomi /Naomi 2 arcade boards: per-component testing (CPU, all RAM, EEPROMs, cartridge...) with simultaneous serial, video, and voice reporting.

Resources

Stars

16 stars

Watchers

4 watching

Forks

Latest commit

 

History

180 Commits

Folders and files

Repository files navigation

NaomiDiag

Work in progress. Some functions have not been tested on real hardware yet. But I am working on it as fast as I can :-)

A replacement diagnostic BIOS ROM for the SEGA Naomi and Naomi 2 arcade boards. It replaces the stock BIOS in the IC27 socket and tests the board's components one by one, reporting results on up to three channels — serial (SCIF), on-screen (VGA) and spoken audio — without ever relying on memory it has not yet proven good.

It has been used to repair a board: the ROM named IC10, replacing IC10 alone cleared the fault.

Available in English and French, text and voice both localized. Pre-built ROMs ready to burn are on the Releases page — direct downloads: NaomiDIAG_EN.bin · NaomiDIAG_FR.bin.

Français : voir README.fr.md.

A run, with a fault

Finding a dead data line on CPU RAM

Data line D5 held low across part of the CPU RAM, under MAME. The cell test fails, and the ROM names the chip: D5 is in the low half of the 64-bit word, so it belongs to the even-word pair — IC9, never the odd pair. The flashing border is the heartbeat, which pulses for as long as the ROM is alive.

The full run is on the release page: NaomiDIAG_EN_IC9_fault.mp4 — 95 seconds, every test, with the sound, so you can hear the fault announced as well as read it. GitHub will not play a video that lives in a repository (it strips the <video> tag), hence the silent GIF above and the download for the real thing.

Three simultaneous output channels

Every test result is reported at the same time on every channel that is currently available — serial, then serial + audio, then serial + audio + video — so the operator can watch, listen, or capture the log, whichever is convenient. As each result is produced it is printed on the SCIF, spoken aloud, and drawn on the VGA report screen together.

The order in which the channels come up follows what each one needs:

  • SCIF serial is the only output fully internal to the SH-4 CPU: it works from reset with no external RAM at all, so it is the primary and always-available channel.
  • Audio needs the sound RAM (behind the AICA) and video needs the VRAM (behind the PowerVR); the small area of each that its channel uses is checked first, and each channel switches on only once its own area has passed. The full tests of those memories come later. When audio comes up it first replays every result acquired so far, then reports live.

Because sound and video are brought up before the long main-RAM test, the machine never looks frozen during that ~1-minute test — the screen already shows the earlier results and the SCIF prints per-pass progress.

Spoken reports are blocking, with at least one second of silence between two messages so clips never overlap.

The clips are stored as 4-bit Yamaha ADPCM and handed to the AICA in that form (PCMS=2), which decodes it in hardware. That is a straight 4:1 saving on the EPROM with no decompressor, no scratch buffer and no CPU cost — the bytes are copied into sound RAM exactly as they sit in the ROM. The full French build went from 98 % of the EPROM to 29 %; with the clips added since (Naomi 2 chips, JVS board, data-line reports) a full build sits at about 50 %.

What it tests

The boot suite runs on its own, in this order. The screen and the speaker come up long before the memories they live in are fully tested: each channel is brought up on the small region it actually uses, so results are reported as they land.

  1. SH-4 core — the operand cache is configured as on-chip RAM and self-tested; this is also the stack/.bss for the whole ROM (no external RAM used until proven).

  2. Screen and speaker bring-up — a quick check of the VRAM area the framebuffer uses and of the sound RAM area the clips play from. Each channel switches on only if its own area passes; the speaker then replays every result acquired so far. The framebuffer lives in TEX0; if that area fails, the same area of TEX1 — the other four chips, 8 MB further in the same window — is checked and, if sound, carries the screen instead (VRAM framebuffer TEX1 (fallback)). The heartbeat border is unaffected either way: its colour is a PowerVR register, not VRAM.

  3. Board identification — Naomi 1 vs Naomi 2 by the Elan chip's ID (E1AD0000 on a Naomi 2, confirmed on a real board). On a Naomi 1 that read lands in an unpopulated area and is assumed to return open bus; CFG_BOARD_MODEL=1 avoids it, =2 selects a known Naomi 2 — see PVR_B_ACCESS.md.

  4. Test-loop relocation — the memory-test loops are copied into an 8 KB block of CPU RAM, tested first, and run from there cached (see Where the test loops execute).

  5. G1 bus unlock — Holly keeps the bus to the cartridge or DIMM closed after reset (every read 0xFFFF, writes dropped) until a key is written to 0x5F74E4 and a known stretch of the boot ROM is read through it: an integrity check of the BIOS, the Dreamcast's GD-ROM lock, still in the Naomi. The retail BIOS keys 0x1FFFFF and checks all its 2 MB, which a different ROM cannot pass; the Naomi development BIOS keys 0x3FF and checks only its bytes at 0x100–0x4FF. NaomiDIAG keeps that kilobyte free and does the development BIOS's read. The kilobyte is SEGA's and is not in this repository: build with DEVBOOT=path/to/develop.ic27 (from MAME's naomi set, develop.ic27 or develop110.ic27) and tools/inject_devboot.py copies it from your own dump into your local image and fixes the CRC. Without it the boot log says so and the cartridge and DIMM tests find the bus closed on real hardware (MAME does not model the check, which is why they always worked there). Never publish an image built with DEVBOOT.

  6. BIOS EPROM (IC27) — CRC32 self-check. It runs right after the relocation so that its loop, too, executes cached from CPU RAM: only the 2 MB of data still cross the EPROM bus. Without a proven block it runs from the EPROM as before.

  7. Maple bus / MIE (315-6146 Z80) — version request + factory self-test.

  8. Settings EEPROM (93C46 via MIE) — read and both CRC-checked copies verified. Needs a Z80 program uploaded into the MIE first (src/mie_prog.z80), which then stays resident and also serves the board's buttons and DIP switches (both reported on the serial console).

  9. JVS I/O board — the same program is a JVS master: it resets the bus, gives the board address 1, and reports its identification, revisions and inputs (players, switches, coin slots, analog channels). No board answering is reported as not present, not as a fault.

    Steps 6-8 run here, before the memory tests, on the block qualified at step 5, so the buttons can interrupt the long part of the suite. On a board where no block qualifies they wait for the CPU RAM test and are skipped if it fails.

  10. Main CPU RAM (SDRAM, 16/32 MB, IC9/IC10/IC11S/IC12S) — first a data-bus walking-ones test and an address-bus test, then three phases, each reported as pass n/3 and each driving the progress bar from 0 to 100%:

  • 1/3 — write 0x55555555 (0101…) over the whole region, then read it all back and compare;
  • 2/3 — write 0xAAAAAAAA (1010…) over the whole region, then read back and compare;
  • 3/3 — write a pseudo-random stream, then read it back and compare word by word. With CFG_RAM_CRC=1 a CRC32 kept in a CPU register is also accumulated on both sides and compared (see Building).

A fault is reported per chip, and a failed test means the summary calls main RAM unusable. If all CPU RAM is bad, the program keeps running from the SH-4 cache (OC-RAM) and completes every test that does not need main RAM. 11. VRAM — 16 MB in eight 16 Mbit chips around the graphics chip, tested through the 32-bit window as two 8 MB regions, TEX0 (IC16/18/20/22) and TEX1 (IC17S/19S/21S/23S), with the same bus tests and three phases. Inside a region a chip is a 4 MiB half and a 16-bit data half (see TEX and PVR-A/B diagnostics). 12. Naomi 2 only — PVR-B VRAM (16 MB, IC111 to IC118S) once its windows are shown independent of PVR-A, and the Elan RAM (32 MB, IC106/107/108S/109S); see below. 13. Sound ARM7 and sound RAM (AICA IC33, RAM IC35, 8 MB). The SH-4 reaches this RAM only across G2, one FIFO-paced access at a time — eight minutes for the 8 MB. The AICA's ARM7 sits on the RAM's own bus, so it is used the way the CPU RAM's relocated loops are: the SH-4 tests a 16 KB window, loads arm/aica_arm_test.S there and releases the ARM7 from reset. The ARM checks itself on that window only (general and banked registers, ALU and multiplier, byte and word access, a timed loop) and then runs the three patterns over the rest of the RAM, reporting failures (count, data lines, first addresses) through a mailbox. Result lines: Sound ARM7 (AICA IC33) and the usual sound RAM cell test. If the window is bad or the ARM7 does not start, stops or fails its self-test, the SH-4 runs the cell test itself as before. 14. Backup NVRAM (IC29) — non-destructive save/restore test. 15. RTC (inside the AICA, IC33) — non-destructive: the counter must advance by a plausible amount over 2.2 s. A failure is measured again, so the report tells a stopped clock (still twice) from an irregular one (still, then moving) and from an implausible read (a jump or a step backwards); the serial console prints every raw read. Its date is a separate check: before 2026 it cannot be today's — a flat battery, or a clock never set — and it gets its own line (RTC date (2026 or later)). 16. Serial-number EEPROM (IC31, 93C46 on SH-4 GPIO) — read + content check. 17. Relocated code integrity — the relocated loops ran from the very RAM under test, so they are read back and compared with the ROM copy. On screen only when it fails; serial always.

The operator actions are on the operator menu (see Operator menu): they either write to something or take long enough that they have no business delaying the report.

  • RAM loops (c, v, s) — the CPU, video or sound RAM test, pass after pass, for intermittent faults. The screen shows the pass, the time running and the errors so far, and for each memory OK or FAIL with the pass of its first error and the failing chips; it stays there, so a fault seen once overnight is still on screen in the morning. The first failure of each memory is also spoken. The video loop moves the image to the other bank (TEX0 ↔ TEX1) while it tests the one it sits in. TEST or START stops the loop (key a on the console when the MIE program is not running). The sound RAM loop runs through the AICA's ARM7 as the boot suite does, the SH-4 taking over for any pass where the ARM path is not usable. The CPU RAM loop stops below the 8 KB block the relocated code runs from.
  • Console keys — the serial log shows a framed reminder that a cancels the running tests and h prints the help: as soon as the board's buttons answer (with the blue hint on screen), and in any case just before the long memory tests, MIE or not. Keys are case-insensitive (caps lock does no harm).
  • Exception report — a CPU exception halts with its cause and address on screen, spoken, and on serial with r0-r15, SPC, SSR, PR and TEA (the faulting address). When TEA is a word of the code right around the faulting instruction -- the EPROM handed back a neighbouring word, which is what a faulty cartridge disturbing the G1 bus it shares with the EPROM does -- the report says Suspect cartridge: remove it.
  • Serial monitor (! on the console, from the menu or the idle screen) — r b|w|l ADDR [N] reads, w b|w|l ADDR VAL writes any address (P2 alias for registers, e.g. A05F703C), u [BITS] runs the G1 unlock in parts (bit 0 G1RRC = 0x700, bit 1 the 0x5F74E4 key, bit 2 2 MB read through P2, bit 3 the BIOS's P1 read), x the X76F100 response-to-reset, d the DIMM probe, q returns. It lets a hardware question be put to a real board without burning an EPROM per guess; a wild address ends in the CPU exception report.
  • DIMM board (d) — register dump and read stability, then the destructive SDRAM test over the G1 DMA; f identifies the DIMM's firmware flash (see DIMM board).
  • JVS input test (j) — every input of the I/O board, live.
  • Video test pattern (m) — colour bars, crosshatch, grey scale, per-component ramps, purity fields and a one-pixel checkerboard, for the monitor and the video output stage.
  • Cartridge (g):
    • Security chip (X76F100) — presence via response-to-reset.
    • Content — identifies the game against an embedded database of every known Naomi/Naomi 2 cartridge (192 games plus one alternative dump, 2318 ICs) and verifies each ROM chip by SHA-1, reporting the failing IC by its silkscreen name. Identification streams the first chip and snapshots the SHA-1 at each known first-ROM size, so a cart is named without hashing all of it. Chips are hashed raw, decryption not applied, so the digests are the ones in the MAME dumps. A cart that matches nothing is reported as unknown content rather than as faulty — it may simply be a dump this database does not carry — and the data-line test below still runs, because a dead line is one reason a known cart fails to match. The SHA-1 rounds are written in SH-4 assembly (about 31 instructions per byte, cartridge read included) and read the cartridge port directly; they run cached from CPU RAM with the relocated memory-test loops. Without a proven CPU RAM block the content check is skipped and the serial log says so: from the EPROM it would take about 9 s per MB, 20 minutes for a typical game (132 MB) and over an hour for the largest (512 MB). The screen then shows Cart SHA1 (CPU RAM bad) NOT TESTED in amber and the speech says "Game cartridge, content not checked, main memory, defective". The security chip and data-line tests still run. Chips are named after the MAME file names, whose extension is the silkscreen position (mpr-23083.ic31 → IC31); ic8.bin gives IC8, a bare .18 gives IC18, and the Namco-developed carts keep their PCB grid position (maz1ma1.4m → 4M). A chip MAME maps twice is hashed once, and an alternative dump (F355 Challenge 2's _alt IC22) is a second known content for that chip. The Namco-built boards leave socket 2F empty on several games (Mazan, Ninja Assault, World Kicks): address 0 reads 0xFF and the header is in 2D, at 0x800000. The cartridge is then found, identified, hashed and its data lines sampled from there. On screen, the identified game gets a line of its own, followed by every chip of the game, four per row (IC22 OK IC1 BAD IC2 ABS …): OK in green, BAD (wrong content) and ABS (silent, or mirroring another chip) in red, -- for a chip present but not hashed (QUICK builds). The cartridge is read by G1 DMA, double-buffered: the next 8 KB arrives in one buffer while the rounds hash the previous 8 KB from the other, so the bus and the CPU work at the same time. The DMA path is trusted only after 8 KB fetched by DMA match the same 8 KB read through the port; a transfer that never completes switches to the port, and a chip found bad (or a cart found unknown) through the DMA is read again through the port before any verdict. The log gives the time of 8 KB both ways. Not yet validated on real hardware (MAME models neither speed).
    • ROM set completeness — once the game is identified, the whole set of chips that game needs is checked: every mask ROM in the database entry is probed and the result is stated affirmatively (ROM set: 13 / 13 chips present). A chip answering a constant 0xFFFF/0x0000 everywhere is reported as not responding (missing, unseated, dead) rather than as bad content, and a chip returning the same bytes as another one is flagged as an address-aliasing mirror — an empty socket that a neighbouring chip answers for. Presence is checked on every chip even on QUICK builds; only hashing is trimmed.
    • Data lines — per-pin statistics over the 16-bit cartridge bus: the share of 1s each line reads (a line that never toggles is stuck), plus a comparison of two reads of the same addresses — any bit that differs is an unstable line, the signature of a tired bus transceiver or a dirty edge connector. This runs even when the game cannot be identified, since a dead line is precisely what prevents identification.

RAM faults are reported per component: a bit mask, the affected data lanes, and the silkscreen IC designator (e.g. CPU RAM 1 (IC9) DEFECTIVE). VRAM and Elan RAM chips are named as a suspect lane (chip or connections). On screen the failing chips sit in red on the failure's own line, just before FAIL (SDRAM cell test IC9 IC12S FAIL); a label too long to leave them room drops its parenthesis.

A CPU RAM fault is also checked for a cut data line. Each failing bit is probed on 64 addresses spread over the tested region, on the word parity it failed on: all written, then a decoy of the opposite polarity so a floating line cannot simply hold the last value driven, then all read back, with the bit at 0 and at 1. Wrong on 60 or more is a line, not a cell, and it gets its own line on screen and in speech — Line D5 cut on IC9 DQ5, "Line D, five, cut on, I C nine, D Q, five" — with how it reads on serial (always 0, always 1, or floating). The line is named twice: first as the SH-4's 64-bit bus carries it (an even word is D0-D31, an odd word D32-D63), then as the chip's own data pin, DQ0-DQ15, the one to probe on the package.

Address lines are walked chip by chip on every memory: a step counts only when a whole 16-bit lane of some cell reads back the value written at the other address — two addresses landing on one cell — so a data fault is not taken for an address line. On the CPU RAM the walk also covers the odd 32-bit word, which the classic address test never touches, and the CPU bit is named as the SDRAM pin it travels on, from the SH-4's multiplexing table (Renesas SH7750 hardware manual, appendix F: table 9 for 32 MB, table 13 for 16 MB). One pin carries a column bit and a row bit:

CPU byte-address bit SDRAM pin (32 MB) SH-4 pin
3-10 A0-A7, column A3-A10
11-20 A0-A9, row A3-A12
21, 22 A10, A11, row A13, A14
23, 24 BA0, BA1, bank A15, A16

Address lines are common to the four chips: Address A5 cut on IC10 ("Address line A, five, cut on, I C ten") points at that chip's pin, Address BA0 cut, all 4 chips at the shared trace or the SH-4. The serial console adds the SH-4 pin and the CPU bits behind the SDRAM pin. VRAM, Elan RAM and sound RAM sit behind controllers whose multiplexing is not documented, so for them the report names the CPU bit and the chips it touched: Address bit 12 faulty on IC21. A chip that aliases on many bits at once is left to the data and cell tests: that is a dead chip or lane, not cut address lines.

The progress bar retires after the Naomi 2 memories: from there on nothing is being measured — the NVRAM, the RTC and the serial EEPROM answer yes or no — and the rows it occupied go to the report instead.

Time left

The top right corner of the screen counts down to the end of the boot suite, and the serial console prints the estimate once the plan is known. Each step has a duration taken from the serial log of a real Naomi 2 running v0.16 with every test working (the "after" log of PR #3), spoken results included; only the case without CPU RAM for the loops is extrapolated:

Step Loops relocated No CPU RAM for the loops
Screen + speaker bring-up 0:29 0:29
Board identification 0:04 0:04
Loop relocation 0:37 0:31 (up to 128 blocks scanned from ROM)
BIOS CRC 0:01 (measured: 1.06 s) 0:04
MIE, settings EEPROM, JVS 0:19 skipped
CPU RAM 0:52 12:39
VRAM TEX0 + TEX1 0:53 6:25
Naomi 2: PVR-B + Elan RAM 1:31 19:00
Sound RAM 8:22 8:22 (never relocated)
NVRAM, RTC, serial EEPROM, end 0:29 0:29
Naomi 1 total 12:06 29:04
Naomi 2 total 13:37 48:04
  • That run took 13:42. The Naomi 1 total is the same run without the PVR-B and Elan RAM. TEX1 is measured slower than TEX0 there, 8.9 s against 4.1 s per pass.
  • Without a CPU RAM block the loops run from the boot EPROM. The quick VRAM check always does: 3 passes over 600 KB in 14.5 s, 7.9 s per megabyte-pass, about 14 times the cached rate. Instruction fetch then dominates, so that rate is applied to every memory the loops test.
  • The count corrects itself as it goes: inside a memory step it follows the passes' progress, the measured duration of the quick VRAM check rescales the ROM case, and the CPU RAM test rescales the later memory steps. Without audio, the speech time is left out.

Where the test loops execute

The SH-4 boots in P2, an address window the hardware never caches, so every instruction is a bus cycle to the boot EPROM. Linking the whole ROM for P1 (the cached alias of the boot area) was tried on real hardware and the board refuses it outright -- black screen before the first visible instruction -- which matches the original BIOS, that never executes cached from ROM either.

Cached execution from SDRAM is a different matter: it is where every Naomi game runs. So the memory-test loops and the failure scan -- about 500 bytes, where essentially all the time goes -- are copied into an 8 KB block of CPU RAM at boot and run from there, cached, while everything else stays in ROM.

The four CPU RAM chips are interleaved by data lane rather than by address range -- IC9/IC10 carry the even words, IC11S/IC12S the odd ones -- so every block spans all four. Blocks are scanned downward from the top and the first sound one is taken, which gives immunity to a localized fault (a bad row or column inside one chip) but not to a chip dead across its range: in that case no block passes and the ROM copies keep being used. A block that fails the scan is reported as the broken memory it is, not quietly skipped.

A chip dead across its whole range is decided in thirty-two accesses by the data bus test, before any block is scanned: all 128 would fail for the same reason, and a megabyte of futile testing from the EPROM would delay the one thing the operator needs to know. Whatever happens, the report names the window the loops really execute from -- 8Cxxxxxx/8Dxxxxxx for cached CPU RAM, A0xxxxxx for the boot EPROM -- read back from the pointer that will actually be called rather than from a flag.

The window is tested with the full pattern and pseudo-random suite before anything is copied into it, and the memory under test is still addressed through P2, so the data path stays uncached and the test keeps its coverage. If no usable RAM is found the pointers keep addressing the ROM copies and the diagnostic runs slowly rather than not at all -- which is exactly the board that needs diagnosing. Build with RELOC=0 to disable it entirely.

TEX and PVR-A/B diagnostics

VRAM failures use the EPR-23608C BIOS lane mapping: the 4 MiB half and D0–D15 / D16–D31, rather than word parity. Tables, disassembly evidence, limits and pinouts are consolidated in ADDRESS_MAP.md (in French). A named IC identifies a suspect lane: chip, connections or controller, not proof of an internal RAM failure.

Interpreting failures

  • The data mask is expected XOR observed. 00000200 identifies D9; 00000300 identifies D8 and D9. At A5C00000–A5FFFFFC, the BIOS assigns these bits to IC21. Real-board tests with DQ9 and DQ8/DQ9 disconnected reproduced these errors. The supplied pinout assigns DQ8 to pin 39 and DQ9 to pin 40; it does not itself prove CPU-to-DQ wiring.
  • The address-test mask identifies failed steps, not defective address pins. Data faults can produce 007FFFFC. A single-address data-bus test can pass while cells elsewhere in the region fail.
  • After a data- or address-bus failure, additional diagnosis checks isolated cells (alternating patterns, walking ones and zeros, two reads), then address pairs in two write orders, two polarities and two repetitions. Samples cover the start, end and power-of-two offsets; they do not replace a full memory test.
  • VRAM readback failure preserves reads and rereads of both cells. A zero initial XOR can therefore accompany a reread failure. VRAM coupling candidate requires isolated cells to pass and then reproduce the other cell's pattern in all eight trials. Reported address bits are CPU byte-address bits, not physical A0–A11 pins. A zero coupling mask means that these trials confirmed no coupling.

The first 32 diagnostic events are printed; counters and masks include later ones. Full passes retain eight failure details but continue counting and mapping subsequent failures. A mismatch that cannot be located again leaves multiple IC candidates across the tested range. A clean sample does not cancel an earlier intermittent failure.

Rescanning after 90%

The fast verify passes only tell whether something differed. When it did, a rescan of the region locates the failing words; it prints “Error detected, locating VRAM failures” (or CPU RAM failures) with its own progress and checks abort input every 1024 words.

The rescan is hand-written assembly and lives in the relocated block, so it runs cached from CPU RAM when a block was qualified, from the EPROM otherwise. It records the first eight failing words in full, for the detail lines; after that it stops only on a word that brings a data bit not yet seen in its 4 MiB half and on its word parity — possibly another chip — and merely counts the others. The error total and the chips named stay exact.

This matters for a cut data line, which fails every word of its half. On a real Naomi 2 with DQ9 cut on IC21, the former rescan — C from ROM, every bad word recorded — took about 3 min 20 s per failing pass, and TEX1 took 7 minutes instead of 17 seconds. The rescan now costs about one more read of the region: a few seconds cached, well under a minute from ROM.

PVR-B access and the Elan RAM

Before PVR-B is written, access qualification checks that the A and B windows are independent. Each sampled cell is first written and read back alone; the bits that fail there are that cell's own fault and are left out of the comparison that follows, where all four cells hold distinct values and a change can only come from a write to another window. A cut data line on one chip — the DQ9 case above — therefore no longer blocks the PVR-B and Elan tests: it is reported by the RAM test of its own region. A mirror or a broadcast still is (code 4), and so is a cell too broken to judge (code 5 on A, 6 on B). Untested means neither healthy nor defective.

The Elan RAM is the Elan's own memory, not a window onto either GPU, so it is tested whatever PVR-B's qualification says, unless the Elan itself does not answer. Its chips follow the BIOS POLY table: even and odd 32-bit words of the lower 16 MiB are IC106 and IC107, of the upper 16 MiB IC108S and IC109S — see ADDRESS_MAP.md. The v loop covers PVR-B and the Elan RAM on a Naomi 2, under the same conditions. See PVR_B_ACCESS.md for the sequence and all access codes.

Maple / MIE communication on real hardware

Maple DMA buffers live in a validated CPU RAM block, usually near the top of 32 MiB. MDAPRO protection is computed from both buffers using inclusive 1 MiB bounds. The old 0x6155404F constant covered only the first 16 MiB, leaving high-RAM buffers outside the allowed range and potentially causing a false "MIE not responding" result. The libnaomi driver uses the same bounds encoding. MAME ignores this protection register, so emulator success does not validate it on hardware.

Failed detection prints one trace per port: desc, rx, mdapro (the programmed value), mdst, the response header and isterr_before / isterr_after. The latter are raw snapshots that may contain old or unrelated errors; the diagnostic does not clear them. The status field distinguishes:

Status Meaning
invalid-request Invalid buffer address, alignment or request size
busy-timeout Previous transfer still active; buffers were not reused
dma-timeout New transfer still active after 100 ms
rx-unchanged DMA finished but the receive sentinel was untouched
no-response Response header indicates no response
invalid-version-reply Received a reply that is not a valid MIE version

A communication failure does not by itself identify a defective MIE. Host tests (sh tools/test_maple.sh) check DMA bounds, high RAM, deadlines, timer wraparound and invalid replies.

Validated on a working Naomi 2 PCB using the filter board TEST/SERVICE buttons: MIE communication, self-test, Z80 program upload and serial-menu navigation all worked on real hardware. The observed identification before uploading the Z80 program was (spacing preserved):

MIE on maple port 0, resp cmd 0x00000083
MIE version: "315-6149    COPYRIGHT SEGA E"

The self-test status was 00000000, followed by a successful program upload. The input report showed raw port 000000FB, DIP SW1 set to 31 kHz / OFF / ON / OFF, and both TEST and SERVICE released.

0x83 answers the 0x82 version request; 00000000 indicates a successful self-test. This is the string displayed by our response reader, not a required identity or proof of the chip's physical marking. The reader displays the first response frame and does not assemble any continuation of the version text. DIP and button states describe this particular run, not mandatory values for a healthy board. This validates filter-board buttons, not the controls of an external JVS I/O board.

Operator menu

The menu lists all eight actions on both VGA and the serial console. Each serial entry includes its direct key (c, v, s, d, g, f, j, m); > marks the current selection. TEST prints the list again with the next selection, and SERVICE runs it. Navigation needs neither a VGA monitor nor ANSI support.

While the suite runs, as soon as the MIE program reads the buttons, a blue line a blank line above the progress label says which ones stop it: TEST or START: stop and operator menu. It gives way when the report reaches its line.

Once the suite is over, the last line of the screen — where the progress bar was — says how to get there, white on blue: TEST or START: operator menu (the board's TEST, PSW1, or the cabinet's player 1 START; the board's SERVICE, PSW2, and the cabinet's TEST work too).

The boot suite is not the end of it. a or a menu key on the serial port, a board button (TEST or SERVICE), or the cabinet's TEST or player 1 START once the JVS board has answered, stops the suite: the test running at the time stops at its next block and draws no verdict from the part it did — its phases end in interrupted, not ok — and the suite does not resume. a goes to the report, a button opens the operator menu, and a menu key (c, v, s, d, g, f, j, m) runs that action straight away. h prints the help without interrupting anything; other keys are ignored.

The buttons need a small Z80 program uploaded into the MIE first — the 315-6146's factory firmware answers four Maple commands and reading the buttons is not one of them. The upload happens right after the test loops are relocated, before the memory tests, as soon as a block of CPU RAM has been qualified to hold the Maple DMA buffers; the program then stays resident. So the buttons can interrupt the long part of the suite. On a board with no usable block the MIE stage falls back to its old place, after the CPU RAM test. The cabinet's TEST and player 1 START, read from the JVS I/O board, act as the board's TEST and SERVICE once the board has answered.

The JVS master lives in the same Z80 program. It drives the MIE's 16550-style UART at 115200 baud (divisor 8, the original BIOS's own set-up), switches the RS-485 driver around each frame as that program does, and polls the I/O board by itself between Maple packets, one byte at a time, so a Maple request is always answered at once. The SH-4 only reads the result, 28 bytes per request.

Keys on the serial console:

Key Action
h help — the only key that never interrupts
a abort the current test and go to the report
c / v / s loop the CPU / video / sound RAM test
d full DIMM SDRAM test
g game flash SHA-1 integrity
f DIMM firmware flash — identify, and choose a version
j JVS input test — every switch, coin count and analog channel, live
m video test pattern

On screen, the operator menu lists the same actions: TEST (or the cabinet's TEST) steps through them and wraps; SERVICE (or player 1 START) runs the selection. The three RAM loops run until a button is pressed and nothing else stops them — that is the point, since an intermittent fault shows up on the tenth pass, not the first. The one exception: when the buttons are unavailable (the MIE never answered the uploaded program), a stops a loop too, or it could only be stopped by a reset. The video loop covers TEX0 and TEX1, plus PVR-B and the Elan RAM on a Naomi 2, and every loop names a failing chip the way the boot suite does.

The DIMM, cartridge and flash actions each start a report of its own, print it, and wait for TEST or SERVICE to bring the operator menu back.

The video test pattern shows ten full-screen images in turn: colour bars, a crosshatch for geometry and convergence, a 16-step grey scale, red, green, blue and white ramps (a stuck DAC bit shows as banding), white, red, green, blue and black fields for purity, and a one-pixel checkerboard for bandwidth. TEST or any serial key shows the next one; SERVICE, START, a or q leaves. The border stops pulsing while they are up. The output is the ROM's own 640x480 at 31 kHz, so a 15 kHz monitor shows nothing.

The JVS input test shows each input the I/O board declared: the system switches (TEST, TILT1-3), each player's START, SERVICE, four directions and buttons, lit while pressed; coin counters; analog channels in hex; and the raw switch bytes for a board whose layout differs. The serial console prints a line whenever a switch or a coin count changes. TEST is one of the inputs under test, the cabinet's and the board's alike (a BOARD TEST line shows the latter), so only the board's SERVICE or a serial key leaves.

Two of these are operator-initiated precisely because they are not safe to run unattended: the DIMM SDRAM test overwrites whatever game is loaded in the DIMM (not the firmware, which runs from its own RAM), and the flash action touches the DIMM's firmware flash — read-only for now, see below.

Building

Toolchain: Debian gcc-sh-elf / binutils-sh-elf.

make LANG=EN            # -> NaomiDIAG_EN.bin (English text + voice)
make LANG=FR            # -> NaomiDIAG_FR.bin (French text + voice)
make LANG=EN QUICK=1    # 1 MB per RAM pass, for fast emulator bring-up
make LANG=EN BAUD=115200  # serial console at 115200 instead of 57600

src/config.h holds the options that are a decision about the ROM rather than a per-build variation. The Makefile carries what changes from one build to the next — LANG, QUICK, RELOC, BAUD, ROM_BASE; the header carries what is edited once and stays. Anything in it can still be overridden without touching the file:

make LANG=EN CFLAGS_EXTRA=-DCFG_LANE_BEACON=1

CFG_RAM_CRC (off by default) restores the CRC32 comparison in the RAM cell tests. The specification asked for it, it is implemented and it works — but it is provably redundant and expensive. Redundant, because the same loop already compares every word against the value it should hold: if no word differed, the two byte streams are identical and their CRCs cannot differ. Expensive, because a CRC-32 costs 20 instructions per 32-bit word and there are two of them — 40 of the 59 instructions in the read-back loop, against 3 for the word comparison that does the actual detecting. With it off the loop is 17 instructions per word, about three times faster, and the test loses no ability to find or locate a fault.

CFG_LANE_BEACON (off by default) enables the lane beacon: after the report it cycles through the twelve 16-bit slices of the CPU RAM and VRAM buses, naming one at a time and hammering it so a scope on the chips shows which package carries which lane. It is a bench instrument for establishing the lane-to-designator map, not part of diagnosing a board — it never ends, so the report stays up but the machine never settles. Turn it on when you have a probe in hand.

AUDIO=0 builds a silent ROM: the spoken-clip table is replaced by a stub and the image drops to 6 % of the EPROM. It was introduced when the clips were 16-bit PCM and left no room for anything else; since they became ADPCM a full build sits at about 50 %, so this is no longer a way of making room — it is for a bench where the speech is in the way, and it boots a little faster. AUDIO=1 is the default.

make LANG=EN AUDIO=0

Note that the shell often exports LANG=fr_FR.UTF-8, which overrides the Makefile's LANG ?= EN. Always pass LANG= explicitly on every make, including make mame-rom, or a target will rebuild with different flags.

A 2 MB image is produced, ready to burn on a 27C160 EPROM (IC27). The build refuses to produce an image larger than 2 MB (no silent truncation).

The same 27C160 image works on both Naomi 1 and Naomi 2 (both use a 2 MB BIOS); the board is detected at runtime.

Regenerating generated sources (rarely needed, committed in the repo):

make audio     # re-render the spoken clips (needs the Piper venv + sox)
               # TTS -> 22050 Hz mono -> ADPCM (tools/adpcm.py)
make cartdb    # rebuild the cartridge SHA-1 DB from `mame -listxml`
make mieprog   # rebuild src/mie_prog.h from the Z80 source (z80asm)

Testing under MAME

make LANG=EN QUICK=1 mame-rom
mame naomi -rompath ../roms_diag -autoboot_script mame/scif_tap.lua

The MAME scripts all live in mame/. scif_tap.lua captures the SH-4 SCIF transmit FIFO and prints the serial console (MAME does not wire the SCIF to anything). The *_fault*.lua scripts inject RAM faults for negative testing. Note: main RAM is fastram under the DRC, so fault injection into it needs -nodrc.

MAME (0.288) does not emulate the Naomi 2's own hardware: its naomi2 has one PowerVR, mirrors the PVR-B window onto PVR-A, reads 0 at the Elan ID and has no Elan RAM, so the ROM sees a Naomi 1 there. mame/elan_id.lua fakes the Elan ID so the Naomi 2 path can be exercised: it ends, correctly, in an access refusal (code 4, the mirror) and a failing Elan RAM. The JVS master can be tested: MAME's naomi carries an emulated 837-13551 I/O board.

Real hardware notes

  • Burn NaomiDIAG_xx.bin on a 27C160 (IC27); for a 27C322, make 27c322 writes NaomiDIAG_xx_27C322.bin, the 2 MB image twice. Serial output is on the SCIF pins at 3.3 V logic — use a 3.3 V USB-serial adapter, never RS-232 levels. For where to connect it on the board, refer to the JinGasa project: it exists solely to talk to a Naomi over the serial port and documents the wiring, which is more than can be said for the pinouts circulating elsewhere.

  • Set the terminal to 57600 baud, 8N1, no flow control. The ROM says so itself in its first lines, once the console is up.

    With the SH-4's 50 MHz peripheral clock, the rate is Pck/(32*(SCBRR+1)). The ROM uses SCBRR2 = 26, giving approximately 57870 baud, 0.47 % above 57600, confirmed on a Naomi 2 with a USB serial adapter. make BAUD=115200 builds the former setting instead: SCBRR2 = 13, 111607 baud, 3.1 % below 115200 — inside UART tolerance, with less margin.

  • A failed cache test means the SH-4 itself is dead: it is reported on SCIF and the ROM halts.

  • A CPU exception is reported and the ROM halts, on every channel that is up and in this order: serial first (cause code EXPEVT and the faulting address — it needs no stack, so it comes out even when the stack is what broke), then a red line on the screen, then the words "CPU exception" on the speaker. The border turns solid red: the machine has stopped. Only an exception in the very first instructions, before the vector table is installed, restarts the ROM instead.

  • The DIMM-board fan is monitored only by the DIMM firmware.

Status and limitations

  • The IC designators were read off a board and are listed in docs/ADDRESS_MAP.md. An earlier version derived them from the order the original BIOS RAM TEST prints its numbers, which was wrong three times over — including having the CPU RAM and GPU RAM groups the wrong way round — so nothing rests on that inference any more.
  • VRAM lanes now follow the EPR-23608C BIOS calculation documented in ADDRESS_MAP.md. Physical wiring and address pins still need verification. The S suffix denotes the PCB underside.
  • For WORK, IC10 on D16–D31 of the even word was validated by repair. IC9, IC11S and IC12S still follow the inferred lane order without individual measurements; the lane beacon can verify them.
  • Every RAM chip the ROM can name has its own spoken clip, Naomi 2 chips included (TEX1, PVR-B, Elan RAM), and the S suffix is spoken: a fault on IC11S is heard as "I C eleven S". The voice is Piper text-to-speech, so the screen and the serial console remain authoritative.
  • The Naomi 2 paths — board identification by the Elan ID, the Elan's initialisation, the PVR-B access check, the PVR-B and Elan RAM tests — are covered by host-side tests but have run on no real Naomi 2 yet, and MAME cannot run them. The Elan ID read on a Naomi 1 has not been tried on a real board either; CFG_BOARD_MODEL=1 removes it.
  • The JVS master has been checked against MAME's emulated 837-13551 I/O board. MAME does not model the UART's timing or the RS-485 direction, so those follow the original BIOS's program and still need a real cabinet. Only one I/O board is addressed (address 1); a daisy chain is not enumerated.

DIMM board

The mailbox protocol between the Naomi and a DIMM board is not publicly documented. What has been recovered from the board's own firmware is written up in docs/DIMM_FIRMWARE.md: the load base, the mailbox window as the DIMM sees it, the response format, the command dispatcher, and the two VxWorks message queues behind it.

The short version is that the mailbox itself offers a diagnostic ROM nothing — no identity, no version, no memory test, no reflash. The only three commands it accepts from the Naomi are a doorbell for a BSD socket proxy, and one of them is a no-op.

What does work goes around it, on the G1 bus:

  • d — DIMM SDRAM test. It begins by standing in for the BIOS on the DIMM's own requests: the DIMM firmware reads and writes the BIOS's work area in Naomi RAM through the mailbox (PEEK/POKE) and waits for a first message from the BIOS before doing anything. NaomiDIAG sends it, answers every request as a BIOS in test mode would (which keeps the DIMM from loading a game), and learns the DIMM's firmware version and memory size from what it posts — "DIMM: firmware 4.03, 512 MB". The session then runs until the next reset, answered from every loop of the ROM. It waits for the DIMM's loader to settle (it may be checking the game it holds) before writing anything. The DIMM firmware resets the Naomi when its loader starts, and again when a network-mode board finds no valid game: the report and the test's state are sealed in CPU RAM first, and the boot that follows such a reset skips the base suite, brings back the screen, the board identification and the MIE program (so the buttons work), puts the report back with a "Resumed after a DIMM reset" line and carries on. At most three resumes in a row, then a normal boot. Holly's GD-DMA has a direction bit, and the sources disagree on it: the DIMM reversing had 0 = read, while the original BIOS loads cartridges with SB_GDDIR = 1. The count register (0x5F7014) is in 8-byte units in one, 32-byte units in the other. So the action first probes the board, without leaving a trace: 1 KB of the game image (1 MB in, or the first of a few places holding real data) is read twice through the PIO port as a reference, then each SB_GDDIR value is tried on a buffer holding a pattern — the buffer becoming the reference is a read, the DIMM becoming the pattern is a write, undone at once with the reference and checked. Then both count units are tried on a read, and 32 KB are timed. The serial log gives every outcome; the screen gives "G1 DMA read GDDIR=n" and "G1 DMA write GDDIR=n". Only with both directions established, and after SERVICE/START (TEST skips), does the destructive memory test run over the whole DIMM (0x55555555, 0xAAAAAAAA, then address-in-data with the whole span written before it is read back, CRC-32, one-second DMA timeout) — it overwrites the loaded game. The question gives the size and the expected time. The DIMM's top 16 MB, its working area, are copied into CPU RAM first (checked against a second read), tested with the rest and put back (checked by reading them back); a game header in "no CRC" mode is broken so the DIMM reloads instead of booting what the test left. Without a CPU RAM the suite has proven, the top 16 MB are left out. With no size from the DIMM, it is found by aliasing. If none of that answers, the BIOS's first message is sent anyway and a request from the DIMM firmware within 3 s counts as presence (on an empty bus the message is simply lost). Presence is decided by writing two patterns into the mailbox's OFFSETL/PARAMETERL latches and reading them back: a DIMM's mailbox reads 0xFFFF in every register after reset, exactly like an empty bus. Not validated on real hardware yet; under MAME (a GD-ROM game with NaomiDIAG staged as naomigd.zip's epr-21576h, -bios bios2) the board is found and the probe reads, but MAME ignores the direction bit and cannot show a write. MAME's full DIMM emulation (its debug-only "Full emulation" setting) does not talk to any BIOS, so the PEEK/POKE session is not testable there either; the resume after a reset is, with mame/dimm_resume.lua, which stands a soft reset in for the DIMM's.
  • f — DIMM firmware flash. The flash is reachable through the G1 ROM-board PIO with AMD commands. The ROM performs a read-ID, which is non-destructive, and offers a 3.17 / 4.01 / 4.03 selection. The screen shows the flash's maker and ID (or "DIMM board: not present" / "DIMM flash (no answer)"), then the versions and "Cancel": TEST moves, SERVICE or START picks, as in the operator menu; keys 1/2/3 still work on the console. The choice ends on an amber "Flash write (not armed yet)". Writing is deliberately not armed. Sega's own updater was decompiled and it does a single chip-erase followed by a full-image reprogram — so the board's two-slot recovery net survives a successful flash but not an interrupted one. That waits on hardware validation, not on more reading.

The supporting analysis of SEGA's firmware images stays out of this repository on purpose.

Credits

Bootstrapped from the JinGasa minimal Naomi BIOS project. Register-level details cross-checked against MAME and libnaomi. Spoken clips generated with Piper.

About

A diagnostic BIOS ROM for SEGA Naomi /Naomi 2 arcade boards: per-component testing (CPU, all RAM, EEPROMs, cartridge...) with simultaneous serial, video, and voice reporting.

Resources

Stars

16 stars

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages