ベーシックマスターのソフトウェア(4)続々々カセットテープ

BASICMASTER, 昔のパソコン

カセットテープルーチン(3)の続き。今回も BASICMASTERの300bps カセットルーチンについて調べてみる。

カセットフォーマットの詳細は BASICMASTER/documents/tape_format.md at main · zu2/BASICMASTER を参照のこと。

その他のテープ形式

BASICとモニタ以外でもテープへの保存は使われていた。その形式を見てみよう。


日立アセンブラ

拡張子は “.S"、ブロック種別は $10(可変アドレス)。 ソースコード全体が1つのファイルとして保存される。



ソースプログラム全体をベタ保存している。

可変アドレスなので、保存時と違うアドレスへの読み込みが行える。アセンブラソースの格納アドレスは、(BASICとは異なり)起動時に指定するのでどこになるかわからない。

ソースプログラム途中への読み込みもできるので、これを使って Mコマンド(MERGE,結合)操作を行なっている。

MERGEとなっているが実際の動作は途中から上書きであり、挿入・併合されるわけではない。
(マニュアルでは、Mコマンドは「修正行の次に」カセットの内容を読むと書かれているが、実際には修正行も上書きされる)


0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0040: ff 01 10 00 20 41 53 4d 20 20 2e 53 01 00 30 00  .... ASM  .S..0.
0050: fd 2a 20 50 52 49 4d 45 2d 31 20 4d 41 52 2e 31  .* PRIME-1 MAR.1
0060: 34 2e 31 39 38 30 0d 2a 0d 4e 3d 24 34 30 30 30  4.1980.*.N=$4000
0070: 20 51 3d 31 30 30 30 2a 32 2b 4e 0d 49 3d 32 2c   Q=1000*2+N.I=2,
0080: 31 30 30 30 0d 20 20 20 4e 28 49 29 3d 30 0d 5c  1000.   N(I)=0.\
0090: 0d 4b 3d 30 0d 50 3d 32 2c 31 30 30 30 0d 20 20  .K=0.P=2,1000.  
00a0: 3b 3d 4e 28 50 29 3c 30 20 23 3d 4c 39 30 3b 0d  ;=N(P)<0 #=L90;.
00b0: 20 20 4b 3d 4b 2b 31 0d 20 20 51 28 4b 29 3d 50    K=K+1.  Q(K)=P
00c0: 0d 20 20 3b 3d 50 3e 33 31 20 23 3d 4c 39 30 3b  .  ;=P>31 #=L90;
00d0: 0d 20 20 49 3d 50 0d 20 20 40 0d 20 20 20 20 20  .  I=P.  @.     
00e0: 4e 28 49 29 3d 2d 31 0d 20 20 20 20 20 49 3d 49  N(I)=-1.     I=I
00f0: 2b 50 0d 20 20 40 3d 49 3e 31 30 30 30 0d 4c 39  +P.  @=I>1000.L9
0100: 30 2e 0d 5c 0d 2a 20 50 52 49 4e 54 20 50 52 49  0..\.* PRINT PRI
0110: 4d 45 53 0d 2f 22 50 52 49 4d 45 53 20 28 55 4e  MES./"PRIMES (UN
0120: 44 45 52 20 31 30 30 30 29 3a 22 2f 0d 49 3d 31  DER 1000):"/.I=1
0130: 2c 4b 0d 20 20 3f 28 34 29 3d 51 28 49 29 0d 20  ,K.  ?(4)=Q(I). 
0140: 20 3b 3d 49 2d 28 28 49 2f 38 29 2a 38 29 3d 30   ;=I-((I/8)*8)=0
0150: 20 69 00 ff ff ff ff ff ff ff ff ff ff ff ff ff   i..............
0160: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0170: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0190: ff ff ff ff 01 10 00 20 41 53 4d 20 20 2e 53 02  ....... ASM  .S.
01a0: 12 31 00 e9 2f 20 3b 0d 5c 0d 41 3d 24 0d 3e 3d  .1../ ;.\.A=$.>=
01b0: 24 46 30 30 30 0d cf 00 ff ff ff ff ff ff ff ff  $F000...........
01c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
01d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
01e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
01f0: ff ff ff ff ff ff ff ff ff 01 00 00 20 41 53 4d  ............ ASM
0200: 20 20 2e 53 02 01 30 00 0b 2a d6 00                .S..0..*..


