From fc3a360e7e3087db067775f975fd420e77c98620 Mon Sep 17 00:00:00 2001 From: Jorj Bauer Date: Sun, 2 Aug 2020 09:06:15 -0400 Subject: [PATCH] convert cpu cycle counter to int64_t --- apple/applekeyboard.cpp | 2 +- apple/applekeyboard.h | 6 ++-- apple/applevm.cpp | 2 +- apple/applevm.h | 2 +- apple/diskii.cpp | 67 +++++++++++++++++++-------------------- apple/diskii.h | 10 +++--- cpu.h | 2 +- linuxfb/aiie.cpp | 2 +- linuxfb/linux-speaker.cpp | 4 +-- linuxfb/timeutil.h | 2 +- physicalspeaker.h | 4 +-- sdl/aiie.cpp | 6 ++-- sdl/sdl-speaker.cpp | 8 ++--- sdl/sdl-speaker.h | 4 +-- sdl/timeutil.h | 2 +- teensy/teensy-speaker.cpp | 8 ++--- teensy/teensy-speaker.h | 4 +-- vmkeyboard.h | 2 +- 18 files changed, 67 insertions(+), 70 deletions(-) diff --git a/apple/applekeyboard.cpp b/apple/applekeyboard.cpp index 4e0fec9..56925cc 100644 --- a/apple/applekeyboard.cpp +++ b/apple/applekeyboard.cpp @@ -172,7 +172,7 @@ void AppleKeyboard::keyReleased(uint8_t k) } } -void AppleKeyboard::maintainKeyboard(uint32_t cycleCount) +void AppleKeyboard::maintainKeyboard(int64_t cycleCount) { if (anyKeyIsDown) { if (startRepeatTimer) { diff --git a/apple/applekeyboard.h b/apple/applekeyboard.h index f39db66..362c346 100644 --- a/apple/applekeyboard.h +++ b/apple/applekeyboard.h @@ -13,7 +13,7 @@ class AppleKeyboard : public VMKeyboard { virtual void keyDepressed(uint8_t k); virtual void keyReleased(uint8_t k); - virtual void maintainKeyboard(uint32_t cycleCount); + virtual void maintainKeyboard(int64_t cycleCount); protected: bool isVirtualKey(uint8_t kc); @@ -49,9 +49,9 @@ class AppleKeyboard : public VMKeyboard { // repeatTimer is the cpu cycle count at which we would repeat again. // (It also has the rollover problem once every 82 minutes.) - uint32_t startRepeatTimer; + int64_t startRepeatTimer; uint8_t keyThatIsRepeating; - uint32_t repeatTimer; + int64_t repeatTimer; }; #endif diff --git a/apple/applevm.cpp b/apple/applevm.cpp index cee577d..b925d2b 100644 --- a/apple/applevm.cpp +++ b/apple/applevm.cpp @@ -127,7 +127,7 @@ void AppleVM::triggerPaddleInCycles(uint8_t paddleNum,uint16_t cycleCount) paddleCycleTrigger[paddleNum] = cycleCount + g_cpu->cycles; } -void AppleVM::cpuMaintenance(uint32_t cycles) +void AppleVM::cpuMaintenance(int64_t cycles) { for (uint8_t i=0; i<2; i++) { if (paddleCycleTrigger[i] && cycles >= paddleCycleTrigger[i]) { diff --git a/apple/applevm.h b/apple/applevm.h index 92220e4..a595d7a 100644 --- a/apple/applevm.h +++ b/apple/applevm.h @@ -17,7 +17,7 @@ class AppleVM : public VM { void Suspend(const char *fn); void Resume(const char *fn); - void cpuMaintenance(uint32_t cycles); + void cpuMaintenance(int64_t cycles); virtual void Reset(); void Monitor(); diff --git a/apple/diskii.cpp b/apple/diskii.cpp index 536be92..16177d1 100644 --- a/apple/diskii.cpp +++ b/apple/diskii.cpp @@ -26,6 +26,9 @@ // 10 second delay before flushing #define FLUSHDELAY (1023000 * 10) +#define SPINFOREVER -2 +#define NOTSPINNING -1 + DiskII::DiskII(AppleMMU *mmu) { this->mmu = mmu; @@ -39,11 +42,11 @@ DiskII::DiskII(AppleMMU *mmu) readWriteLatch = 0x00; sequencer = 0; dataRegister = 0; - driveSpinupCycles[0] = driveSpinupCycles[1] = 0; + driveSpinupCycles[0] = driveSpinupCycles[1] = 0; // CPU cycle number when the disk drive spins up deliveredDiskBits[0] = deliveredDiskBits[1] = 0; disk[0] = disk[1] = NULL; - diskIsSpinningUntil[0] = diskIsSpinningUntil[1] = 0; + diskIsSpinningUntil[0] = diskIsSpinningUntil[1] = -1; flushAt[0] = flushAt[1] = 0; selectedDisk = 0; } @@ -54,7 +57,7 @@ DiskII::~DiskII() bool DiskII::Serialize(int8_t fd) { - uint8_t buf[23] = { DISKIIMAGIC, + uint8_t buf[27] = { DISKIIMAGIC, readWriteLatch, sequencer, dataRegister, @@ -87,13 +90,17 @@ bool DiskII::Serialize(int8_t fd) buf[ptr++] = ((deliveredDiskBits[i] >> 16) & 0xFF); buf[ptr++] = ((deliveredDiskBits[i] >> 8) & 0xFF); buf[ptr++] = ((deliveredDiskBits[i] ) & 0xFF); + buf[ptr++] = (diskIsSpinningUntil[i] >> 56) & 0xFF; + buf[ptr++] = (diskIsSpinningUntil[i] >> 48) & 0xFF; + buf[ptr++] = (diskIsSpinningUntil[i] >> 40) & 0xFF; + buf[ptr++] = (diskIsSpinningUntil[i] >> 32) & 0xFF; buf[ptr++] = (diskIsSpinningUntil[i] >> 24) & 0xFF; buf[ptr++] = (diskIsSpinningUntil[i] >> 16) & 0xFF; buf[ptr++] = (diskIsSpinningUntil[i] >> 8) & 0xFF; buf[ptr++] = (diskIsSpinningUntil[i] ) & 0xFF; - // Safety check: keeping the hard-coded 23 and comparing against ptr. - // If we change the 23, also need to change the size of buf[] above - if (g_filemanager->write(fd, buf, 23) != ptr) { + // Safety check: keeping the hard-coded 27 and comparing against ptr. + // If we change the 27, also need to change the size of buf[] above + if (g_filemanager->write(fd, buf, 27) != ptr) { return false; } @@ -144,7 +151,7 @@ bool DiskII::Deserialize(int8_t fd) for (int i=0; i<2; i++) { uint8_t ptr = 0; - if (g_filemanager->read(fd, buf, 23) != 23) + if (g_filemanager->read(fd, buf, 27) != 27) return false; curHalfTrack[i] = buf[ptr++]; @@ -173,6 +180,10 @@ bool DiskII::Deserialize(int8_t fd) diskIsSpinningUntil[i] <<= 8; diskIsSpinningUntil[i] |= buf[ptr++]; diskIsSpinningUntil[i] <<= 8; diskIsSpinningUntil[i] |= buf[ptr++]; diskIsSpinningUntil[i] <<= 8; diskIsSpinningUntil[i] |= buf[ptr++]; + diskIsSpinningUntil[i] <<= 8; diskIsSpinningUntil[i] |= buf[ptr++]; + diskIsSpinningUntil[i] <<= 8; diskIsSpinningUntil[i] |= buf[ptr++]; + diskIsSpinningUntil[i] <<= 8; diskIsSpinningUntil[i] |= buf[ptr++]; + diskIsSpinningUntil[i] <<= 8; diskIsSpinningUntil[i] |= buf[ptr++]; if (disk[i]) delete disk[i]; @@ -228,12 +239,8 @@ void DiskII::Reset() void DiskII::driveOff() { - if (diskIsSpinningUntil[selectedDisk] == -1) { + if (diskIsSpinningUntil[selectedDisk] == SPINFOREVER) { diskIsSpinningUntil[selectedDisk] = g_cpu->cycles + SPINDOWNDELAY; // 1 second lag - if (diskIsSpinningUntil[selectedDisk] == -1 || - diskIsSpinningUntil[selectedDisk] == 0) - diskIsSpinningUntil[selectedDisk] = 2; // fudge magic numbers; 0 is "off" and -1 is "forever". - // The drive-is-on-indicator is turned off later, when the disk // actually spins down. } @@ -247,13 +254,13 @@ void DiskII::driveOff() void DiskII::driveOn() { - if (diskIsSpinningUntil[selectedDisk] != -1) { + if (diskIsSpinningUntil[selectedDisk] != SPINFOREVER) { // If the drive isn't already spinning, then start keeping track of how // many bits we've delivered (so we can honor the disk bit-delivery time // that might be in the Woz disk image). driveSpinupCycles[selectedDisk] = g_cpu->cycles; deliveredDiskBits[selectedDisk] = 0; - diskIsSpinningUntil[selectedDisk] = -1; // magic "forever" + diskIsSpinningUntil[selectedDisk] = SPINFOREVER; } // FIXME: does the sequencer get reset? Maybe if it's the selected disk? Or no? // sequencer = 0; @@ -301,9 +308,6 @@ uint8_t DiskII::readSwitches(uint8_t s) case 0x0C: // shift one read or write byte readWriteLatch = readOrWriteByte(); if (readWriteLatch & 0x80) { - // static uint32_t lastC = 0; - // printf("%u: read data\n", g_cpu->cycles - lastC); - // lastC = g_cpu->cycles; if (!(sequencer & 0x80)) { // printf("SEQ RESET EARLY [1]\n"); } @@ -478,17 +482,10 @@ bool DiskII::isWriteProtected() int64_t DiskII::calcExpectedBits() { // If the disk isn't spinning, then it can't be expected to deliver data - if (!diskIsSpinningUntil[selectedDisk]) + if (diskIsSpinningUntil[selectedDisk]==NOTSPINNING) return 0; - // Handle potential messy counter rollover - if (driveSpinupCycles[selectedDisk] > g_cpu->cycles) { - driveSpinupCycles[selectedDisk] = g_cpu->cycles-1; - if (driveSpinupCycles[selectedDisk] == 0) // avoid sitting on 0 - driveSpinupCycles[selectedDisk]++; - } - - uint32_t cyclesPassed = g_cpu->cycles - driveSpinupCycles[selectedDisk]; + int64_t cyclesPassed = g_cpu->cycles - driveSpinupCycles[selectedDisk]; // This constant defines how fast the disk drive "spins". // 4.0 is good for DOS 3.3 writes, and reads as 205ms in // Copy 2+'s drive speed verifier. @@ -500,7 +497,7 @@ int64_t DiskII::calcExpectedBits() // As-is, this won't read NIB files for some reason I haven't // fully understood; but if you slow the disk down to /5.0, // then they load? - uint64_t expectedDiskBits = (float)cyclesPassed / 3.90; + int64_t expectedDiskBits = (float)cyclesPassed / 3.90; return expectedDiskBits - deliveredDiskBits[selectedDisk]; } @@ -585,19 +582,19 @@ void DiskII::select(int8_t which) return; if (which != selectedDisk) { - if (diskIsSpinningUntil[selectedDisk] == -1) { + if (diskIsSpinningUntil[selectedDisk] == SPINFOREVER) { // FIXME: I'm not sure what the right behavior is here (read // UTA2E and see if the state diagrams show the right // behavior). This spins it down immediately based on something // I read about the duoDisk not having both motors on // simultaneously. - diskIsSpinningUntil[selectedDisk] = 0; + diskIsSpinningUntil[selectedDisk] = NOTSPINNING; // FIXME: consume any disk bits that need to be consumed, and // spin it down g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, false); // Spin up the other one though - diskIsSpinningUntil[which] = -1; + diskIsSpinningUntil[which] = SPINFOREVER; g_ui->drawOnOffUIElement(UIeDisk1_activity + which, true); } @@ -625,13 +622,13 @@ void DiskII::select(int8_t which) uint8_t DiskII::readOrWriteByte() { if (!disk[selectedDisk]) { - //printf("reading from uninserted disk\n"); return 0xFF; } int32_t bitsToDeliver; - if (diskIsSpinningUntil[selectedDisk] < g_cpu->cycles) { + if (diskIsSpinningUntil[selectedDisk] != SPINFOREVER && + diskIsSpinningUntil[selectedDisk] < g_cpu->cycles) { // Uum, disk isn't spinning? goto done; } @@ -740,15 +737,15 @@ void DiskII::loadROM(uint8_t *toWhere) #endif } -void DiskII::maintenance(uint32_t cycle) +void DiskII::maintenance(int64_t cycle) { // Handle spin-down for the drive. Drives stay on for a second after // the stop was noticed. for (int i=0; i<2; i++) { - if (diskIsSpinningUntil[i] && + if (diskIsSpinningUntil[i] != SPINFOREVER && g_cpu->cycles > diskIsSpinningUntil[i]) { // Stop the given disk drive spinning - diskIsSpinningUntil[i] = 0; + diskIsSpinningUntil[i] = NOTSPINNING; // FIXME: consume any disk bits that need to be consumed, and spin it down g_ui->drawOnOffUIElement(UIeDisk1_activity + i, false); } diff --git a/apple/diskii.h b/apple/diskii.h index 2eff90a..5deaf8d 100644 --- a/apple/diskii.h +++ b/apple/diskii.h @@ -35,7 +35,7 @@ class DiskII : public Slot { const char *DiskName(int8_t num); - void maintenance(uint32_t cycles); + void maintenance(int64_t cycles); uint8_t selectedDrive(); uint8_t headPosition(uint8_t drive); @@ -66,18 +66,18 @@ private: volatile int8_t curPhase[2]; volatile uint8_t readWriteLatch; volatile uint8_t sequencer, dataRegister; // diskII logic state sequencer vars - volatile uint64_t driveSpinupCycles[2]; - volatile uint64_t deliveredDiskBits[2]; + volatile int64_t driveSpinupCycles[2]; + volatile int64_t deliveredDiskBits[2]; bool writeMode; bool writeProt; AppleMMU *mmu; - volatile uint32_t diskIsSpinningUntil[2]; + volatile int64_t diskIsSpinningUntil[2]; volatile int8_t selectedDisk; - volatile uint32_t flushAt[2]; + volatile int64_t flushAt[2]; }; #endif diff --git a/cpu.h b/cpu.h index d1eec8f..a90a59a 100644 --- a/cpu.h +++ b/cpu.h @@ -183,7 +183,7 @@ class Cpu { uint8_t y; uint8_t flags; - uint32_t cycles; + int64_t cycles; bool irqPending; diff --git a/linuxfb/aiie.cpp b/linuxfb/aiie.cpp index 1deea8b..a9a9ac7 100644 --- a/linuxfb/aiie.cpp +++ b/linuxfb/aiie.cpp @@ -90,7 +90,7 @@ void write(void *arg, uint16_t address, uint8_t v) static void *cpu_thread(void *dummyptr) { struct timespec currentTime; struct timespec nextCycleTime; - uint32_t nextSpeakerCycle = 0; + int64_t nextSpeakerCycle = 0; #if 0 int policy; diff --git a/linuxfb/linux-speaker.cpp b/linuxfb/linux-speaker.cpp index 1918f82..7718040 100644 --- a/linuxfb/linux-speaker.cpp +++ b/linuxfb/linux-speaker.cpp @@ -18,11 +18,11 @@ void LinuxSpeaker::begin() { } -void LinuxSpeaker::toggle(uint32_t c) +void LinuxSpeaker::toggle(int64_t c) { } -void LinuxSpeaker::maintainSpeaker(uint32_t c, uint64_t microseconds) +void LinuxSpeaker::maintainSpeaker(int64_t c, uint64_t microseconds) { } diff --git a/linuxfb/timeutil.h b/linuxfb/timeutil.h index 6e7dcca..af41180 100644 --- a/linuxfb/timeutil.h +++ b/linuxfb/timeutil.h @@ -34,7 +34,7 @@ static int do_gettime(struct timespec *tp) { // adds the number of nanoseconds that 'cycles' takes to *start and // returns it in *out static void timespec_add_cycles(struct timespec *start, - int32_t cycles, + int64_t cycles, struct timespec *out) { out->tv_sec = start->tv_sec; diff --git a/physicalspeaker.h b/physicalspeaker.h index f59021a..9a7e711 100644 --- a/physicalspeaker.h +++ b/physicalspeaker.h @@ -9,8 +9,8 @@ class PhysicalSpeaker { virtual void begin() = 0; - virtual void toggle(uint32_t c) = 0; - virtual void maintainSpeaker(uint32_t c, uint64_t microseconds) = 0; + virtual void toggle(int64_t c) = 0; + virtual void maintainSpeaker(int64_t c, uint64_t microseconds) = 0; virtual void beginMixing() = 0; virtual void mixOutput(uint8_t v) = 0; diff --git a/sdl/aiie.cpp b/sdl/aiie.cpp index e124491..fb4d4d0 100644 --- a/sdl/aiie.cpp +++ b/sdl/aiie.cpp @@ -258,7 +258,7 @@ int main(int argc, char *argv[]) g_speaker->begin(); - uint32_t lastCycleCount = -1; + int64_t lastCycleCount = -1; while (1) { if (g_biosInterrupt) { @@ -293,7 +293,7 @@ int main(int argc, char *argv[]) } - static uint32_t usleepcycles = 16384*4; // step-down for display drawing. Dynamically updated based on FPS calculations. + static int64_t usleepcycles = 16384*4; // step-down for display drawing. Dynamically updated based on FPS calculations. if (g_vm->vmdisplay->needsRedraw()) { AiieRect what = g_vm->vmdisplay->getDirtyRect(); @@ -409,7 +409,7 @@ void doDebugging() g_display->debugMsg(buf); break; case D_SHOWCYCLES: - sprintf(buf, "%X", g_cpu->cycles); + sprintf(buf, "%llX", g_cpu->cycles); g_display->debugMsg(buf); break; /* diff --git a/sdl/sdl-speaker.cpp b/sdl/sdl-speaker.cpp index 014d885..2d4f118 100644 --- a/sdl/sdl-speaker.cpp +++ b/sdl/sdl-speaker.cpp @@ -29,7 +29,7 @@ static volatile uint32_t skippedSamples = 0; #define SAMPLEBYTES sizeof(short) volatile uint8_t audioRunning = 0; -volatile uint32_t lastFilledTime = 0; +volatile int64_t lastFilledTime = 0; // Debugging by writing a wav file with the sound output... @@ -157,11 +157,11 @@ void SDLSpeaker::begin() SDL_PauseAudio(0); } -void SDLSpeaker::toggle(uint32_t c) +void SDLSpeaker::toggle(int64_t c) { pthread_mutex_lock(&togmutex); - uint32_t expectedCycleNumber = (float)c * (float)44100 / (float)g_speed; + int64_t expectedCycleNumber = (float)c * (float)44100 / (float)g_speed; if (lastFilledTime == 0) { lastFilledTime = expectedCycleNumber; } @@ -217,7 +217,7 @@ void SDLSpeaker::toggle(uint32_t c) pthread_mutex_unlock(&togmutex); } -void SDLSpeaker::maintainSpeaker(uint32_t c, uint64_t microseconds) +void SDLSpeaker::maintainSpeaker(int64_t c, uint64_t microseconds) { } diff --git a/sdl/sdl-speaker.h b/sdl/sdl-speaker.h index aa33ced..4eddda5 100644 --- a/sdl/sdl-speaker.h +++ b/sdl/sdl-speaker.h @@ -12,8 +12,8 @@ class SDLSpeaker : public PhysicalSpeaker { virtual void begin(); - virtual void toggle(uint32_t c); - virtual void maintainSpeaker(uint32_t c, uint64_t microseconds); + virtual void toggle(int64_t c); + virtual void maintainSpeaker(int64_t c, uint64_t microseconds); virtual void beginMixing(); virtual void mixOutput(uint8_t v); diff --git a/sdl/timeutil.h b/sdl/timeutil.h index 82e2518..737e3cc 100644 --- a/sdl/timeutil.h +++ b/sdl/timeutil.h @@ -28,7 +28,7 @@ static int do_gettime(struct timespec *tp) { // adds the number of nanoseconds that 'cycles' takes to *start and // returns it in *out static void timespec_add_cycles(struct timespec *start, - int32_t cycles, + int64_t cycles, struct timespec *out) { out->tv_sec = start->tv_sec; diff --git a/teensy/teensy-speaker.cpp b/teensy/teensy-speaker.cpp index 6e9c933..822fe3b 100644 --- a/teensy/teensy-speaker.cpp +++ b/teensy/teensy-speaker.cpp @@ -32,7 +32,7 @@ static volatile uint32_t skippedSamples; // Who knows where this will // too long & restart all the // constants) static volatile uint8_t audioRunning = 0; // FIXME: needs constants abstracted -static volatile uint32_t lastFilledTime = 0; +static volatile int64_t lastFilledTime = 0; // how full do we want the audio buffer before we start it playing? #define AUDIO_WATERLEVEL 4096 @@ -66,7 +66,7 @@ void TeensySpeaker::begin() audioRunning = 0; } -void TeensySpeaker::toggle(uint32_t c) +void TeensySpeaker::toggle(int64_t c) { // Figure out when the last time was that we put data in the audio buffer; // then figure out how many audio buffer cycles we have to fill from that @@ -74,7 +74,7 @@ void TeensySpeaker::toggle(uint32_t c) __disable_irq(); // We expect to have filled to this cycle number... - uint32_t expectedCycleNumber = (float)c * (float)AUDIO_SAMPLE_RATE_EXACT / (float)g_speed; + int64_t expectedCycleNumber = (float)c * (float)AUDIO_SAMPLE_RATE_EXACT / (float)g_speed; // Dynamically initialize the lastFilledTime based on the start time of the // audio channel. if (lastFilledTime == 0) @@ -133,7 +133,7 @@ void TeensySpeaker::toggle(uint32_t c) __enable_irq(); } -void TeensySpeaker::maintainSpeaker(uint32_t c, uint64_t microseconds) +void TeensySpeaker::maintainSpeaker(int64_t c, uint64_t microseconds) { begin(); // flush! Hack. FIXME. } diff --git a/teensy/teensy-speaker.h b/teensy/teensy-speaker.h index b956791..43da5d5 100644 --- a/teensy/teensy-speaker.h +++ b/teensy/teensy-speaker.h @@ -18,9 +18,9 @@ class TeensySpeaker : public PhysicalSpeaker { virtual void begin(); - virtual void toggle(uint32_t c); + virtual void toggle(int64_t c); virtual void maintainSpeaker(); - virtual void maintainSpeaker(uint32_t c, uint64_t microseconds); + virtual void maintainSpeaker(int64_t c, uint64_t microseconds); virtual void beginMixing(); virtual void mixOutput(uint8_t v); diff --git a/vmkeyboard.h b/vmkeyboard.h index 53da986..e95ccf9 100644 --- a/vmkeyboard.h +++ b/vmkeyboard.h @@ -9,7 +9,7 @@ class VMKeyboard { virtual void keyDepressed(uint8_t k) = 0; virtual void keyReleased(uint8_t k) = 0; - virtual void maintainKeyboard(uint32_t cycleCount) = 0; + virtual void maintainKeyboard(int64_t cycleCount) = 0; }; #endif