Skip to content

Commit 27321cb

Browse files
committed
Added support for reading and writing Atari ST Disks
Added support for reading and writing PC Disks Added drive head cleaning mode
1 parent 2bc2c32 commit 27321cb

26 files changed

+1167
-203
lines changed

ArduinoFloppyReader/ArduinoFloppyReader/ArduinoFloppyReader.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
<ClInclude Include="..\lib\capsapi\CapsPlug.h" />
156156
<ClInclude Include="..\lib\capsapi\Comtype.h" />
157157
<ClInclude Include="..\lib\ftdi.h" />
158+
<ClInclude Include="..\lib\ibm_sectors.h" />
158159
<ClInclude Include="..\lib\pll.h" />
159160
<ClInclude Include="..\lib\RotationExtractor.h" />
160161
<ClInclude Include="..\lib\SerialIO.h" />
@@ -176,6 +177,7 @@
176177
</ClCompile>
177178
<ClCompile Include="..\lib\capsapi\CapsPlug.cpp" />
178179
<ClCompile Include="..\lib\ftdi.cpp" />
180+
<ClCompile Include="..\lib\ibm_sectors.cpp" />
179181
<ClCompile Include="..\lib\pll.cpp" />
180182
<ClCompile Include="..\lib\RotationExtractor.cpp">
181183
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>

ArduinoFloppyReader/ArduinoFloppyReader/ArduinoFloppyReader.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@
5757
<ClInclude Include="resource.h">
5858
<Filter>Header Files</Filter>
5959
</ClInclude>
60+
<ClInclude Include="..\lib\ibm_sectors.h">
61+
<Filter>Source Files</Filter>
62+
</ClInclude>
6063
</ItemGroup>
6164
<ItemGroup>
6265
<ClCompile Include="Main.cpp">
@@ -83,6 +86,9 @@
8386
<ClCompile Include="..\lib\pll.cpp">
8487
<Filter>Source Files</Filter>
8588
</ClCompile>
89+
<ClCompile Include="..\lib\ibm_sectors.cpp">
90+
<Filter>Source Files</Filter>
91+
</ClCompile>
8692
</ItemGroup>
8793
<ItemGroup>
8894
<ResourceCompile Include="DrawBridge.rc">

ArduinoFloppyReader/ArduinoFloppyReader/Main.cpp

Lines changed: 113 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
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("\nWrite disk from IPF mode\n\n"); else
203-
if (isSCP) printf("\nWrite disk from SCP mode\n\n"); else {
204-
printf("\nWrite 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("\nWriting %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("\nWriting 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("\rDisk write verify error on track %i, %s side. [R]etry, [S]kip, [A]bort? ", currentTrack, (currentSide == DiskSurface::dsUpper) ? "Upper" : "Lower");
281+
printf("\nDisk 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("\nWriting Track %i, %s side ", currentTrack, (currentSide == DiskSurface::dsUpper) ? "Upper" : "Lower");
295+
printf("\rWriting 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("\nWriting Track %i, %s side ", currentTrack, (currentSide == DiskSurface::dsUpper) ? "Upper" : "Lower");
323+
printf("\rWriting 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("\nCreate ADF from disk mode\n\n"); else printf("\nCreate SCP file from disk mode\n\n");
378+
printf("\nCreating %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("\rReading %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("\rReading %s Track %i, %s side ", hdMode ? "HD" : "DD", currentTrack, (currentSide == DiskSurface::dsUpper) ? "Upper" : "Lower");
383417
}
384418
else {
385-
printf("\rReading %s Track %i, %s side ", hdMode ? "HD" : "DD", currentTrack, (currentSide == DiskSurface::dsUpper) ? "Upper" : "Lower");
419+
printf("\rReading %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("\rFile created successfully. "); break;
399438
case ADFResult::adfrAborted: printf("\rFile 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("\rRunning 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("\rProgress: %i%% ", (position * 100) / maxPosition);
454+
#ifndef _WIN32
455+
fflush(stdout);
456+
#endif
457+
return true;
458+
});
459+
printf("\rCleaning cycle completed.\n\n");
460+
}
461+
410462
// Run the diagnostics module
411463
void runDiagnostics(const std::wstring& port) {
412464
printf("\rRunning diagnostics on COM port: %ls\n",port.c_str());
@@ -444,24 +496,20 @@ int wmain(int argc, wchar_t* argv[], wchar_t *envp[])
444496
int 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("\rError 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
}
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)