diff --git a/.gitignore b/.gitignore index 6bbdc19..08d30b5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,6 @@ parallel.rom apple/applemmu-rom.h apple/diskii-rom.h apple/parallel-rom.h +apple/hd32-rom.h aiie-sdl mockingboard-d.rom diff --git a/Makefile b/Makefile index 7810ad1..20068da 100755 --- a/Makefile +++ b/Makefile @@ -6,11 +6,11 @@ CXXFLAGS=-Wall -I .. -I . -I apple -I sdl -I/usr/local/include/SDL2 -O3 -g 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 lcg.o +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 lcg.o apple/hd32.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 +ROMS=apple/applemmu-rom.h apple/diskii-rom.h apple/parallel-rom.h apple/hd32-rom.h all: sdl @@ -25,8 +25,8 @@ test: $(TSRC) g++ $(CXXFLAGS) -DEXIT_ON_ILLEGAL -DVERBOSE_CPU_ERRORS -DTESTHARNESS -DVERBOSETEST $(TSRC) -o testharness.verbose g++ $(CXXFLAGS) -DEXIT_ON_ILLEGAL -DVERBOSE_CPU_ERRORS -DTESTHARNESS -DEXTENDEDTEST $(TSRC) -o testharness.extended -roms: apple2e.rom disk.rom parallel.rom - ./util/genrom.pl apple2e.rom disk.rom parallel.rom +roms: apple2e.rom disk.rom parallel.rom HDDRVR.BIN + ./util/genrom.pl apple2e.rom disk.rom parallel.rom HDDRVR.BIN apple/applemmu-rom.h: roms diff --git a/apple/applevm.cpp b/apple/applevm.cpp index 77e7840..4de3cda 100644 --- a/apple/applevm.cpp +++ b/apple/applevm.cpp @@ -25,11 +25,14 @@ AppleVM::AppleVM() #ifdef TEENSYDUINO teensyClock = new TeensyClock((AppleMMU *)mmu); - ((AppleMMU *)mmu)->setSlot(7, teensyClock); + ((AppleMMU *)mmu)->setSlot(5, teensyClock); #else sdlClock = new SDLClock((AppleMMU *)mmu); - ((AppleMMU *)mmu)->setSlot(7, sdlClock); + ((AppleMMU *)mmu)->setSlot(5, sdlClock); #endif + + hd32 = new HD32((AppleMMU *)mmu); + ((AppleMMU *)mmu)->setSlot(7, hd32); } AppleVM::~AppleVM() @@ -98,6 +101,16 @@ void AppleVM::insertDisk(uint8_t drivenum, const char *filename, bool drawIt) disk6->insertDisk(drivenum, filename, drawIt); } +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; diff --git a/apple/applevm.h b/apple/applevm.h index 9e22a69..6bd9305 100644 --- a/apple/applevm.h +++ b/apple/applevm.h @@ -4,6 +4,7 @@ #include "cpu.h" #include "appledisplay.h" #include "diskii.h" +#include "hd32.h" #include "vmkeyboard.h" #include "parallelcard.h" #ifdef TEENSYDUINO @@ -29,9 +30,13 @@ class AppleVM : public VM { void ejectDisk(uint8_t drivenum); void insertDisk(uint8_t drivenum, const char *filename, bool drawIt = true); + void ejectHD(uint8_t drivenum); + void insertHD(uint8_t drivenum, const char *filename); + virtual VMKeyboard *getKeyboard(); DiskII *disk6; + HD32 *hd32; protected: VMKeyboard *keyboard; ParallelCard *parallel; diff --git a/apple/hd32.cpp b/apple/hd32.cpp new file mode 100644 index 0000000..515865c --- /dev/null +++ b/apple/hd32.cpp @@ -0,0 +1,261 @@ +#include "hd32.h" + +/* AppleWin 32-MB hard drive emulation. + * + * cf. https://github.com/AppleWin/AppleWin/tree/master/firmware/HDD + * + * + * General interface is outlined in + * https://github.com/AppleWin/AppleWin/blob/master/source/Harddisk.cpp + */ + +#ifdef TEENSYDUINO +#include +#else +#include +#include +#include +#include +#include +#include +#endif + +#include "applemmu.h" // for FLOATING + +#include "globals.h" + +#include "hd32-rom.h" + + +#define DEVICE_OK 0x00 +#define DEVICE_UNKNOWN_ERROR 0x28 +#define DEVICE_IO_ERROR 0x27 + +// Switches... +#define HD32_EXEC_RETSTAT 0x0 +#define HD32_STATUS 0x1 +#define HD32_COMMAND 0x2 +#define HD32_UNITNUM 0x3 +#define HD32_LBBUF 0x4 +#define HD32_HBBUF 0x5 +#define HD32_LBBLOCKNUM 0x6 +#define HD32_HBBLOCKNUM 0x7 +#define HD32_NEXTBYTE 0x8 + +// Commands +#define CMD_STATUS 0x0 +#define CMD_READ 0x1 +#define CMD_WRITE 0x2 +#define CMD_FORMAT 0x3 + +HD32::HD32(AppleMMU *mmu) +{ + this->mmu = mmu; + Reset(); +} + +HD32::~HD32() +{ +} + +void HD32::Reset() +{ + enabled = 1; + + fd[0] = fd[1] = -1; + errorState[0] = errorState[1] = 0; + memBlock[0] = memBlock[1] = 0; + diskBlock[0] = diskBlock[1] = 0; + driveSelected = 0; + command = CMD_STATUS; +} + +uint8_t HD32::readSwitches(uint8_t s) +{ + uint8_t ret = DEVICE_OK; + + if (!enabled) + return DEVICE_IO_ERROR; + + switch (s) { + case HD32_EXEC_RETSTAT: + switch (command) { + case CMD_STATUS: + // set ret to DEVICE_IO_ERROR & set error state=true if no image loaded + if (fd[driveSelected] == -1) { + // Nothing inserted + ret = DEVICE_IO_ERROR; + errorState[driveSelected] = 1; + } else { + ret = DEVICE_OK; + errorState[driveSelected] = 0; + } + break; + + case CMD_READ: + // FIXME: if diskblock[selectedDrive] >= disk image size, set/return io error + errorState[driveSelected] = 0; + ret = DEVICE_OK; + + cursor[driveSelected] = diskBlock[driveSelected] * 512; // sectors are 512 bytes + break; + + case CMD_WRITE: + // FIXME: if diskblock[selectedDrive] >= disk image size, set/return io error + if (!writeBlockToSelectedDrive()){ + ret = DEVICE_IO_ERROR; + errorState[driveSelected] = 1; + } + break; + + case CMD_FORMAT: + // Currently ignored. FIXME: make this zero out a 32MB file? + break; + + default: + errorState[driveSelected] = 1; + ret = DEVICE_UNKNOWN_ERROR; + break; + + } + + break; + + case HD32_STATUS: + ret = errorState[driveSelected]; + break; + + case HD32_COMMAND: + ret = command; + break; + + case HD32_UNITNUM: + ret = unitSelected; + break; + + case HD32_LBBUF: + ret = memBlock[driveSelected] & 0x00FF; + break; + case HD32_HBBUF: + ret = ((memBlock[driveSelected] & 0xFF00) >> 8); + break; + + case HD32_LBBLOCKNUM: + ret = diskBlock[driveSelected] & 0x00FF; + break; + case HD32_HBBLOCKNUM: + ret = ((diskBlock[driveSelected] & 0xFF00) >> 8); + break; + + case HD32_NEXTBYTE: + ret = readNextByteFromSelectedDrive(); + break; + } + + return ret; +} + +void HD32::writeSwitches(uint8_t s, uint8_t v) +{ + if (!enabled) + return; + + switch (s) { + case HD32_COMMAND: + command = v; + break; + case HD32_UNITNUM: + unitSelected = v; + // FIXME: verify slot#? + driveSelected = (v & 0x80) ? 1 : 0; + break; + case HD32_LBBUF: + memBlock[driveSelected] = (memBlock[driveSelected] & 0xFF00) | v; + break; + case HD32_HBBUF: + memBlock[driveSelected] = (memBlock[driveSelected] & 0x00FF) | (v << 8); + break; + case HD32_LBBLOCKNUM: + diskBlock[driveSelected] = (diskBlock[driveSelected] & 0xFF00) | v; + break; + case HD32_HBBLOCKNUM: + diskBlock[driveSelected] = (diskBlock[driveSelected] & 0x00FF) | (v << 8); + break; + } +} + +void HD32::loadROM(uint8_t *toWhere) +{ +#ifdef TEENSYDUINO + Serial.println("loading HD32 rom"); + for (uint16_t i=0; i<=0xFF; i++) { + toWhere[i] = pgm_read_byte(&romData[i]); + } +#else + printf("loading HD32 rom\n"); + memcpy(toWhere, romData, 256); +#endif +} + +uint8_t HD32::readNextByteFromSelectedDrive() +{ + // FIXME: assumes file is open & cursor is valid + + uint8_t v; + + v = g_filemanager->readByteAt(fd[driveSelected], cursor[driveSelected]); + // FIXME: error handling + + cursor[driveSelected]++; + + return v; +} + +bool HD32::writeBlockToSelectedDrive() +{ + // FIXME: assumes file is open & cursor is valid + // FIXME: need a better filemanager interface that holds the file open + + for (uint16_t i=0; i<512; i++) { + uint8_t b = mmu->read(memBlock[driveSelected] + i); + if (!g_filemanager->writeByteAt(fd[driveSelected], b, diskBlock[driveSelected] * 512 + i)) { + // FIXME +#ifndef TEENSYDUINO + printf("ERROR: failed to write to hd file? errno %d\n", errno); +#endif + return false; + } + } + + return true; +} + +void HD32::setEnabled(uint8_t e) +{ + enabled = e; +} + +const char *HD32::diskName(int8_t num) +{ + if (fd[num] != -1) + return g_filemanager->fileName(fd[num]); + + return ""; +} + +void HD32::insertDisk(int8_t driveNum, const char *filename) +{ + ejectDisk(driveNum); + fd[driveNum] = g_filemanager->openFile(filename); + errorState[driveNum] = 0; + enabled = 1; +} + +void HD32::ejectDisk(int8_t driveNum) +{ + if (fd[driveNum] != -1) { + g_filemanager->closeFile(fd[driveNum]); + fd[driveNum] = -1; + } +} + diff --git a/apple/hd32.h b/apple/hd32.h new file mode 100644 index 0000000..8b7e808 --- /dev/null +++ b/apple/hd32.h @@ -0,0 +1,55 @@ +#ifndef __HD32_H +#define __HD32_H + +#ifdef TEENSYDUINO +#include +#else +#include +#include +#endif + +#include "filemanager.h" +#include "applemmu.h" +#include "Slot.h" + +#include "RingBuffer.h" + +class HD32 : public Slot { + public: + HD32(AppleMMU *mmu); + virtual ~HD32(); + + virtual void Reset(); // used by BIOS cold-boot + virtual uint8_t readSwitches(uint8_t s); + virtual void writeSwitches(uint8_t s, uint8_t v); + virtual void loadROM(uint8_t *toWhere); + + void setEnabled(uint8_t e); + + void insertDisk(int8_t driveNum, const char *filename); + void ejectDisk(int8_t driveNum); + + const char *diskName(int8_t num); + + protected: + uint8_t readNextByteFromSelectedDrive(); + bool writeBlockToSelectedDrive(); + + private: + AppleMMU *mmu; + + uint8_t driveSelected; // 0 or 1 + uint8_t unitSelected; // b7 = drive#; b6..4 = slot#; b3..0 = ? + uint8_t command; // CMD_*; FIXME, make enum + + uint8_t enabled; + + uint8_t errorState[2]; // status of last operation + uint16_t memBlock[2]; // ?? + uint16_t diskBlock[2]; // currently selected block + + int8_t fd[2]; + uint32_t cursor[2]; // seek position on the given file handle +}; + +#endif diff --git a/filemanager.h b/filemanager.h index 1bde8d2..2b9326e 100644 --- a/filemanager.h +++ b/filemanager.h @@ -24,6 +24,9 @@ class FileManager { virtual bool readBlock(int8_t fd, uint8_t *toWhere, bool isNib = false) = 0; virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false) = 0; virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false) = 0; + + virtual uint8_t readByteAt(int8_t fd, uint32_t pos) = 0; + virtual bool writeByteAt(int8_t fd, uint8_t v, uint32_t pos) = 0; }; #endif diff --git a/sdl/aiie.cpp b/sdl/aiie.cpp index df15594..373f546 100644 --- a/sdl/aiie.cpp +++ b/sdl/aiie.cpp @@ -32,6 +32,9 @@ int send_rst = 0; pthread_t cpuThreadID; +char disk1name[256] = "\0"; +char disk2name[256] = "\0"; + void sigint_handler(int n) { send_rst = 1; @@ -133,7 +136,7 @@ static void *cpu_thread(void *dummyptr) { #endif if (send_rst) { -#if 1 +#if 0 printf("Sending reset\n"); g_cpu->Reset(); @@ -142,7 +145,17 @@ static void *cpu_thread(void *dummyptr) { //g_vm->Reset(); //g_cpu->Reset(); //((AppleVM *)g_vm)->insertDisk(0, "disks/DIAGS.DSK"); - +#else + // Swap disks + if (disk1name[0] && disk2name[0]) { + printf("Swapping disks\n"); + + printf("Inserting disk %s in drive 1\n", disk2name); + ((AppleVM *)g_vm)->insertDisk(0, disk2name); + printf("Inserting disk %s in drive 2\n", disk1name); + ((AppleVM *)g_vm)->insertDisk(1, disk1name); + } + /* #else MMU *mmu = g_vm->getMMU(); @@ -169,6 +182,7 @@ static void *cpu_thread(void *dummyptr) { mmu->write(0x23, 24); mmu->write(0x33, '>'); mmu->write(0x48, 0); // from 0xfb2f: part of text init + */ #endif send_rst = 0; @@ -214,12 +228,17 @@ int main(int argc, char *argv[]) if (argc >= 2) { printf("Inserting disk %s\n", argv[1]); ((AppleVM *)g_vm)->insertDisk(0, argv[1]); + strcpy(disk1name, argv[1]); } if (argc == 3) { printf("Inserting disk %s\n", argv[2]); ((AppleVM *)g_vm)->insertDisk(1, argv[2]); + strcpy(disk2name, argv[2]); } + + // FIXME: fixed test disk... + ((AppleVM *)g_vm)->insertHD(0, "hd32.img"); nonblock(NB_ENABLE); diff --git a/sdl/sdl-clock.cpp b/sdl/sdl-clock.cpp index bfb2d3c..49f7bfe 100644 --- a/sdl/sdl-clock.cpp +++ b/sdl/sdl-clock.cpp @@ -86,7 +86,7 @@ void SDLClock::writeSwitches(uint8_t s, uint8_t v) // printf("unimplemented write to the clock - 0x%X\n", v); } -// FIXME: this assumes slot #7 +// FIXME: this assumes slot #5 void SDLClock::loadROM(uint8_t *toWhere) { memset(toWhere, 0xEA, 256); // fill the page with NOPs @@ -98,9 +98,9 @@ void SDLClock::loadROM(uint8_t *toWhere) toWhere[0x06] = 0x70; // BVS // Pad out those bytes so they will return control well. The program - // at c700 becomes + // at c500 becomes // - // C700: PHP ; push to stack + // C500: PHP ; push to stack // NOP ; filler (filled in by memory clear) // PLP ; pop from stack // RTS ; return @@ -112,19 +112,19 @@ void SDLClock::loadROM(uint8_t *toWhere) // And it needs a small routing here to read/write it: // 0x08: read - toWhere[0x08] = 0x4C; // JMP $C710 + toWhere[0x08] = 0x4C; // JMP $C510 toWhere[0x09] = 0x10; - toWhere[0x0A] = 0xC7; + toWhere[0x0A] = 0xC5; // 0x0b: write - toWhere[0x0B] = 0x8D; // STA $C0F0 (slot 7's first switch) - toWhere[0x0C] = 0xF0; + toWhere[0x0B] = 0x8D; // STA $C0D0 (slot 5's first switch) + toWhere[0x0C] = 0xD0; toWhere[0x0D] = 0xC0; toWhere[0x0E] = 0x60; // RTS // simple read - toWhere[0x10] = 0xAD; // LDA $C0F0 (slot 7's first switch) - toWhere[0x11] = 0xF0; + toWhere[0x10] = 0xAD; // LDA $C0D0 (slot 5's first switch) + toWhere[0x11] = 0xD0; toWhere[0x12] = 0xC0; toWhere[0x13] = 0x60; // RTS } diff --git a/sdl/sdl-filemanager.cpp b/sdl/sdl-filemanager.cpp index b85520b..0ddde4a 100644 --- a/sdl/sdl-filemanager.cpp +++ b/sdl/sdl-filemanager.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "sdl-filemanager.h" @@ -187,3 +188,51 @@ bool SDLFileManager::writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib) } return true; } + +uint8_t SDLFileManager::readByteAt(int8_t fd, uint32_t pos) +{ + if (fd < 0 || fd >= numCached) + return -1; // FIXME: error handling? + + if (cachedNames[fd][0] == 0) + return -1; // FIXME: error handling? + + uint8_t v = 0; + + // open, seek, read, close. + bool ret = false; + int ffd = open(cachedNames[fd], O_RDONLY); + if (ffd) { + lseek(ffd, pos, SEEK_SET); + ret = (read(ffd, &v, 1) == 1); + close(ffd); + } + + if (!ret) { + printf("ERROR reading: %d\n", errno); + } + + // FIXME: error handling? + return v; +} + +bool SDLFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos) +{ + if (fd < 0 || fd >= numCached) + return false; + + if (cachedNames[fd][0] == 0) + return false; + + // open, seek, write, close. + bool ret = false; + int ffd = open(cachedNames[fd], O_WRONLY); + if (ffd) { + lseek(ffd, pos, SEEK_SET); + ret = (write(ffd, &v, 1) == 1); + close(ffd); + } + + return ret; +} + diff --git a/sdl/sdl-filemanager.h b/sdl/sdl-filemanager.h index 9cff777..7e367ec 100644 --- a/sdl/sdl-filemanager.h +++ b/sdl/sdl-filemanager.h @@ -21,6 +21,9 @@ class SDLFileManager : public FileManager { virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false); virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false); + virtual uint8_t readByteAt(int8_t fd, uint32_t pos); + virtual bool writeByteAt(int8_t fd, uint8_t v, uint32_t pos); + private: int8_t numCached; char cachedNames[MAXFILES][MAXPATH]; diff --git a/teensy/hd32-rom.h b/teensy/hd32-rom.h new file mode 120000 index 0000000..b08c030 --- /dev/null +++ b/teensy/hd32-rom.h @@ -0,0 +1 @@ +../apple/hd32-rom.h \ No newline at end of file diff --git a/teensy/hd32.cpp b/teensy/hd32.cpp new file mode 120000 index 0000000..3faa218 --- /dev/null +++ b/teensy/hd32.cpp @@ -0,0 +1 @@ +../apple/hd32.cpp \ No newline at end of file diff --git a/teensy/hd32.h b/teensy/hd32.h new file mode 120000 index 0000000..3031179 --- /dev/null +++ b/teensy/hd32.h @@ -0,0 +1 @@ +../apple/hd32.h \ No newline at end of file diff --git a/teensy/teensy-clock.cpp b/teensy/teensy-clock.cpp index 2341d8a..f1eb38c 100644 --- a/teensy/teensy-clock.cpp +++ b/teensy/teensy-clock.cpp @@ -81,7 +81,7 @@ void TeensyClock::writeSwitches(uint8_t s, uint8_t v) // printf("unimplemented write to the clock - 0x%X\n", v); } -// FIXME: this assumes slot #7 +// FIXME: this assumes slot #5 void TeensyClock::loadROM(uint8_t *toWhere) { memset(toWhere, 0xEA, 256); // fill the page with NOPs @@ -93,9 +93,9 @@ void TeensyClock::loadROM(uint8_t *toWhere) toWhere[0x06] = 0x70; // BVS // Pad out those bytes so they will return control well. The program - // at c700 becomes + // at c500 becomes // - // C700: PHP ; push to stack + // C500: PHP ; push to stack // NOP ; filler (filled in by memory clear) // PLP ; pop from stack // RTS ; return @@ -107,19 +107,19 @@ void TeensyClock::loadROM(uint8_t *toWhere) // And it needs a small routing here to read/write it: // 0x08: read - toWhere[0x08] = 0x4C; // JMP $C710 + toWhere[0x08] = 0x4C; // JMP $C510 toWhere[0x09] = 0x10; - toWhere[0x0A] = 0xC7; + toWhere[0x0A] = 0xC5; // 0x0b: write - toWhere[0x0B] = 0x8D; // STA $C0F0 (slot 7's first switch) - toWhere[0x0C] = 0xF0; + toWhere[0x0B] = 0x8D; // STA $C0D0 (slot 5's first switch) + toWhere[0x0C] = 0xD0; toWhere[0x0D] = 0xC0; toWhere[0x0E] = 0x60; // RTS // simple read - toWhere[0x10] = 0xAD; // LDA $C0F0 (slot 7's first switch) - toWhere[0x11] = 0xF0; + toWhere[0x10] = 0xAD; // LDA $C0D0 (slot 5's first switch) + toWhere[0x11] = 0xD0; toWhere[0x12] = 0xC0; toWhere[0x13] = 0x60; // RTS } diff --git a/teensy/teensy-filemanager.cpp b/teensy/teensy-filemanager.cpp index 104d3de..661b754 100644 --- a/teensy/teensy-filemanager.cpp +++ b/teensy/teensy-filemanager.cpp @@ -273,3 +273,54 @@ bool TeensyFileManager::writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib) return (v == (isNib ? 0x1a00 : (256*16))); } +uint8_t TeensyFileManager::readByteAt(int8_t fd, uint32_t pos) +{ + // open, seek, read, close. + if (fd < 0 || fd >= numCached) + return false; + + if (cachedNames[fd][0] == 0) + return false; + + // open, seek, read, close. + TCHAR buf[MAXPATH]; + char2tchar(cachedNames[fd], MAXPATH, buf); + FRESULT rc = f_open(&fil, (TCHAR*) buf, FA_READ); + if (rc) { + Serial.println("readByteAt: failed to open"); + return false; + } + + rc = f_lseek(&fil, pos); + if (rc) { + Serial.println("readByteAt: seek failed"); + f_close(&fil); + return false; + } + uint8_t b; + UINT v; + f_read(&fil, &b, 1, &v); + f_close(&fil); + return (v == 1); +} + +bool TeensyFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos) +{ + // open, seek, write, close. + if (fd < 0 || fd >= numCached) + return false; + + if (cachedNames[fd][0] == 0) + return false; + + // open, seek, write, close. + TCHAR buf[MAXPATH]; + char2tchar(cachedNames[fd], MAXPATH, buf); + FRESULT rc = f_open(&fil, (TCHAR*) buf, FA_WRITE); + rc = f_lseek(&fil, pos); + UINT ret; + f_write(&fil, &v, 1, &ret); + f_close(&fil); + return (ret == 1); +} + diff --git a/teensy/teensy-filemanager.h b/teensy/teensy-filemanager.h index 910ab3b..f63d4fc 100644 --- a/teensy/teensy-filemanager.h +++ b/teensy/teensy-filemanager.h @@ -21,6 +21,9 @@ class TeensyFileManager : public FileManager { virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false); virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false); + virtual uint8_t readByteAt(int8_t fd, uint32_t pos); + virtual bool writeByteAt(int8_t fd, uint8_t v, uint32_t pos); + private: int8_t numCached; char cachedNames[MAXFILES][MAXPATH]; diff --git a/util/genrom.pl b/util/genrom.pl index c6cc27b..867f2b0 100755 --- a/util/genrom.pl +++ b/util/genrom.pl @@ -6,14 +6,17 @@ use warnings; my $romfile = shift || die "Must provide the path to an Apple //e ROM image"; my $diskrom = shift || die "Must also provide the path to an Apple //e Disk II ROM image"; my $parallelrom = shift || die "Must also provide the path to an Apple // parallel card ROM image"; +my $hdrom = shift || die "Must also provide the path to the AppleWin HDDRVR.BIN"; validate($romfile, 32768, "an Apple //e ROM image"); validate($diskrom, 256, "a DiskII ROM image"); validate($parallelrom, 256, "a parallel card ROM image"); +validate($hdrom, 256, "HDDRVR.BIN from AppleWin"); dumpRom($romfile, "apple/applemmu-rom.h", "romData", 32768); dumpRom($diskrom, "apple/diskii-rom.h", "romData", 256); dumpRom($parallelrom, "apple/parallel-rom.h", "romData", 256); +dumpRom($hdrom, "apple/hd32-rom.h", "romData", 256); exit 0; sub validate {