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