SSブログ

またしても修正版です…申し訳ありません。 [お知らせ]

「Dash-80 Version 1.0b」をリリースいたしました。
先日リリースした「Dash-80 Version 1.0a」では、バイナリのロード不具合を修正したのですが、RC-3 でエンバグした箇所がもうひとつ残っていたため、BASIC ファイルが正常にロードできなくなっておりましたm(_~_)m

今回は間違いなくバグフリー…のはずです^^;(本当か…)

バグが残っているものをリリースしすぎると、信用をなくすよなぁ。
…って、もう既に無いような気がします(反省)


本館サイト「Retro Computer People - Programs - Dash-80」からダウンロードできます。

また、動作報告とか頂けたら大変ありがたいです。

BSAVE / SAVEM 前史 #3 [プログラム]

2010/03/19 プログラム解説部分を加筆修正しました

この記事は「BSAVE / SAVEM 前史 #2」の続きです。


セーブしたいデータ個数分だけループを回す方法だと、データ量が多くなればなるほど時間が掛かります。
しかも、ループ内でやっている事と言えば、メモリ上にあるデータをバッファ内に、そっくりそのままコピーするだけです。

バッファへデータをコピーするなら、マシン語を使用してブロック転送をする方法もあるのですが、BSAVE をするプログラムが BLOAD を必要とするというのも…。
かと言って、プログラム内にデータ文でマシン語を格納するとプログラムが肥大化してしまいます。

そこで、ちょっとトリッキーな方法ですが VARPTR() を使用した方法にトライしてみます。




N-BASIC には VARPTR() という関数があり、変数の値が保存されているアドレスを調べることができます。
数値変数では、そのアドレスに整数型/単精度型/倍精度型それぞれが2/4/8バイトで保存されています。
文字列変数だけは特別で、VARPTR() で返されるアドレス AD に文字数、AD+1, AD+2 に実際に値が保存されているアドレス(ポインタですね)が保存されています (この 3 bytes をまとめてストリングディスクリプタと呼んでいます)。

このストリングディスクリプタを操作すれば、コピーを繰り返すことなくバッファにデータセットできるはずです。

DEFINT A-Z
T1$="":T2$=""
FIELD #1, 128 AS D1$, 128 AS D2$
    |
FOR AD!=BA! TO EA! STEP 256
    |
  POKE VARPTR(T1$)  ,128
  POKE VARPTR(T1$)+1,PEEK(VATPTR(A1))
  POKE VARPTR(T1$)+2,PEEK(VATPTR(A1)+1)
  POKE VARPTR(T2$)  ,128
  POKE VARPTR(T2$)+1,PEEK(VATPTR(A2))
  POKE VARPTR(T2$)+2,PEEK(VATPTR(A2)+1)
  LSET D1$=T1$:LSET D2$=T2$
  PUT #1,RC:RC=RC+1
    |
NEXT
CLOSE #1

1レコードは 256 bytes なのですが、文字列変数には 255 bytes までしか入れられないので、仕方なく2つの変数に分割してあり、似たような処理が二つありますが、メインとなる処理はこれだけです。
A1, A2 の二つの整数変数にはセーブしたい領域の先頭アドレスが入っていて、T1$, T2$ の二つのストリングディスクリプタに文字数とアドレスを強制的に代入しています。
その後、LSET D1$=T1$:LSET D2$=T2$ とすることで、バッファ内へデータをコピーしています。

前回のプログラムではデータ個数分だけループを回していましたが、今回はレコード数分だけ回せばいいので結果的に処理速度は向上します。

Binary data saving sample program #2 (N-BASIC)
バイナリデータセーブ サンプルプログラム #2 (N-BASIC)


ただでさえ少ない Disk-BASIC のメモリをバイナリセーバー自身が浪費してしまわないように注力した結果出来上がったのがこのプログラムです。

前回のモノに比べるとプログラムが大きくなってしまっているのが難点ですが、配列変数を使用しなくなったので全体としてのメモリ使用量は減っています。
前回のように文字列型の配列変数を 256 個定義すると、ストリングディスクリプタだけで 768 bytes もメモリを消費してしまいますから。
N-BASIC に unsigned int 変数型が用意されていれば、もう少しプログラムサイズも小さくなるのでしょうがね…。

ちなみに、掲載した N-BASIC のプログラムはデバッグ済みですので問題なく利用していただけるはずですが、ご使用は自己責任でお願いします。

おわり

タグ:N-BASIC PC-8001

BSAVE / SAVEM 前史 #2 [プログラム]

2010/03/18 タイトルを変更しました

この記事は「BSAVE / SAVEM 前史 #1」の続きです。


シーケンシャルファイルだと収納効率が悪いので、ランダムファイルを使用した方法を考えてみます。
PEEK() 関数で読み込んだデータを FIELD 命令を使ってバッファにセットするというのはどうでしょう。

ファイルバッファのサイズは 256 bytes 固定なので、256 個の要素を持つ整数配列を使用してその中に格納するようにします。

FOR AD!=BA! TO EA!
    |
  FOR I=0 TO 255
    D$(I)=CHR$(PEEK(AD))
  NEXT
    |
  FOR I=0 TO 255
    LSET B$(I)=D$(I)
  NEXT
  PUT #1,RC
    |
