enum media_type_e PicoLoadMedia(const char *filename, const char *carthw_cfg_fname, const char *(*get_bios_filename)(int *region, const char *cd_fname), void (*do_region_override)(const char *media_filename)) { const char *rom_fname = filename; enum media_type_e media_type; enum cd_img_type cd_img_type = CIT_NOT_CD; unsigned char *rom_data = NULL; unsigned int rom_size = 0; pm_file *rom = NULL; int cd_region = 0; int ret; media_type = detect_media(filename); if (media_type == PM_BAD_DETECT) goto out; if ((PicoAHW & PAHW_MCD) && Pico_mcd != NULL) cdd_unload(); PicoCartUnload(); PicoAHW = 0; PicoQuirks = 0; if (media_type == PM_CD) { // check for MegaCD image cd_img_type = PicoCdCheck(filename, &cd_region); if ((int)cd_img_type >= 0 && cd_img_type != CIT_NOT_CD) { // valid CD image, ask frontend for BIOS.. rom_fname = NULL; if (get_bios_filename != NULL) rom_fname = get_bios_filename(&cd_region, filename); if (rom_fname == NULL) { media_type = PM_BAD_CD_NO_BIOS; goto out; } PicoAHW |= PAHW_MCD; } else { media_type = PM_BAD_CD; goto out; } } else if (media_type == PM_MARK3) { lprintf("detected SMS ROM\n"); PicoAHW = PAHW_SMS; } rom = pm_open(rom_fname); if (rom == NULL) { lprintf("Failed to open ROM\n"); media_type = PM_ERROR; goto out; } ret = PicoCartLoad(rom, &rom_data, &rom_size, (PicoAHW & PAHW_SMS) ? 1 : 0); pm_close(rom); if (ret != 0) { if (ret == 2) lprintf("Out of memory\n"); else if (ret == 3) lprintf("Read failed\n"); else lprintf("PicoCartLoad() failed.\n"); media_type = PM_ERROR; goto out; } // detect wrong files if (strncmp((char *)rom_data, "Pico", 4) == 0) { lprintf("savestate selected?\n"); media_type = PM_BAD_DETECT; goto out; } 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"); media_type = PM_BAD_DETECT; goto out; } } // load config for this ROM (do this before insert to get correct region) if (!(PicoAHW & PAHW_MCD)) { memcpy(media_id_header, rom_data + 0x100, sizeof(media_id_header)); if (do_region_override != NULL) do_region_override(filename); } if (PicoCartInsert(rom_data, rom_size, carthw_cfg_fname)) { media_type = PM_ERROR; goto out; } rom_data = NULL; // now belongs to PicoCart Pico.m.ncart_in = 0; // insert CD if it was detected if (cd_img_type != CIT_NOT_CD) { ret = cdd_load(filename, cd_img_type); if (ret != 0) { PicoCartUnload(); media_type = PM_BAD_CD; goto out; } Pico.m.ncart_in = 1; } if (PicoQuirks & PQUIRK_FORCE_6BTN) PicoSetInputDevice(0, PICO_INPUT_PAD_6BTN); out: if (rom_data) free(rom_data); return media_type; }
int cdd_load(const char *filename, int type) { char header[0x210]; int ret; /* first unmount any loaded disc */ cdd_unload(); /* genplus parses cue here, in PD we use our own parser */ ret = load_cd_image(filename, &type); if (ret != 0) return ret; /* read first 16 bytes */ pm_read(header, 0x10, cdd.toc.tracks[0].fd); /* look for valid CD image ID string */ if (memcmp("SEGADISCSYSTEM", header, 14)) { /* if not found, read next 16 bytes */ pm_read(header, 0x10, cdd.toc.tracks[0].fd); /* look again for valid CD image ID string */ if (memcmp("SEGADISCSYSTEM", header, 14)) { elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?"); /* assume bin without security code */ } /* BIN format (2352 bytes data blocks) */ cdd.sectorSize = 2352; } else { /* ISO format (2048 bytes data blocks) */ cdd.sectorSize = 2048; } ret = (type == CT_BIN) ? 2352 : 2048; if (ret != cdd.sectorSize) elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch"); /* read CD image header + security code */ pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd); /* Simulate audio tracks if none found */ if (cdd.toc.last == 1) { /* Some games require exact TOC infos */ if (strstr(header + 0x180,"T-95035") != NULL) { /* Snatcher */ cdd.toc.last = cdd.toc.end = 0; do { cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last]; cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; cdd.toc.last++; } while (cdd.toc.last < 21); } else if (strstr(header + 0x180,"T-127015") != NULL) { /* Lunar - The Silver Star */ cdd.toc.last = cdd.toc.end = 0; do { cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last]; cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; cdd.toc.last++; } while (cdd.toc.last < 52); } else if (strstr(header + 0x180,"T-113045") != NULL) { /* Shadow of the Beast II */ cdd.toc.last = cdd.toc.end = 0; do { cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last]; cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; cdd.toc.last++; } while (cdd.toc.last < 15); } else if (strstr(header + 0x180,"T-143025") != NULL) { /* Dungeon Explorer */ cdd.toc.last = cdd.toc.end = 0; do { cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last]; cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; cdd.toc.last++; } while (cdd.toc.last < 13); } else if (strstr(header + 0x180,"MK-4410") != NULL) { /* Final Fight CD (USA, Europe) */ cdd.toc.last = cdd.toc.end = 0; do { cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last]; cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; cdd.toc.last++; } while (cdd.toc.last < 26); } else if (strstr(header + 0x180,"G-6013") != NULL) { /* Final Fight CD (Japan) */ cdd.toc.last = cdd.toc.end = 0; do { cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last]; cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; cdd.toc.last++; } while (cdd.toc.last < 29); } #if 0 else { /* default TOC (99 tracks & 2s per audio tracks) */ do { cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75; cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75; cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; cdd.toc.last++; } while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75)); } #endif } /* Lead-out */ cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; /* CD loaded */ cdd.loaded = 1; /* disc not scanned yet */ cdd.status = NO_DISC; return 0; }