L1 BASIC

同じく、ソースコード全体をベタ保存している。




拡張子は “.S"、ブロック種別は $10(可変アドレス)。 ソースコード全体が1つのファイルとして保存される。


0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0040: ff 01 10 00 4c 31 54 45 53 54 2e 53 01 00 05 c0  ....L1TEST.S....
0050: ec 00 c8 0c 20 50 4f 4b 45 20 24 30 41 2c 30 0d  .... POKE $0A,0.
0060: 00 c9 0c 20 50 4f 4b 45 20 24 30 42 2c 30 0d 00  ... POKE $0B,0..
0070: ca 0c 20 50 4f 4b 45 20 24 30 43 2c 30 0d 01 2c  .. POKE $0C,0..,
0080: 0e 20 50 52 49 4e 54 22 53 54 41 52 54 22 0d 01  . PRINT"START"..
0090: 90 05 20 4b 3d 30 0d 01 ae 0a 20 44 49 4d 20 4d  .. K=0.... DIM M
00a0: 28 35 29 0d 01 f4 07 20 4b 3d 4b 2b 31 0d 01 fe  (5).... K=K+1...
00b0: 0d 20 41 3d 4b 2f 32 2a 33 2b 34 2d 35 0d 02 08  . A=K/2*3+4-5...
00c0: 0b 20 47 4f 53 55 42 20 38 32 30 0d 02 12 0e 20  . GOSUB 820.... 
00d0: 46 4f 52 20 4c 3d 31 20 54 4f 20 35 0d 02 17 08  FOR L=1 TO 5....
00e0: 20 4d 28 4c 29 3d 41 0d 02 1c 08 20 4e 45 58 54   M(L)=A.... NEXT
00f0: 20 4c 0d 02 58 14 20 49 46 20 4b 3c 31 30 30 30   L..X. IF K<1000
0100: 20 47 4f 54 4f 20 35 30 30 0d 02 bc 0c 20 50 52   GOTO 500.... PR
0110: 49 4e 54 22 45 4e 44 22 0d 02 ee 29 20 50 52 49  INT"END"...) PRI
0120: 4e 54 20 50 45 45 4b 28 24 30 41 29 2a 32 35 36  NT PEEK($0A)*256
0130: 2b 50 45 45 4b 28 24 30 42 29 2c 50 45 45 4b 28  +PEEK($0B),PEEK(
0140: 24 30 43 29 0d 03 20 05 20 45 4e 44 0d 03 34 08  $0C).. . END..4.
0150: 20 12 00 ff ff ff ff ff ff ff ff ff ff ff ff ff   ...............
0160: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0170: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0190: ff ff ff ff 01 10 00 4c 31 54 45 53 54 2e 53 02  .......L1TEST.S.
01a0: 0f 06 c0 db 52 45 54 55 52 4e 0d ff ff 04 45 4e  ....RETURN....EN
01b0: 44 0d ff 2e 00 ff ff ff ff ff ff ff ff ff ff ff  D...............
01c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
01d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
01e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
01f0: ff ff ff ff ff ff 01 00 00 4c 31 54 45 53 54 2e  .........L1TEST.
0200: 53 02 01 05 c0 fa 00 00 00                       S........



そもそも カセットの保存機能そのものが L1 BASICのために作られたと思われるので、素直に実装されている。


GAME-BM

