void xegs_cart_slot_device::get_default_card_software(std::string &result) { if (open_image_file(mconfig().options())) { const char *slot_string = "xegs"; dynamic_buffer head(0x10); UINT32 len = core_fsize(m_file); int type = A800_8K; // check whether there is an header, to identify the cart type if ((len % 0x1000) == 0x10) { core_fread(m_file, &head[0], 0x10); type = identify_cart_type(&head[0]); } if (type != A800_XEGS) { osd_printf_info("This game is not designed for XEGS. "); if (type >= A5200_4K) osd_printf_info("You might want to run it in A5200.\n"); else osd_printf_info("You might want to run it in A800 or A800XL.\n"); } slot_string = a800_get_slot(type); clear(); result.assign(slot_string); } else software_get_default_slot(result, "xegs"); }
void media_identifier::print_results(std::vector<file_info> const &info) { for (file_info const &file : info) { osd_printf_info("%-20s", core_filename_extract_base(file.name()).c_str()); if (file.matches().empty()) { osd_printf_info("NO MATCH\n"); } else { bool first = true; m_matches++; for (match_data const &match : file.matches()) { if (!first) osd_printf_info("%-20s", ""); first = false; osd_printf_info( "= %s%-20s %-10s %s%s\n", match.bad() ? "(BAD) " : "", match.romname().c_str(), match.shortname().c_str(), match.fullname().c_str(), match.device() ? " (device)" : ""); } } } }
std::string xegs_cart_slot_device::get_default_card_software() { if (open_image_file(mconfig().options())) { const char *slot_string; std::vector<uint8_t> head(0x10); uint32_t len = m_file->size(); int type = A800_8K; // check whether there is an header, to identify the cart type if ((len % 0x1000) == 0x10) { m_file->read(&head[0], 0x10); type = identify_cart_type(&head[0]); } if (type != A800_XEGS) { osd_printf_info("This game is not designed for XEGS. "); if (type >= A5200_4K) osd_printf_info("You might want to run it in A5200.\n"); else osd_printf_info("You might want to run it in A800 or A800XL.\n"); } slot_string = a800_get_slot(type); clear(); return std::string(slot_string); } else return software_get_default_slot("xegs"); }
void a5200_cart_slot_device::get_default_card_software(std::string &result) { if (open_image_file(mconfig().options())) { const char *slot_string = "a5200"; dynamic_buffer head(0x10); UINT32 len = core_fsize(m_file); int type = A5200_8K; // check whether there is an header, to identify the cart type if ((len % 0x1000) == 0x10) { core_fread(m_file, &head[0], 0x10); type = identify_cart_type(&head[0]); std::string info; if (hashfile_extrainfo(*this, info) && info.compare("A13MIRRORING")==0) type = A5200_16K_2CHIPS; } if (type < A5200_4K) osd_printf_info("This game is not designed for A5200. You might want to run it in A800 or A800XL.\n"); slot_string = a800_get_slot(type); clear(); result.assign(slot_string); } else software_get_default_slot(result, "a5200"); }
std::string a800_cart_slot_device::get_default_card_software() { if (open_image_file(mconfig().options())) { const char *slot_string; std::vector<uint8_t> head(0x10); uint32_t len = m_file->size(); int type = A800_8K; // check whether there is an header, to identify the cart type if ((len % 0x1000) == 0x10) { m_file->read(&head[0], 0x10); type = identify_cart_type(&head[0]); } else // otherwise try to guess based on size { if (len == 0x4000) type = A800_16K; if (len == 0x2000) type = A800_8K; } if (type >= A5200_4K) osd_printf_info("This game is not designed for A800. You might want to run it in A5200.\n"); slot_string = a800_get_slot(type); clear(); return std::string(slot_string); } else return software_get_default_slot("a800_8k"); }
std::string a5200_cart_slot_device::get_default_card_software() { if (open_image_file(mconfig().options())) { const char *slot_string; std::vector<uint8_t> head(0x10); uint32_t len = m_file->size(); int type = A5200_8K; // check whether there is an header, to identify the cart type if ((len % 0x1000) == 0x10) { m_file->read(&head[0], 0x10); type = identify_cart_type(&head[0]); } else { std::string info; if (hashfile_extrainfo(*this, info) && info.compare("A13MIRRORING")==0) type = A5200_16K_2CHIPS; } if (type < A5200_4K) osd_printf_info("This game is not designed for A5200. You might want to run it in A800 or A800XL.\n"); slot_string = a800_get_slot(type); clear(); return std::string(slot_string); } else return software_get_default_slot("a5200"); }
void video_manager::exit() { // stop recording any movie for (uint32_t index = 0; index < (std::max)(m_mngs.size(), m_avis.size()); index++) { if (index < m_avis.size()) end_recording_avi(index); if (index < m_mngs.size()) end_recording_mng(index); if (!m_snap_native) break; } // free the snapshot target machine().render().target_free(m_snap_target); m_snap_bitmap.reset(); // print a final result if we have at least 2 seconds' worth of data if (!emulator_info::standalone() && m_overall_emutime.seconds() >= 1) { osd_ticks_t tps = osd_ticks_per_second(); double final_real_time = (double)m_overall_real_seconds + (double)m_overall_real_ticks / (double)tps; double final_emu_time = m_overall_emutime.as_double(); osd_printf_info("Average speed: %.2f%% (%d seconds)\n", 100 * final_emu_time / final_real_time, (m_overall_emutime + attotime(0, ATTOSECONDS_PER_SECOND / 2)).seconds()); } }
void a800_cart_slot_device::get_default_card_software(std::string &result) { if (open_image_file(mconfig().options())) { const char *slot_string = "a800_8k"; dynamic_buffer head(0x10); UINT32 len = core_fsize(m_file); int type = A800_8K; // check whether there is an header, to identify the cart type if ((len % 0x1000) == 0x10) { core_fread(m_file, &head[0], 0x10); type = identify_cart_type(&head[0]); } else // otherwise try to guess based on size { if (len == 0x4000) type = A800_16K; if (len == 0x2000) type = A800_8K; } if (type >= A5200_4K) osd_printf_info("This game is not designed for A800. You might want to run it in A5200.\n"); slot_string = a800_get_slot(type); clear(); result.assign(slot_string); } else software_get_default_slot(result, "a800_8k"); }
bool custom_video_init(char *device_name, char *device_id, modeline *desktop_mode, modeline *user_mode, int method, char *s_param) { memset(&m_backup_mode, 0, sizeof(struct modeline)); memcpy(&m_user_mode, user_mode, sizeof(modeline)); memcpy(m_device_name, device_name, sizeof(m_device_name)); if ((method == CUSTOM_VIDEO_TIMING_POWERSTRIP) && ps_init(ps_monitor_index(m_device_name), &m_backup_mode)) { custom_method = CUSTOM_VIDEO_TIMING_POWERSTRIP; m_backup_mode.type |= CUSTOM_VIDEO_TIMING_POWERSTRIP; // If we have a -ps_timing string defined, use it as user defined modeline memcpy(ps_timing, s_param, sizeof(ps_timing)); custom_video_parse_timing(ps_timing, &m_user_mode); return true; } else { int vendor, device; custom_video_parse_pci_id(device_id, &vendor, &device); if (vendor == 0x1002) // ATI/AMD { if (ati_is_legacy(vendor, device)) { memcpy(m_device_key, s_param, sizeof(m_device_key)); if (ati_init(m_device_name, m_device_key, device_id)) { custom_method = CUSTOM_VIDEO_TIMING_ATI_LEGACY; return true; } } else { if (adl_init()) { custom_method = CUSTOM_VIDEO_TIMING_ATI_ADL; return true; } } } else osd_printf_info("Video chipset is not compatible.\n"); } return false; }
image_init_result vsmile_cart_slot_device::call_load() { if (m_cart) { uint32_t size = loaded_through_softlist() ? get_software_region_length("rom") : length(); if (size > 0x1000000) { seterror(IMAGE_ERROR_UNSPECIFIED, "Attempted loading a cart larger than 16MB"); return image_init_result::FAIL; } m_cart->rom_alloc(size, tag()); uint8_t *rom = (uint8_t *)m_cart->get_rom_base(); if (!loaded_through_softlist()) { fread(rom, size); m_type = VSMILE_STD; } else { const char *pcb_name = get_feature("slot"); memcpy(rom, get_software_region("rom"), size); if (pcb_name) m_type = vsmile_get_pcb_id(pcb_name); osd_printf_info("V.Smile: Detected (XML) %s\n", pcb_name ? pcb_name : "NONE"); } if (m_type == VSMILE_NVRAM) { m_cart->nvram_alloc(0x200000); } if (m_cart->get_nvram_size()) { battery_load(m_cart->get_nvram_base(), m_cart->get_nvram_size(), 0x00); } return image_init_result::PASS; } return image_init_result::PASS; }
/* load snapshot */ QUICKLOAD_LOAD_MEMBER( kc_state,kc) { struct kcc_header *header; uint16_t addr; uint16_t datasize; uint16_t execution_address; uint16_t i; /* get file size */ uint64_t size = image.length(); if (size == 0) return image_init_result::FAIL; std::vector<uint8_t> data(size); image.fread( &data[0], size); header = (struct kcc_header *) &data[0]; addr = (header->load_address_l & 0x0ff) | ((header->load_address_h & 0x0ff)<<8); datasize = ((header->end_address_l & 0x0ff) | ((header->end_address_h & 0x0ff)<<8)) - addr; execution_address = (header->execution_address_l & 0x0ff) | ((header->execution_address_h & 0x0ff)<<8); if (datasize > size - 128) { osd_printf_info("Invalid snapshot size: expected 0x%04x, found 0x%04x\n", datasize, (uint32_t)size - 128); datasize = size - 128; } address_space &space = m_maincpu->space( AS_PROGRAM ); for (i=0; i<datasize; i++) space.write_byte((addr+i) & 0xffff, data[i+128]); if (execution_address != 0 && header->number_addresses >= 3 ) { // if specified, jumps to the quickload start address m_maincpu->set_pc(execution_address); } logerror("Snapshot loaded at: 0x%04x-0x%04x, execution address: 0x%04x\n", addr, addr + datasize - 1, execution_address); return image_init_result::PASS; }
void video_manager::exit() { // stop recording any movie end_recording(MF_AVI); end_recording(MF_MNG); // free the snapshot target machine().render().target_free(m_snap_target); m_snap_bitmap.reset(); // print a final result if we have at least 2 seconds' worth of data if (m_overall_emutime.seconds() >= 1) { osd_ticks_t tps = osd_ticks_per_second(); double final_real_time = (double)m_overall_real_seconds + (double)m_overall_real_ticks / (double)tps; double final_emu_time = m_overall_emutime.as_double(); osd_printf_info("Average speed: %.2f%% (%d seconds)\n", 100 * final_emu_time / final_real_time, (m_overall_emutime + attotime(0, ATTOSECONDS_PER_SECOND / 2)).seconds()); } }
/* load snapshot */ QUICKLOAD_LOAD_MEMBER( kc_state,kc) { struct kcc_header *header; UINT16 addr; UINT16 datasize; UINT16 execution_address; UINT16 i; /* get file size */ UINT64 size = image.length(); if (size == 0) return IMAGE_INIT_FAIL; dynamic_buffer data(size); image.fread( &data[0], size); header = (struct kcc_header *) &data[0]; addr = (header->load_address_l & 0x0ff) | ((header->load_address_h & 0x0ff)<<8); datasize = ((header->end_address_l & 0x0ff) | ((header->end_address_h & 0x0ff)<<8)) - addr; execution_address = (header->execution_address_l & 0x0ff) | ((header->execution_address_h & 0x0ff)<<8); if (datasize > size - 128) { osd_printf_info("Invalid snapshot size: expected 0x%04x, found 0x%04x\n", datasize, (UINT32)size - 128); datasize = size - 128; } address_space &space = m_maincpu->space( AS_PROGRAM ); for (i=0; i<datasize; i++) space.write_byte((addr+i) & 0xffff, data[i+128]); if (execution_address != 0 && header->number_addresses >= 3 ) { // if specified, jumps to the quickload start address m_maincpu->set_pc(execution_address); } logerror("Snapshot loaded at: 0x%04x-0x%04x, execution address: 0x%04x\n", addr, addr + datasize - 1, execution_address); return IMAGE_INIT_PASS; }
void sdl_window_info::measure_fps(int update) { const unsigned long frames_skip4fps = 100; static int64_t lastTime=0, sumdt=0, startTime=0; static unsigned long frames = 0; int64_t currentTime, t0; double dt; double tps; osd_ticks_t tps_t; tps_t = osd_ticks_per_second(); tps = (double) tps_t; t0 = osd_ticks(); renderer().draw(update); frames++; currentTime = osd_ticks(); if(startTime==0||frames==frames_skip4fps) startTime=currentTime; if( frames>=frames_skip4fps ) sumdt+=currentTime-t0; if( (currentTime-lastTime)>1L*osd_ticks_per_second() && frames>frames_skip4fps ) { dt = (double) (currentTime-startTime) / tps; // in decimale sec. osd_printf_info("%6.2lfs, %4lu F, " "avrg game: %5.2lf FPS %.2lf ms/f, " "avrg video: %5.2lf FPS %.2lf ms/f, " "last video: %5.2lf FPS %.2lf ms/f\n", dt, frames-frames_skip4fps, (double)(frames-frames_skip4fps)/dt, // avrg game fps ( (currentTime-startTime) / ((frames-frames_skip4fps)) ) * 1000.0 / osd_ticks_per_second(), (double)(frames-frames_skip4fps)/((double)(sumdt) / tps), // avrg vid fps ( sumdt / ((frames-frames_skip4fps)) ) * 1000.0 / tps, 1.0/((currentTime-t0) / osd_ticks_per_second()), // this vid fps (currentTime-t0) * 1000.0 / tps ); lastTime = currentTime; } }
int a78_cart_slot_device::validate_header(int head, bool log) { switch (head & 0x3d) { case 0x05: if (log) { osd_printf_info("POKEY + RAM at $4000 (Header 0x05)\n"); osd_printf_info("Disabling POKEY\n"); } head &= ~0x01; break; case 0x09: if (log) { osd_printf_info("POKEY + Bank 0 of 144K ROM at $4000 (Header 0x09)\n"); osd_printf_info("Disabling POKEY\n"); } head &= ~0x01; break; case 0x11: if (log) { osd_printf_info("POKEY + Bank 6 ROM at $4000 (Header 0x11)\n"); osd_printf_info("Disabling POKEY\n"); } head &= ~0x01; break; case 0x21: if (log) { osd_printf_info("POKEY + banked RAM at $4000 (Header 0x21)\n"); osd_printf_info("Disabling POKEY\n"); } head &= ~0x01; break; case 0x0c: if (log) { osd_printf_info("RAM + Bank 0 of 144K ROM at $4000 (Header 0x0c)\n"); osd_printf_info("Disabling RAM\n"); } head &= ~0x04; break; case 0x14: if (log) { osd_printf_info("RAM + Bank 6 ROM at $4000 (Header 0x14)\n"); osd_printf_info("Disabling RAM\n"); } head &= ~0x04; break; case 0x24: if (log) { osd_printf_info("RAM + Banked RAM at $4000 (Header 0x24)\n"); osd_printf_info("Disabling RAM\n"); } head &= ~0x04; break; case 0x18: if (log) { osd_printf_info("Bank 0 of 144K ROM + Bank 6 ROM at $4000 (Header 0x18)\n"); osd_printf_info("Disabling Bank 0 ROM\n"); } head &= ~0x08; break; case 0x28: if (log) { osd_printf_info("Bank 0 of 144K ROM + Banked RAM at $4000 (Header 0x28)\n"); osd_printf_info("Disabling Bank 0 ROM\n"); } head &= ~0x08; break; case 0x30: if (log) { osd_printf_info("Bank 6 ROM + banked RAM at $4000 (Header 0x30)\n"); osd_printf_info("Disabling Bank 6 ROM\n"); } head &= ~0x10; break; } if ((head & 0x3c) && !(head & 0x02)) { if (log) { osd_printf_info("SuperCart bankswitch detected at $4000, with no SuperCart bit (Header 0x%X)\n", head); osd_printf_info("Enablig SuperCart bankswitch\n"); } head |= 0x02; } if ((head & 0xff00) == 0x100 && (head & 0xff)) { if (log) { osd_printf_info("Bankswitch detected for an Activision cart (Header 0x%X)\n", head); osd_printf_info("Disabling bankswitch\n"); } head &= 0xff00; } if ((head & 0xff00) == 0x200 && (head & 0xff)) { if (log) { osd_printf_info("Bankswitch detected for an Absolute cart (Header 0x%X)\n", head); osd_printf_info("Disabling bankswitch\n"); } head &= 0xff00; } if ((head & 0xff00) > 0x300) { if (log) { osd_printf_info("Unsupported mapper, please contact MAMEdevs (Header 0x%X)\n", head); osd_printf_info("Disabling special bits\n"); } head &= 0x00ff; } return head; }
virtual void notify(const char *outname, INT32 value) override { osd_printf_info("%s = %d\n", ((outname==nullptr) ? "none" : outname), value); }
bool gba_cart_slot_device::call_load() { if (m_cart) { UINT8 *ROM; UINT32 size = (software_entry() != NULL) ? get_software_region_length("rom") : length(); if (size > 0x2000000) { seterror(IMAGE_ERROR_UNSPECIFIED, "Attempted loading a cart larger than 32MB"); return IMAGE_INIT_FAIL; } m_cart->rom_alloc(size, tag()); ROM = (UINT8 *)m_cart->get_rom_base(); if (software_entry() == NULL) { fread(ROM, size); m_type = get_cart_type(ROM, size); } else { const char *pcb_name = get_feature("slot"); memcpy(ROM, get_software_region("rom"), size); if (pcb_name) m_type = gba_get_pcb_id(pcb_name); //printf("Type: %s\n", gba_get_slot(m_type)); osd_printf_info("GBA: Detected (XML) %s\n", pcb_name ? pcb_name : "NONE"); } if (m_type == GBA_SRAM) m_cart->nvram_alloc(0x10000); // mirror the ROM switch (size) { case 2 * 1024 * 1024: memcpy(ROM + 0x200000, ROM, 0x200000); // intentional fall-through case 4 * 1024 * 1024: memcpy(ROM + 0x400000, ROM, 0x400000); // intentional fall-through case 8 * 1024 * 1024: memcpy(ROM + 0x800000, ROM, 0x800000); // intentional fall-through case 16 * 1024 * 1024: memcpy(ROM + 0x1000000, ROM, 0x1000000); break; } if (m_cart->get_nvram_size()) battery_load(m_cart->get_nvram_base(), m_cart->get_nvram_size(), 0x00); return IMAGE_INIT_PASS; } return IMAGE_INIT_PASS; }
int a800_cart_slot_device::identify_cart_type(uint8_t *header) { int type = A800_8K; // check CART format if (strncmp((const char *)header, "CART", 4)) fatalerror("Invalid header detected!\n"); switch ((header[4] << 24) + (header[5] << 16) + (header[6] << 8) + (header[7] << 0)) { case 1: type = A800_8K; break; case 2: type = A800_16K; break; case 3: type = A800_OSS034M; break; case 8: type = A800_WILLIAMS; break; case 9: type = A800_DIAMOND; break; case 10: type = A800_EXPRESS; break; case 11: type = A800_SPARTADOS; break; case 12: type = A800_XEGS; break; case 15: type = A800_OSSM091; break; case 18: type = A800_BBSB; break; case 21: type = A800_8K_RIGHT; break; case 39: type = A800_PHOENIX; break; case 40: type = A800_BLIZZARD; break; case 44: type = A800_OSS8K; break; case 50: type = A800_TURBO64; break; case 51: type = A800_TURBO128; break; case 52: type = A800_MICROCALC; break; // Atari 5200 CART files case 4: type = A5200_32K; break; case 16: type = A5200_16K; break; case 19: type = A5200_8K; break; case 20: type = A5200_4K; break; case 6: type = A5200_16K_2CHIPS; break; case 7: type = A5200_BBSB; break; default: osd_printf_info("Cart type \"%d\" is currently unsupported.\n", (header[4] << 24) + (header[5] << 16) + (header[6] << 8) + (header[7] << 0)); break; } return type; }
image_init_result device_image_interface::load_internal(const std::string &path, bool is_create, int create_format, util::option_resolution *create_args, bool just_load) { // first unload the image unload(); // clear any possible error messages clear_error(); // we are now loading m_is_loading = true; // record the filename set_image_filename(path); if (core_opens_image_file()) { // determine open plan std::vector<UINT32> open_plan = determine_open_plan(is_create); // attempt to open the file in various ways for (auto iter = open_plan.cbegin(); !m_file && iter != open_plan.cend(); iter++) { // open the file m_err = load_image_by_path(*iter, path); if (m_err && (m_err != IMAGE_ERROR_FILENOTFOUND)) goto done; } // did we fail to find the file? if (!is_loaded()) { m_err = IMAGE_ERROR_FILENOTFOUND; goto done; } } // call device load or create m_create_format = create_format; m_create_args = create_args; if (m_init_phase==false) { m_err = (finish_load() == image_init_result::PASS) ? IMAGE_ERROR_SUCCESS : IMAGE_ERROR_INTERNAL; if (m_err) goto done; } // success! done: if (just_load) { if (m_err) clear(); return m_err ? image_init_result::FAIL : image_init_result::PASS; } if (m_err!=0) { if (!m_init_phase) { if (device().machine().phase() == MACHINE_PHASE_RUNNING) device().popmessage("Error: Unable to %s image '%s': %s", is_create ? "create" : "load", path, error()); else osd_printf_error("Error: Unable to %s image '%s': %s\n", is_create ? "create" : "load", path.c_str(), error()); } clear(); } else { // do we need to reset the CPU? only schedule it if load/create is successful if (!schedule_postload_hard_reset_if_needed()) { if (!m_init_phase) { if (device().machine().phase() == MACHINE_PHASE_RUNNING) device().popmessage("Image '%s' was successfully %s.", path, is_create ? "created" : "loaded"); else osd_printf_info("Image '%s' was successfully %s.\n", path.c_str(), is_create ? "created" : "loaded"); } } } return m_err ? image_init_result::FAIL : image_init_result::PASS; }
image_init_result device_image_interface::load_software(const std::string &software_identifier) { // Prepare to load unload(); clear_error(); m_is_loading = true; // Check if there's a software list defined for this device and use that if we're not creating an image std::string list_name; bool softload = load_software_part(software_identifier, m_software_part_ptr, &list_name); if (!softload) { m_is_loading = false; return image_init_result::FAIL; } // set up softlist stuff m_software_info_ptr = &m_software_part_ptr->info(); m_software_list_name = std::move(list_name); m_full_software_name = m_software_part_ptr->info().shortname(); // specify image name with softlist-derived names m_image_name = m_full_software_name; m_basename = m_full_software_name; m_basename_noext = m_full_software_name; m_filetype = use_software_list_file_extension_for_filetype() && m_mame_file != nullptr ? core_filename_extract_extension(m_mame_file->filename(), true) : ""; // check if image should be read-only const char *read_only = get_feature("read_only"); if (read_only && !strcmp(read_only, "true")) { // Copy some image information when we have been loaded through a software list if (m_software_info_ptr) { // sanitize if (m_software_info_ptr->longname().empty() || m_software_info_ptr->publisher().empty() || m_software_info_ptr->year().empty()) fatalerror("Each entry in an XML list must have all of the following fields: description, publisher, year!\n"); // store m_longname = m_software_info_ptr->longname(); m_manufacturer = m_software_info_ptr->publisher(); m_year = m_software_info_ptr->year(); // set file type std::string filename = (m_mame_file != nullptr) && (m_mame_file->filename() != nullptr) ? m_mame_file->filename() : ""; m_filetype = core_filename_extract_extension(filename, true); } } // call finish_load if necessary if (m_init_phase == false && (finish_load() != image_init_result::PASS)) return image_init_result::FAIL; // do we need to reset the CPU? only schedule it if load is successful if (!schedule_postload_hard_reset_if_needed()) { if (!m_init_phase) { if (device().machine().phase() == MACHINE_PHASE_RUNNING) device().popmessage("Image '%s' was successfully loaded.", software_identifier); else osd_printf_info("Image '%s' was successfully loaded.\n", software_identifier.c_str()); } } return image_init_result::PASS; }
int gba_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len) { uint32_t chip = 0; int type = GBA_STD; bool has_rtc = false; bool has_rumble = false; // first detect nvram type based on strings inside the file for (int i = 0; i < len; i++) { if ((i<len-8) && !memcmp(&ROM[i], "EEPROM_V", 8)) chip |= GBA_CHIP_EEPROM; // should be either GBA_CHIP_EEPROM_4K or GBA_CHIP_EEPROM_64K, but it is not yet possible to automatically detect which one else if (((i<len-6) && !memcmp(&ROM[i], "SRAM_V", 6)) || ((i<len-8) && !memcmp(&ROM[i], "SRAM_F_V", 8))) // || ((i<len-11) && !memcmp(&data[i], "ADVANCEWARS", 11))) //advance wars 1 & 2 has SRAM, but no "SRAM_" string can be found inside the ROM space chip |= GBA_CHIP_SRAM; else if ((i<len-9) && !memcmp(&ROM[i], "FLASH1M_V", 9)) chip |= GBA_CHIP_FLASH_1M; else if ((i<len-10) && !memcmp(&ROM[i], "FLASH512_V", 10)) chip |= GBA_CHIP_FLASH_512; else if ((i<len-7) && !memcmp(&ROM[i], "FLASH_V", 7)) chip |= GBA_CHIP_FLASH; else if ((i<len-8) && !memcmp(&ROM[i], "SIIRTC_V", 8)) chip |= GBA_CHIP_RTC; } osd_printf_info("GBA: Detected (ROM) %s\n", gba_chip_string(chip).c_str()); // fix for games which return more than one kind of chip: either it is one of the known titles, or we default to no battery if (gba_chip_has_conflict(chip)) { char game_code[5] = { 0 }; bool resolved = false; if (len >= 0xac + 4) memcpy(game_code, ROM + 0xac, 4); osd_printf_info("GBA: Game Code \"%s\"\n", game_code); chip &= ~(GBA_CHIP_EEPROM | GBA_CHIP_EEPROM_4K | GBA_CHIP_EEPROM_64K | GBA_CHIP_FLASH | GBA_CHIP_FLASH_1M | GBA_CHIP_FLASH_512 | GBA_CHIP_SRAM); // search if it is one of the known titles with NVRAM conflicts for (auto & elem : gba_chip_fix_conflict_list) { const gba_chip_fix_conflict_item *item = &elem; if (!strcmp(game_code, item->game_code)) { chip |= item->chip; resolved = true; break; } } if (!resolved) osd_printf_warning("GBA: NVRAM is disabled because multiple NVRAM chips were detected!\n"); } // fix for games which are known to require an eeprom with 14-bit addressing (64 kbit) if (chip & GBA_CHIP_EEPROM) { char game_code[5] = { 0 }; if (len >= 0xac + 4) memcpy(game_code, ROM + 0xac, 4); osd_printf_info("GBA: Game Code \"%s\"\n", game_code); for (auto & elem : gba_chip_fix_eeprom_list) { const gba_chip_fix_item *item = &elem; if (!strcmp(game_code, item->game_code)) { chip = (chip & ~GBA_CHIP_EEPROM) | GBA_CHIP_EEPROM_64K; break; } } for (auto & elem : gba_chip_fix_rumble_list) { const gba_chip_fix_item *item = &elem; if (!strcmp(game_code, item->game_code)) { has_rumble = true; break; } } } if (chip & GBA_CHIP_RTC) { //osd_printf_info("game has RTC - not emulated at the moment\n"); chip &= ~GBA_CHIP_RTC; has_rtc = true; } osd_printf_info("GBA: Emulate %s\n", gba_chip_string(chip).c_str()); switch (chip) { case GBA_CHIP_SRAM: type = GBA_SRAM; break; case GBA_CHIP_EEPROM: type = GBA_EEPROM; if (has_rumble) type = GBA_YOSHIUG; break; case GBA_CHIP_EEPROM_4K: type = GBA_EEPROM4; break; case GBA_CHIP_EEPROM_64K: type = GBA_EEPROM64; if (has_rtc) type = GBA_BOKTAI; break; case GBA_CHIP_FLASH: type = GBA_FLASH; if (has_rtc) type = GBA_FLASH_RTC; break; case GBA_CHIP_FLASH_512: type = GBA_FLASH512; break; case GBA_CHIP_FLASH_1M: type = GBA_FLASH1M; if (has_rtc) type = GBA_FLASH1M_RTC; break; default: break; } if (len == 0x4000000) type = GBA_3DMATRIX; return type; }
image_init_result gba_cart_slot_device::call_load() { if (m_cart) { uint8_t *ROM; uint32_t size = loaded_through_softlist() ? get_software_region_length("rom") : length(); if (size > 0x4000000) { seterror(IMAGE_ERROR_UNSPECIFIED, "Attempted loading a cart larger than 64MB"); return image_init_result::FAIL; } m_cart->rom_alloc(size, tag()); ROM = (uint8_t *)m_cart->get_rom_base(); if (!loaded_through_softlist()) { fread(ROM, size); m_type = get_cart_type(ROM, size); } else { const char *pcb_name = get_feature("slot"); memcpy(ROM, get_software_region("rom"), size); if (pcb_name) m_type = gba_get_pcb_id(pcb_name); //printf("Type: %s\n", gba_get_slot(m_type)); osd_printf_info("GBA: Detected (XML) %s\n", pcb_name ? pcb_name : "NONE"); } if (m_type == GBA_SRAM || m_type == GBA_DRILLDOZ || m_type == GBA_WARIOTWS) m_cart->nvram_alloc(0x10000); // mirror the ROM switch (size) { case 2 * 1024 * 1024: memcpy(ROM + 0x200000, ROM, 0x200000); // intentional fall-through case 4 * 1024 * 1024: memcpy(ROM + 0x400000, ROM, 0x400000); // intentional fall-through case 8 * 1024 * 1024: memcpy(ROM + 0x800000, ROM, 0x800000); // intentional fall-through case 16 * 1024 * 1024: memcpy(ROM + 0x1000000, ROM, 0x1000000); break; } if (size == 0x4000000) { memcpy((uint8_t *)m_cart->get_romhlp_base(), ROM, 0x2000000); for (uint32_t i = 0; i < 16; i++) { memcpy((uint8_t *)m_cart->get_romhlp_base() + i * 0x1000, ROM + 0x200, 0x1000); } memcpy((uint8_t *)m_cart->get_romhlp_base(), ROM, 0x180); } if (m_cart->get_nvram_size()) battery_load(m_cart->get_nvram_base(), m_cart->get_nvram_size(), 0x00); return image_init_result::PASS; } return image_init_result::PASS; }
void avi_write::stop() { osd_printf_info("Stopping AVI recording after %d frames.\n", m_frame); end_avi_recording(); }
bool ti99_floppy_format::save(io_generic *io, floppy_image *image) { int act_track_size = 0; UINT8 bitstream[500000/8]; UINT8 trackdata[9216]; // max size int cellsizes[] = { 2000, 4000, 1000, 2000 }; // Do we use double-stepping? // If our image was loaded into a 80-track drive, we will always write 80 tracks. int maxtrack, maxheads; image->get_maximal_geometry(maxtrack, maxheads); if (maxtrack > 80) maxtrack = 80; else { if (maxtrack > 35 && maxtrack < 80) maxtrack = 40; else maxtrack = 35; } int attempt = 0; int sector[36]; int maxsect = 18; bool write = true; // We expect a bitstream of length 50000 for FM and 100000 for MFM for(int head=0; head < 2; head++) { int track = 0; while (track < maxtrack) { int cell_size = cellsizes[attempt]; int encoding = get_encoding(cell_size); int track_size = get_track_size(cell_size, 36); // max number of sectors // Retrieve the cells from the flux sequence generate_bitstream_from_track(track, head, cell_size, bitstream, act_track_size, image); // Maybe the track has become longer due to moving splices if (act_track_size > 200000000/cell_size) act_track_size = 200000000/cell_size; int marks = decode_bitstream(bitstream, trackdata, sector, act_track_size, encoding, (encoding==floppy_image::FM)? 0xff:0x4e, track_size); if (track==0) { if (head==0) { // Find the highest sector in the track // This is only needed for the SDF format int i=35; while (i>=0 && sector[i]==-1) i--; if (i>18) maxsect = 36; else { if (i>16) maxsect = 18; else { if (i>9) maxsect = 16; else maxsect = 9; } } if (TRACE) osd_printf_info("ti99_dsk: Sectors/track: %d\n", maxsect); // We try different cell sizes until we find a fitting size. // If this fails, we fall back to a size of 2000 ns // The criterion for a successful decoding is that we find at least // 6 ID or data address marks on the track. It is highly unlikely // to find so many marks with a wrong cell size. if (marks < 6 && attempt < 4) { if (TRACE) osd_printf_verbose("ti99_dsk: Decoding with cell size %d failed.\n", cell_size); attempt++; write = false; } else write = true; } else { if (marks < 6) { if (min_heads()==1) { if (TRACE) osd_printf_info("ti99_dsk: We don't have a second side and the format allows for single-sided recording.\n"); return true; } else { osd_printf_warning("ti99_dsk: No second side, but this format requires two-sided recording. Saving empty tracks.\n"); } } } } if (write) { if (TRACE) { if (head == 0 && track == 0) { if (marks >=6) { if (TRACE) osd_printf_info("ti99_dsk: Decoding with cell size %d successful.\n", cell_size); } else osd_printf_info("ti99_dsk: No address marks found on track 0. Assuming MFM format.\n"); } } // Save to the file write_track(io, trackdata, sector, track, head, maxsect, maxtrack, track_size); track++; } } } return true; }
void media_identifier::digest_file(std::vector<file_info> &info, char const *path) { // CHD files need to be parsed and their hashes extracted from the header if (core_filename_ends_with(path, ".chd")) { // attempt to open as a CHD; fail if not chd_file chd; chd_error const err = chd.open(path); m_total++; if (err != CHDERR_NONE) { osd_printf_info("%-20sNOT A CHD\n", core_filename_extract_base(path).c_str()); m_nonroms++; } else if (!chd.compressed()) { osd_printf_info("%-20sis a writeable CHD\n", core_filename_extract_base(path).c_str()); } else { // otherwise, get the hash collection for this CHD util::hash_collection hashes; if (chd.sha1() != util::sha1_t::null) hashes.add_sha1(chd.sha1()); info.emplace_back(path, chd.logical_bytes(), std::move(hashes), file_flavour::CHD); } } else { // if this is a '.jed' file, process it into raw bits first if (core_filename_ends_with(path, ".jed")) { // load the file and process if it opens and has a valid length uint32_t length; void *data; if (osd_file::error::NONE == util::core_file::load(path, &data, length)) { jed_data jed; if (JEDERR_NONE == jed_parse(data, length, &jed)) { try { // now determine the new data length and allocate temporary memory for it std::vector<uint8_t> tempjed(jedbin_output(&jed, nullptr, 0)); jedbin_output(&jed, &tempjed[0], tempjed.size()); util::hash_collection hashes; hashes.compute(&tempjed[0], tempjed.size(), util::hash_collection::HASH_TYPES_CRC_SHA1); info.emplace_back(path, tempjed.size(), std::move(hashes), file_flavour::JED); free(data); m_total++; return; } catch (...) { } } free(data); } } // load the file and process if it opens and has a valid length util::core_file::ptr file; if ((osd_file::error::NONE == util::core_file::open(path, OPEN_FLAG_READ, file)) && file) { util::hash_collection hashes; hashes.begin(util::hash_collection::HASH_TYPES_CRC_SHA1); std::uint8_t buf[1024]; for (std::uint64_t remaining = file->size(); remaining; ) { std::uint32_t const block = std::min<std::uint64_t>(remaining, sizeof(buf)); if (file->read(buf, block) < block) { osd_printf_error("%s: error reading file\n", path); return; } remaining -= block; hashes.buffer(buf, block); } hashes.end(); info.emplace_back(path, file->size(), std::move(hashes), file_flavour::RAW); m_total++; } else { osd_printf_error("%s: error opening file\n", path); } } }
bool device_image_interface::load_internal(const char *path, bool is_create, int create_format, option_resolution *create_args, bool just_load) { UINT32 open_plan[4]; int i; bool softload = FALSE; m_from_swlist = FALSE; // if the path contains no period, we are using softlists, so we won't create an image astring pathstr(path); bool filename_has_period = (pathstr.rchr(0, '.') != -1) ? TRUE : FALSE; /* first unload the image */ unload(); /* clear any possible error messages */ clear_error(); /* we are now loading */ m_is_loading = TRUE; /* record the filename */ m_err = set_image_filename(path); if (m_err) goto done; if (core_opens_image_file()) { /* Check if there's a software list defined for this device and use that if we're not creating an image */ if (!filename_has_period && !just_load) { softload = load_software_part(path, m_software_part_ptr); if (softload) { m_software_info_ptr = &m_software_part_ptr->info(); m_software_list_name.cpy(m_software_info_ptr->list().list_name()); m_full_software_name.cpy(m_software_part_ptr->info().shortname()); // if we had launched from softlist with a specified part, e.g. "shortname:part" // we would have recorded the wrong name, so record it again based on software_info if (m_software_info_ptr && m_full_software_name) m_err = set_image_filename(m_full_software_name); // check if image should be read-only const char *read_only = get_feature("read_only"); if (read_only && !strcmp(read_only, "true")) { make_readonly(); } m_from_swlist = TRUE; } } if (is_create || filename_has_period) { /* determine open plan */ determine_open_plan(is_create, open_plan); /* attempt to open the file in various ways */ for (i = 0; !m_file && open_plan[i]; i++) { /* open the file */ m_err = load_image_by_path(open_plan[i], path); if (m_err && (m_err != IMAGE_ERROR_FILENOTFOUND)) goto done; } } /* Copy some image information when we have been loaded through a software list */ if ( m_software_info_ptr ) { // sanitize if (m_software_info_ptr->longname() == NULL || m_software_info_ptr->publisher() == NULL || m_software_info_ptr->year() == NULL) fatalerror("Each entry in an XML list must have all of the following fields: description, publisher, year!\n"); // store m_longname = m_software_info_ptr->longname(); m_manufacturer = m_software_info_ptr->publisher(); m_year = m_software_info_ptr->year(); //m_playable = m_software_info_ptr->supported(); } /* did we fail to find the file? */ if (!is_loaded() && !softload) { m_err = IMAGE_ERROR_FILENOTFOUND; goto done; } } /* call device load or create */ m_create_format = create_format; m_create_args = create_args; if (m_init_phase==FALSE) { m_err = (image_error_t)finish_load(); if (m_err) goto done; } /* success! */ done: if (just_load) { if(m_err) clear(); return m_err ? IMAGE_INIT_FAIL : IMAGE_INIT_PASS; } if (m_err!=0) { if (!m_init_phase) { if (device().machine().phase() == MACHINE_PHASE_RUNNING) popmessage("Error: Unable to %s image '%s': %s", is_create ? "create" : "load", path, error()); else osd_printf_error("Error: Unable to %s image '%s': %s\n", is_create ? "create" : "load", path, error()); } clear(); } else { /* do we need to reset the CPU? only schedule it if load/create is successful */ if (device().machine().time() > attotime::zero && is_reset_on_load()) device().machine().schedule_hard_reset(); else { if (!m_init_phase) { if (device().machine().phase() == MACHINE_PHASE_RUNNING) popmessage("Image '%s' was successfully %s.", path, is_create ? "created" : "loaded"); else osd_printf_info("Image '%s' was successfully %s.\n", path, is_create ? "created" : "loaded"); } } } return m_err ? IMAGE_INIT_FAIL : IMAGE_INIT_PASS; }
/* Load the image from disk and convert it into a sequence of flux levels. */ bool ti99_floppy_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { int cell_size = 0; int sector_count = 0; int heads = 0; int log_track_count = 0; determine_sizes(io, cell_size, sector_count, heads, log_track_count); if (cell_size == 0) return false; // Be ready to hold a track of up to 36 sectors (with gaps and marks) UINT8 trackdata[13000]; int maxtrack, maxheads; image->get_maximal_geometry(maxtrack, maxheads); int file_size = io_generic_size(io); int track_size = get_track_size(cell_size, sector_count); // Problem: If the disk is improperly formatted, the track count will be // wrong. For instance, a disk could be reformatted to single-side. // We assume there is no disk with single side format beyond 40 tracks. if ((heads==1) && (file_size > track_size*40)) heads = 2; int phys_track_count = file_size / (track_size*heads); // Some disks are known to have an incomplete header. // PASCAL disks have a track count of 0. if (log_track_count==0) log_track_count = phys_track_count; if (TRACE) osd_printf_info("ti99_dsk: logical tracks = %d, physical tracks = %d\n", log_track_count, phys_track_count); if (phys_track_count > maxtrack) { osd_printf_error("ti99_dsk: Floppy disk has too many tracks for this drive.\n"); return false; } // Is this the first time that this disk is read in an 80-track drive? bool double_step = ((log_track_count * 2) <= maxtrack); bool first_time_double = ((phys_track_count * 2) <= maxtrack); if (first_time_double) { osd_printf_warning("ti99_dsk: 40-track image in an 80-track drive. On save, image size will double.\n"); } int acttrack; // Read the image for (int head=0; head < heads; head++) { for (int track=0; track < phys_track_count; track++) { if (double_step && !first_time_double) acttrack = track/2; else acttrack = track; load_track(io, trackdata, head, track, acttrack, sector_count, phys_track_count, cell_size); if (first_time_double) { // Create two tracks from each medium track. This reflects the // fact that the drive head will find the same data after // a single step if (get_encoding(cell_size)==floppy_image::FM) { generate_track_fm(track*2, head, cell_size, trackdata, image); generate_track_fm(track*2+1, head, cell_size, trackdata, image); } else { generate_track_mfm(track*2, head, cell_size, trackdata, image); generate_track_mfm(track*2+1, head, cell_size, trackdata, image); } } else { // Normal tracks if (get_encoding(cell_size)==floppy_image::FM) generate_track_fm(track, head, cell_size, trackdata, image); else generate_track_mfm(track, head, cell_size, trackdata, image); } } } return true; }
void emulator_info::printf_usage(const char *par1, const char *par2) { osd_printf_info(USAGE, par1, par2); }
bool a78_cart_slot_device::call_load() { if (m_cart) { UINT32 len; if (software_entry() != nullptr) { const char *pcb_name; bool has_ram = get_software_region("ram") ? TRUE : FALSE; bool has_nvram = get_software_region("nvram") ? TRUE : FALSE; len = get_software_region_length("rom"); m_cart->rom_alloc(len, tag()); memcpy(m_cart->get_rom_base(), get_software_region("rom"), len); if ((pcb_name = get_feature("slot")) != nullptr) m_type = a78_get_pcb_id(pcb_name); else m_type = A78_TYPE0; if (has_ram) m_cart->ram_alloc(get_software_region_length("ram")); if (has_nvram) { m_cart->nvram_alloc(get_software_region_length("nvram")); battery_load(m_cart->get_nvram_base(), get_software_region_length("nvram"), 0xff); } } else { // Load and check the header int mapper; char head[128]; fread(head, 128); if (verify_header((char *)head) == IMAGE_VERIFY_FAIL) return IMAGE_INIT_FAIL; len = (head[49] << 24) | (head[50] << 16) | (head[51] << 8) | head[52]; if (len + 128 > length()) { logerror("Invalid length in the header. The game might be corrupted.\n"); len = length() - 128; } // let's try to auto-fix some common errors in the header mapper = validate_header((head[53] << 8) | head[54], TRUE); switch (mapper & 0x2e) { case 0x0000: m_type = BIT(mapper, 0) ? A78_TYPE1 : A78_TYPE0; break; case 0x0002: m_type = BIT(mapper, 0) ? A78_TYPE3 : A78_TYPE2; break; case 0x0006: m_type = A78_TYPE6; break; case 0x000a: m_type = A78_TYPEA; break; case 0x0022: case 0x0026: if (len > 0x40000) m_type = A78_MEGACART; else m_type = A78_VERSABOARD; break; } // check if cart has a POKEY at $0450 (typically a VersaBoard variant) if (mapper & 0x40) { if (m_type != A78_TYPE2) { m_type &= ~0x02; m_type += A78_POKEY0450; } } // check special bits, which override the previous if ((mapper & 0xff00) == 0x0100) m_type = A78_ACTIVISION; else if ((mapper & 0xff00) == 0x0200) m_type = A78_ABSOLUTE; logerror("Cart type: 0x%x\n", m_type); if (head[58] == 1) { osd_printf_info("This cart supports external NVRAM using HSC.\n"); osd_printf_info("Run it with the High Score Cart mounted to exploit this feature.\n"); } else if (head[58] == 2) { osd_printf_info("This cart supports external NVRAM using SaveKey.\n"); osd_printf_info("This is not supported in MAME currently.\n"); } if (head[63]) { osd_printf_info("This cart requires XBoarD / XM expansion\n"); osd_printf_info("Run it through the expansion to exploit this feature.\n"); } internal_header_logging((UINT8 *)head, length()); m_cart->rom_alloc(len, tag()); fread(m_cart->get_rom_base(), len); if (m_type == A78_TYPE6) m_cart->ram_alloc(0x4000); if (m_type == A78_MEGACART || (m_type >= A78_VERSABOARD && m_type <= A78_VERSA_POK450)) m_cart->ram_alloc(0x8000); if (m_type == A78_XB_BOARD || m_type == A78_XM_BOARD) m_cart->ram_alloc(0x20000); if (m_type == A78_HSC || m_type == A78_XM_BOARD) { m_cart->nvram_alloc(0x800); battery_load(m_cart->get_nvram_base(), 0x800, 0xff); } } //printf("Type: %s\n", a78_get_slot(m_type)); } return IMAGE_INIT_PASS; }