From 197c89b772dea49100996ec4aaf6c72b7d9d7c00 Mon Sep 17 00:00:00 2001 From: Jorj Bauer Date: Wed, 20 Feb 2019 22:06:55 -0500 Subject: [PATCH] incremental cleanup and prep for dynamic track loading (instead of full track preloading) --- apple/diskii.cpp | 2 +- apple/woz.cpp | 158 ++++++++++++++++++++++------------ apple/woz.h | 12 ++- filemanager.h | 5 +- nix/nix-filemanager.cpp | 24 +++++- nix/nix-filemanager.h | 1 + physicalspeaker.h | 2 - sdl/sdl-speaker.cpp | 5 -- sdl/sdl-speaker.h | 2 - teensy/teensy-filemanager.cpp | 27 ++++++ teensy/teensy-filemanager.h | 3 + teensy/teensy-speaker.h | 2 + 12 files changed, 167 insertions(+), 76 deletions(-) diff --git a/apple/diskii.cpp b/apple/diskii.cpp index c0910d4..dcde130 100644 --- a/apple/diskii.cpp +++ b/apple/diskii.cpp @@ -395,7 +395,7 @@ void DiskII::insertDisk(int8_t driveNum, const char *filename, bool drawIt) ejectDisk(driveNum); disk[driveNum] = new WozSerializer(); - disk[driveNum]->readFile(filename); // FIXME error checking + disk[driveNum]->readFile(filename, true, T_AUTO); // FIXME error checking curWozTrack[driveNum] = disk[driveNum]->trackNumberForQuarterTrack(curHalfTrack[driveNum]*2); diff --git a/apple/woz.cpp b/apple/woz.cpp index 2f7760d..e9d95d0 100644 --- a/apple/woz.cpp +++ b/apple/woz.cpp @@ -336,10 +336,65 @@ void Woz::_initInfo() } } -bool Woz::readDskFile(const char *filename, uint8_t subtype) +bool Woz::readAndDecodeTrack(uint8_t track, int8_t fh) +{ + if (imageType == T_PO || + imageType == T_DSK) { + static uint8_t sectorData[256*16]; + + g_filemanager->setSeekPosition(fh, 256*16*track); + + 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 + return false; + } + tracks[track].startingBlock = STARTBLOCK + 13*track; + tracks[track].blockCount = 13; + uint32_t sizeInBits = nibblizeTrack(tracks[track].trackData, sectorData, imageType, track); + tracks[track].bitCount = sizeInBits; // ... reality. + + return true; + } + else if (imageType == T_NIB) { + tracks[track].trackData = (uint8_t *)malloc(NIBTRACKSIZE); + if (!tracks[track].trackData) { +#ifndef TEENSYDUINO + printf("Failed to malloc track data\n"); +#endif + return false; + } + + g_filemanager->setSeekPosition(fh, NIBTRACKSIZE * track); + for (int i=0; ireadByte(fh); + } + + tracks[track].startingBlock = STARTBLOCK + 13*track; + tracks[track].blockCount = 13; + tracks[track].bitCount = NIBTRACKSIZE*8; + + return true; + } + + printf("ERROR: need to implement WOZ support in track reader\n"); + return false; +} + +bool Woz::readDskFile(const char *filename, bool preloadTracks, uint8_t subtype) { bool retval = false; + imageType = subtype; + int8_t fh = g_filemanager->openFile(filename); if (fh == -1) { #ifndef TEENSYDUINO @@ -351,25 +406,13 @@ bool Woz::readDskFile(const char *filename, uint8_t subtype) _initInfo(); // 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++) { - 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 + if (preloadTracks) { + for (int track=0; track<35; track++) { + if (!readAndDecodeTrack(track, fh)) { goto done; } - tracks[track].startingBlock = STARTBLOCK + 13*track; - tracks[track].blockCount = 13; - uint32_t sizeInBits = nibblizeTrack(tracks[track].trackData, sectorData, subtype, track); - tracks[track].bitCount = sizeInBits; // ... reality. - } + } + } retval = true; @@ -379,47 +422,41 @@ bool Woz::readDskFile(const char *filename, uint8_t subtype) return retval; } -bool Woz::readNibFile(const char *filename) +bool Woz::readNibFile(const char *filename, bool preloadTracks) { + bool ret = false; + + imageType = T_NIB; + int8_t fh = g_filemanager->openFile(filename); if (fh == -1) { #ifndef TEENSYDUINO perror("Unable to open input file"); #endif - return false; + goto done; } _initInfo(); - // 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++) { - for (int i=0; ireadByte(fh); + if (preloadTracks) { + for (int track=0; track<35; track++) { + if (!readAndDecodeTrack(track, fh)) { + goto done; + } } - - tracks[track].trackData = (uint8_t *)calloc(NIBTRACKSIZE, 1); - if (!tracks[track].trackData) { -#ifndef TEENSYDUINO - printf("Failed to malloc track data\n"); -#endif - return false; - } - - memcpy(tracks[track].trackData, nibData, NIBTRACKSIZE); - tracks[track].startingBlock = STARTBLOCK + 13*track; - tracks[track].blockCount = 13; - tracks[track].bitCount = NIBTRACKSIZE*8; } - g_filemanager->closeFile(fh); + ret = true; - return true; + done: + if (fh != -1) + g_filemanager->closeFile(fh); + return ret; } -bool Woz::readWozFile(const char *filename) +bool Woz::readWozFile(const char *filename, bool preloadTracks) { + imageType = T_WOZ; + int8_t fh = g_filemanager->openFile(filename); if (fh == -1) { #ifndef TEENSYDUINO @@ -471,17 +508,19 @@ bool Woz::readWozFile(const char *filename) #define cTRKS 4 while (1) { - g_filemanager->setSeekPosition(fh, fpos); // FIXME: no error checking + if (!g_filemanager->setSeekPosition(fh, fpos)) + break; uint32_t chunkType; if (!read32(fh, &chunkType)) { + printf("Failed to read chunktype; breaking from loop\n"); break; } uint32_t chunkDataSize; read32(fh, &chunkDataSize); bool isOk; - + printf("reading chunk type 0x%X\n", chunkType); switch (chunkType) { case 0x4F464E49: // 'INFO' isOk = parseInfoChunk(fh, chunkDataSize); @@ -500,11 +539,10 @@ bool Woz::readWozFile(const char *filename) break; default: #ifndef TEENSYDUINO - printf("Unknown chunk type 0x%X\n", chunkType); + printf("Unknown chunk type 0x%X; failed to read woz file\n", chunkType); #endif g_filemanager->closeFile(fh); return false; - break; } if (!isOk) { @@ -525,13 +563,15 @@ bool Woz::readWozFile(const char *filename) return false; } - for (int i=0; i<35; i++) { - if (!readQuarterTrackData(fh, i*4)) { + if (preloadTracks) { + for (int i=0; i<40*4; i++) { + if (!readQuarterTrackData(fh, i)) { #ifndef TEENSYDUINO - printf("Failed to read QTD for track %d\n", i); + printf("Failed to read QTD for track %d\n", i); #endif - g_filemanager->closeFile(fh); - return false; + g_filemanager->closeFile(fh); + return false; + } } } @@ -542,7 +582,7 @@ bool Woz::readWozFile(const char *filename) return true; } -bool Woz::readFile(const char *filename, uint8_t forceType) +bool Woz::readFile(const char *filename, bool preloadTracks, uint8_t forceType) { if (forceType == T_AUTO) { // Try to determine type from the file extension @@ -575,18 +615,18 @@ bool Woz::readFile(const char *filename, uint8_t forceType) #ifndef TEENSYDUINO printf("reading woz file %s\n", filename); #endif - return readWozFile(filename); + return readWozFile(filename, preloadTracks); case T_DSK: case T_PO: #ifndef TEENSYDUINO printf("reading DSK file %s\n", filename); #endif - return readDskFile(filename, forceType); + return readDskFile(filename, preloadTracks, forceType); case T_NIB: #ifndef TEENSYDUINO printf("reading NIB file %s\n", filename); #endif - return readNibFile(filename); + return readNibFile(filename, preloadTracks); default: #ifndef TEENSYDUINO printf("Unknown disk type; unable to read\n"); @@ -598,6 +638,7 @@ bool Woz::readFile(const char *filename, uint8_t forceType) bool Woz::parseTRKSChunk(int8_t fh, uint32_t chunkSize) { if (di.version == 2) { + printf("v2 parse\n"); for (int i=0; i<160; i++) { if (!read16(fh, &tracks[i].startingBlock)) return false; @@ -610,6 +651,7 @@ bool Woz::parseTRKSChunk(int8_t fh, uint32_t chunkSize) return true; } + printf("v1 parse\n"); // V1 parsing uint32_t ptr = 0; uint8_t trackNumber = 0; @@ -740,6 +782,10 @@ bool Woz::readQuarterTrackData(int8_t fh, uint8_t quartertrack) return true; } + // assume if it's malloc'd, then we've already read it + if (tracks[targetImageTrack].trackData) + return true; + uint16_t bitsStartBlock = tracks[targetImageTrack].startingBlock; // if (tracks[targetImageTrack].trackData) diff --git a/apple/woz.h b/apple/woz.h index e457186..5fb1ddd 100644 --- a/apple/woz.h +++ b/apple/woz.h @@ -36,7 +36,7 @@ class Woz { Woz(); ~Woz(); - bool readFile(const char *filename, uint8_t forceType = T_AUTO); + bool readFile(const char *filename, bool preloadTracks, uint8_t forceType = T_AUTO); bool writeFile(uint8_t version, const char *filename); uint8_t getNextWozBit(uint8_t track); @@ -55,9 +55,9 @@ class Woz { uint8_t trackNumberForQuarterTrack(uint16_t qt); private: - bool readWozFile(const char *filename); - bool readDskFile(const char *filename, uint8_t subtype); - bool readNibFile(const char *filename); + bool readWozFile(const char *filename, bool preloadTracks); + bool readDskFile(const char *filename, bool preloadTracks, uint8_t subtype); + bool readNibFile(const char *filename, bool preloadTracks); uint8_t fakeBit(); @@ -73,9 +73,13 @@ class Woz { bool readQuarterTrackData(int8_t fh, uint8_t quartertrack); bool readSectorData(uint8_t track, uint8_t sector, nibSector *sectorData); + bool readAndDecodeTrack(uint8_t track, int8_t fh); + void _initInfo(); protected: + uint8_t imageType; + uint8_t quarterTrackMap[40*4]; diskInfo di; trackInfo tracks[160]; diff --git a/filemanager.h b/filemanager.h index 5bf9098..2147c3f 100644 --- a/filemanager.h +++ b/filemanager.h @@ -116,10 +116,7 @@ class FileManager { return fileSeekPositions[fd]; }; - virtual void setSeekPosition(int8_t fd, uint32_t pos) { - fileSeekPositions[fd] = pos; - }; - + virtual bool setSeekPosition(int8_t fd, uint32_t pos) = 0; virtual void seekToEnd(int8_t fd) = 0; protected: diff --git a/nix/nix-filemanager.cpp b/nix/nix-filemanager.cpp index 3118223..386abe0 100644 --- a/nix/nix-filemanager.cpp +++ b/nix/nix-filemanager.cpp @@ -294,7 +294,7 @@ uint8_t NixFileManager::readByteAt(int8_t fd, uint32_t pos) } if (!ret) { - printf("ERROR reading: %d\n", errno); + printf("ERROR reading byte at %u: %d\n", pos, errno); } // FIXME: error handling? @@ -372,7 +372,7 @@ uint8_t NixFileManager::readByte(int8_t fd) fileSeekPositions[fd]++; if (!ret) { - printf("ERROR reading: %d\n", errno); + printf("ERROR reading from pos %d: %d\n", pos, errno); } // FIXME: error handling? @@ -385,6 +385,26 @@ void NixFileManager::getRootPath(char *toWhere, int8_t maxLen) // strncpy(toWhere, ROOTDIR, maxLen); } +bool NixFileManager::setSeekPosition(int8_t fd, uint32_t pos) +{ + // This could be a whole lot simpler. + bool ret = false; + FILE *f = fopen(cachedNames[fd], "r"); + if (f) { + fseeko(f, 0, SEEK_END); + fileSeekPositions[fd] = ftello(f); + + if (pos < ftello(f)) { + fileSeekPositions[fd] = pos; + ret = true; + } + fclose(f); + } + + return ret; +}; + + void NixFileManager::seekToEnd(int8_t fd) { // This could just be a stat call... diff --git a/nix/nix-filemanager.h b/nix/nix-filemanager.h index c2c897f..c0b7c04 100644 --- a/nix/nix-filemanager.h +++ b/nix/nix-filemanager.h @@ -29,6 +29,7 @@ class NixFileManager : public FileManager { void getRootPath(char *toWhere, int8_t maxLen); + virtual bool setSeekPosition(int8_t fd, uint32_t pos); virtual void seekToEnd(int8_t fd); private: diff --git a/physicalspeaker.h b/physicalspeaker.h index 1967992..f59021a 100644 --- a/physicalspeaker.h +++ b/physicalspeaker.h @@ -14,8 +14,6 @@ class PhysicalSpeaker { virtual void beginMixing() = 0; virtual void mixOutput(uint8_t v) = 0; - virtual uint32_t bufferedContentSize() = 0; - }; #endif diff --git a/sdl/sdl-speaker.cpp b/sdl/sdl-speaker.cpp index f529366..a7ae0f2 100644 --- a/sdl/sdl-speaker.cpp +++ b/sdl/sdl-speaker.cpp @@ -223,8 +223,3 @@ void SDLSpeaker::beginMixing() void SDLSpeaker::mixOutput(uint8_t v) { } - -uint32_t SDLSpeaker::bufferedContentSize() -{ - return bufIdx; -} diff --git a/sdl/sdl-speaker.h b/sdl/sdl-speaker.h index 8d4010b..0318485 100644 --- a/sdl/sdl-speaker.h +++ b/sdl/sdl-speaker.h @@ -19,8 +19,6 @@ class SDLSpeaker : public PhysicalSpeaker { virtual void beginMixing(); virtual void mixOutput(uint8_t v); - virtual uint32_t bufferedContentSize(); - private: uint8_t mixerValue; bool toggleState; diff --git a/teensy/teensy-filemanager.cpp b/teensy/teensy-filemanager.cpp index ec40e6e..ec44976 100644 --- a/teensy/teensy-filemanager.cpp +++ b/teensy/teensy-filemanager.cpp @@ -394,3 +394,30 @@ void TeensyFileManager::getRootPath(char *toWhere, int8_t maxLen) strcpy(toWhere, "/A2DISKS/"); // strncpy(toWhere, "/A2DISKS/", maxLen); } + +bool TeensyFileManager::setSeekPosition(int8_t fd, uint32_t pos) +{ + seekToEnd(fd); + uint32_t endPos = getSeekPosition(fd); + if (pos >= endPos) { + return false; + } + + fileSeekPositions[fd] = pos; + return true; +} + + +void TeensyFileManager::seekToEnd(int8_t fd) +{ + File f = sd.open(cachedNames[fd], FILE_READ); + if (!f) { + Serial.println("failed to open"); + return; + } + + fileSeekPositions[fd] = f.fileSize(); + + f.close(); +} + diff --git a/teensy/teensy-filemanager.h b/teensy/teensy-filemanager.h index a2aff88..f7d5ac3 100644 --- a/teensy/teensy-filemanager.h +++ b/teensy/teensy-filemanager.h @@ -28,6 +28,9 @@ class TeensyFileManager : public FileManager { virtual bool writeByte(int8_t fd, uint8_t v); virtual void getRootPath(char *toWhere, int8_t maxLen); + + virtual bool setSeekPosition(int8_t fd, uint32_t pos); + virtual void seekToEnd(int8_t fd); private: bool _prepCache(int8_t fd); diff --git a/teensy/teensy-speaker.h b/teensy/teensy-speaker.h index f6eebab..3a9a669 100644 --- a/teensy/teensy-speaker.h +++ b/teensy/teensy-speaker.h @@ -8,6 +8,8 @@ class TeensySpeaker : public PhysicalSpeaker { TeensySpeaker(uint8_t pinNum); virtual ~TeensySpeaker(); + virtual void begin() {}; + virtual void toggle(uint32_t c); virtual void maintainSpeaker(uint32_t c, uint64_t runtimeInMicros);