home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / gfx / misc / patchdt / patchdt.c next >
Encoding:
C/C++ Source or Header  |  1993-12-21  |  8.1 KB  |  308 lines

  1. /*
  2.  * PatchDT - Patch datatypes for faster blitting on systems with
  3.  *           enhanced video adapters.
  4.  *
  5.  * Improves performance roughly fourfold on 256-colour Workbench
  6.  * screen in Zorro II mode, and even more when running in Zorro
  7.  * III mode.
  8.  *
  9.  */
  10.  
  11. /* === System Includes === */
  12.  
  13. #include <proto/exec.h>
  14. #include <proto/dos.h>
  15. #include <proto/datatypes.h>
  16. #include <proto/utility.h>
  17. #include <proto/intuition.h>
  18. #include <proto/graphics.h>
  19. #include <datatypes/datatypes.h>
  20. #include <datatypes/pictureclass.h>
  21. #include <exec/memory.h>
  22. #include <exec/execbase.h>
  23.  
  24. #include <string.h>
  25.  
  26. /* === Function prototypes === */
  27.  
  28. ULONG __asm __saveds GetDTAttrsA_patch(register __a0 Object *o, register __a2 struct TagItem *ti);
  29. VOID __asm __saveds DisposeDTObject_patch(register __a0 Object *o);
  30.  
  31. extern __asm struct BitMap * ROMCall(register __d0 ULONG, register __d1 ULONG, register __d2 ULONG, register __d3 ULONG,
  32.                                      register __a0 struct BitMap *, register __a5 void *, register __a6 void * );
  33.  
  34. extern void __asm InitROMCall(void);
  35.  
  36. /* === Various data items === */
  37.  
  38. ULONG __asm (*getDTAttrsA)(register __a0 Object *, register __a2 struct TagItem *, register __a6 struct Library *dtBase);
  39. VOID __asm  (*disposeDTObject)(register __a0 Object *, register __a6 struct Library *dtBase);
  40.  
  41. void *allocBM;
  42.  
  43. struct Library *DataTypesBase;
  44. struct Library *UtilityBase;
  45. struct ExecBase *SysBase;
  46. struct IntuitionBase *IntuitionBase;
  47. struct GfxBase *GfxBase;
  48. struct DosLibrary *DOSBase;
  49.  
  50. #define MAX_KEYS 16             /* Maximum number of associations */
  51.  
  52. ULONG key_list[MAX_KEYS];       /* List of keys */
  53. ULONG val_list[MAX_KEYS];       /* List of values associated with keys */
  54.  
  55. /*
  56.  * __main - Program entry
  57.  *
  58.  * Installs patch functions, waits for SIGBREAKF_CTRL_C, and uninstalls
  59.  * patches.
  60.  *
  61.  */
  62.  
  63. int __asm __saveds
  64. __main(void)
  65. {
  66.   ULONG sig;
  67.  
  68.   /* === Open System Libraries - This only works with V39 and later === */
  69.  
  70.   SysBase = (*((struct ExecBase **)4));
  71.   
  72.   if (SysBase->LibNode.lib_Version < 39) {
  73.     return RETURN_FAIL;
  74.   }
  75.   
  76.   DataTypesBase = OpenLibrary("datatypes.library", 39);
  77.   UtilityBase = OpenLibrary("utility.library", 39);
  78.   IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 39);
  79.   GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 39);
  80.   DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 39);
  81.  
  82.   InitROMCall();
  83.  
  84.   Forbid();
  85.  
  86.   /* === Patch vectors in datatypes.library === */
  87.  
  88.   disposeDTObject = SetFunction(DataTypesBase, -54, (APTR) DisposeDTObject_patch);
  89.   getDTAttrsA = SetFunction(DataTypesBase, -66, (APTR) GetDTAttrsA_patch);
  90.   
  91.   /* === Find out address of AllocBitMap() function === */
  92.   
  93.   allocBM = SetFunction( (struct Library *) GfxBase, -918, NULL);
  94.   SetFunction( (struct Library *) GfxBase, -918, allocBM);
  95.   
  96.   Permit();
  97.  
  98.   /* === Wait for signal to uninstall === */
  99.  
  100.   sig = 0;
  101.  
  102.   while (! (sig & SIGBREAKF_CTRL_C) ) {
  103.     sig = Wait( SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D );
  104.   }
  105.  
  106.   /* === Uninstall patch functions from datatypes.library === */
  107.  
  108.   Forbid();
  109.   
  110.   SetFunction(DataTypesBase, -54, (APTR) disposeDTObject);
  111.   SetFunction(DataTypesBase, -66, (APTR) getDTAttrsA);
  112.   
  113.   Permit();
  114.  
  115.   /* === Close all open libraries === */
  116.  
  117.   CloseLibrary((struct Library *) DOSBase);
  118.   CloseLibrary((struct Library *) GfxBase);
  119.   CloseLibrary((struct Library *) IntuitionBase);  
  120.   CloseLibrary(UtilityBase);
  121.   CloseLibrary(DataTypesBase);
  122.   
  123.   return 0;
  124. }
  125.  
  126. /*
  127.  * Association functions. Used to associate an arbitrary value (in this case
  128.  * a pointer to a BitMap structure) with a key (in this case a datatypes
  129.  * Object).
  130.  *
  131.  * associate(key)           - returns the value associated with the given key.
  132.  * disassociate(key)        - forget an association
  133.  * new_associate(key,value) - create a new association
  134.  *
  135.  */
  136.  
  137. ULONG
  138. associate(ULONG key)
  139. {
  140.   int i;
  141.  
  142.   for (i = 0; i < MAX_KEYS; i++) {
  143.     if (key_list[i] == key) {
  144.       return val_list[i];
  145.     }
  146.   }
  147.   
  148.   return 0;
  149. }
  150.  
  151. void
  152. disassociate(ULONG key)
  153. {
  154.   int i;
  155.  
  156.   for (i = 0; i < MAX_KEYS; i++) {
  157.     if (key_list[i] == key) {
  158.       val_list[i] = 0;
  159.       key_list[i] = 0;
  160.     }
  161.   }
  162. }
  163.  
  164. ULONG
  165. new_associate(ULONG key, ULONG value)
  166. {
  167.   int i;
  168.  
  169.   for (i = 0; i < MAX_KEYS; i++) {
  170.     if (key_list[i] == 0) {
  171.       val_list[i] = value;
  172.       key_list[i] = key;
  173.  
  174.       return key;
  175.     }
  176.   }
  177.   
  178.   return 0;
  179. }
  180.  
  181. /*
  182.  * Patch function for datatypes.library function GetDTAttrsA()
  183.  *
  184.  */
  185.  
  186. ULONG __asm __saveds
  187. GetDTAttrsA_patch(register __a0 Object *o, register __a2 struct TagItem *ti)
  188. {
  189.   ULONG retval;
  190.   struct BitMap **bitmapPtr;
  191.   struct BitMap *newBitMap;
  192.   struct BitMapHeader *bmh;
  193.   struct Screen *WBScreen;
  194.  
  195.   int width, height, depth;
  196.   struct BitMap *friend;
  197.  
  198.   /* == First call original function == */
  199.  
  200.   retval = (*getDTAttrsA)(o, ti, DataTypesBase);
  201.   
  202.   /* === Optimization is only safe if "« IPrefs »" is the name of
  203.    *     the calling task. Programs such as MultiView may expect
  204.    *     the data to be in a specific format (even though it
  205.    *     really should not).
  206.    */
  207.  
  208.   if (strcmp("« IPrefs »", (FindTask(NULL)->tc_Node.ln_Name)) == 0) {
  209.  
  210.     /* Get pointer to where the caller wants the BitMap pointer stored */
  211.  
  212.     bitmapPtr = (struct BitMap **) GetTagData (PDTA_BitMap, 0, ti);
  213.     
  214.     if (bitmapPtr) {
  215.     
  216.       /* If this Object already has an associated bitmap, return it */
  217.     
  218.       if (newBitMap = (struct BitMap *) associate((ULONG) o)) {
  219.         *bitmapPtr = newBitMap;
  220.       } else {
  221.         ULONG tags[3];
  222.         
  223.         /* === Get sizing information from Object === */
  224.  
  225.         tags[0] = PDTA_BitMapHeader;
  226.         tags[1] = (ULONG) &bmh;
  227.         tags[2] = TAG_END;
  228.  
  229.         (*getDTAttrsA)(o, (struct TagItem *) tags, DataTypesBase);
  230.  
  231.         /* === Get pointer to Workbench screen, in order to obtain pointer
  232.          *     to the friend bitmap.
  233.          */
  234.  
  235.         WBScreen = LockPubScreen( "Workbench" );
  236.  
  237.         /* Notice that I use the BitMap pointer stored in the Screen's
  238.          * RastPort instead of the BitMap embedded in the Screen
  239.          * structure. This is for future compatibility with V41 and
  240.          * beyond, which has several different layouts (and sizes) for
  241.          * BitMap structures. Everybody should do it like this.
  242.          */
  243.  
  244.         friend = WBScreen->RastPort.BitMap;
  245.         depth = friend->Depth;
  246.  
  247.         width = bmh->bmh_Width;
  248.         height = bmh->bmh_Height;
  249.  
  250.         /* I have to call the AllocBitMap() function through an assembly
  251.          * language stub in order to make it look as if the AllocBitMap()
  252.          * call was done from ROM. Otherwise the EGS Workbench Emulation
  253.          * software will not redirect the call, and this patch will have
  254.          * no effect.
  255.          */
  256.  
  257.         newBitMap = ROMCall(width, height, depth, 0, friend, allocBM, GfxBase);
  258.  
  259.         /* === Release Lock on Workbench screen === */
  260.  
  261.         UnlockPubScreen(NULL, WBScreen);
  262.  
  263.         /* === Now blit the image from the original bitmap into our newly
  264.          *     allocated bitmap, and set the caller's bitmap pointer to
  265.          *     point at our new bitmap.
  266.          */
  267.  
  268.         if (newBitMap) {
  269.           BltBitMap(*bitmapPtr, 0,0, newBitMap, 0,0, bmh->bmh_Width, bmh->bmh_Height, 0xC0, 0xff, 0);
  270.         
  271.           if (new_associate((ULONG) o, (ULONG) newBitMap)) {
  272.             *bitmapPtr = newBitMap;                     /* Success! */
  273.           } else {
  274.             FreeBitMap(newBitMap);
  275.             DisplayBeep(WBScreen);                      /* Error! Association table full */
  276.           }
  277.         } else {
  278.           DisplayBeep(WBScreen);                        /* Error! Could not allocate BitMap */
  279.         }
  280.       }
  281.     }
  282.   }
  283.  
  284.   return retval;
  285. }
  286.  
  287. /*
  288.  * Patch function for datatypes.library DisposeDTObject() function.
  289.  *
  290.  * Simply calls FreeBitMap() if the Object has a special BitMap
  291.  * allocated by us associated with it, and then falls through to the
  292.  * original DisposeDTObject() function.
  293.  *
  294.  */
  295.  
  296. VOID __asm __saveds
  297. DisposeDTObject_patch(register __a0 Object *o)
  298. {
  299.   struct BitMap *bm;
  300.  
  301.   if (bm = (struct BitMap *) associate((ULONG) o)) {
  302.     FreeBitMap(bm);
  303.     disassociate((ULONG) o);            /* Forget about this object */
  304.   }
  305.  
  306.   (*disposeDTObject)(o, DataTypesBase);
  307. }
  308.