;----------------------------------- ; Space Invaders Test ROM ; ; Documented and transfered to TASM ; By Timothy Shiels ; www.outerworldarcade.com ;----------------------------------- ; 01/21/2022 Cleaned up formatting ; 08/xx/2008 Converted code for TASM, Cleaned up documentation ; 11/16/2007 Documented code ; 05/xx/2001 EPROM Dumped by Paul Sommers .org 0000h ;-------- ; Set-up ;-------- nop ; do nothing nop ; do nothing nop ; do nothing xra a out $03 ;---------------- ; First RAM test ;---------------- .MODULE ramtest1 mvi c,$03 ; We'll do the ram tests three times - keep track in c ;---------------------------------------- ; Store #$55 in all memory $2000 - $4000 ;---------------------------------------- ramtest1 mvi b,$55 lxi h,$2000 _loop mov m,b inx h mov a,h cpi $40 jnz _loop ;--------------------------------------- ; Check each stored value $2000 - $4000 ;--------------------------------------- lxi h,$2000 _loop2 mov a,m xra b jnz badram ; jump to $0190 if not what we expect inx h mov a,h cpi $40 jnz _loop2 ;--------------------------------------- ; Store #$AA in all memory $2000 - $4000 ;--------------------------------------- mvi b,$aa lxi h,$2000 _loop3 mov m,b inx h mov a,h cpi $40 jnz _loop3 ;--------------------------------------- ; Check each stored value $2000 - $4000 ;--------------------------------------- lxi h,$2000 _loop4 mov a,m xra b jnz badram ; jump to $0190 if not what we expect inx h mov a,h cpi $40 jnz _loop4 dcr c jnz ramtest1 ; start again if not done with 3 tests ;----------------------------------------------- ; Second RAM test ; fill memory with incremental values $00 - $FF ;----------------------------------------------- .MODULE ramtest2 ramtest2 lxi h,$2000 mvi b,$00 _loop1 mov a,b mov m,a inx h inr b mov a,b cpi $ff jnz _skip1 mvi b,$00 ;start back at $00 _skip1 mov a,h cpi $40 jnz _loop1 ;----------------- ; Verify each one ;----------------- lxi h,$2000 mvi b,$00 _loop2 mov a,m xra b jnz badram ; jump to $190 if not what we were expecting inr b mov a,b cpi $ff jnz _skip2 mvi b,$00 _skip2 inx h mov a,h cpi $40 jnz _loop2 ;---------------------------------- ; RAM tests GOOD ; Draw Port and Sounds Test Screen ;---------------------------------- .MODULE drawscrn drawscrn lxi sp,$2400 ; set stack pointer to $2400 call clrscrn ; Clear Screen -> Zero out memory $2400 - $4000 lxi d,txtOK ; Load DE with the staring address of the character string "OK ALL RAMS" lxi h,$2501 ; print ">OK ALL RAMS" call print lxi h,$2701 ; print ">CHECK INPORT" call print lxi h,$3301 ; print ">CHECK SOUND" call print lxi h,$2a07 mvi c,$0f lxi d,txtPort push d call print2 ; print "PORT 1 01234567" pop d lxi h,$2e07 mvi c,$0f call print2 ; print "PORT 1 01234567" (will be port 2) mvi a,$1d lxi h,$2e0b call drawchar ; print "2" FOR PORT2 ; PRINT 11 SOUNDS LABELS mvi b,$0b ; b=$0b (11 times) lxi h,$340e ; screen location lxi d,txtSound ; text string location _sndloop mvi c,$06 push b call print2 ; draw it on the screen lxi b,$00fa dad b pop b dcr b jnz _sndloop mvi b,$02 sndloop push b lxi h,$340d ; load HL with location on screen to draw "0" next to sound played shld $2000 ; store screen location in $2000 ;--------------------------- ; Sound Test ; Port 3 ; A = (01) 21 = UFO.F Sound ; A = (02) 22 = MISSL Sound ; A = (04) 24 = LAU.H Sound ; A = (08) 28 = INV.H Sound ; A = (10) 30 = EXTRA Sound ;---------------------------- .MODULE sndloop1 sndloop1 mvi a,$01 ; A = sound to play _loopz push psw ori $20 out $03 ; play the sound call drawO ; draw "O" and update port info for awhile mvi a,$20 out $03 ; quit playing the sound call clearO ; clear "O" and update port info for awhile pop psw rlc cpi $20 jnz _loopz ;--------------------------- ; Sound Test ; Port 5 ; A = 01 = Invader 1 Sound ; A = 02 = Invader 2 Sound ; A = 04 = Invader 3 Sound ; A = 08 = Invader 4 Sound ; A = 10 = UFO.H Sound ; A = 20 = VID.R Sound ;---------------------------- .MODULE sndloop2 sndloop2 mvi a,$01 ; A = sound to play _loop push psw out $05 ; play the sound call drawO ; draw "O" and update port info for awhile xra a out $05 ; quit playing the sound call clearO ; clear "O" and update port info for awhile pop psw rlc cpi $40 jnz _loop pop b dcr b jnz sndloop ; no more sounds - just update port info forever _udports call drawports ; update the port info jmp _udports ; do it again forever drawO lhld $2000 ; load HL with screen loaction to draw "O" mvi a,$0f ; load A with character "O" call drawchar ; draw the "O" jmp portsmain clearO call portsmain lhld $2000 ; load HL with screen loaction to draw " " (clearing the "O") mvi a,$28 ; load A with character " " call drawchar ; draw the " " shld $2000 ; save HL in $2000 ret .MODULE portsmain portsmain mvi a,$60 ;counter do this 96 ($60) times. Pause?? _loop call portstat ;draw status of ports to screen and output A to Port 6 dcr a jnz _loop ret ;------------------------------ ; Draw current status of ports ;------------------------------ .MODULE drawports drawports push psw lxi h,$2b0e ;screen location of port 1 in $01 ;load A with info on port 1 call drawbin ;draw it on screen lxi h,$2f0e ;screen location of port 2 in $02 ;load A with info on port 2 call drawbin ;draw it on screen pop psw ;restore af ret ;--------------------------------- ; Draw binary *'s for what's in A ;--------------------------------- .MODULE drawbin drawbin mvi b,$08 _loop push b push h rrc push psw mvi a,$28 ;" " (blank) jc _skip mvi a,$25 ;"*" _skip call drawchar ;draw "*" or " " to screen pop psw pop h inx h pop b dcr b ;decrement counter jnz _loop ;if not at end of eight cycles do it again ret ;------------------------------------- ; Draw a text string to screen ; INPUTS: ; C = number of characters to draw ; HL = screen location memory address ; DE = location of text characters ;------------------------------------- .MODULE print print mvi c,$0d ;number of characters to draw print2 ldax d ;load A with character number from address in DE push d ;save DE push h ;save HL call drawchar ;draw character pop h ;restore HL (screen location memory address) inx h ;increment it by 1 pop d ;restore DE (location of text character to draw) inx d ;increment it by 1 dcr c ;decrement number of characters left to draw jnz print2 ;done? ret ;-------------------------------- ; Draw a character to the screen ;-------------------------------- .MODULE drawchar drawchar lxi d,$0200 ;character images start at $200 push h ;save memory location to draw to mov l,a mvi h,$00 dad h ;calcuate memory address of data for character to draw dad h dad h dad d xchg ;transfer memory address to DE pop h ;restore memory location to draw to mvi b,$08 _loop push b ldax d mov m,a inx d lxi b,$0020 dad b pop b dcr b jnz _loop ret ;----------------------------------------------- ; Clear Screen -> Zero out memory $2400 - $4000 ;----------------------------------------------- .MODULE clrscrn clrscrn lxi h,$2400 _loop mvi m,$00 inx h mov a,h cpi $40 jnz _loop ret ;--------------- ; Bad RAM found ;--------------- .MODULE badram badram mvi b,$01 ;B = counter for where error exists in byte _loop rrc ;rotate byte right jc _skip ;did we find an "ON" bit? inr b ;NO- increment counter jmp _loop ;try again _skip mov a,l ;YES- load L into A lxi h,charnum ;starting address for images of number error codes rrc jnc _num ;if bad memory location address is even number stay with numbers lxi h,charbad-8 ;starting address for images of letter error codes _num mov a,b ;load result from counter where error exists rlc rlc rlc mov b,a mov e,b mvi d,$00 dad d xchg ;DE= character location pointer mvi b,$08 ;B= 8 lines lxi h,$3011 ;HL = location to draw to the screen _draw ldax d ;load A with a byte of character image mov m,a ;draw a line of error code image to screen mov a,b ;save B lxi b,$0020 ;next screen location is +$20 dad b ;add +$20 to HL mov b,a ;restore B inx d ;increment character location pointer dcr b jnz _draw ;continue to next line if B isn't zero mvi b,$08 ;B=8 lines lxi h,$3012 ;HL = location to draw to the screen lxi d,$0340 ;DE = location of " " character to draw out $06 jmp _draw ;keep drawing blank character forever portstat call drawports ;draw current state of ports out $06 ret .FILL ($200-$1d4) ;------------------ ; Character Images ;------------------ charset .byte $00, $70, $88, $A8, $E8, $68, $08, $F0 ;"@" ($00) .byte $00, $20, $50, $88, $88, $F8, $88, $88 ;"A" ($01) .byte $00, $78, $88, $88, $78, $88, $88, $78 ;"B" ($02) .byte $00, $70, $88, $08, $08, $08, $88, $70 ;"C" ($03) .byte $00, $78, $88, $88, $88, $88, $88, $78 ;"D" ($04) .byte $00, $F8, $08, $08, $78, $08, $08, $F8 ;"E" ($05) .byte $00, $F8, $08, $08, $78, $08, $08, $08 ;"F" ($06) .byte $00, $F0, $08, $08, $08, $C8, $88, $F0 ;"G" ($07) .byte $00, $88, $88, $88, $F8, $88, $88, $88 ;"H" ($08) .byte $00, $70, $20, $20, $20, $20, $20, $70 ;"I" ($09) .byte $00, $80, $80, $80, $80, $80, $88, $70 ;"J" ($0a) .byte $00, $88, $48, $28, $18, $28, $48, $88 ;"K" ($0b) .byte $00, $08, $08, $08, $08, $08, $08, $F8 ;"L" ($0c) .byte $00, $88, $D8, $A8, $A8, $88, $88, $88 ;"M" ($0d) .byte $00, $88, $88, $98, $A8, $C8, $88, $88 ;"N" ($0e) .byte $00, $70, $88, $88, $88, $88, $88, $70 ;"O" ($0f) .byte $00, $78, $88, $88, $78, $08, $08, $08 ;"P" ($10) .byte $00, $70, $88, $88, $88, $A8, $48, $B0 ;"Q" ($11) .byte $00, $78, $88, $88, $78, $28, $48, $88 ;"R" ($12) .byte $00, $70, $88, $08, $70, $80, $88, $70 ;"S" ($13) .byte $00, $F8, $20, $20, $20, $20, $20, $20 ;"T" ($14) .byte $00, $88, $88, $88, $88, $88, $88, $70 ;"U" ($15) .byte $00, $88, $88, $88, $88, $88, $50, $20 ;"V" ($16) .byte $00, $88, $88, $88, $A8, $A8, $D8, $88 ;"W" ($17) .byte $00, $88, $88, $50, $20, $50, $88, $88 ;"X" ($18) .byte $00, $88, $88, $50, $20, $20, $20, $20 ;"Y" ($19) .byte $00, $F8, $80, $40, $20, $10, $08, $F8 ;"Z" ($1a) charnum .byte $00, $70, $88, $C8, $A8, $98, $88, $70 ;"0" ($1b) .byte $00, $20, $30, $20, $20, $20, $20, $70 ;"1" ($1c) .byte $00, $70, $88, $80, $60, $10, $08, $F8 ;"2" ($1d) .byte $00, $F8, $80, $40, $60, $80, $88, $70 ;"3" ($1e) .byte $00, $40, $60, $50, $48, $F8, $40, $40 ;"4" ($1f) .byte $00, $F8, $08, $78, $80, $80, $88, $70 ;"5" ($20) .byte $00, $E0, $10, $08, $78, $88, $88, $70 ;"6" ($21) .byte $00, $F8, $80, $40, $20, $10, $10, $10 ;"7" ($22) .byte $00, $70, $88, $88, $70, $88, $88, $70 ;"8" ($23) .byte $00, $70, $88, $88, $F0, $80, $40, $38 ;"9" ($24) .byte $00, $20, $A8, $70, $20, $70, $A8, $20 ;"*" ($25) .byte $00, $10, $20, $40, $80, $40, $20, $10 ;">" ($26) .byte $00, $00, $00, $00, $00, $00, $00, $20 ;"." ($27) .byte $00, $00, $00, $00, $00, $00, $00, $00 ;" " ($28) ;-------------- ; Text Strings ;-------------- txtOK .byte $26, $0F, $0B, $28, $01, $0C, $0C, $28 ; ">OK ALL RAMS " .byte $12, $01, $0D, $13, $28 .byte $26, $03, $08, $05, $03, $0b, $28, $09 ; ">CHECK INPORT" .byte $0E, $10, $0F, $12, $14 .byte $26, $03, $08, $05, $03, $0B, $28, $13 ; ">CHECK SOUND " .byte $0F, $15, $0E, $04, $28 txtPort .byte $10, $0F, $12, $14, $1C, $28, $28, $1B ; "PORT1 01234567" .byte $1C, $1D, $1E, $1F, $20, $21, $22 txtSound .byte $25, $15, $06, $0F, $27, $06 ; "*UFO.F" .byte $25, $0D, $09, $13, $13, $0C ; "*MISSL" .byte $25, $0C, $01, $15, $27, $08 ; "*LAU.H" .byte $25, $09, $0E, $16, $27, $08 ; "*INV.H" .byte $25, $05, $18, $14, $12, $01 ; "*EXTRA" .byte $25, $09, $0E, $16, $27, $1C ; "*INV.1" .byte $25, $09, $0E, $16, $27, $1D ; "*INV.2" .byte $25, $09, $0E, $16, $27, $1E ; "*INV.3" .byte $25, $09, $0E, $16, $27, $1F ; "*INV.4" .byte $25, $15, $06, $0F, $27, $08 ; "*UFO.H" .byte $25, $16, $09, $04, $27, $12 ; "*VID.R" ;------------------------------------------ ; Character Images Used By Bad RAM Routine ;------------------------------------------ charbad .byte $20, $50, $88, $88, $F8, $88, $88, $00 ;"A" .byte $78, $88, $88, $78, $88, $88, $78, $00 ;"B" .byte $70, $88, $08, $08, $08, $88, $70, $00 ;"C" .byte $70, $90, $90, $90, $90, $90, $70, $00 ;"D" .byte $E0, $20, $20, $E0, $20, $20, $E0, $00 ;"E" .byte $3E, $02, $02, $1E, $02, $02, $02, $00 ;"F" .byte $3C, $02, $02, $02, $32, $22, $3C, $00 ;"G" .byte $22, $22, $22, $3E, $22, $22, $22, $00 ;"H" #if ($ >= 800h) ; generate an invalid statement to cause an error ; when we go over the 2K boundary. !!! ROM bounds exceeded #endif .org $07FF .byte 0 .end