2 // fileio.cpp: File handling (mainly disk related)
5 // (C) 2019 Underground Software
16 uint8_t woz1Header[8] = { 'W', 'O', 'Z', '1', 0xFF, 0x0A, 0x0D, 0x0A };
17 uint8_t woz2Header[8] = { 'W', 'O', 'Z', '2', 0xFF, 0x0A, 0x0D, 0x0A };
18 uint8_t standardTMAP[160] = {
19 0, 0, 0xFF, 1, 1, 1, 0xFF, 2, 2, 2, 0xFF, 3, 3, 3, 0xFF, 4, 4, 4, 0xFF,
20 5, 5, 5, 0xFF, 6, 6, 6, 0xFF, 7, 7, 7, 0xFF, 8, 8, 8, 0xFF, 9, 9, 9, 0xFF,
21 10, 10, 10, 0xFF, 11, 11, 11, 0xFF, 12, 12, 12, 0xFF, 13, 13, 13, 0xFF,
22 14, 14, 14, 0xFF, 15, 15, 15, 0xFF, 16, 16, 16, 0xFF, 17, 17, 17, 0xFF,
23 18, 18, 18, 0xFF, 19, 19, 19, 0xFF, 20, 20, 20, 0xFF, 21, 21, 21, 0xFF,
24 22, 22, 22, 0xFF, 23, 23, 23, 0xFF, 24, 24, 24, 0xFF, 25, 25, 25, 0xFF,
25 26, 26, 26, 0xFF, 27, 27, 27, 0xFF, 28, 28, 28, 0xFF, 29, 29, 29, 0xFF,
26 30, 30, 30, 0xFF, 31, 31, 31, 0xFF, 32, 32, 32, 0xFF, 33, 33, 33, 0xFF,
27 34, 34, 34, 0xFF, 0xFF, 0xFF,
28 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
29 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
34 // sizePtr is optional
36 uint8_t * ReadFile(const char * filename, uint32_t * sizePtr/*= NULL*/)
38 FILE * fp = fopen(filename, "rb");
43 fseek(fp, 0, SEEK_END);
44 uint32_t size = ftell(fp);
45 fseek(fp, 0, SEEK_SET);
47 uint8_t * buffer = (uint8_t *)malloc(size);
48 fread(buffer, 1, size, fp);
59 // This initializes the WOZ type 2 headers
61 void InitWOZ2Headers(WOZ2 & woz)
63 // Set up header (leave CRC as 0 for now)
64 memcpy(woz.magic, woz2Header, 8);
68 memcpy(woz.infoTag, "INFO", 4);
69 woz.infoSize = Uint32LE(60);
72 woz.writeProtected = 0;
75 memset(woz.creator, ' ', 32);
76 memcpy(woz.creator, "Apple2 emulator v1.0.0", 22);
78 woz.bootSectorFmt = 1;
79 woz.optimalBitTmg = 32;
80 woz.largestTrack = Uint16LE(13);
83 memcpy(woz.tmapTag, "TMAP", 4);
84 woz.tmapSize = Uint32LE(160);
87 memcpy(woz.trksTag, "TRKS", 4);
92 // This is used mainly to initialize blank disks and upconvert non-WOZ disks
94 uint8_t * InitWOZ(uint32_t * pSize/*= NULL*/)
96 uint32_t size = 1536 + (35 * (13 * 512));
97 uint8_t * data = (uint8_t *)malloc(size);
98 WOZ2 & woz = *((WOZ2 *)data);
100 // Zero out WOZ image in memory
101 memset(&woz, 0, size);
104 InitWOZ2Headers(woz);
105 memcpy(woz.tmap, standardTMAP, 160);
106 woz.trksSize = Uint32LE(35 * (13 * 512));
108 for(int i=0; i<35; i++)
110 woz.track[i].startingBlock = Uint16LE(3 + (i * 13));
111 woz.track[i].blockCount = Uint16LE(13);
112 woz.track[i].bitCount = Uint32LE(51200);
115 // META header (how to handle? prolly with a separate pointer)
124 uint8_t * UpconvertWOZ1ToWOZ2(uint8_t * woz1Data, uint32_t woz1Size, uint32_t * newSize)
126 WOZ1 & woz1 = *((WOZ1 *)woz1Data);
128 // First, figure out how large the new structure will be in comparison to
130 uint32_t numTracks = woz1.trksSize / sizeof(WOZ1Track);
131 uint32_t metadataSize = woz1Size - (Uint32LE(woz1.trksSize) + 256);
133 // N.B.: # of blocks for each track will *always* be <= 13 for WOZ1
134 *newSize = 0x600 + (numTracks * (13 * 512)) + metadataSize;
135 uint8_t * woz2Data = (uint8_t *)malloc(*newSize);
136 memset(woz2Data, 0, *newSize);
138 WOZ2 & woz2 = *((WOZ2 *)woz2Data);
139 InitWOZ2Headers(woz2);
141 // Copy parts of INFO & TMAP chunks over
142 memcpy(&woz2.diskType, &woz1.diskType, 36);
143 memcpy(woz2.tmap, woz1.tmap, 160);
144 //note: should check the CRC32 integrity 1st before attempting to recreate it here... (the CRC is written out when it's saved anyway, so no need to fuck with this right now)
146 woz2.trksSize = Uint32LE(numTracks * (13 * 512));
148 // Finally, copy over the tracks
149 for(uint32_t i=0; i<numTracks; i++)
151 woz2.track[i].startingBlock = Uint16LE(3 + (i * 13));
152 woz2.track[i].blockCount = Uint16LE(13);
153 woz2.track[i].bitCount = woz1.track[i].bitCount;
154 memcpy(woz2Data + ((3 + (i * 13)) * 512), woz1.track[i].bits, 6646);
157 // Finally, copy over the metadata
158 memcpy(woz2Data + Uint32LE(woz2.trksSize) + 0x600,
159 woz1Data + Uint32LE(woz1.trksSize) + 0x100, metadataSize);
166 // Check WOZ type on the passed in contents (file loaded elsewhere).
167 // Returns type of WOZ if successful, 0 if not.
169 uint8_t CheckWOZType(const uint8_t * wozData, uint32_t wozSize)
171 // Basic sanity checking
172 if ((wozData == NULL) || (wozSize < 8))
175 if (memcmp(wozData, woz1Header, 8) == 0)
177 else if (memcmp(wozData, woz2Header, 8) == 0)
185 // Do basic sanity checks on the passed in contents (file loaded elsewhere).
186 // Returns true if successful, false on failure.
188 bool CheckWOZIntegrity(const uint8_t * wozData, uint32_t wozSize)
190 WOZ2 & woz = *((WOZ2 *)wozData);
191 uint32_t crc = CRC32(&wozData[12], wozSize - 12);
192 uint32_t wozCRC = Uint32LE(woz.crc32);
194 if ((wozCRC != 0) && (wozCRC != crc))
196 WriteLog("FILEIO: Corrupted data found in WOZ. CRC32: %08X, computed: %08X\n", wozCRC, crc);
199 else if (wozCRC == 0)
200 WriteLog("FILEIO: Warning--WOZ file has no CRC...\n");
202 #if 0 // Need to fix this so it works with both 1 & 2 (works with only 1 ATM)
203 WriteLog("Track map:\n");
204 WriteLog(" 1 1 1 1 1 1 1 1\n");
205 WriteLog("0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.\n");
206 WriteLog("------------------------------------------------------------------------\n");
208 for(uint8_t j=0; j<2; j++)
210 for(uint8_t i=0; i<72; i++)
213 buf[0] = buf[1] = '.';
215 if (woz.tmap[i] != 0xFF)
216 sprintf(buf, "%02d", woz.tmap[i]);
218 WriteLog("%c", buf[j]);
224 WriteLog("\n1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3\n");
225 WriteLog("8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5\n");
226 WriteLog("---------------------------------------------------------------------\n");
228 for(uint8_t j=0; j<2; j++)
230 for(uint8_t i=72; i<141; i++)
234 if (woz.tmap[i] != 0xFF)
235 sprintf(buf, "%02d", woz.tmap[i]);
237 WriteLog("%c", buf[j]);
245 uint8_t numTracks = woz.trksSize / sizeof(WOZ1Track);
247 // N.B.: Need to check the track in tmap[] to have this tell the correct track... Right now, it doesn't
248 for(uint8_t i=0; i<numTracks; i++)
250 WriteLog("WOZ: Stream %u: %d bits (packed into %d bytes)\n", i, woz.track[i].bitCount, (woz.track[i].bitCount + 7) / 8);
254 WriteLog("FILEIO: Well formed WOZ file found\n");
259 bool SaveWOZ(const char * filename, WOZ2 * woz, uint32_t size)
261 // Set up CRC32 before writing
262 woz->crc32 = Uint32LE(CRC32(woz->infoTag, size - 12));
264 // META header (skip for now) (actually, should be in the disk[] image already)
266 // Finally, write the damn image
267 FILE * file = fopen(filename, "wb");
271 WriteLog("FILEIO: Failed to open image file '%s' for writing...\n", filename);
275 fwrite((uint8_t *)woz, 1, size, file);
278 WriteLog("FILEIO: Successfully wrote image file '%s'...\n", filename);