2424
2525#include " ADFWriter.h"
2626#include " ArduinoInterface.h"
27+ #include < stdint.h>
2728#ifdef _WIN32
2829#include < conio.h>
2930#else
@@ -184,31 +185,45 @@ void programmeSetting(const std::wstring& port, const std::wstring& settingName,
184185 printf (" Setting %ls was not found.\n\n " , settingName.c_str ());
185186}
186187
188+ #define MODE_ADF 0
189+ #define MODE_IMG 1
190+ #define MODE_ST 2
191+ #define MODE_SCP 3
192+ #define MODE_IPF 4
187193
194+ static const char * ModeNames[] = { " ADF" , " IMG" , " ST" , " SCP" , " IPF" };
188195
189- // Read an ADF/SCP/IPF file and write it to disk
190- void adf2Disk (const std::wstring& filename, bool verify) {
191-
192- bool hdMode = false ;
193- bool isSCP = true ;
194- bool isIPF = false ;
195196
197+ // Read an ADF/SCP/IPF/IMG/IMA/ST file and write it to disk
198+ void file2Disk (const std::wstring& filename, bool verify) {
196199 const wchar_t * extension = wcsrchr (filename.c_str (), L' .' );
200+ int32_t mode = -1 ;
201+
197202 if (extension) {
198203 extension++;
199- isSCP = iequals (extension, L" SCP" );
200- isIPF = iequals (extension, L" IPF" );
204+ if (iequals (extension, L" SCP" )) mode = MODE_SCP; else
205+ if (iequals (extension, L" ADF" )) mode = MODE_ADF; else
206+ if (iequals (extension, L" IMG" )) mode = MODE_IMG; else
207+ if (iequals (extension, L" IMA" )) mode = MODE_IMG; else
208+ if (iequals (extension, L" ST" )) mode = MODE_ST; else
209+ if (iequals (extension, L" IPF" )) mode = MODE_IPF;
201210 }
202- if (isIPF) printf (" \n Write disk from IPF mode\n\n " ); else
203- if (isSCP) printf (" \n Write disk from SCP mode\n\n " ); else {
204- printf (" \n Write disk from ADF mode\n\n " );
205- if (!verify) printf (" WARNING: It is STRONGLY recommended to write with verify support turned on.\r\n\r\n " );
206- }
211+ if (mode < 0 ) {
212+ printf (" File extension not recognised. It must be one of:\n\n " );
213+ printf (" .ADF, .IMG, .IMA, .ST, .SCP or .IPF\n\n " );
214+ return ;
215+ }
216+ bool hdMode = false ;
217+ bool isSCP = true ;
218+ bool isIPF = false ;
207219
220+ printf (" \n Writing %s file to disk\n\n " , ModeNames[mode]);
221+ if (!((mode == MODE_IPF) || (mode == MODE_SCP))) {
222+ if (!verify) printf (" WARNING: It is STRONGLY recommended to write with verify turned on.\r\n\r\n " );
223+ }
208224
209- // Detect disk speed
225+ // Detect disk speed/density
210226 const ArduinoFloppyReader::FirmwareVersion v = writer.getFirwareVersion ();
211-
212227 if (((v.major == 1 ) && (v.minor >= 9 )) || (v.major > 1 )) {
213228 if ((!isSCP) && (!isIPF))
214229 if (writer.GuessDiskDensity (hdMode) != ArduinoFloppyReader::ADFResult::adfrComplete) {
@@ -218,8 +233,9 @@ void adf2Disk(const std::wstring& filename, bool verify) {
218233 }
219234
220235 ADFResult result;
221-
222- if (isIPF) {
236+
237+ switch (mode) {
238+ case MODE_IPF:{
223239 result = writer.IPFToDisk (filename, false , [](const int currentTrack, const DiskSurface currentSide, bool isVerifyError, const CallbackOperation operation) ->WriteResponse {
224240 if (isVerifyError) {
225241 char input;
@@ -244,14 +260,25 @@ void adf2Disk(const std::wstring& filename, bool verify) {
244260#endif
245261 return WriteResponse::wrContinue;
246262 });
247- }
248- else
249- if (isSCP) {
263+ }
264+ break ;
265+
266+ case MODE_SCP: {
250267 result = writer.SCPToDisk (filename, false , [](const int currentTrack, const DiskSurface currentSide, bool isVerifyError, const CallbackOperation operation) ->WriteResponse {
268+ printf (" \n Writing Track %i, %s side " , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" );
269+ #ifndef _WIN32
270+ fflush (stdout);
271+ #endif
272+ return WriteResponse::wrContinue;
273+ });
274+ }
275+ break ;
276+ case MODE_ADF: {
277+ result = writer.ADFToDisk (filename, hdMode, verify, true , false , true , [](const int currentTrack, const DiskSurface currentSide, bool isVerifyError, const CallbackOperation operation) ->WriteResponse {
251278 if (isVerifyError) {
252279 char input;
253280 do {
254- printf (" \r Disk write verify error on track %i, %s side. [R]etry, [S]kip, [A]bort? " , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" );
281+ printf (" \n Disk write verify error on track %i, %s side. [R]etry, [S]kip, [A]bort? " , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" );
255282#ifdef _WIN32
256283 input = toupper (_getch ());
257284#else
@@ -265,14 +292,17 @@ void adf2Disk(const std::wstring& filename, bool verify) {
265292 case ' A' : return WriteResponse::wrAbort;
266293 }
267294 }
268- printf (" \n Writing Track %i, %s side " , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" );
295+ printf (" \r Writing Track %i, %s side " , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" );
269296#ifndef _WIN32
270297 fflush (stdout);
271298#endif
272299 return WriteResponse::wrContinue;
273300 });
274- } else {
275- result = writer.ADFToDisk (filename, hdMode, verify, true , false , true , [](const int currentTrack, const DiskSurface currentSide, bool isVerifyError, const CallbackOperation operation) ->WriteResponse {
301+ break ;
302+ }
303+ case MODE_IMG:
304+ case MODE_ST: {
305+ result = writer.sectorFileToDisk (filename, hdMode, verify, true , false , mode == MODE_ST, [](const int currentTrack, const DiskSurface currentSide, bool isVerifyError, const CallbackOperation operation) ->WriteResponse {
276306 if (isVerifyError) {
277307 char input;
278308 do {
@@ -290,12 +320,14 @@ void adf2Disk(const std::wstring& filename, bool verify) {
290320 case ' A' : return WriteResponse::wrAbort;
291321 }
292322 }
293- printf (" \n Writing Track %i, %s side " , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" );
323+ printf (" \r Writing Track %i, %s side " , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" );
294324#ifndef _WIN32
295325 fflush (stdout);
296326#endif
297327 return WriteResponse::wrContinue;
298328 });
329+ break ;
330+ }
299331 }
300332
301333 switch (result) {
@@ -323,34 +355,36 @@ void adf2Disk(const std::wstring& filename, bool verify) {
323355}
324356
325357
326- // Read a disk and save it to ADF or SCP files
327- void disk2ADF (const std::wstring& filename) {
358+
359+ // Read a disk and save it to ADF/SCP/IMG/IMA/ST files
360+ void disk2file (const std::wstring& filename) {
328361 const wchar_t * extension = wcsrchr (filename.c_str (), L' .' );
329- bool isADF = true ;
362+ int32_t mode = - 1 ;
330363
331364 if (extension) {
332365 extension++;
333- isADF = !iequals (extension, L" SCP" );
366+ if (iequals (extension, L" ADF" )) mode = MODE_ADF; else
367+ if (iequals (extension, L" SCP" )) mode = MODE_SCP; else
368+ if (iequals (extension, L" IMG" )) mode = MODE_IMG; else
369+ if (iequals (extension, L" IMA" )) mode = MODE_IMG; else
370+ if (iequals (extension, L" ST" )) mode = MODE_ST;
371+ }
372+ if (mode < 0 ) {
373+ printf (" File extension not recognised. It must be one of:\n\n " );
374+ printf (" .ADF, .IMG, .IMA, .ST or .SCP\n\n " );
375+ return ;
334376 }
335377
336- if (isADF) printf (" \n Create ADF from disk mode \n\n " ); else printf ( " \n Create SCP file from disk mode \n\n " );
378+ printf (" \n Creating %s file from disk\n\n " , ModeNames[mode] );
337379
338380 bool hdMode = false ;
339381
340382 // Detect disk speed
341- const ArduinoFloppyReader::FirmwareVersion v = writer.getFirwareVersion ();
342- /* DEBUG REMOVE THIS
343- if (((v.major == 1) && (v.minor >= 9)) || (v.major > 1)) {
344- if (writer.GuessDiskDensity(hdMode) != ArduinoFloppyReader::ADFResult::adfrComplete) {
345- printf("Unable to work out the density of the disk inserted.\n");
346- return;
347- }
348- }
349- */
383+ const ArduinoFloppyReader::FirmwareVersion v = writer.getFirwareVersion ();
350384
351385 // Get the current firmware version. Only valid if openDevice is successful
352386 if ((v.major == 1 ) && (v.minor < 8 )) {
353- if (!isADF ) {
387+ if (mode == MODE_SCP ) {
354388 printf (" This requires firmware V1.8 or newer.\n " );
355389 return ;
356390 }
@@ -361,7 +395,7 @@ void disk2ADF(const std::wstring& filename) {
361395 }
362396 }
363397
364- auto callback = [isADF , hdMode](const int currentTrack, const DiskSurface currentSide, const int retryCounter, const int sectorsFound, const int badSectorsFound, const int totalSectors, const CallbackOperation operation) ->WriteResponse {
398+ auto callback = [mode , hdMode](const int currentTrack, const DiskSurface currentSide, const int retryCounter, const int sectorsFound, const int badSectorsFound, const int totalSectors, const CallbackOperation operation) ->WriteResponse {
365399 if (retryCounter > 20 ) {
366400 char input;
367401 do {
@@ -378,11 +412,11 @@ void disk2ADF(const std::wstring& filename) {
378412 case ' A' : return WriteResponse::wrAbort;
379413 }
380414 }
381- if (isADF ) {
382- printf (" \r Reading %s Track %i, %s side (retry: %i) - Got %i/%i sectors (%i bad found) " , hdMode ? " HD" : " DD" , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" , retryCounter, sectorsFound, totalSectors, badSectorsFound );
415+ if (mode == MODE_SCP ) {
416+ printf (" \r Reading %s Track %i, %s side " , hdMode ? " HD" : " DD" , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" );
383417 }
384418 else {
385- printf (" \r Reading %s Track %i, %s side " , hdMode ? " HD" : " DD" , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" );
419+ printf (" \r Reading %s Track %i, %s side (retry: %i) - Got %i/%i sectors (%i bad found) " , hdMode ? " HD" : " DD" , currentTrack, (currentSide == DiskSurface::dsUpper) ? " Upper" : " Lower" , retryCounter, sectorsFound, totalSectors, badSectorsFound );
386420 }
387421#ifndef _WIN32
388422 fflush (stdout);
@@ -391,9 +425,14 @@ void disk2ADF(const std::wstring& filename) {
391425 };
392426
393427 ADFResult result;
394-
395- if (isADF) result = writer.DiskToADF (filename, hdMode, 80 , callback); else result = writer.DiskToSCP (filename, hdMode, 80 , 3 , callback);
396428
429+ switch (mode) {
430+ case MODE_ADF: result = writer.DiskToADF (filename, hdMode, 80 , callback); break ;
431+ case MODE_SCP: result = writer.DiskToSCP (filename, hdMode, 80 , 3 , callback); break ;
432+ case MODE_ST:
433+ case MODE_IMG: result = writer.diskToIBMST (filename, hdMode, callback); break ;
434+ }
435+
397436 switch (result) {
398437 case ADFResult::adfrComplete: printf (" \r File created successfully. " ); break ;
399438 case ADFResult::adfrAborted: printf (" \r File aborted. " ); break ;
@@ -407,6 +446,19 @@ void disk2ADF(const std::wstring& filename) {
407446 }
408447}
409448
449+ // Run drive cleaning action
450+ void runCleaning (const std::wstring& port) {
451+ printf (" \r Running drive head cleaning on COM port: %ls\n\n " , port.c_str ());
452+ writer.runClean ([](const uint16_t position, const uint16_t maxPosition)->bool {
453+ printf (" \r Progress: %i%% " , (position * 100 ) / maxPosition);
454+ #ifndef _WIN32
455+ fflush (stdout);
456+ #endif
457+ return true ;
458+ });
459+ printf (" \r Cleaning cycle completed.\n\n " );
460+ }
461+
410462// Run the diagnostics module
411463void runDiagnostics (const std::wstring& port) {
412464 printf (" \r Running diagnostics on COM port: %ls\n " ,port.c_str ());
@@ -444,24 +496,20 @@ int wmain(int argc, wchar_t* argv[], wchar_t *envp[])
444496int main (int argc, char * argv[], char *envp[])
445497#endif
446498{
447- printf (" DrawBridge aka Arduino Floppy Disk Reader/Writer V2.8.8 , Copyright (C) 2017-2022 Robert Smith\r\n " );
499+ printf (" DrawBridge aka Arduino Floppy Disk Reader/Writer V2.8.9 , Copyright (C) 2017-2024 Robert Smith\r\n " );
448500 printf (" Full sourcecode and documentation at https://amiga.robsmithdev.co.uk\r\n " );
449501 printf (" This is free software licenced under the GNU General Public Licence V3\r\n\r\n " );
450502
451503 if (argc < 2 ) {
452504 printf (" Usage:\r\n\n " );
453- printf (" To read a disk to an ADF file:\r\n " );
454- printf (" ArduinoFloppyReader <COMPORT> OutputFilename.ADF [READ]\r\n\r\n " );
455- printf (" To read a disk to an SCP file:\r\n " );
456- printf (" ArduinoFloppyReader <COMPORT> OutputFilename.SCP [READ]\r\n\r\n " );
457- printf (" To write an ADF file to disk:\r\n " );
458- printf (" ArduinoFloppyReader <COMPORT> InputFilename.ADF WRITE [VERIFY]\r\n\r\n " );
459- printf (" To write an SCP file to disk:\r\n " );
460- printf (" ArduinoFloppyReader <COMPORT> InputFilename.SCP WRITE\r\n\r\n " );
461- printf (" To write an IPF file to disk:\r\n " );
462- printf (" ArduinoFloppyReader <COMPORT> InputFilename.IPF WRITE\r\n\r\n " );
505+ printf (" To read a disk to a file (TYPE can be ADF, SCP, IMA, IMG, ST):\r\n " );
506+ printf (" ArduinoFloppyReader <COMPORT> OutputFilename.TYPE [READ]\r\n\r\n " );
507+ printf (" To write a file to disk (TYPE can be ADF, SCP, IMA, IMG, ST, IPF):\r\n " );
508+ printf (" ArduinoFloppyReader <COMPORT> InputFilename.TYPE WRITE [VERIFY]\r\n\r\n " );
463509 printf (" To start interface diagnostics:\r\n " );
464510 printf (" ArduinoFloppyReader <COMPORT> DIAGNOSTIC\r\n\r\n " );
511+ printf (" To start disk drive head cleaning:\r\n " );
512+ printf (" ArduinoFloppyReader <COMPORT> CLEAN\r\n\r\n " );
465513 printf (" To see the current EEPROM Ssettings:\r\n " );
466514 printf (" ArduinoFloppyReader <COMPORT> SETTINGS\r\n\r\n " );
467515 printf (" To set the status of one of the see EEPROM settings:\r\n " );
@@ -517,23 +565,27 @@ int main(int argc, char* argv[], char *envp[])
517565#ifdef _WIN32
518566 bool writeMode = (argc > 3 ) && (iequals (argv[3 ], L" WRITE" ));
519567 bool verify = (argc > 4 ) && (iequals (argv[4 ], L" VERIFY" ));
520- if (argc >= 2 ) {
521- std::wstring port = argv[1 ];
568+ if (argc >= 3 ) {
522569 std::wstring filename = argv[2 ];
523570#else
524571 bool writeMode = (argc > 3 ) && (iequals (argv[3 ], " WRITE" ));
525572 bool verify = (argc > 4 ) && (iequals (argv[4 ], " VERIFY" ));
526573 if (argc >= 2 ) {
527574 std::wstring filename = atw (argv[2 ]);
528- #endif
575+ #endif
529576 if (iequals (filename, L" DIAGNOSTIC" )) {
530577 runDiagnostics (port);
531578 } else
532579 if (!writer.openDevice (port)) {
533580 printf (" \r Error opening COM port: %s " , writer.getLastError ().c_str ());
534581 }
535582 else {
536- if (writeMode) adf2Disk (filename.c_str (), verify); else disk2ADF (filename.c_str ());
583+ if (iequals (filename, L" CLEAN" )) {
584+ runCleaning (port);
585+ }
586+ else {
587+ if (writeMode) file2Disk (filename.c_str (), verify); else disk2file (filename.c_str ());
588+ }
537589 writer.closeDevice ();
538590 }
539591 }
0 commit comments