X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffileio.cpp;h=d8ff4653da539e4456628739dd74596d857c43e0;hb=6618dd130b72fa3c19b7583855f227160c3384c1;hp=a70b4ca6ef8ede21b2737484534f3246b69b88d1;hpb=017d24f4c7284cee2f7c07f0f7f3c3237f92061b;p=wozmaker diff --git a/src/fileio.cpp b/src/fileio.cpp index a70b4ca..d8ff465 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -10,6 +10,8 @@ #include "fileio.h" #include #include +#include +#include "global.h" static uint32_t crcTable[256] = @@ -78,3 +80,341 @@ uint8_t * ReadFile(const char * filename, uint32_t * size) return buffer; } + +bool LoadA2R(const char * filename) +{ +/* +Really, this crap should go into fileio.cpp. !!! FIX !!! +*/ + static uint8_t a2rHdr[8] = { 0x41, 0x32, 0x52, 0x32, 0xFF, 0x0A, 0x0D, 0x0A }; + static uint8_t a2rHdr1[8] = { 0x41, 0x32, 0x52, 0x31, 0xFF, 0x0A, 0x0D, 0x0A }; + + if (Global::a2r != NULL) + free(Global::a2r); + + Global::a2r = (A2R *)ReadFile(filename, &Global::a2rSize); + + if (Global::a2r == NULL) + return false; + + // Sanity check, to see if what we asked for is what we got + if (memcmp(Global::a2r->magic1, a2rHdr, 8) != 0) + { + // It's not a v2 A2R file, maybe it's v1? + if (memcmp(Global::a2r->magic1, a2rHdr1, 8) == 0) + { + // Bytes 8-F are usually: 01 00 8D 00 A5 01 00 00 + // First, allocate mem to copy the old version to the new: + uint8_t * oldfile = (uint8_t *)Global::a2r; + uint8_t * newfile = (uint8_t *)malloc(Global::a2rSize + 36); + memcpy(newfile + 52, oldfile + 16, Global::a2rSize - 16); + + // Make sure creator is set correctly (v1 doesn't have it) + memset(Global::a2r->creator, 0x20, 32); + + // Swap in the new file, free the old one + free(Global::a2r); + Global::a2r = (A2R *)newfile; + Global::a2rSize += 36; // Add in the size of the INFO chunk + + // Fix up stuff that's different between v1 and v2 +//printf("A2R Size: %08X\n", Global::a2rSize); +//printf("A2R Stream Size: %08X (preswap)\n", Global::a2r->strmSize); + SwapBytes32((uint8_t *)&Global::a2r->strmSize); +//printf("A2R Stream Size: %08X (postswap)\n", Global::a2r->strmSize); + uint32_t dataSize = Uint32LE(Global::a2r->strmSize); + uint32_t pos = 0; + + while (pos < dataSize) + { + A2RStream * stream = (A2RStream *)(&Global::a2r->data[pos]); + + if (stream->location == 0xFF) + break; + + SwapBytes32(stream->dataLength); + SwapBytes32(stream->estLoopPoint); + pos += 10 + Uint32LE(stream->dataLength); + } + + // Change INFO to META & fix size (if any, dunno if it's optional) + if (Global::a2rSize > (60 + dataSize)) + { + memcpy(&Global::a2r->data[dataSize], "META", 4); + SwapBytes32(&Global::a2r->data[dataSize + 4]); + } + } + else + { + free(Global::a2r); + Global::a2r = NULL; + +// QMessageBox::critical(this, "Bad A2R file", "It may have an .a2r extension, but it isn't a valid A2R file."); + + return false; + } + } + + // Setup individual stream pointers + Global::numStreams = 0; + uint8_t * streamPtr = Global::a2r->data; + + while ((*streamPtr != 0xFF) && (Global::numStreams < 800)) + { + Global::stream[Global::numStreams] = (A2RStream *)streamPtr; + streamPtr += 10 + Uint32LE(Global::stream[Global::numStreams]->dataLength); + Global::numStreams++; + } + + // Metadata check + Global::metadata = NULL; + + if (Global::a2rSize > (60 + Uint32LE(Global::a2r->strmSize))) + { + Global::metadata = (Metadata *)((uint8_t *)Global::a2r + (60 + Uint32LE(Global::a2r->strmSize))); + + // Make sure it's plausible metadata + if (memcmp(Global::metadata->metaTag, "META", 4) != 0) + Global::metadata = NULL; + else + UnpackMetadata(Global::metadata); + } + + // Unpack TMNG & XTMG streams to simplify analysis + for(uint32_t i=0; icaptureType == 2) + continue; + + // We skip the first timing byte because it can't tell you what the actual time was when the pulse was seen--it's the time between when the *capture* started and the pulse was seen, not the time between the previous pulse and this one! So that first one is discarded since it's worse than useless; it's misleading. + for(uint32_t j=1; jdataLength); j++) + { + uint32_t a = Global::stream[i]->data[j]; + + while ((Global::stream[i]->data[j] == 0xFF) || (a < 24)) + { + j++; + a += Global::stream[i]->data[j]; + } + + Global::wave[i][Global::waveLen[i]] = a; + Global::waveLen[i]++; + } + } + +//ISO-8061 date format +#if 0 + char buf[200]; + time_t t = time(NULL); + tm * tmp = gmtime(&t); + strftime(buf, sizeof(buf), "%FT%TZ", tmp); + printf("Time is: %s\n", buf); +#endif + + return true; +} + + +bool WriteWOZFile(const char * filename) +{ + // See if we can actually write a file; if not, there's no need to check + // anything else + FILE * file = fopen(filename, "wb"); + + if (!file) + return false; + + // Need to come up with proper numbers here... + uint32_t numTrackBlocks = 0; + + for(uint32_t i=0; i<141; i++) + numTrackBlocks += (Global::bStreamLen[i] + 511) / 512; + + uint32_t wozSize = sizeof(WOZ2) + (numTrackBlocks * 512) + (Global::metadata != NULL ? Global::metadata->metaSize + 8 : 0); + + WOZ2 * woz = (WOZ2 *)malloc(wozSize); + + memcpy(woz->magic1, "WOZ2\xFF\x0A\x0D\x0A", 8); + + memcpy(woz->infoTag, "INFO", 4); + woz->infoSize = Uint32LE(60); + woz->infoVersion = 1; + woz->diskType = 1; + woz->writeProtected = 1; + woz->synchronized = 1; + woz->cleaned = 1; + memcpy(woz->creator, "WOZ Maker v1.0.0 ", 32); + woz->diskSides = 1; + woz->bootSectorFmt = 1; + woz->optimalBitTmg = 32; + woz->compatibleHW = Uint16LE(0); + woz->requiredRAM = Uint16LE(0); + + memcpy(woz->tmapTag, "TMAP", 4); + woz->tmapSize = Uint32LE(160); + + for(uint32_t i=0; i<141; i++) + woz->tmap[i] = (Global::bStreamLen[i] == 0 ? 0xFF : i); + + memcpy(woz->trksTag, "TRKS", 4); + woz->trksSize = Uint32LE(1280 + (numTrackBlocks * 512)); + uint16_t startBlock = 0, largestBlock = 0; + + for(uint32_t i=0; i<141; i++) + { + uint16_t blockLen = (Global::bStreamLen[i] + 511) / 512; + memset(&woz->data[startBlock * 512], 0, blockLen * 512); + memcpy(&woz->data[startBlock * 512], Global::bStream[i], Global::bStreamLen[i]); + woz->track[i].startingBlock = Uint16LE(startBlock + 3); + woz->track[i].blockCount = Uint16LE(blockLen); + woz->track[i].bitCount = Uint16LE(Global::bStreamLenBits[i]); + startBlock += blockLen; + + if (blockLen > largestBlock) + largestBlock = blockLen; + } + + woz->largestTrack = Uint16LE(largestBlock); + + if (Global::metadata != NULL) + memcpy(&woz->data[startBlock * 512], Global::metadata, Uint32LE(Global::metadata->metaSize) + 8); + + woz->crc32 = Uint32LE(CRC32(&woz->infoTag[0], wozSize - 12)); + fwrite(woz, 1, wozSize, file); + fclose(file); + + free(woz); + + return true; +} + + +void UnpackMetadata(Metadata * data) +{ + uint32_t start = 0; + uint32_t end = Uint32LE(data->metaSize); + uint32_t i = 0; + Global::metaCount = 0; + + while (start < end) + { + if (i < 255) + Global::meta[Global::metaCount][i++] = data->data[start]; + + start++; + + if (data->data[start] == '\x0A') + { + Global::meta[Global::metaCount][i] = 0; + Global::metaCount++; + i = 0; + start++; + } + } +} + + +uint8_t * GetMetadata(const char * keyword) +{ + uint32_t kwLen = strlen(keyword); + + for(uint8_t i=0; i= kwLen) + && (memcmp(Global::meta[i], keyword, kwLen) == 0)) + { + return &Global::meta[i][kwLen]; + } + } + + return NULL; +} + + +uint16_t GetRequiredMachineBits(void) +{ + uint8_t * kw = GetMetadata("requires_machine\x09"); + uint32_t kwLen = strlen((char *)kw); + uint16_t bits = 0; + char type[8]; + uint8_t typeLen = 0; + + for(uint32_t i=0; i