Open dirkwhoffmann opened 1 month ago
v5.1 will feature improved REU timing:
Findings: To make the demo scene work, REU timing is critical. First, it is important to transfer one byte at a time. In v5.1, there will be an option OPT_EXP_REU_SPEED. It must be set to 1 (native speed):
Second, timing inside the emulator is essential. When a DMA transfer is requested, the following code is executed (new 5.1 code):
void
Reu::prepareDma()
{
if (REU_DEBUG) { dump(Category::Dma, std::cout); }
c64Addr = c64Base;
reuAddr = reuBase;
isize len = tlen ? tlen : 0x10000;
// Freeze the CPU
cpu.pullDownRdyLine(INTSRC_EXP);
// Schedule the first event
c64.scheduleRel<SLOT_EXP>(2, EXP_REU_PREPARE, len);
}
To get the demo work, there must be a 2 cycle delay before the first DMA access happens. This is emulated in the last line by scheduling an EXP_REU_PREPARE
event in 2 cycles. A value of 0 or 1 causes the screen to remain blank. A value of 3 causes distortion.
Hence, 2 seems to be the correct value (assuming the demo runs fine on real hardware).
Update: To get the second scene working, timing on VICII's BA line is crucial.
On csdb, there is a lot of talk about REU hardware bugs, stealing cycles from VICII etc. I doubt this is true. When reading the BA line with the proper delay (3 cycles), the demo scene looks in VirtualC64 like it does on the original C64 (at least to my aging eyes).
This is how I changed REU::processEvent
to make the scene work:
// Perform DMA if VICII does not block the bus
if (!vic.baLine.delayed()) for (; todo; todo--, remaining--) doDma(id);
if (remaining) {
// Prepare the next event
c64.scheduleInc<SLOT_EXP>(1, id, remaining);
} else {
// Finalize DMA if this was the last cycle
finalizeDma(id);
c64.cancel<SLOT_EXP>();
}
Note: Using baLine.delayed()
instead of baLine.current()
is essential here.
To reproduce:
The CPU will jam eventually.