IMPLEMENTATION MODULE ByteFiddler; (* * REPERTOIRE * Release 1.6 * By Charles Bradford and Cole Brecheen * (c) Copyright 1985-1992 PMI * Green Bay, Wisconsin * All rights reserved * (414) 468-6040 * * $Header: D:/logfiles/mods/bytefidd.mov 1.5 10 Mar 1991 15:25:24 coleb $ * *) IMPORT ErrorManager; IMPORT LowLevel; IMPORT SYSTEM; VAR Initialized : BOOLEAN; PROCEDURE Init(); BEGIN IF Initialized THEN RETURN; ELSE Initialized := TRUE; END; ErrorManager.Init(); LowLevel.Init(); END Init; TYPE BitRange = [0..15]; WordConverter = RECORD CASE : BOOLEAN OF TRUE : x : SYSTEM.WORD; | FALSE : lo, hi : CHAR; END; END; LongConverter = RECORD CASE : BOOLEAN OF TRUE: long: LONGINT; | FALSE: locard, hicard: CARDINAL; END; END; PROCEDURE BitRangeToInt(TheSet : BITSET; LowBit, HighBit : CARDINAL; VAR answer : CARDINAL); (*BitRangeToInt lets us specify the bits that store the value in which we're interested, and it loads that value into the last parameter in the list.*) BEGIN LowLevel.ShiftLeft(TheSet, 15-HighBit); (*Assumes bit 15 is most significant.*) LowLevel.ShiftRight(TheSet, LowBit+(15-HighBit)); answer := CARDINAL(TheSet); END BitRangeToInt; PROCEDURE BytesToWord(lobyte, hibyte : CARDINAL) : CARDINAL; (*Takes two bytes and stores them in a single word. The last byte in the parameter list is most significant.*) VAR conv : WordConverter; BEGIN conv.lo := CHR(lobyte); conv.hi := CHR(hibyte); RETURN (CARDINAL(conv.x)); END BytesToWord; PROCEDURE CardinalToDate(TheInt : CARDINAL; VAR month, day, year : CARDINAL); VAR TheSet : BITSET; BEGIN (*CardinalToDate*) TheSet := BITSET(TheInt); (* Diagnostics.diagB( 'TheDate', TheSet ); *) BitRangeToInt(TheSet, 0, 4, day); BitRangeToInt(TheSet, 5, 8, month); BitRangeToInt(TheSet, 9, 15, year); INC(year, 80); END CardinalToDate; PROCEDURE CardinalToTime(TheCardinal : CARDINAL; VAR hours, minutes, seconds : CARDINAL); VAR TheSet : BITSET; BEGIN (*CardinalToTime*) TheSet := BITSET(TheCardinal); (* Diagnostics.diagB( 'TheTime', TheSet ); *) BitRangeToInt(TheSet, 11, 15, hours); BitRangeToInt(TheSet, 5, 10, minutes); BitRangeToInt(TheSet, 0, 4, seconds); seconds := seconds*2; (*We double seconds because the operating system stores this value in two-second increments.*) END CardinalToTime; PROCEDURE DateToCardinal(month, day, year : CARDINAL) : CARDINAL; CONST msg = 'Invalid date'; VAR BitSet1, BitSet2 : BITSET; buf : BitRange; BEGIN (*DateToCardinal*) IF year>1900 THEN year := year-1900; END; IF ((year>=80) AND (year<=199)) THEN year := year-80; ELSE (* Diagnostics.diagC( 'year', year ); *) ErrorManager.WARN(msg); END; IF ((month<1) OR (month>12)) THEN (* Diagnostics.diagC( 'month', month ); *) ErrorManager.WARN(msg); END; IF ((day<1) OR (day>31)) THEN (* Diagnostics.diagC( 'day', day ); *) ErrorManager.WARN(msg); END; BitSet2 := BITSET(0); BitSet1 := BITSET(day); FOR buf := 0 TO 15 DO IF buf IN BitSet1 THEN INCL(BitSet2, buf); END; END; BitSet1 := BITSET(month); FOR buf := 0 TO 15 DO IF buf IN BitSet1 THEN INCL(BitSet2, buf+5); END; END; BitSet1 := BITSET(year); FOR buf := 0 TO 15 DO IF buf IN BitSet1 THEN INCL(BitSet2, buf+9); END; END; RETURN CARDINAL(BitSet2); END DateToCardinal; PROCEDURE HighByte( TheCard: CARDINAL ): CHAR; VAR tmp: WordConverter; BEGIN tmp.x := SYSTEM.WORD(TheCard); RETURN tmp.hi; END HighByte; PROCEDURE HighCard( TheLong: LONGINT ): CARDINAL; VAR tmp: LongConverter; BEGIN tmp.long := TheLong; RETURN tmp.hicard; END HighCard; PROCEDURE LowByte( TheCard: CARDINAL ): CHAR; VAR tmp: WordConverter; BEGIN tmp.x := SYSTEM.WORD(TheCard); RETURN tmp.lo; END LowByte; PROCEDURE LowCard( TheLong: LONGINT ): CARDINAL; VAR tmp: LongConverter; BEGIN tmp.long := TheLong; RETURN tmp.locard; END LowCard; PROCEDURE PeekChar( TheAdr: SYSTEM.ADDRESS ): CHAR; VAR tmp: LowLevel.Address8086; BEGIN tmp.a := TheAdr; RETURN tmp.b^; END PeekChar; PROCEDURE PokeChar( TheChar: CHAR; TheAdr: SYSTEM.ADDRESS ); VAR tmp: LowLevel.Address8086; BEGIN tmp.a := TheAdr; tmp.b^ := TheChar; END PokeChar; PROCEDURE Size( VAR AnyObject: ARRAY OF SYSTEM.BYTE ): CARDINAL; BEGIN RETURN HIGH(AnyObject) + 1; END Size; PROCEDURE swap(VAR TheWord : SYSTEM.WORD); (*Reverses the order of the high and low bytes in TheWord.*) VAR conv : WordConverter; tmp : CHAR; BEGIN conv.x := TheWord; tmp := conv.hi; conv.hi := conv.lo; conv.lo := tmp; TheWord := conv.x; END swap; PROCEDURE TimeToCardinal(hours, minutes, seconds : CARDINAL) : CARDINAL; CONST msg = 'Invalid time'; VAR BitSet1, BitSet2 : BITSET; buf : BitRange; BEGIN (*TimeToCardinal*) IF (hours>23) THEN (* Diagnostics.diagC( 'hours', hours ); *) ErrorManager.WARN(msg); END; IF (minutes>59) THEN (* Diagnostics.diagC( 'minutes', minutes ); *) ErrorManager.WARN(msg); END; IF (seconds>59) THEN (* Diagnostics.diagC( 'seconds', seconds ); *) ErrorManager.WARN(msg); END; BitSet2 := BITSET(0); BitSet1 := BITSET(seconds DIV 2); FOR buf := 0 TO 15 DO IF buf IN BitSet1 THEN INCL(BitSet2, buf); END; END; BitSet1 := BITSET(minutes); FOR buf := 0 TO 15 DO IF buf IN BitSet1 THEN INCL(BitSet2, buf+5); END; END; BitSet1 := BITSET(hours); FOR buf := 0 TO 15 DO IF buf IN BitSet1 THEN INCL(BitSet2, buf+11); END; END; RETURN CARDINAL(BitSet2); END TimeToCardinal; BEGIN Initialized := FALSE; Init(); END ByteFiddler.