;***************************************************
;*         GRAPHIC LIBRALY(NORMAL系)
;*
;*(1)CLS
;*(2)GPRINT
;*(3)SGPRINT(FX-870P専用)BANK1(&H0000～&H1000)の空きメモリにシフト展開済みのキャラクタを転送する
;*(4)SGPRINT_FAST:(3)の高速版、キャラクタ長は8固定、X方向の描画制限以上にも書き込む
;*(5)SGPRINT_4:(3)の幅4高さ2のビットマップデータへ特化。Y軸は偶数しか移動できない。VRAMまたぎをしないので超高速。弾に使用を想定
;*(6)SET_SGPRINT_DATA:FX-870Pの&H0480～&H0FFFまでに1ドットごとシフトしたキャラデータを展開する(最大23個)上段:基準アドレス～+63BYTE,下段:64BYTE～128BYTE
;*(7)CPRINT(X:0-191),(Y:8,16,24,32)指定でキャラクタを通常転送する。同じキャラの繰り返し描画機能あり
;*(8)CPRINT_OR(X:0-191),(Y:8,16,24,32)指定でキャラクタをOR転送する。同じキャラの繰り返し描画機能あり
;*(9)CPRINT_FILL(指定した範囲を指定したPTNでAND,OR,XORする)(Y:8,16,24,32)
;*(10)TEXT;FX-870P専用
;*(11)PSET
;*(12)LINE      ;妖怪ビルディングまで使用していたLINE命令
;*(13)LINE_NEW  ;FX-890Pから移植したLINE命令、PSETのたびにPUSH,POPしない。($7以外のレジスタ,IX,IZを破壊)
;*(14)BTOB(2BYTEの2進数を10進数に変換表示:0～65535)
;*(15)BTOB256(2進数を10進数に変換表示:0～255)
;*(16)R2D(2次元回転)
;*(17)GET_BMP_PIXCEL(BMPの(X,Y)座標のデータの有無を調べる)
;*(18)CROSS_Y_ANS_X(指定した直線が指定したYで交わる時のX座標を算出する)
;*(19)ROTATE_BMP(ビットマップを回転させる:Y<0で暴走はしないが反応しなくなるので注意)
;*(20)PAINT_SQUARE(四角形の塗りつぶし:画面外に描画すると暴走はしないが反応しなくなるので注意)
;*(21)LINE_HORIZON8(横位置が8の倍数の位置間で線を引く)
;***************************************************

;*************************************
;*             CPRINT_FILL
;*PARA:
;*      $10     X(0-&HC0)
;*      $11     Y(8,16,24,32 ONLY)
;*      $12     CHARACTOR LENGTH
;*      $13     DATA PTN
;*      $15     MODE(&H80:NORM &HA0:OR &H20:XR)
;*WORK  $0      WORK
;*      $1      WORK
;*      $2      WORK
;*      $3      WORK
;*************************************
CPRINT_FILL:

SBC $12,$31
RTN Z

LDW $0,0

BID $11
BID $11
BID $11
SB $11,$30
JR Z,CPRF_Y_SET_END

LDW $2,&HC0

CPRF_Y_SET_LOOP:
ADW $0,$2
SB $11,$30
JR NZ,CPRF_Y_SET_LOOP

CPRF_Y_SET_END:

LDW $2,LEDTP0
ADW $0,$2

;BYTE X -> WORD X
LD $11,$31
ADW $0,$10

PRE IX,$0
SB $12,$30

CPRINT_FILL_LP:

SBC $15,&H80
JR Z,CPRINT_FILL_NORM
SBC $15,&H20
JR Z,CPRINT_FILL_XOR
LD $0,(IX+$12)
OR $0,$13
ST $0,(IX+$12)
JR NEXT_CPRINT_FILL
CPRINT_FILL_NORM:
ST $13,(IX+$12)
JR NEXT_CPRINT_FILL
CPRINT_FILL_XOR:
LD $0,(IX+$12)
XR $0,$13
ST $0,(IX+$12)

NEXT_CPRINT_FILL:
SB $12,$30
JR NC,CPRINT_FILL_LP
RTN

;**********************************
;*      SET_SGPRINT_DATA
;*PARA: $0,$1   - NO(0-31)
;*      $2,$3   - CHARACTOR DATA ADRESS(8*8 BITMAP)
;*WORK:
;*      IX      - キャラクタの読み込みアドレス
;*      IZ      - キャラクタの書き込みアドレス
;**********************************

MK_SG_CLR:DB 0,0,0,0,0,0,0,0

SET_SGPRINT_DATA:

PRE IX,MK_SG_CLR
LDM $20,(IX+$31),8

;格納先アドレスの算出。1キャラ128BYTEなのでキャラ番号を128倍する
BIUW $0;2
BIUW $0;4
BIUW $0;8
BIUW $0;16
BIUW $0;32
BIUW $0;64
BIUW $0;128

