csc@watmath.UUCP (Jan Gray) (09/16/86)
Just when you thought it was safe to turn your monitor rightside-up... Here are the sources and uuencoded binary to a new version of my silly upside down desk accessory. This one refreshes the screen at more than 10 Hz when there is little change between refreshes. It keeps checksums on 32 byte blocks of the screen and reverses the changed blocks. I promise not to post any more of these. Honest. What do you mean, pointless? Jan Gray ud.c: ------------------ /* * Upside-down DA, v.2 ...a somewhat less disappointing experiment * * Jan Gray 1986 * * link: accstart,ud,flip,aesbind,osbind */ #include "gemdefs.h" #include "osbind.h" #define NULL 0 #define SCR_BYTES 32000L #define SCR_ALIGN 512L /* must page align screen */ #define Supexec(code) xbios(38, code) typedef unsigned char Byte; /* must be unsigned! */ long Chksums[32000/32]; Byte RevBytes[256]; Byte *RealScreen; /* real screen address */ Byte *FlipScreen; /* flipped screen address */ Byte *Phys; /* passed to setPhysBase() */ setPhysBase(); main() { extern int gl_apid; char menuName[20]; int menuID; int event; int msg[8]; int ret; appl_init(); buildRevBytes(); zapChksums(); RealScreen = Physbase(); FlipScreen = (Byte *)((Malloc(SCR_BYTES + SCR_ALIGN) + (SCR_ALIGN-1)) & ~(SCR_ALIGN-1)); menuName[0] = NULL; menuID = menu_register(gl_apid, menuName); for (;;) { /* Wait for accessory open message */ strcpy(menuName, " Upside-down"); do { event = evnt_mesag(msg); } while (!(msg[0] == AC_OPEN && msg[4] == menuID)); /* Flip screen */ refreshFlip(); Phys = FlipScreen; Supexec(setPhysBase); /* * Wait for accessory open or close message or 50 ms timeout. */ strcpy(menuName, " Rightside-up"); do { event = evnt_multi(MU_MESAG | MU_TIMER, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, msg, 50, 0, &ret, &ret, &ret, &ret, &ret, &ret); if (event & MU_TIMER) refreshFlip(); /* 20 to 150 ms */ } while (!((event & MU_MESAG) && (msg[0] == AC_OPEN && msg[4] == menuID || msg[0] == AC_CLOSE && msg[3] == menuID))); /* Restore screen */ Phys = RealScreen; Supexec(setPhysBase); } } buildRevBytes() /* Build the byte reversal table */ { register int i; for (i = 0; i < 256; i++) RevBytes[i] = ((i & 1) << 7) | ((i & 2) << 5) | ((i & 4) << 3) | ((i & 8) << 1) | ((i & 0x10) >> 1) | ((i & 0x20) >> 3) | ((i & 0x40) >> 5) | ((i & 0x80) >> 7); } zapChksums() /* Initialize the checksums to ff's */ { register long *p; register long ffffffff = 0xffffffffL; for (p = Chksums; p < &Chksums[32000/32]; ) { *p++ = ffffffff; *p++ = ffffffff; *p++ = ffffffff; *p++ = ffffffff; } } #define VBASE_HIGH (Byte *)0xff8201L #define VBASE_LOW (Byte *)0xff8203L /* * setPhysBase -- set the physical screen to Phys. I don't use Setscreen() * because it seems to clear the old logical screen...I don't want the * ST to know that anything funny is going on, just to go merrily on its * way writing to what it thinks is the physical screen... */ setPhysBase() { *VBASE_HIGH = (Byte)((unsigned long)Phys >> 16); *VBASE_LOW = (Byte)((unsigned long)Phys >> 8); } /* Writing strcpy here saves us from linking with gemlib */ strcpy(dst, src) register char *dst; register char *src; { while (*dst++ = *src++) ; } ---------------------- flip.s: ---------------------- * * flip.s * * Assembler _refreshFlip. * * Reverse the real screen onto the flip screen. Rather than reversing * every byte every time called (which is slow -- about 120 ms per call), * we reverse only those bytes which have changed since the last call. * * Instead of saving yet another copy of the screen, we keep a longword * checksum for each block of 32 bytes. If a new checksum differs, we save * it away and reverse that 32 byte block. * * Since the screen changes little between calls, this is a big win, reducing * the average time spent here from about 120 to 20 ms per call. * * * Registers used * a5 - real screen * a4 - flip screen start * a3 - flip screen * a2 - reverse table * a1 - checksum table * a0 - constant 32 * d7-d0 - scratch .globl _RealScreen .globl _FlipScreen .globl _RevBytes .globl _Chksums .text .globl _refreshFlip _refreshFlip: link a6,#0 movem.l d0-d7/a0-a5,-(sp) move.l _RealScreen,a5 move.l _FlipScreen,a4 move.l a4,a3 add.l #32000,a3 * a3 = end of FlipScreen move.l #_RevBytes,a2 move.l #_Chksums,a1 move.l #32,a0 loop: movem.l (a5)+,d0-d7 * fetch 32 bytes add.l d1,d0 * compute new checksum add.l d2,d0 add.l d3,d0 add.l d4,d0 add.l d5,d0 add.l d6,d0 add.l d7,d0 cmp.l (a1)+,d0 * compare against old checksum bne rev * reverse line if different sub.l a0,a3 * skip 32 bytes on flip screen loop1: cmp.l a4,a3 * done? bcc loop movem.l (sp)+,d0-d7/a0-a5 unlk a6 rts rev: move.l d0,-4(a1) * differs; save new checksum sub.l a0,a5 * adjust a5 to front of 32 bytes moveq.l #0,d0 * load upper byte with 0 move.b (a5)+,d0 * copy real byte through byte- move.b 0(a2,d0.w),-(a3) * reversal table to flip screen move.b (a5)+,d0 * likewise for 31 bytes move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) move.b (a5)+,d0 move.b 0(a2,d0.w),-(a3) bra loop1 * continue ----------------- ud.acc.uue: ----------------- begin 644 ud.acc M8!H 8. !>@ %38 "Y\ +C$ZY ("Z\ M $Y!(B\ !# \ ,A.0DYU3E;_TDZY $4$ZY !T$ZY "2#Z\ ).N0 M!=XCP "[ NO ?P _/ !(3KD 7^5(_0O ?_ O/___@ CP "])" M+O_L+HX&E____^P_.0 #1!.N0 !;Q4CSU _^HNO !VHO#@:7____[$ZY M "I%B/+HX&E____]A.N0 !,0]0/_H#&X */_89N8P+O_@L&[_ZF;<3KD M +&(_D O2 +E"Z\ "=C\\ "9.N0 !=Y4CRZ\ '>"\.!I?____L M3KD *D6(\NC@:7____UB\.!I?____6+PX&E____]8O#@:7____UB\.!I?_ M___6+PX&E____]9"9S\\ #(O#@:7____V$)G0F="9T)G0F="9T)G0F="9T)G M0F="9T)G/SP ,$ZY $WM_\ .#U _^@(+@ %_^EG (3KD +&""X M!/_I9P#_? QN "C_V&8 XP+O_@L&[_ZF< !@,;@ I_]AF /]<,"[_WK!N M_^IF /]0(_D NP +E"Z\ "=C\\ "9.N0 !=Y4CV _KY.7DYU3E8 M $CG P!"1V %PP!\!\ 'O0#('PGP NM!@$$R!\)\ 3G08!!,@?"? ( MXT& 03('PGP $.)!@$$R!\)\ "#F08!!,@?"? ! ZD& 03('PGP @.Y!@$$R M1]/\ +UA* 4D>^? $ ;:!*GTS? (!.7DYU3E8 $CG P1^_RI\ -&F M HJQRK'*L<JQ[O\ <NF7P2I],WR" 3EY.=4Y6__P@.0 "Y1R$.*HP'P M_Q/ /^" 2 Y +E."(P'P _Q/ /^" TY>3G5.5@ 2.<!#"IN @H;@ , M8 AK<9OQ*GTS?, !.7DYU3E8 $CG__PJ>0 "[ H>0 "](F3-?\ !] M "1\ +UB)\ -&B!\ ($S= /_0@=""T(/0A-"%T(;0A["99@ $)?( MM\QDXDS?/_].7DYU(T#__)O(< 0'1<R 0'1<R 0'1<R 0'1<R 0 M'1<R 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R M 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R 0 M'1<R 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R M 0'1<R 0'1<R 0'1<R 0'1<R 0'1<R !@ /\J3E;_]C/N @ M S6,"X "-!\__;!_ #2,#0O !@XM0/_Z/7P ?_^8!X@;O_Z$!!(@#)N M__[3R=/\ ,UC* 4J[_^E)N__X,;@ $__YMVBZY -#$ZY %$) ,#D M S^3EY.=4Y6__HC_ #-8 N8(_P NT +G"/\ ,W@ "Z C_ M#/X ND(_P T2 +J"/\ <N@ "ZPC_ "Y@ T,/KP "F$ _T8S M^0 #/X T0< %.7DYU3E;__#Z\ !-A /\J< %.7DYU3E;__"/N @ T2 M/KP %TZY #YDY>3G5.5O_\,^X " #-XS[@ * ,X#/N P SB,^X M#@ #.0S[@ 0 ,YC/N !( SH,^X % #.HS[@ 6 ,[#/N !@ SN M,^X &@ #/ S[@ < ,\C/N !X ST,^X ( #/8S[@ B ,^"/N "0 M T2,^X * #/HS[@ J ,_#Z\ !E.N0 ^8@;@ L,+D T (&X ,#"Y M - B!N #0PN0 #00@;@ X,+D T&(&X /#"Y -""!N $ PN0 #0I" M0# Y ,_DY>3G5.5O_\,^X " #-XC[@ * -$CZ\ "-.N0 ^9.7DYU M(]\ N03DXO.0 "Y!.=2/? +D$Y-+SD N03G4CWP "Y!.02\Y + MD$YU $ @$! @$! $! @$! 0$! $ $ P4 !04 $! M @$ $ <! @$ 0$! @$! @$! @$! 0$" 0$! M @$! 0$!!@$!! $! 0,! @$!! (!" $! 0$!"0$! 0$! 0$ M 4! M ! , " , !@$ " $ " $ ! $! P$! 4 0$! 4 $! $! M (" M !0$ !0$ 0$ 0$ @4 !@$ @$ 0$ !@4 $! $ @$ @$! M 0$! $" P$" 0$! 0$! $! $"("!5<'-I9&4M M9&]W;@ @(%)I9VAT<VED92UU< @8>!@8*!A 4$@8,#A <!@0&"@@. M9!H\! 8*;B02%A1 !@X& 084(!@&" X$!@0&! 8$!@0&! 8$#@0D"A (" @( >" @(" @(" @(" @("@H*"@H*"@@0" H*" @(" @ end