; Tab width = 4

;----------------------------------------------------------------------------
; ** 総合サンプル **
;
;----------------------------------------------------------------------------
; 1.12 990105 SEGA Enterprises,LTD.
;----------------------------------------------------------------------------

chip	LC868700			; チップの種類をアセンブラに指定
world	external			; 外部メモリ用プログラム

public	main				; ghead.asm から参照されるシンボル
public	int_BaseTimer		;
public	int_P3				;
public	int_T0H				;

extern	_game_end			; アプリケーション終了
extern	fm_wrt_ex, fm_vrf_ex, fm_prd_ex	; ghead.asm への参照シンボル


; **** マクロ文の定義 *******************************************************

LcdAccessBegin	macro		; **** LCDへのアクセス開始 ****
		push	OCR			; OCR値を退避
		mov		#osc_rc,OCR ; システムクロックを指定
		clr1	VCCR,6		; LCD RAMへのCPUアクセス許可
		endm
		
LcdAccessEnd	macro		; **** LCDへのアクセス終了 ****
		set1	VCCR,6		; LCD RAMへのCPUアクセス禁止
		pop		OCR			; OCR値を復帰
		endm


; **** システム定数の定義 ***************************************************

							; OCR(発振制御レジスタ)設定値
osc_rc		equ 04dh		;	システムクロックに内蔵RC発振を指定
osc_xt		equ 0efh		;	システムクロックに水晶発振を指定
sec_h		equ 01dh		; 時計バッファの秒値

LowBattChk	equ 06eh		; ローバッテリー検出フラグ(RAMバンク0)

fmflag		equ 07ch		; フラッシュメモリ書き込み終了検出方式
fmbank		equ 07dh		; フラッシュメモリバンク切替え
fmadd_h		equ 07eh		; フラッシュメモリ上位アドレス
fmadd_l		equ 07fh		; フラッシュメモリ下位アドレス

fmbuff		equ 080h		; フラッシュメモリ読み書き用バッファ先頭


; **** ゲーム定数の定義 *****************************************************

mainloop	equ	1


; *** データセグメント ******************************************************

			dseg			; データセグメント開始

r0:			ds		1		; 間接アドレッシングレジスタ r0
r1:			ds		1		; 間接アドレッシングレジスタ r1
r2:			ds		1		; 間接アドレッシングレジスタ r2
r3:			ds		1		; 間接アドレッシングレジスタ r3
			ds		12		; その他のレジスタ

work1:		ds		1		; 作業用(put2digitで使用)
pmwk1:		ds		1		; put_mimi で使用
pclin:		ds		1		; putch で使用
ip3wk1:		ds		1		; DoHit で使用
rnds:		ds		1		; ランダムシード
ms_ptr:		ds		1		; ministr で使用
ms_x:		ds		1		; ministr で使用
ms_y:		ds		1		; ministr で使用
ms_trh:		ds		1		; ministr で使用
ms_trl:		ds		1		; ministr で使用
phase:		ds		1		; プログラムの状態
sleeping:	ds		1		; スリープ中フラグ

score:		ds		1		; スコア値
bscore:		ds		1		; 表示済みのスコア
lefttime:	ds		1		; 残り時間
timechg:	ds		1		; 残り時間変化フラグ
snding:		ds		1		; 音声出力中カウンタ
btnflg:		ds		1		; ボタン状態フラブ
t0flg:		ds		1		; タイマ割り込みフラグ

mgrstat:	ds		4		; モグラの状態


; *** コードセグメント ******************************************************

		cseg				; コードセグメント開始
		
; *-------------------------------------------------------------------------*
; * ユーザープログラム														*
; *-------------------------------------------------------------------------*
main:
		mov		#0,sleeping		; スリープ中フラグリセット
		mov		#0,phase		; ゲーム状態を初期化
		clr1	P3INT,0			; P3割り込みをマスク
		callo	SndInit			; サウンド初期化

		callo	cls				; LCDの消去
		set1	pcon,0			; 次の割り込みまでHALTモードで待つ
		callo	PutCopyright
		set1	pcon,0			; 次の割り込みまでHALTモードで待つ
		set1	pcon,0			;
		set1	pcon,0			;
		set1	pcon,0			;
		callo	cls				; LCDの消去
		set1	pcon,0			; 次の割り込みまでHALTモードで待つ

splash:
		callo	cls				; LCDの消去
		callo	PutSample		; 「SAMPLE GAME」スプラッシュの表示
		callo	PutPushAB		; 「PUSH A+B」の表示
		callo	ABWait			; [A]+[B]ボタンを待つ
		bzo		finish			; [M]が押されたか、本体に接続されたら終了
		
		callo	cls				; LCDの消去
		mov		#mgrstat,r1		; モグラ状態の初期化(0クリア)
		mov		#4,b			;
lp2:	mov		#0,@r1			;
		inc		r1				;
		dbnz	b,lp2			;
		
		ld		sec_h			; 乱数初期化
		st		rnds			;
		mov		#4,pclin		; putch 表示処理ライン数初期化		
		mov		#0,snding		; 音声出力中カウンタクリア
		mov		#0,score		; スコアのクリア
		mov		#0ffh,bscore	; 表示済みのスコア

		callo	T0Mode2Init		; タイマT0初期化
		callo	PutScene1		; 初期画面
		callo	PutReady		; 「READY」表示
		callo	Eff4			; 効果音
		callo	DelStr			; 「READY」消去
		callo	PutGo			; 「GO」表示

		mov		#20*2,lefttime	; 残り時間10秒
		mov		#0ffh,ip3wk1	; 押されてるフラグクリア
		mov		#0,timechg		; 時間変化フラグリセット
		mov		#mainloop,phase	; ゲーム状態はメインループ
		clr1	P3INT,1			; P3割り込みフラグクリア
		set1	P3INT,0			; P3割り込みを許可
		
