static void process_region_list(romload_private *romdata) { astring regiontag; /* loop until we hit the end */ device_iterator deviter(romdata->machine().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != NULL; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); rom_region_name(regiontag, *device, region); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.cstr(), regionlength)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); if (ROMREGION_ISROMDATA(region)) { /* if this is a device region, override with the device width and endianness */ UINT8 width = ROMREGION_GETWIDTH(region) / 8; endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; if (romdata->machine().device(regiontag) != NULL) normalize_flags_for_device(romdata->machine(), regiontag, width, endianness); /* remember the base and length */ romdata->region = romdata->machine().memory().region_alloc(regiontag, regionlength, width, endianness); LOG(("Allocated %X bytes @ %p\n", romdata->region->bytes(), romdata->region->base())); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(romdata->region->base(), ROMREGION_GETERASEVAL(region), romdata->region->bytes()); /* or if it's sufficiently small (<= 4MB) */ else if (romdata->region->bytes() <= 0x400000) memset(romdata->region->base(), 0, romdata->region->bytes()); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(romdata->machine(), romdata->region->base(), romdata->region->bytes()); #endif /* now process the entries in the region */ process_rom_entries(romdata, device->shortname(), region, region + 1, device, FALSE); } else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(romdata, regiontag, region, region + 1, NULL); } /* now go back and post-process all the regions */ for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != NULL; region = rom_next_region(region)) { rom_region_name(regiontag, *device, region); region_post_process(romdata, regiontag, ROMREGION_ISINVERTED(region)); } }
static void region_post_process(struct rom_load_data *romdata, const struct RomModule *regiondata) { int type = ROMREGION_GETTYPE(regiondata); int datawidth = ROMREGION_GETWIDTH(regiondata) / 8; int littleendian = ROMREGION_ISLITTLEENDIAN(regiondata); UINT8 *base; int i, j; debugload("+ datawidth=%d little=%d\n", datawidth, littleendian); /* if this is a CPU region, override with the CPU width and endianness */ if (type >= REGION_CPU1 && type < REGION_CPU1 + MAX_CPU) { int cputype = Machine->drv->cpu[type - REGION_CPU1].cpu_type; if (cputype != 0) { datawidth = cputype_databus_width(cputype) / 8; littleendian = (cputype_endianess(cputype) == CPU_IS_LE); debugload("+ CPU region #%d: datawidth=%d little=%d\n", type - REGION_CPU1, datawidth, littleendian); } } /* if the region is inverted, do that now */ if (ROMREGION_ISINVERTED(regiondata)) { debugload("+ Inverting region\n"); for (i = 0, base = romdata->regionbase; i < romdata->regionlength; i++) *base++ ^= 0xff; } /* swap the endianness if we need to */ #ifdef MSB_FIRST if (datawidth > 1 && littleendian) #else if (datawidth > 1 && !littleendian) #endif { debugload("+ Byte swapping region\n"); for (i = 0, base = romdata->regionbase; i < romdata->regionlength; i += datawidth) { UINT8 temp[8]; memcpy(temp, base, datawidth); for (j = datawidth - 1; j >= 0; j--) *base++ = temp[j]; } } }
int cartslot_image_device::load_cartridge(const rom_entry *romrgn, const rom_entry *roment, bool load) { const char *region; const char *type; UINT32 flags; offs_t offset, size, read_length, pos = 0, len; UINT8 *ptr; UINT8 clear_val; int datawidth, littleendian, i, j; device_t *cpu; astring regiontag; device().siblingtag(regiontag, ROMREGION_GETTAG(romrgn)); region = regiontag.cstr(); offset = ROM_GETOFFSET(roment); size = ROM_GETLENGTH(roment); flags = ROM_GETFLAGS(roment); ptr = ((UINT8 *) device().machine().root_device().memregion(region)->base()) + offset; if (load) { if (software_entry() == NULL) { /* must this be full size */ if (flags & ROM_FULLSIZE) { if (length() != size) return IMAGE_INIT_FAIL; } /* read the ROM */ pos = read_length = fread(ptr, size); /* reset the ROM to the initial point. */ /* eventually, we could add a flag to allow the ROM to continue instead of restarting whenever a new cart region is present */ fseek(0, SEEK_SET); } else { /* must this be full size */ if (flags & ROM_FULLSIZE) { if (get_software_region_length("rom") != size) return IMAGE_INIT_FAIL; } /* read the ROM */ pos = read_length = get_software_region_length("rom"); memcpy(ptr, get_software_region("rom"), read_length); } /* do we need to mirror the ROM? */ if (flags & ROM_MIRROR) { while(pos < size) { len = MIN(read_length, size - pos); memcpy(ptr + pos, ptr, len); pos += len; } } /* postprocess this region */ type = regiontag.cstr(); littleendian = ROMREGION_ISLITTLEENDIAN(romrgn); datawidth = ROMREGION_GETWIDTH(romrgn) / 8; /* if the region is inverted, do that now */ device_memory_interface *memory; cpu = device().machine().device(type); if (cpu!=NULL && cpu->interface(memory)) { datawidth = cpu->memory().space_config(AS_PROGRAM)->m_databus_width / 8; littleendian = (cpu->memory().space_config()->m_endianness == ENDIANNESS_LITTLE); } /* swap the endianness if we need to */ #ifdef LSB_FIRST if (datawidth > 1 && !littleendian) #else if (datawidth > 1 && littleendian) #endif { for (i = 0; i < size; i += datawidth) { UINT8 temp[8]; memcpy(temp, &ptr[i], datawidth); for (j = datawidth - 1; j >= 0; j--) ptr[i + j] = temp[datawidth - 1 - j]; } } } /* clear out anything that remains */ if (!(flags & ROM_NOCLEAR)) { clear_val = (flags & ROM_FILL_FF) ? 0xFF : 0x00; memset(ptr + pos, clear_val, size - pos); } return IMAGE_INIT_PASS; }
void load_software_part_region(device_t &device, software_list_device &swlist, const char *swname, const rom_entry *start_region) { astring locationtag(swlist.list_name()), breakstr("%"); romload_private *romdata = device.machine().romload_data; const rom_entry *region; astring regiontag; romdata->errorstring.reset(); romdata->softwarningstring.reset(); romdata->romstotal = 0; romdata->romstotalsize = 0; romdata->romsloadedsize = 0; software_info *swinfo = swlist.find(swname); if (swinfo != NULL) { UINT32 supported = swinfo->supported(); if (supported == SOFTWARE_SUPPORTED_PARTIAL) { romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name()); romdata->softwarningstring.catprintf("Support for software %s (in list %s) is only partial\n", swname, swlist.list_name()); } if (supported == SOFTWARE_SUPPORTED_NO) { romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name()); romdata->softwarningstring.catprintf("Support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name()); } // attempt reading up the chain through the parents and create a locationtag astring in the format // " swlist % clonename % parentname " // open_rom_file contains the code to split the elements and to create paths to load from locationtag.cat(breakstr); while (swinfo != NULL) { locationtag.cat(swinfo->shortname()).cat(breakstr); const char *parentname = swinfo->parentname(); swinfo = (parentname != NULL) ? swlist.find(parentname) : NULL; } // strip the final '%' locationtag.del(locationtag.len() - 1, 1); } /* loop until we hit the end */ for (region = start_region; region != NULL; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); device.subtag(regiontag, ROMREGION_GETTAG(region)); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.cstr(), regionlength)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); /* if this is a device region, override with the device width and endianness */ endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; UINT8 width = ROMREGION_GETWIDTH(region) / 8; memory_region *memregion = romdata->machine().root_device().memregion(regiontag); if (memregion != NULL) { if (romdata->machine().device(regiontag) != NULL) normalize_flags_for_device(romdata->machine(), regiontag, width, endianness); /* clear old region (todo: should be moved to an image unload function) */ romdata->machine().memory().region_free(memregion->name()); } /* remember the base and length */ romdata->region = romdata->machine().memory().region_alloc(regiontag, regionlength, width, endianness); LOG(("Allocated %X bytes @ %p\n", romdata->region->bytes(), romdata->region->base())); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(romdata->region->base(), ROMREGION_GETERASEVAL(region), romdata->region->bytes()); /* or if it's sufficiently small (<= 4MB) */ else if (romdata->region->bytes() <= 0x400000) memset(romdata->region->base(), 0, romdata->region->bytes()); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(romdata->machine(), romdata->region->base(), romdata->region->bytes()); #endif /* update total number of roms */ for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) { romdata->romstotal++; romdata->romstotalsize += rom_file_size(rom); } /* now process the entries in the region */ if (ROMREGION_ISROMDATA(region)) process_rom_entries(romdata, locationtag, region, region + 1, &device, TRUE); else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(romdata, core_strdup(regiontag.cstr()), region, region + 1, locationtag); } /* now go back and post-process all the regions */ for (region = start_region; region != NULL; region = rom_next_region(region)) { device.subtag(regiontag, ROMREGION_GETTAG(region)); region_post_process(romdata, regiontag.cstr(), ROMREGION_ISINVERTED(region)); } /* display the results and exit */ display_rom_load_results(romdata, TRUE); }
void rom_load_manager::process_region_list() { std::string regiontag; /* loop until we hit the end */ device_iterator deviter(machine().root_device()); for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != nullptr; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); regiontag = rom_region_name(*device, region); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.c_str(), regionlength)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); if (ROMREGION_ISROMDATA(region)) { /* if this is a device region, override with the device width and endianness */ UINT8 width = ROMREGION_GETWIDTH(region) / 8; endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; if (machine().device(regiontag.c_str()) != nullptr) normalize_flags_for_device(machine(), regiontag.c_str(), width, endianness); /* remember the base and length */ m_region = machine().memory().region_alloc(regiontag.c_str(), regionlength, width, endianness); LOG(("Allocated %X bytes @ %p\n", m_region->bytes(), m_region->base())); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(m_region->base(), ROMREGION_GETERASEVAL(region), m_region->bytes()); /* or if it's sufficiently small (<= 4MB) */ else if (m_region->bytes() <= 0x400000) memset(m_region->base(), 0, m_region->bytes()); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(m_region->base(), m_region->bytes()); #endif /* now process the entries in the region */ process_rom_entries(device->shortname().c_str(), region, region + 1, device, FALSE); } else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(regiontag.c_str(), region, region + 1, nullptr); } /* now go back and post-process all the regions */ for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != nullptr; region = rom_next_region(region)) { regiontag = rom_region_name(*device, region); region_post_process(regiontag.c_str(), ROMREGION_ISINVERTED(region)); } /* and finally register all per-game parameters */ for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *param = rom_first_parameter(*device); param != nullptr; param = rom_next_parameter(param)) { regiontag = rom_parameter_name(*device, param); machine().parameters().add(regiontag, rom_parameter_value(param)); } }
static int load_cartridge(const rom_entry *romrgn, const rom_entry *roment, mame_file *file) { UINT32 region, flags; offs_t offset, length, read_length, pos = 0, len; UINT8 *ptr; UINT8 clear_val; int type, datawidth, littleendian, i, j; region = ROMREGION_GETTYPE(romrgn); offset = ROM_GETOFFSET(roment); length = ROM_GETLENGTH(roment); flags = ROM_GETFLAGS(roment); ptr = ((UINT8 *) memory_region(region)) + offset; if (file) { /* must this be full size */ if (flags & ROM_FULLSIZE) { if (mame_fsize(file) != length) return INIT_FAIL; } /* read the ROM */ pos = read_length = mame_fread(file, ptr, length); /* do we need to mirror the ROM? */ if (flags & ROM_MIRROR) { while(pos < length) { len = MIN(read_length, length - pos); memcpy(ptr + pos, ptr, len); pos += len; } } /* postprocess this region */ type = ROMREGION_GETTYPE(romrgn); littleendian = ROMREGION_ISLITTLEENDIAN(romrgn); datawidth = ROMREGION_GETWIDTH(romrgn) / 8; /* if the region is inverted, do that now */ if (type >= REGION_CPU1 && type < REGION_CPU1 + MAX_CPU) { int cputype = Machine->drv->cpu[type - REGION_CPU1].cpu_type; if (cputype != 0) { datawidth = cputype_databus_width(cputype, ADDRESS_SPACE_PROGRAM) / 8; littleendian = (cputype_endianness(cputype) == CPU_IS_LE); } } /* swap the endianness if we need to */ #ifdef LSB_FIRST if (datawidth > 1 && !littleendian) #else if (datawidth > 1 && littleendian) #endif { for (i = 0; i < length; i += datawidth) { UINT8 temp[8]; memcpy(temp, &ptr[i], datawidth); for (j = datawidth - 1; j >= 0; j--) ptr[i + j] = temp[datawidth - 1 - j]; } } } /* clear out anything that remains */ if (!(flags & ROM_NOCLEAR)) { clear_val = (flags & ROM_FILL_FF) ? 0xFF : 0x00; memset(ptr + pos, clear_val, length - pos); } return INIT_PASS; }