home *** CD-ROM | disk | FTP | other *** search
- MODULE ReadPlusD;
-
- (*
-
- This file may be distributed anywhere provided it is unmodified and is not
- sold for profit. Please report bugs to the author.
-
- Author: Peter McGavin, 86 Totara Crescent, Lower Hutt, New Zealand.
- e-mail: srwmpnm@wnv.dsir.govt.nz .
-
-
- This Benchmark Modula-2 program reads an MGT (Miles Gordon Technology) PLUS D
- 3.5" double-sided diskette on any Amiga. MGT PLUS D diskettes are used on
- Sinclair Spectrum computers. This is useful for transferring Spectrum programs
- to the format required by the Spectrum emulator on the Amiga.
-
- ReadPlusD requires messydisk.device (supplied with MSH on Fred Fish disk 382)
- in the devs: directory.
-
-
- CLI usage: ReadPlusD disk-unit-number [directory-entry-number output-file]
-
-
- The disk unit number should be an integer in the range 0..3 corresponding to
- the drive (DF0:..DF3:) containing the PLUS D diskette.
-
- If given just the unit-number, ReadPlusD displays a directory of the disk.
-
- If you also give a directory entry number and an output file name, ReadPlusD
- converts a 48 kbyte snapshot file to the format required by the Amiga Spectrum
- emulator. The output is written to the given file name.
-
- Note that you specify the number of the directory entry (an integer in the
- range 1..80), not the name of the input file. If the file is not a 48 kbyte
- snapshot file, ReadPlusD displays an error message.
-
-
- Examples:
-
- ReadPlusD 2 get a directory of the PLUS D disk in DF2:
-
- ReadPlusD 1 17 RAM:TRON convert the 17th file on DF1: to RAM:TRON
-
-
- Known bug:
-
- ReadPlusD always sets the z80 interrupt mode to 1. A few Spectrum programs use
- interrupt mode 2. If a converted program doesn't run and you suspect it might
- use mode 2, try patching the byte at offset 25 in the output file to be $02.
- Use a binary file editor like, for example, NEWZAP. The byte you patch is
- actually the 26th byte in the file (because the 1st byte is at offset 0), and
- it will always be $01 to begin with.
-
- If you know how to fix this bug, please tell me how to do it.
-
- *)
-
- FROM SYSTEM IMPORT ADR, ADDRESS, BYTE, LONGWORD;
- FROM AmigaDOS IMPORT FileHandle, ModeNewFile, Open, Write, Close;
- FROM Conversions IMPORT ConvStringToNumber;
- FROM InOut IMPORT WriteLn, WriteString, WriteCard, Read;
- FROM IODevices IMPORT OpenDevice, CloseDevice, DoIO, CmdRead;
- FROM IODevicesUtil IMPORT CreateExtIO, DeleteExtIO;
- FROM Memory IMPORT AllocMem, FreeMem, MemReqSet, MemPublic, MemClear;
- FROM Ports IMPORT MsgPortPtr, GetMsg, PutMsg, WaitPort;
- FROM PortsUtil IMPORT CreatePort, DeletePort;
- FROM Strings IMPORT ExtractSubString;
- FROM System IMPORT argc, argv;
- FROM TrackDiskDevice IMPORT IOExtTD, IOExtTDPtr, TDName, TDMotor;
-
-
- CONST
- MDName = "messydisk.device";
- NumSecs = 10;
-
-
- VAR
- buffer: ARRAY [0..511] OF BYTE;
-
-
- PROCEDURE motor (diskreq: IOExtTDPtr; onoff: BOOLEAN);
- VAR
- dummy: LONGINT;
- BEGIN
- WITH diskreq^.iotdReq DO
- IF onoff THEN
- ioLength := 1D
- ELSE
- ioLength := 0D
- END;
- ioCommand := TDMotor
- END;
- dummy := DoIO (diskreq)
- END motor;
-
-
- PROCEDURE read_sector (diskreq: IOExtTDPtr;
- sector: CARDINAL;
- bufptr: ADDRESS): CARDINAL;
- VAR
- dummy: LONGINT;
- BEGIN
- WITH diskreq^.iotdReq DO
- ioLength := 512D;
- ioData := bufptr;
- ioOffset := 512D * LONGCARD(sector);
- ioCommand := CmdRead;
- dummy := DoIO (diskreq);
- RETURN CARDINAL (ioError)
- END
- END read_sector;
-
-
- PROCEDURE msh_sector (track, sector: CARDINAL): CARDINAL;
- (* Convert from Plus-D track and sector number to messydisk sector number *)
- BEGIN
- IF track >= 128 THEN (* it's on the reverse side *)
- RETURN 2 * NumSecs * (track - 128) + NumSecs + sector - 1
- ELSE
- RETURN 2 * NumSecs * track + sector - 1
- END
- END msh_sector;
-
-
- TYPE
- dir_entry_type = RECORD
- CASE :INTEGER OF
- 0: c: ARRAY [0..255] OF CHAR |
- 1: b: ARRAY [0..255] OF BYTE
- END;
- END;
-
- dir_entry_ptr_type = POINTER TO dir_entry_type;
-
-
- PROCEDURE write_dir_entry (entry_number: CARDINAL;
- dir_entry_ptr: dir_entry_ptr_type);
- VAR
- name: ARRAY [0..10] OF CHAR;
- BEGIN
- WITH dir_entry_ptr^ DO
- IF CARDINAL(b[0]) <> 0 THEN
- WriteCard (entry_number, 2);
- WriteString (" ");
- CASE CARDINAL(b[0]) OF
- 1: WriteString ("Basic program ") |
- 2: WriteString ("Numeric array ") |
- 3: WriteString ("Character array ") |
- 4: WriteString ("Code file ") |
- 5: WriteString ("48k snapshot ") |
- 7: WriteString ("Screen dump ") |
- 10:WriteString ("Open# file ")
- ELSE
- WriteString ("Type ");
- WriteCard (CARDINAL(b[0]), 2);
- WriteString (" ")
- END;
- ExtractSubString (name, c, 1, 10);
- WriteString (name);
- WriteCard (CARDINAL(b[12]), 6); (* size *)
- (*
- WriteCard (CARDINAL(b[13]), 4); (* starting track *)
- WriteCard (CARDINAL(b[14]), 4); (* starting sector *)
- *)
- WriteLn
- END
- END
- END write_dir_entry;
-
-
- PROCEDURE directory (diskreq: IOExtTDPtr): BOOLEAN;
- VAR
- track,
- sector,
- entry_number: CARDINAL;
- BEGIN
- entry_number := 0;
- FOR track := 0 TO 3 DO
- FOR sector := 1 TO 10 DO
- IF read_sector (diskreq, msh_sector (track, sector), ADR(buffer)) <> 0 THEN
- WriteString ("Error reading sector\n");
- RETURN FALSE
- END;
- INC (entry_number);
- write_dir_entry (entry_number, ADR(buffer[0]));
- INC (entry_number);
- write_dir_entry (entry_number, ADR(buffer[256]))
- END
- END;
- RETURN TRUE
- END directory;
-
-
- PROCEDURE convert_snapshot (entry_number: CARDINAL;
- filename: ARRAY OF CHAR;
- diskreq: IOExtTDPtr): BOOLEAN;
- CONST
- image_size = 49179D;
- image_buffer_size = image_size + 512D;
- VAR
- track,
- sector,
- sp: CARDINAL;
- z80_address,
- tmp: LONGCARD;
- ok: BOOLEAN;
- image: POINTER TO ARRAY [0..27] OF BYTE; (* really 49179 byte buffer *)
- image_ptr: POINTER TO ARRAY [0..511] OF BYTE;
- dir_entry_ptr: dir_entry_ptr_type;
- file: FileHandle;
- BEGIN
- ok := TRUE;
- image := NIL;
- file := NIL;
-
- IF (entry_number <= 0) OR (entry_number > 80) THEN
- WriteString ("Entry number is out of range\n");
- ok := FALSE
- END;
-
- DEC (entry_number); (* now in range 0..79 *)
-
- IF ok THEN
- track := entry_number DIV 20;
- sector := (entry_number MOD 20) DIV 2 + 1;
- IF read_sector (diskreq, msh_sector (track, sector), ADR(buffer)) <> 0 THEN
- WriteString ("Error reading sector\n");
- ok := FALSE
- END
- END;
-
- IF ok THEN
- IF ODD(entry_number) THEN
- dir_entry_ptr := ADR(buffer[256])
- ELSE
- dir_entry_ptr := ADR(buffer[0])
- END;
- WITH dir_entry_ptr^ DO
- IF CARDINAL(b[0]) <> 5 THEN
- WriteString ("Error, entry number ");
- WriteCard (entry_number + 1, 2);
- WriteString (" is not a 48k snapshot file\n");
- ok := FALSE
- END
- END
- END;
-
- IF ok THEN
- image := AllocMem (image_buffer_size, MemReqSet{});
- IF image = NIL THEN
- WriteString ("Can't allocate image buffer\n");
- ok := FALSE
- END
- END;
-
- IF ok THEN
- sp := 256 * CARDINAL(dir_entry_ptr^.b[0F1H]) + CARDINAL(dir_entry_ptr^.b[0F0H]);
- INC (sp, 4);
- image^[ 0] := dir_entry_ptr^.b[0EFH]; (* i *)
- image^[ 1] := dir_entry_ptr^.b[0E4H]; (* l' *)
- image^[ 2] := dir_entry_ptr^.b[0E5H]; (* h' *)
- image^[ 3] := dir_entry_ptr^.b[0E0H]; (* e' *)
- image^[ 4] := dir_entry_ptr^.b[0E1H]; (* d' *)
- image^[ 5] := dir_entry_ptr^.b[0E2H]; (* c' *)
- image^[ 6] := dir_entry_ptr^.b[0E3H]; (* b' *)
- image^[ 7] := dir_entry_ptr^.b[0E6H]; (* f' *)
- image^[ 8] := dir_entry_ptr^.b[0E7H]; (* a' *)
- image^[ 9] := dir_entry_ptr^.b[0ECH]; (* l *)
- image^[10] := dir_entry_ptr^.b[0EDH]; (* h *)
- image^[11] := dir_entry_ptr^.b[0E8H]; (* e *)
- image^[12] := dir_entry_ptr^.b[0E9H]; (* d *)
- image^[13] := dir_entry_ptr^.b[0EAH]; (* c *)
- image^[14] := dir_entry_ptr^.b[0EBH]; (* b *)
- image^[15] := dir_entry_ptr^.b[0DCH]; (* iyl *)
- image^[16] := dir_entry_ptr^.b[0DDH]; (* iyh *)
- image^[17] := dir_entry_ptr^.b[0DEH]; (* ixl *)
- image^[18] := dir_entry_ptr^.b[0DFH]; (* ixh *)
- image^[19] := dir_entry_ptr^.b[0EEH]; (* int *)
- image^[20] := BYTE(00H); (* r *)
- image^[21] := BYTE(00H); (* f filled in later *)
- image^[22] := BYTE(00H); (* a filled in later *)
- image^[23] := BYTE(sp MOD 256); (* spl *)
- image^[24] := BYTE(sp DIV 256); (* sph *)
- image^[25] := BYTE(1); (* im might be wrong!!! *)
- image^[26] := BYTE(0); (* fill *)
- track := CARDINAL(dir_entry_ptr^.b[00DH]);
- sector := CARDINAL(dir_entry_ptr^.b[00EH]);
- image_ptr := ADR(image^[27]);
- z80_address := 16384D
- END;
-
- WHILE ok AND (track <> 0) AND (sector <> 0) DO
- IF read_sector (diskreq, msh_sector (track, sector), image_ptr) <> 0 THEN
- WriteString ("Error reading sector\n");
- ok := FALSE
- ELSE
- tmp := LONGCARD(sp - 2);
- IF (tmp >= z80_address) AND
- (tmp < (z80_address + 510D)) THEN
- image^[21] := image_ptr^[CARDINAL(tmp - z80_address)] (* f *)
- END;
- tmp := LONGCARD(sp - 1);
- IF (tmp >= z80_address) AND
- (tmp < (z80_address + 510D)) THEN
- image^[22] := image_ptr^[CARDINAL(tmp - z80_address)] (* a *)
- END;
- track := CARDINAL(image_ptr^[510]);
- sector := CARDINAL(image_ptr^[511]);
- image_ptr := ADDRESS(LONGCARD(image_ptr) + 510D);
- INC (z80_address, 510D)
- END
- END;
-
- IF ok THEN
- file := Open (ADR(filename), ModeNewFile);
- IF file = NIL THEN
- WriteString ("Error opening output file\n");
- ok := FALSE
- END
- END;
-
- IF ok THEN
- IF Write (file, image, image_size) <> image_size THEN
- WriteString ("Error writing output file\n");
- ok := FALSE
- END
- END;
-
- IF file <> NIL THEN
- Close (file)
- END;
-
- IF image <> NIL THEN
- FreeMem (image, image_buffer_size)
- END;
-
- RETURN ok
- END convert_snapshot;
-
-
- VAR
- unit: CARDINAL;
- diskport: MsgPortPtr;
- diskreq: IOExtTDPtr;
- devopen: LONGINT;
- ok: BOOLEAN;
- ch: CHAR;
- entry_number: CARDINAL;
- temp: LONGCARD;
-
- BEGIN
- ok := TRUE;
- diskport := NIL;
- diskreq := NIL;
- devopen := -1D;
- unit := 0;
- entry_number := 0;
-
- IF ok THEN
- IF (argc <> 2) AND (argc <> 4) THEN
- ok := FALSE
- END
- END;
-
- IF ok THEN
- IF argc >= 2 THEN
- ok := ConvStringToNumber (argv^[1]^, temp, FALSE, 10);
- IF ok THEN
- unit := CARDINAL(temp);
- ok := unit < 4
- END;
- IF NOT ok THEN
- WriteString ("Disk unit must be a number in the range 0..3\n")
- END
- END
- END;
-
- IF ok THEN
- IF argc >= 3 THEN
- ok := ConvStringToNumber (argv^[2]^, temp, FALSE, 10);
- IF ok THEN
- entry_number := CARDINAL(temp);
- ok := (entry_number > 0) AND (entry_number <= 80)
- END;
- IF NOT ok THEN
- WriteString ("Entry number must be a number in the range 1..80\n")
- END
- END
- END;
-
- IF NOT ok THEN
- WriteString ("Usage: ReadPlusD disk-unit-number [entry-number output-file]\n");
- END;
-
- IF ok THEN
- diskport := CreatePort (NIL, 0);
- IF diskport = NIL THEN
- WriteString ("Can't create message port\n");
- ok := FALSE
- END
- END;
-
- IF ok THEN
- diskreq := CreateExtIO (diskport^, SIZE(IOExtTD));
- IF diskreq = NIL THEN
- WriteString ("Can't create external IO request\n");
- ok := FALSE
- END
- END;
-
- IF ok THEN
- devopen := OpenDevice (ADR(MDName), unit, diskreq, 0D);
- IF devopen <> 0D THEN
- WriteString ("Can't open devs:messydisk.device on unit ");
- WriteCard (unit, 1);
- WriteLn;
- ok := FALSE
- END
- END;
-
- IF ok THEN (* must read sector 0 first to discover number of sectors/track *)
- ok := read_sector (diskreq, 0, ADR(buffer)) = 0;
- IF NOT ok THEN
- WriteString ("Error reading sector\n")
- END
- END;
-
- IF ok THEN
- IF entry_number = 0 THEN
- ok := directory (diskreq)
- END
- END;
-
- IF ok THEN
- IF entry_number <> 0 THEN
- WriteString ("\nConverting entry ");
- WriteCard (entry_number, 1);
- WriteString (" to ");
- WriteString (argv^[3]^);
- WriteLn;
- ok := convert_snapshot (entry_number, argv^[3]^, diskreq)
- END
- END;
-
- IF devopen = 0D THEN
- motor (diskreq, FALSE);
- CloseDevice (diskreq);
- devopen := -1D
- END;
-
- IF diskreq <> NIL THEN
- DeleteExtIO (diskreq);
- diskreq := NIL
- END;
-
- IF diskport <> NIL THEN
- DeletePort (diskport^);
- diskport := NIL
- END
-
- END ReadPlusD.
-