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 determine_bios_rom(const struct SystemBios *bios) { const struct SystemBios *firstbios = bios; /* set to default */ int bios_no = 0; /* Not system_bios_0 and options.bios is set */ if(bios && (options.bios != NULL)) { /* Allow '-bios n' to still be used */ while(!BIOSENTRY_ISEND(bios)) { char bios_number[3]; sprintf(bios_number, "%d", bios->value); if(!strcmp(bios_number, options.bios)) bios_no = bios->value; bios++; } bios = firstbios; /* Test for bios short names */ while(!BIOSENTRY_ISEND(bios)) { if(!strcmp(bios->_name, options.bios)) bios_no = bios->value; bios++; } } debugload("Using System BIOS: %d\n", bios_no); return bios_no; }
int rom_load(const struct RomModule *romp) { const struct RomModule *regionlist[REGION_MAX]; const struct RomModule *region; static struct rom_load_data romdata; int regnum; /* reset the region list */ for (regnum = 0;regnum < REGION_MAX;regnum++) regionlist[regnum] = NULL; /* reset the romdata struct */ memset(&romdata, 0, sizeof(romdata)); romdata.romstotal = count_roms(romp); /* reset the disk list */ memset(disk_handle, 0, sizeof(disk_handle)); /* determine the correct biosset to load based on options.bios string */ system_bios = determine_bios_rom(Machine->gamedrv->bios); /* loop until we hit the end */ for (region = romp, regnum = 0; region; region = rom_next_region(region), regnum++) { int regiontype = ROMREGION_GETTYPE(region); debugload("Processing region %02X (length=%X)\n", regiontype, ROMREGION_GETLENGTH(region)); /* the first entry must be a region */ if (!ROMENTRY_ISREGION(region)) { printf("Error: missing ROM_REGION header\n"); return 1; } /* if sound is disabled and it's a sound-only region, skip it */ if (Machine->sample_rate == 0 && ROMREGION_ISSOUNDONLY(region)) continue; /* allocate memory for the region */ if (new_memory_region(regiontype, ROMREGION_GETLENGTH(region), ROMREGION_GETFLAGS(region))) { printf("Error: unable to allocate memory for region %d\n", regiontype); return 1; } /* remember the base and length */ romdata.regionlength = memory_region_length(regiontype); romdata.regionbase = memory_region(regiontype); debugload("Allocated %X bytes @ %08X\n", romdata.regionlength, (int)romdata.regionbase); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(romdata.regionbase, ROMREGION_GETERASEVAL(region), romdata.regionlength); /* or if it's sufficiently small (<= 4MB) */ else if (romdata.regionlength <= 0x400000) memset(romdata.regionbase, 0, romdata.regionlength); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(romdata.regionbase, romdata.regionlength); #endif /* now process the entries in the region */ if (ROMREGION_ISROMDATA(region)) { if (!process_rom_entries(&romdata, region + 1)) return 1; } else if (ROMREGION_ISDISKDATA(region)) { if (!process_disk_entries(&romdata, region + 1)) return 1; } /* add this region to the list */ if (regiontype < REGION_MAX) regionlist[regiontype] = region; } /* post-process the regions */ for (regnum = 0; regnum < REGION_MAX; regnum++) if (regionlist[regnum]) { debugload("Post-processing region %02X\n", regnum); romdata.regionlength = memory_region_length(regnum); romdata.regionbase = memory_region(regnum); region_post_process(&romdata, regionlist[regnum]); } /* display the results and exit */ return display_rom_load_results(&romdata); }
static int process_disk_entries(struct rom_load_data *romdata, const struct RomModule *romp) { /* loop until we hit the end of this region */ while (!ROMENTRY_ISREGIONEND(romp)) { /* handle files */ if (ROMENTRY_ISFILE(romp)) { struct chd_file *source, *diff = NULL; struct chd_header header; char filename[1024], *c; char acthash[HASH_BUF_SIZE]; int err; /* make the filename of the source */ strcpy(filename, ROM_GETNAME(romp)); c = strrchr(filename, '.'); if (c) strcpy(c, ".chd"); else strcat(filename, ".chd"); /* first open the source drive */ debugload("Opening disk image: %s\n", filename); source = chd_open(filename, 0, NULL); if (!source) { if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION) sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s UNSUPPORTED CHD VERSION\n", filename); else sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s NOT FOUND\n", filename); romdata->errors++; romp++; continue; } /* get the header and extract the MD5/SHA1 */ header = *chd_get_header(source); hash_data_clear(acthash); hash_data_insert_binary_checksum(acthash, HASH_MD5, header.md5); hash_data_insert_binary_checksum(acthash, HASH_SHA1, header.sha1); /* verify the MD5 */ if (!hash_data_is_equal(ROM_GETHASHDATA(romp), acthash, 0)) { sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s WRONG CHECKSUMS:\n", filename); dump_wrong_and_correct_checksums(romdata, ROM_GETHASHDATA(romp), acthash); romdata->warnings++; } /* if not read-only, make the diff file */ if (!DISK_ISREADONLY(romp)) { /* make the filename of the diff */ strcpy(filename, ROM_GETNAME(romp)); c = strrchr(filename, '.'); if (c) strcpy(c, ".dif"); else strcat(filename, ".dif"); /* try to open the diff */ debugload("Opening differencing image: %s\n", filename); diff = chd_open(filename, 1, source); if (!diff) { /* didn't work; try creating it instead */ debugload("Creating differencing image: %s\n", filename); err = chd_create(filename, 0, 0, CHDCOMPRESSION_NONE, source); if (err != CHDERR_NONE) { if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION) sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s UNSUPPORTED CHD VERSION\n", filename); else sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s: CAN'T CREATE DIFF FILE\n", filename); romdata->errors++; romp++; continue; } /* open the newly-created diff file */ debugload("Opening differencing image: %s\n", filename); diff = chd_open(filename, 1, source); if (!diff) { if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION) sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s UNSUPPORTED CHD VERSION\n", filename); else sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s: CAN'T OPEN DIFF FILE\n", filename); romdata->errors++; romp++; continue; } } } /* we're okay, set the handle */ debugload("Assigning to handle %d\n", DISK_GETINDEX(romp)); disk_handle[DISK_GETINDEX(romp)] = DISK_ISREADONLY(romp) ? source : diff; romp++; } } return 1; }
static int process_rom_entries(struct rom_load_data *romdata, const struct RomModule *romp) { UINT32 lastflags = 0; /* loop until we hit the end of this region */ while (!ROMENTRY_ISREGIONEND(romp)) { /* if this is a continue entry, it's invalid */ if (ROMENTRY_ISCONTINUE(romp)) { printf("Error in RomModule definition: ROM_CONTINUE not preceded by ROM_LOAD\n"); goto fatalerror; } /* if this is a reload entry, it's invalid */ if (ROMENTRY_ISRELOAD(romp)) { printf("Error in RomModule definition: ROM_RELOAD not preceded by ROM_LOAD\n"); goto fatalerror; } /* handle fills */ if (ROMENTRY_ISFILL(romp)) { if (!fill_rom_data(romdata, romp++)) goto fatalerror; } /* handle copies */ else if (ROMENTRY_ISCOPY(romp)) { if (!copy_rom_data(romdata, romp++)) goto fatalerror; } /* handle files */ else if (ROMENTRY_ISFILE(romp)) { if (!ROM_GETBIOSFLAGS(romp) || (ROM_GETBIOSFLAGS(romp) == (system_bios+1))) /* alternate bios sets */ { const struct RomModule *baserom = romp; int explength = 0; /* open the file */ debugload("Opening ROM file: %s\n", ROM_GETNAME(romp)); if (!open_rom_file(romdata, romp)) handle_missing_file(romdata, romp); /* loop until we run out of reloads */ do { /* loop until we run out of continues */ do { struct RomModule modified_romp = *romp++; int readresult; /* handle flag inheritance */ if (!ROM_INHERITSFLAGS(&modified_romp)) lastflags = modified_romp._flags; else modified_romp._flags = (modified_romp._flags & ~ROM_INHERITEDFLAGS) | lastflags; explength += ROM_GETLENGTH(&modified_romp); /* attempt to read using the modified entry */ readresult = read_rom_data(romdata, &modified_romp); if (readresult == -1) goto fatalerror; } while (ROMENTRY_ISCONTINUE(romp)); /* if this was the first use of this file, verify the length and CRC */ if (baserom) { debugload("Verifying length (%X) and checksums\n", explength); verify_length_and_hash(romdata, ROM_GETNAME(baserom), explength, ROM_GETHASHDATA(baserom)); debugload("Verify finished\n"); } /* reseek to the start and clear the baserom so we don't reverify */ if (romdata->file) mame_fseek(romdata->file, 0, SEEK_SET); baserom = NULL; explength = 0; } while (ROMENTRY_ISRELOAD(romp)); /* close the file */ if (romdata->file) { debugload("Closing ROM file\n"); mame_fclose(romdata->file); romdata->file = NULL; } } else { romp++; /* skip over file */ } } } return 1; /* error case */ fatalerror: if (romdata->file) mame_fclose(romdata->file); romdata->file = NULL; return 0; }
static int read_rom_data(struct rom_load_data *romdata, const struct RomModule *romp) { int datashift = ROM_GETBITSHIFT(romp); int datamask = ((1 << ROM_GETBITWIDTH(romp)) - 1) << datashift; int numbytes = ROM_GETLENGTH(romp); int groupsize = ROM_GETGROUPSIZE(romp); int skip = ROM_GETSKIPCOUNT(romp); int reversed = ROM_ISREVERSED(romp); int numgroups = (numbytes + groupsize - 1) / groupsize; UINT8 *base = romdata->regionbase + ROM_GETOFFSET(romp); int i; debugload("Loading ROM data: offs=%X len=%X mask=%02X group=%d skip=%d reverse=%d\n", ROM_GETOFFSET(romp), numbytes, datamask, groupsize, skip, reversed); /* make sure the length was an even multiple of the group size */ if (numbytes % groupsize != 0) { printf("Error in RomModule definition: %s length not an even multiple of group size\n", ROM_GETNAME(romp)); return -1; } /* make sure we only fill within the region space */ if (ROM_GETOFFSET(romp) + numgroups * groupsize + (numgroups - 1) * skip > romdata->regionlength) { printf("Error in RomModule definition: %s out of memory region space\n", ROM_GETNAME(romp)); return -1; } /* make sure the length was valid */ if (numbytes == 0) { printf("Error in RomModule definition: %s has an invalid length\n", ROM_GETNAME(romp)); return -1; } /* special case for simple loads */ if (datamask == 0xff && (groupsize == 1 || !reversed) && skip == 0) return rom_fread(romdata, base, numbytes); /* chunky reads for complex loads */ skip += groupsize; while (numbytes) { int evengroupcount = (sizeof(romdata->tempbuf) / groupsize) * groupsize; int bytesleft = (numbytes > evengroupcount) ? evengroupcount : numbytes; UINT8 *bufptr = romdata->tempbuf; /* read as much as we can */ debugload(" Reading %X bytes into buffer\n", bytesleft); if (rom_fread(romdata, romdata->tempbuf, bytesleft) != bytesleft) return 0; numbytes -= bytesleft; debugload(" Copying to %08X\n", (int)base); /* unmasked cases */ if (datamask == 0xff) { /* non-grouped data */ if (groupsize == 1) for (i = 0; i < bytesleft; i++, base += skip) *base = *bufptr++; /* grouped data -- non-reversed case */ else if (!reversed) while (bytesleft) { for (i = 0; i < groupsize && bytesleft; i++, bytesleft--) base[i] = *bufptr++; base += skip; } /* grouped data -- reversed case */ else while (bytesleft) { for (i = groupsize - 1; i >= 0 && bytesleft; i--, bytesleft--) base[i] = *bufptr++; base += skip; } } /* masked cases */ else { /* non-grouped data */ if (groupsize == 1) for (i = 0; i < bytesleft; i++, base += skip) *base = (*base & ~datamask) | ((*bufptr++ << datashift) & datamask); /* grouped data -- non-reversed case */ else if (!reversed) while (bytesleft) { for (i = 0; i < groupsize && bytesleft; i++, bytesleft--) base[i] = (base[i] & ~datamask) | ((*bufptr++ << datashift) & datamask); base += skip; } /* grouped data -- reversed case */ else while (bytesleft) { for (i = groupsize - 1; i >= 0 && bytesleft; i--, bytesleft--) base[i] = (base[i] & ~datamask) | ((*bufptr++ << datashift) & datamask); base += skip; } } } debugload(" All done\n"); return ROM_GETLENGTH(romp); }
void rom_init(running_machine *machine, const rom_entry *romp) { const rom_entry *regionlist[REGION_MAX]; const rom_entry *region; static rom_load_data romdata; int regnum; /* if no roms, bail */ if (romp == NULL) return; /* make sure we get called back on the way out */ add_exit_callback(machine, rom_exit); /* reset the region list */ memset((void *)regionlist, 0, sizeof(regionlist)); /* reset the romdata struct */ memset(&romdata, 0, sizeof(romdata)); romdata.romstotal = count_roms(romp); /* reset the disk list */ memset(disk_handle, 0, sizeof(disk_handle)); /* determine the correct biosset to load based on options.bios string */ system_bios = determine_bios_rom(Machine->gamedrv->bios); /* loop until we hit the end */ for (region = romp, regnum = 0; region; region = rom_next_region(region), regnum++) { int regiontype = ROMREGION_GETTYPE(region); debugload("Processing region %02X (length=%X)\n", regiontype, ROMREGION_GETLENGTH(region)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); /* remember the base and length */ romdata.regionbase = new_memory_region(machine, regiontype, ROMREGION_GETLENGTH(region), ROMREGION_GETFLAGS(region)); romdata.regionlength = ROMREGION_GETLENGTH(region); debugload("Allocated %X bytes @ %08X\n", romdata.regionlength, (int)romdata.regionbase); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(romdata.regionbase, ROMREGION_GETERASEVAL(region), romdata.regionlength); /* or if it's sufficiently small (<= 4MB) */ else if (romdata.regionlength <= 0x400000) memset(romdata.regionbase, 0, romdata.regionlength); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(romdata.regionbase, romdata.regionlength); #endif /* now process the entries in the region */ if (ROMREGION_ISROMDATA(region)) process_rom_entries(&romdata, region + 1); else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(&romdata, region + 1); /* add this region to the list */ if (regiontype < REGION_MAX) regionlist[regiontype] = region; } /* post-process the regions */ for (regnum = 0; regnum < REGION_MAX; regnum++) if (regionlist[regnum]) { debugload("Post-processing region %02X\n", regnum); romdata.regionlength = memory_region_length(regnum); romdata.regionbase = memory_region(regnum); region_post_process(&romdata, regionlist[regnum]); } /* display the results and exit */ total_rom_load_warnings = romdata.warnings; display_rom_load_results(&romdata); }
static void process_disk_entries(rom_load_data *romdata, const rom_entry *romp) { /* loop until we hit the end of this region */ while (!ROMENTRY_ISREGIONEND(romp)) { /* handle files */ if (ROMENTRY_ISFILE(romp)) { chd_file *source, *diff = NULL; chd_header header; char filename[1024]; char acthash[HASH_BUF_SIZE]; chd_error err; /* make the filename of the source */ sprintf(filename, "%s.chd", ROM_GETNAME(romp)); /* first open the source drive */ debugload("Opening disk image: %s\n", filename); err = open_disk_image(Machine->gamedrv, romp, &source); if (err != CHDERR_NONE) { if (err == CHDERR_UNSUPPORTED_VERSION) sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s UNSUPPORTED CHD VERSION\n", filename); else sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s NOT FOUND\n", filename); /* if this is NO_DUMP, keep going, though the system may not be able to handle it */ if (hash_data_has_info(ROM_GETHASHDATA(romp), HASH_INFO_NO_DUMP)) romdata->warnings++; else romdata->errors++; romp++; continue; } /* get the header and extract the MD5/SHA1 */ header = *chd_get_header(source); hash_data_clear(acthash); hash_data_insert_binary_checksum(acthash, HASH_MD5, header.md5); hash_data_insert_binary_checksum(acthash, HASH_SHA1, header.sha1); /* verify the MD5 */ if (!hash_data_is_equal(ROM_GETHASHDATA(romp), acthash, 0)) { sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s WRONG CHECKSUMS:\n", filename); dump_wrong_and_correct_checksums(romdata, ROM_GETHASHDATA(romp), acthash); romdata->warnings++; } else if (hash_data_has_info(ROM_GETHASHDATA(romp), HASH_INFO_BAD_DUMP)) { sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s CHD NEEDS REDUMP\n", filename); romdata->warnings++; } /* if not read-only, make the diff file */ if (!DISK_ISREADONLY(romp)) { /* make the filename of the diff */ sprintf(filename, "%s.dif", ROM_GETNAME(romp)); /* try to open the diff */ debugload("Opening differencing image: %s\n", filename); err = chd_open(filename, CHD_OPEN_READWRITE, source, &diff); if (err != CHDERR_NONE) { /* didn't work; try creating it instead */ debugload("Creating differencing image: %s\n", filename); err = chd_create(filename, 0, 0, CHDCOMPRESSION_NONE, source); if (err != CHDERR_NONE) { if (err == CHDERR_UNSUPPORTED_VERSION) sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s UNSUPPORTED CHD VERSION\n", filename); else sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s: CAN'T CREATE DIFF FILE\n", filename); romdata->errors++; romp++; continue; } /* open the newly-created diff file */ debugload("Opening differencing image: %s\n", filename); err = chd_open(filename, CHD_OPEN_READWRITE, source, &diff); if (err != CHDERR_NONE) { if (err == CHDERR_UNSUPPORTED_VERSION) sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s UNSUPPORTED CHD VERSION\n", filename); else sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s: CAN'T OPEN DIFF FILE\n", filename); romdata->errors++; romp++; continue; } } } /* we're okay, set the handle */ debugload("Assigning to handle %d\n", DISK_GETINDEX(romp)); disk_handle[DISK_GETINDEX(romp)] = DISK_ISREADONLY(romp) ? source : diff; romp++; } } }