LDW $4,SG_CHR_DATA00
ADW $0,$4

PHUW $1

;キャラクタの読み込みアドレス設定
PRE IX,$2

;キャラクタの書き込みアドレスの設定
PRE IZ,$0

LD $19,64;下段書き込み用

;0DOT SHIFT
LDM $0,(IX+$31),8
STM $0,(IZ+$31),8       ;上段
STM $20,(IZ+$19),8     ;下段

PPUW $20
LDW $18,8
ADW $20,$18
LDW $22,$20
LDW $18,64
ADW $22,$18

PRE IX,$20;上段書き込み用
PRE IZ,$22;下段書き込み用

;データをレジスタに展開・初期化
LD $15,$7
LD $14,$31
LD $13,$6
LD $12,$31
LD $11,$5
LD $10,$31
LD $9,$4
LD $8,$31
LD $7,$3
LD $6,$31
LD $5,$2
LD $4,$31
LD $3,$1
LD $2,$31
LD $1,$0
LD $0,$31

LD $18,7  ;データ読み込みカウンタ


MSGDATA_LOOP:
BIDW $1
BIDW $3
BIDW $5
BIDW $7
BIDW $9
BIDW $11
BIDW $13
BIDW $15

STI $0,(IZ+$31)
STI $1,(IX+$31)
STI $2,(IZ+$31)
STI $3,(IX+$31)
STI $4,(IZ+$31)
STI $5,(IX+$31)
STI $6,(IZ+$31)
STI $7,(IX+$31)
STI $8,(IZ+$31)
STI $9,(IX+$31)
STI $10,(IZ+$31)
STI $11,(IX+$31)
STI $12,(IZ+$31)
STI $13,(IX+$31)
STI $14,(IZ+$31)
STI $15,(IX+$31)

SB $18,$30
JR NZ,MSGDATA_LOOP
RTN

;************************************************************
; SGPRINT_FAST
; 　LCD(0,0)がこのサブルーチンでは(0,8)となる。
;   Y座標は画面外に書き込まない処理を行っている。
;   X座標の描画制限を無視したい場合は、このサブルーチン内のSGPRINT_FAST_NCを呼び出すこと。
;   キャラクタ長は8固定でGPRINT_XMAX(定数)を超える部分も描画する。
;
;   処理は最上段(キャラクタをBYTE SHFIT)と最下段(キャラクタをBYTE SHFIT)、
;   行をまたぐためキャラクタをWORD SHIFTする場合の3つに分けて行っている。
;   また、高速化のためY座標が８の倍数の場合は、キャラのシフトを行わない処理を行っている。
;
; PARAMETER
;  $10       キャラのX座標
;  $11       キャラのY座標
;  $12       キャラの長さ
;  $13-$14   キャラのアドレス
;
; WORK
;  $0        カウンタ
;  $15-$16   LEDTPのアドレス（LEDTP0:&H6201、LEDTP1:&H62C1・・）
;  $17-$18   LEDTP+192(LCDをまたぐ際の下段LCDのアドレス）
;  $19-$20   キャラシフト用ワーク
;  $21       レジスタ退避用
;  $22-$23   またぐ場合：2バイト足し算（ADW $R+$22)
;            またがない場合（LCDLINE1）：ワーク
;  $24       OR転送用ワーク
;  IX        CHR ADRESS
;  IZ        BASE LEDTP ADRESS
;************************************************************

SGPRINT_FAST:

;X軸チェック
;キャラのX座標>GPRINT_XMAXなら描画範囲外なので戻る
SBC $10,D_GPRINT_XMAX
RTN NC

SGPRINT_FAST_NC:

;Y軸チェック

;キャラのY座標=0なら描画範囲外なので戻る
SBC $11,$31 ;$31=0
RTN Z

;キャラのY座標>40なら描画範囲外なので戻る
SBC $11,40
RTN NC

;  Y<7ならLINE0のみの描画処理
SGF_LINE_0:
SBC $11,8
JR NC,SGF_LINE_0_1
LDW $26,LEDTP0
JR SGF_DRAW1

;  8<Y<15ならLINE0とLINE1のまたぎ描画処理
SGF_LINE_0_1:
SB $11,8
SBC $11,8
JR NC,SGF_LINE_1_2
LDW $26,LEDTP0
JP SGF_DRAW0_3 ;JRは使用不能

;  16<Y<24ならLINE1とLINE2のまたぎ描画処理
SGF_LINE_1_2:
SB $11,8
SBC $11,8
JR NC,SGF_LINE_2_3
LDW $26,LEDTP1
JP SGF_DRAW0_3

;  24<Y<32ならLINE2とLINE3のまたぎ描画処理
SGF_LINE_2_3:
SB $11,8
SBC $11,8
JR NC,SGF_LINE_4
LDW $26,LEDTP2
JR SGF_DRAW0_3

