10 REM > RAMTest/s
   20 REM Based on www.willegal.net/appleii/6502mem.htm translation of
   30 REM Carl Moser's 6502 RAM test in Issue 1 Compute, 1979.
   40 :
   50 REM Destructively tests almost all 6502 RAM
   60 REM Run on I/O, tests &0E00-&7FFF
   70 REM Run on Tube, tests &0500-&F7FF
   80 REM On error, prints pp aaaa bb tt
   90 REM pp=pass, aaaa=address, bb=byte from ram, tt=test byte
  100 :
  110 REM On completion, language memory zeroed and language re-entered
  120 :
  130 OSRDCH=&FFE0:OSNEWL=&FFE7:OSWRCH=&FFEE:OSBYTE=&FFF4
  140 DIM mcode% &180
  150 :
  160 start=&80:end=&82:addr=&84
  170 test=&86:pass=&87
  180 :
  190 FOR P=0 TO 1
  200   P%=&400:O%=mcode%
  210   [OPT P*3+4
  220   .exec%
  230   JMP go%:BRK:BRK:BRK            \ Header identifies
  240   EQUB &42:EQUB copy-exec%       \ this as 6502 code
  250   EQUB &10:EQUS "RAMTEST"
  260   EQUB &00:EQUS "1.00 (15 Feb 2010)"
  270   .copy
  280   EQUB 0:EQUS"(C)J.G.Harston":EQUB 0
  290   :
  300   .go%
  310   LDA #&82:JSR OSBYTE            \ What side of the Tube are we on?
  320   LDA #&0E:LDX #&80              \ start, end for I/O
  330   INY:BEQ setlimits
  340   LDA #&05:LDX #&F8              \ start, end for Tube
  350   .setlimits
  360   STA start+1:STX end+1          \ Set memory test limits
  370   LDA #0:TAY                     \ Initial test byte=&00
  380   \STA start+0:\STA end+0
  390   .loop0
  400   STA test
  410   :
  420   \ Test type in Y
  430   \ 0 = all zeros
  440   \ 1 = all ones
  450   \ 2 = move 1s up through bytes
  460   \ 3 = move 0s up through bytes
  470   \ 4 = low byte of address
  480   \ 5 = high byte of address
  490   \ 6 = all zeros again
  500   :
  510   \ Test all memory with test byte specified by Y
  520   \ ---------------------------------------------
  530   .loop1
  540   \LDA start+0:\STA addr+0
  550   LDX #0:STX addr+0              \ Point to start of memory to test
  560   LDA start+1:STA addr+1
  570   :
  580   \ On pass 4 and 5 use address as test byte
  590   \ ----------------------------------------
  600   .loop2
  610   LDA addr+0:CPY #4:BCC testbyte \ pass<4, use current test byte
  620   BEQ setbyte                    \ pass=4, use low byte of address
  630   LDA addr+1:CPY #6:BCS testbyte \ pass=5, use high byte of address
  640   .setbyte
  650   STA test
  660   :
  670   \ Test memory with test value
  680   \ ---------------------------
  690   .testbyte
  700   LDA test                       \ Get test byte
  710   STA (addr,X):LDA (addr,X)      \ Store test byte and fetch it back again
  720   CMP test:BEQ no_error          \ Fetched value didn't match stored value
  730   :
  740   \ Error occured, report it
  750   \ ------------------------
  760   PHA                            \ Save test byte
  770   TYA:JSR PrHex                  \ Output pass number
  780   LDA addr+1:JSR PrHexSpc
  790   LDA addr+0:JSR PrHex           \ Output address
  800   PLA:JSR PrHexSpc               \ Output actual byte
  810   LDA test:JSR PrHexSpc          \ Output test byte
  820   JSR OSNEWL
  830   :
  840   .no_error
  850   INC addr+0:BNE P%+4:INC addr+1 \ Step to next address
  860   \LDA addr+0:\CMP end+0:\BNE loop2
  870   LDA addr+1:CMP end+1:BNE loop2 \ Loop to test memory
  880   :
  890   \ All memory tested, prepare for next pass
  900   \ ----------------------------------------
  910   CPY #1:BCC next0:BEQ next1
  920   CPY #3:BCC next2:BEQ next3
  930   CPY #5:BEQ next5:BCS done
  940   :                               \ Drop through to INC Y and loop back
  950   .next0
  960   DEC test:INY:BNE loop1          \ test byte=&FF, retest memory
  970   .next1
  980   STY test:INY:BNE loop1          \ test byte=&01, retest memory
  990   .next2
 1000   ROL test:BCC loop1              \ Move set bit up, retest memory
 1010   LDA #&FE:STA test:INY:BNE loop1 \ Set bits done, test byte=&FE, retest memory
 1020   .next3
 1030   ROL test:BCS loop1              \ Move clear bit up, retest memory
 1040   .next5
 1050   LDA #0:INY:BNE loop0            \ Clear bits done, do address bytes
 1060   :
 1070   .done
 1080   LDA #ASC"O":JSR OSWRCH
 1090   LDA #ASC"K":JSR OSWRCH
 1100   JSR OSRDCH:JSR OSNEWL           \ Wait for a keypress
 1110   LDA #252:LDY #255               \ X will still be &00
 1120   JSR OSBYTE:LDA #142:JMP OSBYTE  \ Re-enter current language
 1130   :
 1140   .PrHexSpc
 1150   PHA:LDA #ASC" ":JSR OSWRCH:PLA  \ Print a leading space
 1160   .PrHex
 1170   PHA:LSR A:LSR A:LSR A:LSR A
 1180   JSR PrNyb:PLA
 1190   .PrNyb
 1200   AND #15:CMP #10:BCC P%+4:ADC #6
 1210   ADC #ASC"0":JMP OSWRCH
 1220 ]:NEXT
 1230 PRINT"*SAVE RAMTEST ";~mcode%;" ";~O%;" ";~exec%;" ";~exec%