home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’93 / Wavy / Experiments / staticMap / staticMap.c next >
Encoding:
C/C++ Source or Header  |  1993-06-17  |  8.9 KB  |  356 lines  |  [TEXT/KAHL]

  1. /*
  2.     Test mappings
  3. */
  4.  
  5. #include <QDOffscreen.h>
  6. #include <FixMath.h>
  7.  
  8. #define pictID    128
  9. #define    kFrameCount 16
  10.  
  11. void MapCoordinates(short width, short height, short x, short y, short *resultX, short *resultY)
  12. #define cycleSize    (16)
  13. {
  14. #define HorizontalSineWave 0
  15. #define VerticalSineWave 1
  16. #define Mirror 0
  17.  
  18. #if Mirror
  19.     *resultX = width - x;
  20.     *resultY = y;
  21. #endif
  22.  
  23. #if HorizontalSineWave
  24.     *resultX = x + (2*Frac2Fix(FracSin(y*205887/cycleSize))+32768)/65536;
  25.     *resultY = y;
  26. #endif
  27.  
  28. #if VerticalSineWave
  29.     *resultX = x;
  30.     *resultY = y + (2*Frac2Fix(FracSin(x*205887/cycleSize))+32768)/65536;
  31. #endif
  32.  
  33.     while (*resultX < 0)
  34.         *resultX += width;
  35.     while (*resultY < 0)
  36.         *resultY += height;
  37.  
  38.     *resultX %= width;
  39.     *resultY %= height;
  40. }
  41.  
  42. /*
  43.     Generate the addresses for the mapping. 
  44. */
  45.  
  46. void
  47. GenerateMappingTable(long    *mappingTable, short width, short height, short rowBytes, short frameNumber)
  48. {
  49.     long    *offsetHere;
  50.     short    x, y;
  51.     
  52.     offsetHere = mappingTable;
  53.  
  54.     for (y = 0; y < height; ++y) {
  55.         for (x = 0; x < width; ++x)
  56.             {
  57.             short    destinationX, destinationY;
  58.  
  59.             MapCoordinates(width, height, x, y, &destinationX, &destinationY);
  60.             *offsetHere++ = (long)destinationY * rowBytes + destinationX;
  61.             }
  62.     }
  63. }
  64.  
  65. //
  66. // Blit the entire bitmap from source to dest
  67. //
  68.  
  69. void
  70. BlitThroughTable(char *sourceBase, char *destinationBase, short height, short width,
  71.             short rowBytes, long *mappingTable)
  72. {
  73.     short    x, y;
  74.     char    *sourceRow, *sourceByte;
  75.     long    *offsetHere;
  76.     
  77.     offsetHere = mappingTable;
  78.     
  79.     for (y = 0; y < height; ++y)
  80.         {
  81.         sourceRow = sourceBase;
  82.         for (x = 0; x < width; ++x)
  83.             *(destinationBase + *offsetHere++) = *sourceRow++;
  84.         sourceBase += rowBytes;
  85.         }
  86. }
  87.     
  88. //
  89. // Blit the entire bitmap from source to dest using a technique similar to what
  90. // we'd like to compile.
  91. //
  92. //    Use 5 destination registers so we can use 16-bit constant offsets in instructions
  93. //    of the form:
  94. //
  95. //    move.b    (sourceRow)+, tableValue(destReg[0..4])
  96. //    
  97. //    
  98. // Some useful instructions
  99. // 00000000: 207C 1234 5678        MOVEA.L    #$12345678,A0
  100. // 00000006: 227C 1234 5678        MOVEA.L    #$12345678,A1
  101. // 0000000C: 247C 1234 5678        MOVEA.L    #$12345678,A2
  102. // 00000012: 267C 1234 5678        MOVEA.L    #$12345678,A3
  103. // 00000018: 287C 1234 5678        MOVEA.L    #$12345678,A4
  104. // 0000001E: 2A7C 1234 5678        MOVEA.L    #$12345678,A5
  105. //
  106. // 00000006: 115D 1234             MOVE.B     (A5)+,$1234(A0)
  107. // 0000000A: 135D 1234             MOVE.B     (A5)+,$1234(A1)
  108. // 0000000E: 155D 1234            MOVE.B     (A5)+,$1234(A2)
  109. // 00000012: 175D 1234             MOVE.B     (A5)+,$1234(A3)
  110. // 00000016: 195D 1234            MOVE.B     (A5)+,$1234(A4)
  111.  
  112. // 00000038: 48E7 00FC            MOVEM.L    A0-A5,-(A7)
  113. // 0000003C: 4CDF 3F00            MOVEM.L    (A7)+,A0-A5
  114.  
  115. // 00000040: 4E75                RTS        
  116.  
  117. #define movea_to_a0        0x207c
  118. #define movea_to_a1        0x227c
  119. #define movea_to_a2        0x247c
  120. #define movea_to_a3        0x267c
  121. #define movea_to_a4        0x287c
  122. #define    movea_to_a5        0x2a7c
  123.  
  124. #define    move_b_a5plus_a0    0x115d
  125. #define    move_b_a5plus_a1    0x135d
  126. #define    move_b_a5plus_a2    0x155d
  127. #define    move_b_a5plus_a3    0x175d
  128. #define    move_b_a5plus_a4    0x195d
  129.  
  130. #define movem_push_a0_a5    0x48e700fcL
  131. #define movem_pop_a0_a5        0x4cdf3f00L
  132.  
  133. #define rts                0x4e75
  134.  
  135. void
  136. WriteSomeCode(char *sourceBase, char *destinationBase, short height, short width,
  137.                 short rowBytes, long *mappingTable, short *theCode)
  138. {
  139.     short    i, x, y;
  140.     char    *sourceRow, *sourceByte;
  141.     long    *offsetHere;
  142.     
  143.     char    *destRegisters[5];
  144.     long    registerRange;            // how much of a bitmap chunk each register sees
  145.     long    rangeOffset;            // where in the chunk each register points
  146.     long    targetBitMapSize;
  147.  
  148.     targetBitMapSize = (long) height * (long) rowBytes;
  149.     registerRange = (targetBitMapSize + 20) / 5;
  150.     rangeOffset = (registerRange / 2) & ~3;
  151.     
  152.     for (i = 0; i < 5; i++)
  153.         destRegisters[i] = destinationBase + registerRange * i + rangeOffset;
  154.     
  155.     offsetHere = mappingTable;
  156.  
  157.     // save the registers we trash
  158.     *(*(long **) &theCode)++ = movem_push_a0_a5;
  159.     
  160.     // load the 4 registers
  161.     *(*(short **) &theCode)++ = movea_to_a0;
  162.     *(*(char ***) &theCode)++ = destRegisters[0];
  163.     *(*(short **) &theCode)++ = movea_to_a1;
  164.     *(*(char ***) &theCode)++ = destRegisters[1];
  165.     *(*(short **) &theCode)++ = movea_to_a2;
  166.     *(*(char ***) &theCode)++ = destRegisters[2];
  167.     *(*(short **) &theCode)++ = movea_to_a3;
  168.     *(*(char ***) &theCode)++ = destRegisters[3];
  169.     *(*(short **) &theCode)++ = movea_to_a4;
  170.     *(*(char ***) &theCode)++ = destRegisters[4];
  171.         
  172.     for (y = 0; y < height; ++y)
  173.         {
  174.         sourceRow = sourceBase;
  175.  
  176.         // load the row register
  177.         *(*(short **) &theCode)++ = movea_to_a5;
  178.         *(*(char ***) &theCode)++ = sourceRow;
  179.  
  180.         for (x = 0; x < width; ++x) {
  181.             char    *targetByte;
  182.             long    registerOffset;
  183.             
  184.             targetByte = destinationBase + *offsetHere++;
  185.             
  186.             for (i = 0; i < 5; i++) {
  187.                 registerOffset = targetByte - destRegisters[i];
  188.                 if (registerOffset >= -32768 && registerOffset < 32768) {
  189.                     switch(i) {
  190.                         case 0:
  191.                             *(*(short **) &theCode)++ = move_b_a5plus_a0;
  192.                             *(*(short **) &theCode)++ = registerOffset;
  193.                             break;
  194.                         case 1:
  195.                             *(*(short **) &theCode)++ = move_b_a5plus_a1;
  196.                             *(*(short **) &theCode)++ = registerOffset;
  197.                             break;
  198.                         case 2:
  199.                             *(*(short **) &theCode)++ = move_b_a5plus_a2;
  200.                             *(*(short **) &theCode)++ = registerOffset;
  201.                             break;
  202.                         case 3:
  203.                             *(*(short **) &theCode)++ = move_b_a5plus_a3;
  204.                             *(*(short **) &theCode)++ = registerOffset;
  205.                             break;
  206.                         case 4:
  207.                             *(*(short **) &theCode)++ = move_b_a5plus_a4;
  208.                             *(*(short **) &theCode)++ = registerOffset;
  209.                             break;
  210.                         default:
  211.                             Debugger();
  212.                             break;
  213.                     }                
  214.                     break;
  215.                 }
  216.             }
  217.         }
  218.         sourceBase += rowBytes;
  219.     }
  220.     *(*(long **) &theCode)++ = movem_pop_a0_a5;
  221.     *(*(short **) &theCode)++ = rts;
  222. }
  223.     
  224. void
  225. CompileTable(char *sourceBase, char *destinationBase, short height, short width,
  226.         short rowBytes, long *mappingTable)
  227. {
  228.     short    x, y;        
  229.     
  230.     char    *sourceRow;
  231.     
  232.     for (y = 0; y < height; ++y)
  233.         {
  234.         sourceRow = sourceBase;
  235.         for (x = 0; x < width; ++x)
  236.             *(destinationBase + *mappingTable++) = *sourceRow++;
  237.         sourceBase += rowBytes;
  238.         }
  239. }
  240.  
  241. long Microseconds() = 0xA093;
  242.  
  243. main()
  244. {
  245.     WindowPtr        sourceWindow, destinationWindow;
  246.     Rect            sourceRect, destRect;
  247.     Rect            frame;
  248.     PicHandle        picture;
  249.     GWorldPtr        sourceGWorld, destinationGWorld;
  250.     PixMapHandle    sourcePix, destinationPix;
  251.     GWorldPtr        savedGWorld;
  252.     GDHandle        savedGDevice;
  253.     short            height, width, rowBytes;
  254.     short            x, y;
  255.     long            *buffer1, *offsetHere;
  256.     char            *sourceBase, *destinationBase;
  257.     long            *mappingTable;
  258.     short            *theCode;
  259.     long            startTime, endTime;
  260.     GrafPtr            windowManagerPort;
  261.  
  262.  
  263. #define PICTURE 1
  264.  
  265.     SetRect(&frame, 0, 0, 640, 480);
  266. #ifdef PICTURE    
  267.     picture = GetPicture(pictID);
  268.     frame = (**picture).picFrame;
  269. #endif
  270.  
  271.     width = frame.right - frame.left;
  272.     height = frame.bottom - frame.top;
  273.  
  274. #ifdef PICTURE
  275.     SetRect(&sourceRect, 50, 50, width + 50, height + 50);
  276.     destRect = sourceRect;
  277.     OffsetRect(&destRect, 0, 220);
  278.  
  279.     sourceWindow = NewCWindow(nil,&sourceRect,
  280.                             "\pSource", TRUE,
  281.                             documentProc, (WindowPtr)(-1), FALSE, 0);
  282.                             
  283.     destinationWindow = NewCWindow(nil,&destRect,
  284.                             "\pDestination", TRUE,
  285.                             documentProc, (WindowPtr)(-1), FALSE, 0);
  286. #else
  287.  
  288. //    destinationWindow = NewCWindow(nil,&frame,
  289. //                            "\pDestination", TRUE,
  290. //                            documentProc, (WindowPtr)(-1), FALSE, 0);
  291. #endif
  292.  
  293.     GetGWorld(&savedGWorld, &savedGDevice);
  294.     NewGWorld(&sourceGWorld,8,&frame,nil,nil,0);
  295.     NewGWorld(&destinationGWorld,8,&frame,nil,nil,0);
  296.     sourcePix = GetGWorldPixMap(sourceGWorld);
  297.     LockPixels(sourcePix);
  298.     SetGWorld(sourceGWorld, nil);
  299. #ifdef PICTURE
  300.     DrawPicture(picture,&sourceGWorld->portRect);
  301. #else
  302.     GetWMgrPort(&windowManagerPort);
  303.     CopyBits(&windowManagerPort->portBits, &((GrafPtr)sourceGWorld)->portBits,
  304.         &frame, &frame, srcCopy, nil);
  305. #endif
  306.     UnlockPixels(sourcePix);
  307.     SetGWorld(savedGWorld, savedGDevice);
  308.  
  309.     sourcePix = GetGWorldPixMap(sourceGWorld);
  310.     destinationPix = GetGWorldPixMap(destinationGWorld);
  311.     rowBytes = (**GetGWorldPixMap(sourceGWorld)).rowBytes & 0x7FFF;
  312.  
  313. #ifdef PICTURE
  314.     SetPort(sourceWindow);
  315.     LockPixels(sourcePix);
  316.     CopyBits((BitMap *)*sourcePix, &sourceWindow->portBits,
  317.          &sourceGWorld->portRect, &sourceWindow->portRect, srcCopy, nil);
  318.     UnlockPixels(sourcePix);
  319. #endif
  320.     
  321.     theCode = (short *)NewPtr(4L * width * height + 6 * height + 500L);
  322.     if (theCode == nil)
  323.         Debugger();
  324.         
  325.     mappingTable = (long *)NewPtr(sizeof(long) * (long)width * height);
  326.     if (mappingTable == nil)
  327.         Debugger();
  328.  
  329.     GenerateMappingTable(mappingTable, width, height, rowBytes, x);
  330.  
  331.     LockPixels(sourcePix);
  332.     LockPixels(destinationPix);
  333.  
  334.     sourceBase = (**sourcePix).baseAddr;
  335.     destinationBase = (**destinationPix).baseAddr;
  336.  
  337.     WriteSomeCode(sourceBase, destinationBase, height, width, rowBytes, mappingTable, theCode);
  338.  
  339.     startTime = Microseconds();
  340.     asm {
  341.         movea.l    theCode, a0
  342.         jsr        (a0)                // whee!
  343.     }
  344.     endTime = Microseconds();
  345.     
  346.     UnlockPixels(sourcePix);
  347.     UnlockPixels(destinationPix);
  348.  
  349.     SetPort(destinationWindow);
  350.     CopyBits((BitMap *)*destinationPix, &destinationWindow->portBits,
  351.          &destinationGWorld->portRect, &destinationWindow->portRect, srcCopy, nil);
  352.  
  353.     while (!Button());
  354.     while (Button());
  355. }
  356.