;  32<Y<40ならLINE3のみの描画処理
SGF_LINE_4:
SB $11,8
LDW $26,LEDTP3

;************************
;境界をまたがないLCD最下段の描画
;************************
SGF_DRAW4:

;キャラクターの読み込みアドレスを算出する
CAL SUB_SGPRINT_CALC

;書き込みアドレスの算出
LD $2,$10
LD $3,$31
ADW $26,$2;LEDTPX+X座標
;書き込みアドレスをIZに設定
PRE IZ,$26

;$0-$7  読み込みキャラクタデータ
;$8-$15 背景データ
;IX     読み込みキャラクタデータ
;IZ     書き込みアドレス

;キャラクタデータを$0-$7に読み込む
LDM $0,(IX+$31),8

;VRAMデータを$8-$14に読み込む
LDM $8,(IZ+$31),8

JP SGF_DATA_PROC
;RTN

;************************
;境界をまたがないLCD最上段の描画
;************************
SGF_DRAW1:

;キャラクターの読み込みアドレスを算出する
CAL SUB_SGPRINT_CALC

;読み込みキャラクタのアドレスを+64(8BYTE×8キャラ)して下段のキャラに設定
LDW $0,64
ADW $22,$0
;読み込みキャラクタのアドレスをIXに設定
PRE IX,$22

;$0-$7  読み込みキャラクタデータ
;$8-$15 背景データ
;IX     読み込みキャラクタデータ
;IZ     書き込みアドレス

;書き込みアドレスの算出
LD $2,$10
LD $3,$31
ADW $26,$2;LEDTPX+X座標

;書き込みアドレスをIZに設定
PRE IZ,$26

JR SGF_DATA_PROC

;RTN

;************************
;境界をまたぐ描画
;************************
SGF_DRAW0_3:

CAL SUB_SGPRINT_CALC

;読み込みキャラクタ(下段)のアドレスを+64(8BYTE×8キャラ)に設定
LDW $24,$22
LDW $0,64
ADW $24,$0

;書き込みアドレス(上段)の算出
LD $2,$10
LD $3,$31
ADW $26,$2;LEDTPX+X座標

;書き込みアドレス(下段)の算出
LDW $28,$26
LDW $0,192;NEXT VRAM
ADW $28,$0

;$0-$7  読み込みキャラクタデータ
;$8-$15 背景データ
;IX     読み込みキャラクタデータ
;IZ     書き込みアドレス

;読み込みキャラクタ(上段)のアドレスをIXに設定
PRE IX,$22
;書き込みアドレス(上段)をIZに設定
PRE IZ,$26

;キャラクタ(上段)を$0-$7に読み込む
LDM $0,(IX+$31),8

;下段のVRAMデータ(上段)を$8-$14に読み込む
CAL SGF_DATA_PROC

;読み込みキャラクタ(下段)のアドレスをIXに設定
PRE IX,$24
;書き込みアドレス(下段)をIZに設定
PRE IZ,$28

JR SGF_DATA_PROC

;RTN

;******************************
;*PARA
;* IX   - CHARACTOR DATA ASRESS
;* IZ   - VRAM ADRESS
;*WORK
;* $0-$7  - CHARACTOR DATA
;* $8-$15 - VRAM DATA
;******************************

SGF_DATA_PROC:

;キャラクタ(上段)を$0-$7に読み込む
LDM $0,(IX+$31),8

;VRAMデータ(上段)を$8-$14に読み込む
LDM $8,(IZ+$31),8

;キャラと背景のOR(8BYTE)をとる
ORM $0,$8,8

;VRAMデータ(上段)に書き込む
STM $0,(IZ+$31),8

RTN

;************************************************************
; SGPRINT_4
; 　LCD(0,0)がこのサブルーチンでは(0,8)となる。
;   キャラは4×2固定
;   キャラはY座標が2ドットごと4段階の16×8のビットマップを用意すること
;   Y方向の移動は偶数しか出来ない。
;   Y座標は画面外に書き込まない処理を行う。
;   X座標についてはGPRINT_XMAX(定数)を超える部分は描画しない処理を行う。
;
;    0123456789012345
;0   ■■■■
;1   ■■■■
;2       ■■■■
;3       ■■■■
;4           ■■■■
;5           ■■■■
;6               ■■■■
;7               ■■■■
;
;   DB &HC0,&HC0,&HC0,&HC0,&H30,&H30,&H30,&H30
;   DB &H0C,&H0C,&H0C,&H0C,&H03,&H03,&H03,&H03

;
; PARAMETER
;  $10       キャラのX座標
;  $11       キャラのY座標
;  $13-$14   キャラのアドレス
;
; USE
;  $17       キャラの長さ(強制的に4)
; WORK
;  $0        カウンタ
;  $9        WORK
;  $12       WORK
;  $15-$16   LEDTPのアドレス（PB-1000 LEDTP0:&H6201、LEDTP1:&H62C1・・）
;  IX        CHR ADRESS
;  IZ        BASE LEDTP ADRESS
;************************************************************