loop0:							; *** ゲームメインループ **********************

		set1	pcon,0			; HALT して割り込みイベント発生を待つ

		ld		t0flg			; タイマ割り込みによるスロットタイムフラグ
		bz		nx6				; フラグ立ってないとき次へ
		mov		#0,t0flg		; フラグリセット
		callo	DoMgr			; モグラ処理
								;
		ld		snding			;; 音声出力中カウンタ処理
		bz		nx4				;;
		dbnz	snding,nx4		;;
		callo	SndStop			;;
nx4:							;;
nx6:							;

		ld		btnflg			; ボタンが押されたらたたく関連の処理
		bz		nx5				;
		callo	DoHit			; たたく処理		
nx5:							;

		ld		score			; スコアに変化があったときスコア表示
		be		bscore,nx1		;
		st		bscore			;
		callo	PutScore		;
nx1:							;

		ld		timechg			; 残り時間に変化があったとき残り時間表示
		bz		nx2				;
		ld		lefttime		;
		bne		#19*2,nx3		;; 残り時間19秒のタイミングで「GO」を消去
		callo	DelStr			;;		
nx3:							;;
		callo	PutTime			;
		mov		#0,timechg		; 時間変化フラグクリア
		inc		rnds			;
nx2:							;

		bn		P3,6,finish		; [M]が押されていたら強制終了
		bp		P7,0,finish		; 本体に接続されたら強制終了
		bp		P3,7,nx7		; [S]が押されていたらスリープ
		callo	sleep			;
nx7:							;

		ld		lefttime		; 残り時間のある限りループ
		bnz		loop0			;
								; *********************************************

		mov		#0,phase		; ゲーム状態
		clr1	P3INT,0			; P3割り込みをマスク
		callo	T0HStop			; T0Hタイマ停止
		callo	PutGameover		; GAMEOVER 表示
		callo	Eff1			; 効果音

								; ** [A]か[B]が押されるまで待つ **
		set1	P3INT,0			; P3割り込みを許可
lp6:	mov		#2*60*2,lefttime ; スリープタイマをリセット(2分)
lp4:	set1	pcon,0			; HALTして割り込みを待つ
		ld		lefttime		; スリープタイマ状態のチェック
		bnz		nx9				; まだ間があるならnx9
		callo	sleep			; スリープ
		br		lp6				; 起きたらまたスリープタイマリセットから
nx9:							;
		ld		P3				; [A]or[B]ボタンを待つ
		bn		acc,6,finish	;; [M]が押されていたら終了
		bp		P3,7,nx8		;; [S]が押されていたらスリープ
		callo	sleep			;;
		br		lp4				;;
nx8:							;;
		bp		P7,0,finish		; 本体に接続されたら終了
		and		#%00110000		;
		be		#%00110000,lp4	;

		clr1	P3INT,0			; P3割り込みをマスク
		bro		splash			; スタート画面に戻る

finish:							; ** アプリケーション終了処理 **
		mov		#0,phase		; ゲーム状態
		callo	T0HStop			; T0Hタイマ停止
		callo	SndStop			; 音声出力停止
		jmpo	_game_end		; アプリケーション終了


; *-------------------------------------------------------------------------*
; * スリープ																*
; *-------------------------------------------------------------------------*
sleep:
		push	T0CNT			; 関連レジスタを退避
		push	P3INT			;
		push	I01CR			;
		set1	I01CR,3			; P70 Hレベル検出割り込み設定
		set1	I01CR,2			;
		set1	I01CR,0			; P70割り込み許可
		set1	P3INT,2			; P3割り込み許可設定
		set1	P3INT,0			;
		clr1	T0CNT,0			; ボタン以外の割り込みを禁止
		clr1	T0CNT,2			;			
		mov		#0ffh,sleeping	; スリープ中フラグセット
		mov		#%01000000,VCCR	; 液晶表示OFF
	
sllp2:	bn		P3,7,sllp2		; [S]が離されるまで待つ
	
								; ** HALTモードで、[S]ボタンを待機 **
		clr1	I01CR,1			;
sllp1:							;
		clr1	P3INT,1			;
		set1	pcon,0			; HALT
		bp		I01CR,1,slnx1	; 本体と接続されたら脱出
		bp		P3,7,sllp1		; [S]が押されていなければさらに待機
slnx1:

		mov		#%10000000,VCCR	; 液晶表示ON

sllp3:	bn		P3,7,sllp3		; [S]が離されるまで待つ

		mov		#0,sleeping		; スリープ中フラグ解除
		pop		I01CR			; 関連レジスタ復帰
		pop		P3INT			;
		pop		T0CNT			;
		ret						; sleep終了


; *-------------------------------------------------------------------------*
; * モグラ処理																*
; *-------------------------------------------------------------------------*
DoMgr:
		callo	rand			; ランダムに位置を選ぶ
		and		#3				; 0〜3
		st		c				; c に位置を保存
		mov		#mgrstat,r1		; その位置の現在の状態を調べる
		add		r1				;
		st		r1				;
		ld		@r1				;
		
		be		#0,st0			; 現在いないとき
		be		#1,st1			; 現在出始め
		be		#2,st2			; 現在完全
		be		#3,st3			; 現在戻り
		be		#4,st4			; 現在たたかれ
		ret						; DoMgr終了

st0:							; モグラ出始め
		inc		@r1				; 状態
		callo	PutMgr1			; モグラ(半分)キャラ表示
		callo	Eff3
		ret						; DoMgr終了

st1:							; モグラ完全
		inc		@r1				; 状態
		callo	PutMgr2			; モグラ(完全)キャラ表示
		ret						; DoMgr終了

st2:							; モグラ戻り
		inc		@r1				; 状態
		callo	PutMgr1			; モグラ(半分)キャラ表示
		ret						; DoMgr終了

st3:							; モグラ隠れる
st4:							; モグラやっつけ消去
		mov		#0,@r1			; 状態
		callo	PutNull			; モグラ消去キャラ表示
		ret						; DoMgr終了


