#include <exec/types.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <devices/trackdisk.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <stdlib.h>
#include <stdio.h>
#include <proto/exec.h>
#include <proto/dos.h>
/* Lhwarp version 1.03 */
#define MAJOR_VERSION 1
#define MINOR_VERSION 0
#define DECIMAL_VERSION 3
#define NUM_HEADS 2
#define TRACK_SIZE (TD_SECTOR * NUMSECS * NUM_HEADS)
#define SEEK_SET 0
#define WARP_READ 1
#define WARP_WRITE 2
#define IN_BUFFER_SIZE 16384
#define OUT_BUFFER_SIZE 16384
/* Only LZHUF is supported at the moment */
#define COMPTYPE_LHARC 0
/* Note, this has changed! */
#define DATATYPE_NORMAL 0
#define DATATYPE_RAW 1
struct WarpHeader
{
UBYTE MajorVersion;
UBYTE MinorVersion;
UBYTE DecimalVersion;
UBYTE Reserved;
USHORT StartTrack;
USHORT EndTrack;
ULONG TextLength;
ULONG CompressedTextLength;
};
struct CompHeader101
{
UBYTE CompressionType;
UBYTE DataType;
UBYTE TrackNumber;
UBYTE Unused;
ULONG FullLength;
ULONG CompressedLength;
};
struct CompHeader102
{
UBYTE CompressionType;
UBYTE DataType;
UBYTE TrackNumber;
UBYTE Unused;
ULONG FullLength;
ULONG CompressedLength;
ULONG CheckSum;
};
#define LABEL_LENGTH (16 * NUMSECS * NUM_HEADS)
UBYTE *iotd_SecLabel = NULL;
struct WarpHeader WHeader;
struct IOExtTD *ReadMsg = NULL;
struct IOExtTD *WriteMsg = NULL;
struct MsgPort *ReadPort = NULL;
struct MsgPort *WritePort = NULL;
extern FILE *infile;
extern FILE *outfile;
extern UBYTE *FilePosition;
extern UBYTE *EndOfFilePosition;
extern UBYTE *PutFilePosition;
/* LZHUF defines and externs */
#define N 4096 /* Size of string buffer */
#define F 60 /* Size of look-ahead buffer */
#define THRESHOLD 2
#define NIL N /* End of tree's node */
extern unsigned char *text_buf;
extern short *lson, *rson, *dad;
struct CompHeader101 CHeader101;
struct CompHeader102 CHeader102;
char FileName[256];
char TextFileName[256];
UBYTE Command;
UBYTE AppendTextFile;
UBYTE Version101;
BPTR FHandle;
ULONG StartTrack;
ULONG EndTrack;
ULONG Unit;
APTR DataBlock = NULL;
APTR NewBlock = NULL;
APTR TrackdiskBlock = NULL;
ULONG GetFileLength(register char *FileToOpen);
ULONG DoSum(UBYTE *Block, ULONG Length);
void __regargs Decode(ULONG Size);
void main(int argc, char **argv)
{
if (argc != 2 && argc != 4 && argc != 6 && argc != 7)
{
Title();
exit (1);
}
if (!stricmp(argv[1], "READ"))
{
/* Remove the file if it was already there */
remove(FileName);
Command = WARP_READ;
}
else if (!stricmp(argv[1], "WRITE"))
{
Command = WARP_WRITE;
}
else if (!stricmp(argv[1], "HELP"))
{
exit(0);
}
else
{
puts("\nUnknown command\n");
exit(1);
}
if (argc < 6 && Command == WARP_READ)
{
Title();
exit (1);
}
if (argc == 7)
{
strcpy(TextFileName, argv[6]);
AppendTextFile = 1;
}
else
{
AppendTextFile = 0;
}
/* Get the unit number */
Unit = atoi(argv[2]);
/* Get the file name */
strcpy(FileName, argv[3]);
strupr(FileName);
/* Append .LHW if necessary */
if (strcmp(FileName, ".LHW"))
{
if (strlen(FileName) > 4)
{
if (strcmp(&FileName[strlen(FileName)-4], ".LHW"))
{
strcat(FileName, ".LHW");
}
}
else
{
strcat(FileName, ".LHW");
}
}
/* Get the start and end tracks */
if (argc > 5)
{
StartTrack = atoi(argv[4]);
EndTrack = atoi(argv[5]);
}
if (StartTrack > EndTrack)
{
puts("Start track is greater than end track\n");
exit (1);
}
Init();
if (Command == WARP_WRITE)
{
WriteData();
}
else
{
ReadData();
}
}
Init()
{
text_buf = NULL;
lson = NULL;
rson = NULL;
dad = NULL;
if (!(ReadPort = CreatePort(0L, 0L)))
{
puts("Couldn't create read port");
exit (1);
}
if (!(WritePort = CreatePort(0L, 0L)))
{
puts("Couldn't create write port");
CleanUp();
exit (1);
}
if (!(ReadMsg = (struct IORequest *) CreateExtIO(ReadPort, (long) sizeof(struct IOExtTD))))
{
puts("Couldn't create i/o read request");
CleanUp();
exit (1);
}
if (!(WriteMsg = (struct IORequest *) CreateExtIO(WritePort, (long) sizeof(struct IOExtTD))))
{
puts("Couldn't create i/o write request");
CleanUp();
exit (1);
}
ReadMsg->iotd_Req.io_Command = ETD_READ;
WriteMsg->iotd_Req.io_Command = ETD_WRITE;
if (OpenDevice(TD_NAME, Unit, (struct IORequest *) ReadMsg, 0L))
{
puts("Couldn't open trackdisk.device for reading");
CleanUp();
exit (1);
}
if (OpenDevice(TD_NAME, Unit, (struct IORequest *) WriteMsg, 0L))
{
puts("Couldn't open trackdisk.device for writing");
CleanUp();
exit (1);
}
if (!(DataBlock = AllocMem((ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH, MEMF_PUBLIC)))
{
puts("Couldn't allocate trackdisk memory buffer");
CleanUp();
exit (1);
}
if (!(NewBlock = AllocMem((ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH, MEMF_PUBLIC)))
{
puts("Couldn't allocate trackdisk memory buffer");
CleanUp();
exit (1);
}
if (!(TrackdiskBlock = AllocMem((ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH, MEMF_CHIP)))
{
puts("Couldn't allocate trackdisk memory buffer");
CleanUp();
exit (1);
}
if (!(iotd_SecLabel = AllocMem((ULONG) LABEL_LENGTH, MEMF_CHIP)))
{
puts("Couldn't allocate trackdisk extended memory buffer");
CleanUp();
exit (1);
}
if (!(text_buf = AllocMem((ULONG) (N + F - 1), MEMF_PUBLIC)))
{
puts("Out of memory");
CleanUp();
exit (1);
}
if (!(lson = AllocMem((ULONG) (N + 1) * (ULONG) (sizeof(short)), MEMF_PUBLIC)))
{
puts("Out of memory");
CleanUp();
exit (1);
}
if (!(rson = AllocMem((ULONG) (N + 257) * (ULONG) (sizeof(short)), MEMF_PUBLIC)))
{
puts("Out of memory");
CleanUp();
exit (1);
}
if (!(dad = AllocMem((ULONG) (N + 1) * (ULONG) (sizeof(short)), MEMF_PUBLIC)))
{
puts("Out of memory");
CleanUp();
exit (1);
}
}
Archive(USHORT Track, ULONG DataSize)
{
UBYTE *OutBuffer;
UBYTE CanSetBuffer;
ULONG CurrentPosition;
ULONG AfterEncodeLength;
ULONG TotalEncodeLength;
BPTR outfp;
if (OutBuffer = AllocMem((ULONG) OUT_BUFFER_SIZE, MEMF_PUBLIC))
{
CanSetBuffer = 1;
}
else
{
CanSetBuffer = 0;
}
CurrentPosition = GetFileLength(FileName);
/* Lhwarp to a file; this way, if the output is larger than the input */
/* we won't crash the machine */
if (!(outfile = fopen(FileName, "a+b")))
{
printf("Couldn't open temporary file for output\n");
if (CanSetBuffer)
{
FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE);
}
CleanUp();
exit (1);
}
if (CanSetBuffer)
{
setvbuf(outfile, OutBuffer, _IOFBF, (long) OUT_BUFFER_SIZE);
}
/* Write out a dummy file compression header */
fwrite(&CHeader102, sizeof(struct CompHeader102), 1, outfile);
Encode((ULONG) (DataSize));
fclose(outfile);
if (CanSetBuffer)
{
FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE);
}
AfterEncodeLength = GetFileLength(FileName);
TotalEncodeLength = AfterEncodeLength - CurrentPosition - sizeof(struct CompHeader102);
if (!(outfp = (BPTR) Open(FileName, (long) MODE_READWRITE)))
{
printf("Couldn't open temporary file for output\n");
if (CanSetBuffer)
{
FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE);
}
CleanUp();
exit (1);
}
/* Seek back to the CompHeader section */
Seek((BPTR) outfp, (long) CurrentPosition, (long) OFFSET_BEGINNING);
CHeader102.CompressedLength = TotalEncodeLength;
CHeader102.FullLength = DataSize;
CHeader102.TrackNumber = (UBYTE) Track;
CHeader102.CompressionType = COMPTYPE_LHARC;
CHeader102.DataType = DATATYPE_NORMAL;
/* Checksum the block */
CHeader102.CheckSum = (ULONG) DoSum(NewBlock, (ULONG) CHeader102.FullLength);
/* Write it to disk */
Write((BPTR) outfp, &CHeader102, (long) sizeof(struct CompHeader102));
/* Close the file */
Close((BPTR) outfp);
}
WriteData()
{
ULONG Track;
UBYTE *TextMemory;
UBYTE *TextCompMemory;
UBYTE *ExtendedDataBlock;
ULONG CheckSum;
ULONG TracksWritten = 0L;
printf("\nLHWARP %d.%d%d - Amiga disk tracker - Written by Jonathan Forbes @ 1:250/642\n", (UBYTE) MAJOR_VERSION, (UBYTE) MINOR_VERSION, (UBYTE) DECIMAL_VERSION);
puts("Copyright © Xenomiga Technology, 1990.\n");
printf("Writing to disk in drive %ld from file %s\n", Unit, FileName);
/* Set up the write request */
WriteMsg->iotd_Req.io_Command = ETD_FORMAT;
if (!(infile = fopen(FileName, "r")))
{
printf("Cannot open %s for input\n", FileName);
CleanUp();
exit (1);
}
/* Read the Warp header */
fread(&WHeader, sizeof(struct WarpHeader), 1, infile);
/* What version of Lhwarp was used to compress the disk? */
if (WHeader.MajorVersion == 1 && WHeader.MinorVersion == 0 && WHeader.DecimalVersion == 1)
{
printf("Disk was compressed using Lhwarp 1.01\n\n");
Version101 = 1;
}
else
{
printf("Disk was compressed using Lhwarp %d.%d%d\n\n", WHeader.MajorVersion, WHeader.MinorVersion, WHeader.DecimalVersion);
Version101 = 0;
}
if ((WHeader.MajorVersion > MAJOR_VERSION) ||
(WHeader.MajorVersion == MAJOR_VERSION && WHeader.MinorVersion > MINOR_VERSION))
{
printf("Sorry, this file was Lhwarp'd with Lhwarp V%d%d.%d\n",
WHeader.MajorVersion, WHeader.MinorVersion, WHeader.DecimalVersion);
printf("You are using Lhwarp V%d%d.%d\n",
MAJOR_VERSION, MINOR_VERSION, DECIMAL_VERSION);
CleanUp();
exit(1);
}
if (WHeader.TextLength)
{
if (!(TextMemory = AllocMem((ULONG) WHeader.TextLength+1, MEMF_PUBLIC)))
{
printf("Insufficient memory (%ld bytes required) to read compressed text\n", (ULONG) WHeader.TextLength+1);
CleanUp();
exit(1);
}
if (!(TextCompMemory = AllocMem((ULONG) WHeader.CompressedTextLength, MEMF_PUBLIC)))
{
printf("Insufficient memory (%ld bytes required) to decompress text\n", (ULONG) WHeader.CompressedTextLength);
FreeMem(TextMemory, (ULONG) WHeader.TextLength+1);
CleanUp();
exit(1);
}
fread(TextCompMemory, (ULONG) WHeader.CompressedTextLength, 1, infile);
FilePosition = (UBYTE *) TextCompMemory;
/* Arbitrary number; just make it greater than TextLength */
EndOfFilePosition = (UBYTE *) ( ((UBYTE *) TextCompMemory) + (WHeader.CompressedTextLength));
PutFilePosition = (UBYTE *) TextMemory;
Decode((ULONG) WHeader.TextLength);
/* Make sure the text has a null terminator */
TextMemory[WHeader.TextLength] = 0;
puts("\n----\n");
puts(TextMemory);
puts("----\n");
FreeMem(TextMemory, (ULONG) WHeader.TextLength+1);
FreeMem(TextCompMemory, (ULONG) WHeader.CompressedTextLength);
}
/* Start writing tracks */
for (;;)
{
if (Version101)
{
if (!(fread(&CHeader101, sizeof(struct CompHeader101), 1, infile)))
{
break;
}
}
else
{
if (!(fread(&CHeader102, sizeof(struct CompHeader102), 1, infile)))
{
break;
}
}
FilePosition = (UBYTE *) DataBlock;
PutFilePosition = (UBYTE *) NewBlock;
if (Version101)
{
EndOfFilePosition = (UBYTE *) ( ((UBYTE *) DataBlock) + CHeader101.CompressedLength);
fread(DataBlock, (long) CHeader101.CompressedLength, 1, infile);
Decode((ULONG) CHeader101.FullLength);
Track = (ULONG) CHeader101.TrackNumber;
}
else
{
EndOfFilePosition = (UBYTE *) ( ((UBYTE *) DataBlock) + CHeader102.CompressedLength);
fread(DataBlock, (long) CHeader102.CompressedLength, 1, infile);
Decode((ULONG) CHeader102.FullLength);
CheckSum = (ULONG) DoSum(NewBlock, (ULONG) CHeader102.FullLength);
if (CheckSum != CHeader102.CheckSum)
{
printf("Warning: Track %ld fails checksum\n", Track);
}
Track = (ULONG) CHeader102.TrackNumber;
}
ExtendedDataBlock = (UBYTE *) ( ((UBYTE *) NewBlock) + ((ULONG) TRACK_SIZE));
CopyMem(ExtendedDataBlock, (UBYTE *) &iotd_SecLabel[0], (ULONG) LABEL_LENGTH);
if (!Track)
{
puts("Disk contains the following bootblock:\n");
DisplayBootBlock(NewBlock);
}
/* Copy data into CHIP RAM */
CopyMem(NewBlock, TrackdiskBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
WriteMsg->iotd_Req.io_Offset = (long) TRACK_SIZE * Track;
WriteMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock;
WriteMsg->iotd_Req.io_Length = (long) TRACK_SIZE;
WriteMsg->iotd_SecLabel = &iotd_SecLabel[0];
WriteMsg->iotd_Count = 0xFFFFFFFF;
printf("Writing track %2ld", (ULONG) (Track));
fflush(stdout);
if (DoIO((struct IORequest *) WriteMsg))
{
fclose(infile);
printf("Fatal error writing to disk in unit %ld -terminating\n\n", Unit);
MotorOff();
CleanUp();
exit (1);
}
printf("\n[A");
fflush(stdout);
TracksWritten++;
}
MotorOff();
WriteMsg->iotd_Req.io_Length = 0L;
WriteMsg->iotd_Req.io_Command = CMD_FLUSH;
DoIO((struct IORequest *) WriteMsg);
fclose(infile);
printf("\n\nFinished writing %ld tracks\n\n", TracksWritten);
printf("Please remove and re-insert destination disk, to use\n\n");
CleanUp();
}
MotorOff()
{
WriteMsg->iotd_Req.io_Length = 0L;
WriteMsg->iotd_Req.io_Command = TD_MOTOR;
DoIO((struct IORequest *) WriteMsg);
}
DisplayBootBlock(UBYTE *Data)
{
char Line[76];
UBYTE i;
register UBYTE j;
register UBYTE c;
/* End of the line to be displayed */
Line[73] = 10;
Line[74] = 13;
Line[75] = 0;
for (i=0; i<14; i++)
{
for (j=0; j<73; j++)
{
c = *((UBYTE *) ( ((UBYTE *) Data) + (i * 64) + j));
if (c < 32 || c > 126)
{
c = '.';
}
Line[j] = c;
}
printf(Line);
}
puts("");
}
ReadData()
{
ULONG AfterEncodeLength;
ULONG TotalEncodeLength;
ULONG TextLength;
ULONG i;
ULONG FileLength;
ULONG OriginalLength = 0L;
BPTR OutputFile;
ULONG Error;
ULONG DataSize;
ULONG OnlyDataSize;
FILE *TextInFile;
UBYTE *TextMemory;
UBYTE *ExtendedDataBlock;
printf("\nLHWARP %d.%d%d - Amiga disk tracker - Written by Jonathan Forbes @ 1:250/642\n", (UBYTE) MAJOR_VERSION, (UBYTE) MINOR_VERSION, (UBYTE) DECIMAL_VERSION);
puts("Copyright © Xenomiga Technology, 1990.\n");
printf("Reading from disk in drive %ld to file %s\n", Unit, FileName);
/* Set up the read request */
ReadMsg->iotd_Req.io_Command = ETD_READ;
ReadMsg->iotd_Count = 0xFFFFFFFF;
/* If we start at track zero, check the boot block */
if (!StartTrack)
{
ReadMsg->iotd_Req.io_Offset = (long) 0L;
ReadMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock;
/* Only get the first two sectors */
ReadMsg->iotd_Req.io_Length = (long) 1024L;
if (Error = DoIO((struct IORequest *) ReadMsg))
{
printf("Error %d reading from trackdisk.device\n", Error);
CleanUp();
exit (1);
}
printf("\nBoot block of floppy disk in drive %d:\n\n", Unit);
DisplayBootBlock(TrackdiskBlock);
}
if (AppendTextFile)
{
TextLength = GetFileLength(TextFileName);
if (!TextLength)
{
puts("Text file missing or zero length\n");
CleanUp();
exit (1);
}
WHeader.TextLength = TextLength;
}
else
{
WHeader.TextLength = 0L;
}
/* Build the Warp header */
WHeader.StartTrack = StartTrack;
WHeader.EndTrack = EndTrack;
/* Version 1.03 */
WHeader.MajorVersion = (UBYTE) MAJOR_VERSION;
WHeader.MinorVersion = (UBYTE) MINOR_VERSION;
WHeader.DecimalVersion = (UBYTE) DECIMAL_VERSION;
/* Write out the Warp header */
if (!(OutputFile = Open(FileName, MODE_NEWFILE)))
{
printf("Couldn't open output file\n");
CleanUp();
exit (1);
}
Write(OutputFile, &WHeader, (long) sizeof(struct WarpHeader));
Close(OutputFile);
if (AppendTextFile)
{
printf("Compressing text ... ");
fflush(stdout);
if (!(TextInFile = fopen(TextFileName, "r")))
{
printf("Can't open %s for input\n", TextInFile);
CleanUp();
exit(1);
}
if (!(TextMemory = AllocMem((ULONG) TextLength, MEMF_PUBLIC)))
{
puts("Couldn't allocate text memory buffer");
CleanUp();
exit(1);
}
fread(TextMemory, (ULONG) TextLength, 1, TextInFile);
fclose(TextInFile);
if (!(outfile = fopen(FileName, "a")))
{
printf("Can't open %s for append\n", FileName);
FreeMem(TextMemory, (ULONG) TextLength);
CleanUp();
exit(1);
}
FilePosition = (UBYTE *) TextMemory;
EndOfFilePosition = (UBYTE *) ( ((UBYTE *) TextMemory) + (TextLength));
Encode((ULONG) (TextLength));
fclose(outfile);
FreeMem(TextMemory, (ULONG) TextLength);
AfterEncodeLength = GetFileLength(FileName);
TotalEncodeLength = AfterEncodeLength - (ULONG) sizeof(struct WarpHeader);
WHeader.CompressedTextLength = TotalEncodeLength;
if (!(outfile = fopen(FileName, "r+w")))
{
printf("Can't open %s for append\n", FileName);
CleanUp();
exit(1);
}
fwrite(&WHeader, sizeof(struct WarpHeader), 1, outfile);
fclose(outfile);
printf("done\n\n");
}
/* Start reading tracks */
for (i = StartTrack; i <= EndTrack; i++)
{
DataSize = (ULONG) TRACK_SIZE + (ULONG) (NUMSECS * NUM_HEADS * 16);
OnlyDataSize = (ULONG) TRACK_SIZE;
ExtendedDataBlock = (UBYTE *) ( ((UBYTE *) NewBlock) + ((ULONG) OnlyDataSize));
ReadMsg->iotd_Req.io_Offset = (long) TRACK_SIZE * i;
ReadMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock;
ReadMsg->iotd_Req.io_Length = (long) TRACK_SIZE;
ReadMsg->iotd_SecLabel = &iotd_SecLabel[0];
ReadMsg->iotd_Count = 0xFFFFFFFF;
printf("Reading track %2ld ... [11D", (ULONG) (i));
fflush(stdout);
DoIO((struct IORequest *) ReadMsg);
printf("compressing");
fflush(stdout);
/* Copy data out of CHIP RAM */
CopyMem(TrackdiskBlock, NewBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
CopyMem((UBYTE *) &iotd_SecLabel[0], (UBYTE *) ExtendedDataBlock, (ULONG) NUMSECS * NUM_HEADS * 16);
FilePosition = (UBYTE *) NewBlock;
EndOfFilePosition = (UBYTE *) ( ((UBYTE *) NewBlock) + (DataSize));
Archive(i, DataSize);
OriginalLength += (DataSize);
printf("\n[A");
}
ReadMsg->iotd_Req.io_Length = 0;
ReadMsg->iotd_Req.io_Command = TD_MOTOR;
DoIO((struct IORequest *) ReadMsg);
FileLength = GetFileLength(FileName);
printf("\n\nFinished reading tracks %d to %d (%d total)\n", WHeader.StartTrack, WHeader.EndTrack, WHeader.EndTrack - WHeader.StartTrack + 1);
printf(" Input file: %ld bytes\n", OriginalLength);
printf("Output file: %ld bytes\n\n", FileLength);
CleanUp();
}
CleanUp()
{
if (ReadMsg)
{
CloseDevice((struct IORequest *) ReadMsg);
DeleteExtIO((struct IORequest *) ReadMsg, (long) sizeof(struct IOExtTD));
}
if (WriteMsg)
{
CloseDevice((struct IORequest *) WriteMsg);
DeleteExtIO((struct IORequest *) WriteMsg, (long) sizeof(struct IOExtTD));
}
if (ReadPort)
{
DeletePort(ReadPort);
}
if (WritePort)
{
DeletePort(WritePort);
}
if (DataBlock)
{
FreeMem(DataBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
}
if (NewBlock)
{
FreeMem(NewBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
}
if (TrackdiskBlock)
{
FreeMem(TrackdiskBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
}
if (iotd_SecLabel)
{
FreeMem(iotd_SecLabel, (ULONG) LABEL_LENGTH);
}
if (text_buf)
{
FreeMem(text_buf, (ULONG) (N + F - 1));
}
if (lson)
{
FreeMem(lson, (ULONG) (N + 1) * (ULONG) (sizeof(short)));
}
if (rson)
{
FreeMem(rson, (ULONG) (N + 257) * (ULONG) (sizeof(short)));
}
if (dad)
{
FreeMem(dad, (ULONG) (N + 1) * (ULONG) (sizeof(short)));
}
}
Title()
{
printf("\nLHWARP %d.%d%d - Amiga disk tracker - Written by Jonathan Forbes @ 1:250/642\n", (UBYTE) MAJOR_VERSION, (UBYTE) MINOR_VERSION, (UBYTE) DECIMAL_VERSION);
puts("Copyright © Xenomiga Technology, 1990.\n");
puts("Usage: LHWARP <Read|Write> <Unit> <Filename> <StartTrack> <EndTrack> <TextFile>\n");
puts("<Unit> - Drive number (0 for internal, 1 ... 3 for external)");
puts("<Filename> - Output|Input filename");
puts("<StartTrack> - Track number (0 ... 79) [only valid in read mode]");
puts("<EndTrack> - Track number (0 ... 79) [only valid in read mode]");
puts("<TFile> - Append text in <TextFile> to output file [optional]\n");
}
ULONG GetFileLength(register char *FileToOpen)
{
register ULONG FileLength;
register ULONG lock;
register struct FileInfoBlock *fileinfo;
if (access(FileToOpen, 0))
{
return (0L);
}
fileinfo = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock),
MEMF_CLEAR | MEMF_PUBLIC);
if (!fileinfo)
{
printf("\n\r\n\rUtterly fatal error: Out of memory\n\r\n\r");
return (NULL);
}
lock = (ULONG) Lock(FileToOpen, ACCESS_READ);
if (!lock)
{
FreeMem(fileinfo, sizeof(struct FileInfoBlock));
return (NULL);
}
Examine(lock, fileinfo);
FileLength = fileinfo->fib_Size;
UnLock(lock);
FreeMem(fileinfo, sizeof(struct FileInfoBlock));
return (FileLength);
}
/* If the user presses ^C */
int CXBRK()
{
if (WriteMsg)
{
WriteMsg->iotd_Req.io_Length = 0L;
WriteMsg->iotd_Req.io_Command = TD_MOTOR;
DoIO((struct IORequest *) WriteMsg);
}
if (ReadMsg)
{
ReadMsg->iotd_Req.io_Length = 0L;
ReadMsg->iotd_Req.io_Command = TD_MOTOR;
DoIO((struct IORequest *) ReadMsg);
}
CleanUp();
return (-1);
}
ULONG DoSum(UBYTE *Block, ULONG Length)
{
register ULONG Sum = 0;
register ULONG i;
for (i = 0; i < Length; i++)
{
Sum = Sum + Block[i];
}
return (Sum);
}