;****************************************************
;* 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
