JavaScriptでJw_cad(.jww)のバイナリを読み解く その1
Jw_cadという、国産のCADソフトがあります。Jw_cadはデータのシリアライズ部分の仕様を公開しているので、サードパーティがソフトを開発する際にバイナリを無理やり解析する必要がありません。(もちろん、バイナリに関する知識は必要です。)
そこで、勉強を兼ねてJavaScriptでJWWバイナリを解析し、最終的にcanvasに出力するところまでを目標にがんばってみます。
バイナリを読み込むライブラリ
バイナリから型や値に変換することは今回の本質ではないので、潔く既存のバイナリリーダーを探します。今回はその名もずばりAjax Binary Readerを使うことにしました。
Hello, JWW!
まずデータを取ってきて変数に格納する部分ですが、本家のデモにあったソースをほぼそのまま使います。非同期になっていなかったりしますが、ひとまず気にせずに。
var load_binary_resource = function(url){
var req = new XMLHttpRequest();
req.open("GET", url, false);
req.overrideMimeType("text/plain; charset=x-user-defined");
req.send();
if(req.status != 200) return "";
return req.responseText;
};
var reader = new BinaryReader(load_binary_resource("sample.jww"));
この部分は問題なく動作しました。そして、資料を見ると、まず定義されているのが以下。
◆ JWWのデータファイルの宣言
ar.Write(“JwwData.”, 8);
この部分は簡単に、以下で読み取ることができます。
var declaration = reader.readString(8);
console.log(declaration); // => JwwData.
次に、バージョンナンバーが記されています。
◆ バージョンNo.
ar << (DWORD)JW_DATA_VERSION; 7.02の内部データ値は700
DWORD型?この辺の知識からまずあやふや…。なので検索してみると、unsigned long(32ビット符号なし整数)の別名だということがわかりました。それに対応するメソッドは、reader.readUInt32らしく、そのまま使ってもいいのですが、こちらもエイリアスを作ることにします。
BinaryReader.prototype.readDWORD = BinaryReader.prototype.readUInt32;
これを使って読んでみると、
var version = reader.readDWORD();
console.log(version); // => 420
無事読めました。資料のコメントにもありますが、どうやらバージョンナンバーx100の値が入っているようです。
次に出てきたのが、CString型。
◆ ファイルメモ
ar << (CString)m_strMemo;
読み込み方が分からない…終端がNull?とか考えたけど文字化け&後ろのデータがずれる…。そこでサンプルデータのバイナリを見てみると、
02 0d 0a 01 …
となっていることが分かりました。0d0aってことは改行で、その前の02は文字数ってことかな?と思いやってみると、無事読めた模様。その後ろも(おそらく)ずれることなく読めているようです。ただ、255文字しか入らない仕様?この辺はまたいつか再確認。
BinaryReader.prototype.readCString = function(){
var length = this.readUInt8();
return this.readString(length);
};
var memo = reader.readCString();
console.log(jww.memo); // => 改行コードだけ
この後、154行目まで読みましたが、
・DWORDの他にdoubleが出てきた
・forループが出てきた
くらいで、特に難しい箇所はありませんでした。その後を見ると、圧縮済み画像やクラスのシリアライズがあるようなので、まだまだ先は長そうです。
今後の課題
今回出てきたもの
- 変数名とオブジェクトの整理
- 値やマジックナンバーと意味の紐付け
- バージョンや設定ごとの値の計算
- 画像・オブジェクトのデシリアライズ
- 根気
TODO
- 全バイナリデータの読み込み
- 変数名とオブジェクトの整理
- canvasへの出力