int G64Archive::getStartOfItem(int n) { if (n < 0 || n >= 84) return -1; int offset = 0x00C + (4 * n); return LO_LO_HI_HI(data[offset], data[offset+1], data[offset+2], data[offset+3]); }
void T64File::seekItem(long offset) { size_t i = 0x48 + (selectedItem * 0x20); // Move file pointer the the start of the selected item + offset iFp = LO_LO_HI_HI(data[i], data[i+1], data[i+2], data[i+3]) + offset; // Invalidate file pointer if it is out of range if (iFp > size) iFp = -1; }
bool TAPFile::readFromBuffer(const uint8_t *buffer, size_t length) { if (!AnyC64File::readFromBuffer(buffer, length)) return false; int l = LO_LO_HI_HI(data[0x10], data[0x11], data[0x12], data[0x13]); if (l + 0x14 /* Header */ != size) { warn("Size mismatch! Archive should have %d data bytes, found %d\n", l, size - 0x14); } return true; }
void T64Archive::selectItem(int n) { unsigned i; if (n < getNumberOfItems()) { // Compute start address in container i = 0x48 + (n * 0x20); if ((fp = LO_LO_HI_HI(data[i], data[i+1], data[i+2], data[i+3])) >= size) fprintf(stderr, "PANIC! fp is out of bounds!\n"); // Compute start address in memory i = 0x42 + (n * 0x20); uint16_t startAddrInMemory = LO_HI(data[i], data[i+1]); // Compute end address in memory i = 0x44 + (n * 0x20); uint16_t endAddrInMemory = LO_HI(data[i], data[i+1]); if (endAddrInMemory == 0xC3C6) { fprintf(stderr, "WARNING: Corrupted archive. Mostly likely created with CONV64!\n"); // WHAT DO WE DO ABOUT IT? } // Compute size of item uint16_t length = endAddrInMemory - startAddrInMemory; // fprintf(stderr, "start = %d end = %d diff = %d\n", startAddrInMemory, endAddrInMemory, length); // fprintf(stderr, "fp = %d fp_eof = %d\n", fp, fp_eof); // Store largest offset that belongs to the file if ((fp_eof = fp + length) > size) fprintf(stderr, "PANIC! fp_eof is out of bounds!\n"); // Return if offset values are safe if (fp < size && fp_eof <= size) return; // success } fp = fp_eof = -1; // fail return; }
int Datasette::pulseLength(int *skip) { assert(head < size); if (data[head] != 0) { // Pulse lengths between 1 * 8 and 255 * 8 if (skip) *skip = 1; return 8 * data[head]; } if (type == 0) { // Pulse lengths greater than 8 * 255 (TAP V0 files) if (skip) *skip = 1; return 8 * 256; } else { // Pulse lengths greater than 8 * 255 (TAP V1 files) if (skip) *skip = 4; return LO_LO_HI_HI(data[head+1], data[head+2], data[head+3], 0); } }
void T64File::selectItem(unsigned item) { // Invalidate the file pointer if a non-existing item is requested. if (item >= numberOfItems()) { iFp = -1; return; } // Remember the selection selectedItem = item; // Set file pointer and end of file index unsigned i = 0x48 + (item * 0x20); iFp = LO_LO_HI_HI(data[i], data[i+1], data[i+2], data[i+3]); iEof = iFp + getSizeOfItem(); // Check for inconsistent values. As all inconsistencies should have // been ruled out by repair(), the if condition should never hit. if (iFp > size || iEof > size) { assert(false); } }
bool T64File::repair() { unsigned i, n; uint16_t noOfItems = numberOfItems(); // // 1. Repair number of items, if this value is zero // if (noOfItems == 0) { while (directoryItemIsPresent(noOfItems)) noOfItems++; uint16_t noOfItemsStatedInHeader = numberOfItems(); if (noOfItems != noOfItemsStatedInHeader) { debug(1, "Repairing corrupted T64 archive: Changing number of items from %d to %d.\n", noOfItemsStatedInHeader, noOfItems); data[0x24] = LO_BYTE(noOfItems); data[0x25] = HI_BYTE(noOfItems); } assert(noOfItems == numberOfItems()); } for (i = 0; i < noOfItems; i++) { // // 2. Check relative offset information for each item // // Compute start address in file n = 0x48 + (i * 0x20); uint16_t startAddrInContainer = LO_LO_HI_HI(data[n], data[n+1], data[n+2], data[n+3]); if (startAddrInContainer >= size) { warn("T64 archive is corrupt (offset mismatch). Sorry, can't repair.\n"); return false; } // // 3. Check for file end address mismatches (as created by CONVC64) // // Compute start address in memory n = 0x42 + (i * 0x20); uint16_t startAddrInMemory = LO_HI(data[n], data[n+1]); // Compute end address in memory n = 0x44 + (i * 0x20); uint16_t endAddrInMemory = LO_HI(data[n], data[n+1]); if (endAddrInMemory == 0xC3C6) { // Let's assume that the rest of the file data belongs to this file ... uint16_t fixedEndAddrInMemory = startAddrInMemory + (size - startAddrInContainer); debug(1, "Repairing corrupted T64 archive: Changing end address of item %d from %04X to %04X.\n", i, endAddrInMemory, fixedEndAddrInMemory); data[n] = LO_BYTE(fixedEndAddrInMemory); data[n+1] = HI_BYTE(fixedEndAddrInMemory); } } return 1; // Archive repaired successfully }