(* Title : Unpack.MOD Author : Kim Moser System : JPI's TopSpeed Modula-2 with PMI's Repertoire 1.5c Descrip : Unpacks a packed Doodle file Usage : UNPACK *) MODULE Unpack; (* JPI *) FROM IO IMPORT WrStr, WrLn, WrCard; (* Repertoire *) IMPORT InitJPI; FROM FileIO IMPORT OpenFile, SetFilePtr, BlockRead, CloseHandle, FileLength, FileExists, CreateFile, BlockWrite, FileOffSet; FROM StringIO IMPORT ErrorMessage; FROM EnvironUtils IMPORT ParsedParam; FROM LowLevel IMPORT Address8086, IncAddr; CONST MaxInSize = 30000; (* Maximum allowed length of packed file *) OutSize = 10240; (* Size of unpacked Doodle file *) TYPE inBufType = ARRAY [0..MaxInSize-1] OF BYTE; outBufType = ARRAY [0..OutSize-1 +512] OF BYTE; (* +512 in case of problems *) VAR inName, outName: ARRAY [0..80] OF CHAR; in, out: CARDINAL; inBuf: inBufType; outBuf: outBufType; PROCEDURE CloseFile( VAR f: CARDINAL ); BEGIN IF CloseHandle(f) <> NoError THEN END; END CloseFile; PROCEDURE DoUnpack(); VAR p, q: Address8086; (* Pointers to inBuf, outBuf *) count: CHAR; i, howBig: CARDINAL; (* How many bytes dest is taking up *) BEGIN (* Put $5C00 in first 2 bytes of OutBuf: *) outBuf[0] := BYTE(CHR(0H)); outBuf[1] := BYTE(CHR(5CH)); p.a := ADR(inBuf); q.a := ADR(outBuf); IncAddr( q.a, 2 ); (* Point past where load address is *) howBig := 0; WHILE ( p.b^ <> CHR(0) ) DO count := p.b^; (* How many *) IncAddr( p.a, 1 ); (* Point to char to be replicated *) FOR i := 1 TO ORD(count) DO q.b^ := p.b^; IncAddr( q.a, 1 ); (* Point to next free destination spot *) INC( howBig ); IF howBig > OutSize THEN WrStr( 'OutSize exceeded!' ); RETURN; END; END; IncAddr( p.a, 1 ); (* Point to next count *) END; WrStr( 'Output size: ' ); WrCard( howBig, 1 ); WrLn(); END DoUnpack; BEGIN IF NOT ( ParsedParam(1,inName) AND ParsedParam(2,outName) ) THEN WrStr( 'Usage: UNPACK ' ); WrLn; RETURN; END; IF FileExists( outName ) THEN WrStr( 'Out file exists: ' ); WrStr( outName ); WrLn(); RETURN; END; IF OpenFile( in, inName ) <> NoError THEN WrStr( 'Unable to open in file: ' ); WrStr( inName ); WrLn(); RETURN; END; SetFilePtr( in, FromStart, VAL(LONGINT,2) ); (* Skip load address *) IF BlockRead( in, ADR(inBuf), VAL(CARDINAL,FileLength(in))-2 ) <> NoError THEN (* -2 because we skipped 2 bytes when setting the file ptr *) WrStr( 'Error reading in file: ' ); WrStr( inName ); WrLn(); CloseFile( in ); RETURN; END; CloseFile( in ); IF CreateFile( out, outName ) <> NoError THEN WrStr( 'Unable to create out file: ' ); WrStr( outName ); WrLn(); RETURN; END; DoUnpack(); IF BlockWrite( out, ADR(outBuf), OutSize ) <> NoError THEN WrStr( 'Unable to write to out file: ' ); WrStr( outName ); CloseFile( out ); RETURN; END; CloseFile( out ); WrStr( 'Done.' ); END Unpack.