2017-02-19 23:55:54 +00:00
|
|
|
#include "applevm.h"
|
|
|
|
#include "filemanager.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
|
|
|
|
#include "appledisplay.h"
|
|
|
|
#include "applekeyboard.h"
|
|
|
|
#include "physicalkeyboard.h"
|
|
|
|
|
2021-01-10 02:32:40 +00:00
|
|
|
#include "serialize.h"
|
|
|
|
|
2017-02-19 23:55:54 +00:00
|
|
|
#include "globals.h"
|
|
|
|
|
2020-07-04 11:41:32 +00:00
|
|
|
#ifdef TEENSYDUINO
|
|
|
|
#include "teensy-println.h"
|
2021-01-10 02:32:40 +00:00
|
|
|
#include "iocompat.h"
|
2020-07-04 11:41:32 +00:00
|
|
|
#endif
|
|
|
|
|
2017-12-30 20:20:34 +00:00
|
|
|
#include <errno.h>
|
2020-06-28 19:24:49 +00:00
|
|
|
const char *suspendHdr = "Sus2";
|
2017-12-30 20:20:34 +00:00
|
|
|
|
2017-02-19 23:55:54 +00:00
|
|
|
AppleVM::AppleVM()
|
|
|
|
{
|
|
|
|
// FIXME: all this typecasting makes me knife-stabby
|
2018-02-18 01:44:04 +00:00
|
|
|
vmdisplay = new AppleDisplay();
|
2017-02-19 23:55:54 +00:00
|
|
|
mmu = new AppleMMU((AppleDisplay *)vmdisplay);
|
|
|
|
vmdisplay->SetMMU((AppleMMU *)mmu);
|
|
|
|
|
|
|
|
disk6 = new DiskII((AppleMMU *)mmu);
|
|
|
|
((AppleMMU *)mmu)->setSlot(6, disk6);
|
|
|
|
|
|
|
|
keyboard = new AppleKeyboard((AppleMMU *)mmu);
|
2017-02-20 23:41:46 +00:00
|
|
|
|
|
|
|
parallel = new ParallelCard();
|
|
|
|
((AppleMMU *)mmu)->setSlot(1, parallel);
|
|
|
|
|
2017-12-29 19:08:49 +00:00
|
|
|
hd32 = new HD32((AppleMMU *)mmu);
|
|
|
|
((AppleMMU *)mmu)->setSlot(7, hd32);
|
2020-12-29 14:12:33 +00:00
|
|
|
|
|
|
|
mouse = new Mouse();
|
|
|
|
((AppleMMU *)mmu)->setSlot(4, mouse);
|
2017-02-19 23:55:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
AppleVM::~AppleVM()
|
|
|
|
{
|
|
|
|
delete disk6;
|
2017-02-24 15:15:17 +00:00
|
|
|
delete parallel;
|
2017-02-19 23:55:54 +00:00
|
|
|
}
|
|
|
|
|
2021-01-10 02:32:40 +00:00
|
|
|
bool AppleVM::Suspend(const char *fn)
|
2017-12-30 20:20:34 +00:00
|
|
|
{
|
|
|
|
/* Open a new suspend file via the file manager; tell all our
|
|
|
|
objects to serialize in to it; close the file */
|
|
|
|
|
2021-01-10 02:32:40 +00:00
|
|
|
int8_t fd = g_filemanager->openFile(fn);
|
|
|
|
if (fd == -1) {
|
2017-12-30 20:20:34 +00:00
|
|
|
// Unable to open; skip suspend
|
2021-01-10 02:32:40 +00:00
|
|
|
printf("failed to open suspend file\n");
|
|
|
|
return false;
|
2017-12-30 20:20:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Header */
|
2021-01-10 02:32:40 +00:00
|
|
|
serializeString(suspendHdr);
|
2017-12-30 20:20:34 +00:00
|
|
|
|
|
|
|
/* Tell all of the peripherals to suspend */
|
2021-01-10 02:32:40 +00:00
|
|
|
if (g_cpu->Serialize(fd) &&
|
|
|
|
disk6->Serialize(fd) &&
|
|
|
|
hd32->Serialize(fd)
|
2017-12-30 20:20:34 +00:00
|
|
|
) {
|
2020-06-28 19:24:49 +00:00
|
|
|
printf("All serialized successfully\n");
|
2017-12-30 20:20:34 +00:00
|
|
|
}
|
|
|
|
|
2021-01-10 02:32:40 +00:00
|
|
|
g_filemanager->closeFile(fd);
|
|
|
|
return true;
|
|
|
|
|
|
|
|
err:
|
|
|
|
g_filemanager->closeFile(fd);
|
|
|
|
return false;
|
2017-12-30 20:20:34 +00:00
|
|
|
}
|
|
|
|
|
2021-01-10 02:32:40 +00:00
|
|
|
bool AppleVM::Resume(const char *fn)
|
2017-12-30 20:20:34 +00:00
|
|
|
{
|
|
|
|
/* Open the given suspend file via the file manager; tell all our
|
|
|
|
objects to deserialize from it; close the file */
|
|
|
|
|
2021-01-10 02:32:40 +00:00
|
|
|
int8_t fd = g_filemanager->openFile(fn);
|
|
|
|
if (fd == -1) {
|
2017-12-30 20:20:34 +00:00
|
|
|
// Unable to open; skip resume
|
2021-01-10 02:32:40 +00:00
|
|
|
printf("Unable to open resume file '%s'\n", fn);
|
|
|
|
goto err;
|
2017-12-30 20:20:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Header */
|
2021-01-10 02:32:40 +00:00
|
|
|
deserializeString(debugBuf);
|
|
|
|
if (strcmp(debugBuf, suspendHdr)) {
|
|
|
|
printf("Bad file header while resuming\n");
|
|
|
|
goto err;
|
2017-12-30 20:20:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Tell all of the peripherals to resume */
|
2021-01-10 02:32:40 +00:00
|
|
|
if (g_cpu->Deserialize(fd) &&
|
|
|
|
disk6->Deserialize(fd) &&
|
|
|
|
hd32->Deserialize(fd)
|
2017-12-30 20:20:34 +00:00
|
|
|
) {
|
|
|
|
printf("All deserialized successfully\n");
|
|
|
|
} else {
|
|
|
|
printf("Deserialization failed\n");
|
2021-01-10 02:32:40 +00:00
|
|
|
#ifndef TEENSYDUINO
|
2017-12-30 20:20:34 +00:00
|
|
|
exit(1);
|
|
|
|
#endif
|
2021-01-10 02:32:40 +00:00
|
|
|
goto err;
|
2017-12-30 20:20:34 +00:00
|
|
|
}
|
|
|
|
|
2021-01-10 02:32:40 +00:00
|
|
|
g_filemanager->closeFile(fd);
|
|
|
|
return true;
|
|
|
|
err:
|
|
|
|
g_filemanager->closeFile(fd);
|
|
|
|
return false;
|
2017-12-30 20:20:34 +00:00
|
|
|
}
|
|
|
|
|
2017-02-19 23:55:54 +00:00
|
|
|
// fixme: make member vars
|
|
|
|
unsigned long paddleCycleTrigger[2] = {0, 0};
|
|
|
|
|
|
|
|
void AppleVM::triggerPaddleInCycles(uint8_t paddleNum,uint16_t cycleCount)
|
|
|
|
{
|
|
|
|
paddleCycleTrigger[paddleNum] = cycleCount + g_cpu->cycles;
|
|
|
|
}
|
|
|
|
|
2020-08-02 13:06:15 +00:00
|
|
|
void AppleVM::cpuMaintenance(int64_t cycles)
|
2017-02-19 23:55:54 +00:00
|
|
|
{
|
|
|
|
for (uint8_t i=0; i<2; i++) {
|
|
|
|
if (paddleCycleTrigger[i] && cycles >= paddleCycleTrigger[i]) {
|
|
|
|
((AppleMMU *)mmu)->triggerPaddleTimer(i);
|
|
|
|
paddleCycleTrigger[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
keyboard->maintainKeyboard(cycles);
|
2019-02-22 06:01:48 +00:00
|
|
|
disk6->maintenance(cycles);
|
2021-01-10 20:04:52 +00:00
|
|
|
mouse->maintainMouse(cycles);
|
2017-02-19 23:55:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppleVM::Reset()
|
|
|
|
{
|
|
|
|
disk6->Reset();
|
|
|
|
((AppleMMU *)mmu)->resetRAM();
|
|
|
|
mmu->Reset();
|
|
|
|
|
|
|
|
g_cpu->pc = (((AppleMMU *)mmu)->read(0xFFFD) << 8) | ((AppleMMU *)mmu)->read(0xFFFC);
|
|
|
|
|
|
|
|
// give the keyboard a moment to depress keys upon startup
|
|
|
|
keyboard->maintainKeyboard(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppleVM::Monitor()
|
|
|
|
{
|
|
|
|
g_cpu->pc = 0xff69; // "call -151"
|
|
|
|
((AppleMMU *)mmu)->readSwitches(0xC054); // make sure we're in page 1
|
|
|
|
((AppleMMU *)mmu)->readSwitches(0xC056); // and that hires is off
|
|
|
|
((AppleMMU *)mmu)->readSwitches(0xC051); // and text mode is on
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *AppleVM::DiskName(uint8_t drivenum)
|
|
|
|
{
|
|
|
|
return disk6->DiskName(drivenum);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppleVM::ejectDisk(uint8_t drivenum)
|
|
|
|
{
|
|
|
|
disk6->ejectDisk(drivenum);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppleVM::insertDisk(uint8_t drivenum, const char *filename, bool drawIt)
|
|
|
|
{
|
|
|
|
disk6->insertDisk(drivenum, filename, drawIt);
|
|
|
|
}
|
|
|
|
|
2017-12-29 20:35:47 +00:00
|
|
|
const char *AppleVM::HDName(uint8_t drivenum)
|
|
|
|
{
|
|
|
|
return hd32->diskName(drivenum);
|
|
|
|
}
|
|
|
|
|
2017-12-29 19:08:49 +00:00
|
|
|
void AppleVM::ejectHD(uint8_t drivenum)
|
|
|
|
{
|
|
|
|
hd32->ejectDisk(drivenum);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppleVM::insertHD(uint8_t drivenum, const char *filename)
|
|
|
|
{
|
|
|
|
hd32->insertDisk(drivenum, filename);
|
|
|
|
}
|
|
|
|
|
2017-02-19 23:55:54 +00:00
|
|
|
VMKeyboard * AppleVM::getKeyboard()
|
|
|
|
{
|
|
|
|
return keyboard;
|
|
|
|
}
|
2021-01-11 16:32:40 +00:00
|
|
|
|
|
|
|
bool AppleVM::isMouseEnabled()
|
|
|
|
{
|
|
|
|
return mouse->isEnabled();
|
|
|
|
}
|