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