mmmはTURBO Pascal 6.0で作成されたDOS汎用BBSホストプログラムで、Kuro氏が当時ASCII-NET等で公開していたが、転載禁止のβ版であるmmm50b3.lzh及びmmm450a.lzhを最後に作者多忙の為、バージョンアップされなくなっている。
尚、2000年以降は全て2028年(BBS上での表示は"28"もしくは"<8")になる問題から、2001年以降から未読ポインタが正常に動作しなくなるという、いわゆる2000年問題を抱えている。
これらの事情から過去のデータを他の環境に引き継ぐため、mmmの各データファイルのフォーマット解析をおこなった。
ここではmmm450a.lzhに含まれる、各ファイルの解説ドキュメント(DOC/FILES.DOC)に記載されていないものを中心に解析結果を記載している。
データファイルの種類と含まれる内容
データファイルにはテキストファイルとバイナリファイルの2種類がある。
テキストファイルは1行が0D、0Aで終わり、ファイル末尾に1Aは付かない。mmmはMS-DOS上で動作する為、文字コードはシフトJISを採用しており、エスケープシーケンスが含まれる場合もある。
バイナリファイルは固定長レコードで出来ており、レコード内には文字(8ビット長の文字コード)、文字列、日付(16ビット長の数値)、時間(16ビット長の数値)、8ビット長の数値、16ビット長の数値、32ビット長の数値があり、数値はリトルエンディアンで格納される。(例:04F835BAなら、BA、35、F8、04のように下位バイトから順に格納される)
文字列は1バイト目が2バイト目以降に続く文字列の長さを示しており、末尾に終端コード等は付かない。
日付はいわゆるFAT形式で上位7ビット分が1980年からの年数、次の4ビット分が月、下位5ビット分が日を表している。
時間もFAT形式で上位5ビット分が時、次の6ビット分が分、下位5ビット分が2秒ごとの数値を表している。
尚、どちらのファイルも基本的に同じ長さの内容変更か追記しか行われない。(ただし、追記した箇所の削除は行われる場合がある)
解析内容で使用する略記について
前項で解説した文字をCHAR、文字列をSTRN、日付をDATE、時間をTIME、8ビット長の数値をBYTE、16ビット長の数値をWORD、32ビット長の数値をLONGとして以後表記する。
BBSディレクトリ(ノートファイル)
ノートファイルのファイル名に拡張子を付加したものが、ノートファイルごとに格納されている。
.MSG
テキストファイルで、1行目にノートファイル名、2行目以降にノートファイルの紹介文章が格納されている。
.BAS(インデックスファイル)
1レコードが6バイトのバイナリファイルで、ベースノートが1つ作成されるごとに1レコード作成される。
- +0000 WORD ベースノートを示すIDXファイルのレコード番号
- +0002 TIME ベースノート内の最終更新日時(時間)
- +0004 DATE ベースノート内の最終更新日時(日付)
.IDX(インデックスファイル)
1レコードが105バイトのバイナリファイルで、ベースノートおよびレスポンス1つに対して1レコード作成される。
- +0000 STRN Subject ※ベースノートの場合はTitle
- +0029 TIME 作成日時(時間)
- +002B DATE 作成日時(日付)
- +002D STRN ID
- +0036 STRN ハンドルネーム
- +0047 LONG CMPファイル読み出し位置
- +004B LONG CMPファイル読み出し容量 ※Bytesで表示される本文のサイズでもある
- +004F STRN メッセージの種別 ※"Bas"ならベースノート、"Res"ならレスポンス
- +0053 WORD 親ベースノートを示すIDXファイルのレコード番号 ※ベースノートの場合はレスポンス数
- +0055 WORD 前のレスポンスまたはベースノートを示すIDXファイルのレコード番号
- +0057 WORD 次のレスポンスを示すIDXファイルのレコード番号 ※次が無い場合は0
- +0059 TIME このレコードの更新日時(時間)
- +005B DATE このレコードの更新日時(日付)
- +005D WORD 最終レスポンスを示すIDXファイルのレコード番号 ※レスポンスが無い場合は0
- +005F WORD レスポンス番号 ※ベースノートの場合はベースノート番号−1
- +0061 BYTE 削除フラグ ※最下位ビットが1なら削除マーク
- +0062 BYTE クローズフラグ ※最下位ビットが1ならclose設定
- +0063 BYTE 作成者専用フラグ ※最下位ビットが1ならauthor write onlyベースノート
- +0064 BYTE フラグ(?)
- +0065 BYTE フラグ(?) ※レスポンスの場合は最下位ビットが1になっている
- +0066 BYTE フラグ(?) ※レスポンスの場合は最下位ビットが1になっている
- +0067 BYTE フラグ(?) ※レスポンスの場合は最下位ビットが1になっている
- +0068 BYTE フラグ(?) ※レスポンスの場合は最下位ビットが1になっている
.CMP(本文データファイル)
テキストファイルで、ベースノート及びレスポンスの本文が連続で格納されている。どこからどこまでがベースノート及びレスポンスの本文になるかは、IDXファイルに書かれている。
FILERディレクトリ(ファイルライブラリ)
ファイルライブラリのライブラリ名で作られたディレクトリ内にFILER.IDX、FILER.CMP、RECORD.USRが格納されている。さらに登録されているファイル本体がアップロードされた順番に00001〜99999のファイル名(拡張子は無い)にリネームされて格納されている。
FILER.IDX(インデックスファイル)
1レコードが179バイトのバイナリファイルで、ファイルが1つ登録されるごとに1レコード作成される。
- +0000 WORD No. ※対応するファイル名も示している、削除された場合は0
- +0002 CHAR ファイル属性 ※'T'ならテキストファイル、'B'ならバイナリファイル
- +0003 STRN ファイル名
- +002C TIME 登録日時(時間)
- +002E DATE 登録日時(日付)
- +0030 STRN ID
- +0039 STRN ハンドルネーム
- +004A LONG CMPファイル読み出し位置
- +004E LONG CMPファイル読み出し容量
- +0052 STRN 1行コメント
- +0097 WORD アクセス回数
- +0099 STRN ファイル種別情報 ※2つの種別が付いている場合はスペースで区切る
- +00AC LONG ファイルサイズ
- +00AF WORD 登録されているファイルのタイムスタンプ(時間)
- +00B1 WORD 登録されているファイルのタイムスタンプ(日付)
FILER.CMP(データファイル)
テキストファイルで、詳細なコメントが連続で格納されている。どこからどこまでがどのファイルに対する詳細なコメントになるかは、FILER.IDXファイルに書かれている。
RECORD.USR
1レコードが4バイトのバイナリファイルで、ユーザーごとに1レコード作成される。(1レコード目が1番目に登録されたユーザーで、以後2番目に登録されたユーザー、3番目に登録されたユーザーと続く。)
- +0000 TIME 最終アップロードもしくはダウンロード日時(時間)※アップロードもダウンロードもしていない場合は0
- +0002 DATE 最終アップロードもしくはダウンロード日時(日付)※アップロードもダウンロードもしていない場合は0
TALKディレクトリ(talkルーム)
"R"に続けて1回線Talk(S-Talk)のルーム番号を記したファイル名に拡張子を付加したものが、ルームごとに格納されている。(例えば、Room 25ならR25.USR、R25.IDXというファイルが存在する。)
この他に全ルームの使用状況を表すROOMS.DATというファイルも格納されている。
ROOMS.DAT
1レコードが1バイトのバイナリファイルで、ルーム1つに対して1レコード作成される。1レコード目がRoom 1、2レコード目がRoom 2…1500レコード目がRoom 1500に対応している。最初から全ルームの使用状況が格納されている為、ファイルサイズは1500バイト固定。
- +0000 BYTE ルームの使用状況 ※0なら未使用、1なら使用中
.USR(参加ユーザー状態ファイル)
1レコードが31バイトのバイナリファイルで、1レコード目がルームの状態、2レコード目以降から1人参加するごとに参加者の情報が1レコード作成される。
- +0000 STRN ID ※ 1レコード目はルームの状態(Open、Closed、Lockedなど)
- +0009 TIME 更新日時(時間)
- +000B DATE 更新日時(日付)
- +000D STRN ハンドルネーム ※ 1レコード目は未使用
- +001E BYTE ユーザーフラグ ※ 1レコード目は未使用
※ユーザーフラグは最下位ビットから順に座席、ノック、リーダーを示しており、0なら無し、1なら有りとなる。
.IDX(発言内容ファイル)
1レコードが94バイトのバイナリファイルで、1レコード目がルーム名、2レコード目以降からルーム内のメッセージ1行につき、1レコード作成される。
- +0000 STRN ID ※ 1レコード目はルーム名
- +0009 TIME 作成日時(時間)
- +000B DATE 作成日時(日付)
- +000D STRN 発言内容 ※ システムが出力するメッセージも発言内容として記録されている