diff --git a/apple/applemmu.cpp b/apple/applemmu.cpp index 2ba4005..84216e2 100644 --- a/apple/applemmu.cpp +++ b/apple/applemmu.cpp @@ -12,10 +12,13 @@ #include "physicalspeaker.h" #include "cpu.h" +#include "serialize.h" + #include "globals.h" #ifdef TEENSYDUINO #include "teensy-clock.h" +#include "iocompat.h" #else #include "nix-clock.h" #endif @@ -166,24 +169,23 @@ AppleMMU::~AppleMMU() bool AppleMMU::Serialize(int8_t fd) { - uint8_t buf[13] = { MMUMAGIC, - (uint8_t)((switches >> 8) & 0xFF), - (uint8_t)((switches ) & 0xFF), - auxRamRead ? 1 : 0, - auxRamWrite ? 1 : 0, - bank2 ? 1 : 0, - readbsr ? 1 : 0, - writebsr ? 1 : 0, - altzp ? 1 : 0, - intcxrom ? 1 : 0, - slot3rom ? 1 : 0, - slotLatch, - preWriteFlag ? 1 : 0 }; - if (g_filemanager->write(fd, buf, 13) != 13) - return false; + serializeMagic(MMUMAGIC); + serialize16(switches); + serialize8(auxRamRead ? 1 : 0); + serialize8(auxRamWrite ? 1 : 0); + serialize8(bank2 ? 1 : 0); + serialize8(readbsr ? 1 : 0); + serialize8(writebsr ? 1 : 0); + serialize8(altzp ? 1 : 0); + serialize8(intcxrom ? 1 : 0); + serialize8(slot3rom ? 1 : 0); + serialize8(slotLatch); + serialize8(preWriteFlag ? 1 : 0); - if (!g_ram.Serialize(fd)) - return false; + if (!g_ram.Serialize(fd)) { + printf("Failed to serialize RAM\n"); + goto err; + } // readPages & writePages don't need suspending, but we will need to // recalculate after resume @@ -191,47 +193,42 @@ bool AppleMMU::Serialize(int8_t fd) // Not suspending/resuming slots b/c they're a fixed configuration // in this project. Should probably checksum them though. FIXME. - if (g_filemanager->write(fd, buf, 1) != 1) - return false; - + serializeMagic(MMUMAGIC); return true; + + err: + return false; } bool AppleMMU::Deserialize(int8_t fd) { - uint8_t buf[13]; + deserializeMagic(MMUMAGIC); - if (g_filemanager->read(fd, buf, 13) != 13) - return false; + deserialize16(switches); + serialize8(auxRamRead); + serialize8(auxRamWrite); + serialize8(bank2); + serialize8(readbsr); + serialize8(writebsr); + serialize8(altzp); + serialize8(intcxrom); + serialize8(slot3rom); + serialize8(slotLatch); + serialize8(preWriteFlag); - if (buf[0] != MMUMAGIC) - return false; - - switches = (buf[1] << 8) | buf[2]; - auxRamRead = buf[3]; - auxRamWrite = buf[4]; - bank2 = buf[5]; - readbsr = buf[6]; - writebsr = buf[7]; - altzp = buf[8]; - intcxrom = buf[9]; - slot3rom = buf[10]; - slotLatch = buf[11]; - preWriteFlag = buf[12]; - if (!g_ram.Deserialize(fd)) { - return false; + goto err; } - if (g_filemanager->read(fd, buf, 1) != 1) - return false; - if (buf[0] != MMUMAGIC) - return false; + deserializeMagic(MMUMAGIC); // Reset readPages[] and writePages[] and the display resetDisplay(); return true; + + err: + return false; } diff --git a/apple/applevm.cpp b/apple/applevm.cpp index b0c822c..3fc0d2c 100644 --- a/apple/applevm.cpp +++ b/apple/applevm.cpp @@ -6,10 +6,13 @@ #include "applekeyboard.h" #include "physicalkeyboard.h" +#include "serialize.h" + #include "globals.h" #ifdef TEENSYDUINO #include "teensy-println.h" +#include "iocompat.h" #endif #include @@ -43,83 +46,75 @@ AppleVM::~AppleVM() delete parallel; } -void AppleVM::Suspend(const char *fn) +bool AppleVM::Suspend(const char *fn) { /* Open a new suspend file via the file manager; tell all our objects to serialize in to it; close the file */ - int8_t fh = g_filemanager->openFile(fn); - if (fh == -1) { + int8_t fd = g_filemanager->openFile(fn); + if (fd == -1) { // Unable to open; skip suspend - return; + printf("failed to open suspend file\n"); + return false; } /* Header */ - if (g_filemanager->write(fh, suspendHdr, strlen(suspendHdr)) != strlen(suspendHdr)) - return; + serializeString(suspendHdr); /* Tell all of the peripherals to suspend */ - if (g_cpu->Serialize(fh) && - disk6->Serialize(fh) && - hd32->Serialize(fh) + if (g_cpu->Serialize(fd) && + disk6->Serialize(fd) && + hd32->Serialize(fd) ) { -#ifdef TEENSYDUINO - println("All serialized successfully"); -#else printf("All serialized successfully\n"); -#endif } - g_filemanager->closeFile(fh); + g_filemanager->closeFile(fd); + return true; + + err: + g_filemanager->closeFile(fd); + return false; } -void AppleVM::Resume(const char *fn) +bool AppleVM::Resume(const char *fn) { /* Open the given suspend file via the file manager; tell all our objects to deserialize from it; close the file */ - int8_t fh = g_filemanager->openFile(fn); - if (fh == -1) { + int8_t fd = g_filemanager->openFile(fn); + if (fd == -1) { // Unable to open; skip resume -#ifdef TEENSYDUINO - print("Unable to open resume file "); - println(fn); -#else - printf("Unable to open resume file\n"); -#endif - g_filemanager->closeFile(fh); - return; + printf("Unable to open resume file '%s'\n", fn); + goto err; } /* Header */ - uint8_t c; - for (int i=0; iread(fh, &c, 1) != 1 || - c != suspendHdr[i]) { - /* Failed to read correct header; abort */ - g_filemanager->closeFile(fh); - return; - } + deserializeString(debugBuf); + if (strcmp(debugBuf, suspendHdr)) { + printf("Bad file header while resuming\n"); + goto err; } /* Tell all of the peripherals to resume */ - if (g_cpu->Deserialize(fh) && - disk6->Deserialize(fh) && - hd32->Deserialize(fh) + if (g_cpu->Deserialize(fd) && + disk6->Deserialize(fd) && + hd32->Deserialize(fd) ) { -#ifdef TEENSYDUINO - println("Deserialization successful"); -#else printf("All deserialized successfully\n"); -#endif } else { -#ifndef TEENSYDUINO printf("Deserialization failed\n"); +#ifndef TEENSYDUINO exit(1); #endif + goto err; } - g_filemanager->closeFile(fh); + g_filemanager->closeFile(fd); + return true; + err: + g_filemanager->closeFile(fd); + return false; } // fixme: make member vars diff --git a/apple/applevm.h b/apple/applevm.h index 65e02f4..57759b1 100644 --- a/apple/applevm.h +++ b/apple/applevm.h @@ -15,8 +15,8 @@ class AppleVM : public VM { AppleVM(); virtual ~AppleVM(); - void Suspend(const char *fn); - void Resume(const char *fn); + bool Suspend(const char *fn); + bool Resume(const char *fn); void cpuMaintenance(int64_t cycles); diff --git a/apple/diskii.cpp b/apple/diskii.cpp index 16177d1..42f9288 100644 --- a/apple/diskii.cpp +++ b/apple/diskii.cpp @@ -3,6 +3,7 @@ #ifdef TEENSYDUINO #include #include "teensy-println.h" +#include "iocompat.h" #else #include #include @@ -16,6 +17,8 @@ #include "globals.h" #include "appleui.h" +#include "serialize.h" + #include "diskii-rom.h" #define DISKIIMAGIC 0xAA @@ -57,171 +60,101 @@ DiskII::~DiskII() bool DiskII::Serialize(int8_t fd) { - uint8_t buf[27] = { DISKIIMAGIC, - readWriteLatch, - sequencer, - dataRegister, - writeMode, - writeProt, - selectedDisk }; + serializeMagic(DISKIIMAGIC); + serialize8(readWriteLatch); + serialize8(sequencer); + serialize8(dataRegister); + serialize8(writeMode); + serialize8(writeProt); + serialize8(selectedDisk); - if (g_filemanager->write(fd, buf, 7) != 7) { - return false; - } - for (int i=0; i<2; i++) { - uint8_t ptr = 0; - buf[ptr++] = curHalfTrack[i]; - buf[ptr++] = curWozTrack[i]; - buf[ptr++] = curPhase[i]; - buf[ptr++] = ((driveSpinupCycles[i] >> 56) & 0xFF); - buf[ptr++] = ((driveSpinupCycles[i] >> 48) & 0xFF); - buf[ptr++] = ((driveSpinupCycles[i] >> 40) & 0xFF); - buf[ptr++] = ((driveSpinupCycles[i] >> 32) & 0xFF); - buf[ptr++] = ((driveSpinupCycles[i] >> 24) & 0xFF); - buf[ptr++] = ((driveSpinupCycles[i] >> 16) & 0xFF); - buf[ptr++] = ((driveSpinupCycles[i] >> 8) & 0xFF); - buf[ptr++] = ((driveSpinupCycles[i] ) & 0xFF); - buf[ptr++] = ((deliveredDiskBits[i] >> 56) & 0xFF); - buf[ptr++] = ((deliveredDiskBits[i] >> 48) & 0xFF); - buf[ptr++] = ((deliveredDiskBits[i] >> 40) & 0xFF); - buf[ptr++] = ((deliveredDiskBits[i] >> 32) & 0xFF); - buf[ptr++] = ((deliveredDiskBits[i] >> 24) & 0xFF); - 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 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; - } + serialize8(curHalfTrack[i]); + serialize8(curWozTrack[i]); + serialize8(curPhase[i]); + serialize64(driveSpinupCycles[i]); + serialize64(deliveredDiskBits[i]); + serialize64(diskIsSpinningUntil[i]); if (disk[i]) { // Make sure we have flushed the disk images disk[i]->flush(); flushAt[i] = 0; // and there's no need to re-flush them now - buf[0] = 1; - if (g_filemanager->write(fd, buf, 1) != 1) - return false; + serialize8(1); // FIXME: this ONLY works for builds using the filemanager to read // the disk image, so it's broken until we port Woz to do that! const char *fn = disk[i]->diskName(); - if (g_filemanager->write(fd, fn, strlen(fn)+1) != strlen(fn)+1) // include null terminator - return false; + serializeString(fn); if (!disk[i]->Serialize(fd)) - return false; + goto err; } else { - buf[0] = 0; - if (g_filemanager->write(fd, buf, 0) != 1) - return false; + serialize8(0); } } - buf[0] = DISKIIMAGIC; - if (g_filemanager->write(fd, buf, 1) != 1) - return false; + serializeMagic(DISKIIMAGIC); return true; + err: + return false; } bool DiskII::Deserialize(int8_t fd) { - uint8_t buf[MAXPATH]; - if (g_filemanager->read(fd, buf, 7) != 7) - return false; - if (buf[0] != DISKIIMAGIC) - return false; + deserializeMagic(DISKIIMAGIC); - readWriteLatch = buf[1]; - sequencer = buf[2]; - dataRegister = buf[3]; - writeMode = buf[4]; - writeProt = buf[5]; - selectedDisk = buf[6]; + deserialize8(readWriteLatch); + deserialize8(sequencer); + deserialize8(dataRegister); + deserialize8(writeMode); + deserialize8(writeProt); + deserialize8(selectedDisk); for (int i=0; i<2; i++) { - uint8_t ptr = 0; - if (g_filemanager->read(fd, buf, 27) != 27) - return false; + deserialize8(curHalfTrack[i]); + deserialize8(curWozTrack[i]); + deserialize8(curPhase[i]); - curHalfTrack[i] = buf[ptr++]; - curWozTrack[i] = buf[ptr++]; - curPhase[i] = buf[ptr++]; + deserialize64(driveSpinupCycles[i]); + deserialize64(deliveredDiskBits[i]); + deserialize64(diskIsSpinningUntil[i]); - driveSpinupCycles[i] = buf[ptr++]; - driveSpinupCycles[i] <<= 8; driveSpinupCycles[i] |= buf[ptr++]; - driveSpinupCycles[i] <<= 8; driveSpinupCycles[i] |= buf[ptr++]; - driveSpinupCycles[i] <<= 8; driveSpinupCycles[i] |= buf[ptr++]; - driveSpinupCycles[i] <<= 8; driveSpinupCycles[i] |= buf[ptr++]; - driveSpinupCycles[i] <<= 8; driveSpinupCycles[i] |= buf[ptr++]; - driveSpinupCycles[i] <<= 8; driveSpinupCycles[i] |= buf[ptr++]; - driveSpinupCycles[i] <<= 8; driveSpinupCycles[i] |= buf[ptr++]; - - deliveredDiskBits[i] = buf[ptr++]; - deliveredDiskBits[i] <<= 8; deliveredDiskBits[i] |= buf[ptr++]; - deliveredDiskBits[i] <<= 8; deliveredDiskBits[i] |= buf[ptr++]; - deliveredDiskBits[i] <<= 8; deliveredDiskBits[i] |= buf[ptr++]; - deliveredDiskBits[i] <<= 8; deliveredDiskBits[i] |= buf[ptr++]; - deliveredDiskBits[i] <<= 8; deliveredDiskBits[i] |= buf[ptr++]; - deliveredDiskBits[i] <<= 8; deliveredDiskBits[i] |= buf[ptr++]; - deliveredDiskBits[i] <<= 8; deliveredDiskBits[i] |= buf[ptr++]; - - 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++]; - diskIsSpinningUntil[i] <<= 8; diskIsSpinningUntil[i] |= buf[ptr++]; + uint8_t hasDisk; + deserialize8(hasDisk); - if (disk[i]) - delete disk[i]; - if (g_filemanager->read(fd, buf, 1) != 1) - return false; - if (buf[0]) { + if (disk[i]) delete disk[i]; + if (hasDisk) { disk[i] = new WozSerializer(); - ptr = 0; // FIXME: MAXPATH check! - while (1) { - if (g_filemanager->read(fd, &buf[ptr++], 1) != 1) - return false; - if (buf[ptr-1] == 0) - break; - } - if (buf[0]) { - // Important we don't read all the tracks, so we can also flush - // writes back to the fd... - disk[i]->readFile((char *)buf, false, T_AUTO); // FIXME error checking + char fn[MAXPATH]; + deserializeString(fn); + if (fn[0]) { + printf("Restoring disk image named '%s'\n", fn); + disk[i]->readFile((char *)fn, false, T_AUTO); // FIXME error checking } else { // ERROR: there's a disk but we don't have the path to its image? - return false; + printf("Failed to read inserted disk name for disk %d\n", i); + goto err; } - if (!disk[i]->Deserialize(fd)) - return false; + if (!disk[i]->Deserialize(fd)) { + printf("Failed to deserialize disk %d\n", i); + goto err; + } } else { disk[i] = NULL; } } - if (g_filemanager->read(fd, buf, 1) != 1) - return false; - if (buf[0] != DISKIIMAGIC) - return false; + deserializeMagic(DISKIIMAGIC); return true; + + err: + return false; } void DiskII::Reset() diff --git a/apple/hd32.cpp b/apple/hd32.cpp index 4837d39..f05030c 100644 --- a/apple/hd32.cpp +++ b/apple/hd32.cpp @@ -12,6 +12,7 @@ #ifdef TEENSYDUINO #include #include "teensy-println.h" +#include "iocompat.h" #else #include #include @@ -23,6 +24,8 @@ #include "applemmu.h" // for FLOATING +#include "serialize.h" + #include "globals.h" #include "hd32-rom.h" @@ -66,92 +69,58 @@ HD32::~HD32() bool HD32::Serialize(int8_t fd) { - uint8_t buf[19] = { HD32MAGIC, - driveSelected, - unitSelected, - command, - enabled, - errorState[0], - errorState[1], - (uint8_t)((memBlock[0] >> 8) & 0xFF), - (uint8_t)((memBlock[0] ) & 0xFF), - (uint8_t)((memBlock[1] >> 8) & 0xFF), - (uint8_t)((memBlock[1] ) & 0xFF), - (uint8_t)((cursor[0] >> 24) & 0xFF), - (uint8_t)((cursor[0] >> 16) & 0xFF), - (uint8_t)((cursor[0] >> 8) & 0xFF), - (uint8_t)((cursor[0] ) & 0xFF), - (uint8_t)((cursor[1] >> 24) & 0xFF), - (uint8_t)((cursor[1] >> 16) & 0xFF), - (uint8_t)((cursor[1] >> 8) & 0xFF), - (uint8_t)((cursor[1] ) & 0xFF) - }; - if (g_filemanager->write(fd, buf, 19) != 10) - return false; + serializeMagic(HD32MAGIC); + serialize8(driveSelected); + serialize8(unitSelected); + serialize8(command); + serialize8(enabled); + serialize8(errorState[0]); + serialize8(errorState[1]); + serialize16(memBlock[0]); + serialize16(memBlock[1]); + serialize32(cursor[0]); + serialize32(cursor[1]); for (int i=0; i<2; i++) { const char *fn = diskName(i); - if (g_filemanager->write(fd, fn, strlen(fn)+1) != strlen(fn)+1) { - return false; - } + serializeString(fn); } + serializeMagic(HD32MAGIC); + return true; - buf[0] = HD32MAGIC; - return (g_filemanager->write(fd, buf, 1) == 1); + err: + return false; } bool HD32::Deserialize(int8_t fd) { - uint8_t buf[255]; - if (g_filemanager->read(fd, buf, 19) != 19) { - return false; - } - if (buf[0] != HD32MAGIC) - return false; - - driveSelected = buf[1]; - unitSelected = buf[2]; - command = buf[3]; - enabled = buf[4]; - errorState[0] = buf[5]; - errorState[1] = buf[6]; - memBlock[0] = buf[7]; - memBlock[0] <<= 8; memBlock[0] |= buf[8]; - memBlock[1] = buf[9]; - memBlock[1] <<= 8; memBlock[1] |= buf[10]; - cursor[0] = buf[11]; - cursor[0] <<= 8; cursor[0] |= buf[12]; - cursor[0] <<= 8; cursor[0] |= buf[13]; - cursor[0] <<= 8; cursor[0] |= buf[14]; - cursor[1] = buf[15]; - cursor[1] <<= 8; cursor[1] |= buf[16]; - cursor[1] <<= 8; cursor[1] |= buf[17]; - cursor[1] <<= 8; cursor[1] |= buf[18]; + deserializeMagic(HD32MAGIC); + deserialize8(driveSelected); + deserialize8(unitSelected); + deserialize8(command); + deserialize8(enabled); + deserialize8(errorState[0]); + deserialize8(errorState[1]); + deserialize16(memBlock[0]); + deserialize16(memBlock[1]); + deserialize32(cursor[0]); + deserialize32(cursor[1]); + cachedBlockNum = -1; // just invalidate the cache; it will reload... for (int i=0; i<2; i++) { - uint32_t ptr = 0; - // FIXME: MAXPATH check! - while (1) { - if (g_filemanager->read(fd, &buf[ptr++], 1) != 1) - return false; - if (buf[ptr-1] == 0) - break; - } - if (strlen((char *)buf)) { - // FIXME: this tromps on error and some other vars ... that we just restored - insertDisk(i, (char *)buf); - } + char buf[MAXPATH]; + deserializeString(buf); + // FIXME: this tromps on error and some other vars ... that we just restored + insertDisk(i, (char *)buf); } - if (g_filemanager->read(fd, buf, 1) != 1) - return false; - - if (buf[0] != HD32MAGIC) - return false; - + deserializeMagic(HD32MAGIC); + return true; + err: + return false; } void HD32::Reset() diff --git a/apple/woz-serializer.cpp b/apple/woz-serializer.cpp index 926182a..890d3eb 100644 --- a/apple/woz-serializer.cpp +++ b/apple/woz-serializer.cpp @@ -1,6 +1,12 @@ #include "woz-serializer.h" #include "globals.h" +#include "serialize.h" + +#ifdef TEENSYDUINO +#include "iocompat.h" +#endif + #define WOZMAGIC 0xD5 WozSerializer::WozSerializer() : Woz(0,0) @@ -20,60 +26,36 @@ bool WozSerializer::Serialize(int8_t fd) // If we're being asked to serialize, make sure we've flushed any data first flush(); - uint8_t buf[17] = { WOZMAGIC, - (trackPointer >> 24) & 0xFF, - (trackPointer >> 16) & 0xFF, - (trackPointer >> 8) & 0xFF, - (trackPointer ) & 0xFF, - (trackBitCounter >> 24) & 0xFF, - (trackBitCounter >> 16) & 0xFF, - (trackBitCounter >> 8) & 0xFF, - (trackBitCounter ) & 0xFF, - (lastReadPointer >> 24) & 0xFF, - (lastReadPointer >> 16) & 0xFF, - (lastReadPointer >> 8) & 0xFF, - (lastReadPointer ) & 0xFF, - trackByte, - trackBitIdx, - trackLoopCounter, - WOZMAGIC }; - if (g_filemanager->write(fd, buf, 17) != 17) - return false; + serializeMagic(WOZMAGIC); + serialize32(trackPointer); + serialize32(trackBitCounter); + serialize32(lastReadPointer); + serialize8(trackByte); + serialize8(trackBitIdx); + serialize8(trackLoopCounter); + serializeMagic(WOZMAGIC); return true; + + err: + return false; } bool WozSerializer::Deserialize(int8_t fd) { // Before deserializing, the caller has to re-load the right disk image! - uint8_t buf[17]; - if (g_filemanager->read(fd, buf, 17) != 17) - return false; - - if (buf[0] != WOZMAGIC) - return false; - - trackPointer = buf[1]; - trackPointer <<= 8; trackPointer |= buf[2]; - trackPointer <<= 8; trackPointer |= buf[3]; - trackPointer <<= 8; trackPointer |= buf[4]; - - trackBitCounter = buf[5]; - trackBitCounter <<= 8; trackBitCounter |= buf[6]; - trackBitCounter <<= 8; trackBitCounter |= buf[7]; - trackBitCounter <<= 8; trackBitCounter |= buf[8]; - - lastReadPointer = buf[9]; - lastReadPointer <<= 8; lastReadPointer |= buf[10]; - lastReadPointer <<= 8; lastReadPointer |= buf[11]; - lastReadPointer <<= 8; lastReadPointer |= buf[12]; - - trackByte = buf[13]; - trackBitIdx = buf[14]; - trackLoopCounter = buf[15]; - if (buf[16] != WOZMAGIC) - return false; + deserializeMagic(WOZMAGIC); + deserialize32(trackPointer); + deserialize32(trackBitCounter); + deserialize32(lastReadPointer); + deserialize8(trackByte); + deserialize8(trackBitIdx); + deserialize8(trackLoopCounter); + deserializeMagic(WOZMAGIC); return true; + + err: + return false; } diff --git a/cpu.cpp b/cpu.cpp index 7738457..532a3b1 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -7,10 +7,13 @@ #include #include "mmu.h" +#include "serialize.h" + #include "globals.h" #ifdef TEENSYDUINO #include "teensy-println.h" +#include "iocompat.h" #endif // define DEBUGSTEPS to show disassembly of each instruction as it's processed @@ -320,74 +323,54 @@ Cpu::~Cpu() mmu = NULL; } -bool Cpu::Serialize(int8_t fh) +bool Cpu::Serialize(int8_t fd) { - uint8_t buf[13] = { CPUMAGIC, - (uint8_t)((pc >> 8) & 0xFF), - (uint8_t)((pc ) & 0xFF), - sp, - a, - x, - y, - flags, - (uint8_t)((cycles >> 24) & 0xFF), - (uint8_t)((cycles >> 16) & 0xFF), - (uint8_t)((cycles >> 8) & 0xFF), - (uint8_t)((cycles ) & 0xFF), - irqPending ? (uint8_t)1 : (uint8_t)0 }; + serializeMagic(CPUMAGIC); + serialize16(pc); + serialize8(sp); + serialize8(a); + serialize8(x); + serialize8(y); + serialize8(flags); + serialize32(cycles); + serialize8(irqPending ? 1 : 0); - if (g_filemanager->write(fh, buf, 13) != 13) - return false; - - if (!mmu->Serialize(fh)) { -#ifndef TEENSYDUINO + if (!mmu->Serialize(fd)) { printf("MMU serialization failed\n"); -#else - println("MMU serialization failed"); -#endif - return false; + goto err; } - - if (g_filemanager->write(fh, buf, 1) != 1) - return false; + serializeMagic(CPUMAGIC); return true; + + err: + return false; } -bool Cpu::Deserialize(int8_t fh) +bool Cpu::Deserialize(int8_t fd) { - uint8_t buf[13]; - if (g_filemanager->read(fh, buf, 13) != 13) - return false; - if (buf[0] != CPUMAGIC) - return false; - pc = (buf[1] << 8) | buf[2]; - sp = buf[3]; - a = buf[4]; - x = buf[5]; - y = buf[6]; - flags = buf[7]; - - cycles = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11]; - - irqPending = buf[12]; - - if (!mmu->Deserialize(fh)) { -#ifndef TEENSYDUINO + deserializeMagic(CPUMAGIC); + deserialize16(pc); + deserialize8(sp); + deserialize8(a); + deserialize8(x); + deserialize8(y); + deserialize8(flags); + deserialize32(cycles); + deserialize8(irqPending); + + if (!mmu->Deserialize(fd)) { printf("MMU deserialization failed\n"); -#endif return false; } - if (g_filemanager->read(fh, buf, 1) != 1) - return false; - if (buf[0] != CPUMAGIC) - return false; + deserializeMagic(CPUMAGIC); -#ifndef TEENSYDUINO printf("CPU deserialization complete\n"); -#endif return true; + + err: + return false; } void Cpu::Reset() diff --git a/globals.cpp b/globals.cpp index e9e683d..e614a4c 100644 --- a/globals.cpp +++ b/globals.cpp @@ -19,3 +19,7 @@ bool g_invertPaddleX = false; bool g_invertPaddleY = false; char debugBuf[255]; + +#ifdef TEENSYDUINO +char fsbuf[200]; +#endif diff --git a/globals.h b/globals.h index d8fda9a..5edd239 100644 --- a/globals.h +++ b/globals.h @@ -56,4 +56,8 @@ extern bool g_invertPaddleY; extern char debugBuf[255]; +#ifdef TEENSYDUINO +extern char fsbuf[200]; +#endif + #endif diff --git a/nix/nix-filemanager.cpp b/nix/nix-filemanager.cpp index 9793d16..5b8b5bc 100644 --- a/nix/nix-filemanager.cpp +++ b/nix/nix-filemanager.cpp @@ -194,33 +194,43 @@ void NixFileManager::seekToEnd(int8_t fd) int NixFileManager::write(int8_t fd, const void *buf, int nbyte) { - if (fd < 0 || fd >= numCached) + if (fd < 0 || fd >= numCached) { + printf("invalid fd (out of range)\n"); return -1; + } - if (cachedNames[fd][0] == 0) + if (cachedNames[fd][0] == 0) { + printf("invalid fd (not opened)\n"); return -1; + } uint32_t pos = fileSeekPositions[fd]; // open, seek, write, close. - bool ret = false; + ssize_t rv = 0; int ffd = ::open(cachedNames[fd], O_WRONLY|O_CREAT, 0644); - if (ffd != -1) { - if (::lseek(ffd, pos, SEEK_SET) == -1) { - close(ffd); - return -1; - } - ssize_t rv = ::write(ffd, buf, nbyte); - if (rv != nbyte) { - printf("error writing: %d; wanted to write %d got %d\n", errno, nbyte, ret); - } - close(ffd); - } else { + if (ffd == -1) { printf("Failed to open '%s' for writing: %d\n", cachedNames[fd], errno); + close(ffd); + return -1; } + + if (::lseek(ffd, pos, SEEK_SET) == -1) { + printf("failed to open and seek\n"); + close(ffd); + return -1; + } + + rv = ::write(ffd, buf, nbyte); + if (rv != nbyte) { + printf("error writing: %d; wanted to write %d got %ld\n", errno, nbyte, rv); + } + + close(ffd); + fileSeekPositions[fd]+=nbyte; - return ret; + return (int)rv; }; int NixFileManager::read(int8_t fd, void *buf, int nbyte) diff --git a/teensy/fscompat.h b/teensy/fscompat.h index 0fc0830..1fd1a8a 100644 --- a/teensy/fscompat.h +++ b/teensy/fscompat.h @@ -16,8 +16,4 @@ #define read(filedes,buf,nbyte) g_filemanager->read(filedes,buf,nbyte) #define lseek(filedes,offset,whence) g_filemanager->lseek(filedes,offset,whence) -static char fsbuf[200]; -#define printf(x, ...) {sprintf(fsbuf, x, ##__VA_ARGS__); Serial.println(fsbuf); Serial.flush(); Serial.send_now();} -#define fprintf(f, x, ...) {sprintf(fsbuf, x, ##__VA_ARGS__); Serial.println(fsbuf); Serial.flush(); Serial.send_now();} -#define perror(x) {Serial.println(x);Serial.flush(); Serial.send_now();} - +#include "iocompat.h" diff --git a/teensy/iocompat.h b/teensy/iocompat.h new file mode 100644 index 0000000..94531ce --- /dev/null +++ b/teensy/iocompat.h @@ -0,0 +1,12 @@ +#ifndef __IOCOMPAT_H +#define __IOCOMPAT_H + +#include "globals.h" +#include + +#define printf(x, ...) {sprintf(fsbuf, x, ##__VA_ARGS__); Serial.println(fsbuf); Serial.flush(); Serial.send_now();} +#define fprintf(f, x, ...) {sprintf(fsbuf, x, ##__VA_ARGS__); Serial.println(fsbuf); Serial.flush(); Serial.send_now();} +#define perror(x) {Serial.println(x);Serial.flush(); Serial.send_now();} + + +#endif diff --git a/teensy/teensy-filemanager.cpp b/teensy/teensy-filemanager.cpp index 44b4f48..5c24a80 100644 --- a/teensy/teensy-filemanager.cpp +++ b/teensy/teensy-filemanager.cpp @@ -9,7 +9,7 @@ static SdFat sd; static FsFile cacheFile; static FsFile outerDir; - +#include "iocompat.h" TeensyFileManager::TeensyFileManager() { @@ -179,14 +179,15 @@ bool TeensyFileManager::_prepCache(int8_t fd) } // Open the new one - cacheFile.open(cachedNames[fd], O_RDWR); + cacheFile.open(cachedNames[fd], O_CREAT|O_RDWR); if (!cacheFile) { + printf("failed to open cacheFile\n"); return false; } cacheFd = fd; // cache is live } - return true; // FIXME error handling + return true; } void TeensyFileManager::getRootPath(char *toWhere, int8_t maxLen) @@ -225,10 +226,12 @@ int TeensyFileManager::write(int8_t fd, const void *buf, int nbyte) { // open, seek, write, close. if (fd < 0 || fd >= numCached) { + printf("no fd\n"); return -1; } if (cachedNames[fd][0] == 0) { + printf("no name\n"); return -1; } @@ -237,15 +240,16 @@ int TeensyFileManager::write(int8_t fd, const void *buf, int nbyte) uint32_t pos = fileSeekPositions[fd]; if (!cacheFile.seek(pos)) { + printf("can't seek to %d\n", pos); return -1; } if (cacheFile.write((const uint8_t *)buf, (size_t)nbyte) != (size_t)nbyte) { + printf("can't write\n"); return -1; } fileSeekPositions[fd] += nbyte; - cacheFile.close(); return nbyte; }; @@ -266,6 +270,7 @@ int TeensyFileManager::read(int8_t fd, void *buf, int nbyte) if (!cacheFile.seek(pos)) { return -1; } + fileSeekPositions[fd] += nbyte; if (cacheFile.read(buf, nbyte) != nbyte) { diff --git a/vm.h b/vm.h index c98a02a..6eebc11 100644 --- a/vm.h +++ b/vm.h @@ -16,8 +16,8 @@ class VM { VM() { mmu=NULL; vmdisplay = NULL; hasIRQ = false;} virtual ~VM() { if (mmu) delete mmu; if (vmdisplay) delete vmdisplay; } - virtual void Suspend(const char *fn) = 0; - virtual void Resume(const char *fn) = 0; + virtual bool Suspend(const char *fn) = 0; + virtual bool Resume(const char *fn) = 0; virtual void SetMMU(MMU *mmu) { this->mmu = mmu; } virtual MMU *getMMU() { return mmu; } diff --git a/vmram.cpp b/vmram.cpp index cb07178..236de94 100644 --- a/vmram.cpp +++ b/vmram.cpp @@ -5,6 +5,7 @@ #include "vmram.h" #include +#include "serialize.h" #include "globals.h" #ifdef TEENSYDUINO @@ -55,46 +56,35 @@ uint8_t *VMRam::memPtr(uint32_t addr) bool VMRam::Serialize(int8_t fd) { uint32_t size = sizeof(preallocatedRam); - uint8_t buf[5] = { RAMMAGIC, - (uint8_t)((size >> 24) & 0xFF), - (uint8_t)((size >> 16) & 0xFF), - (uint8_t)((size >> 8) & 0xFF), - (uint8_t)((size ) & 0xFF) }; - if (g_filemanager->write(fd, buf, 5) != 5) - return false; + serializeMagic(RAMMAGIC); + serialize32(size); if (g_filemanager->write(fd, preallocatedRam, sizeof(preallocatedRam)) != sizeof(preallocatedRam)) - return false; - - if (g_filemanager->write(fd, buf, 1) != 1) - return false; + goto err; + + serializeMagic(RAMMAGIC); return true; + + err: + return false; } bool VMRam::Deserialize(int8_t fd) { - uint8_t buf[5]; - if (g_filemanager->read(fd, buf, 5) != 5) - return false; - - if (buf[0] != RAMMAGIC) - return false; - - uint32_t size = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4]; - - if (size != sizeof(preallocatedRam)) - return false; + deserializeMagic(RAMMAGIC); + uint32_t size; + deserialize32(size); if (g_filemanager->read(fd, preallocatedRam, size) != size) - return false; + goto err; - if (g_filemanager->read(fd, buf, 1) != 1) - return false; - if (buf[0] != RAMMAGIC) - return false; + deserializeMagic(RAMMAGIC); return true; + + err: + return false; } bool VMRam::Test()