; IPL command hipl equ 0fe03h ; IPLコマンドフックアドレス frmqnt equ 542fh ; 式を2バイト整数で評価 chput equ 0a2h ; 1文字出力 chrgtr equ 4666h ; コマンドラインから1文字取り出す snsmat equ 0141h ; キーマトリックスのスキャン kilbuf equ 0156h ; キーバッファクリア wrtvrm equ 4dh ; VRAM書き込み nambas equ 0f922h ; パターンネームテーブルの番地 linlen equ 0f3b0h ; 画面の桁数 enaslt equ 24h ; スロット切り替え txttab equ 0f676h ; テキストエリア vartab equ 0f6c2h ; 変数エリア arytab equ 0f6c4h ; 配列エリア strend equ 0f6c6h ; フリーエリア savtxt equ 0f6afh ; テキスト位置 basrom equ 0fbb1h ; CTRL+STOP有効・無効切替 newstt equ 4601h ; BASIC実行 latch equ 0a0h ; PSGアドレスラッチ write equ 0a1h ; データライト read equ 0a2h ; データリード org 0ef40h ld bc,5 ld de,hipl ld hl,hookcmd ldir ret hookcmd: jp iplmain nop nop command: defs 1 file1: defs 13 file2: defs 13 addr1: defs 2 addr2: defs 2 addr3: defs 2 addrflg: defs 1 error: defs 2 portb: defs 1 portset: defs 1 savesize: defs 2 iplmain: pop bc ld (error),bc ; エラー処理アドレス保存 xor a ld (command),a ld (file1),a ld (file2),a ld (addrflg),a ; 0..未設定 1..addr1設定済 2..addr2設定済 3..addr3設定済 dec hl ; 最初の1文字目の位置に戻す cmdloop: call chrgtr ; コマンドライン読み取りループ jr z,cmdcheck cp 20h ; 0B〜1Fは数値の識別コード jr c,evaluat cp '"' jr z,getname cp ',' jr z,cmdloop ; カンマは無視 ld (command),a jr cmdloop getname: ld a,(file1) or a jr nz,skip1st ld bc,file1 jr skip2nd skip1st: ld a,(file2) or a jp nz,errexit ld bc,file2 skip2nd: ld d,13 ; SDファイル名は8文字+'.'+3文字 getloop: call chrgtr cp '"' jr z,setnull ld (bc),a inc bc dec d ld a,d or a jp z,errexit jr getloop setnull: xor a ld (bc),a ; 文字列の終端セット jr cmdloop evaluat: call frmqnt ld a,(addrflg) or a jr nz,skipadd1 ; addr1は設定済み ld (addr1),de ld a,1 ld (addrflg),a ; addr1を設定した jr cmdloop skipadd1: cp 1 jr nz,skipadd2 ; addr2は設定済み ld (addr2),de ld a,2 ld (addrflg),a ; addr2を設定した jr cmdloop skipadd2: cp 2 jp nz,errexit ; addr3まで設定してある ld (addr3),de ld a,3 ld (addrflg),a ; addr3を設定した jr cmdloop cmdcheck: push hl ; BASICコマンドラインの位置保存 ld a,(command) cp 'F' jr z,files cp 'L' jr z,load cp 'S' jp z,save cp 'R' jp z,rename cp 'K' jp z,kill cp 'C' jp z,romcart jp errexit files: call init_out ld bc,command call outbyte ; Fコマンド送信 call end_out call init_in loop_f: call inbyte ; ファイル一覧の文字列受信 or a jr z,endfiles call chput ; 1文字表示 call pause ; SPACEキーで一時停止 jr loop_f endfiles: call end_in pop hl ; BASICコマンドラインの位置復元 ret pause: ld a,8 call snsmat and 1 ret nz ; SPACEキーが押されているか norelease: ld a,8 call snsmat and 1 jr z,norelease ; SPACEキーを離したか call kilbuf ; キーバッファクリア ret load: ld a,(file1) or a jp z,errexit ; ファイル名が入力されていない call init_out ld bc,command call outbyte ; Lコマンド送信 ld bc,file1 call sendname call end_out call init_in call inbyte ; ファイルサイズの下位バイト exx ; 裏レジスタ活用 ld c,a exx ; 表に戻す call inbyte ; ファイルサイズの上位バイト exx ; 裏 ld b,a or c exx ; 表 jp z,errorin ; 0ならエラーが発生した call inbyte ; ロードアドレスの下位バイト exx ; 裏 ld e,a exx ; 表 call inbyte ; ロードアドレスの上位バイト exx ; 裏 ld d,a exx ; 表 call inbyte ; 実行アドレスの下位バイト exx ; 裏 ld l,a exx ; 表 call inbyte ; 実行アドレスの上位バイト exx ; 裏 ld h,a push hl ; 実行アドレス一時保存 ld hl,(nambas) ; パターンネームテーブル(VRAM) ld a,(linlen) ; 1行の桁数 add a,l ld l,a exx ; 表 call loop_c exx ; 裏 pop hl ; 実行アドレス復元 exx ; 表 ld hl,backbas push hl ; 読み込んだプログラム実行後の戻り先 exx ; 裏 push hl ; 実行アドレス保存 exx ; 表 pop hl ; 実行アドレス取得 jp (hl) ; 読み込んだプログラム実行 backbas: pop hl ; BASICコマンドラインの位置復元 ret save: ld a,(file1) or a jp z,errexit ; ファイル名が入力されていない ld a,(addrflg) cp 2 jp c,errexit ; アドレスが2つ以上入力されていない ld hl,(addr2) ; 終了アドレス ld bc,(addr1) ; 開始アドレス sbc hl,bc jp c,errexit ; 開始アドレス < 終了アドレスではない inc hl ld (savesize),hl ; ファイルサイズ保存 call init_out ld bc,command call outbyte ; Sコマンド送信 ld bc,file1 call sendname call end_out call init_in call inbyte or a ; 0が帰ってきたらエラー jp z,errorin call end_in call init_out ld bc,addr1 ; 開始アドレス call outbyte inc bc call outbyte ld bc,addr2 ; 終了アドレス call outbyte inc bc call outbyte ld a,(addrflg) cp 3 jr c,nostart ; 開始アドレスが省略されている ld bc,addr3 ; 実行アドレス call outbyte inc bc call outbyte jr skip_s nostart: ld bc,addr1 ; 開始アドレスを実行アドレスに call outbyte inc bc call outbyte skip_s: ld bc,(addr1) ; 開始アドレス ld hl,(savesize) ; 保存バイト数 loop_s: call outbyte inc bc dec hl ld a,h or l jr nz,loop_s call end_out pop hl ; BASICコマンドラインの位置復元 ret rename: ld a,(file1) or a jp z,errexit ; 旧ファイル名が入力されていない ld a,(file2) or a jp z,errexit ; 新ファイル名が入力されていない call init_out ld bc,command call outbyte ; Rコマンド送信 ld bc,file1 call sendname ld bc,file2 call sendname call end_out jr errchk kill: ld a,(file1) or a jp z,errexit ; ファイル名が入力されていない call init_out ld bc,command call outbyte ; Kコマンド送信 ld bc,file1 call sendname call end_out errchk: call init_in call inbyte or a ; 0が帰ってきたらエラー jp z,errorin call end_in pop hl ; BASICコマンドラインの位置復元 ret romcart: ld a,(file1) or a jp z,errexit ; ファイル名が入力されていない call init_out ld bc,command call outbyte ; Cコマンド送信 ld bc,file1 call sendname call end_out call init_in call inbyte push af ; ROMの種別保存 and 0fh ; ROMサイズ確認 jp z,errorin ; 0ならエラーが発生した exx ; 裏レジスタ活用 cp 1 jr z,size8k ; 8K cp 2 jr z,size16k ; 16K jr size32k ; 32K size8k: ld bc,2000h ; romファイルサイズ8K jr pagesel size16k: ld bc,4000h ; romファイルサイズ16K jr pagesel size32k: ld bc,8000h ; romファイルサイズ32K pagesel: ld hl,(nambas) ; パターンネームテーブル(VRAM) ld a,(linlen) ; 1行の桁数 add a,l ld l,a pop af ; ROMの種別復元 and 0f0h cp 10h jr z,page1 ; ページ1をRAMにする cp 20h jr z,page2 ; ページ切替なし jr basic page1: ld de,4000h ; 裏RAM4000Hに読み込む exx ; 表 ld a,8bh ; 基本スロット3 拡張スロット 2 ld hl,4000h ; ページ1 call enaslt ; スロット切り替え call loop_c pop hl ; BASICプロンプトに戻ってこないので破棄 ld hl,(4002h) jp (hl) ; ROMプログラム実行 page2: ld de,8000h ; RAM8000Hに読み込む exx ; 表 call loop_c pop hl ; BASICプロンプトに戻ってこないので破棄 ld hl,(8002h) jp (hl) ; ROMプログラム実行 basic: ld de,8000h ; 8000Hに読み込む exx ; 表 call loop_c pop hl ; BASICプロンプトに戻ってこないので破棄 ld hl,0c000h ld (vartab),hl ; 変数エリア ld (arytab),hl ; 配列エリア ld (strend),hl ; フリーエリア ld hl,8008h ld (savtxt),hl ; 現在のテキストの位置 ld hl,(8008h) inc hl ld (txttab),hl ; テキストエリア ld a,1 ld (basrom),a ; CTRL+STOP無効 call 629ah ; 変数エリア初期化 jp newstt ; BASIC実行 loop_c: call inbyte exx ; 裏 ld (de),a call wrtvrm ; 読み込んだキャラクタを画面右上に表示 inc de dec bc ld a,c or b exx ; 表 jr nz,loop_c call end_in ret sendname: call outbyte inc bc ld a,(bc) or a jr nz,sendname ; ファイル名の終端チェック call outbyte ; 終端文字も送る ret errorin: call end_in ; データ受信中のエラー errexit: pop hl ; BASICコマンドラインの位置復元 ld bc,(error) push bc ; エラー処理アドレス復元 ret init_out: di ld a,0fh out (latch),a ; 汎用入出力ポートB選択 in a,(read) ld (portb),a ; ポートBの状態保存 or 40h out (write),a ; 汎用入出力インターフェイス2と接続 ld (portset),a ; ポートB設定値の保存 and 0dfh ; 8ピンをLOW out (write),a ; 8ピン出力 ei ret end_out: di ld a,0fh out (latch),a ; 汎用入出力ポートB選択 ld a,(portb) out (write),a ; ポートBの状態復元 ei ret outbyte: di ld a,0fh out (latch),a ; 汎用入出力ポートB選択 ld a,(portset) or 20h ; 8ピンをHIGH スタートビット out (write),a ; 8ピン出力 ld a,0eh out (latch),a ; 汎用入出力ポートA選択 waitrep: in a,(read) ; ポートAから入力 and 1 ; 1ピンの値を確認 jr nz,waitrep ; 送信許可待ち(PULLUPなのでLOW待ち) ld a,0fh out (latch),a ; 汎用入出力ポートB選択 ld a,(portset) and 0dfh ; 8ピンをLOW out (write),a ; 8ピン出力 call wait ld a,(portset) and 0f3h ; 汎用入出力6,7ピンをLOW ld e,a ; ポートBの状態をeレジスタに保存 ld a,(bc) ; 出力データ ld d,a ; 出力データをdレジスタに保存 and 3 ; データの0,1ビットを残す rlca ; データの0,1ビットをシフトして汎用入出力 rlca ; 6,7ピン(ポートBの2,3ビット)にセット add a,e ; ポートBの状態復元+出力2ビット or 20h ; 8ピンをHIGH out (write),a ; データ出力 call wait ld a,e ; ポートBの状態復元 and 0dfh ; 8ピンをLOW out (write),a ; 8ピン出力 call wait ld a,d ; 出力データを復元 and 0ch ; データの2,3ビットを残す add a,e ; ポートBの状態復元+出力2ビット or 20h ; 8ピンをHIGH out (write),a ; データ出力 call wait ld a,e ; ポートBの状態復元 and 0dfh ; 8ピンをLOW out (write),a ; 8ピン出力 call wait ld a,d ; 出力データを復元 rrca ; データの4,5ビットをシフトして汎用入出力 rrca ; 6,7ピン(ポートBの2,3ビット)にセット ld d,a ; 2ビットずらしたデータを保存しておく and 0ch ; データの2,3ビットを残す add a,e ; ポートBの状態復元 or 20h ; 8ピンをHIGH out (write),a ; データ出力 call wait ld a,e ; ポートBの状態復元 and 0dfh ; 8ピンをLOW out (write),a ; 8ピン出力 call wait ld a,d ; 2ビットずらした出力データを復元 rrca ; データの4,5ビットをシフトして汎用入出力 rrca ; 6,7ピン(ポートBの2,3ビット)にセット and 0ch ; データの2,3ビットを残す add a,e ; ポートBの状態復元 or 20h ; 8ピンをHIGH out (write),a ; データ出力 call wait ld a,e ; ポートBの状態復元 and 0dfh ; 8ピンをLOW out (write),a ; 8ピン出力 call wait ld a,0eh out (latch),a ; 汎用入出力ポートA選択 waitend: in a,(read) ; ポートAから入力 and 1 ; 1ピンの値を確認 jr z,waitend ; 受信確認(HIGH待ち) ei ret init_in: di ld a,0fh out (latch),a ; 汎用入出力ポートB選択 in a,(read) ld (portb),a ; ポートBの状態保存 or 40h out (write),a ; 汎用入出力インターフェイス2と接続 ld (portset),a ; ポートB設定値の保存 and 0dfh ; 8ピンをLOW out (write),a ; 8ピン出力 ei ret end_in: di ld a,0fh out (latch),a ; 汎用入出力ポートB選択 ld a,(portb) out (write),a ; ポートBの状態復元 ei ret inbyte: di ld a,0eh out (latch),a ; 汎用入出力ポートA選択 inloop: in a,(read) ; ポートAから入力 and 10h ; 6ピンのLOW待ち 送信可能 jr nz,inloop ld a,0fh out (latch),a ; 汎用入出力ポートB選択 ld a,(portset) ld c,a ; ポートB設定値の一時保存 or 20h ; 8ピンをHIGH out (write),a ; 8ピン出力 call wait ld a,c ; ポートB設定値の復元 and 0dfh ; 8ピンをLOW out (write),a ; 8ピン出力 ld a,0eh out (latch),a ; 汎用入出力ポートA選択 in a,(read) ; ポートAから入力 and 0fh rlca rlca rlca rlca ; 4ビットシフト ld b,a ; 4ビットのデータ保存 ld a,0fh out (latch),a ; 汎用入出力ポートB選択 ld a,c ; ポートB設定値の復元 or 20h ; 8ピンをHIGH 送信要求 out (write),a ; 8ピン出力 call wait ld a,c ; ポートB設定値の復元 and 0dfh ; 8ピンをLOW out (write),a ; 8ピン出力 ld a,0eh out (latch),a ; 汎用入出力ポートA選択 in a,(read) and 0fh add a,b ; バイトデータを復元 ei ret ; 約1.2ms wait: ld a,255 wloop: dec a jr nz,wloop ret ; 約2.2ms ;wait: push bc ; ld bc,100h ;165hなら 3ms ;wloop: dec bc ; ld a,b ; or c ; jr nz,wloop ; pop bc ; ret