MC6802シングルボードコンピューターに以前作成したK68-VDG(MC6847搭載)ビデオボードが接続できましたので、せっかくだから? Universal MonitorをTV(というかVRAM?)対応してみたり、その上で動くTiny BASICもVRAM対応してTV(RCAコンポジット入力モニター)に映してみたいと思います。
機械語モニターのVRAM対応の前に
Universal Monitor(機械語モニター)のVRAM対応の前に、K68-VDGビデオボードのサンプルプログラムがK68-SBC(MC6802シングルボードコンピュータ)+K68-VDGビデオボードで ちゃんと動くか試してみます。
サンプルプログラムは数年前に作りまして、以下のgithubのフォルダに「全キャラクタ表示」と「エコーバックプログラム」があります。
全キャラクタ表示サンプル(asciilist-6800)
全キャラクタ表示サンプルは、VRAMのアドレスの先頭から$00~$FFのキャラクタを並べるだけのでもプログラムです。
上図のように、割と表示がきれいなので好きなのです。
VRAM_TOP EQU $A000
VRAM_END EQU $A200
VRAMアドレスが上記のVRAM_TOP
とかVRAM_END
に定義されていますので、$A000をVRAMにする場合は変更が必要です。
またコンパイルしなおしのために Makefile
もつけてますので、The Macroassembler ASとGNU makeが動く環境で make
して再アセンブリしてください。インテルHexファイルが作成されます。
出来上がってIntelHexファイルを Universal MonitorのL
コマンドでロードして G0100
で $100番地から実行すると上記のようなキャラクタ一覧が表示できます。
エコーバックプログラム(echoback-6800)
エコーバックプログラムは、シリアル入力でキーボードから入力したデータをK68-VDGビデオボード経由でRCAコンポジットモニター画面へ表示するものです。
プログラムの実際の動きは、シリアル通信で届いた1バイトキャラクタをいい感じでVRAMに配置していくもので、CR($0D)入力で改行したり、最下行まで行ったら自動スクロールしたりという仕込みをしてあったはず。このロジックを応用するとUniversal MonitorをK68-VDG経由でTV対応(w にできる思います。
以前も書きましたが、K68-VDGボードに載っているMC6847というビデオコントローラにはキャラクタジェネレータが内蔵されていまして、VRAMに文字コードをセットすると英字や数字を表示してくれます。上記のように、プログラムを起動してTeraTermのようなシリアル端末から文字を入力すると画面に文字が出力されます。ちなみに、緑背景になってるのがRCAコンポジットモニター替わりのUSBキャプチャケーブル経由の画面です。

ただしデータシートを見ると分かりますが、上記のように6bit x 2面の独特なコード配置となっているため ひと工夫必要です。また英小文字は出ませんので、そこもちょっと一工夫…
;
; キー入力エコー
;
ECHO:
JSR CONIN
CMPA #ESC
BEQ ECHO_END
JSR CONOUT
;
; 内部CGにあわせて キャラクターコード変換
;
; 英小文字は大文字変換
CMPA #$60
BGE SUB20
; 英大文字はそのまま出力
CMPA #$40
BGE ECHO1
; 特殊記号はリバースキャラへ変更
CMPA #$20
BGE ADD40
BRA ECHO1
SUB20:
SUBA #$20
BRA ECHO1
ADD40:
ADDA #$40
BRA ECHO1
ECHO1:
JSR VRAM_OUT
BRA ECHO
エコーバックプログラムで、届いた文字コードをいろいろと変換してましたが、コメントがなかったためすでに私も何をやったか忘れてました。今後また忘れないようにコメントを追加しておきました。
Universal MonitorのVRAM対応
エコーバックプログラムの文字出力の部分をいい感じで移植すると、Universal Monitorの文字出力をRCAコンポジットモニターに出力できるはずです。
Universal Monitorのコンソールドライバ
Universal Monitorは、いろいろな環境に合わせられるように「コンソールドライバ」が定義できるようになってます。
SBC6800コンソールドライバからの変更点
SBC6800用シリアルドライバがUniversal Monitorについてきますので、そちらにVRAM対応ルーチンを仕込んでいきたいと思います。コンソールドライバに作りこみするルーチンは以下の通りです。
ルーチン | 説明 | 今回の対応点 |
INIT | デバイス等初期化 | シリアルLSI MC6850の初期化はそのままにして、VRAMデータのクリアなどを実施します。 |
CONIN | 1文字入力 | ★ここは変更ありません。 |
CONOUT | 1文字出力 | シリアルへの出力の後、VRAMへ文字データをセットします。 必要ならスクロール処理も実施します。 |
変更したソースは以下の通りです
★ちょっと長いです
;;;
;;; MC6850 (ACIA) & K68-VDG Console Driver
;;;
INIT:
LDAA #$FF
INIT_LOOP1:
LDAB #$FF
INIT_LOOP2:
DECB
BNE INIT_LOOP2
DECA
BNE INIT_LOOP1
LDAA #$03 ; Master reset
STAA ACIAC
NOP
NOP
LDAA #ACCR_V
STAA ACIAC
;
; VRAM関係初期化
;
VRAM_SCREND EQU VRAM_END-$20
;
SPC EQU $60
ESC EQU $1B
;CR EQU $0D
CURSOR EQU $CF
;BS EQU $08
;
CHAR_A EQU $40
CHAR_UNS EQU $5F
;
CHAR_S_A EQU $60
CHAR_END EQU $7F
;
VDG_MODE EQU %00000000
VDG_CTL_AD EQU $8110
;
STX WK_X
LDX #VRAM_TOP
STX WK_VRAM
;
JSR VDG_INIT
JSR VRAM_CLR
JSR DISP_CURSOR
LDX WK_X
RTS
CONIN:
LDAA ACIAC
ANDA #$01
BEQ CONIN
LDAA ACIAD
RTS
CONST:
LDAA ACIAC
ANDA #$01
RTS
CONOUT:
PSHA
CO0:
LDAA ACIAC
ANDA #$02
BEQ CO0
PULA
STAA ACIAD
STX WK_X
;
;
; 内部CGにあわせて キャラクターコード変換
;
; 英小文字は大文字変換
CMPA #$60
BGE SUB20
; 英大文字はそのまま出力
CMPA #$40
BGE ECHO1
; 特殊記号はリバースキャラへ変更
CMPA #$20
BGE ADD40
BRA ECHO1
SUB20:
SUBA #$20
BRA ECHO1
ADD40:
ADDA #$40
BRA ECHO1
ECHO1:
JSR VRAM_OUT
;
LDX WK_X
RTS
;
; VRAM SUB
;
;
; MC6747初期化
;
VDG_INIT:
LDAA #VDG_MODE
STAA VDG_CTL_AD
RTS
;
; VRAMクリア
;
VRAM_CLR:
LDX #VRAM_TOP
LDAA #SPC
VRAM_CLR_LOOP:
STAA 0,X
INX
CPX #VRAM_END
BNE VRAM_CLR_LOOP
RTS
;
; VRAM出力ルーチン
;
VRAM_OUT:
CMPA #CR
BEQ VRAM_OUT_END
CMPA #LF
BEQ VRAM_CR
CMPA #BS
BEQ BS_RTN
;
LDX WK_VRAM
STAA 0,X
LDAA #CURSOR
STAA 1,X
INX
STX WK_VRAM
CPX #VRAM_END ; 画面右下まできた?
BNE VRAM_OUT_END
;
; スクロール処理
;
VRAM_SCR1:
LDX #VRAM_TOP
STX WK_VRAM
VRAM_SCR:
LDAA $20,X
STAA 0,X
INX
CPX #VRAM_SCREND
BNE VRAM_SCR
;
LDAA #SPC
LINE_CLR:
STAA 0,X
INX
CPX #VRAM_END
BNE LINE_CLR
LDX #VRAM_SCREND
STX WK_VRAM
JSR DISP_CURSOR
BRA VRAM_OUT_END
;
; CR($0D)が押されたら改行処理
;
VRAM_CR:
JSR CLR_CURSOR
;
LDAA WK_VRAM+1
ANDA #$E0
LDAB WK_VRAM
ADDA #$20
ADCB #0
CMPB #$A2 ; VRAMはみ出す?
BEQ VRAM_SCR1 ; スクロール処理へ
STAB WK_VRAM
STAA WK_VRAM+1
JSR DISP_CURSOR
BRA VRAM_OUT_END
;
VRAM_OUT_END:
RTS
;
; カーソル表示
;
DISP_CURSOR:
LDAA #CURSOR
LDX WK_VRAM
STAA 0,X
RTS
;
; カーソル消去
;
CLR_CURSOR:
LDAA #SPC
LDX WK_VRAM
STAA 0,X
RTS
;
; BS処理
;
BS_RTN:
CPX #VRAM_TOP
BEQ VRAM_OUT_END
;
JSR CLR_CURSOR
LDX WK_VRAM
DEX
STX WK_VRAM
JSR DISP_CURSOR
BRA VRAM_OUT_END
config.incとUniversal Monitor(6800版)本体の変更点
config.inc
で定数などを定義していますので、今回のVRAM対応版用に定数定義を追加します。USE_DEV_6850_VRAM
というスイッチを「1」にしてやります。
VRAMアドレスは変更の可能性が高いかな?と思い、config.inc
で定義することにしました。それ以外の定数定義はコンソールドライバ側に持っちゃいましたが、こちらに持ってきてもOKです。
;;;
;;; Motorola MC6850 & VRAM
;;;
USE_DEV_6850_VRAM = 1
IF USE_DEV_6850_VRAM
;; ACIA
ACIAC: equ $8018 ; Control / Status Register
ACIAD: equ $8019 ; Data Register
ACCR_V: EQU $15 ; Control: x16, 8-bit, N, 1
;
VRAM_TOP EQU $A000
VRAM_END EQU $A200
ENDIF
前記のコンソールドライバは dev\dev_6850_VRAM.asm
としてdevフォルダへ配置しまして、それを読み込むunimon_6800.asm
にも、ソースの下の方にインクルードされるよう以下のように手を入れました。
IF USE_DEV_6850_VRAM
INCLUDE "dev/dev_6850_VRAM.asm"
ENDIF
ソースを配置、修正したらThe Macroassembler ASとGNU makeがある環境でmakeするとIntelHex形式のオブジェクトが出来上がります。
このIntel HexファイルをROMライター(TL866など)でEPROMへ焼きましょう。
動かしたら暴走?! ~うまく動きました!
上記に掲載したコンソールドライバールーチンでは修正済みですが、最初つくったときは CONOUT
ルーチンでインデックスレジスタXを保存せず破壊したためUniversal Monitorに戻った後 暴走してしまいましたw
STX WK_X
とLDX WK_X
のロジックでVRAM出力ルーチンをはさんでインデックスレジスタを保護することで対応しました。起動すると無事 RCAコンポジットモニターにもUniversal Monitorの出力が表示されました。やったー。
上記のスクショでは行頭に「^J」が出てますが、Universal Monitorの文字列出力が CR($0D)、LF($0A)が行末についてくることを当初は考慮せずにCR($0D)で改行処理を実施していたためです。
上記のコンソールドライバでは対応済みです。
電大版Tiny BASICを動かしてみたい
機械語モニター Universal MonitorがRCAコンポジットディスプレー対応できましたので、高校時代からの夢だった「電大版Tiny BASICをRCAコンポジットディスプレーに表示」をやってみたい!と思います。
自分特製のBASICパソコンっぽくて憧れます。
電大版Tiny BASICのソースを取得
電大版Tiny BASICですが、ブルーバックス「マイコンピュータをつかう」とか「続マイコンピュータの作り方つかいかた」などの専門書にダンプリストが掲載されていますので頑張ってウチコミすると動きますが、今回はいろいろと手を入れますし 今後のROM化などを考えるとソースを入手したいところです。
実は電大版Tiny BASICソースリストは、bit誌 1978年8月号に掲載されています。Amazonで復刻されていますのでご興味ある方はぜひぜひ。

けっこう印字が かすれていたりして入力は難儀ですが、わたしも以前頑張ってソースコードを入力しました。このソースを手入力して公開しているページがありますので、今回はそちらからソースコードをいただいてきました。古風平凡さんのページです。
TB2KD110.zip
が SBC6800で動くように手直しされたソースですので、今回作成したSBC6800互換のMC6802シングルボードコンピューターでの動作確認には最適です。シリアル入出力であれば無修正で動くはず。

上記のように SフォーマットのダンプをTeraTerm経由でMIKBUGへ流し込んで無事BASICが動きました。電大版Tiny BASICのオリジナルはMIKBUGを前提にしてますので、SBC6800データパックにあるACIA対応MIKBUGで動かしました。
アセンブリ環境の整備
ソースを変更してUniversal Monitor対応したりするためにはアセンブリ環境が必要です。アセンブリ環境には以前もご紹介した「Motorola 6800 Assembler」を使ってみたいと思います。
電大版Tiny BASICのソース書式は古風(?)なMC6800アセンブラに近いはず。
アセンブラはmakeしてビルドする必要がありますが、昨今のWindowsはWSL2でLinuxを動かすことができますのでビルド環境作成も容易です。
またVisual Studio Codeで色分けしたコード閲覧をしたりアセンブルをかけたりできるともっと素敵。そんな環境構築方法がryu10さんのBLOGで紹介されてました。ありがたい!!!

Windows10/11へのWSL2(Ubuntu)の導入だとか、コンパイラgccのセットアップだとかはGoogleさんに聞いていただいてセットアップしていただいたのち、上記のryu10さんのBLOGの手順で「M6800 Assembly」プラグインを入れていただくとas0というMC6800アセンブラで手軽にvscode上でアセンブリできる環境が構築できます。素晴らしい!!!
bash.exeでWSL上のファイルをWindows側から動かせるんですね。すごいです。

ソースの変更点
さてソースを入手出来てアセンブリ環境ができたところで、電大版Tiny BASICのソースへUniversal Monitor(K68-VDG RCAコンポジットディスプレイ(VRAM))対応をしていきたいと思います。
Universal MonitorのVRAM対応ができているので、実際はUniversal Monitorを呼ぶだけでOKなんですが…
CMPAとかLDAAとか…
古風平凡さんのソースは、CMPA
命令がCMPA A
とか、LDAA
命令がLDA A
のように間に空白がはいったかたちになってました。こちらは古来のMC6800ニーモニックに倣って CMPA A
⇒ CMPAA
、LDA A
⇒LDAA
のようにテキストエディタの置換機能で変更する必要があります。
いろいろな命令でこの事象が出てましたので、ちょっと手抜きして △A
⇒A
(△は半角スペース)とか△B
⇒B
とかでまとめて置換してしまいました。
RAM拡張の対応とかUniversal Monitorの文字入出力ルーチン対応
今回のMC6802シングルボードコンピュータではRAMを32kBにしてます、また$C000~の領域にRAMもありますのでスタックなどはそちらに逃がしたいと思います
<修正点>
RAMSSS EQU $0A00
RAMEEE EQU $7FFF
:
STACK EQU $C0FF
SUBSTK EQU $C1FF
INEEE EQU $FFA0 ; Universal Monitor CONIN
OUTEEE EQU $FF90 ; Universal Monitor CONOUT
RESET EQU $E000 ; Universal Monitor START
あと動かしてから気づいたのですが、MIKBUGではINEEE(1文字入力ルーチン)でシリアル入力された文字データはすぐOUTEEE(1文字出力ルーチン)へ渡されてエコーバックしています。
<MIKBUGの1文字入力ルーチン>
288 E1AC INEEE
289 E1AC 8DF7 BSR SAV
290 E1AE B68018 IN1 LDAA ACIACS
291 E1B1 47 ASRA
292 E1B2 24FA BCC IN1 RECEIVE NOT READY
293 E1B4 B68019 LDAA ACIADA INPUT CHARACTER
294 E1B7 847F ANDA #$7F RESET PARITY BIT
295 E1B9 817F CMPA #$7F
296 E1BB 27F1 BEQ IN1 IF RUBOUT, GET NEXT CHA
297 E1BD 8D12 BSR OUTEEE
298 E1BF 39 RTS
UniversalMonitorの1文字入力では入力されるだけでエコーバックされないため電大版Tiny BASICの入力ルーチンに、以下のようにちょっと細工しておきました。いちおうAレジスタをスタックへ退避して保護しつつJSR OUTEEE
を呼んでるあたりです。
<エコーバック修正箇所>
INFFF JSR INEEE
CMPA #$60
BCS *+4
SUBA #$20
CMPA #$25
BNE *+4
LDAA #$40
PSHA
JSR OUTEEE
PULA
RTS
BASICコマンドテーブルの書式変更
「Motorola 6800 Assembler」では1バイトづつデータ定義するFCB
命令で文字列を扱うことはできません。古風平凡さんのソースだと、アセンブラの処理の違いだと思いますが以下のように FCB 'LOA
と定義されていてこのままでは正しく展開されません。FCC /LOA/
のように命令を変更する必要があります。
※最初これに気づかなくて、BASICが暴走して焦りました。
FCB 'LOA
↓↓↓
FCC /LOA/
オリジナルのソースだと FCB 'L,'O,'A,'D+N
のように1文字づつシングルクォーテーションが付与されてカンマ区切りで定義されていますので、この形で定義する対応でもOKです。
ここは前回もハマったところでした。
ソースの入力間違い部分修正
古風平凡さんのソースには一部に入力間違いがありましたので、修正しました。ARRAYルーチンとFACTルーチンです。昔自分が打ち込んだソースリストと比較して見つけました。
こちらを直したことでRND関数が正しく動くようになり、STAR TREKゲームが動きました!!
元ソース | 修正ソース |
ARRAY JSR FACT JSR POP BITB #$C0 BNE ERR11 SEC ROLA ROLB ADDA PREND+1 ADCB PREND CMPB RAMEND BNE *+4 CMPA RAMEND*1 BCC ERR11 CLC RTS | ARRAY JSR FACT JSR POP BITB #$C0 BNE ERR11 SEC ROLA ROLB ADDA PREND+1 ADCB PREND CMPB RAMEND BNE *+4 CMPA RAMEND+1 BCC ERR11 CLC RTS |
元ソース | 修正ソース |
FACT INX BSR GETN BCS PUSH CMPA #’# BEQ PEEK CMPA #’$ BEQ HEXA2 STX PX LDX #TABLE3 OPRATE JSR SEARCH LDAA 1,X PSHA LDAA 0,X PSHA LDX PX RTS | FACT INX BSR GETN BCS PUSH CMPA #’# BEQ PEEK CMPA #’$ BEQ HEXA2 STX PX LDX #TABLE3-2 OPRATE JSR SEARCH LDAA 1,X PSHA LDAA 0,X PSHA LDX PX RTS |
電大版TinyBASICの動作確認!
電大版Tiny BASICのアセンブラソースが正しくアセンブリできると、モトローラS形式というダンプリストができあがります。そのデータをTeraTerm経由でUniversalMonitorのLコマンドで流し込んでメモリーへ配置してやると準備OKです。
下記のように、以前入力して動かしたSTAR TREKゲーム(ブルーバックス「マイコンピュータの使い方」巻末掲載)も無事稼働しました!! やったー
BASICソースをTeraTermで流し込みする場合は、1行ごとのwaitを200msぐらいとってあげると安心です。取りこぼしがひどいのです。

今後の予定
高校時代にブルーバックスの「マイコンピュータをつかう」や専門書「マイコンの作り方使い方」などを見ながらMC6800系マイコンを自作してBASICが動いてTVに映るコンピュータを作りたかったと夢想していましたが、だいぶ近づいてきました。
今ならパソコン上のスクリーンエディタやMC6800クロスコンパイラがあったり、TeraTermでシリアル通信できたりするしますが、高校時代だとパソコンすら手元にない環境なので動かすことができたとは、とうてい思えませんが…😊
今回の対応で基本機能は整ってきましたので、今後は「USBかんたんホスト」でUSBキーボードをつないでスタンドアロンコンピュータにしたり、SBC-IOボードをつないで他の機器を制御したりできるようにしてみたいと思います。
コメント