csc@watmath.UUCP (Jan Gray) (09/12/86)
This silly desk accessory turns your ST screen upside down. It was mainly a "see if it can be done" experiment which I thought you might enjoy. It allocates memory for another screen, moves the hardware screen there, and repeatedly flips the "logical" screen onto the new screen. Unfortunately I couldn't coerce the 68000 to take less than 120 ms per flip, so leaving the ST some computing cycles you get about a 4 Hz update rate. Following are the C sources (which work with the new Alcyon C release) and a uuencoded binary. Unpack it, uudecode it, upload it and install it as ud.acc. It's cute, but you'll tire of it quickly, believe me. Jan Gray University of Waterloo but doing a workterm at Northern Software (519) 885-5921 ud.c: ----------------------------- /* * Upside-down DA...a somewhat disappointing experiment * * Jan Gray 1986 * * link: accstart,ud,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! */ 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(); 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 */ Phys = FlipScreen; Supexec(setPhysBase); refreshFlip(); /* * Wait for accessory open message or 130 ms timeout. * 130 ms should give roughly 50% duty cycle. */ 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, 130, 0, &ret, &ret, &ret, &ret, &ret, &ret); if (event & MU_TIMER) refreshFlip(); } while (!((event & MU_MESAG) && msg[0] == AC_OPEN && msg[4] == 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); } #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); } /* * Copy the flip of the real screen to FlipScreen. Scans the real screen * from last byte to first, writing to the flip screen from first byte * to last. */ refreshFlip() { register /* a5 */ Byte *real = RealScreen + SCR_BYTES; register /* a4 */ Byte *flip = FlipScreen; register /* a3 */ Byte *rev = RevBytes; register int count = SCR_BYTES/8; /* * Copy bytes of the real screen to the flip screen, through * the byte reverse table. Unrolled 8 times for speed. * * Written in assembler (probably not optimal assembler...) * because Alcyon C 4.14 generates really really stupid code * (like "andi #$ff, d0" followed by "andi.l #$ff, d0"). Oh, God. * * Expected time: 4 us/byte * 32000 bytes = 130 ms */ while (count-- > 0) { #ifdef STUPID_ALCYON_C #define COPY *flip++ = rev[*--real]; #else asm("moveq #0,d0"); /* clear upper byte of d0.w */ #define COPY asm("move.b -(a5),d0"); /* 10->12 cycles == 1.5 us */\ asm("move.b 0(a3,d0.w),(a4)+"); /* 18->20 cycles == 2.5 us */ #endif COPY COPY COPY COPY COPY COPY COPY COPY } } /* Writing strcpy here saves us from linking with gemlib */ strcpy(dst, src) register char *dst; register char *src; { while (*dst++ = *src++) ; } -------------------------- ud.acc.uue: -------------------------- begin 644 ud.acc M8!H 40 !>@ !98 "Y\ *CDZY ("Z\ M $Y!(B\ !# \ ,A.0DYU3E;_TDZY #4DZY !M#Z\ ).N0 !. CP M"K(NO ?P _/ !(3KD 4 5(_0O ?_ O/___@ CP "M1"+O_L+HX& ME____^P_.0 #!).N0 !+Y4CSU _^HNO !FPO#@:7____[$ZY "QEB/ M+HX&E____]A.N0 \8]0/_H#&X */_89N8P+O_@L&[_ZF;<(_D K4 * MEBZ\ "+#\\ "9.N0 !.!4CTZY "6BZ\ &>B\.!I?____L3KD +& M6(\NC@:7____UB\.!I?____6+PX&E____]8O#@:7____UB\.!I?____6+PX& ME____]9"9S\\ ((O#@:7____V$)G0F="9T)G0F="9T)G0F="9T)G0F="9T)G M/SP ,$ZY #X-_\ .#U _^@(+@ %_^EG (3KD ):""X !/_I9P#_ M? QN "C_V&8 _W(P+O_@L&[_ZF8 _V8C^0 "K( J6+KP (L/SP )DZY M $X%2/8 #^U$Y>3G5.5@ 2.<# $)'8 7# 'P'P >] ,@?"? "ZT& M03('PGP !.=!@$$R!\)\ CC08!!,@?"? 0XD& 03('PGP (.9!@$$R!\)\ M $#J08!!,@?"? " [D& 03)'T_P K8$H!21[Y\ 0!MH$J?3-\ @$Y>3G5. M5O_\(#D J6<A#BJ,!\ /\3P #_@@$@.0 "I;@B,!\ /\3P #_@@-.7DYU M3E8 $CG QPJ>0 "K+;_ ?0 H>0 "M0F? "M@^/ ^@8 -' $"48 M\P $"48\P $"48\P $"48\P $"48\P $"48\P $"48\P $"48\P M, =31TI ;L9*GTS?.(!.7DYU3E8 $CG 0PJ;@ (*&X #& (:W&;\2I], MWS 3EY.=4Y6__8S[@ ( +V# N C0?/_VP?P TC T+P 40+4#_^CU\ M '__F >(&[_^A 02( R;O_^T\G3_ "]@R@%*N__I2;O_^#&X !/_^;=HN MN0 # Y.N0 !1"0# Y , $Y>3G5.5O_Z(_P O8 *FB/\ *M@ M"IXC_ "^ JB(_P P *IB/\ ,% "JHC_ #!P JN(_P M J: ,#CZ\ IA /]&,_D P ,$G !3EY.=4Y6__P^O 380#_*G ! M3EY.=4Y6__PC[@ ( ,%#Z\ !=.N0 NA.7DYU3E;__#/N @ O@,^X M"@ "^(S[@ , +Y#/N X OF,^X $ "^@S[@ 2 +ZC/N !0 OL M,^X %@ "^XS[@ 8 +\#/N !H OR,^X ' "_0S[@ > +]C/N " M OX,^X (@ "_HC[@ D ,%#/N "@ O\,^X *@ "_X^O 93KD +H M(&X +#"Y , B!N # PN0 # 0@;@ T,+D P&(&X .#"Y ,""!N #PP MN0 # H@;@! ,+D P,0D P.0 # !.7DYU3E;__#/N @ O@(^X "@ M#!0^O C3KD +H3EY.=2/? *DDY.+SD J23G4CWP "I).32\Y * MDDYU(]\ J23D$O.0 "I).=0 ! (! 0(! 0 ! 0(! 0$! 0 M ! ! ,% 4% ! 0(! ! ' 0(! $! 0(! 0(! 0(! M 0$! @$! 0 (! 0$! 08! 00! 0$# 0(! 00" 0@! 0 M $! 0D! 0$! 0$! % 0 M 0# @# 8! @! @! 0! 0,! 0 % $! M 0 % ! 0 ! 0 " @ M 4! 4! $! $! (% 8! (! $! 8% M ! 0 ! (! (! 0$! 0 ! @,! @$! 0$! M 0 ! 0 ! B @57!S:61E+61O=VX ("!2:6=H='-I9&4M=7 (&'@8* M!A 4$@8,#A <! 8*" 8.9!HF! 8*;AX4'@P&>A0@& 8(#@0&! 8$!@0&! 8$ I!@0.!"0*$ @(" @(" @(" @(" @(" @*"@H*"@H*"! ("@H(" @(" & end
jhs@mitre-bedford.ARPA (09/13/86)
Heck, if all you want to do is turn a screen upside down, buy an Atari 800xl. All you have to do there is write one number to one memory location and the screen turns upside down! (:^/) -jhs