aiie/apple/applevm.cpp

197 lines
4.5 KiB
C++
Raw Normal View History

#include "applevm.h"
#include "filemanager.h"
#include "cpu.h"
#include "appledisplay.h"
#include "applekeyboard.h"
#include "physicalkeyboard.h"
#include "globals.h"
2020-07-04 11:41:32 +00:00
#ifdef TEENSYDUINO
#include "teensy-println.h"
#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
AppleVM::AppleVM()
{
// FIXME: all this typecasting makes me knife-stabby
vmdisplay = new AppleDisplay();
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);
hd32 = new HD32((AppleMMU *)mmu);
((AppleMMU *)mmu)->setSlot(7, hd32);
}
AppleVM::~AppleVM()
{
delete disk6;
2017-02-24 15:15:17 +00:00
delete parallel;
}
2017-12-30 20:20:34 +00:00
void 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) {
// Unable to open; skip suspend
return;
}
/* Header */
2020-06-28 19:24:49 +00:00
if (g_filemanager->write(fh, suspendHdr, strlen(suspendHdr)) != strlen(suspendHdr))
return;
2017-12-30 20:20:34 +00:00
/* Tell all of the peripherals to suspend */
if (g_cpu->Serialize(fh) &&
disk6->Serialize(fh) &&
hd32->Serialize(fh)
) {
2020-06-28 19:24:49 +00:00
#ifdef TEENSYDUINO
2020-07-04 11:41:32 +00:00
println("All serialized successfully");
2020-06-28 19:24:49 +00:00
#else
printf("All serialized successfully\n");
2017-12-30 20:20:34 +00:00
#endif
}
g_filemanager->closeFile(fh);
}
void 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) {
// Unable to open; skip resume
#ifdef TEENSYDUINO
2020-07-04 11:41:32 +00:00
print("Unable to open resume file ");
println(fn);
2017-12-30 20:20:34 +00:00
#else
printf("Unable to open resume file\n");
#endif
g_filemanager->closeFile(fh);
2017-12-30 20:20:34 +00:00
return;
}
/* Header */
2020-06-28 19:24:49 +00:00
uint8_t c;
2017-12-30 20:20:34 +00:00
for (int i=0; i<strlen(suspendHdr); i++) {
2020-06-28 19:24:49 +00:00
if (g_filemanager->read(fh, &c, 1) != 1 ||
c != suspendHdr[i]) {
2017-12-30 20:20:34 +00:00
/* Failed to read correct header; abort */
g_filemanager->closeFile(fh);
2017-12-30 20:20:34 +00:00
return;
}
}
/* Tell all of the peripherals to resume */
if (g_cpu->Deserialize(fh) &&
disk6->Deserialize(fh) &&
hd32->Deserialize(fh)
) {
#ifdef TEENSYDUINO
2020-07-04 11:41:32 +00:00
println("Deserialization successful");
#else
2017-12-30 20:20:34 +00:00
printf("All deserialized successfully\n");
#endif
} else {
#ifndef TEENSYDUINO
printf("Deserialization failed\n");
exit(1);
#endif
}
g_filemanager->closeFile(fh);
}
// 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;
}
void AppleVM::cpuMaintenance(uint32_t cycles)
{
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);
}
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);
}
const char *AppleVM::HDName(uint8_t drivenum)
{
return hd32->diskName(drivenum);
}
void AppleVM::ejectHD(uint8_t drivenum)
{
hd32->ejectDisk(drivenum);
}
void AppleVM::insertHD(uint8_t drivenum, const char *filename)
{
hd32->insertDisk(drivenum, filename);
}
VMKeyboard * AppleVM::getKeyboard()
{
return keyboard;
}