int main(int argc, const char *argv[]) { ez::ezOptionParser opt; opt.overview = "GenEmu -- Sega Genesis Emulator"; opt.syntax = "genemu [OPTIONS] rom"; opt.add("",0,0,0,"Display usage instructions.", "-h", "--help"); opt.add("",0,-1,',',"Apply Game Genie codes [format=ABCD-EFGH]", "--gamegenie", "--gg"); opt.add("",0,1,0,"Force console type [accepted values: PAL or NTSC]", "--mode", "--type"); opt.add("",0,-1,',',"Make screenshots on the specified frames and exit", "--screenshots"); opt.add("",0,1,0,"Load from saved state", "--load"); opt.parse(argc, argv); if (opt.isSet("-h")) { std::string usage; opt.getUsage(usage, 120); std::cout << usage; return 0; } std::vector<std::string*> args; if (opt.firstArgs.size() >= 2) { strcpy(romname, opt.firstArgs[1]->c_str()); } else if (opt.lastArgs.size() >= 1) strcpy(romname, opt.lastArgs[0]->c_str()); else { std::cerr << "ERROR: no ROM specified\n"; return 2; } int romsize; if (strstr(romname, ".smd")) romsize = load_smd(romname); else romsize = load_bin(romname); mem_init(romsize); #if 0 uint16_t checksum = 0; for (int i=0;i<(romsize-512)/2;i++) checksum += m68k_read_memory_16(512+i*2); assert(checksum == m68k_read_memory_16(0x18e)); #endif #if 1 char buf[256]; int pc = 0; strcpy(buf, argv[1]); strcat(buf, ".asm"); FILE *f = fopen(buf, "w"); while (pc < romsize) { int oplen = m68k_disassemble(buf, pc, M68K_CPU_TYPE_68000); fprintf(f, "%06x\t%s\n", pc, buf); pc += oplen; } fclose(f); #endif if (opt.isSet("--mode")) { std::string mode; opt.get("--mode")->getString(mode); if (mode == "PAL") { VERSION_PAL = 1; std::cerr << "Forced mode: PAL\n"; } else if (mode == "NTSC") { VERSION_PAL = 0; std::cerr << "Forced mode: NTSC\n"; } else { std::cerr << "ERROR: invalid mode: " << mode << std::endl; return 2; } } std::vector<int> ss_frames; int ss_idx = 0; hw_init(YM2612_FREQ, VERSION_PAL ? 50 : 60); if (!opt.isSet("--screenshots")) { hw_enable_video(true); hw_enable_audio(true); gfx_enable(true); } else { opt.get("--screenshots")->getInts(ss_frames); } CPU_M68K.init(); CPU_Z80.init(); MASTER_CLOCK = 0; CPU_M68K.reset(); VDP.reset(); if (opt.isSet("--load")) { std::string sn; opt.get("--load")->getString(sn); loadstate(sn.c_str()); } while (hw_poll()) { if (ss_idx < ss_frames.size() && framecounter == ss_frames[ss_idx]) { gfx_enable(true); } int numscanlines = VDP.num_scanlines(); uint8_t *screen; int pitch; hw_beginframe(&screen, &pitch); int16_t *audio; int nsamples; hw_beginaudio(&audio, &nsamples); int audio_index = 0; int audio_step = (nsamples << 16) / numscanlines; for (int sl=0;sl<numscanlines;++sl) { CPU_M68K.run(MASTER_CLOCK + VDP_CYCLES_PER_LINE); CPU_Z80 .run(MASTER_CLOCK + VDP_CYCLES_PER_LINE); vdp_scanline(screen); screen += pitch; int prev_index = audio_index; audio_index += audio_step; YM2612Update(audio + ((prev_index+0x8000)>>16)*2, (audio_index-prev_index+0x8000)>>16); MASTER_CLOCK += VDP_CYCLES_PER_LINE; } hw_endaudio(); hw_endframe(); if (framecounter == 100 && opt.isSet("--gamegenie")) { std::vector<std::string> codes; opt.get("--gamegenie")->getStrings(codes); for (int i=0;i<codes.size();++i) mem_apply_gamegenie(codes[i].c_str()); } if (ss_idx < ss_frames.size() && framecounter == ss_frames[ss_idx]) { static char ssname[2048]; sprintf(ssname, "%s.%d.%s.bmp", romname, framecounter, (VERSION_PAL ? "PAL" : "NTSC")); std::cerr << "Saving screenshot " << ssname << std::endl; hw_save_screenshot(ssname); sprintf(ssname, "%s.%d.%s.gs", romname, framecounter, (VERSION_PAL ? "PAL" : "NTSC")); savestate(ssname); ++ss_idx; if (ss_idx == ss_frames.size()) break; } ++framecounter; state_poll(); } #if 0 checksum = 0; for (int i=0;i<(romsize-512)/2;i++) checksum += m68k_read_memory_16(512+i*2); assert(checksum == m68k_read_memory_16(0x18e)); #endif #if 0 { char buf[256]; int pc = 0xffffee00; FILE *f = fopen(buf, "w"); while (pc <= 0xffffef00) { int oplen = m68k_disassemble(buf, pc, M68K_CPU_TYPE_68000); fprintf(stdout, "%06x\t%s\n", pc, buf); pc += oplen; } fclose(f); } #endif return 0; }
unsigned int m68k_read_disassembler_16(unsigned int address) { return m68k_read_memory_16(address); }