PC-8001 SIO
PC−8001はSIOにμPD8251C(USART)を使用します。 CMT、シリアルソケットに繋がり、 シリアルソケットからRS−232Cとして使用出来ますが ターミナルモードの使用のみで、 N−BASICのRS−232C命令は使用出来ません。 N−BASICのRS−232C命令は オプション(PC−8011等)の為にあります。 ターミナルモードとCMTはポート020H〜021Hを使用 オプションのRS−232Cはポート0C1H〜0CFHを使用 PC−8001mkII、PC−8801では CMTはポート020H〜021Hを使用 ターミナルモード、RS−232Cもポート020H〜021Hを使用します。 CMTとシリアルソケット(他機種ではCMTとRS−232C)の切り換えは ポート030Hのd5−4のBS2、BS1の組み合わせになります。 PC−8001はボーレートは300/600ボーの切り換えなります PC−8001mkII、PC−8801では600/1200ボーの切り換えになります。
主な設定 8251を使用する為にはコマンド指定で 内部リセット(IR=1)する必要があります。 リセットがかかるとモード設定が出来ますのでCMT等の設定を行います N−BASICでは8251の内部リセットが何時起きたのか分かりません そこでダミーのデーターをセットしてモード設定からコマンド指定 またはコマンド設定からコマンド指定して 次からのセットはコマンド指定(内部リセット)出来るようにしています 8251の内部リセット(N−BASIC内) ポート021Hに00EH、040Hを出力 CMTロードの設定 8251の内部リセット後 ポート021Hに04EH(モードワード)、014H(コマンドワード)を出力 CMTセーブの設定 8251の内部リセット後 ポート021Hに0CEH(モードワード)、011H(コマンドワード)を出力
使用ポート 020H:μPD8251データ 021H:μPD8251コントロール コマンドワード(出力) d7:EH 1=SYNCキャラクタの検出を始める、0=何もしない d6:IR 1=内部リセットの実行 、0=何もしない d5:RTS 1=センド要求を実行 、0=何もしない d4:ER 1=全エラーフラグをリセット 、0=何もしない d3:SBRK 1=ブレイクキャラクタの送信 、0=通常動作 d2:RxE 1=受信可 、0=受信不可 d1:DTR 1=データ・ターミナルレディを実行 、0=何もしない d0:TxEN 1=送信可 、0=送信不可 EH ハントイネーブル 同期モード時にSYNCキャラクタがくるの待つ IR 内部リセット 8251をモード・ワード受け取り状態にする RTS センド要求 1で/RTS端子をLにする ER エラーリセット PE、OE、FEを0にする SBRK センドブレイク・キャラクタ 1でTxD端子をLとして通信ブレイク RxE 受信イネーブル DTR データ・ターミナルレディ 1で/DTR端子をLにする TxEN 送信イネーブル ステータス(入力) d7:DSR 1=レディ 、0=ビジィ d6:SYNDET 1=キャラクタ検出、0=検出無し d5:FE 1=エラー発生 、0=エラー無し d4:OE 1=エラー発生 、0=エラー無し d3:PE 1=エラー発生 、0=エラー無し d2:T×E 1=エンプティ 、0=フル d1:R×RDY 1=レディ 、0=ビジィ d0:T×RDY 1=レディ 、0=ビジィ DSR データ・レディ /DSR端子がLの時に1になる SYNDET SYNCキャラクタ検出 SYNDET端子の内容 FE フレミングエラー ストップビットが検出されない OE オーバーランエラー CPUがデータを読む前に次のデータが入った PE パリティエラー 入力データにパリティエラーの検出 T×E 送信バッファエンプティ TxEMPTY端子の内容 R×RDY 受信レディ RxRDSY端子の内容 T×RDY 送信レディ TxEN=1、/CTS=0の場合1 モードワード(出力) 非同期モード d7:S2 ストップビット 11=2ビット、10=1+1/2ビット d6:S1 01=1ビット、00=無効 d5:EP 偶数パリティ発生/チェック 1=偶数 、0=奇数 d4:PEN パリティ・イネーブル 1=実行可、0=実行不可 d3:L2 キャラクタ長 11=8ビット、10=7ビット d2:L1 01=6ビット、00=5ビット d1:B2 ボーレート 11=×64、10=×16 d0:B1 01=×1 、00=同期モード 同期モード d7:SCS 単一キャラクタ同期 1=単一SYNCキャラクタ、0=ダブルSYNCキャラクタ d6:ESD 外部同期検出 1=SYNDET入力、0=SYNDET出力 d5:EP 偶数パリティ発生/チェック 1=偶数 、0=奇数 d4:PEN パリティ・イネーブル 1=実行可、0=実行不可 d3:L2 キャラクタ長 11=8ビット、10=7ビット d2:L1 01=6ビット、00=5ビット d1:0 d0:0 030H(出力) d7:未使用 d6:未使用 d5:CMT BS2 d4:CMT BS1 d3:CMT MOTOR 1=MOTORオン 、0=MOTORオフ d2:CMT CHIN 1=マーク(2400Hz)、0=スペース(1200Hz) d1:CRT 1=白黒、0=カラー d0:CRT 1=80行、0=40行 BS2、BS1 11=SIO同期(使用しません) 10=SIO非同期(シリアルソケット) 01=CMT 300bps 00=CMT 600bps 040H(入力) d7:未使用 d6:未使用 d5:CRT VRTC 1=垂直帰線期間、0=表示または水平帰線期間 d4:RTC μPD1990 DATA OUT d3:EXP /EXTON 1=接続されていない、0=接続されている d2:CMT CDIN CMTからのキャリア信号が検出されたら1 d1:PRT /STROBEを/PR、/ACKをCLK、D=0にしたFF(LS74)のQ d0:PRT /READY
CMTフォーマット FSKフォーマットで600ボー ’1’になる波形 2400Hz 4サイクル ’0’になる波形 1200Hz 2サイクル 1バイトデータの内容 ’0’、d0、d1、d2、d3、d4、d5、d6、d7、’1’、’1’ BASICファイル ヘッダー部分 2.5秒のWAIT 0D3H*10 ファイルネーム6文字 0.1秒のWAIT プログラム部分 プログラム本体((0EB54H、0EB55H)−(0EFA0H、0EFA1H)-1、最後は000H*3) 000H*10 1.3秒のWAIT データファイル(PRINT#−1) WAIT 09CH*6 データ、データ、...(データの区切りはカンマ) WAIT マシン語ファイル 3.8秒のWAIT 03AH スタートアドレス(上位、下位の順) チェックバイト NEG(アドレス上位+下位) 03AH データ数(255バイト) データ本体 チェックバイト NEG(データ数+データ本体の合計 MOD 256) 03AH 最終のデータ数 データ本体 チェックバイト NEG(最終のデータ数+データ本体の合計 MOD 256) 03AH 000H、000H 1.3秒のWAIT *チェックバイトは合計で最下位1バイトが000Hになる値 <例>スタートアドレス0EA52Hの場合 ファイルの先頭03AH、0EAH、052H、0C4Hとなる 0EAH+052H+0C4H=00200H
CMTのオートスタート CMTはコントロールはリモートのみなので オートスタートは出来ませんが プログラムで出来るだけオート化を図ります BASICでマシン語のプログラムをロード、復帰または実行 I/O クレイジークライマー(エンパイアクライマー)の場合 まずBASICプログラムをロード、実行 マシン語プログラムがあるかPEEK文で判断する マシン語プログラムがあればメインへ、無ければロードプログラムを実行する ロードプログラム A$="MON"+CHR$(13)+"L"+CHR$(13)+CHR$(2)+"RUN"+CHR$(13)+CHR$(0) A=VARPTR(A$)+1:POKE&HEDC0,PEEK(A):POKE&HEDC1,PEEK(A+1):POKE&HEA68,1 A$があるアドレスをVARPTRで取得 そのアドレス+1をファンクションキーのポインタとして設定 ファンクションキーフラグをオンにして A$の内容をファンクションキーを押したとみなされます つまりプログラム中でファンクションキーを押したように MON L ^B RUN を実行します ロード中はキーを押したとはみなされないので ロード終了後に残りのコマンドが実行されます そして再び1本目のプログラムをRUNするのですが 今度はマシン語プログラムがロードされているので ロードプログラムは実行されずにメインルーチンへ飛びます 短所としてBASICプログラムをロードするのに ファイルネームを指定しなければいけません ワークエリアをロードしてファンクションキーフラグをオンにする ポニカ ザ・レーサーの場合 1本目のIPLプログラムが0EA68H−0EACAHなので ロード終了後0EA68Hが001Hに書き換えられ ファンクションキーフラグがオンになります デフォルトでファンクションキーのポインタは EDC0:C0 EA となっており0EAC0H以降がファンクションキーの内容になります EAC0:0D 0D 0D 6C :...l EAC4:0D 67 65 63 :.gec EAC8:63 30 0D :c0. L GECC0 つまりIPLロード終了後、ファンクションキーを押したと判断して L[RET]を実行、ロード終了後、残りのファンクションキーの内容 GECC0[RET]を実行してゲームがスタートします BASICでVARPTRを使用したのを直接CMTロードで ワークエリアをロード(書き換え)してロード終了後に ファンクションキーを押した状態にするタイプです マシン語ファイルをロード、終了後に実行 マシン語をロード、終了しだい実行されます スタック領域までロードされロード終了後、 本来ならモニタに帰る所をゲームプログラムの実行に ロードデータで書き換えられてしまっているので モニタへ戻らずにゲームが実行される仕組みです MON、Lを実行するとスタック内0E8CBH−0E8CCHが 帰り値(05DE1H)を実行したいアドレスにロードして内容を書き換えます 帰り値 05DE1Hということは Lコマンド内05DDEHのCALL 05F3AHから帰るアドレスで 05F3AHはCMTロードルーチンになります つまりロード終了後、即ゲームプログラムが実行されます ただしモータはストップされないのでゲームプログラムの方でストップを行います スタックはモニタに移行すると再設定されるので 書き換えるスタックアドレスが変わる心配はありません ただしCLEAR文でマシン語領域を確保されるとスタック位置が変わる為 オートスタート出来なくなります HAL研のジュピターランダーでは0C69CH−0E8FFHまでロードされ 0E8C8H−0E8FFHは0D7Hで埋まっている ロードが終了すると0E8CBH−0E8CCHが0D7H、0D7Hに 書き換わっているのでロード終了後0D7D7Hへジャンプします FAN FUN、ザクサスのIPL部分が同じタイプになります BASICファイルにマシン語データを埋め込む BASICファイルは000H×10が見つかるまで ロード、メモリストアを行い続けます 終了後000H×10が書かれたアドレスが変数領域に設定されます これを利用してプログラムの最終アドレス、変数領域アドレスを設定しなおして BASICプログラムの後ろにマシン語プログラムを埋め込み、セーブされたタイプです ただしデータ等000H×10以上は置けません どうしても必要になる場合、プログラムで構築、展開する必要がありますが その場合、変数領域アドレスを再設定しなければなりません オリジナルフォーマット マリオブラザース(ウェストサイド) <テープの内容> IPLプログラム ローダー メイン(オリジナルフォーマット) ワークエリアをロードしてファンクションキーフラグをオン ローダープログラムをロード、実行 メインプログラムは1ブロック(255バイト)+1 ロードすると1ブロック毎に1文字画面表示される メインプログラムのフォーマット ヘッダ 03CH アドレス上位 nn 下位 mm チェックサム(NEGヘッダ含まず) ヘッダ 03CH データ長 nn データ ロードメッセージ(1バイト) チェックサム(NEGヘッダ含まず) | ヘッダ 03CH エンドマーク 000H 000H THE FAR WAY(ブレインメディア) <テープの内容> IPL兼ローダ 画面データ(オリジナルフォーマット) BASIC(オリジナルフォーマット) ワークエリアをロードしてファンクションキーフラグをオンにして ファンクションキーポインタも0EDD0Hに上書き GEA7CでIPL内のローダ部分を実行 BASICプログラムをロードしたらBASICコマンドフックでRUN 画面、BASICプログラムのフォーマット ヘッダ 088H×5 スタートアドレス下位、上位 エンド アドレス下位、上位 データ スーパーペンギン (マイコンセンターRAM) <テープの内容> IPL兼ローダ マシン語プログラム(オリジナルフォーマット) ワークエリアをロードしてファンクションキーフラグをオンにして ファンクションキーポインタも0EA77Hに上書き GEA7DでIPL内のローダ部分を実行 プログラムのロード終了後 IPL内のゲームプログラム一部(9バイト)を転送 STOP+RESET(ホットスタート)のアドレスを変更後 ゲームスタート マシン語プログラムのフォーマット ヘッダ 06EH アドレス上位 nn 下位 mm チェックサム(NEGヘッダ含まず) ヘッダ 06EH データ長 nn データ ロードメッセージ(1バイト) チェックサム(NEGヘッダ含まず) | ヘッダ 06EH エンドマーク 000H 000H PC−8001mkII用 ロードランナー(システムソフト) <テープの内容> BASIC ローダー(プログラム隠避、マシン語埋め込み) データ1 オリジナルフォーマット1 データ2 オリジナルフォーマット1 プログラム1 オリジナルフォーマット1 プログラム2 オリジナルフォーマット1 データ3 オリジナルフォーマット1 データ4 オリジナルフォーマット1 面データ01 オリジナルフォーマット2 面データ02 オリジナルフォーマット2 面データ03 オリジナルフォーマット2 面データ04 オリジナルフォーマット2 面データ05 オリジナルフォーマット2 面データ06 オリジナルフォーマット2 面データ07 オリジナルフォーマット2 面データ08 オリジナルフォーマット2 面データ09 オリジナルフォーマット2 面データ10 オリジナルフォーマット2 面データ11 オリジナルフォーマット2 面データ12 オリジナルフォーマット2 面データ13 オリジナルフォーマット2 面データ14 オリジナルフォーマット2 面データ15 オリジナルフォーマット2 BASICのローダ部分は行番号0FFFFHで隠されている 80BB:E8 03 でローダ部分の可視が出来る BASICは更にマシン語が埋め込まれており 08400H−084C4Hがマシン語部分になる データ、プログラム等のアドレス指定はBASIC上で スタート、エンドアドレスの指定、ロード後に裏RAMに転送 面データは10面分のデータとなる オリジナルフォーマット1 ヘッダ 03AH データ長 nn データ チェックサム(NEG、ヘッダー除く) | ヘッダ 03AH エンドマーク 000H 000H オリジナルフォーマット2 ヘッダ 0D3H×10 ファイルネーム6バイト ヘッダ 03AH データ長 nn データ チェックサム(NEG、ヘッダー除く) | ヘッダ 03AH エンドマーク 000H 000H PC−8001mkII用 タイムシークレット(ボンドソフト) <テープの内容> BASIC ローダー(プログラム隠避) プログラム オリジナルフォーマット BASIC部分で見る事が出来る範囲はタイトル表示部分までで ローダーのDATA(マシン語)、USR文等の実行部分は隠避されています ローダー部分はA面は1200bps、B面は 600bpsタイプになっています プログラムロードが終了するとCMTクローズ、スタック設定 ローダにあるCMTルーチンを裏RAM 07700Hに転送して 082F8Hの内容をジャンプしてゲームが始まります ヘッダ 0AAH スタートアドレス00000H (上位、下位の順) チェックバイト NEG(アドレス上位+下位) ヘッダ 0AAH データ数 0FFH(255バイト) データ本体 チェックバイト NEG(データ数+データ本体の合計 MOD 256) | ヘッダ 0AAH 最終のデータ数 データ本体 チェックバイト NEG(最終のデータ数+データ本体の合計 MOD 256) ヘッダ 0AAH 000H PC−8001mkII用 パンチボール マリオブラザース(ハドソン) <テープの内容> マシン語 ローダー プログラム オリジナルフォーマットNONTAMA ローダーは0E4CBHから始まっています N80−BASICはN−BASICに比べ 0400Hワークエリアが取られるのでスタックも0400H分前にずれます つまりマシン語ファイルをロード、終了後に実行するタイプで 0E4CBH−0E4CCHがモニタに帰る所を ローダーをロードした時点で書き換えられているので ロード終了後、実行されます ローダーにはCMT読み込みルーチンがあり オールRAMにして0100Hからロードする様になっています プログラム本体は暗号化され単純なテープダンプでは判らない様にしてあります 最初にXORデータ0A3Hがローダー側でセットされ 1バイト目リードデータとXOR 0A3Hを行いメモリにストア 2バイト目リードデータとXOR 1バイト目リードデータを行いメモリストア... 以降、最終アドレスまで繰り返します 尚、チェックサムはXORで変換されたデータ総合計の最下位1バイトになります ・―――――――――――――――――――・ |ロード値 前のロード値|ストア値| |――――――――――――――+――――| |060H XOR *0A3H|0C3H| |00CH XOR 060H|06CH| |009H XOR 00CH|005H| | : | : | | : | : | ・―――――――――――――――――――・ *ローダーで設定された値 プログラム本体(暗号化)の先頭部分 60 0C 09 29 09 5F 1A 48 1B 52 1D 53 73 42 62 53 6A 52 66 46 76 4E 6E 5F 6E 4E 0C 55 75 3E 77 3C ↓ メモリにストアされるプログラムの先頭部分 C3 6C 05 20 20 56 45 52 53 49 4F 4E 20 31 20 31 39 38 34 20 30 38 20 31 31 20 42 59 20 4B 49 4B オリジナルフォーマットの内容 0FFH ;テープヘッダ NONTAMA ;文字列 000H,001H ;先頭アドレス 00100H 000H,06CH ;最終アドレス+1 06C00H 000H,001H ;実行アドレス 00100H 06CH〜 ;プログラム本体(暗号化) 033H ; 02EH ;チェックサム 1バイト 000H×11 ;エンドマーク(チェックは10個) PC−8001mkII用 野球狂(ハドソン) <テープの内容> BASIC ローダー(プログラム隠避) プログラム オリジナルフォーマットNONTAMA 画面設定等BASICで行い 後ろに隠避されているマシン語を実行を行います ローダー本体は0E800Hへ転送、実行 プログラム自身はパンチボールとほぼ同様ですが NONTAMAの後の先頭アドレス〜実行アドレス6バイトの チェックサム1バイトがあります 最初にXORデータ0A3Hを用意して 1バイト目リードデータとXOR 0A3H 2バイト目リードデータとXOR 1バイト目リードデータ... となりますがメモリ読み込みROM、メモリ書き込みRAMにして 1バイト読み込みをしたらXORで変換したデータで チェックサムを行い、そのチェックサムを画面に表示します チェックサムはXORで変換されたデータ総合計の最下位1バイトになります プログラム本体(暗号化)の先頭部分 92 92 93 5E 0D 1A D7 F2 E8 25 25 7D B0 12 0C C1 F9 E3 2E E0 F3 3E 9D 88 B6 B7 85 C8 9E 53 BD E8 ↓ メモリにストアされるプログラムの先頭部分 31 00 01 CD 53 17 CD 25 1A CD 00 58 CD A2 1E CD 38 1A CD CE 13 CD A3 15 3E 01 32 4D 56 CD EE 55 オリジナルフォーマットの内容 0FFH ;テープヘッダ NONTAMA ;文字列 000H,001H ;先頭アドレス 00100H 000H,0B2H ;最終アドレス+1 0B200H 000H,001H ;実行アドレス 00100H 0B4H ;先頭〜実行アドレスのチェックサム 092H〜 ;プログラム本体(暗号化) 0E4H ; 033H ;チェックサム 1バイト 000H×12 ;エンドマーク(チェックは8個) PC−8001mkII用 ガンマン(ハドソン) <テープの内容> マシン語 ローダー プログラム オリジナルフォーマット ローダーは上記のパンチボールと同様0E4CBHから始まっています 0E4CBH−0E4CCHがモニタに帰る所を ローダーをロードした時点で書き換えられているので ロード終了後、実行されます ローダーにはCMT読み込みルーチンがあり 他機種のHu−BASICに近いファイルフォーマットを ロード、実行を行います プログラムはインフォメーションとデータに分けられ チェックサムというより1バイトごとリードデータを元に XORで変化されたチェックコードを採用されています インフォメーションはサイズ、ロードアドレスだけ使用 プログラムロード終了後、ロードアドレスを実行されます 暗号化はされていません 0D3H 16バイト ’F’ 1バイト 001H FCB 001H 1バイト(ファイルタイプ?) ファイルネーム 16バイト 予備? 1バイト(パスワード?) サイズ 2バイト ロードアドレス 2バイト 実行アドレス 2バイト チェックコード 1バイト 0D3H 16バイト ’F’ 1バイト 002H データ データ : チェックコード 1バイト
PC−8001のコーナへ Home へ戻る