SGPRINT_4:

;キャラの長さを4に設定する
LD $17,3    ;キャラの長さが4の場合3

;Y軸チェック

;キャラのY座標<8なら描画範囲外なので戻る
SBC $11,8
RTN C

;キャラのY座標>40なら描画範囲外なので戻る
SBC $11,40
RTN NC

;X軸チェック
;キャラのX座標>GPRINT_XMAXなら描画範囲外なので戻る
SBC $10,D_GPRINT_XMAX
RTN NC

;キャラのX座標+キャラの長さ>GPRINT_XMAXならキャラの長さを調節して、
;描画するキャラがGPRINT_XMAXからはみ出ないようにする。
LD $0,$10
AD $0,$17
SBC $0,D_GPRINT_XMAX
JR C,SG4_DRAW
LD $17,D_GPRINT_XMAX
SB $17,$10 ;キャラの長さ=GPRINT_XMAX-キャラのX座標

;************************
;       描画
;************************
SG4_DRAW:

;VRAM書き込みアドレスの算出
SBC $11,16
JR C,SG4_L0
SBC $11,24
JR C,SG4_L1
SBC $11,32
JR C,SG4_L2
LDW $0,LEDTP3;&H147C
JR SG4_SET_VRAM

SG4_L0:
LDW $0,LEDTP0;&H123C
JR SG4_SET_VRAM

SG4_L1:
LDW $0,LEDTP1;&H12FC
JR SG4_SET_VRAM

SG4_L2:
LDW $0,LEDTP2;&H13BC

SG4_SET_VRAM:
PHU $11
LD $11,$31
ADW $0,$10;LEDTPx+X座標
PRE IZ,$0
PPU $11

;キャラクタデータ読み込みアドレス設定
;キャラのY座標は偶数しか設定できない
AN $11,&H06
BIU $11

LD $12,$31

ADW $13,$11
PRE IX,$13

SG4_LOOP:
;キャラクタを$0に読み込む
LD $0,(IX+$17)
;OR転送
LD $1,(IZ+$17)
OR $0,$1
ST $0,(IZ+$17)
;$17:キャラクタの長さ
SB $17,$30
JR NC,SG4_LOOP
RTN

;;************************************************************
; SGPRINT
; 　LCD(0,0)がこのサブルーチンでは(0,8)となる。
;   Y座標は画面外に書き込まない処理を行っている。
;   X座標についてはGPRINT_XMAX(定数)を超える部分は描画しない処理を行っている。
;   X座標の描画制限を無視したい場合は、このサブルーチン内のGPRINT_NO_CHECKを呼び出すこと。
;
;   処理は最上段(キャラクタをBYTE SHFIT)と最下段(キャラクタをBYTE SHFIT)、
;   行をまたぐためキャラクタをWORD SHIFTする場合の3つに分けて行っている。
;   また、高速化のためY座標が８の倍数の場合は、キャラのシフトを行わない処理を行っている。
;
; PARAMETER
;  $10       キャラのX座標
;  $11       キャラのY座標
;  $12       キャラの長さ
;  $13-$14   キャラのアドレス
;
; WORK
;  $0        カウンタ
;  $1        SGPRINT_MAX読み込み用
;  $15-$16   LEDTPのアドレス（LEDTP0:&H6201、LEDTP1:&H62C1・・）
;  $17-$18   LEDTP+192(LCDをまたぐ際の下段LCDのアドレス）
;  $19-$20   キャラシフト用ワーク
;  $21       レジスタ退避用
;  $22-$23   またぐ場合：2バイト足し算（ADW $R+$22)
;            またがない場合（LCDLINE1）：ワーク
;  $24       OR転送用ワーク
;  IX        CHR ADRESS
;  IZ        BASE LEDTP ADRESS
;************************************************************
SGPRINT:

;キャラの読み込みカウンタとして活用するため1減じる。減じない場合は読み込むデータのアドレスが1ドット分プラスになる
;8ドットのキャラなら(IX+0～7)なので、減じないと(IX+1～8)になりずれる
SB $12,$30

;X-LEN<7なら戻る
AN $12,7
RTN C

;X軸チェック
;キャラのX座標>GPRINT_XMAXなら描画範囲外なので戻る
PRE IX,SGPRINT_XMAX
LD $1,(IX+$31)
SBC $10,$1
RTN NC

;X+LEN>GPRINT_XMAXなら長さを>GPRINT_XMAXまでに変更する
LD $0,$10
AD $0,$12
;RTN C ;x+LEN>&FF RANGE OVER
SBC $0,$1
JR C,SGPRINT_NC
LD $12,$1
SB $12,$10

SGPRINT_NC:

;Y軸チェック

