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");
209 // Need to fix this so it works with both 1 & 2 (works with only 1 ATM)
210 WriteLog("Track map:\n");
211 WriteLog(" 1 1 1 1 1 1 1 1\n");
212 WriteLog("0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.\n");
213 WriteLog("------------------------------------------------------------------------\n");
215 for(uint8_t j=0; j<2; j++)
217 for(uint8_t i=0; i<72; i++)
220 buf[0] = buf[1] = '.';
222 if (woz.tmap[i] != 0xFF)
223 sprintf(buf, "%02d", woz.tmap[i]);
225 WriteLog("%c", buf[j]);
231 WriteLog("\n1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3\n");
232 WriteLog("8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5\n");
233 WriteLog("---------------------------------------------------------------------\n");
235 for(uint8_t j=0; j<2; j++)
237 for(uint8_t i=72; i<141; i++)
241 if (woz.tmap[i] != 0xFF)
242 sprintf(buf, "%02d", woz.tmap[i]);
244 WriteLog("%c", buf[j]);
253 uint8_t numTracks = woz.trksSize / sizeof(WOZ1Track);
255 // N.B.: Need to check the track in tmap[] to have this tell the correct track... Right now, it doesn't
256 for(uint8_t i=0; i<numTracks; i++)
258 WriteLog("WOZ: Stream %u: %d bits (packed into %d bytes)\n", i, woz.track[i].bitCount, (woz.track[i].bitCount + 7) / 8);
263 WriteLog("FILEIO: Well formed WOZ file found\n");
268 bool SaveWOZ(const char * filename, WOZ2 * woz, uint32_t size)
270 // Set up CRC32 before writing
271 woz->crc32 = Uint32LE(CRC32(woz->infoTag, size - 12));
273 // META header (skip for now) (actually, should be in the disk[] image already)
275 // Finally, write the damn image
276 FILE * file = fopen(filename, "wb");
280 WriteLog("FILEIO: Failed to open image file '%s' for writing...\n", filename);
284 fwrite((uint8_t *)woz, 1, size, file);
287 WriteLog("FILEIO: Successfully wrote image file '%s'...\n", filename);