From e033f6e039d9ffcce53396d478ceb6b48dec00ba Mon Sep 17 00:00:00 2001 From: Jorj Bauer Date: Tue, 28 Feb 2017 23:44:03 -0500 Subject: [PATCH] added SDL clock for testing --- Makefile | 2 +- apple/applevm.cpp | 5 ++ apple/applevm.h | 4 ++ sdl/sdl-clock.cpp | 131 ++++++++++++++++++++++++++++++++++++++++++++++ sdl/sdl-clock.h | 26 +++++++++ 5 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 sdl/sdl-clock.cpp create mode 100644 sdl/sdl-clock.h diff --git a/Makefile b/Makefile index 4513b41..5cde791 100755 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ TSRC=cpu.cpp util/testharness.cpp COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o RingBuffer.o globals.o apple/parallelcard.o apple/fx80.o apple/mockingboard.o apple/sy6522.o apple/ay8910.o lcg.o -SDLOBJS=sdl/sdl-speaker.o sdl/sdl-display.o sdl/sdl-keyboard.o sdl/sdl-paddles.o sdl/sdl-filemanager.o sdl/aiie.o sdl/sdl-printer.o +SDLOBJS=sdl/sdl-speaker.o sdl/sdl-display.o sdl/sdl-keyboard.o sdl/sdl-paddles.o sdl/sdl-filemanager.o sdl/aiie.o sdl/sdl-printer.o sdl/sdl-clock.o ROMS=apple/applemmu-rom.h apple/diskii-rom.h apple/parallel-rom.h diff --git a/apple/applevm.cpp b/apple/applevm.cpp index 2ad1df2..ffdfc6c 100644 --- a/apple/applevm.cpp +++ b/apple/applevm.cpp @@ -29,6 +29,9 @@ AppleVM::AppleVM() #ifdef TEENSYDUINO teensyClock = new TeensyClock((AppleMMU *)mmu); ((AppleMMU *)mmu)->setSlot(7, teensyClock); +#else + sdlClock = new SDLClock((AppleMMU *)mmu); + ((AppleMMU *)mmu)->setSlot(7, sdlClock); #endif } @@ -36,6 +39,8 @@ AppleVM::~AppleVM() { #ifdef TEENSYDUINO delete teensyClock; +#else + delete sdlClock; #endif delete disk6; delete parallel; diff --git a/apple/applevm.h b/apple/applevm.h index 9aa801c..de57ab2 100644 --- a/apple/applevm.h +++ b/apple/applevm.h @@ -9,6 +9,8 @@ #include "mockingboard.h" #ifdef TEENSYDUINO #include "teensy-clock.h" +#else +#include "sdl-clock.h" #endif #include "vm.h" @@ -37,6 +39,8 @@ class AppleVM : public VM { Mockingboard *mockingboard; #ifdef TEENSYDUINO TeensyClock *teensyClock; +#else + SDLClock *sdlClock; #endif }; diff --git a/sdl/sdl-clock.cpp b/sdl/sdl-clock.cpp new file mode 100644 index 0000000..bfb2d3c --- /dev/null +++ b/sdl/sdl-clock.cpp @@ -0,0 +1,131 @@ +#include // memset +#include + +#include "sdl-clock.h" +#include "applemmu.h" // for FLOATING + +/* + * http://apple2online.com/web_documents/prodos_technical_notes.pdf + * + * When ProDOS calls a clock card, the card deposits an ASCII string + * in the GETLN input buffer in the form: 07,04,14,22,46,57. The + * string translates as the following: + * + * 07 = the month, July + * 04 = the day of the week (00 = Sun) + * 14 = the date (00 to 31) + * 22 = the hour (00 to 23) + * 46 = the minute (00 to 59) + * 57 = the second (00 to 59) +*/ + +static void timeToProDOS(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, + uint8_t proDOStimeOut[4]) +{ + proDOStimeOut[0] = ((year % 100) << 1) | (month >> 3); + proDOStimeOut[1] = ((month & 0x0F) << 5) | (day & 0x1F); + proDOStimeOut[2] = hour & 0x1F; + proDOStimeOut[3] = minute & 0x3F; +} + +SDLClock::SDLClock(AppleMMU *mmu) +{ + this->mmu = mmu; +} + +SDLClock::~SDLClock() +{ +} + +void SDLClock::Reset() +{ +} + +uint8_t SDLClock::readSwitches(uint8_t s) +{ + // When any switch is read, we'll put the current time in the prodos time buffer + time_t lt; + time(<); + struct tm *ct = localtime(<); + + // Put the date/time in the official ProDOS buffer + uint8_t prodosOut[4]; + timeToProDOS(ct->tm_year+1900, + ct->tm_mon, + ct->tm_mday, + ct->tm_hour, + ct->tm_min, + prodosOut); + mmu->write(0xBF90, prodosOut[0]); + mmu->write(0xBF91, prodosOut[1]); + mmu->write(0xBF92, prodosOut[2]); + mmu->write(0xBF93, prodosOut[3]); + + // and also generate a date/time that contains seconds, but not a + // year, which it also consumes + char ts[18]; + sprintf(ts, "%.2d,%.2d,%.2d,%.2d,%.2d,%.2d", + ct->tm_mon, + ct->tm_wday, + ct->tm_mday, + ct->tm_hour, + ct->tm_min, + ct->tm_sec); + + uint8_t i = 0; + while (ts[i]) { + mmu->write(0x200 + i, ts[i] | 0x80); + i++; + } + + return FLOATING; +} + +void SDLClock::writeSwitches(uint8_t s, uint8_t v) +{ + // printf("unimplemented write to the clock - 0x%X\n", v); +} + +// FIXME: this assumes slot #7 +void SDLClock::loadROM(uint8_t *toWhere) +{ + memset(toWhere, 0xEA, 256); // fill the page with NOPs + + // ProDOS only needs these 4 bytes to recognize that a clock is present + toWhere[0x00] = 0x08; // PHP + toWhere[0x02] = 0x28; // PLP + toWhere[0x04] = 0x58; // CLI + toWhere[0x06] = 0x70; // BVS + + // Pad out those bytes so they will return control well. The program + // at c700 becomes + // + // C700: PHP ; push to stack + // NOP ; filler (filled in by memory clear) + // PLP ; pop from stack + // RTS ; return + // CLI ; required to detect driver, but not used + // NOP ; filled in by memory clear + // BVS ; required to detect driver, but not used + + toWhere[0x03] = 0x60; // RTS + + // And it needs a small routing here to read/write it: + // 0x08: read + toWhere[0x08] = 0x4C; // JMP $C710 + toWhere[0x09] = 0x10; + toWhere[0x0A] = 0xC7; + + // 0x0b: write + toWhere[0x0B] = 0x8D; // STA $C0F0 (slot 7's first switch) + toWhere[0x0C] = 0xF0; + toWhere[0x0D] = 0xC0; + toWhere[0x0E] = 0x60; // RTS + + // simple read + toWhere[0x10] = 0xAD; // LDA $C0F0 (slot 7's first switch) + toWhere[0x11] = 0xF0; + toWhere[0x12] = 0xC0; + toWhere[0x13] = 0x60; // RTS +} + diff --git a/sdl/sdl-clock.h b/sdl/sdl-clock.h new file mode 100644 index 0000000..cc17bd8 --- /dev/null +++ b/sdl/sdl-clock.h @@ -0,0 +1,26 @@ +#ifndef __SDLCLOCK_H +#define __SDLCLOCK_H + +#include +#include + +#include "slot.h" +#include "applemmu.h" + +class SDLClock : public Slot { + public: + SDLClock(AppleMMU *mmu); + virtual ~SDLClock(); + + virtual void Reset(); + + virtual uint8_t readSwitches(uint8_t s); + virtual void writeSwitches(uint8_t s, uint8_t v); + + virtual void loadROM(uint8_t *toWhere); + + private: + AppleMMU *mmu; +}; + +#endif