diff --git a/hash/vboy.xml b/hash/vboy.xml index 273a1876927..fbb1b06b721 100644 --- a/hash/vboy.xml +++ b/hash/vboy.xml @@ -26,10 +26,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -42,8 +40,7 @@ According to Planet Virtual Boy, the following undumped protos exist Nintendo - - + @@ -57,10 +54,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -73,11 +68,10 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - + @@ -90,10 +84,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -108,10 +100,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -124,10 +114,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -142,10 +130,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -158,12 +144,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - - - @@ -178,8 +160,7 @@ According to Planet Virtual Boy, the following undumped protos exist - - + @@ -191,10 +172,8 @@ According to Planet Virtual Boy, the following undumped protos exist Bullet-Proof Software - - + - @@ -209,12 +188,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - - - @@ -227,10 +202,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -243,10 +216,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -259,10 +230,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -275,12 +244,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - - - @@ -290,8 +255,7 @@ According to Planet Virtual Boy, the following undumped protos exist 1995 Nintendo - - + @@ -305,12 +269,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - - - @@ -323,12 +283,10 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - - + @@ -341,12 +299,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - - - @@ -359,10 +313,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -380,12 +332,10 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - - + @@ -398,10 +348,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -414,10 +362,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -430,11 +376,10 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - + @@ -449,10 +394,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -465,10 +408,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -481,10 +422,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - @@ -497,12 +436,8 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - - - @@ -515,11 +450,10 @@ According to Planet Virtual Boy, the following undumped protos exist - - + - + @@ -532,8 +466,7 @@ According to Planet Virtual Boy, the following undumped protos exist - - + diff --git a/src/devices/bus/generic/slot.h b/src/devices/bus/generic/slot.h index 5704347e826..871d4f8e2cb 100644 --- a/src/devices/bus/generic/slot.h +++ b/src/devices/bus/generic/slot.h @@ -7,6 +7,8 @@ #include "softlist_dev.h" +#include + /*************************************************************************** TYPE DEFINITIONS @@ -15,6 +17,41 @@ class device_generic_cart_interface : public device_interface { public: + // TODO: find a better home for this helper + template + static void install_non_power_of_two( + offs_t length, + offs_t decode_limit, + offs_t decode_mask, + offs_t decode_offset, + offs_t base, + T &&install) + { + assert(!(decode_limit & base)); + for (offs_t remain = length, start = 0U; remain && (decode_limit >= start); ) + { + unsigned const msb(31 - count_leading_zeros(u32(remain))); + offs_t const chunk(offs_t(1) << msb); + offs_t range((chunk - 1) & decode_limit); + offs_t mirror(decode_limit & ~decode_mask & ~range); + + // TODO: deal with small offsets - probably requires breaking into smaller chunks with mirror set + if (decode_offset & range) + throw emu_fatalerror("Can't deal with offset/size combination\n"); + + range = (range << Shift) | ((offs_t(1) << Shift) - 1); + mirror <<= Shift; + offs_t const begin(start << Shift); + offs_t const end(begin | range); + offs_t const src(start | ((chunk - 1) & decode_offset)); + + install(base | begin, base | end, mirror, src); + + remain ^= chunk; + start ^= chunk; + } + } + // construction/destruction virtual ~device_generic_cart_interface(); diff --git a/src/devices/bus/vboy/rom.cpp b/src/devices/bus/vboy/rom.cpp index 6c6117c8a9b..e709ad9ed26 100644 --- a/src/devices/bus/vboy/rom.cpp +++ b/src/devices/bus/vboy/rom.cpp @@ -1,59 +1,207 @@ // license:BSD-3-Clause // copyright-holders:Fabio Priuli -/*********************************************************************************************************** - - - Nintendo Virtual Boy cart emulation - - - ***********************************************************************************************************/ - - +/*************************************************************************** + Virtual Boy cartridges + ***************************************************************************/ #include "emu.h" #include "rom.h" +#include "bus/generic/slot.h" -//------------------------------------------------- -// vboy_rom_device - constructor -//------------------------------------------------- - -DEFINE_DEVICE_TYPE(VBOY_ROM_STD, vboy_rom_device, "vboy_rom", "Nintendo Virtual Boy Carts") -DEFINE_DEVICE_TYPE(VBOY_ROM_EEPROM, vboy_eeprom_device, "vboy_eeprom", "Nintendo Virtual Boy Carts + EEPROM") +//#define VERBOSE 1 +#include "logmacro.h" -vboy_rom_device::vboy_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock), device_vboy_cart_interface(mconfig, *this) -{ -} +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** -vboy_rom_device::vboy_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : vboy_rom_device(mconfig, VBOY_ROM_STD, tag, owner, clock) -{ -} +DEFINE_DEVICE_TYPE(VBOY_FLAT_ROM, vboy_flat_rom_device, "vboy_flatrom", "Nintendo Virtual Boy Flat ROM Cartridge") +DEFINE_DEVICE_TYPE(VBOY_FLAT_ROM_SRAM, vboy_flat_rom_sram_device, "vboy_flatrom_sram", "Nintendo Virtual Boy Flat ROM Cartridge with Backup SRAM") -vboy_eeprom_device::vboy_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : vboy_rom_device(mconfig, VBOY_ROM_EEPROM, tag, owner, clock) + + +//************************************************************************** +// vboy_flat_rom_device +//************************************************************************** + +vboy_flat_rom_device::vboy_flat_rom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + vboy_flat_rom_device(mconfig, VBOY_FLAT_ROM, tag, owner, clock) { } -/*------------------------------------------------- - mapper specific handlers - -------------------------------------------------*/ - -READ32_MEMBER(vboy_rom_device::read_cart) +vboy_flat_rom_device::vboy_flat_rom_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, type, tag, owner, clock), + device_vboy_cart_interface(mconfig, *this) { - return m_rom[offset & m_rom_mask]; } -READ32_MEMBER(vboy_eeprom_device::read_eeprom) +image_init_result vboy_flat_rom_device::load() { - return m_eeprom[offset]; + // if the host has supplied a ROM space, install with appropriate mirroring + memory_region *const romregion(memregion("^rom")); + if (rom_space() && romregion) + { + // the slot should have verified that the ROM is a supported size + assert(!(romregion->bytes() & 0x0000'0003U)); + assert(romregion->bytes() <= 0x0100'0000U); + + // this should fail a validity check + assert(!(rom_base() & 0x00ff'ffff)); + + device_generic_cart_interface::install_non_power_of_two<2>( + romregion->bytes() >> 2, + 0x00ff'ffff >> 2, + 0, + 0, + rom_base(), + [this, rom = reinterpret_cast(romregion->base())] (offs_t begin, offs_t end, offs_t mirror, offs_t src) + { + LOG( + "Install ROM 0x%08X-0x%08X at 0x%08X-0x%08X mirror %08X\n", + src << 2, + (src << 2) + (end - begin), + begin, + end, + mirror); + rom_space()->install_rom(begin, end, mirror, &rom[src]); + }); + } + + return image_init_result::PASS; } -WRITE32_MEMBER(vboy_eeprom_device::write_eeprom) +void vboy_flat_rom_device::device_start() { - COMBINE_DATA(&m_eeprom[offset]); +} + + + +//************************************************************************** +// vboy_flat_rom_sram_device +//************************************************************************** + +vboy_flat_rom_sram_device::vboy_flat_rom_sram_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + vboy_flat_rom_device(mconfig, VBOY_FLAT_ROM_SRAM, tag, owner, clock) +{ +} + + +image_init_result vboy_flat_rom_sram_device::load() +{ + image_init_result const result(vboy_flat_rom_device::load()); + if (image_init_result::PASS != result) + return result; + + memory_region *const sramregion(memregion("^sram")); + if (sramregion) + { + // this should fail a validity check + assert(!(chip_base() & 0x00ff'ffff)); + + switch (sramregion->bitwidth()) + { + case 8: + if (chip_space()) + { + device_generic_cart_interface::install_non_power_of_two<2>( + sramregion->bytes(), + 0x00ff'ffff >> 2, + 0, + 0, + chip_base(), + [this, sramregion] (offs_t begin, offs_t end, offs_t mirror, offs_t src) + { + LOG( + "Install SRAM 0x%08X-0x%08X at 0x%08X-0x%08X mirror %08X\n", + src, + src + ((end - begin) >> 2), + begin, + end, + mirror); + u8 *const base(&reinterpret_cast(sramregion->base())[src]); + chip_space()->install_readwrite_handler( + begin, + end, + read8sm_delegate(*this, NAME([base] (offs_t offset) { return base[offset]; })), + write8sm_delegate(*this, NAME([base] (offs_t offset, u8 data) { base[offset] = data; })), + 0x0000'00ff); + }); + } + save_pointer(NAME(&sramregion->as_u8()), sramregion->bytes()); + break; + + case 16: + if (chip_space()) + { + device_generic_cart_interface::install_non_power_of_two<2>( + sramregion->bytes() >> 1, + 0x00ff'ffff >> 2, + 0, + 0, + chip_base(), + [this, sramregion] (offs_t begin, offs_t end, offs_t mirror, offs_t src) + { + LOG( + "Install SRAM 0x%08X-0x%08X at 0x%08X-0x%08X mirror %08X\n", + src << 1, + (src << 1) + ((end - begin) >> 1), + begin, + end, + mirror); + u16 *const base(&reinterpret_cast(sramregion->base())[src]); + chip_space()->install_readwrite_handler( + begin, + end, + read16s_delegate(*this, NAME([base] (offs_t offset, u16 mem_mask) { return base[offset]; })), + write16s_delegate(*this, NAME([base] (offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(base + offset); })), + 0x0000'ffff); + }); + } + save_pointer(NAME(&sramregion->as_u16()), sramregion->bytes() >> 1); + break; + + case 32: + if (chip_space()) + { + device_generic_cart_interface::install_non_power_of_two<2>( + sramregion->bytes() >> 2, + 0x00ff'ffff >> 2, + 0, + 0, + chip_base(), + [this, sram = reinterpret_cast(sramregion->base())] (offs_t begin, offs_t end, offs_t mirror, offs_t src) + { + LOG( + "Install SRAM 0x%08X-0x%08X at 0x%08X-0x%08X mirror %08X\n", + src << 2, + (src << 2) + (end - begin), + begin, + end, + mirror); + chip_space()->install_ram(begin, end, mirror, &sram[src]); + }); + } + save_pointer(NAME(&sramregion->as_u32()), sramregion->bytes() >> 2); + break; + + default: + throw emu_fatalerror("Unsupported Virtual Boy cartridge backup RAM width\n"); + } + + battery_load(sramregion->base(), sramregion->bytes(), nullptr); + } + + return image_init_result::PASS; +} + + +void vboy_flat_rom_sram_device::unload() +{ + memory_region *const sramregion(memregion("^sram")); + if (sramregion) + battery_save(sramregion->base(), sramregion->bytes()); } diff --git a/src/devices/bus/vboy/rom.h b/src/devices/bus/vboy/rom.h index 6963a09fb9c..79ad95f2e9a 100644 --- a/src/devices/bus/vboy/rom.h +++ b/src/devices/bus/vboy/rom.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Vas Crabb #ifndef MAME_BUS_VBOY_ROM_H #define MAME_BUS_VBOY_ROM_H @@ -8,41 +8,43 @@ #include "slot.h" -// ======================> vboy_rom_device +//************************************************************************** +// CLASS DECLARATIONS +//************************************************************************** -class vboy_rom_device : public device_t, - public device_vboy_cart_interface +class vboy_flat_rom_device : public device_t, public device_vboy_cart_interface { public: - // construction/destruction - vboy_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + vboy_flat_rom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); - // reading and writing - virtual DECLARE_READ32_MEMBER(read_cart) override; + // device_vboy_cart_interface implementation + virtual image_init_result load() override ATTR_COLD; protected: - vboy_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + vboy_flat_rom_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock); - // device-level overrides - virtual void device_start() override { } + // device_t implementation + virtual void device_start() override ATTR_COLD; }; -// ======================> vboy_eeprom_device -class vboy_eeprom_device : public vboy_rom_device +class vboy_flat_rom_sram_device : public vboy_flat_rom_device { public: - // construction/destruction - vboy_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + vboy_flat_rom_sram_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); - // reading and writing - virtual DECLARE_READ32_MEMBER(read_eeprom) override; - virtual DECLARE_WRITE32_MEMBER(write_eeprom) override; + // device_vboy_cart_interface implementation + virtual image_init_result load() override ATTR_COLD; + virtual void unload() override ATTR_COLD; }; -// device type definition -DECLARE_DEVICE_TYPE(VBOY_ROM_STD, vboy_rom_device) -DECLARE_DEVICE_TYPE(VBOY_ROM_EEPROM, vboy_eeprom_device) + +//************************************************************************** +// DEVICE TYPE DECLARATIONS +//************************************************************************** + +DECLARE_DEVICE_TYPE(VBOY_FLAT_ROM, vboy_flat_rom_device) +DECLARE_DEVICE_TYPE(VBOY_FLAT_ROM_SRAM, vboy_flat_rom_sram_device) #endif // MAME_BUS_VBOY_ROM_H diff --git a/src/devices/bus/vboy/slot.cpp b/src/devices/bus/vboy/slot.cpp index cf0c667e880..c30ec18e34c 100644 --- a/src/devices/bus/vboy/slot.cpp +++ b/src/devices/bus/vboy/slot.cpp @@ -1,250 +1,172 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli -/*********************************************************************************************************** - - Nintendo Virtual Boy cart emulation - (through slot devices) - - ***********************************************************************************************************/ - +// copyright-holders:Vas Crabb +/*************************************************************************** + Virtual Boy cartridge slot + ***************************************************************************/ #include "emu.h" #include "slot.h" +#include "emuopts.h" +#include "romload.h" + +#include + +//#define VERBOSE 1 +#include "logmacro.h" + + //************************************************************************** // GLOBAL VARIABLES //************************************************************************** DEFINE_DEVICE_TYPE(VBOY_CART_SLOT, vboy_cart_slot_device, "vboy_cart_slot", "Nintendo Virtual Boy Cartridge Slot") -//************************************************************************** -// vboy cartridges Interface -//************************************************************************** - -//------------------------------------------------- -// device_vboy_cart_interface - constructor -//------------------------------------------------- - -device_vboy_cart_interface::device_vboy_cart_interface(const machine_config &mconfig, device_t &device) : - device_interface(device, "vboycart"), - m_rom(nullptr), - m_rom_size(0), - m_rom_mask(0) -{ -} - - -//------------------------------------------------- -// ~device_vboy_cart_interface - destructor -//------------------------------------------------- - -device_vboy_cart_interface::~device_vboy_cart_interface() -{ -} - -//------------------------------------------------- -// rom_alloc - alloc the space for the cart -//------------------------------------------------- - -void device_vboy_cart_interface::rom_alloc(uint32_t size, const char *tag) -{ - if (m_rom == nullptr) - { - m_rom = (uint32_t *)device().machine().memory().region_alloc(std::string(tag).append(VBOYSLOT_ROM_REGION_TAG).c_str(), size, 4, ENDIANNESS_LITTLE)->base(); - m_rom_size = size/4; - m_rom_mask = m_rom_size - 1; - } -} - - -//------------------------------------------------- -// ram_alloc - alloc the space for the ram -//------------------------------------------------- - -void device_vboy_cart_interface::eeprom_alloc(uint32_t size) -{ - m_eeprom.resize(size/sizeof(uint32_t)); -} - //************************************************************************** -// LIVE DEVICE +// vboy_cart_slot_device //************************************************************************** -//------------------------------------------------- -// vboy_cart_slot_device - constructor -//------------------------------------------------- -vboy_cart_slot_device::vboy_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : +vboy_cart_slot_device::vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, VBOY_CART_SLOT, tag, owner, clock), device_image_interface(mconfig, *this), device_single_card_slot_interface(mconfig, *this), - m_type(VBOY_STD), + m_intcro(*this), + m_exp_space(*this, finder_base::DUMMY_TAG, -1, 32), + m_chip_space(*this, finder_base::DUMMY_TAG, -1, 32), + m_rom_space(*this, finder_base::DUMMY_TAG, -1, 32), + m_exp_base(0U), + m_chip_base(0U), + m_rom_base(0U), m_cart(nullptr) { } -//------------------------------------------------- -// vboy_cart_slot_device - destructor -//------------------------------------------------- - -vboy_cart_slot_device::~vboy_cart_slot_device() +image_init_result vboy_cart_slot_device::call_load() { + if (!m_cart) + return image_init_result::PASS; + + memory_region *romregion(loaded_through_softlist() ? memregion("rom") : nullptr); + if (loaded_through_softlist() && !romregion) + { + seterror(IMAGE_ERROR_INVALIDIMAGE, "Software list item has no 'rom' data area"); + return image_init_result::FAIL; + } + + u32 const len(loaded_through_softlist() ? romregion->bytes() : length()); + if ((0x0000'0003 & len) || (0x0100'0000 < len)) + { + seterror(IMAGE_ERROR_UNSUPPORTED, "Unsupported cartridge size (must be a multiple of 4 bytes no larger than 16 MiB)"); + return image_init_result::FAIL; + } + + if (!loaded_through_softlist()) + { + LOG("Allocating %u byte cartridge ROM region\n", len); + romregion = machine().memory().region_alloc(subtag("rom").c_str(), len, 4, ENDIANNESS_LITTLE); + u32 const cnt(fread(romregion->base(), len)); + if (cnt != len) + { + seterror(IMAGE_ERROR_UNSPECIFIED, "Error reading cartridge file"); + return image_init_result::FAIL; + } + } + + return m_cart->load(); +} + + +void vboy_cart_slot_device::call_unload() +{ + if (m_cart) + m_cart->unload(); +} + + +void vboy_cart_slot_device::device_validity_check(validity_checker &valid) const +{ + if (m_exp_base & 0x00ff'ffff) + osd_printf_error("EXP base address 0x%X is not on a 24-bit boundary\n", m_exp_base); + + if (m_chip_base & 0x00ff'ffff) + osd_printf_error("CHIP base address 0x%X is not on a 24-bit boundary\n", m_chip_base); + + if (m_rom_base & 0x00ff'ffff) + osd_printf_error("ROM base address 0x%X is not on a 24-bit boundary\n", m_rom_base); +} + + +void vboy_cart_slot_device::device_resolve_objects() +{ + m_intcro.resolve_safe(); } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- void vboy_cart_slot_device::device_start() { + if (!m_exp_space && ((m_exp_space.finder_tag() != finder_base::DUMMY_TAG) || (m_exp_space.spacenum() >= 0))) + throw emu_fatalerror("%s: Address space %d of device %s not found (EXP)\n", tag(), m_exp_space.spacenum(), m_exp_space.finder_tag()); + + if (!m_chip_space && ((m_chip_space.finder_tag() != finder_base::DUMMY_TAG) || (m_chip_space.spacenum() >= 0))) + throw emu_fatalerror("%s: Address space %d of device %s not found (CHIP)\n", tag(), m_chip_space.spacenum(), m_chip_space.finder_tag()); + + if (!m_rom_space && ((m_rom_space.finder_tag() != finder_base::DUMMY_TAG) || (m_rom_space.spacenum() >= 0))) + throw emu_fatalerror("%s: Address space %d of device %s not found (ROM)\n", tag(), m_rom_space.spacenum(), m_rom_space.finder_tag()); + m_cart = get_card_device(); } -//------------------------------------------------- -// vboy PCB -//------------------------------------------------- - -struct vboy_slot -{ - int pcb_id; - const char *slot_option; -}; - -// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it -static const vboy_slot slot_list[] = -{ - { VBOY_STD, "vb_rom" }, - { VBOY_EEPROM, "vb_eeprom" } -}; - -static int vboy_get_pcb_id(const char *slot) -{ - for (auto & elem : slot_list) - { - if (!core_stricmp(elem.slot_option, slot)) - return elem.pcb_id; - } - - return 0; -} - -#if 0 -static const char *vboy_get_slot(int type) -{ - for (int i = 0; i < ARRAY_LENGTH(slot_list); i++) - { - if (slot_list[i].pcb_id == type) - return slot_list[i].slot_option; - } - - return "vb_rom"; -} -#endif - -/*------------------------------------------------- - call load - -------------------------------------------------*/ - -image_init_result vboy_cart_slot_device::call_load() -{ - if (m_cart) - { - uint8_t *ROM; - uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom"); - bool has_eeprom = loaded_through_softlist() && get_software_region("eeprom"); - - if (len > 0x200000) - { - seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); - return image_init_result::FAIL; - } - - // always alloc 0x200000 so to be able to directly map the region - // to the address map (speeding up emulation a bit) - m_cart->rom_alloc(0x200000, tag()); - if (has_eeprom) - m_cart->eeprom_alloc(get_software_region_length("eeprom")); - - ROM = (uint8_t *)m_cart->get_rom_base(); - - if (!loaded_through_softlist()) - fread(ROM, len); - else - memcpy(ROM, get_software_region("rom"), len); - - if (len < 0x080000) { memcpy(ROM + 0x040000, ROM, 0x040000); } - if (len < 0x100000) { memcpy(ROM + 0x080000, ROM, 0x080000); } - if (len < 0x200000) { memcpy(ROM + 0x100000, ROM, 0x100000); } - - if (!loaded_through_softlist()) - m_type = vboy_get_pcb_id("vb_rom"); - else - { - const char *pcb_name = get_feature("slot"); - if (pcb_name) - m_type = vboy_get_pcb_id(pcb_name); - } - - //printf("Type: %s\n", vboy_get_slot(m_type)); - - return image_init_result::PASS; - } - - return image_init_result::PASS; -} - - -/*------------------------------------------------- - call_unload - -------------------------------------------------*/ - -void vboy_cart_slot_device::call_unload() -{ - if (m_cart && m_cart->get_eeprom_base() && m_cart->get_eeprom_size()) - battery_save(m_cart->get_eeprom_base(), m_cart->get_eeprom_size() * 4); -} - -/*------------------------------------------------- - get default card software - -------------------------------------------------*/ - std::string vboy_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const { - return software_get_default_slot("vb_rom"); -} - -/*------------------------------------------------- - read - -------------------------------------------------*/ - -READ32_MEMBER(vboy_cart_slot_device::read_cart) -{ - if (m_cart) - return m_cart->read_cart(space, offset, mem_mask); + std::string const image_name(mconfig().options().image_option(instance_name()).value()); + software_part const *const part(!image_name.empty() ? find_software_item(image_name, true) : nullptr); + if (part) + { + //printf("[%s] Found software part for image name '%s'\n", tag(), image_name.c_str()); + for (rom_entry const &entry : part->romdata()) + { + if (ROMENTRY_ISREGION(entry) && (entry.name() == "sram")) + { + //printf("[%s] Found 'sram' data area, enabling cartridge backup RAM\n", tag()); + return "flatrom_sram"; + } + } + } else - return 0xffffffff; + { + //printf("[%s] No software part found for image name '%s'\n", tag(), image_name.c_str()); + } + + //printf("[%s] Assuming plain ROM cartridge\n", tag()); + return "flatrom"; } -/*------------------------------------------------- - read - -------------------------------------------------*/ -READ32_MEMBER(vboy_cart_slot_device::read_eeprom) + +//************************************************************************** +// device_vboy_cart_interface +//************************************************************************** + +void device_vboy_cart_interface::unload() { - if (m_cart) - return m_cart->read_eeprom(space, offset, mem_mask); - else - return 0xffffffff; } -/*------------------------------------------------- - write - -------------------------------------------------*/ -WRITE32_MEMBER(vboy_cart_slot_device::write_eeprom) +device_vboy_cart_interface::device_vboy_cart_interface(machine_config const &mconfig, device_t &device) : + device_interface(device, "vboycart"), + m_slot(dynamic_cast(device.owner())) { - if (m_cart) - m_cart->write_eeprom(space, offset, data, mem_mask); +} + + + +#include "rom.h" + +void vboy_carts(device_slot_interface &device) +{ + device.option_add_internal("flatrom", VBOY_FLAT_ROM); + device.option_add_internal("flatrom_sram", VBOY_FLAT_ROM_SRAM); } diff --git a/src/devices/bus/vboy/slot.h b/src/devices/bus/vboy/slot.h index e1f2716ace5..b804a8624d8 100644 --- a/src/devices/bus/vboy/slot.h +++ b/src/devices/bus/vboy/slot.h @@ -1,5 +1,62 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Vas Crabb +/*************************************************************************** + Virtual Boy cartridge slot + + 60-pin two-row connector (2.0 mm pin pitch, 1.6 mm row pitch) + + GND 1 2 GND + /WE0 3 4 /ES + /WE1 5 6 /CS + /RESET 7 8 VCC + /INTCRO 9 10 A23 + A19 11 12 A22 + A18 13 14 A21 + A8 15 16 A20 + A7 17 18 A9 + A6 19 20 A10 + A5 21 22 A11 + A4 23 24 A12 + A3 25 26 A13 + A2 27 28 A14 + A1 29 30 A15 + /RS 31 32 A16 + GND 33 34 A17 + /OE 35 36 VCC + D0 37 38 D15 + D8 39 40 D7 + D1 41 42 D14 + D9 43 44 D6 + D2 45 46 D13 + D10 47 48 D5 + D3 49 50 D12 + D11 51 52 D4 + VCC 53 54 VCC + ARO 55 56 ALO + ARI 57 58 ALI + GND 59 60 GND + + The cartridge effectively has three 16 bit 8 megaword (16 megabyte) read/ + write memory spaces. These are conventionally called EXP, CHIP and ROM. + Only 16 bit word accesses are possible (no lane select signals, and no + address bit A0). No commercial cartridges use the EXP space. The CHIP + space is used for cartridge SRAM (if present) and the ROM space is used + for program ROM. + + Space Select Read Enable Write Enable Mapping on Virtual Boy + EXP /ES /OE /WE1 0x0400'0000-0x04ff'ffff + CHIP /CS /OE /WE0 0x0600'0000-0x06ff'ffff + ROM /RS /OE /WE1 0x0700'0000-0x07ff'ffff + + Audio is passed through the cartridge, allowing cartridge hardware to + modify it. The output of the Virtual Boy's VSU sound chip is DC-coupled + to ARO (right) and ALO (left) via 4.7 kΩ resistors. ARI (right) and ALI + (left) are AC-coupled to the Virtual Boy's audio amplifier. + + VCC is +5V + /INTCRO is an interrupt input from the cartridge to the host + /RESET is bidirectional - the system or cartridge can pull it low + ***************************************************************************/ #ifndef MAME_BUS_VBOY_SLOT_H #define MAME_BUS_VBOY_SLOT_H @@ -8,115 +65,121 @@ #include "softlist_dev.h" -/*************************************************************************** - TYPE DEFINITIONS - ***************************************************************************/ +//************************************************************************** +// FORWARD DECLARATIONS +//************************************************************************** + +class device_vboy_cart_interface; -/* PCB */ -enum -{ - VBOY_STD = 0, - VBOY_EEPROM -}; +//************************************************************************** +// CLASS DECLARATIONS +//************************************************************************** -// ======================> device_vboy_cart_interface - -class device_vboy_cart_interface : public device_interface +class vboy_cart_slot_device : + public device_t, + public device_image_interface, + public device_single_card_slot_interface { public: - // construction/destruction - virtual ~device_vboy_cart_interface(); - - // reading and writing - virtual DECLARE_READ32_MEMBER(read_cart) { return 0xffffffff; } - virtual DECLARE_READ32_MEMBER(read_eeprom) { return 0xffffffff; } - virtual DECLARE_WRITE32_MEMBER(write_eeprom) { } - - void rom_alloc(uint32_t size, const char *tag); - void eeprom_alloc(uint32_t size); - uint32_t* get_rom_base() { return m_rom; } - uint32_t* get_eeprom_base() { return &m_eeprom[0]; } - uint32_t get_rom_size() { return m_rom_size; } - uint32_t get_eeprom_size() { return m_eeprom.size(); } - - void save_eeprom() { device().save_item(NAME(m_eeprom)); } - -protected: - device_vboy_cart_interface(const machine_config &mconfig, device_t &device); - - // internal state - uint32_t *m_rom; - uint32_t m_rom_size; - uint32_t m_rom_mask; - std::vector m_eeprom; -}; - - -// ======================> vboy_cart_slot_device - -class vboy_cart_slot_device : public device_t, - public device_image_interface, - public device_single_card_slot_interface -{ -public: - // construction/destruction template - vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) - : vboy_cart_slot_device(mconfig, tag, owner, 0) + vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) : + vboy_cart_slot_device(mconfig, tag, owner, 0U) { option_reset(); opts(*this); set_default_option(dflt); set_fixed(false); } - vboy_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); - virtual ~vboy_cart_slot_device(); + vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0U); - // image-level overrides + // configuration + auto intcro() { return m_intcro.bind(); } + template void set_exp(T &&tag, int no, offs_t base) { m_exp_space.set_tag(std::forward(tag), no); m_exp_base = base; } + template void set_chip(T &&tag, int no, offs_t base) { m_chip_space.set_tag(std::forward(tag), no); m_chip_base = base; } + template void set_rom(T &&tag, int no, offs_t base) { m_rom_space.set_tag(std::forward(tag), no); m_rom_base = base; } + + // device_image_interface implementation virtual image_init_result call_load() override; virtual void call_unload() override; - virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); } + virtual iodevice_t image_type() const noexcept override { return IO_CARTSLOT; } + virtual bool is_readable() const noexcept override { return true; } + virtual bool is_writeable() const noexcept override { return false; } + virtual bool is_creatable() const noexcept override { return false; } + virtual bool must_be_loaded() const noexcept override { return true; } + virtual bool is_reset_on_load() const noexcept override { return true; } + virtual char const *image_interface() const noexcept override { return "vboy_cart"; } + virtual char const *file_extensions() const noexcept override { return "vb,bin"; } - int get_type() { return m_type; } - - void save_eeprom() { if (m_cart && m_cart->get_eeprom_size()) m_cart->save_eeprom(); } - - virtual iodevice_t image_type() const override { return IO_CARTSLOT; } - virtual bool is_readable() const override { return 1; } - virtual bool is_writeable() const override { return 0; } - virtual bool is_creatable() const override { return 0; } - virtual bool must_be_loaded() const override { return 1; } - virtual bool is_reset_on_load() const override { return 1; } - virtual const char *image_interface() const override { return "vboy_cart"; } - virtual const char *file_extensions() const override { return "vb,bin"; } - - // slot interface overrides + // device_slot_interface implementation virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override; - // reading and writing - virtual DECLARE_READ32_MEMBER(read_cart); - virtual DECLARE_READ32_MEMBER(read_eeprom); - virtual DECLARE_WRITE32_MEMBER(write_eeprom); - protected: - // device-level overrides - virtual void device_start() override; + // device_t implementation + virtual void device_validity_check(validity_checker &valid) const override ATTR_COLD; + virtual void device_resolve_objects() override ATTR_COLD; + virtual void device_start() override ATTR_COLD; - int m_type; - device_vboy_cart_interface* m_cart; + // device_image_interface implementation + virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); } + +private: + devcb_write_line m_intcro; + optional_address_space m_exp_space; + optional_address_space m_chip_space; + optional_address_space m_rom_space; + offs_t m_exp_base; + offs_t m_chip_base; + offs_t m_rom_base; + + device_vboy_cart_interface *m_cart; + + friend class device_vboy_cart_interface; }; -// device type definition +class device_vboy_cart_interface : public device_interface +{ +public: + virtual image_init_result load() ATTR_COLD = 0; + virtual void unload() ATTR_COLD; + +protected: + device_vboy_cart_interface(machine_config const &mconfig, device_t &device); + + bool has_slot() const { return nullptr != m_slot; } + address_space *exp_space() { return m_slot ? m_slot->m_exp_space.target() : nullptr; } + address_space *chip_space() { return m_slot ? m_slot->m_chip_space.target() : nullptr; } + address_space *rom_space() { return m_slot ? m_slot->m_rom_space.target() : nullptr; } + offs_t exp_base() { return m_slot ? m_slot->m_exp_base : 0U; } + offs_t chip_base() { return m_slot ? m_slot->m_chip_base : 0U; } + offs_t rom_base() { return m_slot ? m_slot->m_rom_base : 0U; } + + void battery_load(void *buffer, int length, int fill) { assert(m_slot); m_slot->battery_load(buffer, length, fill); } + void battery_load(void *buffer, int length, void *def_buffer) { assert(m_slot); m_slot->battery_load(buffer, length, def_buffer); } + void battery_save(void const *buffer, int length) { assert(m_slot); m_slot->battery_save(buffer, length); } + + void intcro(int state) { if (m_slot) m_slot->m_intcro(state); } + +private: + vboy_cart_slot_device *const m_slot; +}; + + + +//************************************************************************** +// FUNCTION PROTOTYPES +//************************************************************************** + +void vboy_carts(device_slot_interface &device); + + + +//************************************************************************** +// DEVICE TYPE DECLARATIONS +//************************************************************************** + DECLARE_DEVICE_TYPE(VBOY_CART_SLOT, vboy_cart_slot_device) - -/*************************************************************************** - DEVICE CONFIGURATION MACROS - ***************************************************************************/ - -#define VBOYSLOT_ROM_REGION_TAG ":cart:rom" - #endif // MAME_BUS_VBOY_SLOT_H diff --git a/src/devices/bus/wswan/slot.h b/src/devices/bus/wswan/slot.h index b1be84a4f55..c6b4ee3d3c8 100644 --- a/src/devices/bus/wswan/slot.h +++ b/src/devices/bus/wswan/slot.h @@ -1,5 +1,66 @@ // license:BSD-3-Clause // copyright-holders:Wilbert Pol +/*************************************************************************** + Bandai WonderSwan cartridge slot + + 48-pin single-sided PCB edge connector + + The SoC maps the following ranges to the cartridge slot: + * Memory 0x10000-0x1ffff 8-bit read/write (typically used for cartridge SRAM) + 3-cycle access on WonderSwan, 1-cycle access on WonderSwan Color + * Memory 0x20000-0xfffff 16-bit read-only (writes not emitted) + * I/O 0xc0-0xff + + Pin Name Notes + 1 GND + 2 A15 + 3 A10 + 4 A11 + 5 A9 + 6 A8 + 7 A13 + 8 A14 + 9 A12 + 10 A7 + 11 A6 + 12 A5 + 13 A4 + 14 D15 + 15 D14 + 16 D7 + 17 D6 + 18 D5 + 19 D4 + 20 D3 + 21 D2 + 22 D1 + 23 D0 + 24 +3.3V + 25 +3.3V + 26 A0 + 27 A1 + 28 A2 + 29 A3 + 30 A19 + 31 A18 + 32 A17 + 33 A16 + 34 D8 + 35 D9 + 36 D10 + 37 D11 + 38 D12 + 39 D13 + 40 /RESET + 41 ? input used while authenticating cartridge + 42 IO/M low when accessing I/O ports + 43 /RD + 44 /WR + 45 /CART low when accessing cartridge + 46 INT usually used for RTC alarm interrupt + 47 CLK 384 kHz on WonderSwan + 48 GND + ***************************************************************************/ #ifndef MAME_BUS_WSWAN_SLOT_H #define MAME_BUS_WSWAN_SLOT_H diff --git a/src/devices/cpu/v810/v810.cpp b/src/devices/cpu/v810/v810.cpp index 19de0e7cfca..070048d6f55 100644 --- a/src/devices/cpu/v810/v810.cpp +++ b/src/devices/cpu/v810/v810.cpp @@ -1257,7 +1257,7 @@ void v810_device::device_start() { m_program = &space(AS_PROGRAM); m_cache = m_program->cache<2, 0, ENDIANNESS_LITTLE>(); - m_io = &space(AS_IO); + m_io = has_space(AS_IO) ? &space(AS_IO) : m_program; m_irq_line = 0; m_irq_state = CLEAR_LINE; diff --git a/src/emu/device.cpp b/src/emu/device.cpp index 5dc0366d99e..934c05ddcd7 100644 --- a/src/emu/device.cpp +++ b/src/emu/device.cpp @@ -879,16 +879,15 @@ std::string device_t::subtag(std::string _tag) const { const char *tag = _tag.c_str(); std::string result; - // if the tag begins with a colon, ignore our path and start from the root if (*tag == ':') { + // if the tag begins with a colon, ignore our path and start from the root tag++; result.assign(":"); } - - // otherwise, start with our path else { + // otherwise, start with our path result.assign(m_tag); if (result != ":") result.append(":"); diff --git a/src/mame/drivers/vboy.cpp b/src/mame/drivers/vboy.cpp index 2efc1d95614..57febfc513e 100644 --- a/src/mame/drivers/vboy.cpp +++ b/src/mame/drivers/vboy.cpp @@ -31,8 +31,8 @@ #include "cpu/v810/v810.h" #include "bus/vboy/slot.h" -#include "bus/vboy/rom.h" #include "machine/timer.h" + #include "emupal.h" #include "screen.h" #include "softlist.h" @@ -85,7 +85,6 @@ public: void vboy(machine_config &config); protected: - virtual void machine_start() override; virtual void machine_reset() override; virtual void video_start() override; @@ -191,7 +190,6 @@ private: TIMER_DEVICE_CALLBACK_MEMBER(timer_pad_tick); TIMER_DEVICE_CALLBACK_MEMBER(vboy_scanlineL); - void vboy_io(address_map &map); void vboy_mem(address_map &map); }; @@ -1073,40 +1071,10 @@ void vboy_state::vboy_mem(address_map &map) map(0x01000000, 0x010005ff).rw("vbsnd", FUNC(vboysnd_device::read), FUNC(vboysnd_device::write)); map(0x02000000, 0x0200002b).mirror(0x0ffff00).rw(FUNC(vboy_state::io_r), FUNC(vboy_state::io_w)); // Hardware control registers mask 0xff - //map(0x04000000, 0x04ffffff) // Expansion area + //map(0x04000000, 0x04ffffff) cartslot EXP map(0x05000000, 0x0500ffff).mirror(0x0ff0000).ram().share("wram");// Main RAM - 64K mask 0xffff - map(0x06000000, 0x06003fff).rw(m_cart, FUNC(vboy_cart_slot_device::read_eeprom), FUNC(vboy_cart_slot_device::write_eeprom)); // Cart RAM - 8K NVRAM -// map(0x07000000, 0x071fffff).mirror(0x0e00000).r("cartslot", FUNC(vboy_cart_slot_device::read_cart)); /* ROM */ -} - -void vboy_state::vboy_io(address_map &map) -{ - map.global_mask(0x07ffffff); - map(0x00000000, 0x00005fff).ram().share("l_frame_0"); // L frame buffer 0 - map(0x00006000, 0x00007fff).rw(FUNC(vboy_state::font0_r), FUNC(vboy_state::font0_w)); // Font 0-511 - map(0x00008000, 0x0000dfff).ram().share("l_frame_1"); // L frame buffer 1 - map(0x0000e000, 0x0000ffff).rw(FUNC(vboy_state::font1_r), FUNC(vboy_state::font1_w)); // Font 512-1023 - map(0x00010000, 0x00015fff).ram().share("r_frame_0"); // R frame buffer 0 - map(0x00016000, 0x00017fff).rw(FUNC(vboy_state::font2_r), FUNC(vboy_state::font2_w)); // Font 1024-1535 - map(0x00018000, 0x0001dfff).ram().share("r_frame_1"); // R frame buffer 1 - map(0x0001e000, 0x0001ffff).rw(FUNC(vboy_state::font3_r), FUNC(vboy_state::font3_w)); // Font 1536-2047 - - map(0x00020000, 0x0003ffff).rw(FUNC(vboy_state::vboy_bgmap_r), FUNC(vboy_state::vboy_bgmap_w)); // VIPC memory - - //map(0x00040000, 0x0005ffff).ram(); // VIPC - map(0x0005f800, 0x0005f87f).rw(FUNC(vboy_state::vip_r), FUNC(vboy_state::vip_w)); - - map(0x00078000, 0x00079fff).rw(FUNC(vboy_state::font0_r), FUNC(vboy_state::font0_w)); // Font 0-511 mirror - map(0x0007a000, 0x0007bfff).rw(FUNC(vboy_state::font1_r), FUNC(vboy_state::font1_w)); // Font 512-1023 mirror - map(0x0007c000, 0x0007dfff).rw(FUNC(vboy_state::font2_r), FUNC(vboy_state::font2_w)); // Font 1024-1535 mirror - map(0x0007e000, 0x0007ffff).rw(FUNC(vboy_state::font3_r), FUNC(vboy_state::font3_w)); // Font 1536-2047 mirror - - map(0x01000000, 0x010005ff).rw("vbsnd", FUNC(vboysnd_device::read), FUNC(vboysnd_device::write)); - map(0x02000000, 0x0200002b).mirror(0x0ffff00).rw(FUNC(vboy_state::io_r), FUNC(vboy_state::io_w)); // Hardware control registers mask 0xff -// map(0x04000000, 0x04ffffff) // Expansion area - map(0x05000000, 0x0500ffff).mirror(0x0ff0000).ram().share("wram"); // Main RAM - 64K mask 0xffff - map(0x06000000, 0x06003fff).noprw(); // Cart RAM - 8K NVRAM ? -// map(0x07000000, 0x071fffff).mirror(0x0e00000).r("cartslot", FUNC(vboy_cart_slot_device::read_cart)); /* ROM */ + //map(0x06000000, 0x06ffffff) cartslot CHIP + //map(0x07000000, 0x07ffffff) cartslot ROM } /* Input ports */ @@ -1131,25 +1099,6 @@ static INPUT_PORTS_START( vboy ) INPUT_PORTS_END -void vboy_state::machine_start() -{ - // install the cart ROM as a bank into the address map. - // this speeds up the rom access, by skipping the m_cart->read_rom - // trampoline (but forces us to alloc always a 0x200000-wide region) - if (m_cart->exists()) - { - std::string region_tag; - m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(VBOYSLOT_ROM_REGION_TAG).c_str()); - - m_maincpu->space(AS_PROGRAM).install_read_bank(0x07000000, 0x071fffff, 0x0e00000, "prog_cart_bank"); - m_maincpu->space(AS_IO).install_read_bank(0x07000000, 0x071fffff, 0x0e00000, "io_cart_bank"); - membank("prog_cart_bank")->set_base(m_cart_rom->base()); - membank("io_cart_bank")->set_base(m_cart_rom->base()); - - m_cart->save_eeprom(); - } -} - void vboy_state::machine_reset() { /* Initial values taken from Reality Boy, to be verified when emulation improves */ @@ -1299,18 +1248,12 @@ TIMER_DEVICE_CALLBACK_MEMBER(vboy_state::vboy_scanlineR) #endif -static void vboy_cart(device_slot_interface &device) -{ - device.option_add_internal("vb_rom", VBOY_ROM_STD); - device.option_add_internal("vb_eeprom", VBOY_ROM_EEPROM); -} - void vboy_state::vboy(machine_config &config) { /* basic machine hardware */ V810(config, m_maincpu, XTAL(20'000'000)); m_maincpu->set_addrmap(AS_PROGRAM, &vboy_state::vboy_mem); - m_maincpu->set_addrmap(AS_IO, &vboy_state::vboy_io); + TIMER(config, "scantimer_l").configure_scanline(FUNC(vboy_state::vboy_scanlineL), "3dleft", 0, 1); //TIMER(config, "scantimer_r").configure_scanline(FUNC(vboy_state::vboy_scanlineR), "3dright", 0, 1); @@ -1337,7 +1280,11 @@ void vboy_state::vboy(machine_config &config) rscreen.set_palette(m_palette); /* cartridge */ - VBOY_CART_SLOT(config, m_cart, vboy_cart, nullptr); + VBOY_CART_SLOT(config, m_cart, vboy_carts, nullptr); + m_cart->intcro().set_inputline(m_maincpu, 2); + m_cart->set_exp(m_maincpu, AS_PROGRAM, 0x0400'0000); + m_cart->set_chip(m_maincpu, AS_PROGRAM, 0x0600'0000); + m_cart->set_rom(m_maincpu, AS_PROGRAM, 0x0700'0000); /* software lists */ SOFTWARE_LIST(config, "cart_list").set_original("vboy");