bios support for HD files; Teensy 32-MB HD image support

This commit is contained in:
Jorj Bauer 2017-12-29 15:35:47 -05:00
parent 0fecbd3956
commit 8aafabc61e
7 changed files with 113 additions and 34 deletions

View File

@ -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 the ROMs that I dumped out of my Apple //e. You can probably get yours
a lot easier. 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 * 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) * 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 * 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: The MD5 sums of those files are:
* 003a780b461c96ae3e72861ed0f4d3d9 apple2e.rom * 003a780b461c96ae3e72861ed0f4d3d9 apple2e.rom
* 2020aa1413ff77fe29353f3ee72dc295 disk.rom * 2020aa1413ff77fe29353f3ee72dc295 disk.rom
* 5902996f16dc78fc013f6e1db14805b3 parallel.rom * 5902996f16dc78fc013f6e1db14805b3 parallel.rom
* e91f379957d87aa0af0c7255f6ee6ba0 HDDRVR.BIN
From those, the appropriate headers will be automatically generated by From those, the appropriate headers will be automatically generated by
"make roms" (or any other target that relies on the ROMs). "make roms" (or any other target that relies on the ROMs).

View File

@ -101,6 +101,11 @@ void AppleVM::insertDisk(uint8_t drivenum, const char *filename, bool drawIt)
disk6->insertDisk(drivenum, filename, drawIt); disk6->insertDisk(drivenum, filename, drawIt);
} }
const char *AppleVM::HDName(uint8_t drivenum)
{
return hd32->diskName(drivenum);
}
void AppleVM::ejectHD(uint8_t drivenum) void AppleVM::ejectHD(uint8_t drivenum)
{ {
hd32->ejectDisk(drivenum); hd32->ejectDisk(drivenum);

View File

@ -30,6 +30,7 @@ class AppleVM : public VM {
void ejectDisk(uint8_t drivenum); void ejectDisk(uint8_t drivenum);
void insertDisk(uint8_t drivenum, const char *filename, bool drawIt = true); void insertDisk(uint8_t drivenum, const char *filename, bool drawIt = true);
const char *HDName(uint8_t drivenum);
void ejectHD(uint8_t drivenum); void ejectHD(uint8_t drivenum);
void insertHD(uint8_t drivenum, const char *filename); void insertHD(uint8_t drivenum, const char *filename);

View File

@ -238,7 +238,7 @@ int main(int argc, char *argv[])
} }
// FIXME: fixed test disk... // FIXME: fixed test disk...
((AppleVM *)g_vm)->insertHD(0, "hd32.img"); // ((AppleVM *)g_vm)->insertHD(0, "hd32.img");
nonblock(NB_ENABLE); nonblock(NB_ENABLE);

View File

@ -12,16 +12,18 @@
enum { enum {
ACT_EXIT = 0, ACT_EXIT = 0,
ACT_RESET = 1, ACT_RESET = 1,
ACT_REBOOT = 2, ACT_COLDBOOT = 2,
ACT_MONITOR = 3, ACT_MONITOR = 3,
ACT_DISPLAYTYPE = 4, ACT_DISPLAYTYPE = 4,
ACT_DEBUG = 5, ACT_DEBUG = 5,
ACT_DISK1 = 6, ACT_DISK1 = 6,
ACT_DISK2 = 7, ACT_DISK2 = 7,
ACT_VOLPLUS = 8, ACT_HD1 = 8,
ACT_VOLMINUS = 9, ACT_HD2 = 9,
ACT_VOLPLUS = 10,
ACT_VOLMINUS = 11,
NUM_ACTIONS = 10 NUM_ACTIONS = 12
}; };
const char *titles[NUM_ACTIONS] = { "Resume", const char *titles[NUM_ACTIONS] = { "Resume",
@ -32,6 +34,8 @@ const char *titles[NUM_ACTIONS] = { "Resume",
"Debug: %s", "Debug: %s",
"%s Disk 1", "%s Disk 1",
"%s Disk 2", "%s Disk 2",
"%s HD 1",
"%s HD 2",
"Volume +", "Volume +",
"Volume -" "Volume -"
}; };
@ -86,7 +90,7 @@ bool BIOS::runUntilDone()
switch (prevAction = GetAction(prevAction)) { switch (prevAction = GetAction(prevAction)) {
case ACT_EXIT: case ACT_EXIT:
goto done; goto done;
case ACT_REBOOT: case ACT_COLDBOOT:
ColdReboot(); ColdReboot();
goto done; goto done;
case ACT_RESET: case ACT_RESET:
@ -124,6 +128,26 @@ bool BIOS::runUntilDone()
} }
} }
break; 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: case ACT_VOLPLUS:
g_volume ++; g_volume ++;
if (g_volume > 15) { if (g_volume > 15) {
@ -204,12 +228,14 @@ bool BIOS::isActionActive(int8_t action)
switch (action) { switch (action) {
case ACT_EXIT: case ACT_EXIT:
case ACT_RESET: case ACT_RESET:
case ACT_REBOOT: case ACT_COLDBOOT:
case ACT_MONITOR: case ACT_MONITOR:
case ACT_DISPLAYTYPE: case ACT_DISPLAYTYPE:
case ACT_DEBUG: case ACT_DEBUG:
case ACT_DISK1: case ACT_DISK1:
case ACT_DISK2: case ACT_DISK2:
case ACT_HD1:
case ACT_HD2:
return true; return true;
case ACT_VOLPLUS: case ACT_VOLPLUS:
@ -225,11 +251,13 @@ bool BIOS::isActionActive(int8_t action)
void BIOS::DrawMainMenu(int8_t selection) void BIOS::DrawMainMenu(int8_t selection)
{ {
((TeensyDisplay *)g_display)->clrScr(); ((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; i<NUM_ACTIONS; i++) { for (int i=0; i<NUM_ACTIONS; i++) {
char buf[25]; char buf[25];
if (i == ACT_DISK1 || i == ACT_DISK2) { if (i == ACT_DISK1 || i == ACT_DISK2) {
sprintf(buf, titles[i], ((AppleVM *)g_vm)->DiskName(i - ACT_DISK1)[0] ? "Eject" : "Insert"); sprintf(buf, titles[i], ((AppleVM *)g_vm)->DiskName(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) { } else if (i == ACT_DISPLAYTYPE) {
switch (g_displayType) { switch (g_displayType) {
case m_blackAndWhite: case m_blackAndWhite:
@ -277,9 +305,9 @@ void BIOS::DrawMainMenu(int8_t selection)
} }
if (isActionActive(i)) { 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 { } 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) { while (1) {
char fn[BIOS_MAXPATH]; char fn[BIOS_MAXPATH];
// FIXME: add po, nib int8_t idx = g_filemanager->readDir(rootPath, "dsk,.po,nib,img", fn, startNum + count, BIOS_MAXPATH);
int8_t idx = g_filemanager->readDir(rootPath, "dsk", fn, startNum + count, BIOS_MAXPATH);
if (idx == -1) { if (idx == -1) {
return count; return count;

View File

@ -10,6 +10,9 @@ DIR dir;
FILINFO fno; FILINFO fno;
FIL fil; FIL fil;
int8_t rawFd = -1;
FIL rawFil;
static TCHAR *char2tchar( const char *charString, int nn, TCHAR *output) static TCHAR *char2tchar( const char *charString, int nn, TCHAR *output)
{ {
int ii; int ii;
@ -42,6 +45,12 @@ TeensyFileManager::~TeensyFileManager()
int8_t TeensyFileManager::openFile(const char *name) 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... // See if there's a hole to re-use...
for (int i=0; i<numCached; i++) { for (int i=0; i<numCached; i++) {
if (cachedNames[i][0] == '\0') { if (cachedNames[i][0] == '\0') {
@ -68,6 +77,12 @@ int8_t TeensyFileManager::openFile(const char *name)
void TeensyFileManager::closeFile(int8_t fd) void TeensyFileManager::closeFile(int8_t fd)
{ {
// invalidate the raw file cache
if (rawFd != -1) {
f_close(&rawFil);
rawFd = -1;
}
// invalid fd provided? // invalid fd provided?
if (fd < 0 || fd >= numCached) if (fd < 0 || fd >= numCached)
return; return;
@ -136,7 +151,7 @@ int8_t TeensyFileManager::readDir(const char *where, const char *suffix, char *o
} }
p = strstr(p, ",")+1; p = strstr(p, ",")+1;
} }
if (matchesAny) if (!matchesAny)
continue; continue;
} else { } else {
// one suffix to check // 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))); 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) uint8_t TeensyFileManager::readByteAt(int8_t fd, uint32_t pos)
{ {
// open, seek, read, close. // open, seek, read, close.
@ -282,26 +327,21 @@ uint8_t TeensyFileManager::readByteAt(int8_t fd, uint32_t pos)
if (cachedNames[fd][0] == 0) if (cachedNames[fd][0] == 0)
return false; return false;
// open, seek, read, close. FRESULT rc;
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); _prepCache(fd);
rc = f_lseek(&rawFil, pos);
if (rc) { if (rc) {
Serial.println("readByteAt: seek failed"); Serial.println("readByteAt: seek failed");
f_close(&fil);
return false; return false;
} }
uint8_t b; uint8_t b;
UINT v; UINT v;
f_read(&fil, &b, 1, &v); f_read(&rawFil, &b, 1, &v);
f_close(&fil);
return (v == 1); // FIXME: check v == 1 & handle error
return b;
} }
bool TeensyFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos) 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) if (cachedNames[fd][0] == 0)
return false; return false;
// open, seek, write, close. FRESULT rc;
TCHAR buf[MAXPATH];
char2tchar(cachedNames[fd], MAXPATH, buf); _prepCache(fd);
FRESULT rc = f_open(&fil, (TCHAR*) buf, FA_WRITE);
rc = f_lseek(&fil, pos); rc = f_lseek(&rawFil, pos);
UINT ret; UINT ret;
f_write(&fil, &v, 1, &ret); f_write(&rawFil, &v, 1, &ret);
f_close(&fil);
return (ret == 1); return (ret == 1);
} }

View File

@ -23,6 +23,9 @@ class TeensyFileManager : public FileManager {
virtual uint8_t readByteAt(int8_t fd, uint32_t pos); virtual uint8_t readByteAt(int8_t fd, uint32_t pos);
virtual bool writeByteAt(int8_t fd, uint8_t v, uint32_t pos); virtual bool writeByteAt(int8_t fd, uint8_t v, uint32_t pos);
private:
bool _prepCache(int8_t fd);
private: private:
int8_t numCached; int8_t numCached;