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 // Note that size *must* be a valid pointer, otherwise this will go BOOM
36 uint8_t * ReadFile(const char * filename, uint32_t * size)
38 FILE * fp = fopen(filename, "rb");
43 fseek(fp, 0, SEEK_END);
45 fseek(fp, 0, SEEK_SET);
47 uint8_t * buffer = (uint8_t *)malloc(*size);
48 fread(buffer, 1, *size, fp);
56 // This initializes the WOZ type 2 headers
58 void InitWOZ2Headers(WOZ2 & woz)
60 // Set up header (leave CRC as 0 for now)
61 memcpy(woz.magic, woz2Header, 8);
65 memcpy(woz.infoTag, "INFO", 4);
66 woz.infoSize = Uint32LE(60);
69 woz.writeProtected = 0;
72 memset(woz.creator, ' ', 32);
73 memcpy(woz.creator, "Apple2 emulator v1.0.0", 22);
75 woz.bootSectorFmt = 1;
76 woz.optimalBitTmg = 32;
77 woz.largestTrack = Uint16LE(13);
80 memcpy(woz.tmapTag, "TMAP", 4);
81 woz.tmapSize = Uint32LE(160);
84 memcpy(woz.trksTag, "TRKS", 4);
89 // This is used mainly to initialize blank disks and upconvert non-WOZ disks
91 uint8_t * InitWOZ(uint32_t * pSize/*= NULL*/)
93 uint32_t size = 1536 + (35 * (13 * 512));
94 uint8_t * data = (uint8_t *)malloc(size);
95 WOZ2 & woz = *((WOZ2 *)data);
97 // Zero out WOZ image in memory
98 memset(&woz, 0, size);
101 InitWOZ2Headers(woz);
102 memcpy(woz.tmap, standardTMAP, 160);
103 woz.trksSize = Uint32LE(35 * (13 * 512));
105 for(int i=0; i<35; i++)
107 woz.track[i].startingBlock = Uint16LE(3 + (i * 13));
108 woz.track[i].blockCount = Uint16LE(13);
109 woz.track[i].bitCount = Uint32LE(51200);
112 // META header (how to handle? prolly with a separate pointer)
121 uint8_t * UpconvertWOZ1ToWOZ2(uint8_t * woz1Data, uint32_t woz1Size, uint32_t * newSize)
123 WOZ1 & woz1 = *((WOZ1 *)woz1Data);
125 // First, figure out how large the new structure will be in comparison to
127 uint32_t numTracks = woz1.trksSize / sizeof(WOZ1Track);
128 uint32_t metadataSize = woz1Size - (Uint32LE(woz1.trksSize) + 256);
130 // N.B.: # of blocks for each track will *always* be <= 13 for WOZ1
131 *newSize = 0x600 + (numTracks * (13 * 512)) + metadataSize;
132 uint8_t * woz2Data = (uint8_t *)malloc(*newSize);
133 memset(woz2Data, 0, *newSize);
135 WOZ2 & woz2 = *((WOZ2 *)woz2Data);
136 InitWOZ2Headers(woz2);
138 // Copy parts of INFO & TMAP chunks over
139 memcpy(&woz2.diskType, &woz1.diskType, 36);
140 memcpy(woz2.tmap, woz1.tmap, 160);
141 //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)
143 woz2.trksSize = Uint32LE(numTracks * (13 * 512));
145 // Finally, copy over the tracks
146 for(uint32_t i=0; i<numTracks; i++)
148 woz2.track[i].startingBlock = Uint16LE(3 + (i * 13));
149 woz2.track[i].blockCount = Uint16LE(13);
150 woz2.track[i].bitCount = woz1.track[i].bitCount;
151 memcpy(woz2Data + ((3 + (i * 13)) * 512), woz1.track[i].bits, 6646);
154 // Finally, copy over the metadata
155 memcpy(woz2Data + Uint32LE(woz2.trksSize) + 0x600,
156 woz1Data + Uint32LE(woz1.trksSize) + 0x100, metadataSize);
163 // Check WOZ type on the passed in contents (file loaded elsewhere).
164 // Returns type of WOZ if successful, 0 if not.
166 uint8_t CheckWOZType(const uint8_t * wozData, uint32_t wozSize)
168 // Basic sanity checking
169 if ((wozData == NULL) || (wozSize < 8))
172 if (memcmp(wozData, woz1Header, 8) == 0)
174 else if (memcmp(wozData, woz2Header, 8) == 0)
182 // Do basic sanity checks on the passed in contents (file loaded elsewhere).
183 // Returns true if successful, false on failure.
185 bool CheckWOZIntegrity(const uint8_t * wozData, uint32_t wozSize)
187 WOZ2 & woz = *((WOZ2 *)wozData);
188 uint32_t crc = CRC32(&wozData[12], wozSize - 12);
189 uint32_t wozCRC = Uint32LE(woz.crc32);
191 if ((wozCRC != 0) && (wozCRC != crc))
193 WriteLog("FILEIO: Corrupted data found in WOZ. CRC32: %08X, computed: %08X\n", wozCRC, crc);
196 else if (wozCRC == 0)
197 WriteLog("FILEIO: Warning--WOZ file has no CRC...\n");
199 #if 0 // Need to fix this so it works with both 1 & 2 (works with only 1 ATM)
200 WriteLog("Track map:\n");
201 WriteLog(" 1 1 1 1 1 1 1 1\n");
202 WriteLog("0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.\n");
203 WriteLog("------------------------------------------------------------------------\n");
205 for(uint8_t j=0; j<2; j++)
207 for(uint8_t i=0; i<72; i++)
210 buf[0] = buf[1] = '.';
212 if (woz.tmap[i] != 0xFF)
213 sprintf(buf, "%02d", woz.tmap[i]);
215 WriteLog("%c", buf[j]);
221 WriteLog("\n1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3\n");
222 WriteLog("8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5\n");
223 WriteLog("---------------------------------------------------------------------\n");
225 for(uint8_t j=0; j<2; j++)
227 for(uint8_t i=72; i<141; i++)
231 if (woz.tmap[i] != 0xFF)
232 sprintf(buf, "%02d", woz.tmap[i]);
234 WriteLog("%c", buf[j]);
242 uint8_t numTracks = woz.trksSize / sizeof(WOZ1Track);
244 // N.B.: Need to check the track in tmap[] to have this tell the correct track... Right now, it doesn't
245 for(uint8_t i=0; i<numTracks; i++)
247 WriteLog("WOZ: Stream %u: %d bits (packed into %d bytes)\n", i, woz.track[i].bitCount, (woz.track[i].bitCount + 7) / 8);
251 WriteLog("FILEIO: Well formed WOZ file found\n");
256 bool SaveWOZ(const char * filename, WOZ2 * woz, uint32_t size)
258 // Set up CRC32 before writing
259 woz->crc32 = Uint32LE(CRC32(woz->infoTag, size - 12));
261 // META header (skip for now) (actually, should be in the disk[] image already)
263 // Finally, write the damn image
264 FILE * file = fopen(filename, "wb");
268 WriteLog("FILEIO: Failed to open image file '%s' for writing...\n", filename);
272 fwrite((uint8_t *)woz, 1, size, file);
275 WriteLog("FILEIO: Successfully wrote image file '%s'...\n", filename);