home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 63 / applic / upsidedn.c < prev   
Encoding:
C/C++ Source or Header  |  1986-10-16  |  3.7 KB  |  151 lines

  1. /*
  2.  * Upside-down DA...a somewhat disappointing experiment
  3.  *
  4.  * Jan Gray 1986
  5.  *
  6.  * link: accstart,ud,aesbind,osbind
  7.  */
  8.  
  9. #include "gemdefs.h"
  10. #include "osbind.h"
  11.  
  12. #define    NULL        0
  13. #define    SCR_BYTES    32000L
  14. #define    SCR_ALIGN    512L            /* must page align screen */
  15. #define    Supexec(code)    xbios(38, code)
  16.  
  17. typedef unsigned char    Byte;            /* must be unsigned! */
  18.  
  19. Byte    RevBytes[256];
  20.  
  21. Byte    *RealScreen;                /* real screen address */
  22. Byte    *FlipScreen;                /* flipped screen address */
  23. Byte    *Phys;                    /* passed to setPhysBase() */
  24.  
  25. setPhysBase();
  26.  
  27. main()
  28. {
  29.     extern int    gl_apid;
  30.     char    menuName[20];
  31.     int    menuID;
  32.     int    event;
  33.     int    msg[8];
  34.     int    ret;
  35.  
  36.     appl_init();
  37.  
  38.     buildRevBytes();
  39.  
  40.     RealScreen = Physbase();
  41.     FlipScreen = (Byte *)((Malloc(SCR_BYTES + SCR_ALIGN) + (SCR_ALIGN-1))
  42.                 & ~(SCR_ALIGN-1));
  43.  
  44.     menuName[0] = NULL;
  45.     menuID = menu_register(gl_apid,  menuName);
  46.  
  47.     for (;;) {
  48.         /* Wait for accessory open message */
  49.         strcpy(menuName, "  Upside-down");
  50.         do {
  51.             event = evnt_mesag(msg);
  52.         } while (!(msg[0] == AC_OPEN && msg[4] == menuID));
  53.  
  54.         /* Flip screen */
  55.         Phys = FlipScreen;
  56.         Supexec(setPhysBase);
  57.         refreshFlip();
  58.             
  59.         /*
  60.          * Wait for accessory open message or 130 ms timeout.
  61.          * 130 ms should give roughly 50% duty cycle.
  62.          */
  63.         strcpy(menuName, "  Rightside-up");
  64.         do {
  65.             event = evnt_multi(MU_MESAG | MU_TIMER,
  66.                        0, 0, 0,
  67.                        0, 0, 0, 0, 0,
  68.                        0, 0, 0, 0, 0,
  69.                        msg, 130, 0,
  70.                         &ret, &ret, &ret, &ret, &ret, &ret);
  71.             if (event & MU_TIMER)
  72.                 refreshFlip();
  73.         } while (!((event & MU_MESAG) &&
  74.                msg[0] == AC_OPEN && msg[4] == menuID));
  75.  
  76.         /* Restore screen */
  77.         Phys = RealScreen;
  78.         Supexec(setPhysBase);
  79.     }
  80. }
  81.  
  82. buildRevBytes()                /* Build the byte reversal table */
  83. {
  84.     register int    i;
  85.  
  86.     for (i = 0; i < 256; i++)
  87.         RevBytes[i] =    ((i & 1) << 7) | ((i & 2) << 5) |
  88.                 ((i & 4) << 3) | ((i & 8) << 1) |
  89.                 ((i & 0x10) >> 1) | ((i & 0x20) >> 3) |
  90.                 ((i & 0x40) >> 5) | ((i & 0x80) >> 7);
  91. }
  92.  
  93. #define    VBASE_HIGH    (Byte *)0xff8201L
  94. #define    VBASE_LOW    (Byte *)0xff8203L
  95. /*
  96.  * setPhysBase -- set the physical screen to Phys.  I don't use Setscreen()
  97.  * because it seems to clear the old logical screen...I don't want the
  98.  * ST to know that anything funny is going on, just to go merrily on its
  99.  * way writing to what it thinks is the physical screen...
  100.  */
  101. setPhysBase()
  102. {
  103.     *VBASE_HIGH = (Byte)((unsigned long)Phys >> 16);
  104.     *VBASE_LOW  = (Byte)((unsigned long)Phys >> 8);
  105. }
  106.  
  107. /*
  108.  * Copy the flip of the real screen to FlipScreen.  Scans the real screen
  109.  * from last byte to first, writing to the flip screen from first byte
  110.  * to last.
  111.  */
  112. refreshFlip()
  113. {
  114.     register /* a5 */ Byte    *real    = RealScreen + SCR_BYTES;
  115.     register /* a4 */ Byte    *flip    = FlipScreen;
  116.     register /* a3 */ Byte    *rev    = RevBytes;
  117.     register int        count    = SCR_BYTES/8;
  118.  
  119.     /*
  120.      * Copy bytes of the real screen to the flip screen, through
  121.      * the byte reverse table.  Unrolled 8 times for speed.
  122.      *
  123.      * Written in assembler (probably not optimal assembler...)
  124.      * because Alcyon C 4.14 generates really really stupid code
  125.      * (like "andi #$ff, d0" followed by "andi.l #$ff, d0").  Oh, God.
  126.      *
  127.      * Expected time: 4 us/byte * 32000 bytes = 130 ms
  128.      */
  129.     while (count-- > 0) {
  130. #ifdef STUPID_ALCYON_C
  131. #define    COPY    *flip++ = rev[*--real];
  132. #else
  133.         asm("moveq #0,d0");        /* clear upper byte of d0.w */
  134.  
  135. #define    COPY    asm("move.b -(a5),d0");        /* 10->12 cycles == 1.5 us */\
  136.         asm("move.b 0(a3,d0.w),(a4)+");    /* 18->20 cycles == 2.5 us */
  137. #endif
  138.  
  139.         COPY COPY COPY COPY COPY COPY COPY COPY
  140.     }
  141. }
  142.  
  143. /* Writing strcpy here saves us from linking with gemlib */
  144. strcpy(dst, src)
  145. register char    *dst;
  146. register char    *src;
  147. {
  148.     while (*dst++ = *src++)
  149.         ;
  150. }
  151.