org $7000 ; Spectrum +2 (not +2A!) RAM test ; assemble & run at $7000 (28672) then $8000 (32768) ; NOT RELOCATABLE! RAMTEST:di ; disable interrupts ld hl,PAGES-7 ld b,0 ld c,h srl c srl c srl c srl c add hl,bc ld a,(hl) ld (PAGENO),a ; skip this page ld ix,$ffff ; IX=top of RAM ld a,$02 call $1601 ; open channel to stream 2 ld sp,$7fff ; set stack to top of page 5 call I7P0 ; set INK 7, PAPER 0 ld hl,MESSGO call MESSAGE ld hl,(23635) ;PROG ld de,$5b00 and a sbc hl,de ld b,h ld c,l ld (SAVELEN),bc ex de,hl ld de,SAVESYS ldir ;save system variables ($5b00->PROG) after routine ld b,$28 ei DELAY: halt djnz DELAY ;loop for approx. 0.8s to show message di ld a,$04 out ($fe),a ; green border ld de,$0002 ; D=test pattern,E=pass counter DOPASS1:ld a,$00 ; start with page 0 ld bc,$7ffd DOPAGE1:out (c),a ; page in next page ex af,af' ; save page number ld hl,$c000 DOBYTE1:ld (hl),d ; fill page with D inc hl ld a,l or h jr nz,DOBYTE1 ; until page filled ex af,af' ld hl,PAGENO NOTHIS1:inc a cp (hl) jr z,NOTHIS1 cp $08 jr nz,DOPAGE1 ; back for more pages ld a,$00 ; start at page 0 again DOPAGE2:out (c),a ; page in next page ex af,af' ; save page number ld hl,$c000 DOBYTE2:ld a,(hl) cp d ; check pattern jp nz,NOTOK2 ; move on if error cpl ld (hl),a ; store inverse pattern inc hl ld a,l or h jr nz,DOBYTE2 ; until page done ex af,af' ld hl,PAGENO NOTHIS2:inc a cp (hl) jr z,NOTHIS2 cp $08 jr nz,DOPAGE2 ; back for more pages dec a ; back to page 7 DOPAGE3:ex af,af' ld hl,$0000 ; start at end of memory DOBYTE3:dec hl ld a,h cp $bf jr z,DOPAGE4 ; move on if at start of page ld a,d cpl cp (hl) ; check inverse pattern jp nz,NOTOK2 ; move on if error ld (hl),d ; store normal pattern jr DOBYTE3 ; loop back DOPAGE4:ex af,af' ld hl,PAGENO cp $00 jr z,DOPASS3 NOTHIS3:dec a cp (hl) jr z,NOTHIS3 out (c),a jr DOPAGE3 ; back for more pages DOPASS3:dec e ; decrement pass counter jr z,ULACHEK ; move on if successful ld d,$ff jp DOPASS1 ; back for second pass with new pattern ULACHEK:ld a,$00 ; start with page 0 ld hl,$cafe ; location to use ld bc,$7ffd ULALD: out (c),a ; page in page ld (hl),a ; and store page number inc a cp $08 jr nz,ULALD ; back for more ULACP: dec a out (c),a ; page in page cp (hl) ; check correct number jp nz,NOTOK1 ; if not, go to signal ULA error and a jr nz,ULACP ; back for more ld bc,$7ffd ld a,$00 out (c),a ; make sure ROM 0, page 0 is selected call CHKSUM ; get checksum of ROM 0 sub 145 jr nz,NOTOK0 ; if not zero, go to error ld bc,$7ffd ld a,$10 out (c),a ; get ROM 1 call CHKSUM ; and its checksum sub 112 jr nz,NOTOK0 ; if not zero, go to error DONE: call RESTORE ld hl,MESSOK call MESSAGE ld a,(PAGENO) add a,48 rst $10 DI HALT ; Subroutine to form an 8-bit addition checksum of the current ROM ; All ROMs should checksum to zero CHKSUM: srl a srl a srl a srl a ex af,af' ; save ROM# xor a ; zero checksum ld h,a ld l,a ; and address CHKADD: add a,(hl) ; add next byte inc hl ld d,a ld a,h cp $40 ld a,d jr nz,CHKADD ; back for rest of page and a ; check if zero ret NOTOK0: ld hl,MESSNO+4 ld (hl),"O" ex af,af' NOTOK1: ld hl,$0000 ; specify address 0000 for page error ex af,af' NOTOK2: ex af,af' push af ; save page and address of failure push hl call RESTORE ld hl,MESSNO call MESSAGE pop hl ld a,h call HEXADEC ; output high byte of address ld a,l call HEXADEC ; output low byte of address exx ld hl,MESSPN call MESSAGE pop af exx and $07 call HEXADEC ; output page number DI HALT MESSGO: defb $16,$05,$07,$14,$01 defm "RAM DATA TESTS" defb $16,$0a,$05 defm ".. STARTING NOW .." defb $14,$00,$0d,$ff MESSOK: defb $16,$0a,$00 defm "RAM pass, excluding page " defb $ff MESSNO: defb $16,$0a,$00 defm "RAM fail: address " defb $ff MESSPN: defm ", page " defb $ff ; restore some semblance of BASIC to display messages RESTORE:ld a,%00010000 ld bc,$7ffd ld (23388),a ; BANKM out (c),a ; page in RAM 1 (48k BASIC) ld hl,SAVESYS ld de,$5b00 ld bc,(SAVELEN) ldir call I7P0 ; set INK 7, PAPER 0 ret ; output A as two hexadecimal digits HEXADEC:push hl ; save registers ld b,1 push bc push af inc b push bc push af srl a srl a srl a srl a ; A=A/16 DIGIT: exx ld d,$00 ld e,a ; DE=0...F ld hl,HEXDIG add hl,de ld a,(hl) ; A=ASCII hex digit rst $10 ; output it pop af ; restore value and $0f ; get low nibble exx pop bc djnz DIGIT ; loop back for second digit pop hl ret HEXDIG: defm "0123456789ABCDEF" MESSAGE:ld a,(hl) ;print an $ff-terminated string cp $ff ret z rst $10 inc hl jr MESSAGE I7P0: ld bc,$0700 ;set INK 7, PAPER 0 ld a,$10 rst $10 ld a,b rst $10 ld a,$11 rst $10 ld a,c rst $10 call $0d6b ;clear screen ret PAGES: defb 5,2 PAGENO: defb 0 SAVELEN:defw $0000 SAVESYS: ;copy system variables here ($5b00->PROG)