; *-------------------------------------------------------------------------*
; * たたく処理																*
; *-------------------------------------------------------------------------*
DoHit:
		ld		ip3wk1				; 押されてるフラグをチェック
		bne		#0ffh,dhnx1			; 既に押されている時は離されるまで無処理
		
		ld		P3					; P3の状態を読み込む
		st		ip3wk1				; 押されフラグセット
		mov		#0,c
		be		#%11111011,chkmgr	; [←]ボタンのチェック
		inc		c
		be		#%11110111,chkmgr	; [→]ボタンのチェック
		inc		c
		be		#%11101111,chkmgr	; [A]ボタンのチェック
		inc		c
		be		#%11011111,chkmgr	; [B]ボタンのチェック
		ret							; DoHit終了
		
dhnx1:	ld		P3					; P3の状態を記録する
		st		ip3wk1				;
		bne		#0ffh,dhnx2			; 押されている時はこれで終わり
		mov		#0,btnflg			; 離されたらボタンフラグクリア
		set1	P3INT,0				; P3割り込みを許可
dhnx2:								;
		ret							; DoHit終了

chkmgr:	ld		c					; c:押されたボタンの位置
		mov		#mgrstat,r1			; その位置の現在の状態を調べる
		add		r1					;
		st		r1					;
		ld		@r1					;
		bne		#2,dxnx2			; 完全状態でなければ帰る
		
									; ↓たたくことができた
		mov		#4,@r1				; たたかれ状態にセット
		callo	PutYarare			; たたかれパターン表示
		callo	Eff2				; たたかれ音を発音
		inc		score				; スコアカウントアップ
dxnx2:
		ret							; DoHit終了


; *-------------------------------------------------------------------------*
; * 基本画面セットの描画													*
; *-------------------------------------------------------------------------*
PutScene1:
		callo	PutJimen	; 地面

										; ** 「SCORE」文字表示
		mov		#low( str_score),TRL	; 文字列データアドレス
		mov		#high(str_score),TRH	;
		mov		#0,c					; 水平位置
		mov		#0,b					; 垂直位置
		callo	ministr					; 「SCORE」を表示

		callo	PutScore	; ** スコア表示 **

							; ダミー00表示
		mov		#5,c		; 水平位置
		mov		#0,b		; 垂直位置
		callo	locate		; 座標から表示RAMのアドレスを計算

		mov		#0,c		; 表示文字
		mov		#0,b		; 表示文字
		callo	put_mini	; ミニフォント描画

							; ** 残り時間表示部分の初期 **
		mov		#5,c		; 表示位置指定
		mov		#20,b		;
		callo	locate		;

		mov		#0,c		; 表示文字
		mov		#2,b		; 表示文字
		callo	put_mini	; ミニフォント描画

		ret					; PutScene1終了

str_score:		dc	'SCORE@\x0'


PutJimen:					; ** 地面 **
		mov		#3,pclin	; キャラクタ表示ライン数

		mov		#6,c		; 横方向キャラクタ数
lp1:	push	c
		dec		c			; キャラクタ数カウンタを水平座標に変換

		mov		#13,acc		; 地面キャラコード
		mov		#26,b		; 垂直位置
		callo	putch		; 1キャラ表示

		pop		c
		dbnz	c,lp1		; 横方向描画ループ

		ret					; PutJimen終了


; *-------------------------------------------------------------------------*
; * 残り時間数値描画														*
; *-------------------------------------------------------------------------*
PutTime:
		mov		#5,c		; ** 表示位置の指定 **
		mov		#20,b		;
		call	locate		;

		ld		lefttime	; 残り時間(0.5秒カウント)
		clr1	PSW,7		; CYフラグクリア
		rorc				; 1秒値に換算
		st		c			; cへ
		
							; ** 各桁を分解	**	
		mov		#0,acc		; ac = c/10 (...b)
		mov		#10,b		;
		div					; c: 10の位 b: 1の位
				
		ld		b			; b <-> c
		xch		c			;
		st		b			;
		
		call	put_mini	; bc文字を表示

		ret					; PutTime終了


; *-------------------------------------------------------------------------*
; * スコア数値描画															*
; *-------------------------------------------------------------------------*
PutScore:
		mov		#4,c		; ** 表示位置の指定 **
		mov		#0,b		;
		call	locate		;

		ld		score
		st		c			; c:スコア値
		
							; ** 各桁を分解 **
		mov		#0,acc		; ac = ac/100 (...b)
		mov		#100,b		;
		div					;
		push	c			; push 100の位
		
		ld		b			; ac = 剰余/10 (...b)
		st		c			;
		mov		#0,acc		;
		mov		#10,b		;
		div					; c: 10の位 b: 1の位
				
		ld		b			; b <-> c
		xch		c			;
		st		b			;
		
		call	put_mini	; bc文字を表示 (スコア下2桁)

		mov		#3,c		; 表示位置の指定
		mov		#0,b		;
		call	locate		;

		pop		c			; pop 100の位
		mov		#0,b		; 1000の位
		call	put_mini	; 上位2桁表示

		ret					; PutScore終了


; *-------------------------------------------------------------------------*
; * ミニフォントによる文字列描画											*
; * 文字列は偶数文字数である必要がある。スペースは「@」						*
; * 入力: c:水平位置 b:垂直位置 TR:文字列									*
; *-------------------------------------------------------------------------*
ministr:
		mov		#3,pclin		; putch 表示処理ライン数(3*2=6)
		ld		c				; 表示指定水平位置を ms_x へコピー
		st		ms_x			;
		ld		b				; 表示指定水平位置を ms_x へコピー
		st		ms_y			;
		mov		#0,ms_ptr		; 文字列中の表示ポイント

mslp1:							; 文字列表示ループ
		ld		ms_x			; 表示位置取り出し
		st		c				;
		ld		ms_y			;
		st		b				;
		callo	locate			; 座標から表示RAMのアドレスを計算(R2)

		ld		ms_ptr			; 文字コード左側を取り出し
		ldc						;
		bz		msnx1			; コードが 0 ならば終了
		sub		#'@'			; 「@」コードを0として
		st		b				; Bへ格納
		inc		ms_ptr			; 文字列ポインタ移動
		ld		ms_ptr			; 文字コード右側取り出し
		ldc						;
		sub		#'@'			; 「@」コードを0として
		st		c				; Cへ格納
		inc		ms_ptr			; 文字列ポインタ移動

		push	TRL
		push	TRH
		call	put_minic		; ミニフォント描画
		pop		TRH
		pop		TRL

		inc		ms_x			; 表示位置を右へ移動
		br		mslp1			; 文字列表示ループ

