emulate slot-1 read timings (fixes SF bug 1258)

This commit is contained in:
zeromus 2017-04-26 18:31:11 -05:00
parent 6600a2c393
commit 281268e05f
3 changed files with 58 additions and 2 deletions

View File

@ -1351,11 +1351,14 @@ void FASTCALL MMU_writeToGCControl(u32 val)
return;
}
val |= 0x00800000;
T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val);
//don't do this yet. it needs to be scheduled for the future
//val |= 0x00800000;
// Launch DMA if start flag was set to "DS Cart"
triggerDma(EDMAMode_Card);
//triggerDma(EDMAMode_Card);
NDS_RescheduleReadSlot1(blocksize);
}
/*template<int PROCNUM>

View File

@ -1085,6 +1085,31 @@ template<int procnum, int chan> struct TSequenceItem_DMA : public TSequenceItem
}
};
struct TSequenceItem_ReadSlot1 : public TSequenceItem
{
FORCEINLINE bool isTriggered()
{
return enabled && nds_timer >= timestamp;
}
bool isEnabled() { return this->enabled; }
FORCEINLINE u64 next()
{
return timestamp;
}
void exec()
{
enabled = false;
u32 val = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4);
val |= 0x00800000;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4, val);
triggerDma(EDMAMode_Card);
}
};
struct TSequenceItem_divider : public TSequenceItem
{
FORCEINLINE bool isTriggered()
@ -1150,6 +1175,7 @@ struct Sequencer
TSequenceItem_divider divider;
TSequenceItem_sqrtunit sqrtunit;
TSequenceItem_GXFIFO gxfifo;
TSequenceItem_ReadSlot1 readslot1;
TSequenceItem_DMA<0,0> dma_0_0; TSequenceItem_DMA<0,1> dma_0_1;
TSequenceItem_DMA<0,2> dma_0_2; TSequenceItem_DMA<0,3> dma_0_3;
TSequenceItem_DMA<1,0> dma_1_0; TSequenceItem_DMA<1,1> dma_1_1;
@ -1173,6 +1199,7 @@ struct Sequencer
divider.save(os);
sqrtunit.save(os);
gxfifo.save(os);
readslot1.save(os);
wifi.save(os);
#define SAVE(I,X,Y) I##_##X##_##Y .save(os);
SAVE(timer,0,0); SAVE(timer,0,1); SAVE(timer,0,2); SAVE(timer,0,3);
@ -1191,6 +1218,7 @@ struct Sequencer
if(!divider.load(is)) return false;
if(!sqrtunit.load(is)) return false;
if(!gxfifo.load(is)) return false;
if(!readslot1.load(is)) return false;
if(version >= 1) if(!wifi.load(is)) return false;
#define LOAD(I,X,Y) if(!I##_##X##_##Y .load(is)) return false;
LOAD(timer,0,0); LOAD(timer,0,1); LOAD(timer,0,2); LOAD(timer,0,3);
@ -1224,6 +1252,28 @@ void NDS_RescheduleTimers()
NDS_Reschedule();
}
void NDS_RescheduleReadSlot1(int size)
{
u32 gcromctrl = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4);
u32 clocks = (gcromctrl & (1<<27)) ? 8 : 5;
u32 gap = gcromctrl & 0x1FFF;
//time to send 8 command bytes, and then wait for the gap
u32 delay = (8+gap)*clocks;
//if data is to be returned, the first word is read before it's available and irqs and dmas fire
if(size != 0) delay += 4;
//timings are basically 33mhz but internal tracking is 66mhz
delay *= 2;
sequencer.readslot1.timestamp = nds_timer + delay;
sequencer.readslot1.enabled = true;
NDS_Reschedule();
}
void NDS_RescheduleDMA()
{
//TBD
@ -1604,6 +1654,7 @@ u64 Sequencer::findNext()
if(divider.isEnabled()) next = _fast_min(next,divider.next());
if(sqrtunit.isEnabled()) next = _fast_min(next,sqrtunit.next());
if(gxfifo.enabled) next = _fast_min(next,gxfifo.next());
if(readslot1.isEnabled()) next = _fast_min(next,readslot1.next());
#ifdef EXPERIMENTAL_WIFI_COMM
next = _fast_min(next,wifi.next());
@ -1674,6 +1725,7 @@ void Sequencer::execHardware()
if(divider.isTriggered()) divider.exec();
if(sqrtunit.isTriggered()) sqrtunit.exec();
if(gxfifo.isTriggered()) gxfifo.exec();
if(readslot1.isTriggered()) readslot1.exec();
#define test(X,Y) if(dma_##X##_##Y .isTriggered()) dma_##X##_##Y .exec();

View File

@ -149,6 +149,7 @@ extern u64 nds_timer;
void NDS_Reschedule();
void NDS_RescheduleGXFIFO(u32 cost);
void NDS_RescheduleDMA();
void NDS_RescheduleReadSlot1(int size);
void NDS_RescheduleTimers();
enum ENSATA_HANDSHAKE