/[projet1]/public/pc/tools/osdk/main/makedisk/Floppy.cpp
Defence Force logotype

Contents of /public/pc/tools/osdk/main/makedisk/Floppy.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1038 - (show annotations)
Tue Dec 17 21:24:32 2013 UTC (5 years, 11 months ago) by dbug
File size: 24017 byte(s)
FloppyBuilder 0.10
- The compression code now generates correct data (it was using the Atari ST mode encoding, making the unpacking code not happy)
- Added to the report file the occupation ratio of the floppy (by maintaining an internal list of used sectors also used to check if there's no overlap)
The loader code is now able to decompress data on the fly just using the page 2 as a temporary sector loader.
1
2 #include "infos.h"
3
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <sstream>
7 #include <iostream>
8 #include <string.h>
9
10 #include <assert.h>
11
12 #include "Floppy.h"
13
14 #include "common.h"
15
16
17
18
19 FloppyHeader::FloppyHeader()
20 {
21 assert(sizeof(*this)==256);
22 memset(this,0,sizeof(*this));
23 }
24
25 FloppyHeader::~FloppyHeader()
26 {
27 }
28
29 bool FloppyHeader::IsValidHeader() const
30 {
31 if (memcmp(m_Signature,"MFM_DISK",8)!=0) return false;
32
33 int sideNumber=GetSideNumber();
34 if ((sideNumber<1) || (sideNumber>2)) return false;
35
36 int trackNumber=GetTrackNumber();
37 if ((trackNumber<30) || (trackNumber>82)) return false;
38
39 return true;
40 }
41
42
43 void FloppyHeader::Clear()
44 {
45 memset(this,0,sizeof(FloppyHeader));
46 }
47
48 void FloppyHeader::SetSignature(char signature[8])
49 {
50 memcpy(m_Signature,signature,8);
51 }
52
53
54 void FloppyHeader::SetSideNumber(int sideNumber)
55 {
56 m_Sides[0]=(sideNumber>>0)&255;
57 m_Sides[1]=(sideNumber>>8)&255;
58 m_Sides[2]=(sideNumber>>16)&255;
59 m_Sides[3]=(sideNumber>>24)&255;
60 }
61
62 int FloppyHeader::GetSideNumber() const
63 {
64 int sideNumber= ( ( ( ( (m_Sides[3]<<8) | m_Sides[2]) << 8 ) | m_Sides[1]) << 8 ) | m_Sides[0];
65 return sideNumber;
66 }
67
68
69 void FloppyHeader::SetTrackNumber(int trackNumber)
70 {
71 m_Tracks[0]=(trackNumber>>0)&255;
72 m_Tracks[1]=(trackNumber>>8)&255;
73 m_Tracks[2]=(trackNumber>>16)&255;
74 m_Tracks[3]=(trackNumber>>24)&255;
75 }
76
77 int FloppyHeader::GetTrackNumber() const
78 {
79 int trackNumber= ( ( ( ( (m_Tracks[3]<<8) | m_Tracks[2]) << 8 ) | m_Tracks[1]) << 8 ) | m_Tracks[0];
80 return trackNumber;
81 }
82
83 void FloppyHeader::SetGeometry(int geometry)
84 {
85 m_Geometry[0]=(geometry>>0)&255;
86 m_Geometry[1]=(geometry>>8)&255;
87 m_Geometry[2]=(geometry>>16)&255;
88 m_Geometry[3]=(geometry>>24)&255;
89 }
90
91 int FloppyHeader::GetGeometry() const
92 {
93 int geometry= ( ( ( ( (m_Geometry[3]<<8) | m_Geometry[2]) << 8 ) | m_Geometry[1]) << 8 ) | m_Geometry[0];
94 return geometry;
95 }
96
97 int FloppyHeader::FindNumberOfSectors(int& firstSectorOffset,int& sectorInterleave) const
98 {
99 firstSectorOffset=0;
100 sectorInterleave=0;
101
102 /*
103 Format of a track:
104 6400 bytes in total
105 - gap1: 72/12 bytes at the start of the track (with zeroes)
106 Then for each sector:
107 - ?: 4 bytes (A1 A1 A1 FE)
108 - track number: 1 byte (0-40-80...)
109 - side number: 1 byte (0-1)
110 - sector number: 1 byte (1-18-19)
111 - one: 1 byte (1)
112 - crc: 2 bytes (crc of the 8 previous bytes)
113 - gap2: 34 bytes (22xAE , 12x00)
114 - ?: 4 bytes (A1 A1 A1 FB)
115 - data: 256 bytes
116 - crc: 2 bytes (crc of the 256+4 previous bytes)
117 - gap3: 50/46 bytes
118 */
119 unsigned char* trackDataStart=(unsigned char*)(this+1);
120 unsigned char* trackData =trackDataStart;
121 unsigned char* trackDataEnd=trackDataStart+6400;
122
123 int lastSectorFound=0;
124 while (trackData<(trackDataEnd-16))
125 {
126 if ( (trackData[0]==0xa1) && (trackData[1]==0xa1) && (trackData[2]==0xa1) && (trackData[3]==0xfe) )
127 {
128 // Found a marker for a synchronization sequence for a sector [#A1 #A1 #A1], [#FE Track Side Sector tt CRC CRC]
129 int sectorNumber=trackData[6];
130 if (sectorNumber==(lastSectorFound+1))
131 {
132 lastSectorFound=sectorNumber;
133 }
134 else
135 {
136 ShowError("There's something wrong in the track structure of the floppy, the sector id does not make sense.");
137 }
138 trackData+=10; // Skip synchronization sequence
139 trackData+=34; // - gap2: 34 bytes (22xAE , 12x00)
140 trackData+=4; // - ?: 4 bytes (A1 A1 A1 FB)
141
142 if (sectorNumber==1)
143 {
144 firstSectorOffset=trackData-trackDataStart;
145 }
146 else
147 if (sectorNumber==2)
148 {
149 sectorInterleave=trackData-trackDataStart-firstSectorOffset;
150 }
151 trackData+=256; // Sector data
152 }
153 else
154 {
155 trackData++;
156 }
157 }
158
159 return lastSectorFound;
160 }
161
162
163
164 FileEntry::FileEntry() :
165 m_FloppyNumber(0),
166 m_StartSide(0),
167 m_StartTrack(0),
168 m_StartSector(1),
169 m_SectorCount(0),
170 m_LoadAddress(0),
171 m_FinalFileSize(0),
172 m_CompressionMode(e_CompressionNone),
173 m_StoredFileSize(0)
174 {
175 }
176
177 FileEntry::~FileEntry()
178 {
179 }
180
181
182
183
184 Floppy::Floppy() :
185 m_Buffer(0),
186 m_BufferSize(0),
187 m_TrackNumber(0),
188 m_SectorNumber(0),
189 m_CurrentTrack(0),
190 m_CurrentSector(1),
191 m_CompressionMode(e_CompressionNone),
192 m_OffsetFirstSector(156), // 156 (Location of the first byte of data of the first sector)
193 m_InterSectorSpacing(358) // 358 (Number of bytes to skip to go to the next sector: 256+59+43)
194 {
195 }
196
197
198 Floppy::~Floppy()
199 {
200 delete m_Buffer;
201 }
202
203
204 unsigned int crctab[256] =
205 {
206 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
207 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
208 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
209 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
210 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
211 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
212 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
213 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
214 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
215 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
216 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
217 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
218 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
219 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
220 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
221 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
222 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
223 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
224 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
225 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
226 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
227 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
228 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
229 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
230 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
231 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
232 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
233 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
234 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
235 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
236 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
237 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
238 };
239
240 void compute_crc(unsigned char *ptr,int count)
241 {
242 int i;
243 unsigned short crc=0xFFFF,byte;
244 for (i=0;i<count;i++) {
245 byte= *ptr++;
246 crc=(crc<<8)^crctab[(crc>>8)^byte];
247 }
248 *ptr++=crc>>8;
249 *ptr++=crc&0xFF;
250 }
251
252
253 bool Floppy::CreateDisk(int numberOfSides,int numberOfTracks,int numberOfSectors)
254 {
255 // Heavily based on MakeDisk and Tap2DSk
256 int gap1,gap2,gap3;
257
258 switch (numberOfSectors)
259 {
260 case 15: case 16: case 17:
261 gap1=72; gap2=34; gap3=50;
262 break;
263
264 case 18:
265 gap1=12; gap2=34; gap3=46;
266 break;
267
268 default:
269 ShowError("Unrealistic sectors per track number\n");
270 }
271
272 m_BufferSize=256+numberOfSides*numberOfTracks*6400;
273 m_Buffer=malloc(m_BufferSize);
274 if (m_Buffer)
275 {
276 m_TrackNumber =numberOfTracks; // 42
277 m_SectorNumber=numberOfSectors; // 17
278 m_SideNumber =numberOfSides; // 2
279
280 FloppyHeader& header(*((FloppyHeader*)m_Buffer));
281 header.Clear();
282 header.SetSignature("MFM_DISK");
283 header.SetSideNumber(numberOfSides);
284 header.SetTrackNumber(numberOfTracks);
285 header.SetGeometry(1);
286
287 unsigned char* trackbuf=(unsigned char*)m_Buffer+256;
288 for (int s=0;s<numberOfSides;s++)
289 {
290 for (int t=0;t<numberOfTracks;t++)
291 {
292 {
293 int i;
294 int offset=0;
295 for (i=0;i<gap1-12;i++)
296 {
297 trackbuf[offset++]=0x4E;
298 }
299 for (int j=0;j<numberOfSectors;j++)
300 {
301 for (i=0;i<12;i++) trackbuf[offset++]=0;
302 for (i=0;i<3;i++) trackbuf[offset++]=0xA1;
303 trackbuf[offset++]=0xFE;
304 for (i=0;i<6;i++) offset++;
305 for (i=0;i<gap2-12;i++) trackbuf[offset++]=0x22;
306 for (i=0;i<12;i++) trackbuf[offset++]=0;
307 for (i=0;i<3;i++) trackbuf[offset++]=0xA1;
308 trackbuf[offset++]=0xFB;
309 for (i=0;i<258;i++) offset++;
310 for (i=0;i<gap3-12;i++) trackbuf[offset++]=0x4E;
311 }
312
313 while (offset<6400)
314 {
315 trackbuf[offset++]=0x4E;
316 }
317 }
318 int offset=gap1;
319 for (int i=0;i<numberOfSectors;i++)
320 {
321 trackbuf[offset+4]=t;
322 trackbuf[offset+5]=s;
323 trackbuf[offset+6]=i+1;
324 trackbuf[offset+7]=1;
325 compute_crc(trackbuf+offset,4+4);
326 offset+=4+6;
327 offset+=gap2;
328 memset(trackbuf+offset+4,0,256);
329 compute_crc(trackbuf+offset,4+256);
330 offset+=256+6;
331 offset+=gap3;
332 }
333 trackbuf+=6400;
334 }
335 }
336 if (header.IsValidHeader())
337 {
338 m_SectorNumber=header.FindNumberOfSectors(m_OffsetFirstSector,m_InterSectorSpacing); //17; // Can't figure out that from the header Oo
339 return true;
340 }
341 }
342
343 return false;
344 }
345
346
347 bool Floppy::LoadDisk(const char* fileName)
348 {
349 if (LoadFile(fileName,m_Buffer,m_BufferSize))
350 {
351 const FloppyHeader& header(*((FloppyHeader*)m_Buffer));
352 if (header.IsValidHeader())
353 {
354 m_TrackNumber =header.GetTrackNumber();
355 m_SideNumber =header.GetSideNumber();
356 m_SectorNumber=header.FindNumberOfSectors(m_OffsetFirstSector,m_InterSectorSpacing); //17; // Can't figure out that from the header Oo
357 return true;
358 }
359 }
360 return false;
361 }
362
363
364 bool Floppy::SaveDisk(const char* fileName) const
365 {
366 if (m_Buffer)
367 {
368 return SaveFile(fileName,m_Buffer,m_BufferSize);
369 }
370 return false;
371 }
372
373 /*
374 Début de la piste (facultatif): 80 [#4E], 12 [#00], [#C2 #C2 #C2 #FC] et 50 [#4E] (soit 146 octets selon
375 la norme IBM) ou 40 [#4E], 12 [#00], [#C2 #C2 #C2 #FC] et 40 [#4E] (soit 96 octets pour SEDORIC).
376
377 Pour chaque secteur: 12 [#00], 3 [#A1] [#FE #pp #ff #ss #tt CRC], 22 [#4E], 12 [#00], 3 [#A1], [#FB],
378 les 512 octets, [CRC CRC], 80 octets [#4E] (#tt = #02) (soit 141 + 512 = 653 octets selon la norme IBM)
379 ou 12 [#00], 3 [#A1] [#FE #pp #ff #ss #01 CRC CRC], 22 [#4E], 12 [#00], 3 [#A1], [#FB], les 256
380 octets, [CRC CRC], 12, 30 ou 40 octets [#4E] (selon le nombre de secteurs/piste). Soit environ 256 + (72
381 à 100) = 328 à 356 octets pour SEDORIC.
382
383 Fin de la piste (facultatif): un nombre variable d'octets [#4E
384
385 Selon NIBBLE,
386 une piste IBM compte 146 octets de début de piste + 9 secteurs de 653 octets + 257 octets de fin de piste = 6280 octets.
387 Une piste SEDORIC, formatée à 17 secteurs, compte 96 octets de début de piste + 17 secteurs de 358 octets + 98 octets de fin de piste = 6280 octets.
388 Une piste SEDORIC, formatée à 19 secteurs, compte 0 octet de début de piste + 19 secteurs de 328 octets + 48 octets de fin de piste = 6280 octets.
389 On comprend mieux le manque de fiabilité du formatage en 19 secteurs/piste dû à la faible largeur des zones de sécurité (12 [#4E] entre chaque secteur et 48 octets entre le dernier et le premier).
390
391 Lors de l'élaboration du tampon de formatage SEDORIC, les octets #C2 sont remplacés par des octets
392 #F6, les octets #A1 sont remplacés par des octets #F5 et chaque paire de 2 octets [CRC CRC] et
393 remplacée par un octet #F7. Comme on le voit, nombre de variantes sont utilisées, sauf la zone 22 [#4E],
394 12 [#00], 3 [#A1] qui est strictement obligatoire.
395
396 // From DskTool:
397 15, 16 or 17 sectors: gap1=72; gap2=34; gap3=50;
398 18 sectors: gap1=12; gap2=34; gap3=46;
399 */
400 // Header secteur
401 #define nb_oct_before_sector 59 // Cas de 17 secteurs/pistes !
402 #define nb_oct_after_sector 43 //#define nb_oct_after_sector 31
403
404 unsigned int Floppy::GetDskImageOffset()
405 {
406 unsigned int offset=256; // Add the DSK file header size
407 offset+=m_CurrentTrack*6400; // And move to the correct track
408 offset+=m_OffsetFirstSector; // Add the offset from the start of track to the data of the first sector
409 offset+=m_InterSectorSpacing*(m_CurrentSector-1);
410 return offset;
411 }
412
413
414 // 0x0319 -> 793
415 bool Floppy::WriteSector(const char *fileName)
416 {
417 if (!m_Buffer)
418 {
419 return false;
420 }
421
422 std::string filteredFileName(StringTrim(fileName," \t\f\v\n\r"));
423
424 void* buffer;
425 size_t bufferSize;
426
427 if (LoadFile(filteredFileName.c_str(),buffer,bufferSize))
428 {
429 if (bufferSize>256)
430 {
431 ShowError("File for sector is too large. %d bytes (%d too many)",bufferSize,bufferSize-256);
432 }
433
434 unsigned int sectorOffset=GetDskImageOffset();
435 if (m_BufferSize>sectorOffset+256)
436 {
437 memcpy((char*)m_Buffer+sectorOffset,buffer,bufferSize);
438 }
439 MarkCurrentSectorUsed();
440 printf("Boot sector '%s' installed, %d free bytes remaining in this sector.\n",filteredFileName.c_str(),256-bufferSize);
441
442 MoveToNextSector();
443 }
444 else
445 {
446 ShowError("Boot Sector file '%s' not found",filteredFileName.c_str());
447 }
448 return true;
449 }
450
451
452 class TapeInfo
453 {
454 public:
455 TapeInfo()
456 : m_StartAddress(0)
457 , m_EndAddress(0)
458 , m_FileType(0)
459 , m_AutoStarts(false)
460 , m_PtrData(nullptr)
461 , m_DataSize(0)
462 {
463
464 }
465
466 bool ParseHeader(void* fileBuffer,size_t fileSize)
467 {
468 m_DataSize=fileSize;
469 m_PtrData =(unsigned char*)fileBuffer;
470 while (m_DataSize && (m_PtrData[0]==0x16))
471 {
472 m_DataSize--;
473 m_PtrData++;
474 }
475 if (m_DataSize>8 && (m_PtrData[0]==0x24) && (m_PtrData[1]==0x00) && (m_PtrData[2]==0x00) )
476 {
477 // At this point at least we have a valid synchro sequence and we know we have a usable header
478 m_FileType = m_PtrData[3];
479 m_AutoStarts =(m_PtrData[4]!=0);
480 m_EndAddress =(m_PtrData[5]<<8)|m_PtrData[6];
481 m_StartAddress=(m_PtrData[7]<<8)|m_PtrData[8];
482
483 m_DataSize-=9;
484 m_PtrData+=9;
485
486 if (m_DataSize && (m_PtrData[0]==0x00) )
487 {
488 // Skip the zero
489 m_DataSize--;
490 m_PtrData++;
491
492 // Now we read the name
493 while (m_DataSize && (m_PtrData[0]!=0x00))
494 {
495 m_FileName+=m_PtrData[0];
496 m_DataSize--;
497 m_PtrData++;
498 }
499 if (m_DataSize && (m_PtrData[0]==0x00) )
500 {
501 // Skip the zero
502 m_DataSize--;
503 m_PtrData++;
504
505 // Now ptr points on the actual data
506 return true;
507 }
508 }
509 }
510 // Not a valid tape file
511 return false;
512 }
513
514 public:
515 unsigned char* m_PtrData;
516 int m_DataSize;
517 int m_StartAddress;
518 int m_EndAddress;
519 int m_FileType;
520 bool m_AutoStarts;
521 std::string m_FileName;
522 };
523
524
525 bool Floppy::WriteFile(const char *fileName,int loadAddress,bool removeHeaderIfPresent)
526 {
527 if (!m_Buffer)
528 {
529 return false;
530 }
531
532 void* fileBuffer;
533 size_t fileSize;
534 if (!LoadFile(fileName,fileBuffer,fileSize))
535 {
536 ShowError("Error can't open file '%s'\n",fileName);
537 }
538
539 unsigned char* fileData=(unsigned char*)fileBuffer;
540
541 if (removeHeaderIfPresent)
542 {
543 TapeInfo tapeInfo;
544 if (!tapeInfo.ParseHeader(fileBuffer,fileSize))
545 {
546 ShowError("File '%s' is not a valid tape file\n",fileName);
547 }
548 // If the file was a valid tape header, then we use these new information
549 fileData=tapeInfo.m_PtrData;
550 fileSize=tapeInfo.m_DataSize;
551 loadAddress=tapeInfo.m_StartAddress;
552 }
553
554 FileEntry fileEntry;
555 fileEntry.m_FloppyNumber=0; // 0 for a single floppy program
556
557 if (m_CurrentTrack>41) // face 2
558 {
559 fileEntry.m_StartSide=1;
560 }
561 else
562 {
563 fileEntry.m_StartSide=0;
564 }
565
566 fileEntry.m_StartTrack =m_CurrentTrack; // 0 to 42 (80...)
567 fileEntry.m_StartSector=m_CurrentSector; // 1 to 17 (or 16 or 18...)
568 fileEntry.m_LoadAddress=loadAddress;
569 fileEntry.m_StoredFileSize=fileSize;
570 fileEntry.m_FinalFileSize =fileSize;
571 fileEntry.m_SectorCount=(fileSize+255)/256;
572 fileEntry.m_FilePath =fileName;
573 fileEntry.m_CompressionMode=e_CompressionNone;
574
575 std::vector<unsigned char> compressedBuffer;
576 if (m_CompressionMode==e_CompressionFilepack)
577 {
578 // So the user requested FilePack compression.
579 // Great, we can do that.
580 compressedBuffer.resize(fileSize);
581 gLZ77_XorMask=0;
582 size_t compressedFileSize=LZ77_Compress(fileData,compressedBuffer.data(),fileSize);
583 if (compressedFileSize<fileSize)
584 {
585 // We actually did manage to compress the data
586 fileData=compressedBuffer.data();
587 fileSize=compressedFileSize;
588
589 fileEntry.m_CompressionMode=e_CompressionFilepack;
590 fileEntry.m_StoredFileSize=compressedFileSize;
591 fileEntry.m_SectorCount=(fileSize+255)/256;
592 }
593 }
594
595 //
596 // Finally write the data to the disk structure
597 //
598 while (fileSize)
599 {
600 unsigned int offset=SetPosition(m_CurrentTrack,m_CurrentSector);
601
602 int sizeToWrite=256;
603 if (fileSize<256)
604 {
605 sizeToWrite=fileSize;
606 }
607 fileSize-=sizeToWrite;
608
609 MarkCurrentSectorUsed();
610 memset((char*)m_Buffer+offset,0,256);
611 memcpy((char*)m_Buffer+offset,fileData,sizeToWrite);
612 fileData+=sizeToWrite;
613
614 MoveToNextSector();
615 }
616 free(fileBuffer);
617
618 m_FileEntries.push_back(fileEntry);
619
620 return true;
621 }
622
623 void Floppy::MarkCurrentSectorUsed()
624 {
625 int magicValue=(m_SectorNumber*m_CurrentTrack)+m_CurrentSector;
626 if (m_SectorUsageMap.find(magicValue)!=m_SectorUsageMap.end())
627 {
628 ShowError("Sector %d was already allocated",magicValue);
629 }
630 m_SectorUsageMap.insert(magicValue);
631 }
632
633 bool Floppy::SaveDescription(const char* fileName) const
634 {
635 std::stringstream layoutInfo;
636 layoutInfo << "//\n";
637 layoutInfo << "// Floppy layout generated by FloppyBuilder " << TOOL_VERSION_MAJOR << "." << TOOL_VERSION_MINOR << "\n";
638 layoutInfo << "//\n";
639 layoutInfo << "\n";
640
641 layoutInfo << "#ifdef ASSEMBLER\n";
642 layoutInfo << "//\n";
643 layoutInfo << "// Information for the Assembler\n";
644 layoutInfo << "//\n";
645 layoutInfo << "#ifdef LOADER\n";
646
647 std::stringstream code_sector;
648 std::stringstream code_track;
649 std::stringstream code_compressed;
650 std::stringstream code_size_low;
651 std::stringstream code_size_high;
652 std::stringstream code_stored_size_low;
653 std::stringstream code_stored_size_high;
654 std::stringstream code_adress_low;
655 std::stringstream code_adress_high;
656
657 std::stringstream file_list_summary;
658
659 int counter=0;
660 for (auto it(m_FileEntries.begin());it!=m_FileEntries.end();++it)
661 {
662 const FileEntry& fileEntry(*it);
663
664 if (it!=m_FileEntries.begin())
665 {
666 code_adress_low << ",";
667 code_adress_high << ",";
668
669 code_stored_size_low << ",";
670 code_stored_size_high << ",";
671
672 code_size_low << ",";
673 code_size_high << ",";
674
675 code_sector << ",";
676 code_track << ",";
677
678 code_compressed << ",";
679 }
680 code_adress_low << "<" << fileEntry.m_LoadAddress;
681 code_adress_high << ">" << fileEntry.m_LoadAddress;
682
683 code_size_low << "<" << fileEntry.m_FinalFileSize;
684 code_size_high << ">" << fileEntry.m_FinalFileSize;
685
686 code_stored_size_low << "<" << fileEntry.m_StoredFileSize;
687 code_stored_size_high << ">" << fileEntry.m_StoredFileSize;
688
689 code_sector << fileEntry.m_StartSector;
690
691 file_list_summary << "// - Entry #" << counter << " '"<< fileEntry.m_FilePath << " ' loads at address " << fileEntry.m_LoadAddress;
692 if (fileEntry.m_StartTrack<m_TrackNumber)
693 {
694 // First side
695 file_list_summary << " starts on track " << fileEntry.m_StartTrack;
696 code_track << fileEntry.m_StartTrack;
697 }
698 else
699 {
700 // Second side
701 file_list_summary << " starts on the second side on track " << (fileEntry.m_StartTrack-m_TrackNumber);
702 code_track << fileEntry.m_StartTrack-m_TrackNumber+128;
703 }
704 file_list_summary << " sector " << fileEntry.m_StartSector << " and is " << fileEntry.m_SectorCount << " sectors long ";
705
706 if (fileEntry.m_CompressionMode==e_CompressionNone)
707 {
708 // Uncompressed file
709 file_list_summary << "(" << fileEntry.m_FinalFileSize << " bytes).\n";
710 }
711 else
712 {
713 // Compressed file
714 file_list_summary << "(" << fileEntry.m_StoredFileSize << " compressed bytes: " << (fileEntry.m_StoredFileSize*100)/fileEntry.m_FinalFileSize << "% of " << fileEntry.m_FinalFileSize << " bytes).\n";
715 }
716
717 ++counter;
718 }
719
720
721 layoutInfo << "FileStartSector .byt ";
722 layoutInfo << code_sector.str() << "\n";
723
724 layoutInfo << "FileStartTrack .byt ";
725 layoutInfo << code_track.str() << "\n";
726
727 layoutInfo << "FileStoredSizeLow .byt ";
728 layoutInfo << code_stored_size_low.str() << "\n";
729
730 layoutInfo << "FileStoredSizeHigh .byt ";
731 layoutInfo << code_stored_size_high.str() << "\n";
732
733 layoutInfo << "FileSizeLow .byt ";
734 layoutInfo << code_size_low.str() << "\n";
735
736 layoutInfo << "FileSizeHigh .byt ";
737 layoutInfo << code_size_high.str() << "\n";
738
739 layoutInfo << "FileLoadAdressLow .byt ";
740 layoutInfo << code_adress_low.str() << "\n";
741
742 layoutInfo << "FileLoadAdressHigh .byt ";
743 layoutInfo << code_adress_high.str() << "\n";
744
745
746 layoutInfo << "#endif\n";
747
748 layoutInfo << "#else\n";
749 layoutInfo << "//\n";
750 layoutInfo << "// Information for the Compiler\n";
751 layoutInfo << "//\n";
752 layoutInfo << "#endif\n";
753
754 layoutInfo << "\n";
755 layoutInfo << "//\n";
756 layoutInfo << "// Summary for this floppy building session:\n";
757 layoutInfo << "#define FLOPPY_SIDE_NUMBER " << m_SideNumber << " // Number of sides\n";
758 layoutInfo << "#define FLOPPY_TRACK_NUMBER " << m_TrackNumber << " // Number of tracks\n";
759 layoutInfo << "#define FLOPPY_SECTOR_PER_TRACK " << m_SectorNumber << " // Number of sectors per track\n";
760 layoutInfo << "//\n";
761
762 layoutInfo << "// List of files written to the floppy\n";
763 layoutInfo << file_list_summary.str();
764 layoutInfo << "//\n";
765
766 int totalAvailableSpace=m_TrackNumber*m_SectorNumber*m_SideNumber;
767 layoutInfo << "// " << m_SectorUsageMap.size() << " sectors used, out of " << totalAvailableSpace << ". (" << (m_SectorUsageMap.size()*100)/totalAvailableSpace << "% of the total available size used)\n";
768 layoutInfo << "//\n";
769
770 if (m_DefineList.empty())
771 {
772 layoutInfo << "// No defines set\n";
773 }
774 else
775 {
776 for (auto it(m_DefineList.begin());it!=m_DefineList.end();++it)
777 {
778 layoutInfo << "#define " << it->first << " " << it->second << "\n";
779 ++counter;
780 }
781 }
782
783 if (!SaveFile(fileName,layoutInfo.str().c_str(),layoutInfo.str().length()))
784 {
785 ShowError("Can't save '%s'\n",fileName);
786 }
787
788 return true;
789 }
790
791
792 bool Floppy::AddDefine(std::string defineName,std::string defineValue)
793 {
794 // Ugly token replacement, can do more optimal but as long as it works...
795 {
796 std::stringstream tempValue;
797 tempValue << m_FileEntries.size();
798 StringReplace(defineName ,"{FileIndex}",tempValue.str());
799 StringReplace(defineValue,"{FileIndex}",tempValue.str());
800 }
801
802 m_DefineList.push_back(std::pair<std::string,std::string>(defineName,defineValue));
803 return true;
804 }

  ViewVC Help
Powered by ViewVC 1.1.26