;キャラのY座標=0なら描画範囲外なので戻る
SBC $11,$31 ;$31=0
RTN Z

;キャラのY座標>40なら描画範囲外なので戻る
SBC $11,40
RTN NC

;  Y<7ならLINE0のみの描画処理
SG_LINE_0:
SBC $11,8
JR NC,SG_LINE_0_1
LDW $26,LEDTP0
JR SG_DRAW1

;  8<Y<15ならLINE0とLINE1のまたぎ描画処理
SG_LINE_0_1:
SB $11,8
SBC $11,8
JR NC,SG_LINE_1_2
LDW $26,LEDTP0
JP SG_DRAW0_3 ;JRは使用不能

;  16<Y<24ならLINE1とLINE2のまたぎ描画処理
SG_LINE_1_2:
SB $11,8
SBC $11,8
JR NC,SG_LINE_2_3
LDW $26,LEDTP1
JP SG_DRAW0_3

;  24<Y<32ならLINE2とLINE3のまたぎ描画処理
SG_LINE_2_3:
SB $11,8
SBC $11,8
JR NC,SG_LINE_4
LDW $26,LEDTP2
JR SG_DRAW0_3

;  32<Y<40ならLINE3のみの描画処理
SG_LINE_4:
SB $11,8
LDW $26,LEDTP3

;************************
;境界をまたがないLCD最下段の描画
;************************
SG_DRAW4:

;キャラクターの読み込みアドレスを算出する
CAL SUB_SGPRINT_CALC

;書き込みアドレスの算出
LD $2,$10
LD $3,$31
ADW $26,$2;LEDTPX+X座標
;書き込みアドレスをIZに設定
PRE IZ,$26

;$0-$7  読み込みキャラクタデータ
;$8-$15 背景データ
;IX     読み込みキャラクタデータ
;IZ     書き込みアドレス

SG_LOOP4:
;キャラクタを$0に読み込む
LD $0,(IX+$12)
;上段のみの書き込み
LD $1,(IZ+$12)
OR $0,$1
ST $0,(IZ+$12)
;$12:キャラクタの長さ
SB $12,$30
JR NC,SG_LOOP4

RTN

;************************
;境界をまたがないLCD最上段の描画
;************************
SG_DRAW1:

;キャラクターの読み込みアドレスを算出する
CAL SUB_SGPRINT_CALC

;読み込みキャラクタのアドレスを+64(8BYTE×8キャラ)して下段のキャラに設定
LDW $0,64
ADW $22,$0
;読み込みキャラクタのアドレスをIXに設定
PRE IX,$22

;$0-$7  読み込みキャラクタデータ
;$8-$15 背景データ
;IX     読み込みキャラクタデータ
;IZ     書き込みアドレス

;書き込みアドレスの算出
LD $2,$10
LD $3,$31
ADW $26,$2;LEDTPX+X座標

;書き込みアドレスをIZに設定
PRE IZ,$26


SG_LOOP1:
;キャラクタを$0に読み込む
LD $0,(IX+$12)
;下段のみの書き込み
LD $1,(IZ+$12)
OR $0,$1
ST $0,(IZ+$12)
;$12:キャラクタの長さ
SB $12,$30
JR NC,SG_LOOP1
RTN

;************************
;境界をまたぐ描画
;************************
SG_DRAW0_3:

CAL SUB_SGPRINT_CALC

;読み込みキャラクタ(下段)のアドレスを+64(8BYTE×8キャラ)に設定
LDW $24,$22
LDW $0,64
ADW $24,$0

;書き込みアドレス(上段)の算出
LD $2,$10
LD $3,$31
ADW $26,$2;LEDTPX+X座標

;書き込みアドレス(下段)の算出
LDW $28,$26
LDW $0,192;NEXT VRAM
ADW $28,$0

;$0-$7  読み込みキャラクタデータ
;$8-$15 背景データ
;IX     読み込みキャラクタデータ
;IZ     書き込みアドレス

SG_LOOP1_3:

;読み込みキャラクタ(上段)のアドレスをIXに設定
PRE IX,$22
;書き込みアドレス(上段)をIZに設定
PRE IZ,$26

;キャラクタ(上段)を$0に読み込む
LD $0,(IX+$12)
;下段のVRAMデータ(上段)を$1に読み込む
LD $1,(IZ+$12)
OR $0,$1
ST $0,(IZ+$12)

;読み込みキャラクタ(下段)のアドレスをIXに設定
PRE IX,$24
;書き込みアドレス(下段)をIZに設定
PRE IZ,$28

;キャラクタ(下段)を$0に読み込む
LD $0,(IX+$12)
;下段のVRAMデータ(下段)を$1に読み込む
LD $1,(IZ+$12)
OR $0,$1
ST $0,(IZ+$12)

;$12:キャラクタの長さ
SB $12,1
JR NC,SG_LOOP1_3

RTN

