mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-12-01 14:50:54 +00:00
fix suspend/resume
This commit is contained in:
parent
c6f39f9b39
commit
4cded72e12
@ -12,10 +12,13 @@
|
|||||||
#include "physicalspeaker.h"
|
#include "physicalspeaker.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
|
#include "serialize.h"
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
#include "teensy-clock.h"
|
#include "teensy-clock.h"
|
||||||
|
#include "iocompat.h"
|
||||||
#else
|
#else
|
||||||
#include "nix-clock.h"
|
#include "nix-clock.h"
|
||||||
#endif
|
#endif
|
||||||
@ -155,24 +158,23 @@ AppleMMU::~AppleMMU()
|
|||||||
|
|
||||||
bool AppleMMU::Serialize(int8_t fd)
|
bool AppleMMU::Serialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint8_t buf[13] = { MMUMAGIC,
|
serializeMagic(MMUMAGIC);
|
||||||
(uint8_t)((switches >> 8) & 0xFF),
|
serialize16(switches);
|
||||||
(uint8_t)((switches ) & 0xFF),
|
serialize8(auxRamRead ? 1 : 0);
|
||||||
auxRamRead ? 1 : 0,
|
serialize8(auxRamWrite ? 1 : 0);
|
||||||
auxRamWrite ? 1 : 0,
|
serialize8(bank2 ? 1 : 0);
|
||||||
bank2 ? 1 : 0,
|
serialize8(readbsr ? 1 : 0);
|
||||||
readbsr ? 1 : 0,
|
serialize8(writebsr ? 1 : 0);
|
||||||
writebsr ? 1 : 0,
|
serialize8(altzp ? 1 : 0);
|
||||||
altzp ? 1 : 0,
|
serialize8(intcxrom ? 1 : 0);
|
||||||
intcxrom ? 1 : 0,
|
serialize8(slot3rom ? 1 : 0);
|
||||||
slot3rom ? 1 : 0,
|
serialize8(slotLatch);
|
||||||
slotLatch,
|
serialize8(preWriteFlag ? 1 : 0);
|
||||||
preWriteFlag ? 1 : 0 };
|
|
||||||
if (g_filemanager->write(fd, buf, 13) != 13)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!g_ram.Serialize(fd))
|
if (!g_ram.Serialize(fd)) {
|
||||||
return false;
|
printf("Failed to serialize RAM\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
// readPages & writePages don't need suspending, but we will need to
|
// readPages & writePages don't need suspending, but we will need to
|
||||||
// recalculate after resume
|
// recalculate after resume
|
||||||
@ -180,47 +182,42 @@ bool AppleMMU::Serialize(int8_t fd)
|
|||||||
// Not suspending/resuming slots b/c they're a fixed configuration
|
// Not suspending/resuming slots b/c they're a fixed configuration
|
||||||
// in this project. Should probably checksum them though. FIXME.
|
// in this project. Should probably checksum them though. FIXME.
|
||||||
|
|
||||||
if (g_filemanager->write(fd, buf, 1) != 1)
|
serializeMagic(MMUMAGIC);
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppleMMU::Deserialize(int8_t fd)
|
bool AppleMMU::Deserialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint8_t buf[13];
|
deserializeMagic(MMUMAGIC);
|
||||||
|
|
||||||
if (g_filemanager->read(fd, buf, 13) != 13)
|
deserialize16(switches);
|
||||||
return false;
|
serialize8(auxRamRead);
|
||||||
|
serialize8(auxRamWrite);
|
||||||
if (buf[0] != MMUMAGIC)
|
serialize8(bank2);
|
||||||
return false;
|
serialize8(readbsr);
|
||||||
|
serialize8(writebsr);
|
||||||
switches = (buf[1] << 8) | buf[2];
|
serialize8(altzp);
|
||||||
auxRamRead = buf[3];
|
serialize8(intcxrom);
|
||||||
auxRamWrite = buf[4];
|
serialize8(slot3rom);
|
||||||
bank2 = buf[5];
|
serialize8(slotLatch);
|
||||||
readbsr = buf[6];
|
serialize8(preWriteFlag);
|
||||||
writebsr = buf[7];
|
|
||||||
altzp = buf[8];
|
|
||||||
intcxrom = buf[9];
|
|
||||||
slot3rom = buf[10];
|
|
||||||
slotLatch = buf[11];
|
|
||||||
preWriteFlag = buf[12];
|
|
||||||
|
|
||||||
if (!g_ram.Deserialize(fd)) {
|
if (!g_ram.Deserialize(fd)) {
|
||||||
return false;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_filemanager->read(fd, buf, 1) != 1)
|
deserializeMagic(MMUMAGIC);
|
||||||
return false;
|
|
||||||
if (buf[0] != MMUMAGIC)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Reset readPages[] and writePages[] and the display
|
// Reset readPages[] and writePages[] and the display
|
||||||
resetDisplay();
|
resetDisplay();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppleMMU::Reset()
|
void AppleMMU::Reset()
|
||||||
|
@ -6,10 +6,13 @@
|
|||||||
#include "applekeyboard.h"
|
#include "applekeyboard.h"
|
||||||
#include "physicalkeyboard.h"
|
#include "physicalkeyboard.h"
|
||||||
|
|
||||||
|
#include "serialize.h"
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
#include "teensy-println.h"
|
#include "teensy-println.h"
|
||||||
|
#include "iocompat.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -40,83 +43,75 @@ AppleVM::~AppleVM()
|
|||||||
delete parallel;
|
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
|
/* Open a new suspend file via the file manager; tell all our
|
||||||
objects to serialize in to it; close the file */
|
objects to serialize in to it; close the file */
|
||||||
|
|
||||||
int8_t fh = g_filemanager->openFile(fn);
|
int8_t fd = g_filemanager->openFile(fn);
|
||||||
if (fh == -1) {
|
if (fd == -1) {
|
||||||
// Unable to open; skip suspend
|
// Unable to open; skip suspend
|
||||||
return;
|
printf("failed to open suspend file\n");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
if (g_filemanager->write(fh, suspendHdr, strlen(suspendHdr)) != strlen(suspendHdr))
|
serializeString(suspendHdr);
|
||||||
return;
|
|
||||||
|
|
||||||
/* Tell all of the peripherals to suspend */
|
/* Tell all of the peripherals to suspend */
|
||||||
if (g_cpu->Serialize(fh) &&
|
if (g_cpu->Serialize(fd) &&
|
||||||
disk6->Serialize(fh) &&
|
disk6->Serialize(fd) &&
|
||||||
hd32->Serialize(fh)
|
hd32->Serialize(fd)
|
||||||
) {
|
) {
|
||||||
#ifdef TEENSYDUINO
|
|
||||||
println("All serialized successfully");
|
|
||||||
#else
|
|
||||||
printf("All serialized successfully\n");
|
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
|
/* Open the given suspend file via the file manager; tell all our
|
||||||
objects to deserialize from it; close the file */
|
objects to deserialize from it; close the file */
|
||||||
|
|
||||||
int8_t fh = g_filemanager->openFile(fn);
|
int8_t fd = g_filemanager->openFile(fn);
|
||||||
if (fh == -1) {
|
if (fd == -1) {
|
||||||
// Unable to open; skip resume
|
// Unable to open; skip resume
|
||||||
#ifdef TEENSYDUINO
|
printf("Unable to open resume file '%s'\n", fn);
|
||||||
print("Unable to open resume file ");
|
goto err;
|
||||||
println(fn);
|
|
||||||
#else
|
|
||||||
printf("Unable to open resume file\n");
|
|
||||||
#endif
|
|
||||||
g_filemanager->closeFile(fh);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
uint8_t c;
|
deserializeString(debugBuf);
|
||||||
for (int i=0; i<strlen(suspendHdr); i++) {
|
if (strcmp(debugBuf, suspendHdr)) {
|
||||||
if (g_filemanager->read(fh, &c, 1) != 1 ||
|
printf("Bad file header while resuming\n");
|
||||||
c != suspendHdr[i]) {
|
goto err;
|
||||||
/* Failed to read correct header; abort */
|
|
||||||
g_filemanager->closeFile(fh);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tell all of the peripherals to resume */
|
/* Tell all of the peripherals to resume */
|
||||||
if (g_cpu->Deserialize(fh) &&
|
if (g_cpu->Deserialize(fd) &&
|
||||||
disk6->Deserialize(fh) &&
|
disk6->Deserialize(fd) &&
|
||||||
hd32->Deserialize(fh)
|
hd32->Deserialize(fd)
|
||||||
) {
|
) {
|
||||||
#ifdef TEENSYDUINO
|
|
||||||
println("Deserialization successful");
|
|
||||||
#else
|
|
||||||
printf("All deserialized successfully\n");
|
printf("All deserialized successfully\n");
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
#ifndef TEENSYDUINO
|
|
||||||
printf("Deserialization failed\n");
|
printf("Deserialization failed\n");
|
||||||
|
#ifndef TEENSYDUINO
|
||||||
exit(1);
|
exit(1);
|
||||||
#endif
|
#endif
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_filemanager->closeFile(fh);
|
g_filemanager->closeFile(fd);
|
||||||
|
return true;
|
||||||
|
err:
|
||||||
|
g_filemanager->closeFile(fd);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixme: make member vars
|
// fixme: make member vars
|
||||||
|
@ -14,8 +14,8 @@ class AppleVM : public VM {
|
|||||||
AppleVM();
|
AppleVM();
|
||||||
virtual ~AppleVM();
|
virtual ~AppleVM();
|
||||||
|
|
||||||
void Suspend(const char *fn);
|
bool Suspend(const char *fn);
|
||||||
void Resume(const char *fn);
|
bool Resume(const char *fn);
|
||||||
|
|
||||||
void cpuMaintenance(int64_t cycles);
|
void cpuMaintenance(int64_t cycles);
|
||||||
|
|
||||||
|
177
apple/diskii.cpp
177
apple/diskii.cpp
@ -3,6 +3,7 @@
|
|||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "teensy-println.h"
|
#include "teensy-println.h"
|
||||||
|
#include "iocompat.h"
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -16,6 +17,8 @@
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "appleui.h"
|
#include "appleui.h"
|
||||||
|
|
||||||
|
#include "serialize.h"
|
||||||
|
|
||||||
#include "diskii-rom.h"
|
#include "diskii-rom.h"
|
||||||
|
|
||||||
#define DISKIIMAGIC 0xAA
|
#define DISKIIMAGIC 0xAA
|
||||||
@ -57,171 +60,101 @@ DiskII::~DiskII()
|
|||||||
|
|
||||||
bool DiskII::Serialize(int8_t fd)
|
bool DiskII::Serialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint8_t buf[27] = { DISKIIMAGIC,
|
serializeMagic(DISKIIMAGIC);
|
||||||
readWriteLatch,
|
serialize8(readWriteLatch);
|
||||||
sequencer,
|
serialize8(sequencer);
|
||||||
dataRegister,
|
serialize8(dataRegister);
|
||||||
writeMode,
|
serialize8(writeMode);
|
||||||
writeProt,
|
serialize8(writeProt);
|
||||||
selectedDisk };
|
serialize8(selectedDisk);
|
||||||
|
|
||||||
if (g_filemanager->write(fd, buf, 7) != 7) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
uint8_t ptr = 0;
|
serialize8(curHalfTrack[i]);
|
||||||
buf[ptr++] = curHalfTrack[i];
|
serialize8(curWozTrack[i]);
|
||||||
buf[ptr++] = curWozTrack[i];
|
serialize8(curPhase[i]);
|
||||||
buf[ptr++] = curPhase[i];
|
serialize64(driveSpinupCycles[i]);
|
||||||
buf[ptr++] = ((driveSpinupCycles[i] >> 56) & 0xFF);
|
serialize64(deliveredDiskBits[i]);
|
||||||
buf[ptr++] = ((driveSpinupCycles[i] >> 48) & 0xFF);
|
serialize64(diskIsSpinningUntil[i]);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disk[i]) {
|
if (disk[i]) {
|
||||||
// Make sure we have flushed the disk images
|
// Make sure we have flushed the disk images
|
||||||
disk[i]->flush();
|
disk[i]->flush();
|
||||||
flushAt[i] = 0; // and there's no need to re-flush them now
|
flushAt[i] = 0; // and there's no need to re-flush them now
|
||||||
|
|
||||||
buf[0] = 1;
|
serialize8(1);
|
||||||
if (g_filemanager->write(fd, buf, 1) != 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// FIXME: this ONLY works for builds using the filemanager to read
|
// 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!
|
// the disk image, so it's broken until we port Woz to do that!
|
||||||
const char *fn = disk[i]->diskName();
|
const char *fn = disk[i]->diskName();
|
||||||
if (g_filemanager->write(fd, fn, strlen(fn)+1) != strlen(fn)+1) // include null terminator
|
serializeString(fn);
|
||||||
return false;
|
|
||||||
if (!disk[i]->Serialize(fd))
|
if (!disk[i]->Serialize(fd))
|
||||||
return false;
|
goto err;
|
||||||
} else {
|
} else {
|
||||||
buf[0] = 0;
|
serialize8(0);
|
||||||
if (g_filemanager->write(fd, buf, 0) != 1)
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[0] = DISKIIMAGIC;
|
serializeMagic(DISKIIMAGIC);
|
||||||
if (g_filemanager->write(fd, buf, 1) != 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DiskII::Deserialize(int8_t fd)
|
bool DiskII::Deserialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint8_t buf[MAXPATH];
|
deserializeMagic(DISKIIMAGIC);
|
||||||
if (g_filemanager->read(fd, buf, 7) != 7)
|
|
||||||
return false;
|
|
||||||
if (buf[0] != DISKIIMAGIC)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
readWriteLatch = buf[1];
|
deserialize8(readWriteLatch);
|
||||||
sequencer = buf[2];
|
deserialize8(sequencer);
|
||||||
dataRegister = buf[3];
|
deserialize8(dataRegister);
|
||||||
writeMode = buf[4];
|
deserialize8(writeMode);
|
||||||
writeProt = buf[5];
|
deserialize8(writeProt);
|
||||||
selectedDisk = buf[6];
|
deserialize8(selectedDisk);
|
||||||
|
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
uint8_t ptr = 0;
|
deserialize8(curHalfTrack[i]);
|
||||||
if (g_filemanager->read(fd, buf, 27) != 27)
|
deserialize8(curWozTrack[i]);
|
||||||
return false;
|
deserialize8(curPhase[i]);
|
||||||
|
|
||||||
curHalfTrack[i] = buf[ptr++];
|
deserialize64(driveSpinupCycles[i]);
|
||||||
curWozTrack[i] = buf[ptr++];
|
deserialize64(deliveredDiskBits[i]);
|
||||||
curPhase[i] = buf[ptr++];
|
deserialize64(diskIsSpinningUntil[i]);
|
||||||
|
|
||||||
driveSpinupCycles[i] = buf[ptr++];
|
uint8_t hasDisk;
|
||||||
driveSpinupCycles[i] <<= 8; driveSpinupCycles[i] |= buf[ptr++];
|
deserialize8(hasDisk);
|
||||||
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++];
|
if (disk[i]) delete disk[i];
|
||||||
deliveredDiskBits[i] <<= 8; deliveredDiskBits[i] |= buf[ptr++];
|
if (hasDisk) {
|
||||||
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++];
|
|
||||||
|
|
||||||
if (disk[i])
|
|
||||||
delete disk[i];
|
|
||||||
if (g_filemanager->read(fd, buf, 1) != 1)
|
|
||||||
return false;
|
|
||||||
if (buf[0]) {
|
|
||||||
disk[i] = new WozSerializer();
|
disk[i] = new WozSerializer();
|
||||||
|
|
||||||
ptr = 0;
|
|
||||||
// FIXME: MAXPATH check!
|
// FIXME: MAXPATH check!
|
||||||
while (1) {
|
char fn[MAXPATH];
|
||||||
if (g_filemanager->read(fd, &buf[ptr++], 1) != 1)
|
deserializeString(fn);
|
||||||
return false;
|
if (fn[0]) {
|
||||||
if (buf[ptr-1] == 0)
|
printf("Restoring disk image named '%s'\n", fn);
|
||||||
break;
|
disk[i]->readFile((char *)fn, false, T_AUTO); // FIXME error checking
|
||||||
}
|
|
||||||
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
|
|
||||||
} else {
|
} else {
|
||||||
// ERROR: there's a disk but we don't have the path to its image?
|
// 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))
|
if (!disk[i]->Deserialize(fd)) {
|
||||||
return false;
|
printf("Failed to deserialize disk %d\n", i);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
disk[i] = NULL;
|
disk[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_filemanager->read(fd, buf, 1) != 1)
|
deserializeMagic(DISKIIMAGIC);
|
||||||
return false;
|
|
||||||
if (buf[0] != DISKIIMAGIC)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiskII::Reset()
|
void DiskII::Reset()
|
||||||
|
101
apple/hd32.cpp
101
apple/hd32.cpp
@ -12,6 +12,7 @@
|
|||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "teensy-println.h"
|
#include "teensy-println.h"
|
||||||
|
#include "iocompat.h"
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -23,6 +24,8 @@
|
|||||||
|
|
||||||
#include "applemmu.h" // for FLOATING
|
#include "applemmu.h" // for FLOATING
|
||||||
|
|
||||||
|
#include "serialize.h"
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
#include "hd32-rom.h"
|
#include "hd32-rom.h"
|
||||||
@ -66,92 +69,58 @@ HD32::~HD32()
|
|||||||
|
|
||||||
bool HD32::Serialize(int8_t fd)
|
bool HD32::Serialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint8_t buf[19] = { HD32MAGIC,
|
serializeMagic(HD32MAGIC);
|
||||||
driveSelected,
|
serialize8(driveSelected);
|
||||||
unitSelected,
|
serialize8(unitSelected);
|
||||||
command,
|
serialize8(command);
|
||||||
enabled,
|
serialize8(enabled);
|
||||||
errorState[0],
|
serialize8(errorState[0]);
|
||||||
errorState[1],
|
serialize8(errorState[1]);
|
||||||
(uint8_t)((memBlock[0] >> 8) & 0xFF),
|
serialize16(memBlock[0]);
|
||||||
(uint8_t)((memBlock[0] ) & 0xFF),
|
serialize16(memBlock[1]);
|
||||||
(uint8_t)((memBlock[1] >> 8) & 0xFF),
|
serialize32(cursor[0]);
|
||||||
(uint8_t)((memBlock[1] ) & 0xFF),
|
serialize32(cursor[1]);
|
||||||
(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;
|
|
||||||
|
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
const char *fn = diskName(i);
|
const char *fn = diskName(i);
|
||||||
if (g_filemanager->write(fd, fn, strlen(fn)+1) != strlen(fn)+1) {
|
serializeString(fn);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
serializeMagic(HD32MAGIC);
|
||||||
|
return true;
|
||||||
|
|
||||||
buf[0] = HD32MAGIC;
|
err:
|
||||||
return (g_filemanager->write(fd, buf, 1) == 1);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HD32::Deserialize(int8_t fd)
|
bool HD32::Deserialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint8_t buf[255];
|
deserializeMagic(HD32MAGIC);
|
||||||
if (g_filemanager->read(fd, buf, 19) != 19) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (buf[0] != HD32MAGIC)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
driveSelected = buf[1];
|
deserialize8(driveSelected);
|
||||||
unitSelected = buf[2];
|
deserialize8(unitSelected);
|
||||||
command = buf[3];
|
deserialize8(command);
|
||||||
enabled = buf[4];
|
deserialize8(enabled);
|
||||||
errorState[0] = buf[5];
|
deserialize8(errorState[0]);
|
||||||
errorState[1] = buf[6];
|
deserialize8(errorState[1]);
|
||||||
memBlock[0] = buf[7];
|
deserialize16(memBlock[0]);
|
||||||
memBlock[0] <<= 8; memBlock[0] |= buf[8];
|
deserialize16(memBlock[1]);
|
||||||
memBlock[1] = buf[9];
|
deserialize32(cursor[0]);
|
||||||
memBlock[1] <<= 8; memBlock[1] |= buf[10];
|
deserialize32(cursor[1]);
|
||||||
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];
|
|
||||||
|
|
||||||
cachedBlockNum = -1; // just invalidate the cache; it will reload...
|
cachedBlockNum = -1; // just invalidate the cache; it will reload...
|
||||||
|
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
uint32_t ptr = 0;
|
char buf[MAXPATH];
|
||||||
// FIXME: MAXPATH check!
|
deserializeString(buf);
|
||||||
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
|
// FIXME: this tromps on error and some other vars ... that we just restored
|
||||||
insertDisk(i, (char *)buf);
|
insertDisk(i, (char *)buf);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (g_filemanager->read(fd, buf, 1) != 1)
|
deserializeMagic(HD32MAGIC);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (buf[0] != HD32MAGIC)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HD32::Reset()
|
void HD32::Reset()
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
#include "woz-serializer.h"
|
#include "woz-serializer.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
|
#include "serialize.h"
|
||||||
|
|
||||||
|
#ifdef TEENSYDUINO
|
||||||
|
#include "iocompat.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define WOZMAGIC 0xD5
|
#define WOZMAGIC 0xD5
|
||||||
|
|
||||||
WozSerializer::WozSerializer() : Woz(0,0)
|
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
|
// If we're being asked to serialize, make sure we've flushed any data first
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
uint8_t buf[17] = { WOZMAGIC,
|
serializeMagic(WOZMAGIC);
|
||||||
(trackPointer >> 24) & 0xFF,
|
serialize32(trackPointer);
|
||||||
(trackPointer >> 16) & 0xFF,
|
serialize32(trackBitCounter);
|
||||||
(trackPointer >> 8) & 0xFF,
|
serialize32(lastReadPointer);
|
||||||
(trackPointer ) & 0xFF,
|
serialize8(trackByte);
|
||||||
(trackBitCounter >> 24) & 0xFF,
|
serialize8(trackBitIdx);
|
||||||
(trackBitCounter >> 16) & 0xFF,
|
serialize8(trackLoopCounter);
|
||||||
(trackBitCounter >> 8) & 0xFF,
|
serializeMagic(WOZMAGIC);
|
||||||
(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;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WozSerializer::Deserialize(int8_t fd)
|
bool WozSerializer::Deserialize(int8_t fd)
|
||||||
{
|
{
|
||||||
// Before deserializing, the caller has to re-load the right disk image!
|
// Before deserializing, the caller has to re-load the right disk image!
|
||||||
uint8_t buf[17];
|
deserializeMagic(WOZMAGIC);
|
||||||
if (g_filemanager->read(fd, buf, 17) != 17)
|
deserialize32(trackPointer);
|
||||||
return false;
|
deserialize32(trackBitCounter);
|
||||||
|
deserialize32(lastReadPointer);
|
||||||
if (buf[0] != WOZMAGIC)
|
deserialize8(trackByte);
|
||||||
return false;
|
deserialize8(trackBitIdx);
|
||||||
|
deserialize8(trackLoopCounter);
|
||||||
trackPointer = buf[1];
|
deserializeMagic(WOZMAGIC);
|
||||||
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;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
85
cpu.cpp
85
cpu.cpp
@ -7,10 +7,13 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
|
|
||||||
|
#include "serialize.h"
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
#include "teensy-println.h"
|
#include "teensy-println.h"
|
||||||
|
#include "iocompat.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// define DEBUGSTEPS to show disassembly of each instruction as it's processed
|
// define DEBUGSTEPS to show disassembly of each instruction as it's processed
|
||||||
@ -320,74 +323,54 @@ Cpu::~Cpu()
|
|||||||
mmu = NULL;
|
mmu = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cpu::Serialize(int8_t fh)
|
bool Cpu::Serialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint8_t buf[13] = { CPUMAGIC,
|
serializeMagic(CPUMAGIC);
|
||||||
(uint8_t)((pc >> 8) & 0xFF),
|
serialize16(pc);
|
||||||
(uint8_t)((pc ) & 0xFF),
|
serialize8(sp);
|
||||||
sp,
|
serialize8(a);
|
||||||
a,
|
serialize8(x);
|
||||||
x,
|
serialize8(y);
|
||||||
y,
|
serialize8(flags);
|
||||||
flags,
|
serialize32(cycles);
|
||||||
(uint8_t)((cycles >> 24) & 0xFF),
|
serialize8(irqPending ? 1 : 0);
|
||||||
(uint8_t)((cycles >> 16) & 0xFF),
|
|
||||||
(uint8_t)((cycles >> 8) & 0xFF),
|
|
||||||
(uint8_t)((cycles ) & 0xFF),
|
|
||||||
irqPending ? (uint8_t)1 : (uint8_t)0 };
|
|
||||||
|
|
||||||
if (g_filemanager->write(fh, buf, 13) != 13)
|
if (!mmu->Serialize(fd)) {
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!mmu->Serialize(fh)) {
|
|
||||||
#ifndef TEENSYDUINO
|
|
||||||
printf("MMU serialization failed\n");
|
printf("MMU serialization failed\n");
|
||||||
#else
|
goto err;
|
||||||
println("MMU serialization failed");
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
serializeMagic(CPUMAGIC);
|
||||||
if (g_filemanager->write(fh, buf, 1) != 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cpu::Deserialize(int8_t fh)
|
bool Cpu::Deserialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint8_t buf[13];
|
deserializeMagic(CPUMAGIC);
|
||||||
if (g_filemanager->read(fh, buf, 13) != 13)
|
deserialize16(pc);
|
||||||
return false;
|
deserialize8(sp);
|
||||||
if (buf[0] != CPUMAGIC)
|
deserialize8(a);
|
||||||
return false;
|
deserialize8(x);
|
||||||
pc = (buf[1] << 8) | buf[2];
|
deserialize8(y);
|
||||||
sp = buf[3];
|
deserialize8(flags);
|
||||||
a = buf[4];
|
deserialize32(cycles);
|
||||||
x = buf[5];
|
deserialize8(irqPending);
|
||||||
y = buf[6];
|
|
||||||
flags = buf[7];
|
|
||||||
|
|
||||||
cycles = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
|
if (!mmu->Deserialize(fd)) {
|
||||||
|
|
||||||
irqPending = buf[12];
|
|
||||||
|
|
||||||
if (!mmu->Deserialize(fh)) {
|
|
||||||
#ifndef TEENSYDUINO
|
|
||||||
printf("MMU deserialization failed\n");
|
printf("MMU deserialization failed\n");
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_filemanager->read(fh, buf, 1) != 1)
|
deserializeMagic(CPUMAGIC);
|
||||||
return false;
|
|
||||||
if (buf[0] != CPUMAGIC)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
#ifndef TEENSYDUINO
|
|
||||||
printf("CPU deserialization complete\n");
|
printf("CPU deserialization complete\n");
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::Reset()
|
void Cpu::Reset()
|
||||||
|
@ -19,3 +19,7 @@ bool g_invertPaddleX = false;
|
|||||||
bool g_invertPaddleY = false;
|
bool g_invertPaddleY = false;
|
||||||
|
|
||||||
char debugBuf[255];
|
char debugBuf[255];
|
||||||
|
|
||||||
|
#ifdef TEENSYDUINO
|
||||||
|
char fsbuf[200];
|
||||||
|
#endif
|
||||||
|
@ -56,4 +56,8 @@ extern bool g_invertPaddleY;
|
|||||||
|
|
||||||
extern char debugBuf[255];
|
extern char debugBuf[255];
|
||||||
|
|
||||||
|
#ifdef TEENSYDUINO
|
||||||
|
extern char fsbuf[200];
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -194,33 +194,43 @@ void NixFileManager::seekToEnd(int8_t fd)
|
|||||||
|
|
||||||
int NixFileManager::write(int8_t fd, const void *buf, int nbyte)
|
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;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (cachedNames[fd][0] == 0)
|
if (cachedNames[fd][0] == 0) {
|
||||||
|
printf("invalid fd (not opened)\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t pos = fileSeekPositions[fd];
|
uint32_t pos = fileSeekPositions[fd];
|
||||||
|
|
||||||
// open, seek, write, close.
|
// open, seek, write, close.
|
||||||
bool ret = false;
|
ssize_t rv = 0;
|
||||||
int ffd = ::open(cachedNames[fd], O_WRONLY|O_CREAT, 0644);
|
int ffd = ::open(cachedNames[fd], O_WRONLY|O_CREAT, 0644);
|
||||||
if (ffd != -1) {
|
if (ffd == -1) {
|
||||||
if (::lseek(ffd, pos, SEEK_SET) == -1) {
|
printf("Failed to open '%s' for writing: %d\n",
|
||||||
|
cachedNames[fd], errno);
|
||||||
close(ffd);
|
close(ffd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ssize_t rv = ::write(ffd, buf, nbyte);
|
|
||||||
if (rv != nbyte) {
|
if (::lseek(ffd, pos, SEEK_SET) == -1) {
|
||||||
printf("error writing: %d; wanted to write %d got %d\n", errno, nbyte, ret);
|
printf("failed to open and seek\n");
|
||||||
}
|
|
||||||
close(ffd);
|
close(ffd);
|
||||||
} else {
|
return -1;
|
||||||
printf("Failed to open '%s' for writing: %d\n",
|
|
||||||
cachedNames[fd], errno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
fileSeekPositions[fd]+=nbyte;
|
||||||
return ret;
|
return (int)rv;
|
||||||
};
|
};
|
||||||
|
|
||||||
int NixFileManager::read(int8_t fd, void *buf, int nbyte)
|
int NixFileManager::read(int8_t fd, void *buf, int nbyte)
|
||||||
|
@ -16,8 +16,4 @@
|
|||||||
#define read(filedes,buf,nbyte) g_filemanager->read(filedes,buf,nbyte)
|
#define read(filedes,buf,nbyte) g_filemanager->read(filedes,buf,nbyte)
|
||||||
#define lseek(filedes,offset,whence) g_filemanager->lseek(filedes,offset,whence)
|
#define lseek(filedes,offset,whence) g_filemanager->lseek(filedes,offset,whence)
|
||||||
|
|
||||||
static char fsbuf[200];
|
#include "iocompat.h"
|
||||||
#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();}
|
|
||||||
|
|
||||||
|
12
teensy/iocompat.h
Normal file
12
teensy/iocompat.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef __IOCOMPAT_H
|
||||||
|
#define __IOCOMPAT_H
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#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
|
@ -9,7 +9,7 @@ static SdFat sd;
|
|||||||
static FsFile cacheFile;
|
static FsFile cacheFile;
|
||||||
static FsFile outerDir;
|
static FsFile outerDir;
|
||||||
|
|
||||||
|
#include "iocompat.h"
|
||||||
|
|
||||||
TeensyFileManager::TeensyFileManager()
|
TeensyFileManager::TeensyFileManager()
|
||||||
{
|
{
|
||||||
@ -179,14 +179,15 @@ bool TeensyFileManager::_prepCache(int8_t fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open the new one
|
// Open the new one
|
||||||
cacheFile.open(cachedNames[fd], O_RDWR);
|
cacheFile.open(cachedNames[fd], O_CREAT|O_RDWR);
|
||||||
if (!cacheFile) {
|
if (!cacheFile) {
|
||||||
|
printf("failed to open cacheFile\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cacheFd = fd; // cache is live
|
cacheFd = fd; // cache is live
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; // FIXME error handling
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TeensyFileManager::getRootPath(char *toWhere, int8_t maxLen)
|
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.
|
// open, seek, write, close.
|
||||||
if (fd < 0 || fd >= numCached) {
|
if (fd < 0 || fd >= numCached) {
|
||||||
|
printf("no fd\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedNames[fd][0] == 0) {
|
if (cachedNames[fd][0] == 0) {
|
||||||
|
printf("no name\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,15 +240,16 @@ int TeensyFileManager::write(int8_t fd, const void *buf, int nbyte)
|
|||||||
uint32_t pos = fileSeekPositions[fd];
|
uint32_t pos = fileSeekPositions[fd];
|
||||||
|
|
||||||
if (!cacheFile.seek(pos)) {
|
if (!cacheFile.seek(pos)) {
|
||||||
|
printf("can't seek to %d\n", pos);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacheFile.write((const uint8_t *)buf, (size_t)nbyte) != (size_t)nbyte) {
|
if (cacheFile.write((const uint8_t *)buf, (size_t)nbyte) != (size_t)nbyte) {
|
||||||
|
printf("can't write\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileSeekPositions[fd] += nbyte;
|
fileSeekPositions[fd] += nbyte;
|
||||||
cacheFile.close();
|
|
||||||
return nbyte;
|
return nbyte;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -266,6 +270,7 @@ int TeensyFileManager::read(int8_t fd, void *buf, int nbyte)
|
|||||||
if (!cacheFile.seek(pos)) {
|
if (!cacheFile.seek(pos)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileSeekPositions[fd] += nbyte;
|
fileSeekPositions[fd] += nbyte;
|
||||||
|
|
||||||
if (cacheFile.read(buf, nbyte) != nbyte) {
|
if (cacheFile.read(buf, nbyte) != nbyte) {
|
||||||
|
4
vm.h
4
vm.h
@ -16,8 +16,8 @@ class VM {
|
|||||||
VM() { mmu=NULL; vmdisplay = NULL; hasIRQ = false;}
|
VM() { mmu=NULL; vmdisplay = NULL; hasIRQ = false;}
|
||||||
virtual ~VM() { if (mmu) delete mmu; if (vmdisplay) delete vmdisplay; }
|
virtual ~VM() { if (mmu) delete mmu; if (vmdisplay) delete vmdisplay; }
|
||||||
|
|
||||||
virtual void Suspend(const char *fn) = 0;
|
virtual bool Suspend(const char *fn) = 0;
|
||||||
virtual void Resume(const char *fn) = 0;
|
virtual bool Resume(const char *fn) = 0;
|
||||||
|
|
||||||
virtual void SetMMU(MMU *mmu) { this->mmu = mmu; }
|
virtual void SetMMU(MMU *mmu) { this->mmu = mmu; }
|
||||||
virtual MMU *getMMU() { return mmu; }
|
virtual MMU *getMMU() { return mmu; }
|
||||||
|
44
vmram.cpp
44
vmram.cpp
@ -5,11 +5,14 @@
|
|||||||
|
|
||||||
#include "vmram.h"
|
#include "vmram.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "serialize.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
|
#include "iocompat.h"
|
||||||
EXTMEM uint8_t preallocatedRam[591*256];
|
EXTMEM uint8_t preallocatedRam[591*256];
|
||||||
#else
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
uint8_t preallocatedRam[591*256];
|
uint8_t preallocatedRam[591*256];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -47,46 +50,35 @@ void VMRam::writeByte(uint32_t addr, uint8_t value)
|
|||||||
bool VMRam::Serialize(int8_t fd)
|
bool VMRam::Serialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint32_t size = sizeof(preallocatedRam);
|
uint32_t size = sizeof(preallocatedRam);
|
||||||
uint8_t buf[5] = { RAMMAGIC,
|
serializeMagic(RAMMAGIC);
|
||||||
(uint8_t)((size >> 24) & 0xFF),
|
serialize32(size);
|
||||||
(uint8_t)((size >> 16) & 0xFF),
|
|
||||||
(uint8_t)((size >> 8) & 0xFF),
|
|
||||||
(uint8_t)((size ) & 0xFF) };
|
|
||||||
if (g_filemanager->write(fd, buf, 5) != 5)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (g_filemanager->write(fd, preallocatedRam, sizeof(preallocatedRam)) != sizeof(preallocatedRam))
|
if (g_filemanager->write(fd, preallocatedRam, sizeof(preallocatedRam)) != sizeof(preallocatedRam))
|
||||||
return false;
|
goto err;
|
||||||
|
|
||||||
if (g_filemanager->write(fd, buf, 1) != 1)
|
serializeMagic(RAMMAGIC);
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VMRam::Deserialize(int8_t fd)
|
bool VMRam::Deserialize(int8_t fd)
|
||||||
{
|
{
|
||||||
uint8_t buf[5];
|
deserializeMagic(RAMMAGIC);
|
||||||
if (g_filemanager->read(fd, buf, 5) != 5)
|
uint32_t size;
|
||||||
return false;
|
deserialize32(size);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (g_filemanager->read(fd, preallocatedRam, size) != size)
|
if (g_filemanager->read(fd, preallocatedRam, size) != size)
|
||||||
return false;
|
goto err;
|
||||||
|
|
||||||
if (g_filemanager->read(fd, buf, 1) != 1)
|
deserializeMagic(RAMMAGIC);
|
||||||
return false;
|
|
||||||
if (buf[0] != RAMMAGIC)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VMRam::Test()
|
bool VMRam::Test()
|
||||||
|
Loading…
Reference in New Issue
Block a user