NEXT

1 byte をセットするのにループを2回繰り返すため効率が悪いので、2個のループをまとめてしまいます。
FOR AD!=BA! TO EA!
    |
  FOR I=0 TO 255
    LSET D$(I)=CHR$(PEEK(AD))
  NEXT
    |
  PUT #1,RC
    |
NEXT


この処理をコアにしてオプションパーツをコテコテと貼り付け、N-BASIC 用の MOUNT / REMOVE 処理を振りかけたモノが以下のプログラムです。

Binary data saving sample program (N-BASIC)
バイナリデータセーブ サンプルプログラム(N-BASIC)

セーブしたいデータ個数分だけループを回し、データバッファが満杯になるとディスクへ書き出しています。
でも、ループ内でやっている事と言えば、メモリ上にあったデータがバッファ内に、そっくりそのままコピーされただけなんですよね。
コピーするだけなら、もっと賢い方法があるんじゃないかという事で、次回に続きます。

つづく

タグ:N-BASIC PC-8001

BSAVE / SAVEM 前史 #1 [プログラム]

2010/03/18 タイトルを変更しました

マシン語を使用したモノや BASIC のデータ領域/ワークエリア等を保存する方法として、まず最初に思いつくのはモニタモードでカセットテープに保存する方法ですが、これは速度も遅く信頼性も低いものでした。
「じゃあ、ディスクへの保存なら大丈夫だろう」と考えますが、最初期の Disk-BASIC には BSAVE / SAVEM 等のバイナリデータ保存用の命令はありませんでした。

話は横へそれますが


APPLE II は別として、国産 PC で FM-8 以前にディスクへのバイナリデータのロード/セーブが可能だったモノってありましたっけ?
そう考えると APPLE II って偉大です。

それはさておき


BASIC にバイナリデータのロード/セーブ命令が無いといってバイナリデータを扱えなかった訳ではありません。
BASIC に精通した真のプログラマは、プログラムを組んで問題を解決するものです。

まず最初に思いつくのは、メモリから PEEK() 関数を使用して読み込んだデータをシーケンシャルファイルに出力する方法ですが、これには問題があります。

BASIC のリファレンスマニュアルにはあまり詳しく書かれていないのですが、シーケンシャルファイルで扱えるデータは基本的にテキストデータだけ(',' (コンマ)を除く 20H から 7EH と 80H から FFH まで)です。
シーケンシャルファイル入力で使用する INPUT # 命令は INPUT 命令と違いコンソールからではなくファイルから入力を行います。 しかし、これはコンソールからの入力と同様にコントロールコードが有効になっているのです。
INPUT 命令では入力時に CR / ',' (コンマ) はデータの区切り/終了を意味しますが、同様に INPUT # 命令でも入力される文字列中に LF / CR / ',' (コンマ)が現れるとデータの区切りとみなされるため、データとしては無視されてしまいます。 また、00H も無視されてしまいます。

N-BASIC では、
00H(Null), 07H(Bell), 0AH(LineFeed), 0BH(Home), 0CH(Clear), 0DH(CarriageReturn), 1CH(CursorRight), 1DH(CursorLeft), 1EH(CursorUp), 1FH(CursorDown)
が、影響を受けるコードです。

そのため、影響を受けるコードを正常に読み込むには、例えば 00H → \@, 07H → \G, \ → \\ という具合にエスケープシーケンスを使用して 20H 以上のコードに変換しておく必要があります。
これだとデータを取りこぼすことなく読み込めますが、文字列変数に格納されたデータを1文字づつ取り出してチェックし、エスケープシーケンスならばコントロールコードに戻す必要があり、処理時間が多くかかります。
その上 20H 以下のデータが大量に存在するとデータの収納効率が非常に悪ってしまうので、ディスクの容量を節約するためにも、これよりもっとな方法を考えた方がいいですね。


つづく

タグ:PC-8001 N-BASIC

思考の迷宮 [近況報告]

Dash-80 の修正版のテスト中なんですが、ここのところ10日間ほど悩んでます。

PC-8801 mkII FR & SONY のマルチスキャンモニタはお亡くなりになっちゃいましたので、現在ウチで使用できる実機環境は PC-8001 + PC-8031 (どちらも無印)だけで、2D のシステムはテストできません(T_T)
なので、エミュレータ環境でのテストしかできないのですが…

実は、なぜか「無印 PC-8001」ではうまく動きません。

8001 の N-BASIC Ver 1.1 だとディスクサブシステムと通信する BASIC コマンドを実行すると、コマンド自体は終了するのですがサブシステム側のプログラムがハンドシェークルーチンから抜け出せなくなってしまいます。

FR に搭載されている N-BASIC Ver 1.8 だとうまく動作するんですがね…
サブシステム側の BIOS 部分って 80018031 も FR も同じはずなんですけど…

何か「思考の迷宮」にはまり込んじゃってます(T_T)

こうなったら、トレースログを取って Ver 1.8 と Ver 1.1 の処理の差を手作業で追っていかないとダメかなぁ。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。