(fds.c) backport new fds disk handling

backported from fceux, commit by dinkc64 (fbneo)
0b4be4b639

Fixes saving issue with some games (Bubble Bobble, Super Lode Runner II, ...)
This commit is contained in:
negativeExponent
2020-01-25 08:32:43 +08:00
parent fb516c853a
commit cd30d8cc40

182
src/fds.c
View File

@@ -82,6 +82,30 @@ static int32 DiskPtr;
static int32 DiskSeekIRQ;
static uint8 SelectDisk, InDisk;
/* dec-12-19 */
/* 4024(w), 4025(w), 4031(r) by dink(fbneo) */
/* remove this and old code after testing phase */
#define USE_DINK
enum FDS_DiskBlockIDs {
DSK_INIT = 0,
DSK_VOLUME,
DSK_FILECNT,
DSK_FILEHDR,
DSK_FILEDATA
};
static uint8 mapperFDS_control; /* 4025(w) control register */
static uint16 mapperFDS_filesize; /* size of file being read/written */
static uint8 mapperFDS_block; /* block-id of current block */
static uint16 mapperFDS_blockstart; /* start-address of current block */
static uint16 mapperFDS_blocklen; /* length of current block */
static uint16 mapperFDS_diskaddr; /* current address relative to blockstart */
static uint8 mapperFDS_diskaccess; /* disk needs to be accessed at least once before writing */
#define GET_FDS_DISK() (diskdata[InDisk][mapperFDS_blockstart + mapperFDS_diskaddr])
#define FDS_DISK_INSERTED (InDisk != 255)
uint32 lastDiskPtrRead, lastDiskPtrWrite;
#define DC_INC 1
@@ -148,6 +172,16 @@ static void FDSInit(void) {
FDSSoundReset();
InDisk = 0;
SelectDisk = 0;
#ifdef USE_DINK
mapperFDS_control = 0;
mapperFDS_filesize = 0;
mapperFDS_block = 0;
mapperFDS_blockstart = 0;
mapperFDS_blocklen = 0;
mapperFDS_diskaddr = 0;
mapperFDS_diskaccess = 0;
#endif
}
void FCEU_FDSInsert(int oride) {
@@ -216,6 +250,7 @@ static DECLFR(FDSRead4030) {
return ret;
}
#ifndef USE_DINK
static DECLFR(FDSRead4031) {
static uint8 z = 0;
if (InDisk != 255) {
@@ -232,6 +267,51 @@ static DECLFR(FDSRead4031) {
}
return z;
}
#else /* USE_DISK */
static DECLFR(FDSRead4031) {
uint8 ret = 0xff;
if (FDS_DISK_INSERTED && mapperFDS_control & 0x04) {
mapperFDS_diskaccess = 1;
ret = 0;
switch (mapperFDS_block) {
case DSK_FILEHDR:
if (mapperFDS_diskaddr < mapperFDS_blocklen) {
ret = GET_FDS_DISK();
switch (mapperFDS_diskaddr) {
case 13:
mapperFDS_filesize = ret;
break;
case 14:
mapperFDS_filesize |= ret << 8;
/* char fdsfile[10]; */
/* strncpy(fdsfile, (char*)&diskdata[InDisk][mapperFDS_blockstart + 3], 8); */
/* printf("Read file: %s (size: %d)\n"), fdsfile, mapperFDS_filesize); */
break;
}
mapperFDS_diskaddr++;
}
break;
default:
if (mapperFDS_diskaddr < mapperFDS_blocklen) {
ret = GET_FDS_DISK();
mapperFDS_diskaddr++;
}
break;
}
DiskSeekIRQ = 150;
X6502_IRQEnd(FCEU_IQEXT2);
}
return ret;
}
#endif /* USE_DINK */
static DECLFR(FDSRead4032) {
uint8 ret;
@@ -530,6 +610,7 @@ static DECLFW(FDSWrite) {
X6502_IRQEnd(FCEU_IQEXT2);
}
case 0x4024:
#ifndef USE_DINK
if ((InDisk != 255) && !(FDSRegs[5] & 0x4) && (FDSRegs[3] & 0x1)) {
if (DiskPtr >= 0 && DiskPtr < 65500) {
if (writeskip)
@@ -541,8 +622,43 @@ static DECLFW(FDSWrite) {
}
}
}
#else /* USE_DINK */
if (FDS_DISK_INSERTED && ~mapperFDS_control & 0x04) {
if (mapperFDS_diskaccess == 0) {
mapperFDS_diskaccess = 1;
break;
}
switch (mapperFDS_block) {
case DSK_FILEHDR:
if (mapperFDS_diskaddr < mapperFDS_blocklen) {
GET_FDS_DISK() = V;
switch (mapperFDS_diskaddr) {
case 13: mapperFDS_filesize = V; break;
case 14:
mapperFDS_filesize |= V << 8;
/* char fdsfile[10]; */
/* strncpy(fdsfile, (char*)&diskdata[InDisk][mapperFDS_blockstart + 3], 8); */
/* printf("Write file: %s (size: %d)\n"), fdsfile, mapperFDS_filesize); */
break;
}
mapperFDS_diskaddr++;
}
break;
default:
if (mapperFDS_diskaddr < mapperFDS_blocklen) {
GET_FDS_DISK() = V;
mapperFDS_diskaddr++;
}
break;
}
}
#endif /* USE_DINK */
break;
case 0x4025:
#ifndef USE_DINK
X6502_IRQEnd(FCEU_IQEXT2);
if (InDisk != 255) {
if (!(V & 0x40)) {
@@ -559,6 +675,55 @@ static DECLFW(FDSWrite) {
if (V & 0x40) DiskSeekIRQ = 200;
}
setmirror(((V >> 3) & 1) ^ 1);
#else /* USE_DINK */
X6502_IRQEnd(FCEU_IQEXT2);
if (FDS_DISK_INSERTED) {
if (V & 0x40 && ~mapperFDS_control & 0x40) {
mapperFDS_diskaccess = 0;
DiskSeekIRQ = 150;
/* blockstart - address of block on disk
* diskaddr - address relative to blockstart
* _block -> _blockID ?
*/
mapperFDS_blockstart += mapperFDS_diskaddr;
mapperFDS_diskaddr = 0;
mapperFDS_block++;
if (mapperFDS_block > DSK_FILEDATA)
mapperFDS_block = DSK_FILEHDR;
switch (mapperFDS_block) {
case DSK_VOLUME:
mapperFDS_blocklen = 0x38;
break;
case DSK_FILECNT:
mapperFDS_blocklen = 0x02;
break;
case DSK_FILEHDR:
mapperFDS_blocklen = 0x10;
break;
case DSK_FILEDATA: /* <blockid><filedata> */
mapperFDS_blocklen = 0x01 + mapperFDS_filesize;
break;
}
}
if (V & 0x02) { /* transfer reset */
mapperFDS_block = DSK_INIT;
mapperFDS_blockstart = 0;
mapperFDS_blocklen = 0;
mapperFDS_diskaddr = 0;
DiskSeekIRQ = 150;
}
if (V & 0x40) { /* turn on motor */
DiskSeekIRQ = 150;
}
}
mapperFDS_control = V;
setmirror(((V >> 3) & 1) ^ 1);
#endif /* USE_DINK */
break;
}
FDSRegs[A & 7] = V;
@@ -903,15 +1068,24 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
AddExState(&FDSRegs[3], 1, 0, "REG4");
AddExState(&FDSRegs[4], 1, 0, "REG5");
AddExState(&FDSRegs[5], 1, 0, "REG6");
AddExState(&IRQCount, 4, 1, "IRQC");
AddExState(&IRQLatch, 4, 1, "IQL1");
AddExState(&IRQCount, 4 | FCEUSTATE_RLSB, 1, "IRQC");
AddExState(&IRQLatch, 4 | FCEUSTATE_RLSB, 1, "IQL1");
AddExState(&IRQa, 1, 0, "IRQA");
AddExState(&writeskip, 1, 0, "WSKI");
AddExState(&DiskPtr, 4, 1, "DPTR");
AddExState(&DiskSeekIRQ, 4, 1, "DSIR");
AddExState(&DiskPtr, 4 | FCEUSTATE_RLSB, 1, "DPTR");
AddExState(&DiskSeekIRQ, 4 | FCEUSTATE_RLSB, 1, "DSIR");
AddExState(&SelectDisk, 1, 0, "SELD");
AddExState(&InDisk, 1, 0, "INDI");
AddExState(&DiskWritten, 1, 0, "DSKW");
#ifdef USE_DINK
AddExState(&mapperFDS_control, 1, 0, "CTRG");
AddExState(&mapperFDS_filesize, 2 | FCEUSTATE_RLSB, 1, "FLSZ");
AddExState(&mapperFDS_block, 1, 0, "BLCK");
AddExState(&mapperFDS_blockstart, 2 | FCEUSTATE_RLSB, 1, "BLKS");
AddExState(&mapperFDS_blocklen, 2 | FCEUSTATE_RLSB, 1, "BLKL");
AddExState(&mapperFDS_diskaddr, 2 | FCEUSTATE_RLSB, 1, "DADR");
AddExState(&mapperFDS_diskaccess, 1, 0, "DACC");
#endif
CHRRAMSize = 8192;
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);