DS Slot-1: Emulate KEY delay, improve timing

This commit is contained in:
Vicki Pfau 2017-04-25 00:37:06 -07:00
parent 7879736a44
commit 04541e3b1d
3 changed files with 38 additions and 22 deletions

View File

@ -34,6 +34,7 @@ Misc:
- DS: Attempt to detect if a game is homebrew - DS: Attempt to detect if a game is homebrew
- Qt: Add .srl as an extension for DS ROMs - Qt: Add .srl as an extension for DS ROMs
- FFmpeg: Allow framerate to be adjusted - FFmpeg: Allow framerate to be adjusted
- DS Slot-1: Emulate KEY delay
0.6.0: (Future) 0.6.0: (Future)
Features: Features:

View File

@ -24,6 +24,8 @@ DECL_BIT(DSSlot1AUXSPICNT, DoIRQ, 14);
DECL_BIT(DSSlot1AUXSPICNT, Enable, 15); DECL_BIT(DSSlot1AUXSPICNT, Enable, 15);
DECL_BITFIELD(DSSlot1ROMCNT, uint32_t); DECL_BITFIELD(DSSlot1ROMCNT, uint32_t);
DECL_BITS(DSSlot1ROMCNT, Delay, 0, 12);
DECL_BITS(DSSlot1ROMCNT, Gap, 16, 5);
DECL_BIT(DSSlot1ROMCNT, WordReady, 23); DECL_BIT(DSSlot1ROMCNT, WordReady, 23);
DECL_BITS(DSSlot1ROMCNT, BlockSize, 24, 3); DECL_BITS(DSSlot1ROMCNT, BlockSize, 24, 3);
DECL_BIT(DSSlot1ROMCNT, TransferRate, 27); DECL_BIT(DSSlot1ROMCNT, TransferRate, 27);

View File

