示例#1
0
void software_list_device::device_validity_check(validity_checker &valid) const
{
	// add to the global map whenever we check a list so we don't re-check
	// it in the future
	if (valid.already_checked(std::string("softlist/").append(m_list_name).c_str()))
		return;

	// do device validation only in case of validate command
	if (!valid.validate_all())
		return;

	// actually do the validate
	const_cast<software_list_device *>(this)->internal_validity_check(valid);
}
示例#2
0
void device_gfx_interface::interface_validity_check(validity_checker &valid) const
{
	// validate palette tag
	if (m_palette_tag == NULL)
		osd_printf_error("No palette specified for device '%s'\n", device().tag());
	else
	{
		palette_device *palette;
		if (m_palette_is_sibling)
			palette = device().owner()->subdevice<palette_device>(m_palette_tag);
		else
			palette = device().subdevice<palette_device>(m_palette_tag);

		if (palette == NULL)
			osd_printf_error("Device '%s' specifies nonexistent %sdevice '%s' as palette\n",
								device().tag(),
								(m_palette_is_sibling ? "sibling " : "sub"),
								m_palette_tag);
	}

	if (!m_gfxdecodeinfo)
		return;

	// validate graphics decoding entries
	for (int gfxnum = 0; gfxnum < MAX_GFX_ELEMENTS && m_gfxdecodeinfo[gfxnum].gfxlayout != NULL; gfxnum++)
	{
		const gfx_decode_entry &gfx = m_gfxdecodeinfo[gfxnum];
		const gfx_layout &layout = *gfx.gfxlayout;

		// currently we are unable to validate RAM-based entries
		const char *region = gfx.memory_region;
		if (region != NULL && GFXENTRY_ISROM(gfx.flags))
		{
			// resolve the region
			astring gfxregion;
			if (GFXENTRY_ISDEVICE(gfx.flags))
				device().subtag(gfxregion, region);
			else
				device().owner()->subtag(gfxregion, region);

			UINT32 region_length = valid.region_length(gfxregion);
			if (region_length == 0)
				osd_printf_error("gfx[%d] references nonexistent region '%s'\n", gfxnum, gfxregion.cstr());

			// if we have a valid region, and we're not using auto-sizing, check the decode against the region length
			else if (!IS_FRAC(layout.total))
			{
				// determine which plane is at the largest offset
				int start = 0;
				for (int plane = 0; plane < layout.planes; plane++)
					if (layout.planeoffset[plane] > start)
						start = layout.planeoffset[plane];
				start &= ~(layout.charincrement - 1);

				// determine the total length based on this info
				int len = layout.total * layout.charincrement;

				// do we have enough space in the region to cover the whole decode?
				int avail = region_length - (gfx.start & ~(layout.charincrement / 8 - 1));

				// if not, this is an error
				if ((start + len) / 8 > avail)
					osd_printf_error("gfx[%d] extends past allocated memory of region '%s'\n", gfxnum, region);
			}
		}

		int xscale = GFXENTRY_GETXSCALE(gfx.flags);
		int yscale = GFXENTRY_GETYSCALE(gfx.flags);

		// verify raw decode, which can only be full-region and have no scaling
		if (layout.planeoffset[0] == GFX_RAW)
		{
			if (layout.total != RGN_FRAC(1,1))
				osd_printf_error("gfx[%d] RAW layouts can only be RGN_FRAC(1,1)\n", gfxnum);
			if (xscale != 1 || yscale != 1)
				osd_printf_error("gfx[%d] RAW layouts do not support xscale/yscale\n", gfxnum);
		}

		// verify traditional decode doesn't have too many planes,
		// and has extended offset arrays if its width and/or height demand them
		else
		{
			if (layout.planes > MAX_GFX_PLANES)
				osd_printf_error("gfx[%d] planes > %d\n", gfxnum, MAX_GFX_PLANES);
			if (layout.width > MAX_GFX_SIZE && layout.extxoffs == NULL)
				osd_printf_error("gfx[%d] width > %d but missing extended xoffset info\n", gfxnum, MAX_GFX_SIZE);
			if (layout.height > MAX_GFX_SIZE && layout.extyoffs == NULL)
				osd_printf_error("gfx[%d] height > %d but missing extended yoffset info\n", gfxnum, MAX_GFX_SIZE);
		}
	}
}
示例#3
0
void device_memory_interface::interface_validity_check(validity_checker &valid) const
{
	bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true;

	// loop over all address spaces
	for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++)
	{
		const address_space_config *spaceconfig = space_config(spacenum);
		if (spaceconfig != NULL)
		{
			int datawidth = spaceconfig->m_databus_width;
			int alignunit = datawidth / 8;

			// construct the maps
			::address_map *map = global_alloc(::address_map(const_cast<device_t &>(device()), spacenum));

			// if this is an empty map, just skip it
			if (map->m_entrylist.first() == NULL)
			{
				global_free(map);
				continue;
			}

			// validate the global map parameters
			if (map->m_spacenum != spacenum)
				osd_printf_error("Space %d has address space %d handlers!\n", spacenum, map->m_spacenum);
			if (map->m_databits != datawidth)
				osd_printf_error("Wrong memory handlers provided for %s space! (width = %d, memory = %08x)\n", spaceconfig->m_name, datawidth, map->m_databits);

			// loop over entries and look for errors
			for (address_map_entry *entry = map->m_entrylist.first(); entry != NULL; entry = entry->next())
			{
				UINT32 bytestart = spaceconfig->addr2byte(entry->m_addrstart);
				UINT32 byteend = spaceconfig->addr2byte_end(entry->m_addrend);

				// look for overlapping entries
				if (!detected_overlap)
				{
					address_map_entry *scan;
					for (scan = map->m_entrylist.first(); scan != entry; scan = scan->next())
						if (entry->m_addrstart <= scan->m_addrend && entry->m_addrend >= scan->m_addrstart &&
							((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) ||
								(entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE)))
						{
							osd_printf_warning("%s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type);
							detected_overlap = true;
							break;
						}
				}

				// look for inverted start/end pairs
				if (byteend < bytestart)
					osd_printf_error("Wrong %s memory read handler start = %08x > end = %08x\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend);

				// look for misaligned entries
				if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1))
					osd_printf_error("Wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, alignunit);

				// if this is a program space, auto-assign implicit ROM entries
				if (entry->m_read.m_type == AMH_ROM && entry->m_region == NULL)
				{
					entry->m_region = device().tag();
					entry->m_rgnoffs = entry->m_addrstart;
				}

				// if this entry references a memory region, validate it
				if (entry->m_region != NULL && entry->m_share == 0)
				{
					// make sure we can resolve the full path to the region
					bool found = false;
					astring entry_region;
					entry->m_devbase.subtag(entry_region, entry->m_region);

					// look for the region
					device_iterator deviter(device().mconfig().root_device());
					for (device_t *device = deviter.first(); device != NULL; device = deviter.next())
						for (const rom_entry *romp = rom_first_region(*device); romp != NULL && !found; romp = rom_next_region(romp))
						{
							astring fulltag;
							rom_region_name(fulltag, *device, romp);
							if (fulltag == entry_region)
							{
								// verify the address range is within the region's bounds
								offs_t length = ROMREGION_GETLENGTH(romp);
								if (entry->m_rgnoffs + (byteend - bytestart + 1) > length)
									osd_printf_error("%s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length);
								found = true;
							}
						}

					// error if not found
					if (!found)
						osd_printf_error("%s space memory map entry %X-%X references non-existant region '%s'\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region);
				}

				// make sure all devices exist
				// FIXME: This doesn't work! AMH_DEVICE_DELEGATE entries don't even set m_tag, the device tag is inside the proto-delegate
				if (entry->m_read.m_type == AMH_DEVICE_DELEGATE && entry->m_read.m_tag != NULL)
				{
					astring temp(entry->m_read.m_tag);
					if (device().siblingdevice(temp) == NULL)
						osd_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_read.m_tag);
				}
				if (entry->m_write.m_type == AMH_DEVICE_DELEGATE && entry->m_write.m_tag != NULL)
				{
					astring temp(entry->m_write.m_tag);
					if (device().siblingdevice(temp) == NULL)
						osd_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_write.m_tag);
				}

				// make sure ports exist
//              if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) ||
//                  (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL))
//                  osd_printf_error("%s space memory map entry references nonexistant port tag '%s'\n", spaceconfig->m_name, entry->m_read.m_tag);

				// validate bank and share tags
				if (entry->m_read.m_type == AMH_BANK)
					valid.validate_tag(entry->m_read.m_tag);
				if (entry->m_write.m_type == AMH_BANK)
					valid.validate_tag(entry->m_write.m_tag);
				if (entry->m_share != NULL)
					valid.validate_tag(entry->m_share);
			}

			// release the address map
			global_free(map);
		}
	}
}
示例#4
0
文件: addrmap.cpp 项目: NULUSIOS/mame
void address_map::map_validity_check(validity_checker &valid, const device_t &device, address_spacenum spacenum) const
{
	// it's safe to assume here that the device has a memory interface and a config for this space
	const address_space_config &spaceconfig = *device.memory().space_config(spacenum);
	int datawidth = spaceconfig.m_databus_width;
	int alignunit = datawidth / 8;

	bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true;

	// if this is an empty map, just ignore it
	if (m_entrylist.first() == nullptr)
		return;

	// validate the global map parameters
	if (m_spacenum != spacenum)
		osd_printf_error("Space %d has address space %d handlers!\n", spacenum, m_spacenum);
	if (m_databits != datawidth)
		osd_printf_error("Wrong memory handlers provided for %s space! (width = %d, memory = %08x)\n", spaceconfig.m_name, datawidth, m_databits);

	// loop over entries and look for errors
	for (address_map_entry &entry : m_entrylist)
	{
		UINT32 bytestart = spaceconfig.addr2byte(entry.m_addrstart);
		UINT32 byteend = spaceconfig.addr2byte_end(entry.m_addrend);

		// look for overlapping entries
		if (!detected_overlap)
		{
			for (address_map_entry &scan : m_entrylist)
			{
				if (&scan == &entry)
					break;
				if (entry.m_addrstart <= scan.m_addrend && entry.m_addrend >= scan.m_addrstart &&
					((entry.m_read.m_type != AMH_NONE && scan.m_read.m_type != AMH_NONE) ||
						(entry.m_write.m_type != AMH_NONE && scan.m_write.m_type != AMH_NONE)))
				{
					osd_printf_warning("%s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, entry.m_read.m_type, entry.m_write.m_type, scan.m_addrstart, scan.m_addrend, scan.m_read.m_type, scan.m_write.m_type);
					detected_overlap = true;
					break;
				}
			}
		}

		// look for inverted start/end pairs
		if (byteend < bytestart)
			osd_printf_error("Wrong %s memory read handler start = %08x > end = %08x\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend);

		// look for misaligned entries
		if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1))
			osd_printf_error("Wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, alignunit);

		// if this is a program space, auto-assign implicit ROM entries
		if (entry.m_read.m_type == AMH_ROM && entry.m_region == nullptr)
		{
			entry.m_region = device.tag();
			entry.m_rgnoffs = entry.m_addrstart;
		}

		// if this entry references a memory region, validate it
		if (entry.m_region != nullptr && entry.m_share == nullptr)
		{
			// make sure we can resolve the full path to the region
			bool found = false;
			std::string entry_region = entry.m_devbase.subtag(entry.m_region);

			// look for the region
			for (device_t &dev : device_iterator(device.mconfig().root_device()))
				for (const rom_entry *romp = rom_first_region(dev); romp != nullptr && !found; romp = rom_next_region(romp))
				{
					if (rom_region_name(dev, romp) == entry_region)
					{
						// verify the address range is within the region's bounds
						offs_t length = ROMREGION_GETLENGTH(romp);
						if (entry.m_rgnoffs + (byteend - bytestart + 1) > length)
							osd_printf_error("%s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, entry.m_region, length);
						found = true;
					}
				}

			// error if not found
			if (!found)
				osd_printf_error("%s space memory map entry %X-%X references non-existant region '%s'\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, entry.m_region);
		}

		// make sure all devices exist
		if (entry.m_read.m_type == AMH_DEVICE_DELEGATE)
		{
			// extract the device tag from the proto-delegate
			const char *devtag = nullptr;
			switch (entry.m_read.m_bits)
			{
				case 8: devtag = entry.m_rproto8.device_name(); break;
				case 16: devtag = entry.m_rproto16.device_name(); break;
				case 32: devtag = entry.m_rproto32.device_name(); break;
				case 64: devtag = entry.m_rproto64.device_name(); break;
			}
			if (entry.m_devbase.subdevice(devtag) == nullptr)
				osd_printf_error("%s space memory map entry reads from nonexistent device '%s'\n", spaceconfig.m_name,
					devtag != nullptr ? devtag : "<unspecified>");
		}
		if (entry.m_write.m_type == AMH_DEVICE_DELEGATE)
		{
			// extract the device tag from the proto-delegate
			const char *devtag = nullptr;
			switch (entry.m_write.m_bits)
			{
				case 8: devtag = entry.m_wproto8.device_name(); break;
				case 16: devtag = entry.m_wproto16.device_name(); break;
				case 32: devtag = entry.m_wproto32.device_name(); break;
				case 64: devtag = entry.m_wproto64.device_name(); break;
			}
			if (entry.m_devbase.subdevice(devtag) == nullptr)
				osd_printf_error("%s space memory map entry writes to nonexistent device '%s'\n", spaceconfig.m_name,
					devtag != nullptr ? devtag : "<unspecified>");
		}
		if (entry.m_setoffsethd.m_type == AMH_DEVICE_DELEGATE)
		{
			// extract the device tag from the proto-delegate
			const char *devtag = entry.m_soproto.device_name();
			if (entry.m_devbase.subdevice(devtag) == nullptr)
				osd_printf_error("%s space memory map entry references nonexistent device '%s'\n", spaceconfig.m_name,
					devtag != nullptr ? devtag : "<unspecified>");
		}

		// make sure ports exist
//      if ((entry.m_read.m_type == AMH_PORT && entry.m_read.m_tag != nullptr && portlist.find(entry.m_read.m_tag) == nullptr) ||
//          (entry.m_write.m_type == AMH_PORT && entry.m_write.m_tag != nullptr && portlist.find(entry.m_write.m_tag) == nullptr))
//          osd_printf_error("%s space memory map entry references nonexistent port tag '%s'\n", spaceconfig.m_name, entry.m_read.m_tag);

		// validate bank and share tags
		if (entry.m_read.m_type == AMH_BANK)
			valid.validate_tag(entry.m_read.m_tag);
		if (entry.m_write.m_type == AMH_BANK)
			valid.validate_tag(entry.m_write.m_tag);
		if (entry.m_share != nullptr)
			valid.validate_tag(entry.m_share);
	}
}