テスト用プログラムの作成 (LIFEゲーム)


サンプルプログラムとしてLIFEゲームを取り上げます。
キャラクタタイプの表示装置の場合、表示したい箇所のVRAMアドレスのメモリに キャラクタコードを書込み際すれば良い。
VRAMのベースアドレスを VRAM、書き込みたい箇所の座標をX、Yとするとき、 VRAM + ( Y * 80 ) + X のアドレスに書き込めば良い。


プログラムは、以下のようにアセンブルし、プログラムメモリ内に初期プログラ ムとして配置できるようにしておく。

kiteasm -l life.asm
lst2ram -s -f -2 life.lst
メモリの初期化は以下のように $readmemh を利用する。
   initial
   begin
      $readmemh( "life.ram", MEM );
   end


以下に、LIFE プログラムを示す。
	;;
	;; Life Game 48x16 for LCD Monitor on ATLYS Board
	;; 
	
	.word MAIN		; Start Vector
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0
	.word 0

MAIN:	ld16	#STACK		; sp = 0x800
	mv	sp, acc

	;;
	;; Main Loop
	;;
NEXT1:
	;;
	;; Display DATA1 area
	;;

	call	disp		; copy DATA1 to Display
	call	wait		; wait

	;;
	;; Clear DATA2 area
	;;
	ld16	#768
	st	X
	ld	DAT2
	mv	ixr, acc
LOOP3:	ld	#0
	st	ixr, 0
	inc	ixr, ixr
	ld	X
	dec	acc, acc
	st	X
	jpz	NEXT3
	jp	LOOP3

	;;
	;; for( x=0 ; x<48 ; x++ )
	;; 
NEXT3:	ld	#0
FOR1:	st	X
	sub	#48
	jpz	FOREND1

	;;
	;; for( y=0 ; y<16 ; y++ )
	;; 
	ld	#0
FOR2:	st	Y
	sub	#16
	jpz	FOREND2

BODY:	ld	#0		; NoOf = 0
	st	NoOf
	
	ld	X		; if( what1(x-1,y-1) ) NoOf++;
	dec	acc, acc
	push
	ld	Y
	dec	acc, acc
	push
	call	what1
	jpz	SKIP1
	ld	NoOf
	inc	acc, acc
	st	NoOf

SKIP1:	pop
	ld	Y		; if( what1(x-1  ,y  ) ) NoOf++;
	push
	call	what1
	jpz	SKIP2
	ld	NoOf
	inc	acc, acc
	st	NoOf

SKIP2:	pop
	ld	Y		; if( what1(x-1,y+1) ) NoOf++;
	inc	acc, acc
	push
	call	what1
	jpz	SKIP3
	ld	NoOf
	inc	acc, acc
	st	NoOf

SKIP3:	pop
	pop
	ld	X		; if( what1(x  ,y-1) ) NoOf++;
	push
	ld	Y
	dec	acc, acc
	push
	call	what1
	jpz	SKIP4
	ld	NoOf
	inc	acc, acc
	st	NoOf

SKIP4:	pop
	ld	Y		; if( what1(x  ,y+1) ) NoOf++;
	inc	acc, acc
	push
	call	what1
	jpz	SKIP5
	ld	NoOf
	inc	acc, acc
	st	NoOf

SKIP5:	pop
	pop
	ld	X		; if( what1(x+1,y-1) ) NoOf++;
	inc	acc, acc
	push
	ld	Y
	dec	acc, acc
	push
	call	what1
	jpz	SKIP6
	ld	NoOf
	inc	acc, acc
	st	NoOf

SKIP6:	pop
	ld	Y		; if( what1(x+1,y  ) ) NoOf++;
	push
	call	what1
	jpz	SKIP7
	ld	NoOf
	inc	acc, acc
	st	NoOf

SKIP7:	pop
	ld	Y		; if( what1(x+1,y+1) ) NoOf++;
	inc	acc, acc
	push
	call	what1
	jpz	SKIP8
	ld	NoOf
	inc	acc, acc
	st	NoOf

SKIP8:	pop
	pop
	ld	X		; if( what1(x,y) ) {
	push
	ld	Y
	push
	call	what1
	jpz	CENTER0	
CENTER1:ld	NoOf		;	if( NoOf == 2 || NoOf == 3 ) 
	sub	#2		;		set1(x,y);
	jpz	SET		;	else
	ld	NoOf		;		set0(x,y);
	sub	#3
	jpz	SET
	jp	DEL
CENTER0:ld	NoOf		; } else {
	sub	#3		;	if( NoOf == 3 )
	jpz	SET		;		set1(x,y);
DEL:	call	SET0
	jp	SKIP10
SET:	call	SET1		; }

SKIP10:	pop
	pop
	ld	Y		; y++;
	inc	acc, acc
	jp	FOR2		; };// forend y
	
FOREND2:ld	X		; x++;
	inc	acc, acc
	jp	FOR1		; };// forend x

FOREND1:ld16	#768		; Copy DATA2 -> DATA1 area
	st	X
	ld	DAT1
	st	PTR1
	ld	DAT2
	st	PTR2

LOOP4:	ld	PTR2
	mv	ixr, acc
	ld	ixr, 0
	push
	ld	PTR1
	mv	ixr, acc
	pop
	st	ixr,0
	ld	PTR1
	inc	acc, acc
	st	PTR1
	ld	PTR2
	inc	acc, acc
	st	PTR2
	ld	X
	dec	acc, acc
	st	X
	jpz	NEXT1		; Goto Main Loop
	jp	LOOP4
	
	;;
	;; What1(x,y) return 0 and set Z flag
	;;	if thare is no object in DATA1[x,y]
	;;