;**********************************
;*PARA
;* $11      - キャラクタのシフト量
;* $13,$14  - キャラクタデータの先頭アドレス
;*USE
;* $0
;* $1
;*RTN
;* IX       - READ CHARACTOR ADRESS
;* $22,$23  - READ CHARACTOR ADRESS
;**********************************

;$22,$23 読み込みキャラクタデータ(上段)
;$24,$25 読み込みキャラクタデータ(下段)(ここでは未使用)
;$26,$27 書き込みアドレス(上段)
;$28,$29 書き込みアドレス(下段)(ここでは未使用)
;IX      読み込みキャラクタデータ
;IZ      書き込みアドレス

SUB_SGPRINT_CALC:
LDW $22,$13
;シフト済みキャラクタの読み込みアドレスの算出
LD $1,$31
LD $0,$11
;シフトする量を8倍する
BIU $0
BIU $0
BIU $0
ADW $22,$0
;読み込みキャラクタのアドレスをIXに設定
PRE IX,$22
RTN

;*********************************
;*           CPRINT
;*PARA:
;*      $10     X(0-191)
;*      $11     Y(8の倍数:8,16,24,32,40)
;*      $12     LENGTH(8の倍数以外は動作保証しない)
;*      $13,$14 CHARACTOR ADRESS
;*      $15     LOOP(&HFF=LOOP指定):同じキャラクタを繰り返して表示
;*********************************
CPRINT:

AN $12,&HF8
RTN Z

SB $11,8 ;GPRINT座標系は左上が(0,8)なので、Y座標から8を引き座標系を(0,0)にする

LDW $0,LEDTP0
LDW $2,192
SET_LEDTOPLOOP:
SB $11,8
JR C,SET_CPRINT
ADW $0,$2
JR SET_LEDTOPLOOP

SET_CPRINT:
LD $11,$31
ADW $0,$10

PRE IX,$0
PRE IZ,$13

SBC $15,&HFF
JR Z,C_PRINTLOOP_REP

C_PRINTLOOP:
LDIM $0,(IZ+$31),8
STIM $0,(IX+$31),8
SB $12,8
RTN Z ;SBC $12,$30 ;調整
JR C_PRINTLOOP

C_PRINTLOOP_REP:
LDM $0,(IZ+$31),8
C_PRINTLOOP_REPL:
STIM $0,(IX+$31),8
SB $12,8
RTN Z ;SBC $12,$30 ;調整
JR C_PRINTLOOP_REPL

;*********************************
;*           CPRINT_OR
;*PARA:
;*      $10     X(0-191)
;*      $11     Y(8の倍数:8,16,24,32,40)
;*      $12     LENGTH(8の倍数以外は動作保証しない)
;*      $13,$14 CHARACTOR ADRESS
;*      $15     LOOP(&HFF=LOOP指定):同じキャラクタを繰り返して表示
;*********************************
CPRINT_OR:

AN $12,&HF8
RTN Z

SB $11,8 ;GPRINT座標系は左上が(0,8)なので、Y座標から8を引き座標系を(0,0)にする

LDW $0,LEDTP0
LDW $2,192
SET_LEDTOPLP_OR:
SB $11,8
JR C,SET_C_PRINT_OR
ADW $0,$2
JR SET_LEDTOPLP_OR

SET_C_PRINT_OR:
LD $11,$31
ADW $0,$10

PRE IX,$0
PRE IZ,$13

SBC $15,&HFF
JR Z,C_PRTOR_LOOP_REP

C_PRINT_OR_LOOP:
LDIM $0,(IZ+$31),8
LDM $20,(IX+$31),8
ORM $20,$0,8
STIM $20,(IX+$31),8
SB $12,8
RTN Z ;SBC $12,$30 ;調整
JR C_PRINT_OR_LOOP

C_PRTOR_LOOP_REP:
LDM $0,(IZ+$31),8
C_PRTOR_LOOPREPL:
LDM $20,(IX+$31),8
ORM $20,$0,8
STIM $20,(IX+$31),8
SB $12,8
RTN Z ;SBC $12,$30 ;調整
JR C_PRTOR_LOOPREPL

;*********************************
;*             CLS
;*USE:  $27,$28 IOCS(CLEDB)アドレス
;*********************************
CLS:
LDW $28,CLEDB ;**************(機種依存)
CAL IOCS_CAL
RTN

