<> <> DIRECTORY BitBlt, ViewerOps, CKViewerButtons, ColorDisplay, MessageWindow, Inline, Process USING [MsecToTicks, Pause]; CKViewerOps: PROGRAM IMPORTS BitBlt, ColorDisplay, Inline, Process, MessageWindow, ViewerOps EXPORTS CKViewerButtons = BEGIN OPEN MW: MessageWindow; CKViewer: TYPE = CKViewerButtons.CKViewer; CKViewerState: TYPE = CKViewerButtons.CKViewerState; sym: BOOLEAN _ FALSE; bbspace: BitBlt.BBTableSpace; bb: BitBlt.BBptr _ InitBB[@bbspace]; grayword: CARDINAL _ 0; bitmap,bitmapB: LONG POINTER _ NIL; wpl,wplB: CARDINAL _ 0; width,height: CARDINAL _ 0; lbpp,lbppB: CARDINAL _ 0; -- log (base 2) bits per pixel bpp,bppB: CARDINAL _ 0; -- bits per pixel full: BOOLEAN _ FALSE; ashow,bshow: BOOLEAN _ TRUE; splat: BOOLEAN _ TRUE; test: BOOLEAN _ FALSE; neg: BOOLEAN _ FALSE; cornerSize: CARDINAL _ 4; cornerColor: CARDINAL _ 8; Triple: TYPE = RECORD[r,g,b: [0..256)]; testmap: ARRAY[0..8] OF Triple _ [ [127,127,127], -- gray (background) [ 0, 0, 0], -- black [255, 0, 0], -- red [ 0,255, 0], -- green [255,255, 0], -- yellow [ 0, 0,255], -- blue [255, 0,255], -- magenta [ 0,255,255], -- cyan [255,255,255] -- white ]; ShowTPat: PROC = { x: CARDINAL = 60; h: CARDINAL = 60; w: CARDINAL = 50; gap: CARDINAL = 15; IF NOT full THEN { FOR i: CARDINAL IN[0..9) DO ColorDisplay.SetColor[pixelA: i, r: testmap[i].r, g: testmap[i].g, b: testmap[i].b]; ENDLOOP; ColorDisplay.Show[TRUE,FALSE,FALSE]; }; <> Rect[0,0,width,height,0]; <> { s: CARDINAL = cornerSize; c: CARDINAL = cornerColor; -- color Rect[0,0,s,s,c]; Rect[width-s,0,s,s,c]; Rect[0,height-s,s,s,c]; Rect[width-s,height-s,s,s,c]; }; <> FOR i: CARDINAL IN[0..8) DO r,g,b: [0..256); r _ (i MOD 2)*255; g _ ((i/2) MOD 2)*255; b _ ((i/4) MOD 2)*255; Rect[4,i*h+10,x,h-20,i+1]; ENDLOOP; <> FOR i: CARDINAL IN[0..8) DO r,g,b: [0..256); r _ (i MOD 2)*255; g _ ((i/2) MOD 2)*255; b _ ((i/4) MOD 2)*255; Rect[x+i*w+gap,0,w-gap,8*h,i+1]; ENDLOOP; }; Rect: PROC[x,y,w,h: CARDINAL, i: [0..8]] = { IF NOT (x> <> <> <> <> <> <> <> <> <<};>> <<>> <> <> <> <> <> <> <> <> <> <<};>> MyRandom: PROCEDURE [max: CARDINAL] RETURNS [CARDINAL] = INLINE BEGIN RETURN[Random[] MOD max]; END; SetGray: PROC[g: [0..256)] = { grayword _ MakeGray[g] }; MakeGray: PROC[g: [0..256)] RETURNS[CARDINAL] = { grayword: CARDINAL _ 0; IF bpp#0 THEN { ppw: CARDINAL _ 16/bpp; -- pixels per word mask: CARDINAL _ Inline.BITNOT[Inline.BITSHIFT[-1,bpp]]; g _ Inline.BITAND[g,mask]; THROUGH [0..ppw) DO grayword _ Inline.BITSHIFT[grayword,bpp] + g ENDLOOP; }; RETURN[grayword]; }; InitBB: PROC[bbs: POINTER TO BitBlt.BBTableSpace] RETURNS[BitBlt.BBptr] = INLINE { bb: BitBlt.BBptr _ BitBlt.AlignedBBTable[bbs]; bb^ _ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: @grayword, bit: 0], srcDesc: [gray[[yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]]], width: 0, height: 0, flags: [disjoint: TRUE, gray: TRUE] ]; RETURN[bb]; }; FullRect: PROC[x,y,w,h: CARDINAL, r,g,b: [0..256)] = { rgword: CARDINAL _ 256*r + g; bbword: CARDINAL _ 256*b + b; IF NOT full THEN RETURN; <> bb.dst _ [word: ColorDisplay.baseA + LONG[y]*ColorDisplay.wplA + x, bit: 0]; bb.dstBpl _ 16*ColorDisplay.wplA; bb.src _ [word: @rgword, bit: 0]; bb.width _ 16*w; bb.height _ h; bb.flags.dstFunc _ null; BitBlt.BITBLT[bb]; <> bb.dst _ [word: ColorDisplay.baseB + LONG[y]*ColorDisplay.wplB + x/2, bit: 8*(x MOD 2)]; bb.dstBpl _ 16*ColorDisplay.wplB; bb.src _ [word: @bbword, bit: bb.dst.bit]; bb.width _ 8*w; bb.height _ h; bb.flags.dstFunc _ null; BitBlt.BITBLT[bb]; }; ARect: PROC[x,y,w,h: CARDINAL, i: [0..256), fn: BitBlt.DstFunc _ null] = { iword: CARDINAL _ MakeGray[i]; xbit: CARDINAL _ Inline.BITSHIFT[x,lbpp]; bb.dst _ [word: ColorDisplay.baseA + LONG[y]*ColorDisplay.wplA + xbit/16, bit: xbit MOD 16]; bb.dstBpl _ 16*ColorDisplay.wplA; bb.src _ [word: @iword, bit: bb.dst.bit]; bb.width _ Inline.BITSHIFT[w,lbpp]; bb.height _ h; bb.flags.dstFunc _ fn; BitBlt.BITBLT[bb]; }; index: [0..256) _ 0; Rectangle: PROC[lx,ty,rx,by: CARDINAL, fn: BitBlt.DstFunc _ null] = { IF full THEN { r,g,b: [0..256); r _ MyRandom[256]; g _ MyRandom[256]; b _ MyRandom[256]; FullRect[lx,ty,rx-lx,by-ty,r,g,b]; } ELSE { index _ (index + 1) MOD 256; ARect[lx,ty,rx-lx,by-ty,index,fn]; }; }; BRectangle: PROC[lx,ty,rx,by: CARDINAL] = { xbit: CARDINAL _ Inline.BITSHIFT[lx,lbppB]; black: CARDINAL _ 177777B; bb.dst _ [word: bitmapB + LONG[ty]*wplB + xbit/16, bit: xbit MOD 16]; bb.dstBpl _ 16*wplB; bb.src _ [word: @black, bit: 0]; bb.width _ Inline.BITSHIFT[(rx-lx),lbppB]; bb.height _ by-ty; bb.flags.dstFunc _ xor; BitBlt.BITBLT[bb]; }; RandomSplat: PROCEDURE [ckViewer: CKViewer] = { screenX: CARDINAL = width; screenY: CARDINAL = height; XorRatio: CARDINAL = 3; ty, ty2, lx, w, h: CARDINAL; fn: BitBlt.DstFunc _ (IF MyRandom[XorRatio]=0 THEN xor ELSE null); SetGray[MyRandom[256]]; IF sym THEN { ty _ ty2 _ MyRandom[screenY/2]; lx _ MyRandom[screenX/2]; w _ MyRandom[screenX/2-lx]; h _ MyRandom[screenY/2-ty]; Rectangle[lx, ty, lx+w, ty+h, fn]; ty _ screenY/2+(screenY/2-ty)-h; Rectangle[lx, ty, lx+w, ty+h, fn]; lx _ screenX/2+(screenX/2-lx)-w; Rectangle[lx, ty, lx+w, ty+h, fn]; Rectangle[lx, ty2, lx+w, ty2+h, fn]; } ELSE { ty _ MyRandom[screenY]; lx _ MyRandom[screenX]; w _ MyRandom[screenX-lx]; h _ MyRandom[screenY-ty]; Rectangle[lx, ty, lx+w, ty+h, fn]; }; IF bitmapB#NIL THEN { ty _ MyRandom[screenY]; lx _ MyRandom[screenX]; w _ MyRandom[screenX-lx]; h _ MyRandom[screenY-ty]; BRectangle[lx, ty, lx+w, ty+h]; }; IF ckViewer.state.slow THEN Wait[200]; -- slow mode }; ShowConverge: PROCEDURE = { black: [0..8] = 1; --testmap[1] is black white: [0..8] = 8; --testmap[8] is white hThick: CARDINAL _ height/300; hStep: CARDINAL _ height/30; vThick: CARDINAL _ height/300; vStep: CARDINAL _ height/30; IF NOT full THEN { FOR i: CARDINAL IN[0..9) DO ColorDisplay.SetColor[pixelA: i, r: testmap[i].r, g: testmap[i].g, b: testmap[i].b]; ENDLOOP; ColorDisplay.Show[TRUE,FALSE,FALSE]; }; Rect[0,0,width,height,black]; --black background FOR xx: CARDINAL _ 0, xx+hStep UNTIL xx > width DO Rect[xx, 0, vThick, height, white]; ENDLOOP; FOR v: CARDINAL _ 0, v+vStep UNTIL v > height DO Rect[0, v, width, hThick ,white]; ENDLOOP; }; ShowBigRed,ShowSmallRed: PROCEDURE [] = { MW.Append[message: "RedScreen NOT IMPLEMENTED !!", clearFirst: TRUE]; MW.Blink[]; }; ShowBigGreen,ShowSmallGreen: PROCEDURE [] = { MW.Append[message: "GreenScreen NOT IMPLEMENTED !!", clearFirst: TRUE]; MW.Blink[]; }; ShowBigBlue,ShowSmallBlue: PROCEDURE [] = { MW.Append[message: "BlueScreen NOT IMPLEMENTED !!", clearFirst: TRUE]; MW.Blink[]; }; ShowCBars: PROCEDURE [] = { MW.Append[message: "ShowCBars NOT IMPLEMENTED !!", clearFirst: TRUE]; MW.Blink[]; }; NextRoll: PROCEDURE [] = { r,g,b,r0,g0,b0: [0..256); [r0,g0,b0] _ ColorDisplay.GetColor[0]; FOR i: CARDINAL IN[0..255) DO [r,g,b] _ ColorDisplay.GetColor[i+1]; ColorDisplay.SetColor[i,0,r,g,b]; ENDLOOP; ColorDisplay.SetColor[255,0,r0,g0,b0]; Wait[100]; }; NextScramble: PROCEDURE [] = { SetUpColors; Wait[200]; }; SetBackground: PROCEDURE [v: INTEGER] = BEGIN background _ v; ColorDisplay.SetColor[0, 0, v, v, v]; END; background: INTEGER _ 255; -- initially white ClearScreen: PROCEDURE = { IF NOT full THEN { ColorDisplay.SetColor[0, 0, background, background, background]; SetGray[0] }; Rectangle[0,0,width,height]; }; Wait: PROCEDURE[millisecs: CARDINAL] = INLINE { Process.Pause[Process.MsecToTicks[millisecs]] }; <> defaultSeed: CARDINAL = 27183; numCalls: INTEGER = 3; <> a: ARRAY [0..55] OF CARDINAL; <> <> p: INTEGER [0..55]; <> <> InitRandom: PUBLIC PROC[seed: INTEGER] RETURNS[INTEGER] = { <> <> <0, seed is scaled if necessary and then used; if seed<0, a seed>> <> <<(after scaling) is the integer value returned.>> minSeed: CARDINAL = LAST[CARDINAL]/10; g, gPrev, gSave: CARDINAL; IF seed<=0 THEN seed _ defaultSeed; <> WHILE seed> <> <<(-1)**(i-1) * (F(i) - seed*F(i-1)) MOD maxRand, 0> <<(where F(i) denotes the i-th Fibonacci number) throughout the rest of a. Then>> <> <> a[55] _ gPrev _ seed; g _ 1; FOR i: INTEGER IN [1..54] DO p _ (21*i) MOD 55; a[p] _ gSave _ g; g _ gPrev-g; gPrev _ gSave; ENDLOOP; THROUGH [1..numCalls) DO RandomGen[]; ENDLOOP; <> p _ 1; RETURN[seed] };--InitRandom Random: PUBLIC PROC RETURNS[CARDINAL] = INLINE { p _ p-1; IF p=0 THEN { RandomGen[]; p _ 55 }; RETURN[a[p]] };--Random RandomGen: PROC = INLINE { <> <> <> FOR i: INTEGER IN [1..24] DO a[i] _ a[i] - a[i+31]; ENDLOOP; FOR i: INTEGER IN [25..55] DO a[i] _ a[i] - a[i-24]; ENDLOOP; };--RandomGen Choose: PUBLIC PROC[min, max: CARDINAL] RETURNS[CARDINAL--[min..max]--] = { intervalLen: CARDINAL; IF min > max THEN ERROR; intervalLen _ max - min + 1; --is 0 when min=0, max=LAST[CARDINAL] IF intervalLen = 0 THEN RETURN[Random[]]; DO <> <<"odd interval" at the high end of this range (there is no odd interval if intervalLen>> <> <> r, rem: CARDINAL; <> p _ p-1; IF p=0 THEN { RandomGen[]; p _ 55 }; r _ a[p]; rem _ r MOD intervalLen; IF (r - rem) > LOOPHOLE[-LOOPHOLE[intervalLen,INTEGER],CARDINAL] THEN LOOP; RETURN[min + rem]; ENDLOOP; };--Choose SetLogBitsPerPixel: PROC[n: [0..4)] RETURNS[BOOLEAN] = { b: CARDINAL _ Inline.BITSHIFT[1,n]; mode: ColorDisplay.Mode _ [FALSE,b,1]; IF NOT ColorDisplay.HasMode[mode] THEN { mode.bitsPerPixelB _ 0; IF NOT ColorDisplay.HasMode[mode] THEN RETURN[FALSE]; }; IF NOT ColorDisplay.SetMode[mode] THEN ERROR; lbpp _ n; bpp _ b; full _ FALSE; lbppB _ 0; bppB _ 1; ashow _ bshow _ TRUE; width _ ColorDisplay.width; height _ ColorDisplay.height; bitmap _ ColorDisplay.baseA; wpl _ ColorDisplay.wplA; bitmapB _ ColorDisplay.baseB; wplB _ ColorDisplay.wplB; ClearScreen; SetUpColors; ColorDisplay.TurnOn[]; RETURN[TRUE]; }; Set24BitsPerPixel: PROC = { mode: ColorDisplay.Mode _ [TRUE,0,0]; IF NOT ColorDisplay.HasMode[mode] THEN RETURN; IF NOT ColorDisplay.SetMode[mode] THEN ERROR; lbpp _ 0; bpp _ 0; full _ TRUE; bitmap _ NIL; bitmapB _ NIL; wpl _ 0; ashow _ bshow _ TRUE; width _ ColorDisplay.width; height _ ColorDisplay.height; IF test THEN { ShowTPat[]; test _ FALSE } ELSE ClearScreen; ColorDisplay.TurnOn[]; }; Go: PUBLIC PROC [ckViewer: CKViewer] = { [] _ InitRandom[0]; SELECT TRUE FROM SetLogBitsPerPixel[3] => NULL; SetLogBitsPerPixel[2] => NULL; ENDCASE => { MW.Append[message: "NO COLOR DISPLAY !!", clearFirst: TRUE]; MW.Blink[]; RETURN; }; DO IF ckViewer.state.quit THEN { ClearScreen; ViewerOps.DestroyViewer[ckViewer.container]; []_ColorDisplay.SetMode[ColorDisplay.disconnected]; EXIT; }; IF ckViewer.state.bpp=1 AND bpp#1 THEN { [] _ SetLogBitsPerPixel[0]; IF NOT splat THEN test _ TRUE }; IF ckViewer.state.bpp=2 AND bpp#2 THEN { [] _ SetLogBitsPerPixel[1]; IF NOT splat THEN test _ TRUE }; IF ckViewer.state.bpp=4 AND bpp#4 THEN { [] _ SetLogBitsPerPixel[2]; IF NOT splat THEN test _ TRUE }; IF ckViewer.state.bpp=8 AND bpp#8 THEN { [] _ SetLogBitsPerPixel[3]; IF NOT splat THEN test _ TRUE }; IF ckViewer.state.bpp=24 AND NOT full THEN { Set24BitsPerPixel[]; IF NOT splat THEN test _ TRUE }; IF ckViewer.state.aToggle THEN { ashow _ NOT ashow; ColorDisplay.Show[ashow,bshow,TRUE]; ckViewer.state.aToggle _ FALSE}; IF ckViewer.state.bToggle THEN { bshow _ NOT bshow; ColorDisplay.Show[ashow,bshow,TRUE]; ckViewer.state.bToggle _ FALSE}; IF ckViewer.state.random THEN { sym _ FALSE; splat _ TRUE; ClearScreen[]; ckViewer.state.random _ FALSE}; IF ckViewer.state.symmetric THEN { sym _ TRUE; splat _ TRUE; ClearScreen[]; ckViewer.state.symmetric _ FALSE}; IF NOT ckViewer.state.freeze THEN { ckViewer.state.roll _ ckViewer.state.scramble _ FALSE; --only TRUE when frozen SELECT TRUE FROM test OR ckViewer.state.testPattern => { test _ TRUE; splat _ FALSE; ShowTPat[]; test _ ckViewer.state.testPattern _ FALSE; }; ckViewer.state.cbars => {ShowCBars[]; splat _ ckViewer.state.cbars _ FALSE}; ckViewer.state.converge => {ShowConverge[]; splat _ ckViewer.state.converge _ FALSE}; ckViewer.state.bigRed => {ShowBigRed[]; splat _ ckViewer.state.bigRed _ FALSE}; ckViewer.state.bigGreen => {ShowBigGreen[]; splat _ ckViewer.state.bigGreen _ FALSE}; ckViewer.state.bigBlue => {ShowBigBlue[]; splat _ ckViewer.state.bigBlue _ FALSE}; ckViewer.state.smallRed => {ShowSmallRed[]; splat _ ckViewer.state.smallRed _ FALSE}; ckViewer.state.smallGreen => {ShowSmallGreen[]; splat _ ckViewer.state.smallGreen _ FALSE}; ckViewer.state.smallBlue => {ShowSmallBlue[]; splat _ ckViewer.state.smallBlue _ FALSE}; ENDCASE => IF splat THEN {ColorDisplay.Show[ashow,bshow,TRUE]; RandomSplat[ckViewer]; }; } ELSE { SELECT TRUE FROM ckViewer.state.scramble => NextScramble[]; ckViewer.state.roll => NextRoll[]; ENDCASE => NULL; }; ENDLOOP; IF NOT ColorDisplay.SetMode[ColorDisplay.disconnected] THEN ERROR; }; END.