mirror of https://github.com/mgba-emu/mgba.git
Support proper DMA timings and priority
This commit is contained in:
parent
3c100a5e31
commit
86bc662d9f
|
@ -374,7 +374,7 @@ void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
|
|||
}
|
||||
}
|
||||
|
||||
void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId) {
|
||||
void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) {
|
||||
struct GBAAudioFIFO* channel;
|
||||
if (fifoId == 0) {
|
||||
channel = &audio->chA;
|
||||
|
@ -387,7 +387,8 @@ void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId) {
|
|||
if (CircleBufferSize(&channel->fifo) <= 4 * sizeof(int32_t)) {
|
||||
struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
|
||||
dma->nextCount = 4;
|
||||
GBAMemoryServiceDMA(&audio->p->memory, channel->dmaSource, dma);
|
||||
dma->nextEvent = 0;
|
||||
GBAMemoryUpdateDMAs(&audio->p->memory, -cycles);
|
||||
}
|
||||
CircleBufferRead8(&channel->fifo, &channel->sample);
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value);
|
|||
|
||||
void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value);
|
||||
void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value);
|
||||
void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId);
|
||||
void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles);
|
||||
|
||||
unsigned GBAAudioCopy(struct GBAAudio* audio, void* left, void* right, unsigned nSamples);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region);
|
||||
static int GBAWaitMultiple(struct ARMMemory* memory, uint32_t startAddress, int count);
|
||||
static void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* info);
|
||||
|
||||
static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
|
||||
static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 7, 7, 9, 9, 13, 13, 9 };
|
||||
|
@ -39,6 +40,12 @@ void GBAMemoryInit(struct GBAMemory* memory) {
|
|||
memory->gpio.p = memory->p;
|
||||
memset(memory->io, 0, sizeof(memory->io));
|
||||
memset(memory->dma, 0, sizeof(memory->dma));
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
memory->dma[i].nextEvent = INT_MAX;
|
||||
}
|
||||
memory->activeDMA = -1;
|
||||
memory->nextDMA = INT_MAX;
|
||||
|
||||
if (!memory->wram || !memory->iwram) {
|
||||
GBAMemoryDeinit(memory);
|
||||
|
@ -46,7 +53,6 @@ void GBAMemoryInit(struct GBAMemory* memory) {
|
|||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
memory->waitstates16[i] = GBA_BASE_WAITSTATES[i];
|
||||
memory->waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
|
||||
|
@ -572,57 +578,6 @@ void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters) {
|
|||
memory->d.activeNonseqCycles16 = memory->waitstates16[memory->activeRegion];
|
||||
}
|
||||
|
||||
int32_t GBAMemoryProcessEvents(struct GBAMemory* memory, int32_t cycles) {
|
||||
struct GBADMA* dma;
|
||||
int32_t test = INT_MAX;
|
||||
|
||||
dma = &memory->dma[0];
|
||||
dma->nextIRQ -= cycles;
|
||||
if (dma->enable && dma->doIrq && dma->nextIRQ) {
|
||||
if (dma->nextIRQ <= 0) {
|
||||
dma->nextIRQ = INT_MAX;
|
||||
GBARaiseIRQ(memory->p, IRQ_DMA0);
|
||||
} else if (dma->nextIRQ < test) {
|
||||
test = dma->nextIRQ;
|
||||
}
|
||||
}
|
||||
|
||||
dma = &memory->dma[1];
|
||||
dma->nextIRQ -= cycles;
|
||||
if (dma->enable && dma->doIrq && dma->nextIRQ) {
|
||||
if (dma->nextIRQ <= 0) {
|
||||
dma->nextIRQ = INT_MAX;
|
||||
GBARaiseIRQ(memory->p, IRQ_DMA1);
|
||||
} else if (dma->nextIRQ < test) {
|
||||
test = dma->nextIRQ;
|
||||
}
|
||||
}
|
||||
|
||||
dma = &memory->dma[2];
|
||||
dma->nextIRQ -= cycles;
|
||||
if (dma->enable && dma->doIrq && dma->nextIRQ) {
|
||||
if (dma->nextIRQ <= 0) {
|
||||
dma->nextIRQ = INT_MAX;
|
||||
GBARaiseIRQ(memory->p, IRQ_DMA2);
|
||||
} else if (dma->nextIRQ < test) {
|
||||
test = dma->nextIRQ;
|
||||
}
|
||||
}
|
||||
|
||||
dma = &memory->dma[3];
|
||||
dma->nextIRQ -= cycles;
|
||||
if (dma->enable && dma->doIrq && dma->nextIRQ) {
|
||||
if (dma->nextIRQ <= 0) {
|
||||
dma->nextIRQ = INT_MAX;
|
||||
GBARaiseIRQ(memory->p, IRQ_DMA3);
|
||||
} else if (dma->nextIRQ < test) {
|
||||
test = dma->nextIRQ;
|
||||
}
|
||||
}
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
void GBAMemoryWriteDMASAD(struct GBAMemory* memory, int dma, uint32_t address) {
|
||||
memory->dma[dma].source = address & 0xFFFFFFFE;
|
||||
}
|
||||
|
@ -639,7 +594,6 @@ uint16_t GBAMemoryWriteDMACNT_HI(struct GBAMemory* memory, int dma, uint16_t con
|
|||
struct GBADMA* currentDma = &memory->dma[dma];
|
||||
int wasEnabled = currentDma->enable;
|
||||
currentDma->packed = control;
|
||||
currentDma->nextIRQ = 0;
|
||||
|
||||
if (currentDma->drq) {
|
||||
GBALog(memory->p, GBA_LOG_STUB, "DRQ not implemented");
|
||||
|
@ -658,15 +612,19 @@ uint16_t GBAMemoryWriteDMACNT_HI(struct GBAMemory* memory, int dma, uint16_t con
|
|||
void GBAMemoryScheduleDMA(struct GBAMemory* memory, int number, struct GBADMA* info) {
|
||||
switch (info->timing) {
|
||||
case DMA_TIMING_NOW:
|
||||
GBAMemoryServiceDMA(memory, number, info);
|
||||
info->nextEvent = memory->p->cpu.cycles;
|
||||
GBAMemoryUpdateDMAs(memory, 0);
|
||||
break;
|
||||
case DMA_TIMING_HBLANK:
|
||||
// Handled implicitly
|
||||
info->nextEvent = INT_MAX;
|
||||
break;
|
||||
case DMA_TIMING_VBLANK:
|
||||
// Handled implicitly
|
||||
info->nextEvent = INT_MAX;
|
||||
break;
|
||||
case DMA_TIMING_CUSTOM:
|
||||
info->nextEvent = INT_MAX;
|
||||
switch (number) {
|
||||
case 0:
|
||||
GBALog(memory->p, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
|
||||
|
@ -676,40 +634,71 @@ void GBAMemoryScheduleDMA(struct GBAMemory* memory, int number, struct GBADMA* i
|
|||
GBAAudioScheduleFifoDma(&memory->p->audio, number, info);
|
||||
break;
|
||||
case 3:
|
||||
//this.cpu.irq.video.scheduleVCaptureDma(dma, info);
|
||||
// GBAVideoScheduleVCaptureDma(dma, info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GBAMemoryRunHblankDMAs(struct GBAMemory* memory) {
|
||||
void GBAMemoryRunHblankDMAs(struct GBAMemory* memory, int32_t cycles) {
|
||||
struct GBADMA* dma;
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dma = &memory->dma[i];
|
||||
if (dma->enable && dma->timing == DMA_TIMING_HBLANK) {
|
||||
GBAMemoryServiceDMA(memory, i, dma);
|
||||
dma->nextEvent = memory->p->cpu.cycles;
|
||||
}
|
||||
}
|
||||
GBAMemoryUpdateDMAs(memory, -cycles);
|
||||
}
|
||||
|
||||
void GBAMemoryRunVblankDMAs(struct GBAMemory* memory) {
|
||||
void GBAMemoryRunVblankDMAs(struct GBAMemory* memory, int32_t cycles) {
|
||||
struct GBADMA* dma;
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dma = &memory->dma[i];
|
||||
if (dma->enable && dma->timing == DMA_TIMING_VBLANK) {
|
||||
GBAMemoryServiceDMA(memory, i, dma);
|
||||
dma->nextEvent = memory->p->cpu.cycles;
|
||||
}
|
||||
}
|
||||
GBAMemoryUpdateDMAs(memory, -cycles);
|
||||
}
|
||||
|
||||
int32_t GBAMemoryRunDMAs(struct GBAMemory* memory, int32_t cycles) {
|
||||
if (memory->nextDMA == INT_MAX) {
|
||||
return INT_MAX;
|
||||
}
|
||||
memory->nextDMA -= cycles;
|
||||
memory->eventDiff += cycles;
|
||||
if (memory->nextDMA <= 0) {
|
||||
struct GBADMA* dma = &memory->dma[memory->activeDMA];
|
||||
GBAMemoryServiceDMA(memory, memory->activeDMA, dma);
|
||||
GBAMemoryUpdateDMAs(memory, memory->eventDiff);
|
||||
memory->eventDiff = 0;
|
||||
}
|
||||
return memory->nextDMA;
|
||||
}
|
||||
|
||||
void GBAMemoryUpdateDMAs(struct GBAMemory* memory, int32_t cycles) {
|
||||
int i;
|
||||
memory->activeDMA = -1;
|
||||
memory->nextDMA = INT_MAX;
|
||||
for (i = 3; i >= 0; --i) {
|
||||
struct GBADMA* dma = &memory->dma[i];
|
||||
if (dma->nextEvent != INT_MAX) {
|
||||
dma->nextEvent -= cycles;
|
||||
if (dma->enable && memory->nextDMA >= dma->nextEvent) {
|
||||
memory->activeDMA = i;
|
||||
memory->nextDMA = dma->nextEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (memory->nextDMA < memory->p->cpu.nextEvent) {
|
||||
memory->p->cpu.nextEvent = memory->nextDMA;
|
||||
}
|
||||
}
|
||||
|
||||
void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* info) {
|
||||
if (!info->enable) {
|
||||
// There was a DMA scheduled that got canceled
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t width = info->width ? 4 : 2;
|
||||
int sourceOffset = DMA_OFFSET[info->srcControl] * width;
|
||||
int destOffset = DMA_OFFSET[info->dstControl] * width;
|
||||
|
@ -718,71 +707,89 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
|
|||
uint32_t dest = info->nextDest;
|
||||
uint32_t sourceRegion = source >> BASE_OFFSET;
|
||||
uint32_t destRegion = dest >> BASE_OFFSET;
|
||||
int32_t cycles = 0;
|
||||
|
||||
if (source == info->source) {
|
||||
// TODO: support 4 cycles for ROM access
|
||||
cycles += 2;
|
||||
if (width == 4) {
|
||||
cycles += memory->waitstates32[sourceRegion] + memory->waitstates32[destRegion];
|
||||
source &= 0xFFFFFFFC;
|
||||
dest &= 0xFFFFFFFC;
|
||||
} else {
|
||||
cycles += memory->waitstates16[sourceRegion] + memory->waitstates16[destRegion];
|
||||
}
|
||||
} else {
|
||||
if (width == 4) {
|
||||
cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
|
||||
} else {
|
||||
cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
|
||||
}
|
||||
}
|
||||
|
||||
if (width == 4) {
|
||||
int32_t word;
|
||||
source &= 0xFFFFFFFC;
|
||||
dest &= 0xFFFFFFFC;
|
||||
while (wordsRemaining--) {
|
||||
word = memory->d.load32(&memory->d, source, 0);
|
||||
memory->d.store32(&memory->d, dest, word, 0);
|
||||
source += sourceOffset;
|
||||
dest += destOffset;
|
||||
}
|
||||
word = memory->d.load32(&memory->d, source, 0);
|
||||
memory->d.store32(&memory->d, dest, word, 0);
|
||||
source += sourceOffset;
|
||||
dest += destOffset;
|
||||
--wordsRemaining;
|
||||
} else {
|
||||
uint16_t word;
|
||||
if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
|
||||
while (wordsRemaining--) {
|
||||
word = GBASavedataReadEEPROM(&memory->savedata);
|
||||
memory->d.store16(&memory->d, dest, word, 0);
|
||||
source += sourceOffset;
|
||||
dest += destOffset;
|
||||
}
|
||||
word = GBASavedataReadEEPROM(&memory->savedata);
|
||||
memory->d.store16(&memory->d, dest, word, 0);
|
||||
source += sourceOffset;
|
||||
dest += destOffset;
|
||||
--wordsRemaining;
|
||||
} else if (destRegion == REGION_CART2_EX) {
|
||||
if (memory->savedata.type == SAVEDATA_NONE) {
|
||||
GBASavedataInitEEPROM(&memory->savedata);
|
||||
}
|
||||
while (wordsRemaining) {
|
||||
word = memory->d.load16(&memory->d, source, 0);
|
||||
GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
|
||||
source += sourceOffset;
|
||||
dest += destOffset;
|
||||
--wordsRemaining;
|
||||
}
|
||||
word = memory->d.load16(&memory->d, source, 0);
|
||||
GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
|
||||
source += sourceOffset;
|
||||
dest += destOffset;
|
||||
--wordsRemaining;
|
||||
} else {
|
||||
while (wordsRemaining--) {
|
||||
word = memory->d.load16(&memory->d, source, 0);
|
||||
memory->d.store16(&memory->d, dest, word, 0);
|
||||
source += sourceOffset;
|
||||
dest += destOffset;
|
||||
word = memory->d.load16(&memory->d, source, 0);
|
||||
memory->d.store16(&memory->d, dest, word, 0);
|
||||
source += sourceOffset;
|
||||
dest += destOffset;
|
||||
--wordsRemaining;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wordsRemaining) {
|
||||
if (!info->repeat) {
|
||||
info->enable = 0;
|
||||
info->nextEvent = INT_MAX;
|
||||
|
||||
// Clear the enable bit in memory
|
||||
memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
|
||||
} else {
|
||||
info->nextCount = info->count;
|
||||
if (info->dstControl == DMA_INCREMENT_RELOAD) {
|
||||
info->nextDest = info->dest;
|
||||
}
|
||||
GBAMemoryScheduleDMA(memory, number, info);
|
||||
}
|
||||
if (info->doIrq) {
|
||||
GBARaiseIRQ(memory->p, IRQ_DMA0 + number);
|
||||
}
|
||||
}
|
||||
|
||||
if (info->doIrq) {
|
||||
info->nextIRQ = memory->p->cpu.cycles + 2;
|
||||
info->nextIRQ += (width == 4 ? memory->waitstates32[sourceRegion] + memory->waitstates32[destRegion]
|
||||
: memory->waitstates16[sourceRegion] + memory->waitstates16[destRegion]);
|
||||
info->nextIRQ += (info->count - 1) * (width == 4 ? memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion]
|
||||
: memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion]);
|
||||
}
|
||||
|
||||
info->nextSource = source;
|
||||
info->nextDest = dest;
|
||||
info->nextCount = wordsRemaining;
|
||||
|
||||
if (!info->repeat) {
|
||||
info->enable = 0;
|
||||
|
||||
// Clear the enable bit in memory
|
||||
memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
|
||||
} else {
|
||||
info->nextCount = info->count;
|
||||
if (info->dstControl == DMA_INCREMENT_RELOAD) {
|
||||
info->nextDest = info->dest;
|
||||
}
|
||||
GBAMemoryScheduleDMA(memory, number, info);
|
||||
info->nextDest = dest;
|
||||
info->nextCount = wordsRemaining;
|
||||
}
|
||||
info->nextSource = source;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (memory->dma[i].nextEvent != INT_MAX) {
|
||||
memory->dma[i].nextEvent += cycles;
|
||||
}
|
||||
}
|
||||
memory->p->cpu.cycles += cycles;
|
||||
}
|
||||
|
||||
void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {
|
||||
|
|
|
@ -102,7 +102,7 @@ struct GBADMA {
|
|||
uint32_t nextSource;
|
||||
uint32_t nextDest;
|
||||
int32_t nextCount;
|
||||
int32_t nextIRQ;
|
||||
int32_t nextEvent;
|
||||
};
|
||||
|
||||
struct GBAMemory {
|
||||
|
@ -131,10 +131,11 @@ struct GBAMemory {
|
|||
uint32_t biosPrefetch;
|
||||
|
||||
struct GBADMA dma[4];
|
||||
int activeDMA;
|
||||
int32_t nextDMA;
|
||||
int32_t eventDiff;
|
||||
};
|
||||
|
||||
int32_t GBAMemoryProcessEvents(struct GBAMemory* memory, int32_t cycles);
|
||||
|
||||
int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter);
|
||||
int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter);
|
||||
uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address, int* cycleCounter);
|
||||
|
@ -153,9 +154,10 @@ void GBAMemoryWriteDMACNT_LO(struct GBAMemory* memory, int dma, uint16_t count);
|
|||
uint16_t GBAMemoryWriteDMACNT_HI(struct GBAMemory* memory, int dma, uint16_t control);
|
||||
|
||||
void GBAMemoryScheduleDMA(struct GBAMemory* memory, int number, struct GBADMA* info);
|
||||
void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* info);
|
||||
void GBAMemoryRunHblankDMAs(struct GBAMemory* memory);
|
||||
void GBAMemoryRunVblankDMAs(struct GBAMemory* memory);
|
||||
void GBAMemoryRunHblankDMAs(struct GBAMemory* memory, int32_t cycles);
|
||||
void GBAMemoryRunVblankDMAs(struct GBAMemory* memory, int32_t cycles);
|
||||
void GBAMemoryUpdateDMAs(struct GBAMemory* memory, int32_t cycles);
|
||||
int32_t GBAMemoryRunDMAs(struct GBAMemory* memory, int32_t cycles);
|
||||
|
||||
struct GBASerializedState;
|
||||
void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state);
|
||||
|
|
|
@ -66,6 +66,7 @@ int32_t GBAVideoProcessEvents(struct GBAVideo* video, int32_t cycles) {
|
|||
video->nextEvent -= cycles;
|
||||
video->eventDiff += cycles;
|
||||
if (video->nextEvent <= 0) {
|
||||
int32_t lastEvent = video->nextEvent;
|
||||
video->lastHblank -= video->eventDiff;
|
||||
video->nextHblank -= video->eventDiff;
|
||||
video->nextHblankIRQ -= video->eventDiff;
|
||||
|
@ -86,7 +87,7 @@ int32_t GBAVideoProcessEvents(struct GBAVideo* video, int32_t cycles) {
|
|||
video->renderer->finishFrame(video->renderer);
|
||||
}
|
||||
video->nextVblankIRQ = video->nextEvent + VIDEO_TOTAL_LENGTH;
|
||||
GBAMemoryRunVblankDMAs(&video->p->memory);
|
||||
GBAMemoryRunVblankDMAs(&video->p->memory, lastEvent);
|
||||
if (video->vblankIRQ) {
|
||||
GBARaiseIRQ(video->p, IRQ_VBLANK);
|
||||
}
|
||||
|
@ -119,7 +120,7 @@ int32_t GBAVideoProcessEvents(struct GBAVideo* video, int32_t cycles) {
|
|||
video->nextHblankIRQ = video->nextHblank;
|
||||
|
||||
if (video->vcount < VIDEO_VERTICAL_PIXELS) {
|
||||
GBAMemoryRunHblankDMAs(&video->p->memory);
|
||||
GBAMemoryRunHblankDMAs(&video->p->memory, lastEvent);
|
||||
}
|
||||
if (video->hblankIRQ) {
|
||||
GBARaiseIRQ(video->p, IRQ_HBLANK);
|
||||
|
|
|
@ -165,38 +165,40 @@ void GBABoardReset(struct ARMBoard* board) {
|
|||
}
|
||||
|
||||
static void GBAProcessEvents(struct ARMBoard* board) {
|
||||
struct GBABoard* gbaBoard = (struct GBABoard*) board;
|
||||
int32_t cycles = board->cpu->cycles;
|
||||
int32_t nextEvent = INT_MAX;
|
||||
int32_t testEvent;
|
||||
do {
|
||||
struct GBABoard* gbaBoard = (struct GBABoard*) board;
|
||||
int32_t cycles = board->cpu->cycles;
|
||||
int32_t nextEvent = INT_MAX;
|
||||
int32_t testEvent;
|
||||
|
||||
if (gbaBoard->p->springIRQ) {
|
||||
ARMRaiseIRQ(&gbaBoard->p->cpu);
|
||||
gbaBoard->p->springIRQ = 0;
|
||||
}
|
||||
if (gbaBoard->p->springIRQ) {
|
||||
ARMRaiseIRQ(&gbaBoard->p->cpu);
|
||||
gbaBoard->p->springIRQ = 0;
|
||||
}
|
||||
|
||||
testEvent = GBAVideoProcessEvents(&gbaBoard->p->video, cycles);
|
||||
if (testEvent < nextEvent) {
|
||||
nextEvent = testEvent;
|
||||
}
|
||||
testEvent = GBAVideoProcessEvents(&gbaBoard->p->video, cycles);
|
||||
if (testEvent < nextEvent) {
|
||||
nextEvent = testEvent;
|
||||
}
|
||||
|
||||
testEvent = GBAAudioProcessEvents(&gbaBoard->p->audio, cycles);
|
||||
if (testEvent < nextEvent) {
|
||||
nextEvent = testEvent;
|
||||
}
|
||||
testEvent = GBAAudioProcessEvents(&gbaBoard->p->audio, cycles);
|
||||
if (testEvent < nextEvent) {
|
||||
nextEvent = testEvent;
|
||||
}
|
||||
|
||||
testEvent = GBAMemoryProcessEvents(&gbaBoard->p->memory, cycles);
|
||||
if (testEvent < nextEvent) {
|
||||
nextEvent = testEvent;
|
||||
}
|
||||
testEvent = GBATimersProcessEvents(gbaBoard->p, cycles);
|
||||
if (testEvent < nextEvent) {
|
||||
nextEvent = testEvent;
|
||||
}
|
||||
|
||||
testEvent = GBATimersProcessEvents(gbaBoard->p, cycles);
|
||||
if (testEvent < nextEvent) {
|
||||
nextEvent = testEvent;
|
||||
}
|
||||
testEvent = GBAMemoryRunDMAs(&gbaBoard->p->memory, cycles);
|
||||
if (testEvent < nextEvent) {
|
||||
nextEvent = testEvent;
|
||||
}
|
||||
|
||||
board->cpu->cycles = 0;
|
||||
board->cpu->nextEvent = nextEvent;
|
||||
board->cpu->cycles -= cycles;
|
||||
board->cpu->nextEvent = nextEvent;
|
||||
} while (board->cpu->cycles >= board->cpu->nextEvent);
|
||||
}
|
||||
|
||||
static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles) {
|
||||
|
@ -221,11 +223,11 @@ static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles) {
|
|||
|
||||
if (gba->audio.enable) {
|
||||
if ((gba->audio.chALeft || gba->audio.chARight) && gba->audio.chATimer == 0) {
|
||||
GBAAudioSampleFIFO(&gba->audio, 0);
|
||||
GBAAudioSampleFIFO(&gba->audio, 0, timer->lastEvent);
|
||||
}
|
||||
|
||||
if ((gba->audio.chBLeft || gba->audio.chBRight) && gba->audio.chBTimer == 0) {
|
||||
GBAAudioSampleFIFO(&gba->audio, 1);
|
||||
GBAAudioSampleFIFO(&gba->audio, 1, timer->lastEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,11 +258,11 @@ static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles) {
|
|||
|
||||
if (gba->audio.enable) {
|
||||
if ((gba->audio.chALeft || gba->audio.chARight) && gba->audio.chATimer == 1) {
|
||||
GBAAudioSampleFIFO(&gba->audio, 0);
|
||||
GBAAudioSampleFIFO(&gba->audio, 0, timer->lastEvent);
|
||||
}
|
||||
|
||||
if ((gba->audio.chBLeft || gba->audio.chBRight) && gba->audio.chBTimer == 1) {
|
||||
GBAAudioSampleFIFO(&gba->audio, 1);
|
||||
GBAAudioSampleFIFO(&gba->audio, 1, timer->lastEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue