Annotation of generator/main/patch.c, revision 1.1.1.1

1.1       root        1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
                      2: 
                      3: #include <stdio.h>
                      4: #include <string.h>
                      5: #include <stdlib.h>
                      6: #include <errno.h>
                      7: 
                      8: #include "generator.h"
                      9: 
                     10: #include "ui.h"
                     11: #include "cpu68k.h"
                     12: #include "patch.h"
                     13: 
                     14: /* Merlyn LeRoy's lamp.c comment: */
                     15: 
                     16: /*
                     17:  * "Eet ees not *I* who am crazy, eet ees I who am MAD!" - R. Ho"ek
                     18:  *
                     19:  * lamp.c - a program to control Game Genie for Genesis
                     20:  *
                     21:  * Translate between Game Genie for Genesis 8-character codes and
                     22:  * the 24-bit address & 16-bit value for that address.
                     23:  * The format is this:
                     24:  *
                     25:  * ijklm nopIJ KLMNO PABCD EFGHd efgha bcQRS TUVWX   decodes to...
                     26:  *
                     27:  * ABCDEFGH IJKLMNOP QRSTUVWX: abcdefgh ijklmnop
                     28:  * 24-bit address              16-bit data
                     29:  * MSB                    LSB  MSB           LSB
                     30:  *
                     31:  * ..where each group of five letters is a Genie code character
                     32:  * (ABCDEFGHJKLMNPRSTVWXYZ0123456789, each representing 5 bits 00000-11111),
                     33:  * and each 8-character Genie code is the 24-bit address and 16-bit data.
                     34:  *
                     35:  * For example, SCRA-BJX0 is a game genie code.  Each letter is 5 bits from
                     36:  * the table ABCDEFGHJKLMNPRSTVWXYZ0123456789, A=00000, B=00001, C=00010...
                     37:  *
                     38:  *   S     C     R     A  -  B     J     X     0
                     39:  * 01111 00010 01110 00000 00001 01000 10011 10110
                     40:  * ijklm nopIJ KLMNO PABCD EFGHd efgha bcQRS TUVWX   rearrange as...
                     41:  *
                     42:  * 00000000 10011100 01110110: 01010100 01111000
                     43:  * ABCDEFGH IJKLMNOP QRSTUVWX: abcdefgh ijklmnop
                     44:  * 24-bit address              16-bit data
                     45:  * MSB                    LSB  MSB           LSB
                     46:  *
                     47:  * Which is 009c76: 5478
                     48:  *
                     49:  * See the usage message when run with no arguments...
                     50:  * Merlyn LeRoy (Brian Westley), [email protected] 1/4/93
                     51:  */
                     52: 
                     53: static const char *patch_codestring = "ABCDEFGHJKLMNPRSTVWXYZ0123456789";
                     54: 
                     55: /*** externed ***/
                     56: 
                     57: t_patchlist *patch_patchlist; /* patches */
                     58: 
                     59: /*** patch_savefile - save current patches to file ***/
                     60: 
                     61: int patch_savefile(const char *filename)
                     62: {
                     63:   FILE *f;
                     64:   t_patchlist *ent;
                     65: 
                     66:   if ((f = fopen(filename, "wb")) == NULL) {
                     67:     LOG_CRITICAL(("Failed to open '%s' for writing: %s",
                     68:                   filename, strerror(errno)));
                     69:     return -1;
                     70:   }
                     71:   for (ent = patch_patchlist; ent; ent = ent->next)
                     72:     fprintf(f, "%s    %s\r\n", ent->code, ent->action);
                     73:   if (fclose(f) == EOF) {
                     74:     LOG_CRITICAL(("Failed to close '%s': %s", filename, strerror(errno)));
                     75:     return -1;
                     76:   }
                     77:   return 0;
                     78: }
                     79: 
                     80: /*** patch_loadfile - load the patch file ***/
                     81: 
                     82: int patch_loadfile(const char *filename)
                     83: {
                     84:   char linebuf[256];
                     85:   char *p;
                     86:   FILE *f;
                     87:   t_patchlist *ent, **end;
                     88: 
                     89:   if ((f = fopen(filename, "rb")) == NULL) {
                     90:     LOG_CRITICAL(("Failed to open '%s': %s", filename, strerror(errno)));
                     91:     return -1;
                     92:   }
                     93:   patch_clearlist();
                     94:   end = &patch_patchlist;
                     95:   while (fgets(linebuf, sizeof(linebuf), f)) {
                     96:     if (linebuf[strlen(linebuf)-1] != '\n') {
                     97:       LOG_CRITICAL(("Line too long in '%s': %s", filename, strerror(errno)));
                     98:       return -1;
                     99:     }
                    100:     linebuf[strlen(linebuf)-1] = '\0'; /* remove newline */
                    101:     if (*linebuf && linebuf[strlen(linebuf)-1] == '\r')
                    102:       linebuf[strlen(linebuf)-1] = '\0'; /* remove optional cr */
                    103:     if (strlen(linebuf) < 11 && linebuf[6] != ':') {
                    104:       LOG_CRITICAL(("Invalid patch file '%s'", filename));
                    105:       return -1;
                    106:     }
                    107:     if ((ent = malloc(sizeof(t_patchlist))) == NULL)
                    108:       ui_err("out of memory");
                    109:     snprintf(ent->code, 12, "%s", linebuf);
                    110:     for (p = linebuf + 11; *p == ' '; p++) ;
                    111:     if ((ent->action = strdup(p)) == NULL)
                    112:       ui_err("out of memory");
                    113:     ent->next = NULL;
                    114:     *end = ent;
                    115:     end = &ent->next;
                    116:   }
                    117:   if (!feof(f)) {
                    118:     LOG_CRITICAL(("Error whilst reading patch file '%s'", filename));
                    119:     return -1;
                    120:   }
                    121:   if (fclose(f) == EOF) {
                    122:     LOG_CRITICAL(("Failed to close '%s': %s", filename, strerror(errno)));
                    123:     return -1;
                    124:   }
                    125:   return 0;
                    126: }
                    127: 
                    128: void patch_clearlist(void)
                    129: {
                    130:   t_patchlist *ent;
                    131: 
                    132:   /* clear out old patch list */
                    133:   while (patch_patchlist) {
                    134:     ent = patch_patchlist;
                    135:     patch_patchlist = patch_patchlist->next;
                    136:     free(ent->action);
                    137:     free(ent);
                    138:   }
                    139: }
                    140: 
                    141: void patch_addcode(const char *code, const char *action)
                    142: {
                    143:   t_patchlist *ent, **end;
                    144: 
                    145:   /* where's the end of the list */
                    146:   for (end = &patch_patchlist; *end; end = &((*end)->next)) ;
                    147: 
                    148:   /* create and insert */
                    149:   if ((ent = malloc(sizeof(t_patchlist))) == NULL)
                    150:     ui_err("out of memory");
                    151:   snprintf(ent->code, sizeof(ent->code), "%s", code);
                    152:   ent->action = strdup(action);
                    153:   ent->next = NULL;
                    154:   *end = ent;
                    155: }
                    156: 
                    157: int patch_apply(const char *code, const char *action)
                    158: {
                    159:   uint32 addr;
                    160:   uint32 data;
                    161:   char *end;
                    162: 
                    163:   (void)action;
                    164:   addr = strtol(code, &end, 16);
                    165:   if (*end++ != ':')
                    166:     return -1;
                    167:   data = strtol(end, &end, 16);
                    168:   if (*end)
                    169:     return -1;
                    170:   if (addr & ~0xfffffe || data & ~0xffff)
                    171:     return -1;
                    172:   if (addr < cpu68k_romlen) {
                    173:     printf("applied %X = %X\n", addr, data);
                    174:     ((uint16 *)cpu68k_rom)[addr >> 1] = LOCENDIAN16((uint16)data);
                    175:     gen_modifiedrom = 1;
                    176:   } else if ((addr & 0xe00000) == 0xe00000) {
                    177:     printf("applied %X = %X\n", addr, data);
                    178:     ((uint16 *)cpu68k_ram)[(addr & 0xfff) >> 1] = LOCENDIAN16((uint16)data);
                    179:   } else {
                    180:     return -1;
                    181:   }
                    182:   return 0;
                    183: }
                    184: 
                    185: /* given a game genie code, convert to 24-bit address, 16-bit data */
                    186: 
                    187: int patch_genietoraw(const char *code, uint32 *addr, uint16 *data)
                    188: {
                    189:   char *p;
                    190:   uint32 a, d, v;
                    191:   int i;
                    192: 
                    193:   if (strlen(code) != 9 || code[4] != '-')
                    194:     return -1;
                    195:   for (i = 0; i < 9; i = (i == 3 ? i+2 : i+1)) {
                    196:     if ((p = strchr(patch_codestring, code[i])) == NULL)
                    197:       return -1;
                    198:     v = p - patch_codestring;
                    199:     switch (i) {
                    200:     case 0: d|= v << 3; break;
                    201:     case 1: d|= v >> 2; a|= (v & 3) << 14; break;
                    202:     case 2: a|= v << 9; break;
                    203:     case 3: a|= (v >> 4) << 8; a|= (v & 15) << 20; break;
                    204:     case 5: a|= (v >> 1) << 16; d|= (v & 1) << 12; break;
                    205:     case 6: d|= (v >> 1) << 8; d|= (v & 1) << 15; break;
                    206:     case 7: d|= (v >> 3) << 13; a|= (v & 7) << 5; break;
                    207:     case 8: a|= v; break; 
                    208:     default: return -1;
                    209:     }
                    210:   }
                    211:   *addr = a;
                    212:   *data = d;
                    213:   return 0;
                    214: }
                    215: 
                    216: /* given a 24-bit address, 16-bit data, create game genie code */
                    217: 
                    218: int patch_rawtogenie(uint32 addr, uint16 data, char *code)
                    219: {
                    220:   uint8 v;
                    221:   int i;
                    222: 
                    223:   if (addr & 0xff000000)
                    224:     return -1;
                    225:   code[4] = '-';
                    226:   for (i = 0; i < 9; i = (i == 3 ? i+2 : i+1)) {
                    227:     switch (i) {
                    228:     case 0: v = (data >> 3) & 15; break;
                    229:     case 1: v = ((data & 7) << 2) | ((addr >> 14) & 3); break;
                    230:     case 2: v = (addr >> 9) & 15; break;
                    231:     case 3: v = (addr >> 20) | ((addr >> 4) & 0x10); break;
                    232:     case 5: v = ((addr >> 15) & 14) | ((data >> 12) & 1); break;
                    233:     case 6: v = ((data >> 8) & 14) | (data >> 15); break;
                    234:     case 7: v = ((data >> 10) & 0x18) | ((addr >> 5) & 7); break;
                    235:     case 8: v = addr & 15; break;
                    236:     }
                    237:     code[i] = patch_codestring[v];
                    238:   }
                    239:   return 0;
                    240: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.