/[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 1013 - (show annotations)
Thu Dec 12 19:35:12 2013 UTC (6 years, 2 months ago) by dbug
File size: 10581 byte(s)
Modified the ShowError command to take optional parameters (makes it possible to display actual information in the error message)
FloppyBuilder 0.3: Fixed parsing of comments, added a 'OutputFloppyFile' command, validated that the number of sectors and tracks is correct in the 'SetPosition' command.
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 // BORN.DSK=537856 bytes
19 // 17*358=6086
20 // *2=12172
21 // *44=537856
22
23 // Boot sector at offset 793 (Confirmed)
24 // Loader at offset 0x734 (1844) - Confirmed
25
26 // 793-256-156=381
27 // 381-256=125
28
29 // offset=256+156; // on ajoute le header
30 // offset+=track*6400; // On avance à la bonne piste
31 // offset+=(taille_secteur+nb_oct_after_sector+nb_oct_before_sector)*(sector-1);
32 //
33 // So: Offset = 256+156 + (track*6400) + (taille_secteur+nb_oct_after_sector+nb_oct_before_sector)*(sector-1)
34 // = 256+156 + (track*6400) + (256+43+59)*(sector-1)
35 // = 412 + (track*6400) + (358)*(sector-1)
36
37
38 FloppyHeader::FloppyHeader()
39 {
40 assert(sizeof(*this)==256);
41 memset(this,0,sizeof(*this));
42 }
43
44 FloppyHeader::~FloppyHeader()
45 {
46 }
47
48 bool FloppyHeader::IsValidHeader() const
49 {
50 if (memcmp(m_Signature,"MFM_DISK",8)!=0) return false;
51
52 int sideNumber=GetSideNumber();
53 if ((sideNumber<1) || (sideNumber>2)) return false;
54
55 int trackNumber=GetTrackNumber();
56 if ((trackNumber<30) || (trackNumber>82)) return false;
57
58 return true;
59 }
60
61 int FloppyHeader::GetSideNumber() const
62 {
63 int sideNumber= ( ( ( ( (m_Sides[3]<<8) | m_Sides[2]) << 8 ) | m_Sides[1]) << 8 ) | m_Sides[0];
64 return sideNumber;
65 }
66
67 int FloppyHeader::GetTrackNumber() const
68 {
69 int trackNumber= ( ( ( ( (m_Tracks[3]<<8) | m_Tracks[2]) << 8 ) | m_Tracks[1]) << 8 ) | m_Tracks[0];
70 return trackNumber;
71 }
72
73
74
75
76 FileEntry::FileEntry() :
77 m_FloppyNumber(0),
78 m_StartSide(0),
79 m_StartTrack(0),
80 m_StartSector(1),
81 m_SectorCount(0),
82 m_LoadAddress(0),
83 m_TotalSize(0)
84 {
85 }
86
87 FileEntry::~FileEntry()
88 {
89 }
90
91
92
93
94 Floppy::Floppy() :
95 m_Buffer(0),
96 m_BufferSize(0),
97 m_Offset(0),
98 m_TrackNumber(0),
99 m_SectorNumber(0)
100 {
101 fileCount=0;
102 }
103
104
105 Floppy::~Floppy()
106 {
107 delete m_Buffer;
108 }
109
110
111 bool Floppy::LoadDisk(const char* fileName)
112 {
113 m_Offset=0;
114 if (LoadFile(fileName,m_Buffer,m_BufferSize))
115 {
116 const FloppyHeader& header(*((FloppyHeader*)m_Buffer));
117 if (header.IsValidHeader())
118 {
119 m_TrackNumber =header.GetTrackNumber();
120 m_SideNumber =header.GetSideNumber();
121 m_SectorNumber=17; // Can't figure out that from the header Oo
122 return true;
123 }
124 }
125 return false;
126 }
127
128
129 bool Floppy::SaveDisk(const char* fileName) const
130 {
131 assert(m_Buffer);
132 return SaveFile(fileName,m_Buffer,m_BufferSize);
133 }
134
135 /*
136 Début de la piste (facultatif): 80 [#4E], 12 [#00], [#C2 #C2 #C2 #FC] et 50 [#4E] (soit 146 octets selon
137 la norme IBM) ou 40 [#4E], 12 [#00], [#C2 #C2 #C2 #FC] et 40 [#4E] (soit 96 octets pour SEDORIC).
138
139 Pour chaque secteur: 12 [#00], 3 [#A1] [#FE #pp #ff #ss #tt CRC], 22 [#4E], 12 [#00], 3 [#A1], [#FB],
140 les 512 octets, [CRC CRC], 80 octets [#4E] (#tt = #02) (soit 141 + 512 = 653 octets selon la norme IBM)
141 ou 12 [#00], 3 [#A1] [#FE #pp #ff #ss #01 CRC CRC], 22 [#4E], 12 [#00], 3 [#A1], [#FB], les 256
142 octets, [CRC CRC], 12, 30 ou 40 octets [#4E] (selon le nombre de secteurs/piste). Soit environ 256 + (72
143 à 100) = 328 à 356 octets pour SEDORIC.
144
145 Fin de la piste (facultatif): un nombre variable d'octets [#4E
146
147 Selon NIBBLE,
148 une piste IBM compte 146 octets de début de piste + 9 secteurs de 653 octets + 257 octets de fin de piste = 6280 octets.
149 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.
150 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.
151 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).
152
153 Lors de l'élaboration du tampon de formatage SEDORIC, les octets #C2 sont remplacés par des octets
154 #F6, les octets #A1 sont remplacés par des octets #F5 et chaque paire de 2 octets [CRC CRC] et
155 remplacée par un octet #F7. Comme on le voit, nombre de variantes sont utilisées, sauf la zone 22 [#4E],
156 12 [#00], 3 [#A1] qui est strictement obligatoire.
157
158 // From DskTool:
159 15, 16 or 17 sectors: gap1=72; gap2=34; gap3=50;
160 18 sectors: gap1=12; gap2=34; gap3=46;
161 */
162 unsigned int Floppy::ComputeOffset(int track,int sector)
163 {
164 unsigned int offset=256+156; // on ajoute le header
165 offset+=track*6400; // On avance à la bonne piste
166 offset+=(taille_secteur+nb_oct_after_sector+nb_oct_before_sector)*(sector-1);
167 return offset;
168 }
169
170
171 // 0x0319 -> 793
172 void Floppy::WriteSector(int track,int sector,const char *fileName)
173 {
174 std::string filteredFileName(StringTrim(fileName," \t\f\v\n\r"));
175
176 void* buffer;
177 size_t bufferSize;
178
179 if (LoadFile(filteredFileName.c_str(),buffer,bufferSize))
180 {
181 if (bufferSize>256)
182 {
183 ShowError("File for sector is too large. %d bytes (%d too many)",bufferSize,bufferSize-256);
184 }
185
186 unsigned int bootSectorOffset=ComputeOffset(track,sector);
187 if (m_BufferSize>bootSectorOffset+256)
188 {
189 memcpy((char*)m_Buffer+bootSectorOffset,buffer,bufferSize);
190 }
191 printf("Boot sector '%s' installed, %d free bytes remaining in this sector.\n",filteredFileName.c_str(),256-bufferSize);
192 }
193 else
194 {
195 ShowError("Boot Sector file '%s' not found",filteredFileName.c_str());
196 }
197 }
198
199 int Floppy::WriteFile(const char *fileName,int& currentTrack,int& currentSector,int loadAddress)
200 {
201 FileEntry fileEntry;
202 fileEntry.m_FloppyNumber=0; // 0 for a single floppy program
203
204 if (fileCount)
205 {
206 code_adress_low << ",";
207 code_adress_high << ",";
208
209 code_sector << ",";
210 code_track << ",";
211 code_nombre_secteur << ",";
212 }
213 code_adress_low << "<" << loadAddress;
214 code_adress_high << ">" << loadAddress;
215
216 if (currentTrack>41) // face 2
217 {
218 fileEntry.m_StartSide=1;
219 code_track << currentTrack-42+128;
220 }
221 else
222 {
223 fileEntry.m_StartSide=0;
224 code_track << currentTrack;
225 }
226 code_sector << currentSector;
227
228 void* fileBuffer;
229 size_t fileSize;
230 if (!LoadFile(fileName,fileBuffer,fileSize))
231 {
232 ShowError("Error can't open file '%s'\n",fileName);
233 }
234
235 int nb_sectors_by_files=(fileSize+255)/256;
236
237 fileEntry.m_StartTrack =currentTrack; // 0 to 42 (80...)
238 fileEntry.m_StartSector=currentSector; // 1 to 17 (or 16 or 18...)
239 fileEntry.m_SectorCount=nb_sectors_by_files; // Should probably be the real length
240 fileEntry.m_LoadAddress=loadAddress;
241 fileEntry.m_TotalSize=fileSize;
242 fileEntry.m_FilePath =fileName;
243
244 unsigned char* fileData=(unsigned char*)fileBuffer;
245 while (fileSize)
246 {
247 SetOffset(currentTrack,currentSector);
248
249 int sizeToWrite=256;
250 if (fileSize<256)
251 {
252 sizeToWrite=fileSize;
253 }
254 fileSize-=sizeToWrite;
255
256 memset((char*)m_Buffer+m_Offset,0,256);
257 memcpy((char*)m_Buffer+m_Offset,fileData,sizeToWrite);
258 fileData+=sizeToWrite;
259
260 currentSector++;
261
262 if (currentSector==taille_piste+1) // We reached the end of the track!
263 {
264 currentSector=1;
265 currentTrack++;
266 if (currentTrack==m_TrackNumber)
267 {
268 // Next side is following on the floppy in the DSK format, so technically we should have nothing to do
269 // All the hard work is in the loader
270 }
271 }
272 }
273 free(fileBuffer);
274
275 code_nombre_secteur << nb_sectors_by_files;
276
277 ++fileCount;
278
279 m_FileEntries.push_back(fileEntry);
280
281 return nb_sectors_by_files;
282 }
283
284
285 bool Floppy::SaveDescription(const char* fileName) const
286 {
287 std::stringstream layoutInfo;
288 layoutInfo << "//\n";
289 layoutInfo << "// Floppy layout generated by FloppyBuilder " << TOOL_VERSION_MAJOR << "." << TOOL_VERSION_MINOR << "\n";
290 layoutInfo << "//\n";
291 layoutInfo << "\n";
292
293 layoutInfo << "#ifdef ASSEMBLER\n";
294 layoutInfo << "//\n";
295 layoutInfo << "// Information for the Assembler\n";
296 layoutInfo << "//\n";
297
298 layoutInfo << "FileStartSector .byt ";
299 layoutInfo << code_sector.str() << "\n";
300
301 layoutInfo << "FileStartTrack .byt ";
302 layoutInfo << code_track.str() << "\n";
303
304 layoutInfo << "FileSectorCount .byt ";
305 layoutInfo << code_nombre_secteur.str() << "\n";
306
307 layoutInfo << "FileLoadAdressLow .byt ";
308 layoutInfo << code_adress_low.str() << "\n";
309
310 layoutInfo << "FileLoadAdressHigh .byt ";
311 layoutInfo << code_adress_high.str() << "\n";
312
313 layoutInfo << "#else\n";
314 layoutInfo << "//\n";
315 layoutInfo << "// Information for the Compiler\n";
316 layoutInfo << "//\n";
317 layoutInfo << "#endif\n";
318
319 layoutInfo << "\n";
320 layoutInfo << "//\n";
321 layoutInfo << "// Summary for this floppy building session:\n";
322 layoutInfo << "#define FLOPPY_TRACK_NUMBER " << m_TrackNumber << " // Number of tracks\n";
323 layoutInfo << "#define FLOPPY_SECTOR_PER_TRACK " << m_SectorNumber << " // Number of sectors per track\n";
324 layoutInfo << "//\n";
325
326 layoutInfo << "// List of files written to the floppy\n";
327 int counter=0;
328 for (auto it(m_FileEntries.begin());it!=m_FileEntries.end();++it)
329 {
330 layoutInfo << "// - Entry #" << counter << " '"<< it->m_FilePath << " ' loads at address " << it->m_LoadAddress << " starts on track " << it->m_StartTrack<< " sector "<< it->m_StartSector <<" and is " << it->m_SectorCount << " sectors long (" << it->m_TotalSize << " bytes).\n";
331 ++counter;
332 }
333 layoutInfo << "//\n";
334
335 if (m_DefineList.empty())
336 {
337 layoutInfo << "// No defines set\n";
338 }
339 else
340 {
341 for (auto it(m_DefineList.begin());it!=m_DefineList.end();++it)
342 {
343 layoutInfo << "#define " << it->first << " " << it->second << "\n";
344 ++counter;
345 }
346 }
347
348 if (!SaveFile(fileName,layoutInfo.str().c_str(),layoutInfo.str().length()))
349 {
350 ShowError("Can't save '%s'\n",fileName);
351 }
352
353 return true;
354 }
355
356
357 bool Floppy::AddDefine(std::string defineName,std::string defineValue)
358 {
359 // Ugly token replacement, can do more optimal but as long as it works...
360 {
361 std::stringstream tempValue;
362 tempValue << m_FileEntries.size();
363 StringReplace(defineName ,"{FileIndex}",tempValue.str());
364 StringReplace(defineValue,"{FileIndex}",tempValue.str());
365 }
366
367 m_DefineList.push_back(std::pair<std::string,std::string>(defineName,defineValue));
368 return true;
369 }

  ViewVC Help
Powered by ViewVC 1.1.26