;************************************************************
; GPRINT
; 　LCD(0,0)がこのサブルーチンでは(0,8)となる。
;   Y座標は画面外に書き込まない処理を行っている。
;   X座標についてはGPRINT_XMAX(定数)を超える部分は描画しない処理を行っている。
;   X座標の描画制限を無視したい場合は、このサブルーチン内のGPRINT_NO_CHECKを呼び出すこと。
;
;   処理は最上段(キャラクタをBYTE SHFIT)と最下段(キャラクタをBYTE SHFIT)、
;   行をまたぐためキャラクタをWORD SHIFTする場合の3つに分けて行っている。
;   また、高速化のためY座標が８の倍数の場合は、キャラのシフトを行わない処理を行っている。
;
; PARAMETER
;  $10       キャラのX座標
;  $11       キャラのY座標
;  $12       キャラの長さ
;  $13-$14   キャラのアドレス
;
; WORK
;  $0        カウンタ
;  $1        GPRINT_XMAX読み込み用
;  $15-$16   LEDTPのアドレス（LEDTP0:&H6201、LEDTP1:&H62C1・・）
;  $17-$18   LEDTP+192(LCDをまたぐ際の下段LCDのアドレス）
;  $19-$20   キャラシフト用ワーク
;  $21       レジスタ退避用
;  $22-$23   またぐ場合：2バイト足し算（ADW $R+$22)
;            またがない場合（LCDLINE1）：ワーク
;  $24       OR転送用ワーク
;  IX        CHR ADRESS
;  IZ        BASE LEDTP ADRESS
;************************************************************

GPRINT:

;横幅が0なら戻る
SBC $12,0
RTN Z

;Y軸チェック

;キャラのY座標=0なら描画範囲外なので戻る
SBC $11,$31 ;$31=0
RTN Z

;キャラのY座標>40なら描画範囲外なので戻る
SBC $11,40
RTN NC

;X軸チェック
;キャラのX座標>GPRINT_XMAXなら描画範囲外なので戻る
PRE IX,GPRINT_XMAX
LD $1,(IX+$31)
SBC $10,$1
RTN NC

;キャラのX座標+キャラの長さ>GPRINT_XMAXなら、キャラの長さを調節して
;描画するキャラがGPRINT_XMAXからはみ出ないようにする。
LD $0,$10
AD $0,$12
SBC $0,$1
JR C,LINE_0
LD $12,$1
SB $12,$10 ;キャラの長さ=GPRINT_XMAX-キャラのX座標

GPRINT_NO_CHECK:

;  Y<8ならLINE0のみの描画処理
LINE_0:
SBC $11,8
JR NC,LINE_0_1
JR DRAW1

;  8<Y<16ならLINE0とLINE1のまたぎ描画処理
LINE_0_1:
SB $11,8
SBC $11,8
JR NC,LINE_1_2
LDW $15,LEDTP0
JP Z,LINE_NOSHIFT  ;Y座標が8の倍数(8)の処理
JP DRAW0_3 ;JRは使用不能

;  16<Y<24ならLINE1とLINE2のまたぎ描画処理
LINE_1_2:
SB $11,8
SBC $11,8
JR NC,LINE_2_3
LDW $15,LEDTP1
JP Z,LINE_NOSHIFT  ;Y座標が8の倍数(16)の処理
JP DRAW0_3

;  24<Y<32ならLINE2とLINE3のまたぎ描画処理
LINE_2_3:
SB $11,8
SBC $11,8
JR NC,LINE_4
LDW $15,LEDTP2
JP Z,LINE_NOSHIFT  ;Y座標が8の倍数(24)の処理
JR DRAW0_3

;  32<Y<40ならLINE3のみの描画処理
LINE_4:
SB $11,8
LDW $15,LEDTP3
JP Z,LINE_NOSHIFT  ;Y座標が8の倍数(32)の処理

;************************
;境界をまたがないLCD最下段の描画
;************************
DRAW4:
LD $0,$31 ;$31=0 COUNTER=0

PRE IX,$13 ;キャラのアドレス
PRE IZ,LEDTP3

LOOP4:
LD $21,$11 ;$11はY-(8*n)の余りあまりなので
;キャラクタを何ビットシフトするのかを決める値

LD $20,(IX+$0) ;$0=COUNTER

   SBC $21,$31
   JR Z,NO_SHIFT4

    CHRSHFT4:
    BID $20
    SB $21,$30 ;$30=1
    JR NZ,CHRSHFT4

NO_SHIFT4:
PHU $0
AD $0,$10 ;X座標を追加

LD $24,(IZ+$0)
OR $20,$24;OR転送
ST $20,(IZ+$0)
PPU $0

AD $0,$30 ;$30=1
SBC $0,$12
JR NZ,LOOP4
RTN

;************************
;境界をまたがないLCD最上段の描画
;************************
DRAW1:
LD $0,$31 ;$31=0 COUNTER=0

PRE IX,$13 ;キャラのアドレス
PRE IZ,LEDTP0

LOOP1:
LD $21,$11 ;$11はY-(8*n)の余りあまりなので
;キャラクタを何ビットシフトするのかを決める値

LD $20,(IX+$0) ;$0=COUNTER

;LCDLINE1だけはSHIFTを逆にしているので8から
;SHIFT量を減算して調整する

;また8だとキャラが消えてしまうので8の場合はSHIFT
;はしない
LD $22,8
SB $22,$21
JR Z,N_SHIFT1

    CHRSHFT1:
    BIU $20
    SB $22,$30 ;$30=1
    JR NZ,CHRSHFT1