msnx1:
		ret						; ministr終了


; *-------------------------------------------------------------------------*
; * 簡易乱数発生															*
; * 入力: rnds:シード														*
; * 出力: acc,rnds:乱数														*
; *-------------------------------------------------------------------------*
rand:
		ld		rnds			; c = rnds * 111
		st		b				;
		mov		#111,c			;
		mov		#0,acc			;
		mul						;
		st		b				;
		ld		c				; c = c + 13
		add		#13				;
		st		c				;
		mov		#23,b			; b = c mod 23
		mov		#0,acc			;		
		div						;
		ld		b				; rnds = acc = b
		st		rnds			;

		ret						; rand終了


; *-------------------------------------------------------------------------*
; * 文字消去																*
; * 入力: b:垂直ライン位置 c: 水平文字位置 acc: 消去文字幅					*
; *-------------------------------------------------------------------------*
DelChr:
		mov		#4,pclin		; putch 表示処理ライン数初期化
		push	acc
		push	c
		push	b
		mov		#12,acc			; 消去キャラコード
		call	putch			; 1キャラ表示
		pop		b
		pop		c
		pop		acc
		inc		c
		dbnz	acc,DelChr		; 消去文字幅分ループ
		
		ret						; DelChr終了
		

; *-------------------------------------------------------------------------*
; * モグラキャラ表示														*
; * 入力: c:表示位置(0〜3)													*
; *-------------------------------------------------------------------------*
PutNull:
		mov		#12,acc			; 消去キャラコード
		br		PutMgr0
PutYarare:
		mov		#15,acc			; モグラやられキャラコード
		br		PutMgr0
PutMgr1:
		mov		#16,acc			; モグラ(半分)キャラコード
		br		PutMgr0
PutMgr2:
		mov		#14,acc			; モグラ(完全)キャラコード
PutMgr0:
		mov		#4,pclin		; putch 表示処理ライン数初期化
		inc		c				; 位置補正
		mov		#18,b			; 垂直位置
		call	putch			; 1キャラ表示
		
		ret						; PutNull終了


; *-------------------------------------------------------------------------*
; * 画面真ん中に文字列を表示各種											*
; *-------------------------------------------------------------------------*
		; ****「(C)SEGA ENTERPRISES,LTD.,1998」を表示 ****
PutCopyright:
		mov		#low( str_sega),TRL		; 文字列データアドレス
		mov		#high(str_sega),TRH		;
		mov		#0,c					; 水平位置
		mov		#8,b					; 垂直位置
		call	ministr					; 「(C)SEGA」を表示

		mov		#low( str_enterprises),TRL	; 文字列データアドレス
		mov		#high(str_enterprises),TRH	;
		mov		#0,c					; 水平位置
		mov		#16,b					; 垂直位置
		call	ministr					; 「ENTERPRISES,」を表示

		mov		#low( str_ltd),TRL		; 文字列データアドレス
		mov		#high(str_ltd),TRH		;
		mov		#2,c					; 水平位置
		mov		#24,b					; 垂直位置
		call	ministr					; 「LTD.,」を表示
		
										; 「1998」の表示
		mov		#4,c					; 水平位置
		mov		#24,b					; 垂直位置
		call	locate					; 座標から表示RAMのアドレスを計算

		mov		#1,b					; 表示文字
		mov		#9,c					; 表示文字
		call	put_mini				; ミニフォント描画

		mov		#5,c					; 水平位置
		mov		#24,b					; 垂直位置
		call	locate					; 座標から表示RAMのアドレスを計算

		mov		#9,b					; 表示文字
		mov		#8,c					; 表示文字
		call	put_mini				; ミニフォント描画

		ret								; PutCopyright終了
		
str_sega:			dc	'\x5bC\x5cSEGA@\x0'
str_enterprises:	dc	'ENTERPRISES\x5e\x0'
str_ltd:			dc	'LTD\x5d\x0'


		; ****「SAMPLE GAME」を表示 ****
PutSample:
		mov		#low( str_sample),TRL	; 文字列データアドレス
		mov		#high(str_sample),TRH	;
		mov		#1,c					; 水平位置
		mov		#10,b					; 垂直位置
		call	ministr					; 「SAMPLE」を表示

		mov		#low( str_game),TRL		; 文字列データアドレス
		mov		#high(str_game),TRH		;
		mov		#3,c					; 水平位置
		mov		#16,b					; 垂直位置
		call	ministr					; 「GAME」を表示
		
		ret								; PutSample終了

str_sample:		dc	'SAMPLE\x0'
str_game:		dc	'GAME\x0'
		

		; ****「READY」を表示 ****
PutReady:
		mov		#low( str_ready),TRL	; 文字列データアドレス
		mov		#high(str_ready),TRH	;
		mov		#2,c					; 水平位置
		mov		#10,b					; 垂直位置
		call	ministr					; 「READY」を表示

		ret								; PutReady終了

str_ready:		dc	'READY@\x0'


		; ****「GAMEOVER」を表示 ****
PutGameover:
		mov		#low( str_gameover),TRL	; 文字列データアドレス
		mov		#high(str_gameover),TRH	;
		mov		#1,c					; 水平位置
		mov		#10,b					; 垂直位置
		call	ministr					; 「GAMEOVER」を表示

		ret								; PutGameover終了

str_gameover:	dc	'GAMEOVER\x0'


		; ****「GO」を表示 ****
PutGo:
		mov		#low( str_go),TRL		; 文字列データアドレス
		mov		#high(str_go),TRH		;
		mov		#2,c					; 水平位置
		mov		#10,b					; 垂直位置
		call	ministr					; 「GO」を表示

		ret								; PutGo終了

