home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / programs / desktop / newbar / Source / NewBar / c / pinpatch < prev   
Text File  |  1998-08-02  |  7KB  |  217 lines

  1.  
  2. /* pinpatch.c */
  3.  
  4. #include <stdio.h>
  5. #include <stdarg.h>
  6. #include "OS:os.h"
  7. #include "OS:osmodule.h"
  8. #include "OS:wimp.h"
  9.  
  10. #ifdef MemCheck_MEMCHECK
  11. #include "MemCheck:MemCheck.h"
  12. #endif
  13.  
  14. #include "pinpatch.h"
  15. #include "options.h"
  16.  
  17.  
  18. #define PREFIX    "PinPatch: "
  19.  
  20. typedef struct patch_state patch_state;
  21. struct patch_state {
  22.   char *module;
  23.   int module_size;
  24.   bool verbose;
  25. };
  26.  
  27. static void patch_location(patch_state *info, char *patch,
  28.     unsigned old, unsigned new, ...);
  29.  
  30. char versions[][] = {
  31.   "Unknown Pinboard version",
  32.   "Pin 0.50/OS 3.1",
  33.   "Pin 0.61/OS 3.5",
  34.   "Pin 0.66/OS 3.7",
  35. };
  36. #define VERSION_310    1
  37. #define VERSION_350    2
  38. #define VERSION_370    3
  39.  
  40.  
  41. /* Patches the Pinboard module according to the options given. */
  42. void patch_pinboard(const thiniconbar_options *options, int verbose)
  43. {
  44.   patch_state info;
  45.   if(!options->patch_pinboard) return;
  46.   info.verbose = verbose;
  47.  
  48.   if(info.verbose) printf(PREFIX "Beginning...\n");
  49.  
  50.   /* Find out where the module is, and ensure that it is in RAM. */
  51.   {
  52.     int rma_size;
  53.     char *rma;
  54.     osmodule_lookup("Pinboard", 0, (byte **) &info.module, 0, 0);
  55.     rma = (char *) os_read_dynamic_area(os_DYNAMIC_AREA_RMA, &rma_size, 0);
  56.     if(info.module < rma || info.module >= (rma + rma_size)) {
  57.       /* Pinboard is outside module area, ie. in ROM still.  So: */
  58.       os_cli("RMFaster Pinboard");
  59.       /* The module has moved, so read its location again. */
  60.       osmodule_lookup("Pinboard", 0, (byte **) &info.module, 0, 0);
  61.       if(info.verbose) printf(PREFIX "Module moved to RAM\n");
  62.     }
  63.     else if(info.verbose) printf(PREFIX "Module already in RAM\n");
  64.   }
  65. #ifdef MemCheck_MEMCHECK
  66.   MemCheck_RegisterMiscBlock(info.module - 4, 4);
  67. #endif
  68.   /* Find the module's size.  This relies on the OS's heap format storing
  69.      a block's size in the word before the beginning of the block. */
  70.   info.module_size = *(int *) (info.module - 4) - 4;
  71. #ifdef MemCheck_MEMCHECK
  72.   MemCheck_UnRegisterMiscBlock(info.module - 4);
  73.   MemCheck_RegisterMiscBlock(info.module, info.module_size);
  74. #endif
  75.  
  76.   /* Patch new background colours. */
  77.   if(options->pinboard_bg_colour != -1) {
  78.     /* Patch file icon flags. */
  79.     /* Normal flags. */
  80.     patch_location(&info, "File-bg-1", 0x4000A50B, 0x0000A50B |
  81.     (options->pinboard_bg_colour << wimp_ICON_BG_COLOUR_SHIFT),
  82.     0x30D0, VERSION_370, 0);
  83.     /* Selected flags? */
  84.     patch_location(&info, "File-bg-2", 0x1700A50B, 0x1700A50B,
  85.     0x30D4, VERSION_370, 0);
  86.  
  87.     /* Patch iconise icon flags. */
  88.     /* Normal flags. */
  89.     patch_location(&info, "Iconise-bg-1", 0x4000A50B, 0x0000A50B |
  90.     (options->pinboard_bg_colour << wimp_ICON_BG_COLOUR_SHIFT),
  91.     0x12CC, VERSION_370, 0);
  92.     /* Selected flags? */
  93.     patch_location(&info, "Iconise-bg-2", 0x1700310B, 0x0700310B,
  94.     0x12C8, VERSION_370, 0);
  95.  
  96.     /* Patch background clearing. */
  97.     /* movne r0, #0x84  becomes  movne r0, #0x80 | pinboard_bg_colour */
  98.     patch_location(&info, "CLG-1", 0x13A00084, 0x13A00080 |
  99.     options->pinboard_bg_colour,
  100.     0x0BE0, VERSION_370,
  101.     0x0E10, VERSION_310, 0);
  102.     /* mov r0, #0x84  becomes  mov r0, #0x80 | pinboard_bg_colour */
  103.     patch_location(&info, "CLG-2", 0xE3A00084, 0xE3A00080 |
  104.     options->pinboard_bg_colour,
  105.     0x24F4, VERSION_370,
  106.     0x24E8, VERSION_310, 0);
  107.   }
  108.  
  109.   /* Patch new iconbar height. */
  110.   /* mov r3, #0x86  becomes  mov r3, #window_height... */
  111.   patch_location(&info, "Iconbar-height", 0xE3A03000 + 0x86,
  112.     /* If iconbar has border, it will be higher (assume 4 OS units). */
  113.     0xE3A03000 + options->window_height +
  114.         (options->window_border ? 4 : 0),
  115.     0x4188, VERSION_310,
  116.     0x438C, VERSION_370, 0);
  117.  
  118.   /* Neuter the Pinboard of its error message `Use *Desktop to start
  119.      Pinboard'.  This makes Desktop_Pinboard work, and removes this rather
  120.      fascist tendency. */
  121.   /* Remove the check in the module start code. */
  122.   /* swige OS_GenerateError  becomes  no-op (mov r0, r0) */
  123.   patch_location(&info, "Bstd", 0xAF00002B, 0xE1A00000,
  124.     0x08E4, VERSION_370,
  125.     0x0B30, VERSION_310, 0);
  126.   /* Remove the check in the *Desktop_Pinboard command code. */
  127.   /* Hmm, not finished.  Not sure if it will work cleanly. */
  128.  
  129. #ifdef MemCheck_MEMCHECK
  130.   MemCheck_UnRegisterMiscBlock(info.module);
  131. #endif
  132.   if(info.verbose) printf(PREFIX "Finished\n");
  133. }
  134.  
  135.  
  136. /* Tries patching each location in turn, checking to see if it has been
  137.    patched already or does not match. */
  138. static void patch_location(patch_state *info, char *patch,
  139.     unsigned old, unsigned new, ...)
  140. {
  141.   va_list args;
  142.  
  143.   /* Look at pre-supplied locations for patching. */
  144.   va_start(args, new);
  145.   while(1) {
  146.     int offset, version;
  147.     unsigned *location;
  148.  
  149.     /* Get location info from arguments. */
  150.     offset = va_arg(args, int);
  151.     if(!offset) break; /* End of the list. */
  152.     version = va_arg(args, int);
  153.     location = (unsigned *) (info->module + offset);
  154.  
  155.     /* Check the location in the module. */
  156.     /* Does it fall outside the module? */
  157.     if(offset >= info->module_size) continue;
  158.     /* Has it already been patched? */
  159.     if(*location == new) {
  160.       if(info->verbose) printf(PREFIX "Patch `%s' already applied (to %s)\n",
  161.         patch, versions[version]);
  162.       va_end(args);
  163.       return;
  164.     }
  165.     /* Does it match, and so can be patched? */
  166.     if(*location == old) {
  167.       *location = new;
  168.       if(info->verbose) printf(PREFIX "Patch `%s' now applied (to %s)\n",
  169.         patch, versions[version]);
  170.       va_end(args);
  171.       return;
  172.     }
  173.   }
  174.   va_end(args);
  175.  
  176.   /* If that failed, search through the module to find the word given.  It
  177.      must only appear once (otherwise how do we know which to patch?). */
  178.   {
  179.     unsigned *i, *end = (unsigned *) (info->module + info->module_size),
  180.     *found = 0;
  181.     int found_patched = 0;
  182.     for(i=(unsigned *) info->module; i<end; ++i) {
  183.       if(*i == new) {
  184.         ++found_patched;
  185.         continue;
  186.       }
  187.       if(*i == old) {
  188.         if(found) {
  189.           if(info->verbose) printf(PREFIX "Patch `%s' could not be applied "
  190.         "(multiple matches)\n", patch);
  191.           return;
  192.         }
  193.         found = i;
  194.         continue;
  195.       }
  196.     }
  197.     if(found) {
  198.       /* We can apply the patch! */
  199.       *found = new;
  200.       if(info->verbose) printf(PREFIX "Patch `%s' now applied "
  201.         "(to %s, at 0x%x)\n", patch, versions[0],
  202.         (char *) found - info->module);
  203.       return;
  204.     }
  205.     else if(found_patched) {
  206.       if(info->verbose) printf(PREFIX "Patch `%s' probably already applied "
  207.         "(found %i match%s)\n", patch, found_patched,
  208.         found_patched > 1 ? "es" : "");
  209.       return;
  210.     }
  211.   }
  212.  
  213.   /* If we couldn't apply this patch, whinge. */
  214.   if(info->verbose) printf(PREFIX "Patch `%s' could not be applied "
  215.         "(no matches)\n", patch);
  216. }
  217.