Annotation of generator/main/patch.c, revision 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.