BSAVEデータ・フォーマット概要
実質XOUT/XINの2ピンで通信する形式のようです。 他のピンは通信相手によっては使いますが、使わなくとも通信は可能のようです。
ポケコンからBSAVEするときは、11pinポートのXOUT(7ピン)からPWMでデータが出力されています。 XOUTピンをロジアナで観察し、データを解析したところ下記のようなフォーマットだとわかりました。 ブロック名などは私が勝手に命名しました。
ブロック | 解説 |
---|---|
PULSES1 | 約8秒の長いH/Lパルス列 |
PWM1 | データ1 |
PULSES2 | 約2秒の長いH/Lパルス列 |
PWM2 | データ2 |
PULSES3 | 約4秒の長いH/Lパルス列 |
データはPWM1,PWM2の2群に格納されています。前半のPWM1は、メインデータの種類やサイズなどの情報で、メインデータ本体は後半のPWM2に含まれています。
次項以降で各フォーマットの詳細を確認していきます。
PULSES1,2,3
比較的長いH/Lが続く期間。 パルスに意味があるのかは不明ですが、なにぶん長いですねえ。 たかだか10バイトの転送でも14秒超のオーバヘッドが乗ることになり、省略できないものかなあと思っています。
ブロック | 解説 |
---|---|
PULSES1 | H(30)-L(8000) |
PULSES2 | L(2000)-H(30)- L(24)-H(30)-L(6) |
PULSES3 | L(4000)-H(30) |
表記のH(30)はH期間が30[msec]続くという意味です。
PWM
PWM部では短長2種類のHLパルスで0/1データを表現しています。
- 長い方(1データ)のH期間は実測406[usec]
- 短い方(0データ)のH期間は実測162[usec]
なので、読み側は立ち上がりを検出したのち162x1.5=243[usec]後のデータを取り込めばデータと して抜き出せることになります。
PWM部分は2種類のモードが切り替わっているようです。これまたモード名は勝手に命名です。
モード名 | 解説 |
---|---|
bitseq | 1bitの0/1が長期間続くモード |
data | 1bitのスタートビットと8bitのデータの合わせて9bitの組が繰り返されるモード |
PWM1
PWMデータの前半部分であるPWM1は下記のようなブロック構成になっています。
ブロック | モード | 説明 |
---|---|---|
PWM_HEADER1 | bitseq | PLLロックのため?の長期間の単一周波数とか |
PWM_START_BIT | bitseq | 1bitの1を示すPWM波形 |
PWM_DATA1 | data | メインデータの種類やサイズなどを含むデータ |
PWM_PARITY | data | パリティ |
PWM_STOP_BIT | bitseq | 1bitの1を示すPWM波形 |
PWM_DATA1は下記のようなフォーマットと思われます。
0000: aa 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
0010: 20 0D bb bb 00 cc cc cc cc 00 00 00 00 00 00 FF
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
aa: モードと思われる。01はバイナリ、02はBasic。
bbbb: メインデータのバイト数。リトルエンディアン(下位バイト->上位バイト)
cccccccc: 謎。バイナリの場合:10FFFF00 basic:00000001
PWM_PARITYは16ビットのパリティで、ビッグエンディアン(上位バイト、下位バイト、の順)です。 パリティの計算は、PWM_DATA1に含まれる1の数のようです(これを突き止めるのに苦労しました)
データ以外のbitseqは下記のようになっています。
ブロック | データ |
---|---|
PWM_HEADER1 | 0*10000-1*40-0*40 |
PWM_START_BIT | 1*1 |
PWM_STOP_BIT | 1*1 |
0*40という表記は、0データが40個連続するという意味です。
PWM2
PWMデータの後半部分であるPWM2は下記のようなブロック構成になっています。
ブロック | モード | 説明 |
---|---|---|
PWM_HEADER2 | bitseq | PLLロックのため?の長期間の単一周波数とか |
PWM_START_BIT | bitseq | 1bitの1を示すPWM波形 |
PWM_DATA_MAIN | data | メインデータ |
PWM_PARITY | data | パリティ |
PWM_STOP_BIT | bitseq | 1bitの1を示すPWM波形 |
PWM_DATA_MAINが転送されるべきメインデータ本体です。PWM_PARITYはPWM1と同様で、PWM_DATA_MAINのパリティです。
データ以外のbitseqは下記のようになっています。
ブロック | データ |
---|---|
PWM_HEADER2 | 0*25848-1*20-0*20 |
PWM_START_BIT | 1*1 |
PWM_STOP_BIT | 1*1 |
Basic中間コードのデコード
basicの場合のメインデータ(PWM_DATA_MAIN)には、basicの中間コードが書かれています。
0000: FF 00 03 00 00 00 00 00 00 00 00 00 00 05 03 FE
0010: 50 0D 00 0A 0B FE 60 FE A0 31 30 30 30 30 30 0D
0020: 00 0F 0B FE 60 FE A0 31 30 30 30 30 30 0D 00 14
0030: 03 FE 2A 0D 00 1E 06 FE 2B 1F 00 0A 0D
最初のFF0003で始まる11バイトはなぞ。とくにコードを変えても変わらないようなので 固定のコードなのかなあ。
それ以降はもとのBASICコードと見比べると下記のような対応だと思われます。
行番号 | 行のバイト数 | 中間コード | BASICコード |
---|---|---|---|
0005 | 03 | FE50 0D | 5:CLS |
000A | 0B | FE60 FEA0 313030303030 0D | 10:PRINT RND 100000 |
000F | 0B | FE60 FEA0 313030303030 0D | 15:PRINT RND 100000 |
0014 | 03 | FE2A 0D | 20:WAIT |
001E | 06 | FE2B 1F000A 0D | 30:GOTO 10 |
コード中の0xFE**はBASIC中間コードに関する予約語です。BASIC中間コードの解説はこちらが詳しいです。
0x0Dは改行コード。0x1F****はコード中で行番号を表現する際に使うようです。