GAME言語のBASICMASTER移植版。 [=0 で独自モニタに飛び、そこでSAVEする。




こちらも 拡張子は “.S"、ブロック種別は $10(可変アドレス)。 ソースコード全体が1つのファイルとして保存される。

読み込むソースプログラムの位置を変更したい場合は、事前に == でアドレスを指定すれば良い。LOADの際は =(開始ポインタ) で指定したアドレスに読まれる。


00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000040: ff 01 10 00 47 41 4d 45 20 20 2e 53 01 00 1a 00  ....GAME  .S....
00000050: fa 00 c8 20 56 3d 24 30 41 20 56 28 30 29 3d 30  ... V=$0A V(0)=0
00000060: 20 56 3a 32 29 3d 30 20 56 28 30 29 3d 30 00 01   V:2)=0 V(0)=0..
00000070: 2c 20 22 53 54 41 52 54 22 00 01 90 20 4b 3d 30  , "START"... K=0
00000080: 00 01 ae 20 4d 3d 26 00 01 f4 20 4b 3d 4b 2b 31  ... M=&... K=K+1
00000090: 00 01 fe 20 41 3d 4b 2f 32 2a 33 2b 34 2d 35 00  ... A=K/2*3+4-5.
000000a0: 02 08 20 21 3d 38 32 30 00 02 12 20 4c 3d 31 2c  .. !=820... L=1,
000000b0: 35 00 02 15 20 4d 28 4c 29 3d 30 00 02 17 20 40  5... M(L)=0... @
000000c0: 3d 4c 2b 31 00 02 1c 20 3b 3d 4b 3c 31 30 30 30  =L+1... ;=K<1000
000000d0: 20 23 3d 35 30 30 00 02 bc 20 22 45 4e 44 22 00   #=500... "END".
000000e0: 02 c6 20 57 3d 56 28 30 29 20 58 3d 56 3a 32 29  .. W=V(0) X=V:2)
000000f0: 20 2f 20 22 54 49 4d 45 3d 22 20 3f 3d 57 20 22   / "TIME=" ?=W "
00000100: 2e 22 20 3f 28 32 29 3d 28 58 2a 31 30 30 29 2f  ." ?(2)=(X*100)/
00000110: 36 30 00 03 20 20 23 3d 2d 31 00 03 34 20 5d 00  60..  #=-1..4 ].
00000120: 03 e5 2a 00 03 e6 2a 20 47 41 4d 45 2d 42 4d 20  ..*...* GAME-BM 
00000130: 54 45 53 54 20 50 52 4f 47 52 41 4d 00 03 e7 2a  TEST PROGRAM...*
00000140: 20 4b 49 4c 4f 42 41 55 44 2f 41 53 43 49 49 20   KILOBAUD/ASCII 
00000150: 42 05 00 ff ff ff ff ff ff ff ff ff ff ff ff ff  B...............
00000160: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000170: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000190: ff ff ff ff 01 10 00 47 41 4d 45 20 20 2e 53 02  .......GAME  .S.
000001a0: 09 1b 00 ef 45 4e 43 48 4d 41 52 4b 00 b7 00 ff  ....ENCHMARK....
000001b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000001c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000001d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000001e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000001f0: 01 00 00 47 41 4d 45 20 20 2e 53 02 01 1a 00 08  ...GAME  .S.....
00000200: 00 00 00                                         ...


GAME68/BM

GAME言語のもう一つの移植版。

LOAD/SAVEは L2 BASICと同様にテキスト形式になっている。




ソースコードがそのまま保存されているので、テープからプログラムを抜き出すのが簡単。MERGE(APPEND)も行えるのが利点。

GAME-MBのテープ形式では行番号が見えないし、行末は$00である。GAME68/BMは行番号が見えて、行末は$0D。

GAME-MBと非互換にするメリットがあるかどうか。互換バージョンがあった方が良いのかな?
(多くの人は emulator上で操作しているだろうから、そもそもSAVE操作なんかしていないのかも)


