Yet Another NEC PC-6601 Emulator その7

ディスク関連のバグ見つけました。あとは2ドライブが正しく動けばいい感じです。

http://www.geocities.jp/parallel_computer_inc/android.html

症状1:Androidでは動くけど、Windowsでは動かない。

原因1:fopenで"r+"または"r"としていたためftellが正しくない値を返していた。

対策1:fopenで"r+b"または"rb"とする。

// mount
int Mount88(int drvno, char *fname)
{
	strcpy(FileName88[drvno], fname);
	// open file
	// open with read & write
	if (!(d88[drvno].fp=fopen( FileName88[drvno], "r+b"))) {
		// if No, open with read only
		if (!(d88[drvno].fp=fopen(FileName88[drvno], "rb"))) {
			*FileName88[drvno] = 0;
			return 0;
		} else
			Protected88[drvno] = 1;	// protect is yes
	}
	return ReadHeader88(drvno);	// read D88 header
}

(省略)

// read D88 sector information
static void ReadSector88(int drvno)
{
	if (d88[drvno].fp) {
		d88[drvno].secinfo.c = fgetc(d88[drvno].fp);				// C of ID (cylinder No, when one side, track No)
		d88[drvno].secinfo.h = fgetc(d88[drvno].fp);				// H of ID (header address, when one side, 0)
		d88[drvno].secinfo.r = fgetc(d88[drvno].fp);				// R of ID (sector No in a track)
		d88[drvno].secinfo.n = fgetc(d88[drvno].fp);				// N of ID (sector size 0:256 1:256 2:512 3:1024)
		d88[drvno].secinfo.sec_nr = GETWORD(d88[drvno].fp);		// sector number in this track
		d88[drvno].secinfo.density = fgetc(d88[drvno].fp);		// density     0x00:double  0x40:single
		d88[drvno].secinfo.deleted = fgetc(d88[drvno].fp);		// DELETED MARK 0x00:normal 0x10:deleted
		d88[drvno].secinfo.status = fgetc(d88[drvno].fp);			// status
		fread(d88[drvno].secinfo.reserve, sizeof(unsigned char), 5, d88[drvno].fp);	// read reserve
		d88[drvno].secinfo.size = GETWORD(d88[drvno].fp);			// data size of this sector part
		d88[drvno].secinfo.data = ftell( d88[drvno].fp );			// offset to data
		d88[drvno].secinfo.offset = 0;						// offset to the next data from first sector
	}
}

症状2:DEBUGビルドでは動くけど、RELEASEビルドでは動かない。

原因2:マクロ展開が正しくない動作をしていた。

#define ZeroMemory(d,l)		memset((d), 0, (l))
#define GETWORD(fp)			((unsigned short)(((unsigned char)fgetc(fp))|((unsigned char)fgetc(fp)<<8)))
#define GETDWORD(fp)		((unsigned long)(((unsigned char)fgetc(fp))|((unsigned char)fgetc(fp)<<8)|((unsigned char)fgetc(fp)<<16)|((unsigned char)fgetc(fp)<<24)))

対策1:マクロ展開後をイメージしてベタに実装する。

memset(d88, 0, sizeof(D88INFO) * 2);

(省略)

d88[drvno].size = fgetc(d88[drvno].fp);
d88[drvno].size += (fgetc(d88[drvno].fp)<<8);
d88[drvno].size += (fgetc(d88[drvno].fp)<<16);
d88[drvno].size += (fgetc(d88[drvno].fp)<<24);

(省略)

d88[drvno].secinfo.sec_nr = fgetc(d88[drvno].fp);		// sector number in this track
d88[drvno].secinfo.sec_nr += (fgetc(d88[drvno].fp)<<8);			// data size of this sector part