-- XDisplay.mesa -- Mesa 6 version (won't work on Alto) -- Last changed by Doug Wyatt, May 31, 1980 10:16 PM DIRECTORY XDisplayDefs USING [BankIndex, BBAPtr, BBArray, BBDest, BBPtr, BMPtr, BitBlt, DcbArray, dcbChain, dcbNIL, DcbPtr, FirstDcb, LPBank, LPPtr, NextDcb, pBitBlt], AltoHardware USING [BankRegisters, Task], BitBltDefs USING [BITBLT], ImageDefs USING [AddCleanupProcedure, AllReasons, CleanupItem, CleanupProcedure], SegmentDefs, SystemDefs USING [PagesForWords]; XDisplay: PROGRAM IMPORTS XDisplayDefs,BitBltDefs,ImageDefs,SegmentDefs,SystemDefs EXPORTS XDisplayDefs SHARES XDisplayDefs = BEGIN OPEN XDisplayDefs; XDisplayError: PUBLIC SIGNAL = CODE; dBank: PUBLIC BankIndex←0; -- AltoIIXM bank registers Task: TYPE = AltoHardware.Task; -- The display word task (DWT) is the one that reads words -- out of the bitmap; its bank register supplies the high order -- bits of the long pointer used to address those words. SelectDBank: PROCEDURE[config: SegmentDefs.MemoryConfig] RETURNS[BankIndex] = BEGIN -- b: BankIndex; -- FOR b IN (0..LAST[BankIndex]] -- DO -- IF InlineDefs.BITAND[config.banks,bankMasks[b]]#0 THEN RETURN[b]; -- ENDLOOP; RETURN[0]; END; EnableDBank: PROCEDURE[BOOLEAN] ← NoopEnableDBank; NoopEnableDBank: PROCEDURE[BOOLEAN] = BEGIN END; AltoEnableDBank: PROCEDURE[on: BOOLEAN] = BEGIN AltoHardware.BankRegisters[DWT].normal←IF on THEN dBank ELSE 0 END; AllocDSegment: PUBLIC PROCEDURE[pages: CARDINAL] RETURNS[LONG POINTER] = BEGIN OPEN SegmentDefs; RETURN[LongSegmentAddress[NewDataSegment[ base: DefaultXMBase, pages: pages]]]; END; FreeDSegment: PUBLIC PROCEDURE[lp: LONG POINTER] = BEGIN OPEN SegmentDefs; DeleteDataSegment[LongVMtoDataSegment[lp]]; END; -- Bitmaps BMSize: PUBLIC PROCEDURE[bm: BMPtr, width,height: CARDINAL] = BEGIN w: CARDINAL←(width+15)/16; -- words required for width bm↑←[base: NIL, raster: w, lines: height]; END; BMDisplaySize: PUBLIC PROCEDURE[bm: BMPtr, width,height: CARDINAL] = BEGIN dw: CARDINAL←(width+31)/32; -- double words required for width dl: CARDINAL←(height+1)/2; -- double scanlines required for height bm↑←[base: NIL, raster: 2*dw, lines: 2*dl]; END; AllocBitmap: PUBLIC PROCEDURE[bm: BMPtr] = BEGIN pages: CARDINAL←SystemDefs.PagesForWords[bm.raster*bm.lines]; IF pages>0 THEN BEGIN bm.base←AllocDSegment[pages]; ClearBitmap[bm] END ELSE bm.base←NIL; END; FreeBitmap: PUBLIC PROCEDURE[bm: BMPtr] = BEGIN IF bm.base#NIL THEN BEGIN FreeDSegment[bm.base]; bm.base←NIL END; END; ClearBitmap: PUBLIC PROCEDURE[bm: BMPtr] = BEGIN bba: BBArray; bbt: BBPtr←BBInit[@bba]; IF bm.base=NIL THEN RETURN; BBDest[bbt,bm]; bbt.dw←bm.raster*16; bbt.dh←bm.lines; BitBlt[bbt]; END; -- Display Control Blocks Even: PROCEDURE[p: POINTER] RETURNS[POINTER] = INLINE BEGIN RETURN[p+(LOOPHOLE[p,CARDINAL] MOD 2)] END; dcbSeal: POINTER = LOOPHOLE[177423B]; -- The D-machines will regard dcb.lbitmap as the bitmap pointer only if -- dcb.tag=long AND dcb.bitmap=dcbSeal DcbInit: PUBLIC PROCEDURE[dcba: POINTER TO DcbArray] RETURNS[DcbPtr] = BEGIN dcb: DcbPtr←Even[dcba]; dcb↑←[]; -- use default initialization in XDisplayDefs RETURN[dcb]; END; EnumerateDcbs: PUBLIC PROCEDURE [Proc: PROCEDURE[DcbPtr] RETURNS[BOOLEAN]] RETURNS[DcbPtr] = BEGIN dcb: DcbPtr; FOR dcb←FirstDcb[],NextDcb[dcb] UNTIL dcb=dcbNIL DO IF Proc[dcb] THEN EXIT ENDLOOP; RETURN[dcb]; END; LinesAbove: PUBLIC PROCEDURE[dcb: DcbPtr] RETURNS[CARDINAL] = BEGIN lines: CARDINAL←0; CountLines: PROCEDURE[tdcb: DcbPtr] RETURNS[BOOLEAN] = BEGIN IF tdcb=dcb THEN RETURN[TRUE] ELSE BEGIN lines←lines+2*tdcb.height; RETURN[FALSE] END; END; []←EnumerateDcbs[CountLines]; RETURN[lines]; END; InsertDcb: PUBLIC PROCEDURE[dcb,otherdcb: DcbPtr] = BEGIN Ins: PROCEDURE[tdcb: DcbPtr] RETURNS[BOOLEAN] = BEGIN found: BOOLEAN←(tdcb.next=otherdcb); IF found THEN tdcb.next←dcb; RETURN[found]; END; dcb.next←otherdcb; IF otherdcb=dcbChain↑ THEN dcbChain↑←dcb ELSE []←EnumerateDcbs[Ins]; END; RemoveDcb: PUBLIC PROCEDURE[dcb: DcbPtr] = BEGIN Rem: PROCEDURE[tdcb: DcbPtr] RETURNS[BOOLEAN] = BEGIN found: BOOLEAN←(tdcb.next=dcb); IF found THEN tdcb.next←dcb.next; RETURN[found]; END; IF dcb=dcbChain↑ THEN dcbChain↑←dcb.next ELSE []←EnumerateDcbs[Rem]; dcb.next←dcbNIL; END; Displayed: PUBLIC PROCEDURE[dcb: DcbPtr] RETURNS[BOOLEAN] = BEGIN Match: PROCEDURE[tdcb: DcbPtr] RETURNS[BOOLEAN] = BEGIN RETURN[tdcb=dcb] END; RETURN[EnumerateDcbs[Match]=dcb]; END; DcbBitmapProc: PROCEDURE[DcbPtr,BMPtr] ← ShortDcbBitmap; pDcbBitmap: PUBLIC POINTER TO PROCEDURE[DcbPtr,BMPtr] ← @DcbBitmapProc; ShortDcbBitmap: PROCEDURE[dcb: DcbPtr, bm: BMPtr] = BEGIN IF bm.base#NIL AND LPBank[bm.base]#dBank THEN BEGIN SIGNAL XDisplayError; RETURN END; -- Bitmap not in dBank dcb.width←0; dcb.tag←short; dcb.bitmap←LPPtr[bm.base]; dcb.height←bm.lines/2; dcb.width←(bm.raster/2)*2; END; LongDcbBitmap: PROCEDURE[dcb: DcbPtr, bm: BMPtr] = BEGIN dcb.width←0; dcb.tag←long; dcb.bitmap←dcbSeal; dcb.lbitmap←bm.base; dcb.height←bm.lines/2; dcb.width←(bm.raster/2)*2; END; -- BitBlt BBInit: PUBLIC PROCEDURE[bba: BBAPtr] RETURNS[BBPtr] = BEGIN bb: BBPtr←Even[bba]; bb↑←[]; -- use default initialization in XDisplayDefs RETURN[bb]; END; BitBltProc: PROCEDURE[BBPtr,BankIndex] ← AltoBitBlt; pBitBlt: PUBLIC POINTER TO PROCEDURE[BBPtr,BankIndex] ← @BitBltProc; AltoBitBlt: PROCEDURE[bbt: BBPtr, altbank: BankIndex] = BEGIN ERROR XDisplayError; -- AltoBitBlt not implemented END; D0BitBlt: PROCEDURE[bbt: BBPtr, altbank: BankIndex] = BEGIN bbt.ptrs←D0; BitBltDefs.BITBLT[LOOPHOLE[bbt]]; bbt.ptrs←Alto; END; Reconfigure: PROCEDURE = BEGIN bankreg,dmachine: BOOLEAN; config: SegmentDefs.MemoryConfig←SegmentDefs.GetMemoryConfig[]; bankreg←config.AltoType=AltoIIXM; -- only AltoIIXM has bank registers dmachine←config.AltoType=D0 OR config.AltoType=Dorado; EnableDBank←IF bankreg THEN AltoEnableDBank ELSE NoopEnableDBank; BitBltProc←IF dmachine THEN D0BitBlt ELSE AltoBitBlt; DcbBitmapProc←IF dmachine THEN LongDcbBitmap ELSE ShortDcbBitmap; dBank←SelectDBank[config]; EnableDBank[TRUE]; END; XDisplayCleanupItem: ImageDefs.CleanupItem ← [link:, proc: XDisplayCleanupProc, mask: ImageDefs.AllReasons]; XDisplayCleanupProc: ImageDefs.CleanupProcedure = BEGIN SELECT why FROM Finish,Abort => BEGIN dcbChain↑ ← dcbNIL; EnableDBank[FALSE] END; Save,Checkpoint => EnableDBank[FALSE]; InLd => EnableDBank[TRUE]; Restore,Continue => Reconfigure; ENDCASE; END; XDisplayCleanupProc[Restore]; ImageDefs.AddCleanupProcedure[@XDisplayCleanupItem]; END.