home *** CD-ROM | disk | FTP | other *** search
Wrap
/* LHwarp 1.11, written by Jonathan Forbes */ /* Copyright © Xenomiga Technology, 1990 */ #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> #include "LHcrc.h" /* LHwarp version 1.11 */ #define MAJOR_VERSION 1 #define MINOR_VERSION 1 #define DECIMAL_VERSION 1 /* Trackdisk information */ #define NUM_HEADS 2 #define TRACK_SIZE (TD_SECTOR * NUMSECS * NUM_HEADS) #define LABEL_LENGTH (16 * NUMSECS * NUM_HEADS) #define NUM_CYLS 80 #define BLOCK_SIZE TD_SECTOR #define NUM_BLOCKS (NUM_CYLS * NUM_HEADS * NUMSECS) #define ROOT_BLOCK (NUM_BLOCKS / 2) #define BITMAP_INDEX 79 #define NUM_LONGS (NUM_BLOCKS / 32) /* File i/o information */ #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 /* LHwarp commands */ #define WARP_READ 1 #define WARP_WRITE 2 /* For buffered i/o */ #define IN_BUFFER_SIZE 16384 #define OUT_BUFFER_SIZE 16384 /* Only LZHUF is supported at the moment */ #define COMPTYPE_LHARC 0 #define COMPTYPE_NONE 1 /* Track data types */ #define DATATYPE_NORMAL 0 #define DATATYPE_RAW 1 #define DATATYPE_NORMAL_BLANK 2 /* CRC-32 macro */ #define UPDC32(b, c) (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF)) 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; }; struct CompHeader110 { UBYTE CompressionType; UBYTE DataType; UBYTE TrackNumber; UBYTE Unused; ULONG SectorMask; ULONG FullLength; ULONG CompressedLength; ULONG CRC; }; UBYTE *iotd_SecLabel = NULL; struct WarpHeader WHeader; struct IOExtTD *ReadMsg = NULL; struct IOExtTD *WriteMsg = NULL; struct MsgPort *ReadPort = NULL; struct MsgPort *WritePort = NULL; long GlobalTrack; long GlobalSector; ULONG GlobalSectorMap; extern FILE *infile; /* Input file handle */ extern FILE *outfile; /* Output file handle */ extern UBYTE *FilePosition; /* For memory getc() and putc() functions */ extern UBYTE *EndOfFilePosition; /* For memory getc() and putc() functions */ extern UBYTE *PutFilePosition; /* For memory getc() and putc() functions */ extern long cr3tab[]; /* External CRC-32 table */ /* 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; /* Version 1.01 */ struct CompHeader102 CHeader102; /* Version 1.02/1.03 */ struct CompHeader110 CHeader110; /* Version 1.10/1.11 */ char FileName[256]; char TextFileName[256]; UBYTE Command; UBYTE AppendTextFile; USHORT Version; UBYTE UseBitMap; BPTR FHandle; ULONG StartTrack; ULONG EndTrack; ULONG Unit; APTR DataBlock = NULL; APTR NewBlock = NULL; APTR TrackdiskBlock = NULL; UBYTE BitMapAllocation[NUM_CYLS][NUMSECS * NUM_HEADS]; /* __regargs ... Isn't Lattice C amazing? */ long __regargs GetFileLength(char *FileToOpen); /* Find file length */ ULONG __regargs DoSum(UBYTE *Block, ULONG Length); /* Checksum-32 routine */ ULONG __regargs DoCRC(UBYTE *Block, ULONG Length); /* Fast CRC-32 routine */ void __regargs Decode(ULONG Size); /* Uncompress data */ UBYTE ReadCHeader(); /* Read compression header */ void main(int argc, char **argv) { /* Make sure the user supplied the correct number of arguments */ if (argc != 2 && argc != 4 && argc != 6 && argc != 7) { Title(); exit (1); } BuildFileName(argv); if (!stricmp(argv[1], "READ")) { DoReadInit(); UseBitMap = 1; } else if (!stricmp(argv[1], "WRITE")) { Command = WARP_WRITE; } else if (!stricmp(argv[1], "NOMAP")) { DoReadInit(); UseBitMap = 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 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 IOExtTD *) CreateExtIO(ReadPort, (long) sizeof(struct IOExtTD)))) { puts("Couldn't create i/o read request"); CleanUp(); exit (1); } if (!(WriteMsg = (struct IOExtTD *) 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) { register UBYTE *OutBuffer; UBYTE CanSetBuffer; ULONG CurrentPosition; ULONG AfterEncodeLength; ULONG TotalEncodeLength; register BPTR outfp; /* Allocate a file buffer if we can */ 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(&CHeader110, sizeof(struct CompHeader110), 1, outfile); GlobalTrack = Track; GlobalSector = 0; Encode((ULONG) (DataSize)); fclose(outfile); if (CanSetBuffer) { FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE); } AfterEncodeLength = GetFileLength(FileName); TotalEncodeLength = AfterEncodeLength - CurrentPosition - sizeof(struct CompHeader110); if (!(outfp = (BPTR) Open(FileName, (long) MODE_READWRITE))) { printf("Couldn't open temporary file for output\n\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); CHeader110.CompressedLength = TotalEncodeLength; CHeader110.FullLength = DataSize; CHeader110.TrackNumber = (UBYTE) Track; CHeader110.CompressionType = COMPTYPE_LHARC; CHeader110.DataType = DATATYPE_NORMAL; /* Checksum the block */ CHeader110.CRC = (ULONG) DoCRC(NewBlock, (ULONG) CHeader110.FullLength); /* Write it to disk */ Write((BPTR) outfp, &CHeader110, (long) sizeof(struct CompHeader110)); /* Close the file */ Close((BPTR) outfp); } WriteData() { ULONG j; ULONG Track; UBYTE *TextMemory; UBYTE *TextCompMemory; UBYTE *ExtendedDataBlock; ULONG CheckSum; ULONG TracksWritten = 0L; long Error; long z; register UBYTE *WriteLocation; register UBYTE *TrackdiskBlockLoc; 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("Insert destination disk in drive %ld and press RETURN when ready", Unit); fflush(stdout); while (getc(stdin) != 10) { } puts(""); 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); /* Get the version number */ Version = (WHeader.MajorVersion * 100) + (WHeader.MinorVersion * 10) + WHeader.DecimalVersion; /* 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"); } else { printf("Disk was compressed using Lhwarp %d.%d%d\n\n", WHeader.MajorVersion, WHeader.MinorVersion, WHeader.DecimalVersion); } 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; /* Don't display '.' and 'o' when decompressing text */ GlobalTrack = 0; 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 there are no more tracks to be written, exit */ if (ReadCHeader()) { break; } FilePosition = (UBYTE *) DataBlock; PutFilePosition = (UBYTE *) NewBlock; if (Version == 101) { EndOfFilePosition = (UBYTE *) ( ((UBYTE *) DataBlock) + CHeader101.CompressedLength); fread(DataBlock, (long) CHeader101.CompressedLength, 1, infile); /* Version 1.01 didn't support individual sectors */ GlobalTrack = 0; Decode((ULONG) CHeader101.FullLength); Track = (ULONG) CHeader101.TrackNumber; /* Copy data into CHIP RAM */ CopyMem(NewBlock, TrackdiskBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH); ExtendedDataBlock = (UBYTE *) ( ((UBYTE *) NewBlock) + ((ULONG) TRACK_SIZE)); CopyMem(ExtendedDataBlock, (UBYTE *) &iotd_SecLabel[0], (ULONG) LABEL_LENGTH); printf("Writing track %2ld\r", (ULONG) (Track)); fflush(stdout); } else if ((Version == 110 || Version == 111) && CHeader110.DataType == DATATYPE_NORMAL_BLANK) { Track = (ULONG) CHeader110.TrackNumber; ClearMem(TrackdiskBlock, (ULONG) TRACK_SIZE); ClearMem(&iotd_SecLabel[0], (ULONG) LABEL_LENGTH); WriteMsg->iotd_Req.io_Offset = (long) (TRACK_SIZE * Track); WriteMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock; WriteMsg->iotd_Req.io_Length = (ULONG) TRACK_SIZE; WriteMsg->iotd_SecLabel = (ULONG) &iotd_SecLabel[0]; WriteMsg->iotd_Count = 0xFFFFFFFF; printf("Writing track %2ld: ______________________\r", (ULONG) (Track)); fflush(stdout); if (Error = DoIO((struct IORequest *) WriteMsg)) { fclose(infile); printf("Fatal error %ld writing to disk in unit %ld -terminating\n\n", Error, Unit); MotorOff(); CleanUp(); exit (1); } } else if (Version == 102 || Version == 103) { EndOfFilePosition = (UBYTE *) ( ((UBYTE *) DataBlock) + CHeader102.CompressedLength); fread(DataBlock, (long) CHeader102.CompressedLength, 1, infile); /* Versions 1.02 and 1.03 didn't support individual sectors */ GlobalTrack = 0; Decode((ULONG) CHeader102.FullLength); Track = (ULONG) CHeader102.TrackNumber; CheckSum = (ULONG) DoSum(NewBlock, (ULONG) CHeader102.FullLength); if (CheckSum != CHeader102.CheckSum) { printf("Warning: Track %ld fails checksum\n", Track); } /* Copy data into CHIP RAM */ CopyMem(NewBlock, TrackdiskBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH); ExtendedDataBlock = (UBYTE *) ( ((UBYTE *) NewBlock) + ((ULONG) TRACK_SIZE)); CopyMem(ExtendedDataBlock, (UBYTE *) &iotd_SecLabel[0], (ULONG) LABEL_LENGTH); printf("Writing track %2ld", (ULONG) (Track)); fflush(stdout); } else if (Version == 110 || Version == 111) { Track = (ULONG) CHeader110.TrackNumber; if (Track) { printf("Writing track %2ld: ", (ULONG) (Track)); /* Display the sectors which are to be decompressed */ for (z = 0; z < (NUMSECS * NUM_HEADS); z++) { putc((UBYTE) Bit(&CHeader110.SectorMask, (UBYTE) z) ? '.' : '_', stdout); } printf("D"); fflush(stdout); } EndOfFilePosition = (UBYTE *) ( ((UBYTE *) DataBlock) + CHeader110.CompressedLength); fread(DataBlock, (long) CHeader110.CompressedLength, 1, infile); /* Tell Decode() which sectors are to be decompressed */ /* so it can display '.' and 'o' properly */ GlobalTrack = CHeader110.TrackNumber; GlobalSectorMap = CHeader110.SectorMask; GlobalSector = 0; Decode((ULONG) CHeader110.FullLength); if (DoCRC(NewBlock, (ULONG) CHeader110.FullLength) != CHeader110.CRC) { printf("Warning: Track %ld fails CRC\n", Track); } WriteLocation = (UBYTE *) NewBlock; TrackdiskBlockLoc = (UBYTE *) TrackdiskBlock; if (!Track) { puts("Disk contains the following bootblock:\n"); DisplayBootBlock(NewBlock); } for (j=0; j < (NUMSECS * NUM_HEADS); j++) { if (Bit(&CHeader110.SectorMask, (UBYTE) j)) { CopyMem(WriteLocation, TrackdiskBlockLoc, (ULONG) (TD_SECTOR)); CopyMem((long) WriteLocation + (long) TD_SECTOR, &iotd_SecLabel[j * 16], (long) 16); WriteLocation = WriteLocation + (TD_SECTOR + 16); TrackdiskBlockLoc = TrackdiskBlockLoc + (long) TD_SECTOR; } else { ClearMem(TrackdiskBlockLoc, (ULONG) (TD_SECTOR)); ClearMem(&iotd_SecLabel[j * 16], (long) 16); TrackdiskBlockLoc = TrackdiskBlockLoc + (long) TD_SECTOR; } } WriteMsg->iotd_Req.io_Offset = (long) (TRACK_SIZE * Track); WriteMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock; WriteMsg->iotd_Req.io_Length = (ULONG) TRACK_SIZE; WriteMsg->iotd_SecLabel = (ULONG) &iotd_SecLabel[0]; WriteMsg->iotd_Count = 0xFFFFFFFF; if (Error = DoIO((struct IORequest *) WriteMsg)) { fclose(infile); printf("Fatal error %ld writing to disk in unit %ld -terminating\n\n", Error, Unit); MotorOff(); CleanUp(); exit (1); } } if (Version == 101 || Version == 102 || Version == 103) { if (!Track) { puts("Disk contains the following bootblock:\n"); DisplayBootBlock(NewBlock); } 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 = (ULONG) &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("\r"); fflush(stdout); TracksWritten++; } /* Push all trackdisk buffers onto the disk */ WriteMsg->iotd_Req.io_Length = 0L; WriteMsg->iotd_Req.io_Command = CMD_UPDATE; DoIO((struct IORequest *) WriteMsg); 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] = 0; for (i=0; i<14; i++) { for (j=0; j<73; j++) { c = *((UBYTE *) ( ((UBYTE *) Data) + (ULONG) (i * 64) + j)); if (c < 32 || c > 126) { c = '.'; } Line[j] = c; } puts(Line); } puts(""); } ReadSector(ULONG Sector) { ULONG Error; ReadMsg->iotd_Req.io_Command = CMD_READ; ReadMsg->iotd_Req.io_Offset = (long) BLOCK_SIZE * Sector; ReadMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock; ReadMsg->iotd_Req.io_Length = (long) BLOCK_SIZE; if (Error = DoIO((struct IORequest *) ReadMsg)) { printf("Error %d reading from trackdisk.device\n", Error); CleanUp(); exit (1); } } GetBitMap() { int BitMapSector; ULONG i; ULONG j; ULONG Mask; ULONG BlockNumber; ULONG TrackNumber; ULONG SectorNumber; for (i=1; i<NUM_CYLS; i++) { for (j=0; j<(NUMSECS * NUM_HEADS); j++) { BitMapAllocation[i][j] = 0; } } /* Track zero and the root track must always be sent */ BitMapAllocation[0][0] = 1; BitMapAllocation[0][1] = 1; BitMapAllocation[(ROOT_BLOCK / 22)][0] = 1; ReadSector((ULONG) ROOT_BLOCK); BitMapSector = (int) *((ULONG *) TrackdiskBlock + BITMAP_INDEX); ReadSector((long) BitMapSector); for (i = 1; i <= NUM_LONGS; i++) { Mask = (ULONG) TrackdiskBlock[i]; for (j = 0; j < 32; j++) { if (i < NUM_LONGS || j < 30) { if (~Mask & 1) { BlockNumber = ((i-1) * 32) + j + 2; TrackNumber = (BlockNumber / 22); SectorNumber = (BlockNumber % 22); BitMapAllocation[TrackNumber][SectorNumber] = 1; } Mask >>= 1; } } } } ReadData() { ULONG AfterEncodeLength; ULONG TotalEncodeLength; ULONG TextLength; ULONG i; ULONG j; ULONG SecsRead; ULONG FileLength; ULONG OriginalLength = 0L; BPTR OutputFile; BPTR outfp; ULONG Error; ULONG DataSize; FILE *TextInFile; UBYTE *TextMemory; UBYTE *ReadLocation; 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("Insert source disk in drive %ld and press RETURN when ready", Unit); fflush(stdout); while (getc(stdin) != 10) { } puts(""); if (UseBitMap) { GetBitMap(); printf("Using disk bitmap to skip unused sectors\n\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.11 */ 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)); GlobalTrack = -1; 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"); } if (StartTrack) { puts(""); } /* Start reading tracks */ for (i = StartTrack; i <= EndTrack; i++) { for (j = 0; j < NUMSECS * NUM_HEADS; j++) { if (BitMapAllocation[i][j]) { break; } } if (UseBitMap && j >= (NUMSECS * NUM_HEADS)) { printf("Reading track %2ld: ______________________\r", (ULONG) i); fflush(stdout); CHeader110.CompressedLength = 0L; CHeader110.FullLength = 0L; CHeader110.TrackNumber = (UBYTE) i; CHeader110.CompressionType = COMPTYPE_NONE; CHeader110.DataType = DATATYPE_NORMAL_BLANK; CHeader110.CRC = 0L; CHeader110.SectorMask = 0L; /* Write it to disk */ if (!(outfp = (BPTR) Open(FileName, (long) MODE_READWRITE))) { printf("Couldn't open %s for output\n\n", FileName); CleanUp(); exit(1); } Seek((BPTR) outfp, (long) 0L, (long) OFFSET_END); Write((BPTR) outfp, &CHeader110, (long) sizeof(struct CompHeader110)); Close((BPTR) outfp); } else { DataSize = 0L; ReadLocation = (UBYTE *) NewBlock; printf("Reading track %2ld: D", (ULONG) (i)); fflush(stdout); SecsRead = 0; for (j=0; j<(NUMSECS * NUM_HEADS); j++) { if ((!UseBitMap) || BitMapAllocation[i][j]) { putc('.', stdout); ReadMsg->iotd_Req.io_Offset = (long) (TRACK_SIZE * i) + (j * TD_SECTOR); ReadMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock; ReadMsg->iotd_Req.io_Length = (long) TD_SECTOR; ReadMsg->iotd_SecLabel = (UBYTE *) TrackdiskBlock + TD_SECTOR; ReadMsg->iotd_Count = 0xFFFFFFFF; DoIO((struct IORequest *) ReadMsg); CopyMem(TrackdiskBlock, ReadLocation, (ULONG) (TD_SECTOR + 16)); ReadLocation = ReadLocation + (TD_SECTOR + 16); SecsRead++; DataSize = DataSize + (TD_SECTOR + 16); SetBit(&CHeader110.SectorMask, (UBYTE) j, (UBYTE) 1); } else { putc('_', stdout); SetBit(&CHeader110.SectorMask, (UBYTE) j, (UBYTE) 0); } } printf("D"); fflush(stdout); FilePosition = (UBYTE *) NewBlock; EndOfFilePosition = (UBYTE *) ( ((UBYTE *) NewBlock) + (DataSize)); Archive(i, DataSize); putc('\r', stdout); fflush(stdout); OriginalLength += (DataSize); } } 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 <Command> <Unit> <Filename> <StartTrack> <EndTrack> <TextFile>\n"); puts("<Command> Read, NoMap, or Write"); puts("<Unit> Drive number (0 for internal, 1 ... 3 for external)"); puts("<Filename> Output or input filename"); puts("<StartTrack> Track number (0 ... 79) [valid only in read mode]"); puts("<EndTrack> Track number (0 ... 79) [valid only in read mode]"); puts("<TextFile> Attach text in <TextFile> to output file (optional)\n"); } long __regargs GetFileLength(char *FileToOpen) { FILE *fp; long Length; if (!(fp = fopen(FileToOpen, "r"))) { return (NULL); } fseek(fp, 0L, SEEK_END); Length = ftell(fp); fclose(fp); return (Length); } /* 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 __regargs DoSum(UBYTE *Block, ULONG Length) { register ULONG Sum = 0; register ULONG i; for (i = 0; i < Length; i++) { Sum = Sum + Block[i]; } return (Sum); } ULONG __regargs DoCRC(UBYTE *Block, ULONG Length) { register ULONG CRC = 0; register ULONG i; for (i = 0; i < Length; i++) { CRC = UPDC32(Block[i], CRC); } return (CRC); } BuildFileName(char **argv) { /* 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"); } } } Caution() { UBYTE c; 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("Caution: File %s already exists. Remove it? (y/n) ", FileName); fflush(stdout); while (toupper(c = getc(stdin)) != 'Y' && toupper(c) != 'N') { } if (toupper(c) == 'N') { puts("\n"); CleanUp(); exit(1); } /* Get rid of the 'return' character */ getc(stdin); } DoReadInit() { if (!access(FileName, 0)) { Caution(); /* Remove the file if it was already there */ remove(FileName); Command = WARP_READ; } } ClearMem(register UBYTE *source, register ULONG size) { do { *source = 0; source++; size--; } while (size); } Bit(register UBYTE *StartByte, register UBYTE Position) { register UBYTE WhichByte; register UBYTE WhichBit; WhichByte = Position / 8; WhichBit = Position % 8; return (StartByte[WhichByte] & (1 << WhichBit)); } SetBit(register UBYTE *StartByte, register UBYTE Position, register UBYTE Value) { register UBYTE WhichByte; register UBYTE WhichBit; WhichByte = Position / 8; WhichBit = Position % 8; StartByte[WhichByte] = Value ? (StartByte[WhichByte] | (1 << WhichBit)) : (StartByte[WhichByte] & (~(1 << WhichBit))); } UBYTE ReadCHeader() { if (Version == 101) { if (!(fread(&CHeader101, sizeof(struct CompHeader101), 1, infile))) { return (1); } } else if (Version == 102 || Version == 103) { if (!(fread(&CHeader102, sizeof(struct CompHeader102), 1, infile))) { return (1); } } else { if (!(fread(&CHeader110, sizeof(struct CompHeader110), 1, infile))) { return (1); } } return (0); }