00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000040: ff 01 10 01 47 41 4d 45 36 38 2e 53 01 00 08 00  ....GAME68.S....
00000050: dd 32 30 30 20 56 3d 24 30 41 20 56 28 30 29 3d  .200 V=$0A V(0)=
00000060: 30 20 56 3a 32 29 3d 30 20 56 28 30 29 3d 30 0d  0 V:2)=0 V(0)=0.
00000070: 33 30 30 20 22 53 54 41 52 54 22 0d 34 30 30 20  300 "START".400 
00000080: 4b 3d 30 0d 34 33 30 20 4d 3d 26 0d 35 30 30 20  K=0.430 M=&.500 
00000090: 4b 3d 4b 2b 31 0d 35 31 30 20 41 3d 4b 2f 32 2a  K=K+1.510 A=K/2*
000000a0: 33 2b 34 2d 35 0d 35 32 30 20 21 3d 38 32 30 0d  3+4-5.520 !=820.
000000b0: 35 33 30 20 4c 3d 31 2c 35 0d 35 33 33 20 4d 28  530 L=1,5.533 M(
000000c0: 4c 29 3d 30 0d 35 33 35 20 40 3d 4c 2b 31 0d 35  L)=0.535 @=L+1.5
000000d0: 34 30 20 3b 3d 4b 3c 31 30 30 30 20 23 3d 35 30  40 ;=K<1000 #=50
000000e0: 30 0d 37 30 30 20 22 45 4e 44 22 0d 37 31 30 20  0.700 "END".710 
000000f0: 57 3d 56 28 30 29 20 58 3d 56 3a 32 29 20 2f 20  W=V(0) X=V:2) / 
00000100: 22 54 49 4d 45 3d 22 20 3f 3d 57 20 22 2e 22 20  "TIME=" ?=W "." 
00000110: 3f 28 32 29 3d 28 58 2a 31 30 30 29 2f 36 30 0d  ?(2)=(X*100)/60.
00000120: 38 30 30 20 23 3d 2d 31 0d 38 32 30 20 5d 0d 39  800 #=-1.820 ].9
00000130: 39 37 2a 0d 39 39 38 2a 20 47 41 4d 45 2d 42 4d  97*.998* GAME-BM
00000140: 20 54 45 53 54 20 50 52 4f 47 52 41 4d 0d 39 39   TEST PROGRAM.99
00000150: 39 0d 00 ff ff ff ff ff ff ff ff ff ff ff ff ff  9...............
00000160: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000170: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000190: ff ff ff ff 01 00 01 47 41 4d 45 36 38 2e 53 01  .......GAME68.S.
000001a0: 01 08 00 ec 32 ce 00 ff ff ff ff ff ff ff ff ff  ....2...........
000001b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000001c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000001d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000001e0: ff ff ff ff ff ff ff ff 01 10 02 47 41 4d 45 36  ...........GAME6
000001f0: 38 2e 53 01 12 08 00 ca 2a 20 4b 49 4c 4f 42 41  8.S.....* KILOBA
00000200: 55 44 2f 41 53 43 49 49 0d 00 c6 00 ff ff ff ff  UD/ASCII........
00000210: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000220: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000230: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000240: ff ff ff ff ff ff ff ff ff ff ff ff ff 01 00 02  ................
00000250: 47 41 4d 45 36 38 2e 53 01 01 08 00 eb 2a d6 00  GAME68.S.....*..


余談

BASICMASTERに先行する 日立のワンボードマイコン「H68/TR」にもカセットインターフェイスがあった。

保存形式についての簡単な解説が、「H68/TR+TV01 オート・スタートのテープを作ろう」I/O誌1978年6月号 pp.132-133 に掲載されている。

この記事によると、H68/TRのテープ形式は以下の通り。

  • 680個の$FF
  • ブロック種別 'B', データ長1バイト, データ先頭アドレス2バイト、データ実体、レコード間GAP 25個の$FF
  • 複数ブロックがある場合は、'B' から GAP を繰り返す
  • ブロック種別 'G', フィーダー $FF (任意個)

BASICMASTERのヘッダ部分(ファイル名やブロック種別、チェックサム)に相当する部分は存在しない。

このI/O誌の記事ではオートスタートを実現するために、PIAのコントロールレジスタを叩いている(当該アドレスをブロックとしてSAVEする)。

これによりNMIがかかるので、あらかじめ先導ブロックでNMIの飛び先を設定する。実に豪快である。