diff --git a/hash/supracan.xml b/hash/supracan.xml index 46cb6ac0adaa5..7eeb366dd8199 100644 --- a/hash/supracan.xml +++ b/hash/supracan.xml @@ -15,7 +15,7 @@ license:CC0-1.0 ]]> - + @@ -33,7 +33,7 @@ license:CC0-1.0 ]]> - + @@ -53,11 +53,13 @@ Broken [video] during intro, uses bitmap mode ]]> - - + + + + @@ -74,7 +76,7 @@ Broken [video] during intro, uses bitmap mode ]]> - + @@ -92,11 +94,13 @@ Broken [video] during intro, uses bitmap mode ]]> - - + + + + @@ -109,7 +113,7 @@ Can potentially hang, [maincpu] tight loops for $e80300 bit 7 high (verify) ]]> - + @@ -126,12 +130,15 @@ Can potentially hang, [maincpu] tight loops for $e80300 bit 7 high (verify) ]]> - - + + + + + @@ -141,11 +148,14 @@ Can potentially hang, [maincpu] tight loops for $e80300 bit 7 high (verify) Panda Entertainment Technology - - + + + + + @@ -160,10 +170,15 @@ Erratic gameplay speed, controls [irq 3] as FRC, show [video] missing/glitched t ]]> - + + + + + + @@ -179,7 +194,7 @@ Erratic gameplay speed, controls [irq 3] as FRC ]]> - + @@ -196,7 +211,7 @@ Uses [video] clipping for layer 1 during intro - + diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index c6d4b7f1cb5c5..b1043154c3eb9 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2576,6 +2576,20 @@ if (BUSES["SS50"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/bus/supracan/slot.h,BUSES["SUPRACAN"] = true +--------------------------------------------------- + +if (BUSES["SUPRACAN"]~=null) then + files { + MAME_DIR .. "src/devices/bus/supracan/slot.cpp", + MAME_DIR .. "src/devices/bus/supracan/slot.h", + MAME_DIR .. "src/devices/bus/supracan/rom.cpp", + MAME_DIR .. "src/devices/bus/supracan/rom.h", + } +end + --------------------------------------------------- -- diff --git a/src/devices/bus/supracan/rom.cpp b/src/devices/bus/supracan/rom.cpp new file mode 100644 index 0000000000000..ca3be333df60d --- /dev/null +++ b/src/devices/bus/supracan/rom.cpp @@ -0,0 +1,96 @@ +// license:BSD-3-Clause +// copyright-holders: + +#include "emu.h" +#include "rom.h" + + +//------------------------------------------------- +// superacan_rom_device - constructor +//------------------------------------------------- + +DEFINE_DEVICE_TYPE(SUPERACAN_ROM_STD, superacan_rom_device, "superacan_rom", "Super A'Can Standard Cart") + + +superacan_rom_device::superacan_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, type, tag, owner, clock), device_superacan_cart_interface(mconfig, *this) + , m_rom_base(nullptr) + , m_nvram_base(nullptr) + , m_rom_size(0) + , m_nvram_size(0) +{ +} + +superacan_rom_device::superacan_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : superacan_rom_device(mconfig, SUPERACAN_ROM_STD, tag, owner, clock) +{ +} + + +void superacan_rom_device::device_start() +{ +} + +void superacan_rom_device::device_add_mconfig(machine_config &config) +{ + // TODO: move UM6650 from funtech folder +} + +std::error_condition superacan_rom_device::load() +{ + memory_region *const romregion = memregion("^rom"); + m_rom_base = reinterpret_cast(romregion->base()); + m_rom_size = romregion->bytes() / 2; + +// if (m_rom_size > 0x40'0000) +// return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be no larger than 4M)"); + + memory_region *const nvramregion = memregion("^nvram"); + if (nvramregion) + { + m_nvram_base = reinterpret_cast(nvramregion->base()); + m_nvram_size = nvramregion->bytes(); + + if (m_nvram_size & (m_nvram_size - 1)) + return image_error::BADSOFTWARE; + + save_pointer(NAME(m_nvram_base), m_nvram_size); + battery_load(m_nvram_base, m_nvram_size, 0xff); + } + + return std::error_condition(); +} + + +void superacan_rom_device::unload() +{ + if (m_nvram_base) + battery_save(m_nvram_base, m_nvram_size); +} + + +/*------------------------------------------------- + read/write + -------------------------------------------------*/ + +u16 superacan_rom_device::rom_r(offs_t offset) +{ + if (offset < m_rom_size) + return m_rom_base[offset]; + else + return 0xffff; +} + +u8 superacan_rom_device::nvram_r(offs_t offset) +{ + if (m_nvram_base) + return m_nvram_base[offset & (m_nvram_size - 1)]; + else + return 0xff; +} + +void superacan_rom_device::nvram_w(offs_t offset, u8 data) +{ + if (m_nvram_base) + m_nvram_base[offset & (m_nvram_size - 1)] = data; +} diff --git a/src/devices/bus/supracan/rom.h b/src/devices/bus/supracan/rom.h new file mode 100644 index 0000000000000..a75cb26fa6654 --- /dev/null +++ b/src/devices/bus/supracan/rom.h @@ -0,0 +1,46 @@ +// license:BSD-3-Clause +// copyright-holders: +#ifndef MAME_BUS_SUPERACAN_ROM_H +#define MAME_BUS_SUPERACAN_ROM_H + +#pragma once + +#include "slot.h" + + +// ======================> superacan_rom_device + +class superacan_rom_device : public device_t, + public device_superacan_cart_interface +{ +public: + // construction/destruction + superacan_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // load/unload + virtual std::error_condition load() override; + virtual void unload() override; + + // read/write + virtual u16 rom_r(offs_t offset) override; + virtual u8 nvram_r(offs_t offset) override; + virtual void nvram_w(offs_t offset, u8 data) override; + +protected: + superacan_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); + + virtual void device_start() override; + + virtual void device_add_mconfig(machine_config &config) override; + +private: + const u16 *m_rom_base; + u8 *m_nvram_base; + u32 m_rom_size; + u32 m_nvram_size; +}; + + +DECLARE_DEVICE_TYPE(SUPERACAN_ROM_STD, superacan_rom_device) + +#endif // MAME_BUS_SUPERACAN_ROM_H diff --git a/src/devices/bus/supracan/slot.cpp b/src/devices/bus/supracan/slot.cpp new file mode 100644 index 0000000000000..19f10c449f6b4 --- /dev/null +++ b/src/devices/bus/supracan/slot.cpp @@ -0,0 +1,116 @@ +// license:BSD-3-Clause +// copyright-holders: + +#include "emu.h" +#include "slot.h" + + +DEFINE_DEVICE_TYPE(SUPERACAN_CART_SLOT, superacan_cart_slot_device, "superacan_cart_slot", "Super A'Can Cartridge Slot") + + +device_superacan_cart_interface::device_superacan_cart_interface(const machine_config &mconfig, device_t &device) + : device_interface(device, "superacan_cart") + , m_slot(dynamic_cast(device.owner())) +{ +} + + +device_superacan_cart_interface::~device_superacan_cart_interface() +{ +} + + +void device_superacan_cart_interface::battery_load(void *buffer, int length, int fill) +{ + assert(m_slot); + m_slot->battery_load(buffer, length, fill); +} + +void device_superacan_cart_interface::battery_load(void *buffer, int length, void *def_buffer) +{ + assert(m_slot); + m_slot->battery_load(buffer, length, def_buffer); +} + +void device_superacan_cart_interface::battery_save(const void *buffer, int length) +{ + assert(m_slot); + m_slot->battery_save(buffer, length); +} + + +superacan_cart_slot_device::superacan_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, SUPERACAN_CART_SLOT, tag, owner, clock), + device_cartrom_image_interface(mconfig, *this), + device_single_card_slot_interface(mconfig, *this), + m_cart(nullptr) +{ +} + + +//------------------------------------------------- +// superacan_cart_slot_device - destructor +//------------------------------------------------- + +superacan_cart_slot_device::~superacan_cart_slot_device() +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void superacan_cart_slot_device::device_start() +{ + m_cart = get_card_device(); +} + + + +/*------------------------------------------------- + call load + -------------------------------------------------*/ + +std::pair superacan_cart_slot_device::call_load() +{ + if (!m_cart) + return std::make_pair(std::error_condition(), std::string()); + + memory_region *romregion = loaded_through_softlist() ? memregion("rom") : nullptr; + if (loaded_through_softlist() && !romregion) + return std::make_pair(image_error::INVALIDLENGTH, "Software list item has no 'rom' data area"); + + const u32 len = loaded_through_softlist() ? romregion->bytes() : length(); + + if (!loaded_through_softlist()) + { + romregion = machine().memory().region_alloc(subtag("rom"), len, 2, ENDIANNESS_BIG); + u16 *const rombase = reinterpret_cast(romregion->base()); + const u32 cnt = fread(rombase, len); + if (cnt != len) + return std::make_pair(std::errc::io_error, "Error reading cartridge file"); + } + + return std::make_pair(m_cart->load(), std::string()); +} + + +/*------------------------------------------------- + call unload + -------------------------------------------------*/ + +void superacan_cart_slot_device::call_unload() +{ + if (m_cart) + m_cart->unload(); +} + + +/*------------------------------------------------- + get default card software + -------------------------------------------------*/ + +std::string superacan_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const +{ + return software_get_default_slot("std"); +} diff --git a/src/devices/bus/supracan/slot.h b/src/devices/bus/supracan/slot.h new file mode 100644 index 0000000000000..2c28537780705 --- /dev/null +++ b/src/devices/bus/supracan/slot.h @@ -0,0 +1,90 @@ +// license:BSD-3-Clause +// copyright-holders: + +#ifndef MAME_BUS_SUPERACAN_SLOT_H +#define MAME_BUS_SUPERACAN_SLOT_H + +#include "imagedev/cartrom.h" + +#include +#include + + +/*************************************************************************** + TYPE DEFINITIONS + ***************************************************************************/ + +class superacan_cart_slot_device; + + +class device_superacan_cart_interface : public device_interface +{ +public: + virtual ~device_superacan_cart_interface(); + + // load/unload + virtual std::error_condition load() = 0; + virtual void unload() = 0; + + // read/write + virtual u16 rom_r(offs_t offset) = 0; + virtual u8 nvram_r(offs_t offset) = 0; + virtual void nvram_w(offs_t offset, u8 data) = 0; + +protected: + // construction/destruction + device_superacan_cart_interface(const machine_config &mconfig, device_t &device); + + // helpers for slot stuff + void battery_load(void *buffer, int length, int fill); + void battery_load(void *buffer, int length, void *def_buffer); + void battery_save(const void *buffer, int length); + +private: + superacan_cart_slot_device *const m_slot; +}; + + +class superacan_cart_slot_device : public device_t, + public device_cartrom_image_interface, + public device_single_card_slot_interface +{ +public: + // construction/destruction + template + superacan_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, T &&opts, char const *dflt) + : superacan_cart_slot_device(mconfig, tag, owner, clock) + { + option_reset(); + opts(*this); + set_default_option(dflt); + set_fixed(false); + } + superacan_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + virtual ~superacan_cart_slot_device(); + + // device_image_interface implementation + virtual std::pair call_load() override; + virtual void call_unload() override; + + virtual bool is_reset_on_load() const noexcept override { return true; } + virtual const char *image_interface() const noexcept override { return "superacan_cart"; } + virtual const char *file_extensions() const noexcept override { return "bin"; } + + virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override; + + // reading and writing + u16 rom_r(offs_t offset) { return m_cart ? m_cart->rom_r(offset) : 0xffff; } + u8 nvram_r(offs_t offset) { return m_cart ? m_cart->nvram_r(offset) : 0xff; } + void nvram_w(offs_t offset, u8 data) { if (m_cart) m_cart->nvram_w(offset, data); } + +protected: + // device_t implementation + virtual void device_start() override; + + device_superacan_cart_interface *m_cart; +}; + +DECLARE_DEVICE_TYPE(SUPERACAN_CART_SLOT, superacan_cart_slot_device) + +#endif // MAME_BUS_SUPERACAN_SLOT_H diff --git a/src/mame/funtech/supracan.cpp b/src/mame/funtech/supracan.cpp index b72028b056139..1ce7320e39c40 100644 --- a/src/mame/funtech/supracan.cpp +++ b/src/mame/funtech/supracan.cpp @@ -65,8 +65,8 @@ Super A'Can (c) 1995 Funtech #include "emu.h" -#include "bus/generic/slot.h" -#include "bus/generic/carts.h" +#include "bus/supracan/rom.h" +#include "bus/supracan/slot.h" #include "cpu/m68000/m68000.h" #include "cpu/m6502/m65c02.h" @@ -179,7 +179,7 @@ class supracan_state : public driver_device required_device m_maincpu; required_device m_soundcpu; - required_device m_cart; + required_device m_cart; required_device m_lockout; required_region_ptr m_internal68; memory_view m_main_loview; @@ -265,7 +265,6 @@ class supracan_state : public driver_device TIMER_CALLBACK_MEMBER(line_on_cb); TIMER_CALLBACK_MEMBER(line_off_cb); TIMER_CALLBACK_MEMBER(scanline_cb); - DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load); int get_tilemap_region(int layer); void get_tilemap_info_common(int layer, tile_data &tileinfo, int count); void get_roz_tilemap_info(int layer, tile_data &tileinfo, int count); @@ -308,7 +307,7 @@ int supracan_state::get_tilemap_region(int layer) } // TODO: 4th layer at $f00160 (gfx mode 0 only, ignored for everything else) - throw new emu_fatalerror("Error: layer = %d not defined", layer); + throw emu_fatalerror("Error: layer = %d not defined", layer); } void supracan_state::get_tilemap_info_common(int layer, tile_data &tileinfo, int count) @@ -1349,9 +1348,9 @@ void supracan_state::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask) void supracan_state::main_map(address_map &map) { map(0x000000, 0x3fffff).view(m_main_loview); - m_main_loview[0](0x000000, 0x3fffff).r(m_cart, FUNC(generic_slot_device::read16_rom)); + m_main_loview[0](0x000000, 0x3fffff).r(m_cart, FUNC(superacan_cart_slot_device::rom_r)), m_main_loview[0](0x000000, 0x000fff).rom().region(m_internal68, 0); - m_main_loview[1](0x000000, 0x3fffff).r(m_cart, FUNC(generic_slot_device::read16_rom)); + m_main_loview[1](0x000000, 0x3fffff).r(m_cart, FUNC(superacan_cart_slot_device::rom_r)); map(0xe80000, 0xe8ffff).rw(FUNC(supracan_state::_68k_soundram_r), FUNC(supracan_state::_68k_soundram_w)); map(0xe90000, 0xe9001f).m(*this, FUNC(supracan_state::host_um6619_map)); map(0xe90020, 0xe9002f).w(FUNC(supracan_state::dma_w<0>)); @@ -1361,15 +1360,15 @@ void supracan_state::main_map(address_map &map) map(0xeb0d00, 0xeb0d03).rw(m_lockout, FUNC(umc6650_device::read), FUNC(umc6650_device::write)).umask16(0x00ff); -// map(0xec0000, 0xec*fff) Cart NVRAM, 8-bit interface + map(0xec0000, 0xecffff).rw(m_cart, FUNC(superacan_cart_slot_device::nvram_r), FUNC(superacan_cart_slot_device::nvram_w)).umask16(0x00ff); map(0xf00000, 0xf001ff).rw(FUNC(supracan_state::video_r), FUNC(supracan_state::video_w)); map(0xf00200, 0xf003ff).ram().w("palette", FUNC(palette_device::write16)).share("palette"); map(0xf40000, 0xf5ffff).ram().w(FUNC(supracan_state::vram_w)).share("vram"); map(0xf80000, 0xfbffff).view(m_main_hiview); - m_main_hiview[0](0xf80000, 0xfbffff).r(m_cart, FUNC(generic_slot_device::read16_rom)); + m_main_hiview[0](0xf80000, 0xfbffff).r(m_cart, FUNC(superacan_cart_slot_device::rom_r)); m_main_hiview[0](0xf80000, 0xf80fff).rom().region(m_internal68, 0); - m_main_hiview[1](0xf80000, 0xfbffff).r(m_cart, FUNC(generic_slot_device::read16_rom)); + m_main_hiview[1](0xf80000, 0xfbffff).r(m_cart, FUNC(superacan_cart_slot_device::rom_r)); map(0xfc0000, 0xfcffff).mirror(0x30000).ram(); /* System work ram */ } @@ -2060,20 +2059,6 @@ void supracan_state::video_w(offs_t offset, uint16_t data, uint16_t mem_mask) // m_video_regs[offset] = data; } - -DEVICE_IMAGE_LOAD_MEMBER(supracan_state::cart_load) -{ - uint32_t size = m_cart->common_get_size("rom"); - - if (size > 0x40'0000) - return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be no larger than 4M)"); - - m_cart->rom_alloc(size, GENERIC_ROM16_WIDTH, ENDIANNESS_BIG); - m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom"); - - return std::make_pair(std::error_condition(), std::string()); -} - static INPUT_PORTS_START( supracan ) PORT_START("P1") PORT_BIT(0x000f, IP_ACTIVE_LOW, IPT_UNUSED) @@ -2275,6 +2260,12 @@ static GFXDECODE_START( gfx_supracan ) GFXDECODE_RAM( "vram", 0, supracan_gfx1bpp_alt, 0, 0x80 ) GFXDECODE_END +static void superacan_cart_types(device_slot_interface &device) +{ + device.option_add_internal("std", SUPERACAN_ROM_STD); +} + + void supracan_state::supracan(machine_config &config) { // M68000P10 @@ -2311,11 +2302,8 @@ void supracan_state::supracan(machine_config &config) m_sound->add_route(0, "lspeaker", 1.0); m_sound->add_route(1, "rspeaker", 1.0); - generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "supracan_cart")); - cartslot.set_must_be_loaded(true); - cartslot.set_width(GENERIC_ROM16_WIDTH); - cartslot.set_endian(ENDIANNESS_BIG); - cartslot.set_device_load(FUNC(supracan_state::cart_load)); + // TODO: clock for cart is (again) unconfirmed + SUPERACAN_CART_SLOT(config, m_cart, U13_CLOCK / 6, superacan_cart_types, nullptr).set_must_be_loaded(true); SOFTWARE_LIST(config, "cart_list").set_original("supracan"); }