str_go:			dc	'@GO@\x0'


		; ****「PUSH A+B」を表示 ****
PutPushAB:
		mov		#low( str_pushab),TRL	; 文字列データアドレス
		mov		#high(str_pushab),TRH	;
		mov		#1,c					; 水平位置
		mov		#26,b					; 垂直位置
		call	ministr					; 「PUSH A+B」を表示

		ret								; PutPushAB終了

str_pushab:		dc	'PUSH@A\x5fB\x0'


		; **** 画面真ん中に表示している文字を消去する ****
DelStr:
		mov		#1,c			; 水平文字位置
		mov		#8,b			; 垂直ライン位置
		mov		#4,acc			; 消去幅
		callo	DelChr

		ret						; DelStr終了


; *-------------------------------------------------------------------------*
; * 2桁の数値を表示する														*
; * 入力 acc : 数値															*
; *		   c : 文字水平位置													*
; *		   b : ライン垂直位置												*
; *-------------------------------------------------------------------------*
put2digit:
		push	b			; 座標データを退避
		push	c			;
		st		c			; 10の位と1の位の値をそれぞれ計算
		xor		a			; ( acc = acc/10, work1 = acc mod 10 )
		mov		#10,b		;
		div					;
		ld		b			;
		st		work1		; 1の位の計算結果をwork0に保存
		ld		c			;
		pop		c			; 座標値を(c.b)に復帰
		pop		b			; 
		push	b			; また退避
		push	c			;
		call	putch		; 10の位を表示
		ld		work1			; 1の位の値を読み込み
		pop		c			; 座標値を(c,b)に復帰
		pop		b			; 
		inc		c			; 表示座標を右へ
		call	putch		; 1の位を表示

		ret					; put2digit終わり


; *-------------------------------------------------------------------------*
; * [A]+[B]が押されるまで待つ												*
; * 出力: acc=0: [M],[S]が押されたか、本体に接続された						*
; *		  acc!=0: 正常終了													*
; *-------------------------------------------------------------------------*
ABWait:
		set1	P3INT,0				; P3割り込みを許可
		
ablp2:	mov		#2*60*2,lefttime	; スリープタイマをリセット(2分)

ablp1:	set1	pcon,0				; HALT して割り込みを待つ

		ld		lefttime			; スリープタイマ状態のチェック
		bnz		abnx3				; まだ間があるならabnx3
		callo	sleep				; スリープ
		br		ablp2				; 起きたらまたスリープタイマリセットから
abnx3:								;

		ld		P3					; ボタン状態のチェック
		bn		acc,6,abnx1			; [M]が押されていたら脱出
		bp		P7,0,abnx1			; 本体に接続されていたら脱出
		bp		acc,7,abnx2			; [S]が押されていたらスリープ
		callo	sleep				;
		br		ablp1				;
abnx2:								;
		bne		#%11001111,ablp1	; [A]+[B]が押されるまで待つ
		
		clr1	P3INT,0				; P3割り込みをマスク
		ret							; ABWait終了
		
abnx1:	
		clr1	P3INT,0				; P3割り込みをマスク
		mov		#0,acc
		ret							; ABWait終了


; *-------------------------------------------------------------------------*
; * LCD表示イメージを消去する												*
; *-------------------------------------------------------------------------*
cls:
		LcdAccessBegin		; LCDアクセス開始

		mov		#0,XBNK		; 表示用RAMのバンクアドレスを指定(BANK0)
		call	cls_s		; そのバンク内のデータをクリア

		mov		#1,XBNK		; 表示用RAMのバンクアドレスを指定(BANK1)
		call	cls_s		; そのバンク内のデータをクリア

		LcdAccessEnd		; LCDアクセス終了
		ret					; cls終わり
		
cls_s:						; *** 表示用RAM 1BANK分の消去 ***
		mov		#80h,r2		; 間接アドレッシングレジスタを表示用RAMの先頭に
		mov		#80h,b		; ループカウンタbにループ数をセット
loop3:
		mov		#0,@r2		; アドレスをインクリメントしながら0を書き込む
		inc		r2			;
		dbnz	b,loop3		; bが0になるまで繰り返す
		
		ret					; cls_s終わり
		

; *-------------------------------------------------------------------------*
; * 指定位置に1キャラクタ表示する											*
; * 入力 acc : キャラクタコード												*
; *		   c : 文字水平位置													*
; *		   b : ライン垂直位置 (偶数のみ)									*
; *		 pclin : 表示処理ライン数/2											*
; *-------------------------------------------------------------------------*
putch:
		push	XBNK
		push	acc
		call	locate		; 座標から表示RAMのアドレスを計算
		pop		acc
		call	put_chara	; 1キャラクタ表示する
		pop		XBNK
		
		ret					; putch終わり
		

locate:	; **** 表示位置指定から表示用RAMのアドレスを計算 ****
		; ** 入力 c: 水平位置(0〜5) b: ライン垂直位置 (偶数のみ)
		; ** 出力 r2: RAMアドレス XBNK: 表示用RAMバンク

							; *** 表示用RAMバンクアドレスの判断 ***
		ld		b			; b>=16 のとき next1 へ
		sub		#16			;
		bn		PSW,7,next1	;
		
		mov		#00h,XBNK	; 表示用RAMのバンクアドレスを指定(BANK0)
		br		next2
next1:
		st		b
		mov		#01h,XBNK	; 表示用RAMのバンクアドレスを指定(BANK1)
next2:

							; *** 表示指定位置のRAMアドレス計算 ***
		ld		b			; b * 8 + c + 80h
		rol					;
		rol					;
		rol					;
		add		c			;
		add		#80h		;
		st		r2			; RAMアドレスをr2に格納
				
		ret					; locate終わり


