Homebrew:RAM test

From veswiki
Revision as of 13:11, 15 March 2019 by E5frog (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Used to test the Multi-Cart on board RAM which is placed on the same address location as the SABA 20 Chess game. Reason for this is that this cart was used as a donor for the early Multi-Carts and a test was needed to check that it was OK before sent out to a happy gamer.

Program is run with a nice colorful interface, every memory bit (2048 of them) of the cart RAM is represented by a pixel in the large rectangle in the middle. When tested it's blue, when green it was tested OK and if red it was bad. A full test takes a few minutes because the graphics updated for each bit, a blind test would be a lot faster.

Latest version makes a quick test writing and reading back %10101010 and %01010101 before turning all four RAM capsules green to indicate that these are OK, then a full write and read test is preformed from %00000000 to %11111111 and if there's an error the corresponding RAM capsule is marked in red as well as the bit. For later carts a single 6116 SRAM is used instead so if there's any error at all the whole capsule needs to be replaced.

However, after building over 100 carts there has never been any errors in the cart RAM.

Download binary

	processor f8

pushk           =       $0107       	; used to allow more subroutine stack space
popk            =       $011e


	IF 0

***************************************************
*                                                 *
*    Program to test 2kByte RAM at $2800-$2FFF    *
*                                                 *
*      Written by Fredric Blåholtz 2004-12-17     *
*                                                 *
*        Thanks to Sean Riddle for support        *
*                                                 *
*       Bad RAM is marked by a red pixel          *
*                                                 *
***************************************************

	ENDIF


; r0 - 32 byte rows     counter
; r1 - 64 byte columns  counter
; r2 - current testvalue
; r3 - counter to draw Lines
; r4 - color in plot routine $00 green, $40 red, $80 blue, $C0 background
; r5 - x-coordinate in plot [0,101]
; r6 - y-coordinate in plot [0,57]
; r7 - used by the BIOS_PUSH_K and BIOS_POP_K
; r8 - width RAMpic 
; r9 - temp storage in faulty routine
; r10 HU - DC0 copy in faulty routine 
; r11 HL - DC0 copy in faulty routine
; r12 KU  
; r13 KL  used by pushk and popk

; r14 QU - r5 backup in faulty routine
; r15 QL - r6 backup in faulty routine


	org $0800

CartridgeStart:	LR   $5,A         	; 0800 55
               	NOP               	; 0801 2b
CartridgeEntry: 	LIS  $0           	; init the h/w
                	OUTS 1
                	OUTS 4
			OUTS 5
			OUTS 0
			
			LISU	4			; Set r32 = complement flag to 0
			LISL	0
			LR	S, A
							; setup screen			
			LI	$21		
			LR	3,A	
			PI	$00d0			; BIOS clearscreen routine, uses R3 to set palette

							; Intro screen:
							; B/W
							; "Multi-Cart RAM test 
							; by Fredric Blåholtz
							; no copyrights in 2004"


			; Backup Pac-Man score
			; 2E00 - 2E05
			; Backup current latch value (reset starts this game)
			; 2E06

			dci	$2E00
			lisl	0
			lisu	3
			; set register 'O'30
			lm				; $2E00
			lr	I, A		; 30
			lm				; $2E01
			lr	I, A		; 31
			lm				; $2E02
			lr	I, A		; 32
			lm				; $2E03
			lr	I, A		; 33
			lm				; $2E04
			lr	I, A		; 34
			lm				; $2E05
			lr	I, A		; 35
			lm				; $2E06
			lr	I, A		; 36

			; BACKUP IS DONE


			DCI	introtext		
introrepeat:	LM
			CI	255			; compare to 255 - which is end of data marker
			BZ	endofintro		; go to end if it was 255
			LR	5,A			; read and save x coordinate
			LM
			LR	6,A			; read and save y coordinate
			PI	plot			

			LI	4			; intro draw delay
			LR	6,A
			LI	$ff
testdelay:		AI	$FF
			BNZ	testdelay
			DS	6
			BZ	introrepeat			
			LI	$FF
			BR	testdelay

endofintro:



							; wait a moment


			LI	$ff
			LR	5,A
introwait:		AI	$FF
			BNZ	introwait
			AS	5
			BZ	endintrowait
			DS	5
			LI	$ff
			BR	introwait

endintrowait:
		


			; erase text

			LI	$c0			; plot color to bg color
			LR	4,A

			DCI	introtext		
introrepeat2:	LM
			CI	255			; compare to 255 - which is end of data marker
			BZ	endofintro2		; go to end if it was 255
			LR	5,A			; read and save x coordinate
			LM
			LR	6,A			; read and save y coordinate
			PI	plot			

			LI	$ff			; erase delay
testdelay2:		AI	$FF
			BNZ	testdelay2
			BZ	introrepeat2			
			LI	$FF
			BR	testdelay2

endofintro2:




							; blue frame around test area of 32*64 pixels
							; setup screen			
			LI	$86		
			LR	3,A	
			PI	$00d0			; BIOS clearscreen routine, uses R3 to set bkg color





			PI	drawBord


							; four grey areas that represents the four chips of the 

			LI	$C0
			LR	4,A			; set bgcolor to plotcolor
			LI	25
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

			LI	44
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

			LI	63
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

			LI	80
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic




			PI	loopinit
			LI	$AA
			LR	2,A			; store current testbyte in R2 since PI messes up A
			PI	writetestdata	; write what's in R2 to all RAM bytes
			PI	loopinit		; set pointer back to beginning
			PI	readtest		; read all RAM to see if they're equal to R2
						
							; if there's no error paint all green
							; and it doesn't change if there's no error




			LIS	0
			LR	4,A			; set green to plotcolor
			LI	25
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

			LI	44
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

			LI	63
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

			LI	80
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

	
; first speedtest done

			PI	loopinit
			LI	$55
			LR	2,A
			PI	writetestdata
			PI	loopinit
			PI	readtest

; second speedtest done, speedy test over

;endoffast:		BR	endoffast



;***************    Slow and thorough test:


			LI	$FF			; this time we start at the top and 
			LR	2,A			; loop through all bitpatterns
allbits:		LR	A,2
			PI	loopinit
			PI	writetestdata
			PI	loopinit
			PI	readtest


			DS	2			; decrease R2
			BNZ	allbits		; if it's not zero do again
			
			PI	loopinit		; one last pass on zero as well
			PI	writetestdata
			PI	loopinit
			PI	readtest


endoftest:		JMP	allok			; everythingsOK





			
loopinit:

	
			DCI	$2800			; RAM start adress
			
							; we've got 2048 bytes to write ( $800 )
							; spin around 32 times in a 63-0 loop
			
			LI	63			; A = 63
			LR	1,A			; 63 store in R1 
			LI	32			; We're doing it 32 times
			LR	0,A			; store in R0
			LI	82
			LR	5,A			; set start column of graphics in R5
			LI	36
			LR	6,A			; set start row of graphics in R6
			
			pop

		

;****************  subroutine writetestdata


writetestdata:

			LR	K,P
			;PI	pushk

			LI	$80			; set color to blue
			LR	4,A		
			LR	A,2			; load testvalue into A
			BR	writeloop
next64:								

			ST
			PI	plot			; plot last byte dot

			DS	6			; decrease graphics row
			LI	83
			LR	5,A			; set column to start of row
			DS	0			; decrease R0, one less round to run
			BZ	donewrite
			LI	64
			LR	1,A			; set R1 back to 63 for next chunk of 64 bytes
			LR	A,2			; restore test value

writeagain:		
			DS	5			; decrease x-counter
			DS	1			; decrease R1, count down 64
			BZ	next64	

		
writeloop:		ST				; Store data in RAM
			PI	plot			; plot dot
	
			LR	A,2			; restore testvalue
			BR	writeagain	

donewrite:		;PI	popk
			PK




;*******************  subroutine readtest


readtest:

			LR	K,P
			PI	pushk

			LIS	0
			LR	4,A			; Set color to green (means OK)
			LR	A,2			; load testvalue into A
			BR	readloop
read64:								
			LR	H,DC			; Backup DC0 for errorhandling
			CM				; compares to memory, dc0 is increased
			BNZ	error			; tests last byte of the row
			PI	plot			; plot last byte dot

jumpback:		DS	6			; decrease graphics row
			LI	83
			LR	5,A			; set column to start of row
			DS	0			; decrease R0, one less round to run
			BZ	allread

			LI	64
			LR	1,A			; set R1 back to 63 for next chunk of 64 bytes
			LR	A,2			; restore test value

continue:		LR	A,2			; restore testvalue

			DS	5			; decrease x-counter
			DS	1			; decrease R1, count down 64
			BZ	read64	

			; memo - perhaps backup DC before read, to use with error handling
		
readloop:		LR	H,DC			; Backup DC in case of error
			CM				; Compare A with data from adress adressed by DC0, DC0 is then incremented
			BNZ	error			; jump to error handling if they weren't equal
			PI	plot			; plot dot
			LR	A,2			; restore testvalue
			BR	continue	

allread:		PI	popk
			PK


error:		LI	$40
			LR	4,A			; set color to red, malfunction
			PI	plot			; plot red dot

			JMP	malfunction

enderror:		LR	A,2			; restore testvalue
			BR	continue		; back into loop





;--------------;
; Draw Border  ;
;--------------;

; draws the border around the test area

drawBord:
			LR	K,P
			;PI	pushk

			LI	$80			; set border color to blue
			LR	4, A

							; start row loop
			LI	57
			LR	6, A
.drawBordLRow:
			LI	17
			LR	5, A
.drawBordLColumn:
			PI	plot

.drawBordLCheck:
			DS	5
			LR	A, 5
			BNZ	.drawBordLColumn
			PI	plot
			DS	6
			BP	.drawBordLRow
.drawBordLEnd:


							; start row loop
			LI	57
			LR	6, A
.drawBordRRow:
			LI	101
			LR	5, A
.drawBordRColumn:
			PI	plot

.drawBordRCheck:
			DS	5
			LR	A, 5
			XI	%01010011		; 01010100 : 17 pixels wide, 01010101: 16, 01011000: 13   101-X= width
			BNZ	.drawBordRColumn
			DS	6
			BP	.drawBordRRow
.drawBordREnd:


							; start row loop
			LI	57			; Row
			LR	6, A
							;Last 20 rows to write
			LI	19			; decimal 19
			LR	3,A
.dLowBarColumn:
			LI	83
			LR	5,A			;Column
.dLowBarRow:
			PI	plot

.dLowBarCheck:
			DS	5
			BNZ	.dLowBarRow
			DS	6
			DS	3
			BP	.dLowBarColumn
.dLowBarEnd:


							; start row loop
			LI	3			; Row
			LR	6, A
							;Upper 4 rows to write
			LI	3			; decimal 3
			LR	3,A
.dTopBarColumn:
			LI	83
			LR	5,A			;Column
.dTopBarRow:
			PI	plot

.dTopBarCheck:
			DS	5
			BNZ	.dTopBarRow
			DS	6
			DS	3
			BP	.dTopBarColumn
.dTopBarEnd:
	
.dBorderLEnd:
			PK


;***********************************  Draw DIL pics


RAMpic:
			LR	K,P
								; start row loop
			LI	55				; Row
			LR	6, A
			LR	A,5
			LR	7,A				; temp store value of R5 in R7			
					
			LI	14				; 15 rows
			LR	3,A

.RamPicColumn:
			LR	A,7				; Set back to start column
			LR	5,A				; Column
			LIS	5
			LR	8,A				; 5 pixels wide

.RamPicRow:
			PI	plot

.RamPicCheck:
			DS	5
			LR	A, 5
			DS	8
			BNZ	.RamPicRow
			DS	6
			DS	3
			BP	.RamPicColumn
.RamPicEnd:


			PK






;===================;
; Drawing Functions ;
;===================;

; plot out a single point on the screen
; uses three registers as "arguments"
; r4 = color, $40 red, $80 blue, $00 green, $C0 background
; r5 = x (to screen) (0-101)
; r6 = y (to screen) (0-57)

plot:

	


	; set the color using r4
	LR	A, 4
	outs	1

	; set the column using r5
	lis	4
	as	5
;	LR	A, 5
;	AI	4
	COM
	outs	4

	; set the row using r6
	lis	4
	as	6
;	LR	A, 6
;	AI	4
	COM
	outs	5

	; transfer data to the screen memory
	LI	$60
	outs	0
	LI	$50
	outs	0

	; delay until it's fully updated
	LIS	4				; same as bowling - the disappearing ball...
.plotDelay:	
	AI	$ff
	bnz	.plotDelay

	pop





	org	$C00

malfunction:	
							; Check what adress error is on, change color of chip to red
							; need to decrease DC0 to get the last read byte

						
							
			; mask out what chip has the faulty byte/bit and mark it


			; Chips 0 - 3. 0 and 2 is RAM at $2800-$2bff, and Chip 1 and 3 is RAM at $2c00-2fff
			; Low nibble are chips 0 and 1, high nibble chips 2 and 3.


			LR	A,5
			LR	QU,A			; backup r5 in r14, x-coordinate for plot
			LR	A,6
			LR	QL,A			; backup r6 in r15, y-coordinate for plot 

							; don't want these to be overwritten by the DIL plot


skiphu:		LR	A,HU			; copy upper byte of adress to A
			CI	$2C			
			BM	Chip0			; compare to 2c, if negative HU:[2D,2F] it's high RAM
			BZ	Chip0			; if it's zero it's also high RAM HU = 2C



							; Chip 0 and Chip 2 is low RAM, but what nibble is faulty?
							; Chip 0 is low nibble

			LR	A,2			; copy testvalue into A

			LR	DC,H			; copies H into DC

							; determine if low or high nibble is faulty
			NI	$F			; Accumulator AND $0F, (keep only low nibble)
			LR	9,A			; store result in R9
			LI	$F			; A = $F
			NM				; A AND readbyte, reads memory and ANDs it, DC0 is increased

							; now we need to compare if A and R9 is the same
							; if they are the same the low nibble is OK - 
							; which means the high nibble must be faulty = Chip 3
							; Branch to Chip 3 if R9 and A are equal
							; compare R9 and A
							; R7 AND and 

			XS	9			; A XOR R9

			BZ	Chip3			; If the result is zero => Chip 2 faulty
							; else it's Chip 0...  and I do nothing

Chip1:		LI	25
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

			JMP	endoferrors		; continue test

Chip3:		LI	63
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

			JMP 	endoferrors		; continue testing





Chip0:		

							; Chip 1 and Chip 3 is high RAM, but what nibble is faulty?
							; Chip 1 is low nibble

			LR	A,2			; copy testvalue into A

			LR	DC,H			; copies H into DC

							; determine if low or high nibble is faulty
			NI	$F			; ByteWritten AND $0F, keeps low nibble
			LR	9,A			; store result in R9
			LI	$F			; A = $F
			NM				; A AND readbyte, reads memory and ANDs it, DC0 is increased

							; now we need to compare if A and R9 is the same
							; if they are the same the low nibble is OK - 
							; which means the high nibble must be faulty = Chip 3 faulty
							; Branch to Chip 2 if R9 and A are equal
							; compare R9 and A

			XS	9			; A XOR R9 

			BZ	Chip2			; If the result is zero => Chip3 faulty
							; else it's Chip1...  and I do nothing
							
							; DC is now same as when entering


Chip_0:		LI	44
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

			JMP	endoferrors


Chip2:		LI	80
			LR	5,A			; set column start value for RAMpic
			PI	RAMpic

endoferrors: 	LR	A,QU			
			LR	5,A			; restore r5 from r14
			LR	A,QL
			LR	6,A			; restore r6 from r15
			LIS	0
			LR	4,A			; set color back to green
			LR	DC,H			;
			CM				; restore DC0 adress


							; if we where at the end of the row, go to jumpback instead
							; if R1 is 0 -> jumpback
			LIS	0
			AS	1			
			BZ	lastonrow	

			JMP	enderror		; continue testing from where we left off

lastonrow:		JMP	jumpback		; 


			; data for paiting up intro screen
			; M
introtext:		dc.b	8,12,8,11,8,10,8,9,8,8,8,7,8,6,9,7,9,8,10,9,10,10,10,11
			dc.b	11,12,12,11,12,10,12,9,13,8,13,7,14,6,14,7,14,8,14,9,14,10
			dc.b	14,11,14,12
			; u
			dc.b  16,8,16,9,16,10,16,11,17,12,18,12,19,8,19,9,19,10,19,11,19,12
			; l
			dc.b	21,6,21,7,21,8,21,9,21,10,21,11,21,12
			; t
			dc.b	23,7,23,8,23,9,23,10,23,11,23,12,24,12,22,8,23,8,24,8
			; i
			dc.b	26,8,26,9,26,10,26,11,26,12,26,6
			; -
			dc.b	28,10,29,10
			; C
			dc.b	34,6,33,6,32,6,31,7,31,8,31,9,31,10,31,11,32,12,33,12,34,12
			dc.b	35,11,35,7
			; a
			dc.b	37,8,38,8,39,8,40,8,40,9,40,10,40,11,40,12,39,10,38,10,37,11
			dc.b	37,12,38,12,39,12,40,12
			; r
			dc.b	42,8,42,9,42,10,42,11,42,12,44,8,43,9
			; t
			dc.b	45,7,45,8,45,9,45,10,45,11,45,12,46,12,44,8,45,8,46,8		

			; R
			dc.b	52,6,52,7,52,8,52,9,52,10,52,11,52,12,53,6,54,6,55,6,56,7,56,8
			dc.b	55,9,54,9,53,9,55,10,56,11,56,12
			; A
			dc.b	61,6,60,7,60,8,59,9,59,10,59,11,58,12,61,6,62,7,62,8,63,9,63,10
			dc.b 	63,11,64,12,59,10,60,10,61,10,62,10,63,10
			; M
			dc.b	65,6,65,7,65,8,65,9,65,10,65,11,65,12,66,7,66,8,67,9,67,10,67,11
			dc.b 	68,12,69,11,69,10,69,9,70,8,70,7,71,6,71,7,71,8,71,9,71,10,71,11
			dc.b 	71,12
			; t
			dc.b	75,7,75,8,75,9,75,10,75,11,75,12,76,12,74,8,75,8,76,8
			; e
			dc.b	79,10,80,10,81,10,81,9,80,8,79,8,78,9,78,10,78,11
			dc.b	79,12,80,12,81,12
			; s
			dc.b	86,8,85,8,84,8,83,9,84,10,85,10,86,11,85,12,84,12,83,12
			; t
			dc.b	88,7,88,8,88,9,88,10,88,11,88,12,87,8,88,8,89,8

			; b
			dc.b	44,18,44,19,44,20,44,21,44,22,44,23,44,24,45,20,46,20
			dc.b	47,21,47,22,47,23,46,24,45,24
			; y
			dc.b	49,20,50,21,50,22,50,23,53,20,52,21,52,22,52,23,51,24,51,25,50,26

			; F
			dc.b	18,30,18,31,18,32,18,33,18,34,18,35,18,36,19,30,20,30,21,30
			dc.b 	19,33,20,33
			; r
			dc.b	22,32,22,33,22,34,22,35,22,36,24,32,23,33
			; e
			dc.b	27,34,28,34,29,34,29,33,28,32,27,32,26,33,26,34,26,35
			dc.b	27,36,28,36,29,36
			; d
			dc.b	34,30,34,31,34,32,34,33,34,34,34,35,34,36,33,32,32,32,31,33
			dc.b	31,34,31,35,32,36,33,36
			; r
			dc.b	36,32,36,33,36,34,36,35,36,36,38,32,37,33
			; i 
			dc.b	39,32,39,33,39,34,39,35,39,36,39,30
			; c
			dc.b	44,33,43,32,42,32,41,33,41,34,41,35,42,36,43,36,44,35
			
			; B
			dc.b	50,30,50,31,50,32,50,33,50,34,50,35,50,36,51,30,52,30
			dc.b	53,31,53,32,52,33,51,33,53,34,53,35,52,36,51,36
			; l
			dc.b	55,30,55,31,55,32,55,33,55,34,55,35,55,36
			; å
			dc.b	57,32,58,32,59,32,60,32,60,33,60,34,60,35,60,36,59,34
			dc.b	58,34,57,35,57,36,58,36,59,36,59,28,58,29,59,30,60,29
			; h
			dc.b	62,30,62,31,62,32,62,33,62,34,62,35,62,36,63,32,64,32
			dc.b	65,33,65,34,65,35,65,36
			; o
			dc.b	69,32,68,32,67,33,67,34,67,35,68,36,69,36,70,35,70,34,70,33
			; l
			dc.b	72,30,72,31,72,32,72,33,72,34,72,35,72,36
			; t
			dc.b	74,31,74,32,74,33,74,34,74,35,74,36,75,36,73,32,74,32,75,32
			; z
			dc.b	77,32,78,32,79,32,79,33,78,34,77,35,77,36,78,36,79,36

			; 2
			dc.b	39,43,40,42,41,42,42,43,42,44,41,45,41,46,40,47
			dc.b	39,48,40,48,41,48,42,48
			; 0
			dc.b	46,42,45,42,44,43,44,44,44,45,44,46,44,47,45,48,46,48
			dc.b	47,47,47,46,47,45,47,44,47,43
			; 0
			dc.b	51,42,50,42,49,43,49,44,49,45,49,46,49,47,50,48,51,48
			dc.b	52,47,52,46,52,45,52,44,52,43
			; 4
			dc.b	57,42,56,43,55,44,54,45,54,46,55,46,56,46,57,46,58,46
			dc.b	57,42,57,43,57,44,57,45,57,46,57,47,57,48
	
			; introend
			dc.b	255

	org	$fe0
allok:		
			; RESTORE DATA
			dci	$2E00
			lisl	0
			lisu	3			; set register 'O'30
			lr	A, I		; 30
			st
			lr	A, I		; 31
			st
			lr	A, I		; 32
			st
			lr	A, I		; 33
			st
			lr	A, I		; 34
			st
			lr	A, I		; 35
			st
			lr	A, I		; 36
			st


lock_up_loop:
			BR	lock_up_loop


	org $fff
		.byte $fb