dirkwhoffmann / vAmiga

vAmiga is a user-friendly Amiga 500, 1000, 2000 emulator for macOS
https://dirkwhoffmann.github.io/vAmiga
Other
297 stars 25 forks source link

Implement run-ahead #836

Open dirkwhoffmann opened 1 month ago

dirkwhoffmann commented 1 month ago

As run-ahead mode works so well in VirtualC64, it is time to port it over to vAmiga. A first prototype is already functional, with no critical performance issues:

Here is some debug output reporting the additional workload (M1 Max, 6 run-ahead frames, release build):

Run-ahead: Clone: 0.000356 sec
Run-ahead: Fast-forward: 0.012822 sec
Run-ahead: Clone: 0.000402 sec
Run-ahead: Fast-forward: 0.010971 sec
Run-ahead: Clone: 0.000324 sec
Run-ahead: Fast-forward: 0.011550 sec
Run-ahead: Clone: 0.000370 sec
Run-ahead: Fast-forward: 0.012400 sec

Cloning is less critical than anticipated; most overhead is caused by fast-forwarding the run-ahead instance after cloning. Also, 6 run-ahead frames in unusually high. According to what we see in VirtualC64, 2 to 4 frames will likely be optimal for most games.

There are some work items left before this feature can be officially released, though:

Of course, other issues may arise later while testing.

dirkwhoffmann commented 1 month ago

Update: The following code fragments include a relevant call to rand():

u8
FloppyDrive::readByte() const
{
    // Case 1: No disk is inserted
    if (!disk) return 0xFF;

    // Case 2: A step operation is in progress
    if (agnus.clock < latestStepCompleted) return u8(rand() & 0x55);

    // Case 3: Normal operation
    return disk->readByte(head.cylinder, head.head, head.offset);
}
void
FloppyDisk::clearDisk()
{
    setModified(FORCE_DISK_MODIFIED);

    // Initialize with random data
    srand(0);
    for (isize i = 0; i < isizeof(data.raw); i++) {
        data.raw[i] = rand() & 0xFF;
    }
}
void
FloppyDisk::clearTrack(Track t)
{
    assert(t < numTracks());

    srand(0);
    for (isize i = 0; i < length.track[t]; i++) {
        data.track[t][i] = rand() & 0xFF;
    }
}

The occurrence in readByte() needs to be replaced. The latter two functions call srand(0) which makes them safe.