N_SHIFT1:
PHU $0
AD $0,$10 ;X座標を追加

LD $24,(IZ+$0)
OR $20,$24;OR転送
ST $20,(IZ+$0)
PPU $0

AD $0,$30 ;$30=1
SBC $0,$12
JR NZ,LOOP1
RTN

;************************
;境界をまたぐ描画
;************************
DRAW0_3:
LD $0,$31 ;$31=0 COUNTER=0
LDW $22,&HC0

;PRE IX,$13 ;キャラのアドレス
PRE IZ,$15 ;描画するLCDの上段アドレス

LOOP0_3:
LD $21,$11 ;$11はY-(8*n)の余りあまりなので
;キャラクタを何ビットシフトするのかを決める値

PRE IX,$13 ;キャラのアドレス

LD $20,(IX+$0) ;$0=COUNTER
LD $19,$31 ;$31=0 キャラシフトに2バイト使用するので下位ビットをクリアする

    SBC $21,$31
    JR Z,NO_SHIFTE

    CHRSHFTE:
    BIDW $20
    SB $21,$30 ;$30=1
    JR NZ,CHRSHFTE

NO_SHIFTE:

;$17に下段のLCDアドレスを設定$15(LCD上段アドレス＋192
LDW $17,$15
ADW $17,$22;$22=&HC0

PRE IX,$17

PHU $0
AD $0,$10 ;X座標を追加
LD $24,(IZ+$0)
OR $20,$24;OR転送
ST $20,(IZ+$0);上段の描画

LD $24,(IX+$0)
OR $19,$24;OR転送
ST $19,(IX+$0);下段の描画
PPU $0

AD $0,$30 ;$30=1
SBC $0,$12
JR NZ,LOOP0_3
RTN

LINE_NOSHIFT:

LD $11,$31
ADW $15,$10

SET_CPRINT_OR:

PRE IX,$15
PRE IZ,$13

C_PRINTLOOP_OR:
SB $12,$30
RTN C
LD $0,(IZ+$12)
LD $1,(IX+$12)
OR $0,$1
ST $0,(IX+$12)
JR C_PRINTLOOP_OR

;************************************
;*              TEXT
;*
;* D_TEXTと比べ、$28,$29,IZが破壊される
;* DOTMKを呼び出すため$0～$11,IX,IZも破壊される
;*
;*PARA:
;*      $10 X
;*      $11 Y
;*      $12 LENGTH
;*      $13,$14 DATA ADRESS
;*USE:
;*      $0 CHARACTOR DATA
;*      $1 WORK
;*      $2 WORK/LEDTOP WORK
;*      $3 WORK/LEDTOP WORK
;*      $4 WORK
;*      $28,$29 IOCS ADRESS(DOTMK)
;*      IX DATA READ INDEX
;*      IZ DATA STORE INDEX
;************************************
TEXT:

;文字の長さが0なら戻る
SBC $12,$31
RTN Z

PRE IX,$13

;文字表示座標をEDTOP0+(Y*32+X)を計算する
DIU $11 ;Y*16
BIU $11 ;Y*2
AD $10,$11 ;カーソル開始位置
LD $11,$10;X_START+LEN
AD $11,$12
SB $11,$30

;$10 EDTOP START
;$11 EDTOP END

LD $0,$10
LD $1,$31

LDW $20,EDTOP0
ADW $0,$20
PRE IZ,$0

LD $1,$31

TEXT_LOOP:
LD $0,(IX+$1)
ST $0,(IZ+$1)
AD $1,$30
SBC $1,$12
JR Z,@DOTMK
JR TEXT_LOOP

@DOTMK:
;-----------------------------------------------------
; debug FX-870P/VX-4のDOTMK(977F)は仕様が違う事が判明。
; こたちゃん氏の解析では$10､$11に表示開始/終了位置を
; 指定するが、正しく動作するのは$10=0の場合のみとなる。
; PB-1000/Cと同様に$10を正しく利用できるようにするには、
; 呼出しアドレスをDOTMK+4にして$2,$3にLEDTP指定が必要。
; VX-3も同様。
;-----------------------------------------------------

LD $0,$10      ;$0=カーソル開始位置($10)
LD $1,$31   ;
;-----------------------------------------------------
; $2,$3 = LEDTPアドレス(開始位置)設定
;-----------------------------------------------------
BIUW $0         ;2倍を作成
LDW $4,$0       ;2倍を保存
BIUW $0         ;4倍を作成
ADW $0,$4       ;4倍+2倍=6倍にする
LDW $2,LEDTP0   ;LEDTPアドレスを加える
ADW $2,$0       ;$2,$3=LEDTP+$10*6

LDW $28,DOTMK   ;DOTMK指定
JP IOCS_CAL

RTN




