Annotation of generator/main/generator.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 <stdlib.h>
                      4: #include <stdio.h>
                      5: #include <string.h>
                      6: #include <sys/stat.h>
                      7: #include <unistd.h>
                      8: #include <sys/types.h>
                      9: #include <fcntl.h>
                     10: #include <ctype.h>
                     11: #include <signal.h>
                     12: #include <errno.h>
                     13: 
                     14: #include "generator.h"
                     15: #include "snprintf.h"
                     16: 
                     17: #include "ui.h"
                     18: #include "memz80.h"
                     19: #include "mem68k.h"
                     20: #include "cpu68k.h"
                     21: #include "cpuz80.h"
                     22: #include "vdp.h"
                     23: #include "gensound.h"
                     24: 
                     25: #ifdef ALLEGRO
                     26: #include "allegro.h"
                     27: #endif
                     28: 
                     29: /*** variables externed in generator.h ***/
                     30: 
                     31: unsigned int gen_quit = 0;
                     32: unsigned int gen_debugmode = 1;
                     33: unsigned int gen_loglevel = 2; /* 2 = NORMAL, 1 = CRITICAL */
                     34: t_cartinfo gen_cartinfo;
                     35: char gen_leafname[128];
                     36: 
                     37: /*** forward references ***/
                     38: 
                     39: void gen_nicetext(char *out, char *in, unsigned int size);
                     40: uint16 gen_checksum(uint8 *start, unsigned int length);
                     41: 
                     42: /*** Signal handler ***/
                     43: 
                     44: RETSIGTYPE gen_sighandler(int signum)
                     45: {
                     46:   if (gen_debugmode) {
                     47:     if (signum == SIGINT) {
                     48:       if (gen_quit) {
                     49:         LOG_CRITICAL(("Bye!"));
                     50:        ui_final();
                     51:        ui_err("Exiting");
                     52:       } else {
                     53:        LOG_REQUEST(("Ping - current PC = 0x%X", regs.pc));
                     54:       }
                     55:       gen_quit = 1;
                     56:     }
                     57:   } else {
                     58:     ui_final();
                     59:     exit(0);
                     60:   }
                     61:   signal(signum, gen_sighandler);
                     62: }
                     63: 
                     64: static char thing[] = ("\n\nIt's the year 2000 is there anyone out there?\n"
                     65:                       "\nIf you're from another planet put your hand in the "
                     66:                       "air, say yeah!\n\n");
                     67: 
                     68: /*** Program entry point ***/
                     69: 
                     70: int main(int argc, char *argv[]) {
                     71:   int retval;
                     72:   t_sr test;
                     73: 
                     74:   test.sr_int = 0;
                     75:   test.sr_struct.c = 1;
                     76:   if (test.sr_int != 1) {
                     77:     fprintf(stderr, "%s: compilation variable BYTES_HIGHFIRST not set "
                     78:            "correctly\n", argv[0]);
                     79:     return 1;
                     80:   }
                     81: 
                     82:   /* initialise user interface */
                     83:   if ((retval = ui_init(argc, argv)))
                     84:     return retval;
                     85: 
                     86:   /* initialise 68k memory system */
                     87:   if ((retval = mem68k_init()))
                     88:     ui_err("Failed to initialise mem68k module (%d)", retval);
                     89: 
                     90:   /* initialise z80 memory system */
                     91:   if ((retval = memz80_init()))
                     92:     ui_err("Failed to initialise memz80 module (%d)", retval);
                     93: 
                     94:   /* initialise vdp system */
                     95:   if ((retval = vdp_init()))
                     96:     ui_err("Failed to initialise vdp module (%d)", retval);
                     97: 
                     98:   /* initialise cpu system */
                     99:   if ((retval = cpu68k_init()))
                    100:     ui_err("Failed to initialise cpu68k module (%d)", retval);
                    101: 
                    102:   /* initialise z80 cpu system */
                    103:   if ((retval = cpuz80_init()))
                    104:     ui_err("Failed to initialise cpuz80 module (%d)", retval);
                    105: 
                    106:   /* initialise sound system */
                    107:   if ((retval = sound_init()))
                    108:     ui_err("Failed to initialise sound module (%d)", retval);
                    109: 
                    110:   signal(SIGINT, gen_sighandler);
                    111: 
                    112:   /* enter user interface loop */
                    113:   return ui_loop();
                    114: }
                    115: 
                    116: #ifdef ALLEGRO
                    117: END_OF_MAIN();
                    118: #endif
                    119: 
                    120: /*** gen_reset - reset system ***/
                    121: 
                    122: void gen_reset(void) {
                    123:   vdp_reset();
                    124:   cpu68k_reset();
                    125:   cpuz80_reset();
                    126:   if (sound_reset()) {
                    127:     ui_err("sound failure");
                    128:   }
                    129: }
                    130: 
                    131: /*** gen_softreset - reset system ***/
                    132: 
                    133: void gen_softreset(void) {
                    134:   cpu68k_reset();
                    135: }
                    136: 
                    137: /*** gen_loadimage - load ROM image ***/
                    138: 
                    139: char *gen_loadimage(const char *filename) {
                    140:   int file, imagetype, bytes, bytesleft;
                    141:   struct stat statbuf;
                    142:   const char *extension;
                    143:   uint8 *buffer;
                    144:   char countrybuf[32];
                    145:   unsigned int blocks, x, i;
                    146:   uint8 *new;
                    147:   char *p;
                    148: 
                    149:   /* Remove current file */
                    150:   if (cpu68k_rom) {
                    151:     free(cpu68k_rom);
                    152:     cpu68k_rom = NULL;
                    153:   }
                    154: 
                    155:   /* Load file */
                    156:   if (stat(filename, &statbuf) != 0) {
                    157:     return("Unable to stat file.");
                    158:   }
                    159:   cpu68k_romlen = statbuf.st_size;
                    160:   /* allocate enough memory plus 16 bytes for disassembler to cope
                    161:      with the last instruction */
                    162:   if ((cpu68k_rom = malloc(cpu68k_romlen+16)) == NULL) {
                    163:     cpu68k_romlen = 0;
                    164:     return("Out of memory!");
                    165:   }
                    166:   memset(cpu68k_rom, 0, cpu68k_romlen+16);
                    167: #ifdef ALLEGRO
                    168:   if ((file = open(filename, O_RDONLY|O_BINARY, 0)) == -1) {
                    169: #else
                    170:   if ((file = open(filename, O_RDONLY, 0)) == -1) {
                    171: #endif
                    172:     perror("open");
                    173:     cpu68k_rom = NULL;
                    174:     cpu68k_romlen = 0;
                    175:     return("Unable to open file.");
                    176:   }
                    177:   buffer = cpu68k_rom;
                    178:   bytesleft = cpu68k_romlen;
                    179:   do {
                    180:     if ((bytes = read(file, buffer, bytesleft)) <= 0)
                    181:       break;
                    182:     buffer+= bytes;
                    183:     bytesleft-= bytes;
                    184:   } while (bytesleft >= 0);
                    185:   close(file);
                    186:   if (bytes == -1)
                    187:     return(strerror(errno));
                    188:   else if (bytes != 0)
                    189:     return("invalid return code from read()");
                    190:   if (bytesleft) {
                    191:     LOG_CRITICAL(("%d bytes left to read?!", bytesleft));
                    192:     return("Error whilst loading file");
                    193:   }
                    194: 
                    195:   imagetype = 1; /* BIN file by default */
                    196: 
                    197:   /* SMD file format check - Richard Bannister */
                    198:   if ((cpu68k_rom[8] == 0xAA) && (cpu68k_rom[9] == 0xBB) &&
                    199:       cpu68k_rom[10] == 0x06) {
                    200:     imagetype = 2; /* SMD file */
                    201:   }
                    202:   /* check for interleaved 'SEGA' */
                    203:   if (cpu68k_rom[0x280] == 'E' && cpu68k_rom[0x281] == 'A' &&
                    204:       cpu68k_rom[0x2280] == 'S' && cpu68k_rom[0x2281] == 'G') {
                    205:     imagetype = 2; /* SMD file */
                    206:   }
                    207: 
                    208: #ifndef OS_ACORN
                    209:   /* Check extension is not wrong */
                    210:   extension = filename + strlen(filename) - 3;
                    211:   if (extension > filename) {
                    212:     if (!strcasecmp(extension, "smd") && (imagetype != 2))
                    213:       LOG_REQUEST(("File extension (smd) does not match detected "
                    214:                   "type (bin)"));
                    215:     if (!strcasecmp(extension, "bin") && (imagetype != 1))
                    216:       LOG_REQUEST(("File extension (bin) does not match detected "
                    217:                   "type (smd)"));
                    218:   }
                    219: #endif
                    220: 
                    221:   /* convert to standard BIN file format */
                    222: 
                    223:   switch(imagetype) {
                    224:   case 1: /* BIN */
                    225:     break;
                    226:   case 2: /* SMD */
                    227:     blocks = (cpu68k_romlen-512)/16384;
                    228:     if (blocks*16384+512 != cpu68k_romlen)
                    229:       return("Image is corrupt.");
                    230: 
                    231:     if ((new = malloc(cpu68k_romlen-512)) == NULL) {
                    232:       cpu68k_rom = NULL;
                    233:       cpu68k_romlen = 0;
                    234:       return("Out of memory!");
                    235:     }
                    236: 
                    237:     for (i = 0; i < blocks; i++) {
                    238:       for (x = 0; x < 8192; x++) {
                    239:         new[i*16384+x*2+0] = cpu68k_rom[512+i*16384+8192+x];
                    240:         new[i*16384+x*2+1] = cpu68k_rom[512+i*16384+x];
                    241:       }
                    242:     }
                    243:     free(cpu68k_rom);
                    244:     cpu68k_rom = new;
                    245:     cpu68k_romlen-= 512;
                    246:     break;
                    247:   default:
                    248:     return("Unknown image type");
                    249:     break;
                    250:   }
                    251: 
                    252:   /* reset system */
                    253:   gen_reset();
                    254: 
                    255:   /* is this icky? */
                    256:   if ((p = strrchr(filename, '/')) == NULL &&
                    257:       (p = strrchr(filename, '\\')) == NULL) {
                    258:     snprintf(gen_leafname, sizeof(gen_leafname), "%s", filename);
                    259:   } else {
                    260:     snprintf(gen_leafname, sizeof(gen_leafname), "%s", p+1);
                    261:   }
                    262:   if ((p = strrchr(gen_leafname, '.')) != NULL) {
                    263:     if ((!strcasecmp(p, ".smd")) || (!strcasecmp(p, ".bin")))
                    264:       *p = '\0';
                    265:   }
                    266:   if (gen_leafname[0] == '\0')
                    267:     snprintf(gen_leafname, sizeof(gen_leafname), "rom");
                    268: 
                    269:   memset(&gen_cartinfo, 0, sizeof(gen_cartinfo));
                    270:   gen_nicetext(gen_cartinfo.console, (char *)(cpu68k_rom+0x100), 16);
                    271:   gen_nicetext(gen_cartinfo.copyright, (char *)(cpu68k_rom+0x110), 16);
                    272:   gen_nicetext(gen_cartinfo.name_domestic, (char *)(cpu68k_rom+0x120), 48);
                    273:   gen_nicetext(gen_cartinfo.name_overseas, (char *)(cpu68k_rom+0x150), 48);
                    274:   if (cpu68k_rom[0x180] == 'G' && cpu68k_rom[0x181] == 'M') {
                    275:     gen_cartinfo.prodtype = pt_game;
                    276:   } else if (cpu68k_rom[0x180] == 'A' && cpu68k_rom[0x181] == 'I') {
                    277:     gen_cartinfo.prodtype = pt_education;
                    278:   } else {
                    279:     gen_cartinfo.prodtype = pt_unknown;
                    280:   }
                    281:   gen_nicetext(gen_cartinfo.version, (char *)(cpu68k_rom+0x182), 12);
                    282:   gen_cartinfo.checksum = gen_checksum(((uint8 *)cpu68k_rom)+0x200,
                    283:                                       cpu68k_romlen-0x200);
                    284:   gen_nicetext(gen_cartinfo.memo, (char *)(cpu68k_rom+0x1C8), 28);
                    285:   for (i = 0x1f0; i < 0x1ff; i++) {
                    286:     if (cpu68k_rom[i] == 'J')
                    287:       gen_cartinfo.flag_japan = 1;
                    288:     if (cpu68k_rom[i] == 'U')
                    289:       gen_cartinfo.flag_usa = 1;
                    290:     if (cpu68k_rom[i] == 'E')
                    291:       gen_cartinfo.flag_europe = 1;
                    292:   }
                    293:   if (cpu68k_rom[0x1f0] >= '1' && cpu68k_rom[0x1f0] <= '9') {
                    294:     gen_cartinfo.hardware = cpu68k_rom[0x1f0] - '0';
                    295:   } else if (cpu68k_rom[0x1f0] >= 'A' && cpu68k_rom[0x1f0] <= 'F') {
                    296:     gen_cartinfo.hardware = cpu68k_rom[0x1f0] - 'A' + 10;
                    297:   }
                    298:   p = gen_cartinfo.country;
                    299:   for (i = 0x1f0; i < 0x200; i++) {
                    300:     if (cpu68k_rom[i] != 0 && cpu68k_rom[i] != 32)
                    301:       *p++ = cpu68k_rom[i];
                    302:   }
                    303:   *p = '\0';
                    304: 
                    305:   ui_setinfo(&gen_cartinfo);
                    306: 
                    307:   if (gen_cartinfo.checksum != (cpu68k_rom[0x18e]<<8 | cpu68k_rom[0x18f]))
                    308:     LOG_REQUEST(("Warning: Checksum does not match in ROM (%04X)",
                    309:                  (cpu68k_rom[0x18e]<<8 | cpu68k_rom[0x18f])));
                    310: 
                    311:   vdp_pal = (!gen_cartinfo.flag_usa && !gen_cartinfo.flag_japan &&
                    312:             gen_cartinfo.flag_europe) ? 1 : 0;
                    313: 
                    314:   LOG_REQUEST(("Loaded '%s'/'%s' (%s %04X %s)", gen_cartinfo.name_domestic,
                    315:               gen_cartinfo.name_overseas, gen_cartinfo.version,
                    316:               gen_cartinfo.checksum, gen_cartinfo.country));
                    317: 
                    318:   return NULL;
                    319: }
                    320: 
                    321: /*** get_nicetext - take a string, remove spaces and capitalise ***/
                    322: 
                    323: void gen_nicetext(char *out, char *in, unsigned int size)
                    324: {
                    325:   int flag, i;
                    326:   char c;
                    327:   char *start = out;
                    328: 
                    329:   flag = 0; /* set if within word, e.g. make lowercase */
                    330:   i = size; /* maximum number of chars in input*/
                    331:   while ((c = *in++) && i--) {
                    332:     if (isalpha((int)c)) {
                    333:       if (!flag) {
                    334:         /* make uppercase */
                    335:        flag = 1;
                    336:        if (islower((int)c)) {
                    337:          *out++ = c - 'z'-'Z';
                    338:        } else {
                    339:          *out++ = c;
                    340:        }
                    341:       } else {
                    342:        /* make lowercase */
                    343:        if (isupper((int)c)) {
                    344:          *out++ = (c) + 'z'-'Z';
                    345:        } else {
                    346:          *out++ = c;
                    347:        }
                    348:       }
                    349:       continue;
                    350:     }
                    351:     if (c == ' ' && !flag) {
                    352:        continue;
                    353:     }
                    354:     *out++ = c;
                    355:     flag = 0;
                    356:   }
                    357:   if (out > start && out[-1] == ' ')
                    358:     out--;
                    359:   *out++ = '\0';
                    360: }
                    361: 
                    362: /*** gen_checksum - get Genesis-style checksum of memory block ***/
                    363: 
                    364: uint16 gen_checksum(uint8 *start, unsigned int length)
                    365: {
                    366:   uint16 checksum = 0;
                    367: 
                    368:   if (length & 1) {
                    369:     length&= ~1;
                    370:     LOG_CRITICAL(("checksum routines given odd length (%d)", length));
                    371:   }
                    372: 
                    373:   for (; length; length-= 2, start+= 2) {
                    374:     checksum+= start[0]<<8;
                    375:     checksum+= start[1];
                    376:   }
                    377:   return checksum;
                    378: }
                    379: 
                    380: /*** gen_loadsavepos - load saved position ***/
                    381: 
                    382: char *gen_loadsavepos(const char *filename)
                    383: {
                    384:   LOG_REQUEST(("gen_loadsavepos: %s\n", filename));
                    385:   return("Not implemented.");
                    386: }

unix.superglobalmegacorp.com

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