; Xflash Williams System 9 and 11 CPU board Test Program
; Edward Cheung - ed@edcheung.com

; Typical Assemble command c:\Progra~1\a68\a68 xflash.asm -l xflash.lst -o xflash.hex
;   Build on pinball laptop, use System_11 = 0
;   With Hex Editor or S4 replicate 0-3FFF and paste to 4000-7FFF
;   Burn into 27256 ROM.  Will work for both System 9 and 11.
;   When this ROM is inserted into System9, the upper address bit will have no effect,
;   and the same program will be read.
; For a System 9, ROM is at 0xC000 to 0xFFFF (16 kB / 27128)  
;  PIA addresses are at: 2100,2400,2800 (led and input), 3000.
; For a System 11, it is at 0x8000 to 0xFFFF (32 kB / 27256)
;  Additional PIAs at 2C00, 3400
; For System 3-7, Boot ROM U17 is at 0x7800 to 0x7FFF.
;  PIAs at 0x2100, 0x2200, 0x2400, 0x2800, 0x3000, 0x4000.
;  Replicate binary to 4kbytes and program with 2532 adapter as 2732.

; 3/16/21 - created System 11 configuration
; 3/18/21 - PIA tests working
; 3/19/21 - RAM test working.  Confirmed by checking one location past RAM
; 3/20/21 - Converted to System 9.  Implemented better addressing.  
;             The only hard addresses are ORG statements.  
;             Added switches to handle both 9 and 11.
; 3/21/21 - 1.0 - version compatible with both 9 and 11.  
;             Build code for System 9 (16k image) and 
;             duplicate to fill 32k.  This will run on both System 9 and 11.
; 3/24/21 - 1.1 - Added compatibility with System 9&11 sound section.
;11/25/22 - 1.2 - Expanded RAM check section from 2 to 10 passes.  
;                 Inverted CA2, CB2 to cause flipper relay to click
;11/01/24 - 1.3 - Accomodate 0x800 size ROMs for System 3-7.
;                 RAM check not working (yet).  Once built, convert to binary with
;             HEX2BIN and use Hex Editor to replicate for full 2732 size.
;             Can use 2532 with DIP adapter.  Program as 2732.
;11/5/24  - 1.4 - RAM check on Sys37 goes to 0x100.   Does not check battery backed RAM. 

SYSTEM_37  SET 1

		IF	SYSTEM_37 	; Setup location of ROM in CPU address space
ROM_OFFSET SET $7800
		ELSE
ROM_OFFSET SET $C000
		ENDI

HEADER	ORG $0	
		FCC "XFlash v1.4 edcheung.com - Nov 2024"

; Inits go here
INIT	ORG	$100		;@D000 to CPU
		JMP MAIN+ROM_OFFSET

; Top of main.  Cycle through PIAs and toggle outputs
MAIN	ORG	$200		;@E000 to CPU
PIA_DEL SET $6000	; C000 ~ half second delay

PIA_DTA	SET $2000
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2100
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port, CB2 low
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2200
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port, CB2 low
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2400
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2800
		LDA A PIA_DTA+1	; A <- CRA for CA1
		TST A
		BMI SKIP_28	; Branch if MSbit set
		LDA A PIA_DTA+3	; A <- CRB for CB1
		TST A
		BMI SKIP_28	; Branch if MSbit set

		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
SKIP_28		NOP

PIA_DTA	SET $3000
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2C00
		LDA A PIA_DTA+1	; A <- CRA for CA1
		TST A
		BMI SKIP_2C	; Branch if MSbit set
		LDA A PIA_DTA+3	; A <- CRB for CB1
		TST A
		BMI SKIP_2C	; Branch if MSbit set

		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
SKIP_2C		NOP

PIA_DTA	SET $3400
		LDA A PIA_DTA+1	; A <- CRA for CA1
		TST A
		BMI SKIP_34	; Branch if MSbit set
		LDA A PIA_DTA+3	; A <- CRB for CB1
		TST A
		BMI SKIP_34	; Branch if MSbit set

		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
SKIP_34		NOP

PIA_DTA	SET $4000
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port, CB2 low
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

		LDX #$0000	; Half of delay
LOOP1		INX
		CPX #PIA_DEL
		BNE LOOP1

PIA_DTA	SET $2000
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $2100
		LDA A #$3C	; access Data Register, CB2 high
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2200
		LDA A #$3C	; access Data Register, CB2 high
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2400
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $2800
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $2C00
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $3000
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $3400
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $4000
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

		LDX #$0000	; Half delay
LOOP2		INX
		CPX #PIA_DEL
		BNE LOOP2
		JMP MAIN+ROM_OFFSET

; Interrupt on pushbutton to check RAM
RAM_CHECK	ORG $500	;
;Starting with 0x00, last one checked is -1
		IF	SYSTEM_37
RAM_ADR SET $100;
		ELSE
RAM_ADR SET $800
		ENDI

RAM_DAT	SET $55	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP1	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP1	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP2	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP2	; Loop back to next check

RAM_DAT	SET $AA	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP3	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP3	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP4	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP4	; Loop back to next check
		
RAM_DAT	SET $03	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP5	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP5	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP6	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP6	; Loop back to next check

RAM_DAT	SET $0F	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP7	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP7	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP8	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP8	; Loop back to next check

RAM_DAT	SET $3F	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP9	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP9	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP10	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP10	; Loop back to next check

		JMP MAIN+ROM_OFFSET

RAM_BAD		NOP
		LDA A #$00	; All outputs low to light LED2
		STA A $2800	;   2800 <- 0xFF (literal)
		JMP HALT+ROM_OFFSET	; Halt

HALT	ORG	$700		;@F800 to CPU
		JMP HALT+ROM_OFFSET	;Infinite loop to Halt

; Set up Vectors
		IF	SYSTEM_37 	; If System 37
		ORG $7F8
		ELSE
		ORG $3FF8
		ENDI
		FDB INIT+ROM_OFFSET		; Periodic Int: IRQ Vector (not used)
		FDB INIT+ROM_OFFSET		; SW int (not used)
		FDB RAM_CHECK+ROM_OFFSET; Push button: NMI Interrupt
		FDB INIT+ROM_OFFSET		; Power Up: RESET Interrupt
		END
