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*/, uint32_t skip/*= 0*/)
38 FILE * fp = fopen(filename, "rb");
43 fseek(fp, 0, SEEK_END);
44 uint32_t size = ftell(fp);
45 fseek(fp, 0, SEEK_SET);
49 fseek(fp, skip, SEEK_CUR);
53 uint8_t * buffer = (uint8_t *)malloc(size);
54 fread(buffer, 1, size, fp);
65 // This initializes the WOZ type 2 headers
67 void InitWOZ2Headers(WOZ2 & woz)
69 // Set up header (leave CRC as 0 for now)
70 memcpy(woz.magic, woz2Header, 8);
74 memcpy(woz.infoTag, "INFO", 4);
75 woz.infoSize = Uint32LE(60);
78 woz.writeProtected = 0;
81 memset(woz.creator, ' ', 32);
82 memcpy(woz.creator, "Apple2 emulator v1.0.0", 22);
84 woz.bootSectorFmt = 1;
85 woz.optimalBitTmg = 32;
86 woz.largestTrack = Uint16LE(13);
89 memcpy(woz.tmapTag, "TMAP", 4);
90 woz.tmapSize = Uint32LE(160);
93 memcpy(woz.trksTag, "TRKS", 4);
98 // This is used mainly to initialize blank disks and upconvert non-WOZ disks
100 uint8_t * InitWOZ(uint32_t * pSize/*= NULL*/)
102 uint32_t size = 1536 + (35 * (13 * 512));
103 uint8_t * data = (uint8_t *)malloc(size);
104 WOZ2 & woz = *((WOZ2 *)data);
106 // Zero out WOZ image in memory
107 memset(&woz, 0, size);
110 InitWOZ2Headers(woz);
111 memcpy(woz.tmap, standardTMAP, 160);
112 woz.trksSize = Uint32LE(35 * (13 * 512));
114 for(int i=0; i<35; i++)
116 woz.track[i].startingBlock = Uint16LE(3 + (i * 13));
117 woz.track[i].blockCount = Uint16LE(13);
118 woz.track[i].bitCount = Uint32LE(51200);
121 // META header (how to handle? prolly with a separate pointer)
130 uint8_t * UpconvertWOZ1ToWOZ2(uint8_t * woz1Data, uint32_t woz1Size, uint32_t * newSize)
132 WOZ1 & woz1 = *((WOZ1 *)woz1Data);
134 // First, figure out how large the new structure will be in comparison to
136 uint32_t numTracks = woz1.trksSize / sizeof(WOZ1Track);
137 uint32_t metadataSize = woz1Size - (Uint32LE(woz1.trksSize) + 256);
139 // N.B.: # of blocks for each track will *always* be <= 13 for WOZ1
140 *newSize = 0x600 + (numTracks * (13 * 512)) + metadataSize;
141 uint8_t * woz2Data = (uint8_t *)malloc(*newSize);
142 memset(woz2Data, 0, *newSize);
144 WOZ2 & woz2 = *((WOZ2 *)woz2Data);
145 InitWOZ2Headers(woz2);
147 // Copy parts of INFO & TMAP chunks over
148 memcpy(&woz2.diskType, &woz1.diskType, 36);
149 memcpy(woz2.tmap, woz1.tmap, 160);
150 //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)
152 woz2.trksSize = Uint32LE(numTracks * (13 * 512));
154 // Finally, copy over the tracks
155 for(uint32_t i=0; i<numTracks; i++)
157 woz2.track[i].startingBlock = Uint16LE(3 + (i * 13));
158 woz2.track[i].blockCount = Uint16LE(13);
159 woz2.track[i].bitCount = woz1.track[i].bitCount;
160 memcpy(woz2Data + ((3 + (i * 13)) * 512), woz1.track[i].bits, 6646);
163 // Finally, copy over the metadata
164 memcpy(woz2Data + Uint32LE(woz2.trksSize) + 0x600,
165 woz1Data + Uint32LE(woz1.trksSize) + 0x100, metadataSize);
172 // Check WOZ type on the passed in contents (file loaded elsewhere).
173 // Returns type of WOZ if successful, 0 if not.
175 uint8_t CheckWOZType(const uint8_t * wozData, uint32_t wozSize)
177 // Basic sanity checking
178 if ((wozData == NULL) || (wozSize < 8))
181 if (memcmp(wozData, woz1Header, 8) == 0)
183 else if (memcmp(wozData, woz2Header, 8) == 0)
191 // Do basic sanity checks on the passed in contents (file loaded elsewhere).
192 // Returns true if successful, false on failure.
194 bool CheckWOZIntegrity(const uint8_t * wozData, uint32_t wozSize)
196 WOZ2 & woz = *((WOZ2 *)wozData);
197 uint32_t crc = CRC32(&wozData[12], wozSize - 12);
198 uint32_t wozCRC = Uint32LE(woz.crc32);
200 if ((wozCRC != 0) && (wozCRC != crc))
202 WriteLog("FILEIO: Corrupted data found in WOZ. CRC32: %08X, computed: %08X\n", wozCRC, crc);
205 else if (wozCRC == 0)
206 WriteLog("FILEIO: Warning--WOZ file has no CRC...\n");
208 #if 0 // Need to fix this so it works with both 1 & 2 (works with only 1 ATM)
209 WriteLog("Track map:\n");
210 WriteLog(" 1 1 1 1 1 1 1 1\n");
211 WriteLog("0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.\n");
212 WriteLog("------------------------------------------------------------------------\n");
214 for(uint8_t j=0; j<2; j++)
216 for(uint8_t i=0; i<72; i++)
219 buf[0] = buf[1] = '.';
221 if (woz.tmap[i] != 0xFF)
222 sprintf(buf, "%02d", woz.tmap[i]);
224 WriteLog("%c", buf[j]);
230 WriteLog("\n1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3\n");
231 WriteLog("8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5\n");
232 WriteLog("---------------------------------------------------------------------\n");
234 for(uint8_t j=0; j<2; j++)
236 for(uint8_t i=72; i<141; i++)
240 if (woz.tmap[i] != 0xFF)
241 sprintf(buf, "%02d", woz.tmap[i]);
243 WriteLog("%c", buf[j]);
251 uint8_t numTracks = woz.trksSize / sizeof(WOZ1Track);
253 // N.B.: Need to check the track in tmap[] to have this tell the correct track... Right now, it doesn't
254 for(uint8_t i=0; i<numTracks; i++)
256 WriteLog("WOZ: Stream %u: %d bits (packed into %d bytes)\n", i, woz.track[i].bitCount, (woz.track[i].bitCount + 7) / 8);
260 WriteLog("FILEIO: Well formed WOZ file found\n");
265 bool SaveWOZ(const char * filename, WOZ2 * woz, uint32_t size)
267 // Set up CRC32 before writing
268 woz->crc32 = Uint32LE(CRC32(woz->infoTag, size - 12));
270 // META header (skip for now) (actually, should be in the disk[] image already)
272 // Finally, write the damn image
273 FILE * file = fopen(filename, "wb");
277 WriteLog("FILEIO: Failed to open image file '%s' for writing...\n", filename);
281 fwrite((uint8_t *)woz, 1, size, file);
284 WriteLog("FILEIO: Successfully wrote image file '%s'...\n", filename);