|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.