From 8aafabc61eda0501c81a5861d69feba4bdd4bf7c Mon Sep 17 00:00:00 2001 From: Jorj Bauer Date: Fri, 29 Dec 2017 15:35:47 -0500 Subject: [PATCH] bios support for HD files; Teensy 32-MB HD image support --- README.md | 5 ++- apple/applevm.cpp | 5 +++ apple/applevm.h | 1 + sdl/aiie.cpp | 2 +- teensy/bios.cpp | 49 ++++++++++++++++----- teensy/teensy-filemanager.cpp | 82 ++++++++++++++++++++++++++--------- teensy/teensy-filemanager.h | 3 ++ 7 files changed, 113 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index ed71e1c..0522880 100644 --- a/README.md +++ b/README.md @@ -26,17 +26,20 @@ As with many emulators, you have to go get the ROMs yourself. I've got the ROMs that I dumped out of my Apple //e. You can probably get yours a lot easier. -There are three files that you'll need: +There are four files that you'll need: * apple2e.rom -- a 32k dump of the entire Apple //e ROM * disk.rom -- a 256 byte dump of the DiskII controller ROM (16-sector P5) * parallel.rom -- a 256 byte dump of the Apple Parallel Card +* HDDRVR.BIN -- a 256 byte hard drive driver from AppleWin + (https://github.com/AppleWin/AppleWin/blob/master/firmware/HDD/HDDRVR.BIN) The MD5 sums of those files are: * 003a780b461c96ae3e72861ed0f4d3d9 apple2e.rom * 2020aa1413ff77fe29353f3ee72dc295 disk.rom * 5902996f16dc78fc013f6e1db14805b3 parallel.rom +* e91f379957d87aa0af0c7255f6ee6ba0 HDDRVR.BIN From those, the appropriate headers will be automatically generated by "make roms" (or any other target that relies on the ROMs). diff --git a/apple/applevm.cpp b/apple/applevm.cpp index 4de3cda..622401d 100644 --- a/apple/applevm.cpp +++ b/apple/applevm.cpp @@ -101,6 +101,11 @@ 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); diff --git a/apple/applevm.h b/apple/applevm.h index 6bd9305..3ace7dc 100644 --- a/apple/applevm.h +++ b/apple/applevm.h @@ -30,6 +30,7 @@ class AppleVM : public VM { void ejectDisk(uint8_t drivenum); void insertDisk(uint8_t drivenum, const char *filename, bool drawIt = true); + const char *HDName(uint8_t drivenum); void ejectHD(uint8_t drivenum); void insertHD(uint8_t drivenum, const char *filename); diff --git a/sdl/aiie.cpp b/sdl/aiie.cpp index 373f546..3365c94 100644 --- a/sdl/aiie.cpp +++ b/sdl/aiie.cpp @@ -238,7 +238,7 @@ int main(int argc, char *argv[]) } // FIXME: fixed test disk... - ((AppleVM *)g_vm)->insertHD(0, "hd32.img"); + // ((AppleVM *)g_vm)->insertHD(0, "hd32.img"); nonblock(NB_ENABLE); diff --git a/teensy/bios.cpp b/teensy/bios.cpp index 028a50f..316aafb 100644 --- a/teensy/bios.cpp +++ b/teensy/bios.cpp @@ -12,16 +12,18 @@ enum { ACT_EXIT = 0, ACT_RESET = 1, - ACT_REBOOT = 2, + ACT_COLDBOOT = 2, ACT_MONITOR = 3, ACT_DISPLAYTYPE = 4, ACT_DEBUG = 5, ACT_DISK1 = 6, ACT_DISK2 = 7, - ACT_VOLPLUS = 8, - ACT_VOLMINUS = 9, + ACT_HD1 = 8, + ACT_HD2 = 9, + ACT_VOLPLUS = 10, + ACT_VOLMINUS = 11, - NUM_ACTIONS = 10 + NUM_ACTIONS = 12 }; const char *titles[NUM_ACTIONS] = { "Resume", @@ -32,6 +34,8 @@ const char *titles[NUM_ACTIONS] = { "Resume", "Debug: %s", "%s Disk 1", "%s Disk 2", + "%s HD 1", + "%s HD 2", "Volume +", "Volume -" }; @@ -86,7 +90,7 @@ bool BIOS::runUntilDone() switch (prevAction = GetAction(prevAction)) { case ACT_EXIT: goto done; - case ACT_REBOOT: + case ACT_COLDBOOT: ColdReboot(); goto done; case ACT_RESET: @@ -124,6 +128,26 @@ bool BIOS::runUntilDone() } } break; + case ACT_HD1: + if (((AppleVM *)g_vm)->HDName(0)[0] != '\0') { + ((AppleVM *)g_vm)->ejectHD(0); + } else { + if (SelectDiskImage()) { + ((AppleVM *)g_vm)->insertHD(0, staticPathConcat(rootPath, fileDirectory[selectedFile])); + goto done; + } + } + break; + case ACT_HD2: + if (((AppleVM *)g_vm)->HDName(1)[0] != '\0') { + ((AppleVM *)g_vm)->ejectHD(1); + } else { + if (SelectDiskImage()) { + ((AppleVM *)g_vm)->insertHD(1, staticPathConcat(rootPath, fileDirectory[selectedFile])); + goto done; + } + } + break; case ACT_VOLPLUS: g_volume ++; if (g_volume > 15) { @@ -204,12 +228,14 @@ bool BIOS::isActionActive(int8_t action) switch (action) { case ACT_EXIT: case ACT_RESET: - case ACT_REBOOT: + case ACT_COLDBOOT: case ACT_MONITOR: case ACT_DISPLAYTYPE: case ACT_DEBUG: case ACT_DISK1: case ACT_DISK2: + case ACT_HD1: + case ACT_HD2: return true; case ACT_VOLPLUS: @@ -225,11 +251,13 @@ bool BIOS::isActionActive(int8_t action) void BIOS::DrawMainMenu(int8_t selection) { ((TeensyDisplay *)g_display)->clrScr(); - g_display->drawString(M_NORMAL, 0, 12, "BIOS Configuration"); + g_display->drawString(M_NORMAL, 0, 0, "BIOS Configuration"); for (int i=0; iDiskName(i - ACT_DISK1)[0] ? "Eject" : "Insert"); + } else if (i == ACT_HD1 || i == ACT_HD2) { + sprintf(buf, titles[i], ((AppleVM *)g_vm)->HDName(i - ACT_HD1)[0] ? "Eject" : "Insert"); } else if (i == ACT_DISPLAYTYPE) { switch (g_displayType) { case m_blackAndWhite: @@ -277,9 +305,9 @@ void BIOS::DrawMainMenu(int8_t selection) } if (isActionActive(i)) { - g_display->drawString(selection == i ? M_SELECTED : M_NORMAL, 10, 50 + 14 * i, buf); + g_display->drawString(selection == i ? M_SELECTED : M_NORMAL, 10, 20 + 14 * i, buf); } else { - g_display->drawString(selection == i ? M_SELECTDISABLED : M_DISABLED, 10, 50 + 14 * i, buf); + g_display->drawString(selection == i ? M_SELECTDISABLED : M_DISABLED, 10, 20 + 14 * i, buf); } } @@ -402,8 +430,7 @@ uint8_t BIOS::GatherFilenames(uint8_t pageOffset) while (1) { char fn[BIOS_MAXPATH]; - // FIXME: add po, nib - int8_t idx = g_filemanager->readDir(rootPath, "dsk", fn, startNum + count, BIOS_MAXPATH); + int8_t idx = g_filemanager->readDir(rootPath, "dsk,.po,nib,img", fn, startNum + count, BIOS_MAXPATH); if (idx == -1) { return count; diff --git a/teensy/teensy-filemanager.cpp b/teensy/teensy-filemanager.cpp index 661b754..fab7127 100644 --- a/teensy/teensy-filemanager.cpp +++ b/teensy/teensy-filemanager.cpp @@ -10,6 +10,9 @@ DIR dir; FILINFO fno; FIL fil; +int8_t rawFd = -1; +FIL rawFil; + static TCHAR *char2tchar( const char *charString, int nn, TCHAR *output) { int ii; @@ -42,6 +45,12 @@ TeensyFileManager::~TeensyFileManager() int8_t TeensyFileManager::openFile(const char *name) { + // invalidate the raw file cache + if (rawFd != -1) { + f_close(&rawFil); + rawFd = -1; + } + // See if there's a hole to re-use... for (int i=0; i= numCached) return; @@ -136,7 +151,7 @@ int8_t TeensyFileManager::readDir(const char *where, const char *suffix, char *o } p = strstr(p, ",")+1; } - if (matchesAny) + if (!matchesAny) continue; } else { // one suffix to check @@ -273,6 +288,36 @@ bool TeensyFileManager::writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib) return (v == (isNib ? 0x1a00 : (256*16))); } +bool TeensyFileManager::_prepCache(int8_t fd) +{ + FRESULT rc; + + if (rawFd == -1 || + rawFd != fd) { + + // Not our cached file, or we have no cached file + if (rawFd != -1) { + // Close the old one if we had one + Serial.println("closing old HD cache"); + f_close(&rawFil); + rawFd = -1; + } + + // Open the new one + TCHAR buf[MAXPATH]; + char2tchar(cachedNames[fd], MAXPATH, buf); + rc = f_open(&rawFil, (TCHAR*) buf, FA_READ|FA_WRITE); + if (rc) { + Serial.println("readByteAt: failed to open"); + return false; + } + Serial.println("new cache file open"); + rawFd = fd; // cache is live + } + + return (!rc); +} + uint8_t TeensyFileManager::readByteAt(int8_t fd, uint32_t pos) { // open, seek, read, close. @@ -282,26 +327,21 @@ uint8_t TeensyFileManager::readByteAt(int8_t fd, uint32_t pos) 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; - } + FRESULT rc; - rc = f_lseek(&fil, pos); + _prepCache(fd); + + rc = f_lseek(&rawFil, 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); + f_read(&rawFil, &b, 1, &v); + + // FIXME: check v == 1 & handle error + return b; } bool TeensyFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos) @@ -313,14 +353,14 @@ bool TeensyFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos) 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); + FRESULT rc; + + _prepCache(fd); + + rc = f_lseek(&rawFil, pos); UINT ret; - f_write(&fil, &v, 1, &ret); - f_close(&fil); + f_write(&rawFil, &v, 1, &ret); + return (ret == 1); } diff --git a/teensy/teensy-filemanager.h b/teensy/teensy-filemanager.h index f63d4fc..2c71196 100644 --- a/teensy/teensy-filemanager.h +++ b/teensy/teensy-filemanager.h @@ -23,6 +23,9 @@ class TeensyFileManager : public FileManager { virtual uint8_t readByteAt(int8_t fd, uint32_t pos); virtual bool writeByteAt(int8_t fd, uint8_t v, uint32_t pos); + + private: + bool _prepCache(int8_t fd); private: int8_t numCached;