mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-12-26 08:29:31 +00:00
woz uses built-in file management system
This commit is contained in:
parent
03b0a141bc
commit
687a096702
@ -47,7 +47,7 @@ bool DiskII::Serialize(int8_t fd)
|
||||
{
|
||||
return false;
|
||||
|
||||
// FIXME: all the new variables are missing
|
||||
// FIXME: all the new variables are missing ***
|
||||
|
||||
g_filemanager->writeByte(fd, DISKIIMAGIC);
|
||||
|
||||
@ -84,7 +84,7 @@ bool DiskII::Serialize(int8_t fd)
|
||||
bool DiskII::Deserialize(int8_t fd)
|
||||
{
|
||||
return false;
|
||||
// FIXME: all the new variables are missing
|
||||
// FIXME: all the new variables are missing ***
|
||||
|
||||
if (g_filemanager->readByte(fd) != DISKIIMAGIC) {
|
||||
return false;
|
||||
@ -167,11 +167,11 @@ uint8_t DiskII::readSwitches(uint8_t s)
|
||||
|
||||
case 0x08: // drive off
|
||||
indicatorIsOn[selectedDisk] = 99;
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, false); // FIXME: delay a bit? Queue for later drawing?
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, false); // FIXME: delay a bit? Queue for later drawing? ***
|
||||
break;
|
||||
case 0x09: // drive on
|
||||
indicatorIsOn[selectedDisk] = 100;
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, true); // FIXME: delay a bit? Queue for later drawing?
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, true); // FIXME: delay a bit? Queue for later drawing? ***
|
||||
|
||||
// Start the given disk drive spinning
|
||||
lastDiskRead[selectedDisk] = g_cpu->cycles;
|
||||
@ -186,6 +186,10 @@ uint8_t DiskII::readSwitches(uint8_t s)
|
||||
|
||||
case 0x0C: // shift one read or write byte
|
||||
readWriteLatch = readOrWriteByte();
|
||||
/*
|
||||
if (readWriteLatch & 0x80)
|
||||
printf(" => Disk II reads 0x%.2X @ $%.4X\n", sequencer, g_cpu->pc);
|
||||
*/
|
||||
if (readWriteLatch & 0x80)
|
||||
sequencer = 0;
|
||||
break;
|
||||
@ -210,9 +214,9 @@ uint8_t DiskII::readSwitches(uint8_t s)
|
||||
}
|
||||
|
||||
// FIXME: improve the spin-down here. We need a CPU cycle callback
|
||||
// for some period of time instead of this silly decrement counter.
|
||||
// for some period of time instead of this silly decrement counter ***
|
||||
if (!indicatorIsOn[selectedDisk]) {
|
||||
printf("Unexpected read while disk isn't on?\n");
|
||||
// printf("Unexpected read while disk isn't on?\n");
|
||||
indicatorIsOn[selectedDisk] = 100;
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, true); // FIXME: queue for later drawing?
|
||||
}
|
||||
@ -222,7 +226,7 @@ uint8_t DiskII::readSwitches(uint8_t s)
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, false); // FIXME: queue for later drawing?
|
||||
|
||||
// Stop the given disk drive spinning
|
||||
lastDiskRead[selectedDisk] = 0; // FIXME: magic value. We need a tristate for this.
|
||||
lastDiskRead[selectedDisk] = 0; // FIXME: magic value. We need a tristate for this. ***
|
||||
}
|
||||
|
||||
}
|
||||
@ -351,10 +355,8 @@ void DiskII::setPhase(uint8_t phase)
|
||||
|
||||
if (curHalfTrack[selectedDisk] != prevHalfTrack) {
|
||||
// We're changing track - flush the old track back to disk
|
||||
printf("track change\n");
|
||||
|
||||
curWozTrack[selectedDisk] = disk[selectedDisk]->trackNumberForQuarterTrack(curHalfTrack[selectedDisk]*2);
|
||||
printf("New half: %d; track: %d\n", curHalfTrack[selectedDisk]*2, curWozTrack[selectedDisk]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,7 +402,6 @@ void DiskII::insertDisk(int8_t driveNum, const char *filename, bool drawIt)
|
||||
disk[driveNum]->readFile(filename); // FIXME error checking
|
||||
|
||||
curWozTrack[driveNum] = disk[driveNum]->trackNumberForQuarterTrack(curHalfTrack[driveNum]*2);
|
||||
printf("Cur track: %d\n", curWozTrack[driveNum]);
|
||||
|
||||
if (drawIt)
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_state + driveNum, false);
|
||||
@ -420,8 +421,6 @@ void DiskII::select(int8_t which)
|
||||
if (which != 0 && which != 1)
|
||||
return;
|
||||
|
||||
printf("Select disk %d\n", which);
|
||||
|
||||
if (which != selectedDisk) {
|
||||
indicatorIsOn[selectedDisk] = 100; // spindown time (fixme)
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, false); // FIXME: queue for later drawing?
|
||||
@ -433,14 +432,12 @@ void DiskII::select(int8_t which)
|
||||
// Update the current woz track for the given disk drive
|
||||
curWozTrack[selectedDisk] =
|
||||
disk[selectedDisk]->trackNumberForQuarterTrack(curHalfTrack[selectedDisk]*2);
|
||||
printf("Cur Woz track is %d\n", curWozTrack[selectedDisk]);
|
||||
|
||||
}
|
||||
|
||||
uint8_t DiskII::readOrWriteByte()
|
||||
{
|
||||
if (!disk[selectedDisk]) {
|
||||
printf("reading from uninserted disk\n");
|
||||
//printf("reading from uninserted disk\n");
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
@ -35,22 +35,24 @@ const static uint8_t _trans[64] = {0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa
|
||||
0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
|
||||
0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};
|
||||
|
||||
const static uint8_t _detrans[0x80] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
|
||||
0x00, 0x00, 0x08, 0x0C, 0x00, 0x10, 0x14, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x20,
|
||||
0x00, 0x00, 0x00, 0x24, 0x28, 0x2C, 0x30, 0x34,
|
||||
0x00, 0x00, 0x38, 0x3C, 0x40, 0x44, 0x48, 0x4C,
|
||||
0x00, 0x50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x6C, 0x00, 0x70, 0x74, 0x78,
|
||||
0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x80, 0x84,
|
||||
0x00, 0x88, 0x8C, 0x90, 0x94, 0x98, 0x9C, 0xA0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA8, 0xAC,
|
||||
0x00, 0xB0, 0xB4, 0xB8, 0xBC, 0xC0, 0xC4, 0xC8,
|
||||
0x00, 0x00, 0xCC, 0xD0, 0xD4, 0xD8, 0xDC, 0xE0,
|
||||
0x00, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8, 0xFC };
|
||||
// This is the inverted DOS 3.3 RWTS Write Table (high bit
|
||||
// stripped). Any "bad" value is stored as 0xFF.
|
||||
const static uint8_t _detrans[0x80] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x04,
|
||||
0xFF, 0xFF, 0x08, 0x0C, 0xFF, 0x10, 0x14, 0x18,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0x20,
|
||||
0xFF, 0xFF, 0xFF, 0x24, 0x28, 0x2C, 0x30, 0x34,
|
||||
0xFF, 0xFF, 0x38, 0x3C, 0x40, 0x44, 0x48, 0x4C,
|
||||
0xFF, 0x50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x6C, 0xFF, 0x70, 0x74, 0x78,
|
||||
0xFF, 0xFF, 0xFF, 0x7C, 0xFF, 0xFF, 0x80, 0x84,
|
||||
0xFF, 0x88, 0x8C, 0x90, 0x94, 0x98, 0x9C, 0xA0,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA4, 0xA8, 0xAC,
|
||||
0xFF, 0xB0, 0xB4, 0xB8, 0xBC, 0xC0, 0xC4, 0xC8,
|
||||
0xFF, 0xFF, 0xCC, 0xD0, 0xD4, 0xD8, 0xDC, 0xE0,
|
||||
0xFF, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8, 0xFC };
|
||||
|
||||
// dos 3.3 to physical sector conversion
|
||||
const static uint8_t dephys[16] = {
|
||||
@ -232,6 +234,8 @@ static bool _decodeData(const uint8_t trackBuffer[343], uint8_t output[256])
|
||||
for (int i=0; i<342; i++) {
|
||||
uint8_t in = *(trackBuffer++) & 0x7F; // strip high bit
|
||||
workbuf[i] = _detrans[in];
|
||||
if (workbuf[i] == 0xFF) // bad data is untranslatable
|
||||
return false;
|
||||
}
|
||||
|
||||
// fixme: collapse this in to the previous loop
|
||||
@ -343,7 +347,7 @@ nibErr denibblizeTrack(const uint8_t input[NIBTRACKSIZE], uint8_t rawTrackBuffer
|
||||
nibData[j] = input[(i+j)%NIBTRACKSIZE];
|
||||
}
|
||||
if (!_decodeData(nibData, output)) {
|
||||
continue;
|
||||
return errorBadData;
|
||||
}
|
||||
i += 343;
|
||||
|
||||
|
369
apple/woz.cpp
369
apple/woz.cpp
@ -3,6 +3,7 @@
|
||||
#include "crc32.h"
|
||||
#include "nibutil.h"
|
||||
#include "version.h"
|
||||
#include "globals.h"
|
||||
|
||||
// Block number we start packing data bits after (Woz 2.0 images)
|
||||
#define STARTBLOCK 3
|
||||
@ -13,16 +14,16 @@
|
||||
return false; \
|
||||
if (!write32(f, 0)) \
|
||||
return false; \
|
||||
curpos = ftello(f); \
|
||||
curpos = g_filemanager->getSeekPosition(f); \
|
||||
}
|
||||
|
||||
#define END_SECTION(f) { \
|
||||
long endpos = ftello(f); \
|
||||
fseeko(f, curpos-4, SEEK_SET); \
|
||||
uint32_t endpos = g_filemanager->getSeekPosition(f); \
|
||||
g_filemanager->setSeekPosition(f, curpos-4); \
|
||||
uint32_t chunksize = endpos - curpos; \
|
||||
if (!write32(f, chunksize)) \
|
||||
return false; \
|
||||
fseeko(f, 0, SEEK_END); \
|
||||
g_filemanager->seekToEnd(f); \
|
||||
}
|
||||
|
||||
Woz::Woz()
|
||||
@ -95,49 +96,47 @@ uint8_t Woz::nextDiskByte(uint8_t track)
|
||||
return d;
|
||||
}
|
||||
|
||||
static bool write8(FILE *f, uint8_t v)
|
||||
static bool write8(uint8_t fh, uint8_t v)
|
||||
{
|
||||
if (fwrite(&v, 1, 1, f) != 1)
|
||||
if (!g_filemanager->writeByte(fh, v))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool write16(FILE *f, uint16_t v)
|
||||
static bool write16(uint8_t fh, uint16_t v)
|
||||
{
|
||||
if (!write8(f, v & 0xFF))
|
||||
if (!write8(fh, v & 0xFF))
|
||||
return false;
|
||||
v >>= 8;
|
||||
if (!write8(f, v & 0xFF))
|
||||
if (!write8(fh, v & 0xFF))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool write32(FILE *f, uint32_t v)
|
||||
static bool write32(uint8_t fh, uint32_t v)
|
||||
{
|
||||
for (int i=0; i<4; i++) {
|
||||
if (!write8(f, v&0xFF))
|
||||
if (!write8(fh, v&0xFF))
|
||||
return false;
|
||||
v >>= 8;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read8(FILE *f, uint8_t *toWhere)
|
||||
static bool read8(uint8_t fd, uint8_t *toWhere)
|
||||
{
|
||||
uint8_t r;
|
||||
if (fread(&r, 1, 1, f) != 1)
|
||||
return false;
|
||||
*toWhere = r;
|
||||
// FIXME: no error checking
|
||||
*toWhere = g_filemanager->readByte(fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read16(FILE *f, uint16_t *toWhere)
|
||||
static bool read16(uint8_t fh, uint16_t *toWhere)
|
||||
{
|
||||
uint16_t ret = 0;
|
||||
for (int i=0; i<2; i++) {
|
||||
uint8_t r;
|
||||
if (!read8(f, &r)) {
|
||||
if (!read8(fh, &r)) {
|
||||
return false;
|
||||
}
|
||||
ret >>= 8;
|
||||
@ -149,12 +148,12 @@ static bool read16(FILE *f, uint16_t *toWhere)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read32(FILE *f, uint32_t *toWhere)
|
||||
static bool read32(uint8_t fh, uint32_t *toWhere)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
for (int i=0; i<4; i++) {
|
||||
uint8_t r;
|
||||
if (!read8(f, &r)) {
|
||||
if (!read8(fh, &r)) {
|
||||
return false;
|
||||
}
|
||||
ret >>= 8;
|
||||
@ -168,7 +167,7 @@ static bool read32(FILE *f, uint32_t *toWhere)
|
||||
|
||||
bool Woz::writeFile(uint8_t version, const char *filename)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
int8_t fh = -1; // filehandle (-1 == closed)
|
||||
bool retval = false;
|
||||
uint32_t tmp32; // scratch 32-bit value
|
||||
off_t crcPos, endPos;
|
||||
@ -178,13 +177,17 @@ bool Woz::writeFile(uint8_t version, const char *filename)
|
||||
|
||||
|
||||
if (version > 2 || !version) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: version must be 1 or 2\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
f = fopen(filename, "w+");
|
||||
if (!f) {
|
||||
perror("ERROR: Unable to open output file");
|
||||
fh = g_filemanager->openFile(filename);
|
||||
if (fh==-1) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("ERROR: Unable to open output file\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -194,83 +197,102 @@ bool Woz::writeFile(uint8_t version, const char *filename)
|
||||
} else {
|
||||
tmp32 = 0x325A4F57;
|
||||
}
|
||||
if (!write32(f, tmp32)) {
|
||||
if (!write32(fh, tmp32)) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: failed to write\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
tmp32 = 0x0A0D0AFF;
|
||||
if (!write32(f, tmp32)) {
|
||||
if (!write32(fh, tmp32)) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: failed to write\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
// We'll come back and write the checksum later
|
||||
crcPos = ftello(f);
|
||||
crcPos = g_filemanager->getSeekPosition(fh);
|
||||
tmp32 = 0;
|
||||
if (!write32(f, tmp32)) {
|
||||
if (!write32(fh, tmp32)) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: failed to write\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
PREP_SECTION(f, 0x4F464E49); // 'INFO'
|
||||
if (!writeInfoChunk(version, f)) {
|
||||
PREP_SECTION(fh, 0x4F464E49); // 'INFO'
|
||||
if (!writeInfoChunk(version, fh)) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: failed to write INFO chunk\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
END_SECTION(f);
|
||||
END_SECTION(fh);
|
||||
|
||||
PREP_SECTION(f, 0x50414D54); // 'TMAP'
|
||||
if (!writeTMAPChunk(version, f)) {
|
||||
PREP_SECTION(fh, 0x50414D54); // 'TMAP'
|
||||
if (!writeTMAPChunk(version, fh)) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: failed to write TMAP chunk\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
END_SECTION(f);
|
||||
END_SECTION(fh);
|
||||
|
||||
PREP_SECTION(f, 0x534B5254); // 'TRKS'
|
||||
if (!writeTRKSChunk(version, f)) {
|
||||
PREP_SECTION(fh, 0x534B5254); // 'TRKS'
|
||||
if (!writeTRKSChunk(version, fh)) {
|
||||
fprintf(stderr, "ERROR: failed to write TRKS chunk\n");
|
||||
goto done;
|
||||
}
|
||||
END_SECTION(f);
|
||||
END_SECTION(fh);
|
||||
|
||||
// Write the metadata if we have any
|
||||
if (metaData) {
|
||||
PREP_SECTION(f, 0x4154454D); // 'META'
|
||||
if (fwrite(metaData, 1, strlen(metaData), f) != strlen(metaData)) {
|
||||
PREP_SECTION(fh, 0x4154454D); // 'META'
|
||||
for (int i=0; i<strlen(metaData); i++) {
|
||||
if (!write8(fh, metaData[i])) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: failed to write META chunk\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
END_SECTION(f);
|
||||
}
|
||||
END_SECTION(fh);
|
||||
}
|
||||
|
||||
// FIXME: missing the WRIT chunk, if it exists
|
||||
|
||||
// Fix up the checksum
|
||||
endPos = ftello(f);
|
||||
endPos = g_filemanager->getSeekPosition(fh);
|
||||
crcDataSize = endPos-crcPos-4;
|
||||
crcData = (uint8_t *)malloc(crcDataSize);
|
||||
if (!crcData) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: failed to malloc crc data chunk\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Read the data in for checksumming
|
||||
if (fseeko(f, crcPos+4, SEEK_SET)) {
|
||||
fprintf(stderr, "ERROR: failed to fseek to crcPos+4 (0x%llX)\n", crcPos+4);
|
||||
// FIXME: no error checking on seek
|
||||
g_filemanager->setSeekPosition(fh, crcPos+4);
|
||||
|
||||
for (int i=0; i<crcDataSize; i++) {
|
||||
if (!read8(fh, &crcData[i])) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: failed to read in data for checksum [read %d, wanted %d]\n", tmp32, crcDataSize);
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
tmp32 = fread(crcData, 1, crcDataSize, f);
|
||||
if (tmp32 != crcDataSize) {
|
||||
fprintf(stderr, "ERROR: failed to read in data for checksum [read %d, wanted %d]\n", tmp32, crcDataSize);
|
||||
goto done;
|
||||
}
|
||||
|
||||
tmp32 = compute_crc_32(crcData, crcDataSize);
|
||||
// Write it back out
|
||||
fseeko(f, crcPos, SEEK_SET);
|
||||
if (!write32(f, tmp32)) {
|
||||
g_filemanager->setSeekPosition(fh, crcPos);
|
||||
if (!write32(fh, tmp32)) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: failed to write CRC\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -279,8 +301,9 @@ bool Woz::writeFile(uint8_t version, const char *filename)
|
||||
done:
|
||||
if (crcData)
|
||||
free(crcData);
|
||||
if (f)
|
||||
fclose(f);
|
||||
if (fh != -1) {
|
||||
g_filemanager->closeFile(fh);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -317,9 +340,11 @@ bool Woz::readDskFile(const char *filename, uint8_t subtype)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
FILE *f = fopen(filename, "r");
|
||||
if (!f) {
|
||||
int8_t fh = g_filemanager->openFile(filename);
|
||||
if (fh == -1) {
|
||||
#ifndef TEENSYDUINO
|
||||
perror("Unable to open input file");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -328,15 +353,16 @@ bool Woz::readDskFile(const char *filename, uint8_t subtype)
|
||||
// Now read in the 35 tracks of data from the DSK file and convert them to NIB
|
||||
uint8_t sectorData[256*16];
|
||||
for (int track=0; track<35; track++) {
|
||||
uint32_t bytesRead = fread(sectorData, 1, 256*16, f);
|
||||
if (bytesRead != 256*16) {
|
||||
fprintf(stderr, "Failed to read DSK data; got %d bytes, wanted %d\n", bytesRead, 256);
|
||||
goto done;
|
||||
for (int i=0; i<256*16; i++) {
|
||||
// FIXME: no error checking
|
||||
sectorData[i] = g_filemanager->readByte(fh);
|
||||
}
|
||||
|
||||
tracks[track].trackData = (uint8_t *)calloc(NIBTRACKSIZE, 1);
|
||||
if (!tracks[track].trackData) {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "Failed to malloc track data\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
tracks[track].startingBlock = STARTBLOCK + 13*track;
|
||||
@ -348,16 +374,18 @@ bool Woz::readDskFile(const char *filename, uint8_t subtype)
|
||||
retval = true;
|
||||
|
||||
done:
|
||||
if (f)
|
||||
fclose(f);
|
||||
if (fh != -1)
|
||||
g_filemanager->closeFile(fh);
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool Woz::readNibFile(const char *filename)
|
||||
{
|
||||
FILE *f = fopen(filename, "r");
|
||||
if (!f) {
|
||||
int8_t fh = g_filemanager->openFile(filename);
|
||||
if (fh == -1) {
|
||||
#ifndef TEENSYDUINO
|
||||
perror("Unable to open input file");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -365,16 +393,18 @@ bool Woz::readNibFile(const char *filename)
|
||||
|
||||
// Now read in the 35 tracks of data from the nib file
|
||||
nibSector nibData[16];
|
||||
uint8_t *nibDataPtr = (uint8_t *)nibData;
|
||||
for (int track=0; track<35; track++) {
|
||||
uint32_t bytesRead = fread(nibData, 1, NIBTRACKSIZE, f);
|
||||
if (bytesRead != NIBTRACKSIZE) {
|
||||
printf("Failed to read NIB data; got %d bytes, wanted %d\n", bytesRead, NIBTRACKSIZE);
|
||||
return false;
|
||||
for (int i=0; i<NIBTRACKSIZE; i++) {
|
||||
// FIXME: no error checking
|
||||
nibDataPtr[i] = g_filemanager->readByte(fh);
|
||||
}
|
||||
|
||||
tracks[track].trackData = (uint8_t *)calloc(NIBTRACKSIZE, 1);
|
||||
if (!tracks[track].trackData) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Failed to malloc track data\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -383,43 +413,53 @@ bool Woz::readNibFile(const char *filename)
|
||||
tracks[track].blockCount = 13;
|
||||
tracks[track].bitCount = NIBTRACKSIZE*8;
|
||||
}
|
||||
fclose(f);
|
||||
g_filemanager->closeFile(fh);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Woz::readWozFile(const char *filename)
|
||||
{
|
||||
FILE *f = fopen(filename, "r");
|
||||
if (!f) {
|
||||
int8_t fh = g_filemanager->openFile(filename);
|
||||
if (fh == -1) {
|
||||
#ifndef TEENSYDUINO
|
||||
perror("Unable to open input file");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// Header
|
||||
uint32_t h;
|
||||
read32(f, &h);
|
||||
read32(fh, &h);
|
||||
if (h == 0x325A4F57 || h == 0x315A4F57) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("WOZ%c disk image\n", (h & 0xFF000000)>>24);
|
||||
#endif
|
||||
} else {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Unknown disk image type; can't continue\n");
|
||||
fclose(f);
|
||||
#endif
|
||||
g_filemanager->closeFile(fh);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t tmp;
|
||||
if (!read32(f, &tmp)) {
|
||||
if (!read32(fh, &tmp)) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Read failure\n");
|
||||
fclose(f);
|
||||
#endif
|
||||
g_filemanager->closeFile(fh);
|
||||
return false;
|
||||
}
|
||||
if (tmp != 0x0A0D0AFF) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("WOZ header failure; exiting\n");
|
||||
fclose(f);
|
||||
#endif
|
||||
g_filemanager->closeFile(fh);
|
||||
return false;
|
||||
}
|
||||
uint32_t crc32;
|
||||
read32(f, &crc32);
|
||||
read32(fh, &crc32);
|
||||
// printf("Disk crc32 should be 0x%X\n", crc32);
|
||||
// FIXME: check CRC. Remember that 0x00 means "don't check CRC"
|
||||
|
||||
@ -431,45 +471,47 @@ bool Woz::readWozFile(const char *filename)
|
||||
#define cTRKS 4
|
||||
|
||||
while (1) {
|
||||
if (fseeko(f, fpos, SEEK_SET)) {
|
||||
break;
|
||||
}
|
||||
g_filemanager->setSeekPosition(fh, fpos); // FIXME: no error checking
|
||||
|
||||
uint32_t chunkType;
|
||||
if (!read32(f, &chunkType)) {
|
||||
if (!read32(fh, &chunkType)) {
|
||||
break;
|
||||
}
|
||||
uint32_t chunkDataSize;
|
||||
read32(f, &chunkDataSize);
|
||||
read32(fh, &chunkDataSize);
|
||||
|
||||
bool isOk;
|
||||
|
||||
switch (chunkType) {
|
||||
case 0x4F464E49: // 'INFO'
|
||||
isOk = parseInfoChunk(f, chunkDataSize);
|
||||
isOk = parseInfoChunk(fh, chunkDataSize);
|
||||
haveData |= cINFO;
|
||||
break;
|
||||
case 0x50414D54: // 'TMAP'
|
||||
isOk = parseTMAPChunk(f, chunkDataSize);
|
||||
isOk = parseTMAPChunk(fh, chunkDataSize);
|
||||
haveData |= cTMAP;
|
||||
break;
|
||||
case 0x534B5254: // 'TRKS'
|
||||
isOk = parseTRKSChunk(f, chunkDataSize);
|
||||
isOk = parseTRKSChunk(fh, chunkDataSize);
|
||||
haveData |= cTRKS;
|
||||
break;
|
||||
case 0x4154454D: // 'META'
|
||||
isOk = parseMetaChunk(f, chunkDataSize);
|
||||
isOk = parseMetaChunk(fh, chunkDataSize);
|
||||
break;
|
||||
default:
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Unknown chunk type 0x%X\n", chunkType);
|
||||
fclose(f);
|
||||
#endif
|
||||
g_filemanager->closeFile(fh);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isOk) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Chunk parsing [0x%X] failed; exiting\n", chunkType);
|
||||
fclose(f);
|
||||
#endif
|
||||
g_filemanager->closeFile(fh);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -477,20 +519,26 @@ bool Woz::readWozFile(const char *filename)
|
||||
}
|
||||
|
||||
if (haveData != 0x07) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("ERROR: missing one or more critical sections\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i=0; i<35; i++) {
|
||||
if (!readQuarterTrackData(f, i*4)) {
|
||||
if (!readQuarterTrackData(fh, i*4)) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Failed to read QTD for track %d\n", i);
|
||||
fclose(f);
|
||||
#endif
|
||||
g_filemanager->closeFile(fh);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
g_filemanager->closeFile(fh);
|
||||
#ifndef TEENSYDUINO
|
||||
printf("File read successful\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -500,7 +548,9 @@ bool Woz::readFile(const char *filename, uint8_t forceType)
|
||||
// Try to determine type from the file extension
|
||||
const char *p = strrchr(filename, '.');
|
||||
if (!p) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Unable to determine file type of '%s'\n", filename);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if (strcasecmp(p, ".woz") == 0) {
|
||||
@ -513,37 +563,47 @@ bool Woz::readFile(const char *filename, uint8_t forceType)
|
||||
} else if (strcasecmp(p, ".nib") == 0) {
|
||||
forceType = T_NIB;
|
||||
} else {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Unable to determine file type of '%s'\n", filename);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (forceType) {
|
||||
case T_WOZ:
|
||||
#ifndef TEENSYDUINO
|
||||
printf("reading woz file %s\n", filename);
|
||||
#endif
|
||||
return readWozFile(filename);
|
||||
case T_DSK:
|
||||
case T_PO:
|
||||
#ifndef TEENSYDUINO
|
||||
printf("reading DSK file %s\n", filename);
|
||||
#endif
|
||||
return readDskFile(filename, forceType);
|
||||
case T_NIB:
|
||||
#ifndef TEENSYDUINO
|
||||
printf("reading NIB file %s\n", filename);
|
||||
#endif
|
||||
return readNibFile(filename);
|
||||
default:
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Unknown disk type; unable to read\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Woz::parseTRKSChunk(FILE *f, uint32_t chunkSize)
|
||||
bool Woz::parseTRKSChunk(int8_t fh, uint32_t chunkSize)
|
||||
{
|
||||
if (di.version == 2) {
|
||||
for (int i=0; i<160; i++) {
|
||||
if (!read16(f, &tracks[i].startingBlock))
|
||||
if (!read16(fh, &tracks[i].startingBlock))
|
||||
return false;
|
||||
if (!read16(f, &tracks[i].blockCount))
|
||||
if (!read16(fh, &tracks[i].blockCount))
|
||||
return false;
|
||||
if (!read32(f, &tracks[i].bitCount))
|
||||
if (!read32(fh, &tracks[i].bitCount))
|
||||
return false;
|
||||
tracks[i].startingByte = 0; // v1-specific
|
||||
}
|
||||
@ -557,9 +617,9 @@ bool Woz::parseTRKSChunk(FILE *f, uint32_t chunkSize)
|
||||
tracks[trackNumber].startingByte = trackNumber * 6656 + 256;
|
||||
tracks[trackNumber].startingBlock = 0; // v2-specific
|
||||
tracks[trackNumber].blockCount = 13;
|
||||
fseeko(f, (trackNumber * 6656 + 256) + 6648, SEEK_SET);
|
||||
g_filemanager->setSeekPosition(fh, (trackNumber * 6656 + 256) + 6648); // FIXME: no error checking
|
||||
uint16_t numBits;
|
||||
if (!read16(f, &numBits)) {
|
||||
if (!read16(fh, &numBits)) {
|
||||
return false;
|
||||
}
|
||||
tracks[trackNumber].bitCount = numBits;
|
||||
@ -570,15 +630,17 @@ bool Woz::parseTRKSChunk(FILE *f, uint32_t chunkSize)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Woz::parseTMAPChunk(FILE *f, uint32_t chunkSize)
|
||||
bool Woz::parseTMAPChunk(int8_t fh, uint32_t chunkSize)
|
||||
{
|
||||
if (chunkSize != 0xa0) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("TMAP chunk is the wrong size; aborting\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i=0; i<40*4; i++) {
|
||||
if (!read8(f, (uint8_t *)&quarterTrackMap[i]))
|
||||
if (!read8(fh, (uint8_t *)&quarterTrackMap[i]))
|
||||
return false;
|
||||
chunkSize--;
|
||||
}
|
||||
@ -587,54 +649,60 @@ bool Woz::parseTMAPChunk(FILE *f, uint32_t chunkSize)
|
||||
}
|
||||
|
||||
// return true if successful
|
||||
bool Woz::parseInfoChunk(FILE *f, uint32_t chunkSize)
|
||||
bool Woz::parseInfoChunk(int8_t fh, uint32_t chunkSize)
|
||||
{
|
||||
if (chunkSize != 60) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("INFO chunk size is not 60; aborting\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!read8(f, &di.version))
|
||||
if (!read8(fh, &di.version))
|
||||
return false;
|
||||
if (di.version > 2) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Incorrect version header; aborting\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!read8(f, &di.diskType))
|
||||
if (!read8(fh, &di.diskType))
|
||||
return false;
|
||||
if (di.diskType != 1) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("Not a 5.25\" disk image; aborting\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!read8(f, &di.writeProtected))
|
||||
if (!read8(fh, &di.writeProtected))
|
||||
return false;
|
||||
|
||||
if (!read8(f, &di.synchronized))
|
||||
if (!read8(fh, &di.synchronized))
|
||||
return false;
|
||||
|
||||
if (!read8(f, &di.cleaned))
|
||||
if (!read8(fh, &di.cleaned))
|
||||
return false;
|
||||
|
||||
di.creator[32] = 0;
|
||||
for (int i=0; i<32; i++) {
|
||||
if (!read8(f, (uint8_t *)&di.creator[i]))
|
||||
if (!read8(fh, (uint8_t *)&di.creator[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (di.version >= 2) {
|
||||
if (!read8(f, &di.diskSides))
|
||||
if (!read8(fh, &di.diskSides))
|
||||
return false;
|
||||
if (!read8(f, &di.bootSectorFormat))
|
||||
if (!read8(fh, &di.bootSectorFormat))
|
||||
return false;
|
||||
if (!read8(f, &di.optimalBitTiming))
|
||||
if (!read8(fh, &di.optimalBitTiming))
|
||||
return false;
|
||||
if (!read16(f, &di.compatHardware))
|
||||
if (!read16(fh, &di.compatHardware))
|
||||
return false;
|
||||
if (!read16(f, &di.requiredRam))
|
||||
if (!read16(fh, &di.requiredRam))
|
||||
return false;
|
||||
if (!read16(f, &di.largestTrack))
|
||||
if (!read16(fh, &di.largestTrack))
|
||||
return false;
|
||||
} else {
|
||||
di.diskSides = 0;
|
||||
@ -649,21 +717,22 @@ bool Woz::parseInfoChunk(FILE *f, uint32_t chunkSize)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Woz::parseMetaChunk(FILE *f, uint32_t chunkSize)
|
||||
bool Woz::parseMetaChunk(int8_t fh, uint32_t chunkSize)
|
||||
{
|
||||
metaData = (char *)calloc(chunkSize+1, 1);
|
||||
if (!metaData)
|
||||
return false;
|
||||
|
||||
if (fread(metaData, 1, chunkSize, f) != chunkSize)
|
||||
return false;
|
||||
for (int i=0; i<chunkSize; i++) {
|
||||
metaData[i] = g_filemanager->readByte(fh); // FIXME: no error checking
|
||||
}
|
||||
|
||||
metaData[chunkSize] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Woz::readQuarterTrackData(FILE *f, uint8_t quartertrack)
|
||||
bool Woz::readQuarterTrackData(int8_t fh, uint8_t quartertrack)
|
||||
{
|
||||
uint8_t targetImageTrack = quarterTrackMap[quartertrack];
|
||||
if (targetImageTrack == 0xFF) {
|
||||
@ -681,25 +750,20 @@ bool Woz::readQuarterTrackData(FILE *f, uint8_t quartertrack)
|
||||
if (di.version == 1) count = (tracks[targetImageTrack].bitCount / 8) + ((tracks[targetImageTrack].bitCount % 8) ? 1 : 0);
|
||||
tracks[targetImageTrack].trackData = (uint8_t *)calloc(count, 1);
|
||||
if (!tracks[targetImageTrack].trackData) {
|
||||
#ifndef TEENSYDUINO
|
||||
perror("Failed to alloc buf to read track magnetic data");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (di.version == 1) {
|
||||
if (fseeko(f, tracks[targetImageTrack].startingByte, SEEK_SET)) {
|
||||
perror("Failed to seek to start of block");
|
||||
return false;
|
||||
}
|
||||
g_filemanager->setSeekPosition(fh, tracks[targetImageTrack].startingByte); // FIXME: no error checking
|
||||
} else {
|
||||
if (fseeko(f, bitsStartBlock*512, SEEK_SET)) {
|
||||
perror("Failed to seek to start of block");
|
||||
return false;
|
||||
g_filemanager->setSeekPosition(fh, bitsStartBlock*512); // FIXME: no error checking
|
||||
}
|
||||
}
|
||||
uint32_t didRead = fread(tracks[targetImageTrack].trackData, 1, count, f);
|
||||
if (didRead != count) {
|
||||
printf("Failed to read all track data for track [read %d, wanted %d]\n", didRead, count);
|
||||
return false;
|
||||
for (int i=0; i<count; i++) {
|
||||
// FIXME: no error checking
|
||||
tracks[targetImageTrack].trackData[i] = g_filemanager->readByte(fh);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -781,17 +845,17 @@ bool Woz::readSectorData(uint8_t track, uint8_t sector, nibSector *sectorData)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Woz::writeInfoChunk(uint8_t version, FILE *f)
|
||||
bool Woz::writeInfoChunk(uint8_t version, int8_t fh)
|
||||
{
|
||||
if (!write8(f, version) ||
|
||||
!write8(f, di.diskType) ||
|
||||
!write8(f, di.writeProtected) ||
|
||||
!write8(f, di.synchronized) ||
|
||||
!write8(f, di.cleaned))
|
||||
if (!write8(fh, version) ||
|
||||
!write8(fh, di.diskType) ||
|
||||
!write8(fh, di.writeProtected) ||
|
||||
!write8(fh, di.synchronized) ||
|
||||
!write8(fh, di.cleaned))
|
||||
return false;
|
||||
|
||||
for (int i=0; i<32; i++) {
|
||||
if (!write8(f, di.creator[i]))
|
||||
if (!write8(fh, di.creator[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -800,37 +864,39 @@ bool Woz::writeInfoChunk(uint8_t version, FILE *f)
|
||||
if (di.diskSides == 0)
|
||||
di.diskSides = 1;
|
||||
|
||||
if ( !write8(f, di.diskSides) ||
|
||||
!write8(f, di.bootSectorFormat) ||
|
||||
!write8(f, di.optimalBitTiming) ||
|
||||
!write16(f, di.compatHardware) ||
|
||||
!write16(f, di.requiredRam) ||
|
||||
!write16(f, di.largestTrack))
|
||||
if ( !write8(fh, di.diskSides) ||
|
||||
!write8(fh, di.bootSectorFormat) ||
|
||||
!write8(fh, di.optimalBitTiming) ||
|
||||
!write16(fh, di.compatHardware) ||
|
||||
!write16(fh, di.requiredRam) ||
|
||||
!write16(fh, di.largestTrack))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Padding
|
||||
for (int i=0; i<((version==1)?23:14); i++) {
|
||||
if (!write8(f, 0))
|
||||
if (!write8(fh, 0))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Woz::writeTMAPChunk(uint8_t version, FILE *f)
|
||||
bool Woz::writeTMAPChunk(uint8_t version, int8_t fh)
|
||||
{
|
||||
for (int i=0; i<40*4; i++) {
|
||||
if (!write8(f, quarterTrackMap[i]))
|
||||
if (!write8(fh, quarterTrackMap[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Woz::writeTRKSChunk(uint8_t version, FILE *f)
|
||||
bool Woz::writeTRKSChunk(uint8_t version, int8_t fh)
|
||||
{
|
||||
if (version == 1) {
|
||||
#ifndef TEENSYDUINO
|
||||
printf("V1 write is not implemented\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -851,11 +917,11 @@ bool Woz::writeTRKSChunk(uint8_t version, FILE *f)
|
||||
tracks[i].bitCount = 0;
|
||||
}
|
||||
|
||||
if (!write16(f, tracks[i].startingBlock))
|
||||
if (!write16(fh, tracks[i].startingBlock))
|
||||
return false;
|
||||
if (!write16(f, tracks[i].blockCount))
|
||||
if (!write16(fh, tracks[i].blockCount))
|
||||
return false;
|
||||
if (!write32(f, tracks[i].bitCount))
|
||||
if (!write32(fh, tracks[i].bitCount))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -863,13 +929,16 @@ bool Woz::writeTRKSChunk(uint8_t version, FILE *f)
|
||||
for (int i=0; i<160; i++) {
|
||||
if (tracks[i].startingBlock &&
|
||||
tracks[i].blockCount) {
|
||||
fseeko(f, tracks[i].startingBlock * 512, SEEK_SET);
|
||||
g_filemanager->setSeekPosition(fh, tracks[i].startingBlock*512); // FIXME: no error checking
|
||||
uint32_t writeSize = (tracks[i].bitCount / 8) + ((tracks[i].bitCount % 8) ? 1 : 0);
|
||||
if (fwrite(tracks[i].trackData, 1, writeSize, f) != writeSize)
|
||||
for (int j=0; j<writeSize; j++) {
|
||||
if (!g_filemanager->writeByte(fh, tracks[i].trackData[j])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
uint8_t c = 0;
|
||||
while (writeSize < tracks[i].blockCount * 512) {
|
||||
if (fwrite(&c, 1, 1, f) != 1)
|
||||
if (!write8(fh, c))
|
||||
return false;
|
||||
writeSize++;
|
||||
}
|
||||
@ -902,6 +971,7 @@ bool Woz::decodeWozTrackToDsk(uint8_t track, uint8_t subtype, uint8_t sectorData
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef TEENSYDUINO
|
||||
void Woz::dumpInfo()
|
||||
{
|
||||
printf("WOZ image version %d\n", di.version);
|
||||
@ -1074,6 +1144,7 @@ void Woz::dumpInfo()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Woz::isSynchronized()
|
||||
{
|
||||
|
18
apple/woz.h
18
apple/woz.h
@ -46,7 +46,9 @@ class Woz {
|
||||
bool decodeWozTrackToNib(uint8_t track, nibSector sectorData[16]);
|
||||
bool decodeWozTrackToDsk(uint8_t track, uint8_t subtype, uint8_t sectorData[256*16]);
|
||||
|
||||
#ifndef TEENSYDUINO
|
||||
void dumpInfo();
|
||||
#endif
|
||||
|
||||
bool isSynchronized();
|
||||
|
||||
@ -59,16 +61,16 @@ class Woz {
|
||||
|
||||
uint8_t fakeBit();
|
||||
|
||||
bool parseTRKSChunk(FILE *f, uint32_t chunkSize);
|
||||
bool parseTMAPChunk(FILE *f, uint32_t chunkSize);
|
||||
bool parseInfoChunk(FILE *f, uint32_t chunkSize);
|
||||
bool parseMetaChunk(FILE *f, uint32_t chunkSize);
|
||||
bool parseTRKSChunk(int8_t fh, uint32_t chunkSize);
|
||||
bool parseTMAPChunk(int8_t fh, uint32_t chunkSize);
|
||||
bool parseInfoChunk(int8_t fh, uint32_t chunkSize);
|
||||
bool parseMetaChunk(int8_t fh, uint32_t chunkSize);
|
||||
|
||||
bool writeInfoChunk(uint8_t version, FILE *f);
|
||||
bool writeTMAPChunk(uint8_t version, FILE *f);
|
||||
bool writeTRKSChunk(uint8_t version, FILE *f);
|
||||
bool writeInfoChunk(uint8_t version, int8_t fh);
|
||||
bool writeTMAPChunk(uint8_t version, int8_t fh);
|
||||
bool writeTRKSChunk(uint8_t version, int8_t fh);
|
||||
|
||||
bool readQuarterTrackData(FILE *f, uint8_t quartertrack);
|
||||
bool readQuarterTrackData(int8_t fh, uint8_t quartertrack);
|
||||
bool readSectorData(uint8_t track, uint8_t sector, nibSector *sectorData);
|
||||
|
||||
void _initInfo();
|
||||
|
37
cpu.cpp
37
cpu.cpp
@ -9,6 +9,13 @@
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
// define DEBUGSTEPS to show disassembly of each instruction as it's processed
|
||||
//#define DEBUGSTEPS
|
||||
#ifdef DEBUGSTEPS
|
||||
#include "disassembler.h"
|
||||
extern Disassembler dis;
|
||||
#endif
|
||||
|
||||
// To see calls to unimplemented opcodes, define this:
|
||||
//#define VERBOSE_CPU_ERRORS
|
||||
|
||||
@ -487,6 +494,36 @@ uint8_t Cpu::step()
|
||||
irq();
|
||||
}
|
||||
|
||||
#ifdef DEBUGSTEPS
|
||||
static uint8_t cmdbuf[10];
|
||||
static char buf[50];
|
||||
|
||||
uint16_t loc=g_cpu->pc;
|
||||
for (int idx=0; idx<sizeof(cmdbuf); idx++) {
|
||||
cmdbuf[idx] = g_vm->getMMU()->read(loc+idx);
|
||||
}
|
||||
dis.instructionToMnemonic(loc, cmdbuf, buf, sizeof(buf));
|
||||
while (strlen(buf) < 25) {
|
||||
strcat(buf, " ");
|
||||
}
|
||||
printf("%s ;", buf);
|
||||
|
||||
uint8_t p = g_cpu->flags;
|
||||
printf("BS/BT: %02x/%02x A: %02x X: %02x Y: %02x SP: %02x Flags: %c%cx%c%c%c%c%c\n",
|
||||
g_vm->getMMU()->read(0x3D),
|
||||
g_vm->getMMU()->read(0x41),
|
||||
g_cpu->a, g_cpu->x, g_cpu->y, g_cpu->sp,
|
||||
p & (1<<7) ? 'N':' ',
|
||||
p & (1<<6) ? 'V':' ',
|
||||
p & (1<<4) ? 'B':' ',
|
||||
p & (1<<3) ? 'D':' ',
|
||||
p & (1<<2) ? 'I':' ',
|
||||
p & (1<<1) ? 'Z':' ',
|
||||
p & (1<<0) ? 'C':' '
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
uint8_t m = readmem(pc++);
|
||||
|
||||
optype_t opcode = opcodes[m];
|
||||
|
@ -112,6 +112,16 @@ class FileManager {
|
||||
|
||||
virtual void getRootPath(char *toWhere, int8_t maxLen) = 0;
|
||||
|
||||
virtual uint32_t getSeekPosition(int8_t fd) {
|
||||
return fileSeekPositions[fd];
|
||||
};
|
||||
|
||||
virtual void setSeekPosition(int8_t fd, uint32_t pos) {
|
||||
fileSeekPositions[fd] = pos;
|
||||
};
|
||||
|
||||
virtual void seekToEnd(int8_t fd) = 0;
|
||||
|
||||
protected:
|
||||
unsigned long fileSeekPositions[MAXFILES];
|
||||
char cachedNames[MAXFILES][MAXPATH];
|
||||
|
@ -384,3 +384,14 @@ void NixFileManager::getRootPath(char *toWhere, int8_t maxLen)
|
||||
strcpy(toWhere, ROOTDIR);
|
||||
// strncpy(toWhere, ROOTDIR, maxLen);
|
||||
}
|
||||
|
||||
void NixFileManager::seekToEnd(int8_t fd)
|
||||
{
|
||||
// This could just be a stat call...
|
||||
FILE *f = fopen(cachedNames[fd], "r");
|
||||
if (f) {
|
||||
fseeko(f, 0, SEEK_END);
|
||||
fileSeekPositions[fd] = ftello(f);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ class NixFileManager : public FileManager {
|
||||
|
||||
void getRootPath(char *toWhere, int8_t maxLen);
|
||||
|
||||
virtual void seekToEnd(int8_t fd);
|
||||
|
||||
private:
|
||||
int8_t numCached;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user