-- File: LaurelByteBlt.mesa -- Edited by Brotz, December 9, 1981 10:04 PM -- Derived from -- File: AltoMesaByteBlt.mesa, Last Edit: Taft December 2, 1981 4:05 PM DIRECTORY ByteBltDefs, Stream USING [Block], BitBltDefs USING [BBptr, BBTable, BITBLT], Inline USING [BITAND, COPY]; LaurelByteBlt: PROGRAM IMPORTS BitBltDefs, Inline EXPORTS ByteBltDefs = BEGIN StartIndexGreaterThanStopIndexPlusOne: PUBLIC ERROR = CODE; -- This implementation purportedly handles all cases of overlapping blocks. ByteBlt: PUBLIC PROCEDURE [to, from: Stream.Block] RETURNS [nBytes: CARDINAL] = BEGIN toBase, fromBase: ORDERED POINTER TO PACKED ARRAY [0..0) OF [0..377B); toByte, fromByte: [0..1]; nWords: CARDINAL; nBytesLocal: CARDINAL; -- use for local purposes, since nBytes is returned. -- This check is necessary since subtracting CARDINALs gives big numbers IF to.startIndex>to.stopIndexPlusOne OR from.startIndex>from.stopIndexPlusOne THEN ERROR StartIndexGreaterThanStopIndexPlusOne; nBytes _ MIN[to.stopIndexPlusOne-to.startIndex, from.stopIndexPlusOne-from.startIndex]; IF nBytes=0 THEN RETURN; nBytesLocal _ nBytes; -- Slow byte copy loop -- -- toBase _ LOOPHOLE[ShortenPointer[to.blockPointer]]; -- fromBase _ LOOPHOLE[ShortenPointer[from.blockPointer]]; -- IF toBase > fromBase THEN -- FOR i: CARDINAL DECREASING IN [0 .. nBytesLocal) DO -- toBase[to.startIndex + i] _ fromBase[from.startIndex + i] -- ENDLOOP -- ELSE -- FOR i: CARDINAL IN [0 .. nBytesLocal) DO -- toBase[to.startIndex + i] _ fromBase[from.startIndex + i] -- ENDLOOP; -- RETURN; -- Beginning of old code. -- adjust bases to reduce byte offsets to [0..1] toBase _ LOOPHOLE[ShortenPointer[to.blockPointer], ORDERED POINTER] + to.startIndex/2; fromBase _ LOOPHOLE[ShortenPointer[from.blockPointer], ORDERED POINTER] + from.startIndex/2; toByte _ to.startIndex MOD 2; fromByte _ from.startIndex MOD 2; nWords _ nBytesLocal/2; IF toByte=fromByte AND toBase NOT IN (fromBase .. fromBase+nWords] THEN -- fast case: bytes are in phase, and either there is no overlap or -- the block is being slid "down" in memory. BEGIN -- move the first odd byte (if any) to be sure that blocks are word aligned IF toByte#0 THEN BEGIN toBase[toByte] _ fromBase[fromByte]; nBytesLocal _ nBytesLocal-1; nWords _ nBytesLocal/2; toBase _ toBase+1; -- know we just moved the odd byte of both words fromBase _ fromBase+1; END; Inline.COPY[to: toBase, from: fromBase, nwords: nWords ]; IF (nBytesLocal MOD 2)#0 THEN -- move the one and only remaining byte toBase[nBytesLocal - 1] _ fromBase[nBytesLocal - 1]; END ELSE -- slow case: bytes are out of phase, or there is an overlap and the block -- is being slid "up" in memory. Do it with BITBLT. BEGIN lineWidth: CARDINAL = 16; -- words per scan line: controls interrupt latency. -- BITBLT is not interruptable except at the end of each scan line, so we -- break things up into chunks in order to maintain reasonable interrupt latency -- for the IO devices. It takes about 200microsec to move 50 bytes with the -- display off. bba: ARRAY [0..SIZE[BitBltDefs.BBTable]] OF WORD; -- NB: [...] gets us one extra bbt: BitBltDefs.BBptr _ Inline.BITAND[BASE[bba]+1, 177776B]; -- even word lines, tail: CARDINAL; direction: {forward, backward} = -- forward means left-to-right, top-to-bottom IF toBase