what1:	mv	ixr, sp
	call	check		; area check
	jpz	return		; if out of area
	call	adgen		; acc = Y*48+X
	st	PTR1
	ld16	#PTR1
	mv	ixr, acc	
	ld	DAT1
	add	ixr, 0		; acc = DATA1+Y*48+X
	mv	ixr, acc	
	ld	ixr, 0		; acc = *(DATA1+Y*48+X)
	or	#0
return:	ret

	;;
	;; check boundary
	;; 
check:	ld	ixr, 2		; load X
	sub	#-1		; if out of left side then return Z
	jpz	return
	ld	ixr, 2
	sub	#48		; if out of right side then return Z
	jpz	return
	ld	ixr, 1		; load Y
	sub	#-1		; if out of upper side then return Z
	jpz	return
	ld	ixr, 1
	sub	#16		; if out of lower side then return Z
	ret			; return NZ if within area

	;;
	;; acc = 48*Y+X
	;;
adgen:	ld	ixr, 1		; acc =    Y
	add	ixr, 1		; acc =  2*Y
	add	ixr, 1		; acc =  3*Y
	asl			; acc =  6*Y
	asl			; acc = 12*Y
	asl			; acc = 24*Y
	asl			; acc = 48*Y
	add	ixr, 2		; acc = 48*Y + X
	ret

	;;
	;; SET1(x,y) sets "1" into DATA2[x,y]
	;;
SET1:	mv	ixr, sp
	call	adgen		; acc = Y*48+X
	st	PTR1
	ld16	#PTR1
	mv	ixr, acc	
	ld	DAT2
	add	ixr, 0		; acc = DATA2+Y*48+X
	mv	ixr, acc	
	ld	#1
	st	ixr, 0		; *(DAT2+Y*48+X) = 1
	ret

	;;
	;; SET0(x,y) sets "0" into DATA2[x,y]
	;;
SET0:	mv	ixr, sp
	call	adgen		; acc = Y*80+X
	st	PTR1
	ld16	#PTR1
	mv	ixr, acc	
	ld	DAT2
	add	ixr, 0		; acc = DATA2+Y*80+X
	mv	ixr, acc	
	ld	#0
	st	ixr, 0		; *(DAT2+Y*80+X) = 0
	ret

	;;
	;; Display :  Copy DATA -> VRAM area
	;; 
	
disp:	ld	#16
	st	Y
	ld16	#VRAM940
	st	PTR2		;  ptr2 = dest. pointer
	ld	DAT1
	st	PTR1		;  ptr1 = DATA1 pointer

disp1:	ld	#48
	st	X		;  X = 48

disp5:	ld	PTR1
	mv	ixr, acc
	ld	ixr, 0
	push
	ld	PTR2
	mv	ixr, acc
	pop
	or	#0
	jpz	disp2
	ld	#0x4f		; 'O'
	jp	disp3
disp2:	ld	#0x20		; ' '
disp3:	st	ixr,0
	ld	PTR1		; ptr1++
	inc	acc, acc
	st	PTR1
	ld	PTR2		; ptr2++
	inc	acc, acc
	st	PTR2
	ld	X		; x--
	dec	acc, acc
	st	X
	jpz	disp4
	jp	disp5
disp4:	ld	PTR2		; ptr2 += 32
	add	#32
	st	PTR2
	ld	Y		; y--
	dec	acc, acc
	st	Y
	jpz	return
	jp	disp1
	
	;; 
	;; wait
	;; 
wait:	ld	#10
LOOP22:	push
	ld	#0
LOOP2:	dec	acc, acc
	jpz	LOOP21
	jp	LOOP2
LOOP21:	pop
	dec	acc, acc
	jpz	return
	jp	LOOP22

	;;
	;;
	;;
					
DAT1:	.word	DATA1		; DATA1 pointer
DAT2:	.word	DATA2		; DATA2 pointer
X:	.word	0		; Variable x
Y:	.word	0		; Variable y
PTR1:	.word	0		; General pointer 1
PTR2:	.word	0		; General pointer 2
NoOf:	.word	0		; Number of object

	;;			Current space
DATA1:	.space	24		; line 0
	.word	 1
	.space	11
	.space	 12

	.space	22		; line 1
	.word	 1
	.word	 0
	.word	 1
	.space	11
	.space	 12
	
	.space	12		; line 2
	.word	 1
	.word	 1
	.space	 6
	.word	 1
	.word	 1
	.space	12
	.word	 1
	.word	 1
	.space	 12

	.space	11		; line 3
	.word	 1
	.space	 3
	.word	 1
	.space	 4
	.word	 1
	.word	 1
	.space	12
	.word	 1
	.word	 1
	.space	 12
	
	.word	 1		; line 4
	.word	 1
	.space	 8
	.word	 1
	.space	 5
	.word	 1
	.space	 3
	.word	 1
	.word	 1
	.space	14
	.space	 12

	.word	 1		; line 5
	.word	 1
	.space	 8
	.word	 1
	.space	 3
	.word	 1
	.word	 0
	.word	 1
	.word	 1
	.space	 4
	.word	 1
	.word	 0
	.word	 1
	.space	11
	.space	 12

	.space	10		; line 6
	.word	 1
	.space	 5
	.word	 1
	.space	 7
	.word	 1
	.space	11
	.space	 12

	.space	11		; line 7
	.word	 1
	.space	 3
	.word	 1
	.space	20
	.space	 12
	
	.space	12		; line 8
	.word	 1
	.word	 1
	.space	 22
	.space	 12

	.space	336

DATA2:	.space	768		; Next space


	.data	0x800
STACK:	
VRAM:

	.data	0x940
VRAM940:


| Back | CAD Home |