put_chara:
		push	PSW			; PSW値を退避
		set1	PSW,1		; データRAMバンク1を選択

							; *** キャラクタデータアドレスの計算 ***
		rol					; (TRH,TRL) = acc*8 + fontdata
		rol					;
		rol					;	
		add		#low(fontdata)	;
		st		TRL				;
		mov		#0,acc			;
		addc	#high(fontdata)	;
		st		TRH			;

		LcdAccessBegin		; LCDアクセス開始

		ld		pclin		; 表示処理ライン数/2を
		st		c			; ループカウンタへ
		mov		#0,b		; キャラクタデータ読み出し用オフセット値
loop1:
		ld		b			; 1ライン目の表示データを読み出す
		ldc					;
		inc		b			; 読み出しデータのオフセットを +1
		st		@r2			; 表示データを表示用RAMに転送
		ld		r2			; 表示用RAMアドレス +6
		add		#6			;
		st		r2			;

		ld		b			; 2ライン目の表示データを読み出す
		ldc					;
		inc		b			; 読み出しデータのオフセットを +1
		st		@r2			; 表示データを表示用RAMに転送
		ld		r2			; 表示用RAMアドレス +10
		add		#10			;
		st		r2			;
		
		dec		c			; ループカウンタのデクリメント
		ld		c			; 
		bnz		loop1		; 8ライン分(4回)繰り返し
		
		LcdAccessEnd		; LCDアクセス終了

		pop		PSW			; PSW値を復帰

		ret					; put_chara終わり


; *-------------------------------------------------------------------------*
; * 文字ミニフォントの描画													*
; * 入力: b: 左側の文字コード												*
; *		  c: 右側の文字コード												*
; *-------------------------------------------------------------------------*
put_minic:
		mov		#low( font_mc),TRL	; フォントデータの先頭アドレスをTRに
		mov		#high(font_mc),TRH	;

		br		put_mini0

; *-------------------------------------------------------------------------*
; * 数字ミニフォントの描画													*
; * 入力: b: 左側の文字コード												*
; *		  c: 右側の文字コード												*
; *-------------------------------------------------------------------------*
put_mini:
		mov		#low( font_m),TRL	; フォントデータの先頭アドレスをTRに
		mov		#high(font_m),TRH	;

put_mini0:
		push	PSW			; PSW値を退避
		set1	PSW,1		; データRAMバンク1を選択

							; キャラクタデータアドレスの計算(左)
		ld		b			; b = b*8
		rol					;
		rol					;
		rol					;	
		st		b			;

							; キャラクタデータアドレスの計算(右)
		ld		c			; c = c*8
		rol					;
		rol					;
		rol					;	
		st		c			;		

		LcdAccessBegin		; LCDアクセス開始

							;-- 1ライン目
		ld		b			; 1ライン目の表示データを読み出す(左用)
		ldc					;
		and		#0f0h		; 左側データ使用
		st		@r2			; 表示データを表示用RAMに転送
		
		ld		c			; 1ライン目の表示データを読み出す(右用)
		ldc
		and		#00fh		; 右側データ使用
		or		@r2			; 左側表示データとOR表示
		st		@r2			;

		inc		b			; 読み出しデータのオフセットを +1
		inc		c			; 読み出しデータのオフセットを +1

		ld		r2			; 表示用RAMアドレス +6
		add		#6			;
		st		r2			;

							;-- 2ライン目
		ld		b			; 2ライン目の表示データを読み出す(左用)
		ldc					;
		and		#0f0h		; 左側データ使用
		st		@r2			; 表示データを表示用RAMに転送
		
		ld		c			; 2ライン目の表示データを読み出す(右用)
		ldc
		and		#00fh		; 右側データ使用
		or		@r2			; 左側表示データとOR表示
		st		@r2			;

		inc		b			; 読み出しデータのオフセットを +1
		inc		c			; 読み出しデータのオフセットを +1

		ld		r2			; 表示用RAMアドレス +10
		add		#10			;
		st		r2			;

							;-- 3ライン目
		ld		b			; 1ライン目の表示データを読み出す(左用)
		ldc					;
		and		#0f0h		; 左側データ使用
		st		@r2			; 表示データを表示用RAMに転送
		
		ld		c			; 1ライン目の表示データを読み出す(右用)
		ldc
		and		#00fh		; 右側データ使用
		or		@r2			; 左側表示データとOR表示
		st		@r2			;

		inc		b			; 読み出しデータのオフセットを +1
		inc		c			; 読み出しデータのオフセットを +1

		ld		r2			; 表示用RAMアドレス +6
		add		#6			;
		st		r2			;

							;-- 4ライン目
		ld		b			; 2ライン目の表示データを読み出す(左用)
		ldc					;
		and		#0f0h		; 左側データ使用
		st		@r2			; 表示データを表示用RAMに転送
		
		ld		c			; 2ライン目の表示データを読み出す(右用)
		ldc
		and		#00fh		; 右側データ使用
		or		@r2			; 左側表示データとOR表示
		st		@r2			;

		inc		b			; 読み出しデータのオフセットを +1
		inc		c			; 読み出しデータのオフセットを +1

		ld		r2			; 表示用RAMアドレス +10
		add		#10			;
		st		r2			;

							;-- 5ライン目
		ld		b			; 1ライン目の表示データを読み出す(左用)
		ldc					;
		and		#0f0h		; 左側データ使用
		st		@r2			; 表示データを表示用RAMに転送
		
		ld		c			; 1ライン目の表示データを読み出す(右用)
		ldc
		and		#00fh		; 右側データ使用
		or		@r2			; 左側表示データとOR表示
		st		@r2			;

		inc		b			; 読み出しデータのオフセットを +1
		inc		c			; 読み出しデータのオフセットを +1

		ld		r2			; 表示用RAMアドレス +6
		add		#6			;
		st		r2			;
		
		LcdAccessEnd		; LCDアクセス終了

		pop		PSW			; PSW値を復帰

		ret					; put_mini 終わり


; *-------------------------------------------------------------------------*
; * 効果音																	*
; *-------------------------------------------------------------------------*
Eff1:	; ****「ジョロジョロジョロ」****
		mov		#16,acc				; ループカウンタ初期値
		
