;**************************************************** ;* rob_gng4 - Ghost'n Goblins memory test ROM * ;* * ;* PURPOSE * ;* Replaces the game to hunt an intermittent memory * ;* fault. Burn to EPROM (code sits at $6000, the * ;* fixed ROM region), fit in place of the game ROM, * ;* power up. It loops forever; it never prints. * ;* * ;* ON FAILURE it parks on the failing address and * ;* hammers it endlessly, turning a rare glitch into * ;* a continuous bus signal a scope can follow to a * ;* physical chip. Y register marks the type: * ;* Y = $EEEE RAM verify failed * ;* Y = $EFEF ROM read was unstable * ;* * ;* BUILD * ;* Assemble with a09, Hermann Seib's free 6809 * ;* assembler (hermannseib.com): * ;* a09 -Brob_gng4.bin rob_gng4_comments.txt * ;* Output is the 186-byte binary, code $6000-$60B9. * ;* Add -Lrob_gng4.lst for a listing if wanted. * ;* Burn to EPROM with any programmer (a TL866 was * ;* used here), padding the rest of the chip with * ;* $FF and the code placed at the offset below. * ;* * ;* BURN AND BOOT * ;* The binary is 186 bytes, $6000-$60B9. It burns * ;* into the gg4 socket (10N), whose chip spans * ;* $4000-$7FFF: lower half is bank page 4, upper * ;* half serves $6000-$7FFF. On a 27128 the code * ;* sits at chip offset $2000; the rest of the chip * ;* is left erased ($FF). No other ROM is touched. * ;* * ;* Entry needs no patching anywhere: gg3 (the 32K * ;* ROM at $8000-$FFFF) stays in its socket and * ;* supplies the hardware vectors, and its RESET * ;* vector already points at $6000. Power-on flow: * ;* RESET -> $FFFE in gg3 -> $6000 -> this code. * ;* The first instruction after power-up is the * ;* ORCC below. Pass 4 then read-verifies gg3, the * ;* very chip that booted the test. * ;* * ;* MEMORY MAP UNDER TEST (6809 side) * ;* $0000-$1DFF work RAM * ;* $1E00-$1FFF sprite table (DMAd to B board) * ;* $2000-$27FF foreground video RAM * ;* $2800-$2FFF background video RAM * ;* $4000-$5FFF banked ROM window * ;* $6000-$FFFF fixed ROM (this test lives here) * ;**************************************************** ;**************************************************** ;* Program Code / Data Areas * ;**************************************************** ORG $6000 ; Mask IRQ and FIRQ (ORCC #$E0 sets E, F, I). From here on nothing ; else runs and every bus cycle belongs to this test. Again ORCC #$e0 ; ---- PASS 0: sweep the whole 64K address space. Read every byte and ; write the same value straight back. No verification here; this just ; exercises every address and data line once per lap. ;*** Read through RAM and ROM LDX #$0000 LDY #$ffff ReLoop LDA ,X STA ,X+ LEAY -$01,Y BNE ReLoop ; ---- PASS 1: work RAM $0000-$1DFF. Write $55 (01010101) to each byte ; and read it straight back. Any mismatch -> RAMErr with X just past ; the failing address and the pattern still in A. ;*** RAM Low LDX #$0000 LDY #$1e00 LDA #$55 Loop4 STA ,X CMPA ,X+ BNE RAMErr LEAY -$01,Y BNE Loop4 ; ---- PASS 2: sprite table $1E00-$1FFF, pattern $77. This is the CPU- ; side copy; the video board object RAM gets it by DMA and is NOT ; reachable from here. ;*** spriteram LDX #$1e00 LDY #$200 LDA #$77 Loop1 STA ,X CMPA ,X+ BNE RAMErr LEAY -$01,Y BNE Loop1 ; ---- PASS 3: banked ROM window $4000-$5FFF. ROM contents are not ; known here, so the test is stability: read a byte into B, park it at ; $2000 (scratch write, extra bus exercise), then read the same ROM ; byte again and compare. Two reads that disagree -> ROMErr. This ; catches flaky chips and bad sockets, not wrong burns. ;*** ROM Bank 1 LDX #$4000 LDY #$2000 Loop5 LDB ,X STB $2000 CMPB ,X+ BNE ROMErr LEAY -$01,Y BNE Loop5 ; ---- PASS 4: fixed ROM $6000-$FFFF, same double-read stability test. ; Note this range includes this very test ROM. ;*** ROM Bank Upper LDX #$6000 LDY #$a000 Loop6 LDB ,X STB $2000 CMPB ,X+ BNE ROMErr LEAY -$01,Y BNE Loop6 ; ---- PASS 5: foreground video RAM $2000-$27FF, pattern $F8, ; write-and-verify like the RAM passes. ;*** gng_fgvideoram_w, fgvideoram LDX #$2000 LDY #$800 LDA #$f8 Loop2 STA ,X CMPA ,X+ BNE RAMErr LEAY -$01,Y BNE Loop2 ; ---- PASS 6: background video RAM $2800-$2FFF, pattern $F8. ; Then jump back to Again and run the whole cycle forever. ;*** gng_bgvideoram_w, bgvideoram LDX #$2800 LDY #$800 LDA #$f8 Loop3 STA ,X CMPA ,X+ BNE RAMErr LEAY -$01,Y BNE Loop3 JMP Again ; ---- RAM FAILURE. A holds the pattern, X sits one past the bad byte. ; Y = $EEEE flags the failure type. Step X back onto the bad address ; and hammer it: five spaced writes, then one read-back compare. ; Still wrong -> loop again (LEAX -1 re-centres because CMPA ,X+ ; advanced X). Reads OK -> three more writes and loop anyway. ; Net effect: an endless, tight write/read pattern at one known ; address. Probe the RAM selects and the culprit chip is the one ; that fires. RAMErr LDY #$EEEE LEAX -$01,X STA ,X NOP NOP STA ,X NOP NOP STA ,X NOP NOP STA ,X NOP NOP STA ,X NOP NOP CMPA ,X+ BNE RAMErr STA ,X STA ,X STA ,X NOP NOP NOP NOP BRA RAMErr ; ---- ROM FAILURE. Y = $EFEF flags it. Endless reads at the point of ; instability; put the scope on the ROM /CE lines and look. ROMErr LDY #$EFEF LDA ,X BRA ROMErr END