X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=common%2Femu.c;h=4a95a3fff8bacf5edc7354a400699b69f1845720;hb=ab8a8d36598061ddae8741c6585fbaa3e257c037;hp=88d80b7e9c742bdeb00b826e0281114c7e8df70b;hpb=7a5f9593629010d1cc9e7f9046aad0654412479e;p=libpicofe.git diff --git a/common/emu.c b/common/emu.c index 88d80b7..4a95a3f 100644 --- a/common/emu.c +++ b/common/emu.c @@ -174,8 +174,7 @@ static int emu_isBios(const char *name) static unsigned char id_header[0x100]; -/* checks if fname points to valid MegaCD image - * if so, checks for suitable BIOS */ +/* checks if fname points to valid MegaCD image */ static int emu_cd_check(int *pregion, const char *fname_in) { const char *fname = fname_in; @@ -243,6 +242,96 @@ static int emu_cd_check(int *pregion, const char *fname_in) return type; } +static int detect_media(const char *fname) +{ + static const short sms_offsets[] = { 0x7ff0, 0x3ff0, 0x1ff0 }; + static const char *sms_exts[] = { "sms", "gg", "sg" }; + static const char *md_exts[] = { "gen", "bin", "smd" }; + char buff0[32], buff[32]; + unsigned short *d16; + pm_file *pmf; + char ext[5]; + int i; + + get_ext(fname, ext); + + // detect wrong extensions + if (!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) // s.gz ~ .mds.gz + return PM_BAD; + + /* don't believe in extensions, except .cue */ + if (strcasecmp(ext, ".cue") == 0) + return PM_CD; + + pmf = pm_open(fname); + if (pmf == NULL) + return PM_BAD; + + if (pm_read(buff0, 32, pmf) != 32) { + pm_close(pmf); + return PM_BAD; + } + + if (strncasecmp("SEGADISCSYSTEM", buff0 + 0x00, 14) == 0 || + strncasecmp("SEGADISCSYSTEM", buff0 + 0x10, 14) == 0) { + pm_close(pmf); + return PM_CD; + } + + /* check for SMD evil */ + if (pmf->size >= 0x4200 && (pmf->size & 0x3fff) == 0x200) { + if (pm_seek(pmf, sms_offsets[0] + 0x200, SEEK_SET) == sms_offsets[0] + 0x200 && + pm_read(buff, 16, pmf) == 16 && + strncmp("TMR SEGA", buff, 8) == 0) + goto looks_like_sms; + + /* could parse further but don't bother */ + goto extension_check; + } + + /* MD header? Act as TMSS BIOS here */ + if (pm_seek(pmf, 0x100, SEEK_SET) == 0x100 && pm_read(buff, 16, pmf) == 16) { + if (strncmp(buff, "SEGA", 4) == 0 || strncmp(buff, " SEG", 4) == 0) + goto looks_like_md; + } + + for (i = 0; i < array_size(sms_offsets); i++) { + if (pm_seek(pmf, sms_offsets[i], SEEK_SET) != sms_offsets[i]) + continue; + + if (pm_read(buff, 16, pmf) != 16) + continue; + + if (strncmp("TMR SEGA", buff, 8) == 0) + goto looks_like_sms; + } + +extension_check: + /* probably some headerless thing. Maybe check the extension after all. */ + for (i = 0; i < array_size(md_exts); i++) + if (strcasecmp(pmf->ext, md_exts[i]) == 0) + goto looks_like_md; + + for (i = 0; i < array_size(sms_exts); i++) + if (strcasecmp(pmf->ext, sms_exts[i]) == 0) + goto looks_like_sms; + + /* If everything else fails, make a guess on the reset vector */ + d16 = (unsigned short *)(buff0 + 4); + if ((((d16[0] << 16) | d16[1]) & 0xffffff) >= pmf->size) { + lprintf("bad MD reset vector, assuming SMS\n"); + goto looks_like_sms; + } + +looks_like_md: + pm_close(pmf); + return PM_MD_CART; + +looks_like_sms: + pm_close(pmf); + return PM_MARK3; +} + static int extract_text(char *dest, const unsigned char *src, int len, int swab) { char *p = dest; @@ -321,6 +410,7 @@ static void shutdown_MCD(void) } // note: this function might mangle rom_fname +// XXX: portions of this code should move to pico/ int emu_reload_rom(char *rom_fname) { unsigned int rom_size = 0; @@ -328,20 +418,14 @@ int emu_reload_rom(char *rom_fname) unsigned char *rom_data = NULL; char ext[5]; pm_file *rom = NULL; - int ret, cd_state, cd_region, cfg_loaded = 0; + int cd_state = CIT_NOT_CD; + int ret, media_type, cd_region; + int cfg_loaded = 0, bad_rom = 0; lprintf("emu_ReloadRom(%s)\n", rom_fname); get_ext(rom_fname, ext); - // detect wrong extensions - if (!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) { // s.gz ~ .mds.gz - me_update_msg("Not a ROM/CD selected."); - return 0; - } - - PicoPatchUnload(); - // check for movie file if (movie_data) { free(movie_data); @@ -396,46 +480,54 @@ int emu_reload_rom(char *rom_fname) get_ext(rom_fname, ext); } + media_type = detect_media(rom_fname); + if (media_type == PM_BAD) { + me_update_msg("Not a ROM/CD img selected."); + return 0; + } + shutdown_MCD(); + PicoPatchUnload(); + PicoAHW = 0; - // check for MegaCD image - cd_state = emu_cd_check(&cd_region, rom_fname); - if (cd_state >= 0 && cd_state != CIT_NOT_CD) + if (media_type == PM_CD) { - PicoAHW |= PAHW_MCD; - // valid CD image, check for BIOS.. + // check for MegaCD image + cd_state = emu_cd_check(&cd_region, rom_fname); + if (cd_state >= 0 && cd_state != CIT_NOT_CD) + { + // valid CD image, check for BIOS.. - // we need to have config loaded at this point - ret = emu_read_config(1, 0); - if (!ret) emu_read_config(0, 0); - cfg_loaded = 1; + // we need to have config loaded at this point + ret = emu_read_config(1, 0); + if (!ret) emu_read_config(0, 0); + cfg_loaded = 1; + + if (PicoRegionOverride) { + cd_region = PicoRegionOverride; + lprintf("override region to %s\n", cd_region != 4 ? + (cd_region == 8 ? "EU" : "JAP") : "USA"); + } + if (!find_bios(cd_region, &used_rom_name)) + return 0; - if (PicoRegionOverride) { - cd_region = PicoRegionOverride; - lprintf("overrided region to %s\n", cd_region != 4 ? (cd_region == 8 ? "EU" : "JAP") : "USA"); + get_ext(used_rom_name, ext); + PicoAHW |= PAHW_MCD; } - if (!find_bios(cd_region, &used_rom_name)) { - PicoAHW &= ~PAHW_MCD; + else { + me_update_msg("Invalid CD image"); return 0; } - - get_ext(used_rom_name, ext); } - else - { - if (PicoAHW & PAHW_MCD) Stop_CD(); - PicoAHW &= ~PAHW_MCD; + else if (media_type == PM_MARK3) { + lprintf("detected SMS ROM\n"); + PicoAHW = PAHW_SMS; } rom = pm_open(used_rom_name); - if (!rom) { - me_update_msg("Failed to open ROM/CD image"); - goto fail; - } - - if (cd_state < 0) { - me_update_msg("Invalid CD image"); - goto fail; + if (rom == NULL) { + me_update_msg("Failed to open ROM"); + return 0; } menu_romload_prepare(used_rom_name); // also CD load @@ -443,21 +535,29 @@ int emu_reload_rom(char *rom_fname) PicoCartUnload(); rom_loaded = 0; - if ( (ret = PicoCartLoad(rom, &rom_data, &rom_size)) ) { + ret = PicoCartLoad(rom, &rom_data, &rom_size, (PicoAHW & PAHW_SMS) ? 1 : 0); + pm_close(rom); + if (ret != 0) { if (ret == 2) me_update_msg("Out of memory"); else if (ret == 3) me_update_msg("Read failed"); else me_update_msg("PicoCartLoad() failed."); - goto fail2; + goto fail; + } + + // detect wrong files + if (strncmp((char *)rom_data, "Pico", 4) == 0) + bad_rom = 1; + else if (!(PicoAHW & PAHW_SMS)) { + unsigned short *d = (unsigned short *)(rom_data + 4); + if ((((d[0] << 16) | d[1]) & 0xffffff) >= (int)rom_size) { + lprintf("bad reset vector\n"); + bad_rom = 1; + } } - pm_close(rom); - rom = NULL; - // detect wrong files (Pico crashes on very small files), also see if ROM EP is good - if (rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 || - ((*(unsigned char *)(rom_data+4)<<16)|(*(unsigned short *)(rom_data+6))) >= (int)rom_size) { - if (rom_data) free(rom_data); - me_update_msg("Not a ROM selected."); - goto fail2; + if (bad_rom) { + me_update_msg("Bad ROM detected."); + goto fail; } // load config for this ROM (do this before insert to get correct region) @@ -468,18 +568,19 @@ int emu_reload_rom(char *rom_fname) if (!ret) emu_read_config(0, 0); } - lprintf("PicoCartInsert(%p, %d);\n", rom_data, rom_size); if (PicoCartInsert(rom_data, rom_size)) { me_update_msg("Failed to load ROM."); - goto fail2; + goto fail; } // insert CD if it was detected if (cd_state != CIT_NOT_CD) { ret = Insert_CD(rom_fname, cd_state); if (ret != 0) { + PicoCartUnload(); + rom_data = NULL; // freed by unload me_update_msg("Insert_CD() failed, invalid CD image?"); - goto fail2; + goto fail; } } @@ -511,8 +612,22 @@ int emu_reload_rom(char *rom_fname) } else { + const char *sys_name, *tv_standard; + int fps; + + if (PicoAHW & PAHW_SMS) { + sys_name = "Master System"; + } else { + sys_name = "MegaDrive"; + if ((Pico.m.hardware&0xc0) == 0x80) + sys_name = "Genesis"; + } + tv_standard = Pico.m.pal ? "PAL" : "NTSC"; + fps = Pico.m.pal ? 50 : 60; + + emu_status_msg("%s %s / %dFPS", tv_standard, sys_name, fps); + PicoOpt &= ~POPT_DIS_VDP_FIFO; - emu_status_msg(Pico.m.pal ? "PAL SYSTEM / 50 FPS" : "NTSC SYSTEM / 60 FPS"); } strncpy(rom_fname_loaded, rom_fname, sizeof(rom_fname_loaded)-1); @@ -525,10 +640,10 @@ int emu_reload_rom(char *rom_fname) return 1; -fail2: - menu_romload_end(); fail: - if (rom != NULL) pm_close(rom); + if (rom_data) + free(rom_data); + menu_romload_end(); return 0; } @@ -785,44 +900,53 @@ char *emu_get_save_fname(int load, int is_sram, int slot) if (is_sram) { - romfname_ext(saveFname, (PicoAHW & PAHW_MCD) ? "brm"PATH_SEP : "srm"PATH_SEP, - (PicoAHW & PAHW_MCD) ? ".brm" : ".srm"); - if (load) { - if (try_ropen_file(saveFname)) return saveFname; - // try in current dir.. - romfname_ext(saveFname, NULL, (PicoAHW & PAHW_MCD) ? ".brm" : ".srm"); - if (try_ropen_file(saveFname)) return saveFname; - return NULL; // give up - } + strcpy(ext, (PicoAHW & PAHW_MCD) ? ".brm" : ".srm"); + romfname_ext(saveFname, (PicoAHW & PAHW_MCD) ? "brm"PATH_SEP : "srm"PATH_SEP, ext); + if (!load) + return saveFname; + + if (try_ropen_file(saveFname)) + return saveFname; + + romfname_ext(saveFname, NULL, ext); + if (try_ropen_file(saveFname)) + return saveFname; } else { + const char *ext_main = (currentConfig.EmuOpt & EOPT_GZIP_SAVES) ? ".mds.gz" : ".mds"; + const char *ext_othr = (currentConfig.EmuOpt & EOPT_GZIP_SAVES) ? ".mds" : ".mds.gz"; ext[0] = 0; - if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); - strcat(ext, (currentConfig.EmuOpt & EOPT_GZIP_SAVES) ? ".mds.gz" : ".mds"); + if (slot > 0 && slot < 10) + sprintf(ext, ".%i", slot); + strcat(ext, ext_main); + + if (!load) { + romfname_ext(saveFname, "mds" PATH_SEP, ext); + return saveFname; + } + else { + romfname_ext(saveFname, "mds" PATH_SEP, ext); + if (try_ropen_file(saveFname)) + return saveFname; - romfname_ext(saveFname, "mds" PATH_SEP, ext); - if (load) { - if (try_ropen_file(saveFname)) return saveFname; romfname_ext(saveFname, NULL, ext); - if (try_ropen_file(saveFname)) return saveFname; - // no gzipped states, search for non-gzipped - if (currentConfig.EmuOpt & EOPT_GZIP_SAVES) - { - ext[0] = 0; - if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); - strcat(ext, ".mds"); - - romfname_ext(saveFname, "mds"PATH_SEP, ext); - if (try_ropen_file(saveFname)) return saveFname; - romfname_ext(saveFname, NULL, ext); - if (try_ropen_file(saveFname)) return saveFname; - } - return NULL; + if (try_ropen_file(saveFname)) + return saveFname; + + // try the other ext + ext[0] = 0; + if (slot > 0 && slot < 10) + sprintf(ext, ".%i", slot); + strcat(ext, ext_othr); + + romfname_ext(saveFname, "mds"PATH_SEP, ext); + if (try_ropen_file(saveFname)) + return saveFname; } } - return saveFname; + return NULL; } int emu_check_save_file(int slot) @@ -1208,7 +1332,7 @@ void emu_loop(void) { int pframes_done; /* "period" frames, used for sync */ int frames_done, frames_shown; /* actual frames for fps counter */ - int oldmodes, target_fps, target_frametime; + int target_fps, target_frametime; unsigned int timestamp_base = 0, timestamp_fps; char *notice_msg = NULL; char fpsbuff[24]; @@ -1217,8 +1341,8 @@ void emu_loop(void) fpsbuff[0] = 0; /* make sure we are in correct mode */ - oldmodes = ((Pico.video.reg[12]&1)<<2) ^ 0xc; Pico.m.dirtyPal = 1; + rendstatus_old = -1; /* number of ticks per frame */ if (Pico.m.pal) { @@ -1247,7 +1371,6 @@ void emu_loop(void) { unsigned int timestamp; int diff, diff_lim; - int modes; timestamp = get_ticks(); if (reset_timing) { @@ -1274,13 +1397,6 @@ void emu_loop(void) } } - // check for mode changes - modes = ((Pico.video.reg[12]&1)<<2) | (Pico.video.reg[1]&8); - if (modes != oldmodes) { - oldmodes = modes; - pemu_video_mode_change(!(modes & 4), (modes & 8)); - } - // second changed? if (timestamp - timestamp_fps >= ms_to_ticks(1000)) {