カピバラ父さんのプログラミング処方箋~データファイルの書き出し

アプリケーションが管理するメモリに記憶している内容を、フロッピーディスクなどの 記録媒体にファイルとして書き出す方法について解説します。

書き出したデータファイルは、そのアプリケーションを終了し、再開するときや、 別のアプリケーションで再加工する用途に使うもので、ゲームであればセーブデータです。

DOSコールによる書き出し

ファイルを書き出す手順としては、新規ファイルを作る方法と、 既存ファイルを書き換える方法があります。
ファイルを開いてハンドルを得る方法が異なります。

ゲームのセーブデータを保存する用途の場合、古いファイルを残す必要はないので、 新規ファイルとして書き出す方法を使うのが簡単です。

_CREATE	equ	$ff3c
_WRITE	equ	$ff40
_CLOSE	equ	$ff3e

* in	a1:ファイル名
*	a2:データ領域の先頭アドレス
*	d1:データの大きさ
save_file:
	move	#$20,-(sp)	* A-----属性のファイル
	pea	(a1)
	DOS	_CREATE
	addq.l	#6,sp

	tst	d0		* エラーだったら終了
	bmi	@f

		move.l	d1,-(sp)
		pea	(a2)
		move	d0,-(sp)
		DOS	_WRITE
		DOS	_CLOSE
		lea	10(sp),sp
		moveq.l	#0,d0		
	@@:
	rts

DOSコールの_CREATEは、新規ファイルを作成するAPIです。

引数として、ファイル属性値($20で良い)と、ファイル名のポインタをスタックに積みます。

正常に作成できたら、正の値でファイルハンドルがd0に帰ってきます。

_WRITEの呼び出しは、_READと同様で、ロングワードでデータ長、ロングワードでデータアドレス、 そしてd0に帰ってきたファイルハンドルをスタックに積みます。

書き込み時の配慮事項

フロッピーからのデータの読み込みは、プログラム起動時に一気に読み込んでしまうことが多いので あまり神経質になる必要はないのですが、フロッピーなど差し替え可能なメディアにデータを書くときは、 いろいろな事態を想定しておくことが望まれます。

ディスク挿入確認

ゲームの起動が終わった段階で、ユーザがフロッピーディスクを取り出す可能性があります。

そこで、書き込み処理を行う前に、フロッピーディスクがドライブに入っていることを確認します。

_DRVCTRL	equ	$ff0f

check_media:
	clr	-(sp)		* カレントドライブの状態確認
	DOS	_DRVCTRL
	addq.l	#2,sp
	
	btst	#1,d0		* bit1: メディア挿入時、1
	bne	@f
	
	*	挿入されていないときの対応
	
	@@:
	rts

_DRVCTRLは多機能なディスクドライブ制御APIです。

上のサンプルでは、カレントドライブの状態確認ということで、引数に0を指定しました。

挿入されていないときの対応については、エラーメッセージを表示するとか、 挿入を促すLED点滅をする(これもDRVCTRLで可能)とか、工夫できます。

挿入されているディスクが本来のものかどうか確認が必要であれば、何かのファイルを読み込み、 照合する方法が良いと思います。

書き込み禁止確認

実機の場合、フロッピーディスクの側面に切り欠きがあって、シールで塞ぐと書き込み禁止にできます。

ライトプロテクト状態の確認にも、先程のDRVCTRLを使います。

	clr	-(sp)		* カレントドライブの状態確認
	DOS	_DRVCTRL
	addq.l	#2,sp
	
	btst	#3,d0		* bit3: ライトプロテクト時、1
	beq	@f

	*	ライトプロテクト時の対応
	
	@@:
	rts
分岐条件がメディア挿入チェック時と逆なことに気をつけてください。

ちなみに、書き込み禁止になっているフロッピーでCREATEを実行すると白窓エラーになります。

ディスク残量確認

既存データファイルを上書きする場合には、不要な確認ですが、 ファイル名を変えて書き足していく設計の場合は、ディスクの残量確認が必要です。

_DSKFRE	equ	$ff36

	subq.l	#8,sp
	pea	(sp)
	clr	-(sp)
	DOS	_DSKFRE
	lea	14(sp),sp
	
	cmp.l	d1,d0
	bpl	@f
	
		* 空き容量が不足する場合の対応
		
	@@:

_DSKFREの戻り値d0が、正数なら利用可能なバイト数で、負数ならエラーコードです。

引数は、ドライブ番号(0=カレントドライブ)、4ワード分(8バイト)のバッファアドレスを指定します。

バッファの4ワードには、

  1. 使用可能なクラス多数
  2. 総クラス多数
  3. 1クラスタあたりのセクタ数
  4. 1セクタあたりのバイト数
が得られますが、このサンプルでは利用していません。

ちなみに、残量以外にも、ディレクトリに置けるファイル数の制限がありますので、 無限にファイルを作るような実装は、やめておいたほうが無難かもしれません。

X68000Zにおける留意事項

X68000Zのフロッピーディスクは、SDHCカード内のXDFファイル(ディスクイメージ)で扱う仕様です。

このディスクイメージは、エミュレータでの書き込み操作時ではなく、イジェクトや電源オフなど、 特定操作時に書き戻す方式であるため、ソフトウェア処理としては書き込みが終わったつもりでも、 イメージが更新されていないタイミングが発生します。

特に、EAK(アーリーアクセスキット:グレーモデル)のX68000Zの場合、 本体上部のリセットボタンを押すとエミュレータそのものがリセットされて、 書き戻すべきイメージデータが失われます。

ソフトウェアでフロッピーディスクをイジェクトすることで強制書き出しできそうですが、 プレイ続行時に再マウント操作が必要となり、地味にプレイヤーの負担になるので、 注意喚起レベルでの対策が現実的ではないかと思います。


プログラミング処方箋へ

Copyright©2026 カピバラ父さん