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

Contents of /public/pc/tools/osdk/main/FloppyBuilder/FloppyBuilder.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1393 - (show annotations)
Sat Mar 18 19:32:02 2017 UTC (2 years, 8 months ago) by dbug
File size: 17482 byte(s)
FloppyBuilder 1.1
- Added support for sector interleave: The 'DefineDisk' now has a additional parameter which indicates how far the next sector is (defaults to 1 for a linear search)

1
2 #include <cstdlib>
3 #include <stdio.h>
4 #include <string.h>
5 #include <sstream>
6 #include <iostream>
7 #include <vector>
8
9 #include "infos.h"
10 #include "common.h"
11 #include "Floppy.h"
12
13
14 // while (std::getline(iss,item,' '))
15 bool GetNextToken(std::string& returnedToken,std::string& restOfLine,int lineNumber)
16 {
17 returnedToken.clear();
18
19 const char* startOfLine =restOfLine.c_str();
20 const char* currentPosition=startOfLine;
21 char car;
22
23 // First skip all the white space stuff
24 while ( (car=*currentPosition) && ( (car==' ') || (car=='\t') ) )
25 {
26 ++currentPosition;
27 }
28
29 // Then depending of the character we have, we need a terminator token
30 if (car)
31 {
32 char match =0;
33
34 if (car=='"')
35 {
36 match='"';
37 }
38 else
39 if (car=='{')
40 {
41 match='}';
42 }
43 else
44 if (car=='[')
45 {
46 match =']';
47 }
48
49 if (match)
50 {
51 // Push the starting character
52 returnedToken.push_back(car);
53 ++currentPosition;
54 }
55
56 while ( (car=*currentPosition) && ( (match && (car!=match)) || ( (!match) && ((car!=' ') && (car!='\t')) ) ) )
57 {
58 returnedToken.push_back(car);
59 ++currentPosition;
60 }
61
62 if (match && (car==match))
63 {
64 // Including the matching character
65 returnedToken.push_back(car);
66 ++currentPosition;
67 car=*currentPosition;
68 }
69
70 if (car)
71 {
72 // We have reach the end of the token, just make sure there's a white space behind
73 if ((car==' ') || (car=='\t'))
74 {
75 restOfLine=currentPosition;
76 }
77 else
78 {
79 // Parse error
80 ShowError("Parse error line '%d'\n",lineNumber);
81 }
82 }
83 else
84 {
85 // End of Line
86 restOfLine.clear();
87 }
88 return true;
89 }
90 return false;
91 }
92
93
94 class FloppyBuilder : public ArgumentParser
95 {
96 public:
97 FloppyBuilder(int argc,char *argv[])
98 : ArgumentParser(argc,argv)
99 {
100 }
101
102 int Main();
103
104
105 private:
106 std::string m_FormatVersion;
107 };
108
109
110 int main(int argc, char *argv[])
111 {
112 try
113 {
114 //
115 // Some initialization for the common library
116 //
117 SetApplicationParameters(
118 "FloppyBuilder",
119 TOOL_VERSION_MAJOR,
120 TOOL_VERSION_MINOR,
121 "{ApplicationName} - Version {ApplicationVersion} - This program is a part of the OSDK\r\n"
122 "\r\n"
123 "Author:\r\n"
124 " (c) 2002 Debrune Jerome for the initial version \r\n"
125 " (c) 2015 Pointier Mickael for the subsequent changes \r\n"
126 "\r\n"
127 "Purpose:\r\n"
128 " Generating bootable floppies for the Oric computer.\r\n"
129 "\r\n"
130 "Usage:\r\n"
131 " {ApplicationName} [switches] <init|build|extract> <description file path>\r\n"
132 "\r\n"
133 "Switches:\r\n"
134 " -Dname=value Add define\r\n"
135 " -DTEST=23 \r\n"
136 "\r\n"
137 );
138
139 FloppyBuilder floppyBuilder(argc,argv);
140 return floppyBuilder.Main();
141 }
142
143 catch (std::exception& e)
144 {
145 ShowError("Exception thrown: %s",e.what());
146 }
147 }
148
149
150
151 int FloppyBuilder::Main()
152 {
153 Floppy floppy;
154
155 while (ProcessNextArgument())
156 {
157 if (IsSwitch("-D"))
158 {
159 // One more define
160 std::string defineName=GetStringValue();
161 std::string defineValue;
162 std::size_t found = defineName.find("=");
163 if (found!=std::string::npos)
164 {
165 defineValue =defineName.substr(found+1);
166 defineName =defineName.substr(0,found);
167 }
168 floppy.AddDefine(defineName,defineValue);
169 //printf("--------------> %s=%s\r\n",defineName.c_str(),defineValue.c_str());
170 }
171 }
172
173 if (GetParameterCount()!=2)
174 {
175 ShowError(nullptr);
176 }
177
178 bool extract=false;
179 const char* sequence=GetParameter(0);
180 if (!strcmp(sequence,"init"))
181 {
182 floppy.AllowMissingFiles(true);
183 }
184 else
185 if (!strcmp(sequence,"extract"))
186 {
187 floppy.AllowMissingFiles(true);
188 extract=true;
189 }
190 else
191 if (!strcmp(sequence,"build"))
192 {
193 floppy.AllowMissingFiles(false);
194 }
195 else
196 {
197 ShowError("The first parameter should be either 'init', 'build' or 'extract'.");
198 }
199
200
201 //
202 // Open the description file
203 //
204 const char* description_name(GetParameter(1));
205 std::vector<std::string> script;
206 if (!LoadText(description_name,script))
207 {
208 ShowError("Can't load script file '%s'\n",description_name);
209 }
210
211
212 std::string outputLayoutFileName;
213 std::string targetFloppyDiskName;
214
215 int lineNumber=0;
216 for (auto it(script.begin());it!=script.end();++it)
217 {
218 ++lineNumber;
219
220 std::string currentLine(*it);
221
222 std::size_t found = currentLine.find(";");
223 if (found!=std::string::npos)
224 {
225 // Comments, just skip them
226 currentLine=currentLine.substr(0,found);
227 }
228
229 std::istringstream iss(currentLine);
230
231 std::map<std::string,std::string> metadata;
232 std::string item;
233 std::vector<std::string> tokens;
234 //while (std::getline(iss,item,' '))
235 while (GetNextToken(item,currentLine,lineNumber))
236 {
237 // Remove eventual superfluous spaces and tabs
238 item=StringTrim(item);
239 if (!item.empty())
240 {
241 if ( ((*item.begin())=='[') && ((*item.rbegin())==']') )
242 {
243 // Let's say it's metadata
244 std::string metaItem=StringTrim(item,"[]");
245 std::size_t found = metaItem.find(":");
246 if (found!=std::string::npos)
247 {
248 // Comments, just skip them
249 std::string key =metaItem.substr(0,found);
250 std::string value=metaItem.substr(found+1);
251 metadata[key]=value;
252 }
253 else
254 {
255 ShowError("Syntax error line (%d), found invalid '%s' metadata format, should be '[key:value]'\n",lineNumber,item.c_str());
256 }
257 }
258 else
259 {
260 // Let's say it's an actual parameter
261 item=StringTrim(item,"\"");
262 tokens.push_back(item);
263 }
264 }
265 }
266
267 if (!tokens.empty())
268 {
269 if (tokens[0]=="FormatVersion")
270 {
271 if (tokens.size()==2)
272 {
273 m_FormatVersion=tokens[1];
274 // We found a version string, let's analyze what we can do with it.
275 char* end;
276 int majorVersion =std::strtoul(m_FormatVersion.c_str(),&end,10);
277 if (end && end[0]=='.')
278 {
279 ++end;
280 int minorVersion =std::strtoul(end,&end,10);
281 if ( (majorVersion>TOOL_VERSION_MAJOR) || ( (majorVersion==TOOL_VERSION_MAJOR) && (minorVersion>TOOL_VERSION_MINOR) ) )
282 {
283 ShowError("This is FloppyBuilder %u.%u, not able to handle the requested future FormatVersion %u.%u' \n",TOOL_VERSION_MAJOR,TOOL_VERSION_MINOR,majorVersion,minorVersion);
284 }
285 else
286 {
287 // This is at least a version equal to ours.
288 switch (majorVersion)
289 {
290 default:
291 case 0:
292 switch (minorVersion)
293 {
294 default:
295 case 19: ShowError("AddFile does not have a size parameter anymore\n");
296 case 20:
297 break;
298 }
299 break;
300 }
301 }
302 }
303 else
304 {
305 ShowError("Syntax error line (%d), syntax is 'FormatVersion major.minor' \n",lineNumber);
306 }
307 }
308 else
309 {
310 ShowError("Syntax error line (%d), syntax is 'FormatVersion major.minor' \n",lineNumber);
311 }
312 }
313 else
314 {
315 if (m_FormatVersion.empty())
316 {
317 ShowError("A 'FormatVersion major.minor' instruction is required at the start of the script\n");
318 }
319
320 if (tokens[0]=="LoadDiskTemplate")
321 {
322 if (tokens.size()==2)
323 {
324 const std::string& templateDisk(tokens[1]);
325 if (!floppy.LoadDisk(templateDisk.c_str()))
326 {
327 ShowError("Can't load '%s'\n",templateDisk.c_str());
328 }
329
330 }
331 else
332 {
333 ShowError("Syntax error line (%d), syntax is 'LoadDiskTemplate FilePath' \n",lineNumber);
334 }
335 }
336 else
337 if (tokens[0]=="DefineDisk")
338 {
339 if ((tokens.size()==4) || (tokens.size()==5))
340 {
341 int numberOfSides =std::atoi(tokens[1].c_str());
342 int numberOfTracks =std::atoi(tokens[2].c_str());
343 int numberOfSectors =std::atoi(tokens[3].c_str());
344
345 int sectorInterleave=1;
346 if ((tokens.size()==5))
347 {
348 sectorInterleave =std::atoi(tokens[4].c_str());
349 }
350
351 if ( numberOfSides!=2 )
352 {
353 ShowError("Syntax error line (%d), numberOfSides has to be 2 (so far)\n",lineNumber);
354 }
355
356 /*
357 if ( numberOfTracks!=42 )
358 {
359 ShowError("Syntax error line (%d), numberOfTracks has to be 42 (so far)\n",lineNumber);
360 }
361 */
362
363 if ( numberOfSectors!=17 )
364 {
365 ShowError("Syntax error line (%d), numberOfSectors has to be 17 (so far)\n",lineNumber);
366 }
367
368 if ( sectorInterleave>=numberOfSectors )
369 {
370 ShowError("Syntax error line (%d), the sector interleave value makes no sense\n",lineNumber);
371 }
372
373 if (!floppy.CreateDisk(numberOfSides,numberOfTracks,numberOfSectors,sectorInterleave))
374 {
375 ShowError("Can't create the requested disk format\n");
376 }
377
378 }
379 else
380 {
381 ShowError("Syntax error line (%d), syntax is 'DefineDisk numberOfSides numberOfTracks numberOfSectors' \n",lineNumber);
382 }
383 }
384 else
385 if (tokens[0]=="OutputLayoutFile")
386 {
387 if (tokens.size()==2)
388 {
389 outputLayoutFileName=tokens[1];
390 }
391 else
392 {
393 ShowError("Syntax error line (%d), syntax is 'OutputLayoutFile FilePath' \n",lineNumber);
394 }
395 }
396 else
397 if (tokens[0]=="OutputFloppyFile")
398 {
399 if (tokens.size()==2)
400 {
401 targetFloppyDiskName=tokens[1];
402 }
403 else
404 {
405 ShowError("Syntax error line (%d), syntax is 'targetFloppyDiskName FilePath' \n",lineNumber);
406 }
407 }
408 else
409 if (tokens[0]=="SetPosition")
410 {
411 if (tokens.size()==3)
412 {
413 int currentTrack =std::atoi(tokens[1].c_str());
414 if ( (currentTrack<0) || (currentTrack>41) )
415 {
416 ShowError("Syntax error line (%d), TrackNumber has to be between 0 and 41' \n",lineNumber);
417 }
418 int currentSector=std::atoi(tokens[2].c_str());
419 if ( (currentSector<0) || (currentSector>41) )
420 {
421 ShowError("Syntax error line (%d), SectorNumber has to be between 1 and 17' \n",lineNumber);
422 }
423 floppy.SetPosition(currentTrack,currentSector);
424 }
425 else
426 {
427 ShowError("Syntax error line (%d), syntax is 'SetPosition TrackNumber SectorNumber' \n",lineNumber);
428 }
429 }
430 else
431 if (tokens[0]=="WriteSector")
432 {
433 if (tokens.size()==2)
434 {
435 std::string fileName=tokens[1];
436 if (!floppy.WriteSector(fileName.c_str()))
437 {
438 ShowError("Error line (%d), could not write file '%s' to disk. Make sure you have a valid floppy format declared. \n",lineNumber,fileName.c_str());
439 }
440 }
441 else
442 {
443 ShowError("Syntax error line (%d), syntax is 'WriteSector FilePath' \n",lineNumber);
444 }
445 }
446 else
447 if (tokens[0]=="WriteLoader")
448 {
449 if (tokens.size()==3)
450 {
451 std::string fileName=tokens[1];
452 int loadAddress=ConvertAdress(tokens[2].c_str());
453 if (!floppy.WriteLoader(fileName.c_str(),loadAddress))
454 {
455 ShowError("Error line (%d), could not write file '%s' to disk. Make sure you have a valid floppy format declared. \n",lineNumber,fileName.c_str());
456 }
457 }
458 else
459 {
460 ShowError("Syntax error line (%d), syntax is 'WriteLoader FilePath LoadAddress' \n",lineNumber);
461 }
462 }
463 else
464 if (tokens[0]=="AddFile")
465 {
466 if (tokens.size()==2)
467 {
468 std::string fileName=tokens[1];
469 if (!floppy.WriteFile(fileName.c_str(),false,metadata))
470 {
471 ShowError("Error line (%d), could not write file '%s' to disk. Make sure you have a valid floppy format declared. \n",lineNumber,fileName.c_str());
472 }
473 }
474 else
475 {
476 ShowError("Syntax error line (%d), syntax is 'AddFile FilePath' \n",lineNumber);
477 }
478 }
479 else
480 if (tokens[0]=="AddTapFile")
481 {
482 if (tokens.size()==2)
483 {
484 std::string fileName=tokens[1];
485 if (!floppy.WriteFile(fileName.c_str(),true,metadata))
486 {
487 ShowError("Error line (%d), could not write file '%s' to disk. Make sure you have a valid floppy format declared. \n",lineNumber,fileName.c_str());
488 }
489 }
490 else
491 {
492 ShowError("Syntax error line (%d), syntax is 'AddTapFile FilePath' \n",lineNumber);
493 }
494 }
495 else
496 if (tokens[0]=="ReserveSectors")
497 {
498 if ( (tokens.size()==2) || (tokens.size()==3) )
499 {
500 int sectorCount=ConvertAdress(tokens[1].c_str());
501 int fillValue=0;
502 if (tokens.size()==3)
503 {
504 fillValue=ConvertAdress(tokens[2].c_str());
505 }
506 if (!floppy.ReserveSectors(sectorCount,fillValue,metadata))
507 {
508 ShowError("Error line (%d), could not reserve %u sectors on the disk. Make sure you have a valid floppy format declared. \n",lineNumber,sectorCount);
509 }
510 }
511 else
512 {
513 ShowError("Syntax error line (%d), syntax is 'ReserveSectors SectorCount [FillValue]' \n",lineNumber);
514 }
515 }
516 else
517 if (tokens[0]=="SaveFile")
518 {
519 // ; SaveFile "File_0.bin" $80 $01 $47 ; Name Track Sector Lenght adress
520 if (tokens.size()==5)
521 {
522 std::string fileName=tokens[1];
523 int trackNumber =ConvertAdress(tokens[2].c_str());
524 int sectorNumber=ConvertAdress(tokens[3].c_str());
525 int sectorCount =ConvertAdress(tokens[4].c_str());
526 if (!floppy.ExtractFile(fileName.c_str(),trackNumber,sectorNumber,sectorCount))
527 {
528 ShowError("Error line (%d), could not extract file '%s' from disk. Make sure you have a valid floppy format declared and some available disk space. \n",lineNumber,fileName.c_str());
529 }
530 }
531 else
532 {
533 ShowError("Syntax error line (%d), syntax is 'ExtractFile FilePath TrackNumber SectorNumber SectorCount' \n",lineNumber);
534 }
535 }
536 else
537 if (tokens[0]=="AddDefine")
538 {
539 if (tokens.size()==3)
540 {
541 floppy.AddDefine(tokens[1],tokens[2]);
542 }
543 else
544 {
545 ShowError("Syntax error line (%d), syntax is 'AddDefine DefineName DefineValue' \n",lineNumber);
546 }
547 }
548 else
549 if (tokens[0]=="SetCompressionMode")
550 {
551 if (tokens.size()==2)
552 {
553 if (tokens[1]=="None")
554 {
555 floppy.SetCompressionMode(e_CompressionNone);
556 }
557 else
558 if (tokens[1]=="FilePack")
559 {
560 floppy.SetCompressionMode(e_CompressionFilepack);
561 }
562 else
563 {
564 ShowError("Syntax error line (%d), '%s' is not a valid compression mode, it should be either 'None' or 'FilePack' \n",lineNumber,tokens[1].c_str());
565 }
566 }
567 else
568 {
569 ShowError("Syntax error line (%d), syntax is 'SetCompressionMode [None|FilePack]' \n",lineNumber);
570 }
571 }
572 else
573 {
574 ShowError("Syntax error line (%d), unknown keyword '%s' \n",lineNumber,tokens[0].c_str());
575 }
576 }
577 }
578 }
579
580
581 if (!extract)
582 {
583 // We write the resulting files only in 'init' or 'build' mode
584 if (!floppy.SaveDescription(outputLayoutFileName.c_str()))
585 {
586 ShowError("Failed saving description '%s'\n",outputLayoutFileName.c_str());
587 }
588
589 if (!floppy.SaveDisk(targetFloppyDiskName.c_str()))
590 {
591 ShowError("Failed saving disk '%s'\n",targetFloppyDiskName.c_str());
592 }
593 else
594 {
595 printf("Successfully created '%s'\n",targetFloppyDiskName.c_str());
596 }
597 }
598 return 0;
599 }

  ViewVC Help
Powered by ViewVC 1.1.26