@ -49,10 +49,11 @@ static void _scheduleTransfer(struct DS* ds, struct mTiming* timing, uint32_t by
} else { } else {
cycles = 5; cycles = 5;
} }
cycles *= bytes;
if (!ds->ds7.memory.slot1Access) { if (!ds->ds7.memory.slot1Access) {
cycles <<= 1; cycles <<= 1;
} }
cycles *= bytes / 4;
cycles -= cyclesLate; cycles -= cyclesLate;
mTimingDeschedule(timing, &ds->memory.slot1.transferEvent); mTimingDeschedule(timing, &ds->memory.slot1.transferEvent);
mTimingSchedule(timing, &ds->memory.slot1.transferEvent, cycles); mTimingSchedule(timing, &ds->memory.slot1.transferEvent, cycles);
@ -91,23 +92,20 @@ static void _transferEvent(struct mTiming* timing, void* context, uint32_t cycle
ds->memory.slot1.dmaSource = -1; ds->memory.slot1.dmaSource = -1;
} }
if (ds->memory.slot1.transferRemaining) { ds->romVf->read(ds->romVf, ds->memory.slot1.readBuffer, 4);
ds->romVf->read(ds->romVf, ds->memory.slot1.readBuffer, 4); // TODO: Error check
// TODO: Error check ds->memory.slot1.address += 4;
ds->memory.slot1.address += 4; ds->memory.slot1.transferRemaining -= 4;
ds->memory.slot1.transferRemaining -= 4; romcnt = DSSlot1ROMCNTFillWordReady(romcnt);
romcnt = DSSlot1ROMCNTFillWordReady(romcnt);
if (hasDMA) { if (hasDMA) {
dma->when = mTimingCurrentTime(timing); dma->when = mTimingCurrentTime(timing);
dma->nextCount = 1; dma->nextCount = 1;
DSDMAUpdate(dscore); DSDMAUpdate(dscore);
} }
} else {
if (!ds->memory.slot1.transferRemaining) {
DSSlot1AUXSPICNT config = ds->memory.io7[DS_REG_AUXSPICNT >> 1]; DSSlot1AUXSPICNT config = ds->memory.io7[DS_REG_AUXSPICNT >> 1];
memset(ds->memory.slot1.readBuffer, 0, 4);
romcnt = DSSlot1ROMCNTClearWordReady(romcnt);
romcnt = DSSlot1ROMCNTClearBlockBusy(romcnt);
if (DSSlot1AUXSPICNTIsDoIRQ(config)) { if (DSSlot1AUXSPICNTIsDoIRQ(config)) {
DSRaiseIRQ(dscore->cpu, dscore->memory.io, DS_IRQ_SLOT1_TRANS); DSRaiseIRQ(dscore->cpu, dscore->memory.io, DS_IRQ_SLOT1_TRANS);
} }
@ -142,10 +140,13 @@ static void DSSlot1StartTransfer(struct DS* ds) {
ds->romVf->seek(ds->romVf, ds->memory.slot1.address, SEEK_SET); ds->romVf->seek(ds->romVf, ds->memory.slot1.address, SEEK_SET);
} }
ds->memory.slot1.transferRemaining = ds->memory.slot1.transferSize; ds->memory.slot1.transferRemaining = ds->memory.slot1.transferSize;
DSSlot1ROMCNT romcnt = ds->memory.io7[DS_REG_ROMCNT_LO >> 1];
unsigned delay = DSSlot1ROMCNTGetDelay(romcnt) + 12;
if (ds->ds7.memory.slot1Access) { if (ds->ds7.memory.slot1Access) {
_scheduleTransfer(ds, &ds->ds7.timing, 12, 0); _scheduleTransfer(ds, &ds->ds7.timing, delay, 0);
} else { } else {
_scheduleTransfer(ds, &ds->ds9.timing, 12, 0); _scheduleTransfer(ds, &ds->ds9.timing, delay, 0);
} }
break; break;
case 0xB8: case 0xB8:
@ -185,7 +186,6 @@ DSSlot1ROMCNT DSSlot1Control(struct DS* ds, DSSlot1ROMCNT control) {
} }
if (DSSlot1ROMCNTIsBlockBusy(control)) { if (DSSlot1ROMCNTIsBlockBusy(control)) {
DSSlot1StartTransfer(ds); DSSlot1StartTransfer(ds);
// TODO: timing
if (ds->memory.slot1.command[0] != 0xB7) { if (ds->memory.slot1.command[0] != 0xB7) {
control = DSSlot1ROMCNTFillWordReady(control); control = DSSlot1ROMCNTFillWordReady(control);
} }
@ -196,11 +196,24 @@ DSSlot1ROMCNT DSSlot1Control(struct DS* ds, DSSlot1ROMCNT control) {
uint32_t DSSlot1Read(struct DS* ds) { uint32_t DSSlot1Read(struct DS* ds) {
uint32_t result; uint32_t result;
LOAD_32(result, 0, ds->memory.slot1.readBuffer); LOAD_32(result, 0, ds->memory.slot1.readBuffer);
if (ds->ds7.memory.slot1Access) {
_scheduleTransfer(ds, &ds->ds7.timing, 4, 0); DSSlot1ROMCNT romcnt;
// TODO: Big endian
LOAD_32(romcnt, DS_REG_ROMCNT_LO, ds->memory.io7);
romcnt = DSSlot1ROMCNTClearWordReady(romcnt);
if (ds->memory.slot1.transferRemaining) {
if (ds->ds7.memory.slot1Access) {
_scheduleTransfer(ds, &ds->ds7.timing, 4, 0);
} else {
_scheduleTransfer(ds, &ds->ds9.timing, 4, 0);
}
} else { } else {
_scheduleTransfer(ds, &ds->ds9.timing, 4, 0); romcnt = DSSlot1ROMCNTClearBlockBusy(romcnt);
} }
STORE_32(romcnt, DS_REG_ROMCNT_LO, ds->memory.io7);
STORE_32(romcnt, DS_REG_ROMCNT_LO, ds->memory.io9);
return result; return result;
} }