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****はコード中で行番号を表現する際に使うようです。