355 lines
9.4 KiB
Plaintext
355 lines
9.4 KiB
Plaintext
uses
|
|
dos, crt,
|
|
helpers,
|
|
fdc;
|
|
|
|
const
|
|
SEP = '--------------------------------------------------------------------------';
|
|
|
|
var
|
|
tmp: TFDCBbuffer;
|
|
drive: byte;
|
|
i: integer;
|
|
startTrack, maxTrack: byte;
|
|
ff: file;
|
|
tries, track, head, sector, sc: byte;
|
|
out_file_name, d: string;
|
|
fdcIOErrorBackup: byte;
|
|
maxTries: byte;
|
|
testMode, motorOffMethod, showDump: boolean;
|
|
c: char;
|
|
showDumpSector: byte;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
function fdcGetSpeed(drv: byte): byte;
|
|
var
|
|
speed_id: byte;
|
|
begin
|
|
fdcGetSpeed:= 255; { speed unknown }
|
|
|
|
for speed_id:= 0 to FDC_SPEED_COUNT do
|
|
begin
|
|
port[FDC_REG_DIR]:= speed_id;
|
|
|
|
fdcReadSector(drv,0,0,1,FDC_SECTOR_1024,9); { ISDOS specific }
|
|
if fdcIOError = FDC_OK then
|
|
begin
|
|
fdcGetSpeed:= speed_id;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
fdcIOError:= FDC_ERR_SECTOR_NOT_FOUND;
|
|
end;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
function GetMaxTrack(param: string): byte;
|
|
begin
|
|
GetMaxTrack:= 79;
|
|
|
|
if param[3] = '1' then GetMaxTrack:= 80;
|
|
if param[3] = '2' then GetMaxTrack:= 81;
|
|
if param[3] = '3' then GetMaxTrack:= 82;
|
|
if param[3] = '4' then GetMaxTrack:= 83;
|
|
if param[3] = '5' then GetMaxTrack:= 84;
|
|
|
|
if length(param) = 2 then GetMaxTrack:= 82;
|
|
end;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
function GetMaxTries(param: string): byte;
|
|
begin
|
|
GetMaxTries:= 3;
|
|
|
|
if param[3] = '4' then GetMaxTries:= 4;
|
|
if param[3] = '5' then GetMaxTries:= 5;
|
|
if param[3] = '6' then GetMaxTries:= 6;
|
|
if param[3] = '7' then GetMaxTries:= 7;
|
|
if param[3] = '8' then GetMaxTries:= 8;
|
|
if param[3] = '9' then GetMaxTries:= 9;
|
|
end;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
begin
|
|
ClrScr;
|
|
|
|
drive:= 0;
|
|
startTrack:= 0;
|
|
maxTrack:= 79;
|
|
out_file_name:= '_isdos.isd';
|
|
maxTries:= 5;
|
|
testMode:= false;
|
|
motorOffMethod:= false;
|
|
showDump:= false;
|
|
showDumpSector:= 1;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
if ParamCount = 1 then
|
|
begin
|
|
d:= strlo(ParamStr(1));
|
|
|
|
{ drive }
|
|
if d = 'a:' then drive:= 0;
|
|
if d = 'b:' then drive:= 1;
|
|
end;
|
|
|
|
if ParamCount > 1 then
|
|
begin
|
|
d:= strlo(ParamStr(1));
|
|
|
|
{ drive }
|
|
if d = 'a:' then drive:= 0;
|
|
if d = 'b:' then drive:= 1;
|
|
|
|
d:= strlo(ParamStr(2));
|
|
|
|
{ out file name}
|
|
if d[1] <> '/' then out_file_name:= d;
|
|
end;
|
|
|
|
for i:= 1 to ParamCount do
|
|
begin
|
|
d:= strlo(ParamStr(i));
|
|
if copy(d,1,2) = '/t' then
|
|
begin
|
|
testMode:= true;
|
|
startTrack:= 80;
|
|
maxTrack:= GetMaxTrack(d);
|
|
continue;
|
|
end;
|
|
if copy(d,1,2) = '/m' then
|
|
begin
|
|
maxTrack:= GetMaxTrack(d);
|
|
continue;
|
|
end;
|
|
if copy(d,1,2) = '/r' then
|
|
begin
|
|
maxTries:= GetMaxTries(d);
|
|
continue;
|
|
end;
|
|
if copy(d,1,2) = '/o' then
|
|
begin
|
|
motorOffMethod:= true;
|
|
continue;
|
|
end;
|
|
if copy(d,1,2) = '/d' then
|
|
begin
|
|
showDump:= true;
|
|
if (length(d) = 3) and (d[3] = '1') then showDumpSector:= 1;
|
|
if (length(d) = 3) and (d[3] = '2') then showDumpSector:= 2;
|
|
if (length(d) = 3) and (d[3] = '3') then showDumpSector:= 3;
|
|
if (length(d) = 3) and (d[3] = '4') then showDumpSector:= 4;
|
|
if (length(d) = 3) and (d[3] = '5') then showDumpSector:= 5;
|
|
if (length(d) = 3) and (d[3] = '6') then showDumpSector:= 6;
|
|
if (length(d) = 3) and (d[3] = '7') then showDumpSector:= 7;
|
|
if (length(d) = 3) and (d[3] = '8') then showDumpSector:= 8;
|
|
if (length(d) = 3) and (d[3] = '9') then showDumpSector:= 9;
|
|
continue;
|
|
end;
|
|
end;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
writeln('ZX Spectrum Navigator v1.15 Reading iS-DOS floppy disk');
|
|
writeln('https://zxsn.ru, RomanRom2@gmail.com');
|
|
writeln('Copyright (c) 1996-2026 RomanRom2');
|
|
writeln(SEP);
|
|
|
|
if strlo(ParamStr(1)) = '/h' then
|
|
begin
|
|
writeln('LD-ISDOS.EXE drive|key <file> <keys>');
|
|
writeln(' - key /dN try to show dump of track 0 head 0 sector N');
|
|
writeln(' by default N=1, means /d is the same /d1');
|
|
writeln(' - key /o enable MotorOff method each 4,6,8 tries');
|
|
writeln(' - key /rN set max tries to read bad sector');
|
|
writeln(' by default N=5');
|
|
writeln(' - key /mN enable 8N tracks, N = 1..5 means 81-85 tracks');
|
|
writeln(' /m is the same /m3 for 83');
|
|
writeln('by default drive [A:], file name gets from disk name');
|
|
writeln(SEP);
|
|
writeln('Examples:');
|
|
writeln('LD-ISDOS.EXE /m5 - dump disk A: names as DiskName with max tracks');
|
|
writeln('LD-ISDOS.EXE b: - dump disk B: names as DiskName');
|
|
writeln('LD-ISDOS.EXE a: MYDSK - dump disk A: names as MYDSK');
|
|
writeln('LD-ISDOS.EXE a: MYDSK /m2 - dump disk A: names as MYDSK with 82 tracks');
|
|
writeln('LD-ISDOS.EXE a: /d9 - dump disk A: names as DiskName with dump sector 9');
|
|
writeln('LD-ISDOS.EXE /d /r2 - dump disk A: names as DiskName with dump sector 1');
|
|
writeln(' and 2 retries to read bad sectors');
|
|
end
|
|
else
|
|
begin
|
|
writeln('LD-ISDOS.EXE /h - for help');
|
|
end;
|
|
writeln(SEP);
|
|
|
|
writeln;
|
|
if strlo(ParamStr(1)) = '/h' then exit;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
|
|
writeln('Drive ',chr(drive+65),': is initializing...');
|
|
|
|
fdcInit(drive, FDC_SECTOR_1024);
|
|
if fdcIOError <> FDC_OK then
|
|
begin
|
|
writeln('FDC init error ['+fdcErrorStr(fdcIOError)+']');
|
|
fdcRecalibrate(drive);
|
|
fdcMotorOff;
|
|
exit;
|
|
end;
|
|
|
|
writeln(fdcErrorStr(fdcIOError),', ',fdcSpeedStr(fdcGetSpeed(drive)));{}
|
|
|
|
{ do not show it in test mode }
|
|
if not testMode then
|
|
begin
|
|
{ check 1st sector for disk name }
|
|
fdcReadSector(drive,0,0,1,FDC_SECTOR_1024,9);
|
|
if fdcIOError <> FDC_OK then
|
|
begin
|
|
writeln('1st sector read error ['+fdcErrorStr(fdcIOError)+']');
|
|
fdcRecalibrate(drive);
|
|
fdcMotorOff;
|
|
exit;
|
|
end;
|
|
|
|
{ get disk name }
|
|
d:=''; for i:=1 to 8 do if fdcBuf[i+2]<>32 then d:=d+chr(fdcBuf[i+2]);
|
|
if out_file_name = '_isdos.isd' then out_file_name:= hob2pc(d)+'.isd';;
|
|
write('Disk name: [',d,']');
|
|
|
|
out_file_name:= CheckEx(out_file_name);
|
|
writeln(' (',out_file_name,')');
|
|
|
|
if motorOffMethod then writeln('MotorOff method each 4,6,8 tries is enabled');
|
|
|
|
if showDump then
|
|
begin
|
|
{ dump 1st sector }
|
|
fdcReadSector(drive,0,0,showDumpSector,FDC_SECTOR_1024,9);
|
|
writeln(SEP);
|
|
for i:= 0 to 15 do
|
|
begin
|
|
for track:= 0 to 15 do
|
|
begin
|
|
gotoxy((track+1)*3,wherey); write(dec2hex(strr(fdcBuf[1+i*16+track])));
|
|
gotoxy(51+(track+1),wherey);
|
|
if fdcBuf[1+i*16+track]>31 then write(chr(fdcBuf[1+i*16+track])) else write('.');
|
|
end;
|
|
writeln;
|
|
end;
|
|
|
|
writeln(SEP);
|
|
writeln('ESC - cancel, any key - continue');
|
|
|
|
c:= readkey;
|
|
if c = #27 then
|
|
begin
|
|
writeln;
|
|
writeln('Canceled.');
|
|
fdcRecalibrate(drive);
|
|
fdcMotorOff;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
writeln;
|
|
writeln('Dumping ',maxTrack+1,' tracks...');
|
|
end
|
|
else
|
|
begin
|
|
writeln;
|
|
writeln('TEST [',startTrack,'..',maxTrack+1,'] TRACKS MODE');
|
|
end;
|
|
|
|
|
|
{----------------------------------------------------------------------------}
|
|
if not testMode then
|
|
begin
|
|
{ do not dump in test mode }
|
|
assign(ff, out_file_name);
|
|
rewrite(ff, 1);
|
|
end;
|
|
|
|
|
|
for track:= startTrack to maxTrack do
|
|
begin
|
|
fdcSeek(drive, track);
|
|
|
|
for head:= 0 to 1 do
|
|
Begin
|
|
for i:=1 to 5*1024 do tmp[i]:= 0; { empty buffer by zero }
|
|
|
|
for sector:= 1 to 5 do
|
|
begin
|
|
if keypressed then break;
|
|
|
|
sc:= sector;
|
|
if sector = 5 then sc:= 9;
|
|
|
|
write('Track:',track:2,' Head:',head:1,' Sector:',sc,' ');
|
|
|
|
{ mark sector as a bad sector }
|
|
for i:=1 to 1024 do tmp[(sector-1)*1024+i]:= ord('B');
|
|
|
|
for tries:= 1 to maxTries do
|
|
begin
|
|
if keypressed then break;
|
|
|
|
fdcReadSector(drive+(head shl 2),track,head,sc,FDC_SECTOR_1024,9);
|
|
fdcIOErrorBackup:= fdcIOError;
|
|
|
|
if fdcIOErrorBackup = FDC_OK then break;
|
|
|
|
write('.');
|
|
|
|
if motorOffMethod then
|
|
begin
|
|
if tries in [4,6,8] then
|
|
begin
|
|
fdcMotorOff;
|
|
delay(100);
|
|
fdcMotorOn(drive);
|
|
continue;
|
|
end;
|
|
end;
|
|
|
|
if track > 4 then fdcSeek(drive, track-4) else fdcSeek(drive, 0);
|
|
fdcSeek(drive,track);
|
|
end;
|
|
|
|
if fdcIOErrorBackup = FDC_ERR_BAD_SECTOR then
|
|
write(fdcErrorStr(fdcIOErrorBackup)+' (saved) '+#13)
|
|
else
|
|
write(fdcErrorStr(fdcIOErrorBackup)+' '+#13);
|
|
|
|
if fdcIOErrorBackup <> FDC_OK then writeln;
|
|
|
|
{ save buffer only if [OK] or [BAD_SECTOR] }
|
|
if fdcIOErrorBackup in [FDC_OK, FDC_ERR_BAD_SECTOR] then
|
|
for i:=1 to 1024 do tmp[(sector-1)*1024+i]:= fdcBuf[i];
|
|
end;
|
|
|
|
{ do not dump in test mode }
|
|
if not testMode then
|
|
BlockWrite(ff, tmp, 5*1024); { dump full track }
|
|
End;
|
|
|
|
if KeyPressed then
|
|
if ReadKey = #27 then
|
|
begin
|
|
writeln(#13#10'... break pressed');
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
{ do not dump in test mode }
|
|
if not testMode then
|
|
close(ff);
|
|
|
|
fdcRecalibrate(drive);
|
|
fdcMotorOff;
|
|
|
|
write(#13' ');
|
|
writeln(#13#10'Done.'#13#10);
|
|
end.
|