lp3:								; *** 約342Hz の発音開始 ***
		mov		#0f0h,T1LR			; 周期 = 100h-0f0h = 16
		mov		#0f8h,T1LC			; Lレベル幅 = 100h-0f8h = 8
		mov		#0D4h,T1CNT			; 音声出力開始
		
		push	acc
		call	ewait				; 時間待ち
		pop		acc
									; *** 約781Hz の発音開始 ***
		mov		#0f9h,T1LR			; 周期 = 100h-0f9h = 7
		mov		#0fch,T1LC			; Lレベル幅 = 100h-0fch = 4
		mov		#0D4h,T1CNT			; 音声出力開始

		push	acc
		call	ewait				; 時間待ち
		pop		acc
	
		dbnz	acc,lp3				; 繰り返し

		callo	SndStop				; 発音停止
		
		ret							; Eff1 終了

ewait:	;時間待ち
ew2:	mov		#2,c
ew1:	dbnz	c,ew1
		dbnz	acc,ew2

		ret							; ewait 終了


Eff2:	; ****「ジッ」****
		mov		#0e0h,T1LR			; 周期 = 100h-0e0h = 32
		mov		#0f8h,T1LC			; Lレベル幅 = 100h-0f8h = 8
		mov		#0D4h,T1CNT			; 音声出力開始
		mov		#2,snding			; 音声出力中カウンタセット

		ret							; Eff2終了

Eff3:	; ****「ぶ」****
		mov		#0f0h,T1LR			; 周期 = 100h-0f0h = 16
		mov		#0f8h,T1LC			; Lレベル幅 = 100h-0f8h = 8
		mov		#0D4h,T1CNT			; 音声出力開始
		mov		#1,snding			; 音声出力中カウンタセット

		ret							; Eff3終了


Eff4:	; **** 「ぶぴぶぴ」****
		mov		#6,acc
		
lp5:	push	acc
		mov		#0e5h,T1LR			; 周期 = 100h-0e5h = 27
		mov		#0feh,T1LC			; Lレベル幅 = 100h-0feh = 2
		mov		#0D4h,T1CNT			; 音声出力開始
		
		mov		#8,acc
		callo	bwait				; 時間待ち

		mov		#0f3h,T1LR			; 周期 = 100h-0f3h = 13
		mov		#0f9h,T1LC			; Lレベル幅 = 100h-0f9h = 7
		mov		#0D4h,T1CNT			; 音声出力開始

		mov		#7,acc
		callo	bwait				; 時間待ち
		pop		acc
		
		dbnz	acc,lp5				; ループ

		call	SndStop				; 発音停止
		
		ret							; Eff4終了
		
		
; *-------------------------------------------------------------------------*
; * サウンド出力用時間待ち													*
; * 入力: acc: 待ち時間														*
; *-------------------------------------------------------------------------*
bwait:		
		mov		#16,c
bw1:	dbnz	c,bw1
		dbnz	acc,bwait

		ret							; bwait 終了
		
		
; *-------------------------------------------------------------------------*
; * 音声出力初期化															*
; *-------------------------------------------------------------------------*
SndInit:
		clr1	P1,7			; 音声出力ポートセット
	
		ret						; SndInit 終了


; *-------------------------------------------------------------------------*
; * 音声出力停止															*
; *-------------------------------------------------------------------------*
SndStop:
		mov		#0,T1CNT		; 音声出力停止
		
		ret						; SndStop 終了


; *-------------------------------------------------------------------------*
; * タイマ/カウンタT0 の初期化												*
; *   モード2(16bitカウンタ)で、約0.15秒毎に割り込みをかける				*
; *-------------------------------------------------------------------------*
T0Mode2Init:
		mov		#255,T0PRR	; プリスケーラ値セット
							;   8bitプリスケーラなので
							;   周期 = (256-255)*0.000183 = 0.000183 (sec)
		mov		#high(65536-819),T0HR ; プリセット値(H)セット
		mov		#low(65536-819),T0LR  ; プリセット値(L)セット
							;   プリスケーラとセットで
							;   0.000183 * 819 = 0.149877 (≒0.15sec)
							;   0.15秒毎にオーバーフローが起こる
		mov		#0ffh,T0L	; 最初すぐにオーバーフローするようにする
		mov		#0ffh,T0H	;
		mov		#0e4h,T0CNT	; モード2 (16bitカウンタ)
							; T0Hオーバーフローで割り込みを発生させる
							; T0動作開始
	
		ret					; T0Mode2Init終わり


T0HStop:					; *** T0Hタイマ停止 ***

		clr1	T0CNT,7		; T0Hカウント動作停止
		ret


; *-------------------------------------------------------------------------*
; * タイマT0H割り込みハンドラ												*
; *-------------------------------------------------------------------------*
int_T0H:					; *** T0H割り込みハンドラ ***
		inc		t0flg		; タイマ割り込みフラグセット
		clr1	T0CNT,3		; タイマT0H割り込み要因クリア
		reti


; *-------------------------------------------------------------------------*
; * P3(ボタン操作)割り込みハンドラ部										*
; *-------------------------------------------------------------------------*
int_P3:
		clr1	P3INT,0			; P3割り込みをマスク
		inc		btnflg			; ボタンフラグセット
		clr1	P3INT,1			; P3割り込みフラグクリア
		reti


; *-------------------------------------------------------------------------*
; * ベースタイマ割り込みハンドラ部											*
; *-------------------------------------------------------------------------*
int_BaseTimer:
		bp		sleeping,0,next6 ; sleep中ならすぐ帰る
		
		push	acc				; 使用レジスタを退避
		ld		lefttime		; 残り時間
		bz		next5			; 0ならnext5
		dec		lefttime		; 残り時間をデクリメント
		inc		timechg			; 残り時間変化フラグセット
next5:							;
		pop		acc				; 退避レジスタを復帰		

next6:		
		ret						; (ユーザー側)割り込み処理終了


; *-------------------------------------------------------------------------*
; * キャラクタのビットイメージデータ										*
; *-------------------------------------------------------------------------*
fontdata:
		db	07ch, 0e6h, 0c6h, 0c6h, 0c6h, 0ceh, 07ch, 000h	;0
		db	018h, 038h, 018h, 018h, 018h, 018h, 03ch, 000h	;1
		db	07ch, 0c6h, 0c6h, 00ch, 038h, 060h, 0feh, 000h	;2
		db	07ch, 0e6h, 006h, 01ch, 006h, 0e6h, 07ch, 000h	;3
		db	00ch, 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 000h	;4
		db	0feh, 0c0h, 0fch, 006h, 006h, 0c6h, 07ch, 000h	;5
		db	01ch, 030h, 060h, 0fch, 0c6h, 0c6h, 07ch, 000h	;6
		db	0feh, 0c6h, 004h, 00ch, 018h, 018h, 038h, 000h	;7
		db	07ch, 0c6h, 0c6h, 07ch, 0c6h, 0c6h, 07ch, 000h	;8
		db	07ch, 0c6h, 0c6h, 07eh, 006h, 00ch, 078h, 000h	;9
		
		db	000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h	;:
		db	000h, 000h, 000h, 000h, 000h, 060h, 060h, 000h	;.

		db	000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h	; (null)

		db	0ffh, 052h, 0a5h, 048h, 021h, 000h, 000h, 000h	; 土

		db	%01000010	; モグラ(完全)
		db	%00111100
		db	%01011010
		db	%01011010
		db	%11111111
		db	%01100110
		db	%10111101
		db	%01011010
		
		db	%00010000	; モグラ(やられ)
		db	%00000001
		db	%10100000
		db	%00001000
		db	%01000010
		db	%10111101
		db	%01011110
		db	%11111011
		
		db	%00000000	; モグラ(半分)
		db	%00000000
		db	%00000000
		db	%01000010
		db	%00111100
		db	%01111110
		db	%01011010
		db	%11111111


		; 数字のミニフォント
font_m:	
		db	0eeh, 0aah, 0aah, 0aah, 0eeh, 0,0,0	; 0
		db	022h, 022h, 022h, 022h, 022h, 0,0,0	; 1
		db	0eeh, 022h, 0eeh, 088h, 0eeh, 0,0,0	; 2
		db	0eeh, 022h, 0eeh, 022h, 0eeh, 0,0,0	; 3
		db	0aah, 0aah, 0eeh, 022h, 022h, 0,0,0	; 4
		db	0eeh, 088h, 0eeh, 022h, 0eeh, 0,0,0	; 5
		db	0eeh, 088h, 0eeh, 0aah, 0eeh, 0,0,0	; 6
		db	0eeh, 0aah, 022h, 022h, 022h, 0,0,0	; 7
		db	0eeh, 0aah, 0eeh, 0aah, 0eeh, 0,0,0	; 8
		db	0eeh, 0aah, 0eeh, 022h, 0eeh, 0,0,0	; 9

		; アルファベット文字のミニフォント
font_mc:
		db	000h, 000h, 000h, 000h, 000h, 0,0,0	; 
		db	044h, 0aah, 0aah, 0eeh, 0aah, 0,0,0	; A
		db	0cch, 0aah, 0eeh, 0aah, 0cch, 0,0,0	; B
		db	0eeh, 0aah, 088h, 0aah, 0eeh, 0,0,0	; C
		db	0cch, 0aah, 0aah, 0aah, 0cch, 0,0,0	; D
		db	0eeh, 088h, 0cch, 088h, 0eeh, 0,0,0	; E
		db	0eeh, 088h, 0eeh, 088h, 088h, 0,0,0	; F
		db	066h, 088h, 0aah, 0aah, 066h, 0,0,0	; G
		db	0aah, 0aah, 0eeh, 0aah, 0aah, 0,0,0	; H
		db	0eeh, 044h, 044h, 044h, 0eeh, 0,0,0	; I
		db	0eeh, 022h, 022h, 0aah, 0cch, 0,0,0	; J
		db	0aah, 0aah, 0cch, 0aah, 0aah, 0,0,0	; K
		db	088h, 088h, 088h, 088h, 0eeh, 0,0,0	; L
		db	0aah, 0eeh, 0aah, 0aah, 0aah, 0,0,0	; M
		db	0aah, 0eeh, 0eeh, 0eeh, 0aah, 0,0,0	; N
;		db	044h, 0aah, 0aah, 0aah, 044h, 0,0,0	; O
		db	0eeh, 0aah, 0aah, 0aah, 0eeh, 0,0,0	; O
		db	0eeh, 0aah, 0eeh, 088h, 088h, 0,0,0	; P
		db	044h, 0aah, 0aah, 0cch, 066h, 0,0,0	; Q
;		db	0cch, 0aah, 0cch, 0aah, 0aah, 0,0,0	; R
		db	0eeh, 0aah, 0cch, 0aah, 0aah, 0,0,0	; R
;		db	066h, 088h, 0eeh, 022h, 0cch, 0,0,0	; S
		db	0eeh, 088h, 0eeh, 022h, 0eeh, 0,0,0	; S
		db	0eeh, 044h, 044h, 044h, 044h, 0,0,0	; T
		db	0aah, 0aah, 0aah, 0aah, 0eeh, 0,0,0	; U
		db	0aah, 0aah, 0aah, 0aah, 044h, 0,0,0	; V
		db	0aah, 0aah, 0eeh, 0eeh, 0eeh, 0,0,0	; W
		db	0aah, 0eeh, 044h, 0eeh, 0aah, 0,0,0	; X
		db	0aah, 0aah, 0eeh, 044h, 044h, 0,0,0	; Y
		db	0eeh, 022h, 044h, 088h, 0eeh, 0,0,0	; Z
		db	022h, 044h, 044h, 044h, 022h, 0,0,0	; (
		db	088h, 044h, 044h, 044h, 088h, 0,0,0	; )
		db	000h, 000h, 000h, 011h, 0AAh, 0,0,0	; .,
		db	000h, 000h, 000h, 022h, 044h, 0,0,0	; ,
		db	000h, 044h, 0eeh, 044h, 000h, 0,0,0 ; +		
