diff --git a/hash/supracan.xml b/hash/supracan.xml index d31d96d350b..6a21c6c2cd3 100644 --- a/hash/supracan.xml +++ b/hash/supracan.xml @@ -10,12 +10,12 @@ license:CC0-1.0 AV Artisan Corp. - + @@ -27,14 +27,13 @@ license:CC0-1.0 1995 Panda Entertainment Technology - + @@ -50,14 +49,17 @@ Uses [video] blending during attract and title screen Wrong [video] ROZ paging for title screen Broken [video] during intro, uses bitmap mode [video] uses per-tile priority during gameplay +[sound] BGM during intro releases few keys too early (TODO: pinpoint which) ]]> - - + + + + @@ -68,11 +70,13 @@ Broken [video] during intro, uses bitmap mode - + @@ -84,15 +88,19 @@ Broken [video] during intro, uses bitmap mode 1995 C&E Soft - - + + + + @@ -101,11 +109,11 @@ Broken [video] during intro, uses bitmap mode 1995 Funtech - + @@ -122,12 +130,15 @@ Can potentially hang, [maincpu] tight loops for $e80300 bit 7 high ]]> - - + + + + + @@ -137,11 +148,14 @@ Can potentially hang, [maincpu] tight loops for $e80300 bit 7 high Panda Entertainment Technology - - + + + + + @@ -150,16 +164,21 @@ Can potentially hang, [maincpu] tight loops for $e80300 bit 7 high 1996 Funtech - + + + + + + @@ -168,14 +187,14 @@ Erratic gameplay speed, controls [irq 3] as FRC, can potentially hang 1996 Funtech - + @@ -192,7 +211,7 @@ Uses [video] clipping for layer 1 during intro - + diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index c6d4b7f1cb5..6ca699992a0 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2010,6 +2010,8 @@ if (BUSES["MSX_SLOT"]~=null) then MAME_DIR .. "src/devices/bus/msx/slot/music.h", MAME_DIR .. "src/devices/bus/msx/slot/panasonic08.cpp", MAME_DIR .. "src/devices/bus/msx/slot/panasonic08.h", + MAME_DIR .. "src/devices/bus/msx/slot/panasonic08r.cpp", + MAME_DIR .. "src/devices/bus/msx/slot/panasonic08r.h", MAME_DIR .. "src/devices/bus/msx/slot/rom.cpp", MAME_DIR .. "src/devices/bus/msx/slot/rom.h", MAME_DIR .. "src/devices/bus/msx/slot/ram.cpp", @@ -2576,6 +2578,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/msx/slot/fs4600.cpp b/src/devices/bus/msx/slot/fs4600.cpp index 7f947b5b7fd..abb599d4c42 100644 --- a/src/devices/bus/msx/slot/fs4600.cpp +++ b/src/devices/bus/msx/slot/fs4600.cpp @@ -36,10 +36,11 @@ void msx_slot_fs4600_device::device_start() fatalerror("Memory region '%s' is too small for the FS4600 firmware\n", m_rom_region.finder_tag()); } - m_sram.resize(SRAM_SIZE); - m_nvram->set_base(m_sram.data(), SRAM_SIZE); + m_sram = std::make_unique(SRAM_SIZE); + m_nvram->set_base(&m_sram[0], SRAM_SIZE); save_item(NAME(m_sram_address)); + save_pointer(NAME(m_sram), SRAM_SIZE); for (int i = 0; i < 3; i++) m_rombank[i]->configure_entries(0, 0x40, m_rom_region->base() + m_region_offset, 0x4000); diff --git a/src/devices/bus/msx/slot/fs4600.h b/src/devices/bus/msx/slot/fs4600.h index 5061e9186bf..dacf5be14c2 100644 --- a/src/devices/bus/msx/slot/fs4600.h +++ b/src/devices/bus/msx/slot/fs4600.h @@ -41,7 +41,7 @@ class msx_slot_fs4600_device : public device_t, public msx_internal_slot_interfa memory_view m_view[3]; u32 m_region_offset; u32 m_sram_address; - std::vector m_sram; + std::unique_ptr m_sram; }; diff --git a/src/devices/bus/msx/slot/fsa1fm.cpp b/src/devices/bus/msx/slot/fsa1fm.cpp index 93e55d5b78d..6b59c516bbe 100644 --- a/src/devices/bus/msx/slot/fsa1fm.cpp +++ b/src/devices/bus/msx/slot/fsa1fm.cpp @@ -32,15 +32,15 @@ void msx_slot_fsa1fm2_device::device_start() fatalerror("Memory region '%s' is not the correct size for the FS-A1FM firmware\n", m_rom_region.finder_tag()); } - m_ram.resize(RAM_SIZE); - m_empty_bank.resize(8 * 1024); + m_ram = std::make_unique(RAM_SIZE); + m_empty_bank = std::make_unique(8 * 1024); for (int i = 0; i < 8 * 1024; i++) m_empty_bank[i] = 0xff; save_item(NAME(m_selected_bank)); save_item(NAME(m_control)); save_item(NAME(m_ram_active)); - save_pointer(m_ram.data(), "ram", RAM_SIZE); + save_pointer(NAME(m_ram), m_size); for (int i = 0; i < 6; i++) { @@ -48,10 +48,10 @@ void msx_slot_fsa1fm2_device::device_start() m_bank[i]->configure_entries(0x80, 0x80, m_rom_region->base() + m_region_offset, 0x2000); for (int j = 0; j < 4; j++) { - m_bank[i]->configure_entry(0x80 + j, m_empty_bank.data()); // 0x80-0x83 empty - m_bank[i]->configure_entry(0x84 + j, m_ram.data()); // 0x84-0x87 ram - m_bank[i]->configure_entry(0x88 + j, m_empty_bank.data()); // 0x88-0x8b empty - m_bank[i]->configure_entry(0x8c + j, m_ram.data()); // 0x8c-0x8f ram + m_bank[i]->configure_entry(0x80 + j, &m_empty_bank[0]); // 0x80-0x83 empty + m_bank[i]->configure_entry(0x84 + j, &m_ram[0]); // 0x84-0x87 ram + m_bank[i]->configure_entry(0x88 + j, &m_empty_bank[0]); // 0x88-0x8b empty + m_bank[i]->configure_entry(0x8c + j, &m_ram[0]); // 0x8c-0x8f ram } } @@ -182,14 +182,16 @@ void msx_slot_fsa1fm_device::device_start() fatalerror("Memory region '%s' is not the correct size for the FS-A1FM firmware\n", m_rom_region.finder_tag()); } - m_sram.resize(SRAM_SIZE); - m_nvram->set_base(m_sram.data(), SRAM_SIZE); + m_sram = std::make_unique(SRAM_SIZE); + m_nvram->set_base(&m_sram[0], SRAM_SIZE); + + save_pointer(NAME(m_sram), SRAM_SIZE); m_rombank->configure_entries(0, 16, m_rom_region->base(), 0x2000); page(1)->install_read_bank(0x4000, 0x5fff, m_rombank); // SRAM is always visible? - page(1)->install_ram(0x6000, 0x7fff, m_sram.data()); + page(1)->install_ram(0x6000, 0x7fff, &m_sram[0]); page(1)->install_write_handler(0x7fc0, 0x7fc0, emu::rw_delegate(*m_i8251, FUNC(i8251_device::data_w))); page(1)->install_read_handler(0x7fc0, 0x7fc0, emu::rw_delegate(*m_i8251, FUNC(i8251_device::data_r))); page(1)->install_write_handler(0x7fc1, 0x7fc1, emu::rw_delegate(*m_i8251, FUNC(i8251_device::control_w))); diff --git a/src/devices/bus/msx/slot/fsa1fm.h b/src/devices/bus/msx/slot/fsa1fm.h index 660baa43e99..e0d2bac0bcd 100644 --- a/src/devices/bus/msx/slot/fsa1fm.h +++ b/src/devices/bus/msx/slot/fsa1fm.h @@ -42,8 +42,8 @@ class msx_slot_fsa1fm2_device : public device_t, public msx_internal_slot_interf uint8_t m_selected_bank[6]; bool m_ram_active[6]; uint8_t m_control; - std::vector m_ram; - std::vector m_empty_bank; + std::unique_ptr m_ram; + std::unique_ptr m_empty_bank; }; @@ -76,7 +76,7 @@ class msx_slot_fsa1fm_device : public device_t, public msx_internal_slot_interfa required_memory_region m_rom_region; memory_bank_creator m_rombank; u32 m_region_offset; - std::vector m_sram; + std::unique_ptr m_sram; }; diff --git a/src/devices/bus/msx/slot/msx_rs232.cpp b/src/devices/bus/msx/slot/msx_rs232.cpp index 0750abf7c9a..3848b8e5ff4 100644 --- a/src/devices/bus/msx/slot/msx_rs232.cpp +++ b/src/devices/bus/msx/slot/msx_rs232.cpp @@ -255,21 +255,21 @@ void msx_slot_rs232_sony_device::device_start() { msx_slot_rs232_base_device::device_start(); - m_ram.resize(RAM_SIZE); - save_item(NAME(m_ram)); + m_ram = std::make_unique(RAM_SIZE); + save_pointer(NAME(m_ram), RAM_SIZE); // TODO unmap rom from page 0 - page(0)->install_ram(0x2000, 0x27ff, m_ram.data()); + page(0)->install_ram(0x2000, 0x27ff, &m_ram[0]); page(1)->install_rom(0x4000, 0x5fff, m_rom_region->base() + m_region_offset); - page(1)->install_ram(0x6000, 0x67ff, m_ram.data()); - page(2)->install_ram(0xa000, 0xa7ff, m_ram.data()); + page(1)->install_ram(0x6000, 0x67ff, &m_ram[0]); + page(2)->install_ram(0xa000, 0xa7ff, &m_ram[0]); page(2)->install_read_handler(0xbff8, 0xbff9, emu::rw_delegate(*m_i8251, FUNC(i8251_device::read))); page(2)->install_write_handler(0xbff8, 0xbff9, emu::rw_delegate(*m_i8251, FUNC(i8251_device::write))); page(2)->install_read_handler(0xbffa, 0xbffa, emu::rw_delegate(*this, FUNC(msx_slot_rs232_sony_device::status_r))); page(2)->install_write_handler(0xbffa, 0xbffa, emu::rw_delegate(*this, FUNC(msx_slot_rs232_sony_device::irq_mask_w))); page(2)->install_read_handler(0xbffc, 0xbfff, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::read))); page(2)->install_write_handler(0xbffc, 0xbfff, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::write))); - page(3)->install_ram(0xe000, 0xe7ff, m_ram.data()); + page(3)->install_ram(0xe000, 0xe7ff, &m_ram[0]); } u8 msx_slot_rs232_sony_device::status_r(offs_t offset) @@ -454,10 +454,11 @@ void msx_slot_rs232_toshiba_hx3x_device::device_start() io_space().install_readwrite_handler(0x82, 0x82, emu::rw_delegate(*this, FUNC(msx_slot_rs232_toshiba_hx3x_device::status_r)), emu::rw_delegate(*this, FUNC(msx_slot_rs232_toshiba_hx3x_device::irq_mask_w))); io_space().install_readwrite_handler(0x84, 0x87, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::read)), emu::rw_delegate(*m_i8253, FUNC(pit8253_device::write))); - m_sram.resize(SRAM_SIZE); - m_nvram->set_base(m_sram.data(), SRAM_SIZE); + m_sram = std::make_unique(SRAM_SIZE); + m_nvram->set_base(&m_sram[0], SRAM_SIZE); save_item(NAME(m_bank_reg)); + save_pointer(NAME(m_sram), SRAM_SIZE); m_rombank->configure_entries(0, 4, m_rom_region->base() + m_region_offset + 0x4000, 0x4000); @@ -465,7 +466,7 @@ void msx_slot_rs232_toshiba_hx3x_device::device_start() page(1)->install_read_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_slot_rs232_toshiba_hx3x_device::bank_r))); page(2)->install_view(0x8000, 0xbfff, m_view); m_view[0].install_read_bank(0x8000, 0xbfff, m_rombank); - m_view[1].install_ram(0x8000, 0x87ff, 0x3800, m_sram.data()); + m_view[1].install_ram(0x8000, 0x87ff, 0x3800, &m_sram[0]); } void msx_slot_rs232_toshiba_hx3x_device::device_reset() diff --git a/src/devices/bus/msx/slot/msx_rs232.h b/src/devices/bus/msx/slot/msx_rs232.h index 6aa6ba52ffa..e22221bbe9b 100644 --- a/src/devices/bus/msx/slot/msx_rs232.h +++ b/src/devices/bus/msx/slot/msx_rs232.h @@ -95,7 +95,7 @@ class msx_slot_rs232_sony_device : public msx_slot_rs232_base_device static constexpr size_t RAM_SIZE = 0x800; required_ioport m_switch_port; - std::vector m_ram; + std::unique_ptr m_ram; }; @@ -152,7 +152,7 @@ class msx_slot_rs232_toshiba_hx3x_device : public msx_slot_rs232_base_device required_device m_nvram; memory_bank_creator m_rombank; memory_view m_view; - std::vector m_sram; + std::unique_ptr m_sram; u8 m_bank_reg; }; diff --git a/src/devices/bus/msx/slot/panasonic08.cpp b/src/devices/bus/msx/slot/panasonic08.cpp index 5de4c1d1913..a0a644c46a9 100644 --- a/src/devices/bus/msx/slot/panasonic08.cpp +++ b/src/devices/bus/msx/slot/panasonic08.cpp @@ -41,20 +41,21 @@ void msx_slot_panasonic08_device::device_start() fatalerror("Memory region '%s' is too small for the panasonic08 firmware\n", m_rom_region.finder_tag()); } - m_sram.resize(SRAM_SIZE); + m_sram = std::make_unique(SRAM_SIZE); m_nvram->set_base(&m_sram[0], SRAM_SIZE); save_item(NAME(m_selected_bank)); save_item(NAME(m_control)); + save_pointer(NAME(m_sram), SRAM_SIZE); for (int i = 0; i < 6; i++) { m_bank[i]->configure_entries(0, 0x100, m_rom_region->base() + m_region_offset, 0x2000); - m_bank[i]->configure_entry(0x80, m_sram.data()); - m_bank[i]->configure_entry(0x81, m_sram.data() + 0x2000); - m_bank[i]->configure_entry(0x82, m_sram.data()); - m_bank[i]->configure_entry(0x83, m_sram.data() + 0x2000); + m_bank[i]->configure_entry(0x80, &m_sram[0]); + m_bank[i]->configure_entry(0x81, &m_sram[0x2000]); + m_bank[i]->configure_entry(0x82, &m_sram[0]); + m_bank[i]->configure_entry(0x83, &m_sram[0x2000]); } page(0)->install_view(0x0000, 0x1fff, m_view[0]); diff --git a/src/devices/bus/msx/slot/panasonic08.h b/src/devices/bus/msx/slot/panasonic08.h index 6fd7ace83f4..5602dfd20dd 100644 --- a/src/devices/bus/msx/slot/panasonic08.h +++ b/src/devices/bus/msx/slot/panasonic08.h @@ -41,7 +41,7 @@ class msx_slot_panasonic08_device : public device_t, public msx_internal_slot_in u32 m_region_offset; u8 m_selected_bank[6]; u8 m_control; - std::vector m_sram; + std::unique_ptr m_sram; }; diff --git a/src/devices/bus/msx/slot/panasonic08r.cpp b/src/devices/bus/msx/slot/panasonic08r.cpp new file mode 100644 index 00000000000..c274cf951f4 --- /dev/null +++ b/src/devices/bus/msx/slot/panasonic08r.cpp @@ -0,0 +1,166 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +/* + + Emulation of the firmware mapper as found in Panasonic FS-A1ST and FS-A1GT Turbo-R machines. + + +*/ + +#include "emu.h" +#include "panasonic08r.h" + + +DEFINE_DEVICE_TYPE(MSX_SLOT_PANASONIC08R, msx_slot_panasonic08r_device, "msx_slot_panasonic08r", "MSX Internal Panasonic08r") + + +msx_slot_panasonic08r_device::msx_slot_panasonic08r_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, MSX_SLOT_PANASONIC08R, tag, owner, clock) + , msx_internal_slot_interface(mconfig, *this) + , m_sram_size(0) + , m_nvram(*this, "nvram") + , m_rom_region(*this, finder_base::DUMMY_TAG) + , m_bank(*this, "bank%u", 0U) + , m_view{ + {*this, "view0"}, {*this, "view1"}, {*this, "view2"}, {*this, "view3"}, + {*this, "view4"}, {*this, "view5"}, {*this, "view6"}, {*this, "view7"} + } + , m_mm(*this, finder_base::DUMMY_TAG) + , m_region_offset(0) + , m_control(0) +{ +} + + +void msx_slot_panasonic08r_device::device_add_mconfig(machine_config &config) +{ + NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0); +} + + +void msx_slot_panasonic08r_device::device_start() +{ + // Sanity checks + if (m_rom_region->bytes() < m_region_offset + 0x400000) + fatalerror("Memory region '%s' is too small for the panasonic08r firmware\n", m_rom_region.finder_tag()); + if (m_sram_size != 0x4000 && m_sram_size != 0x8000) + fatalerror("Invalid SRAM size for the panasonic08r firmware\n"); + + m_sram = std::make_unique(m_sram_size); + m_nvram->set_base(&m_sram[0], m_sram_size); + + save_item(NAME(m_selected_bank)); + save_item(NAME(m_control)); + save_item(NAME(m_bank9)); + save_pointer(NAME(m_sram), m_sram_size); + + for (int i = 0; i < 8; i++) + { + m_bank[i]->configure_entries(0, 0x200, m_rom_region->base() + m_region_offset, 0x2000); + m_bank[i]->configure_entry(0x80, &m_sram[0]); + m_bank[i]->configure_entry(0x81, &m_sram[0x2000]); + if (m_sram_size >= 0x8000) + { + m_bank[i]->configure_entry(0x82, &m_sram[0x4000]); + m_bank[i]->configure_entry(0x83, &m_sram[0x6000]); + } + + // Assuming smaller internal RAM is mirrored. + int internal_ram_banks = m_mm->get_ram_size() / 0x2000; + int start_bank = 0x180; + do { + int nr_banks = internal_ram_banks; + if (start_bank + nr_banks > 0x200) + nr_banks = 0x200 - start_bank; + m_bank[i]->configure_entries(start_bank, nr_banks, m_mm->get_ram_base(), 0x2000); + start_bank += internal_ram_banks; + } + while (start_bank < 0x200); + } + + for (int i = 0; i < 8; i++) + { + const u16 start = 0x2000 * i; + const u16 end = start + 0x1fff; + + page(i/2)->install_view(start, end, m_view[i]); + m_view[i][0].install_read_bank(start, end, m_bank[i]); + m_view[i][1].install_readwrite_bank(start, end, m_bank[i]); + } + + m_view[3][2].install_read_bank(0x6000, 0x7fff, m_bank[3]); + m_view[3][2].install_read_handler(0x7ff0, 0x7ff7, read8sm_delegate(*this, [this] (offs_t offset) { return m_selected_bank[offset] & 0xff; }, "bank_r")); + m_view[3][3].install_readwrite_bank(0x6000, 0x7fff, m_bank[3]); + m_view[3][3].install_read_handler(0x7ff0, 0x7ff7, read8sm_delegate(*this, [this] (offs_t offset) { return m_selected_bank[offset] & 0xff; }, "bank_r")); + page(1)->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<0>))); + page(1)->install_write_handler(0x6400, 0x6400, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<1>))); + page(1)->install_write_handler(0x6800, 0x6800, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<2>))); + page(1)->install_write_handler(0x6c00, 0x6c00, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<3>))); + page(1)->install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<4>))); + page(1)->install_write_handler(0x7400, 0x7400, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<6>))); + page(1)->install_write_handler(0x7800, 0x7800, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<5>))); + page(1)->install_write_handler(0x7c00, 0x7c00, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<7>))); + page(1)->install_readwrite_handler(0x7ff8, 0x7ff8, + read8smo_delegate(*this, [this] () { return m_bank9; }, "bank9_r"), + write8smo_delegate(*this, [this] (u8 data) + { + m_bank9 = data; + select_banks(); + }, "bank9_w")); + page(1)->install_write_handler(0x7ff9, 0x7ff9, write8smo_delegate(*this, [this] (u8 data) + { + m_control = data; + select_banks(); + }, "control_w" + )); +} + + +void msx_slot_panasonic08r_device::device_reset() +{ + m_control = 0; + m_bank9 = 0; + for (int i = 0 ; i < 8; i++) + { + m_selected_bank[i] = 0; + m_bank[i]->set_entry(0); + m_view[i].select(0); + } +} + + +template +void msx_slot_panasonic08r_device::set_view() +{ + const bool sram_active = (m_selected_bank[Bank] >= 0x80 && m_selected_bank[Bank] < 0x84); + const bool ram_active = (m_selected_bank[Bank] >= 0x180); + const int view = ((sram_active || ram_active) ? 1 : 0) | ((Bank == 3 && BIT(m_control, 2)) ? 2 : 0); + + m_view[Bank].select(view); +} + + +template +void msx_slot_panasonic08r_device::bank_w(u8 data) +{ + u16 bank = data; + + if (BIT(m_control, 4)) + bank |= (BIT(m_bank9, Bank) << 8); + m_selected_bank[Bank] = bank; + m_bank[Bank]->set_entry(bank); + set_view(); +} + + +void msx_slot_panasonic08r_device::select_banks() +{ + bank_w<0>(m_selected_bank[0]); + bank_w<1>(m_selected_bank[1]); + bank_w<2>(m_selected_bank[2]); + bank_w<3>(m_selected_bank[3]); + bank_w<4>(m_selected_bank[4]); + bank_w<5>(m_selected_bank[5]); + bank_w<6>(m_selected_bank[6]); + bank_w<7>(m_selected_bank[7]); +} diff --git a/src/devices/bus/msx/slot/panasonic08r.h b/src/devices/bus/msx/slot/panasonic08r.h new file mode 100644 index 00000000000..c7efcf6e27a --- /dev/null +++ b/src/devices/bus/msx/slot/panasonic08r.h @@ -0,0 +1,52 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +#ifndef MAME_BUS_MSX_SLOT_PANASONIC08R_H +#define MAME_BUS_MSX_SLOT_PANASONIC08R_H + +#pragma once + +#include "ram_mm.h" +#include "slot.h" +#include "machine/nvram.h" + + +DECLARE_DEVICE_TYPE(MSX_SLOT_PANASONIC08R, msx_slot_panasonic08r_device) + + +class msx_slot_panasonic08r_device : public device_t, public msx_internal_slot_interface +{ +public: + msx_slot_panasonic08r_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // configuration helpers + template msx_slot_panasonic08r_device &set_mm_tag(T &&tag) { m_mm.set_tag(std::forward(tag)); return *this; } + void set_rom_start(const char *region, u32 offset) { m_rom_region.set_tag(region); m_region_offset = offset; } + msx_slot_panasonic08r_device &set_sram_size(u16 size) { m_sram_size = size; return *this; } + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + virtual void device_add_mconfig(machine_config &config) override; + +private: + template void set_view(); + template void bank_w(u8 data); + + void select_banks(); + + u16 m_sram_size; + required_device m_nvram; + required_memory_region m_rom_region; + memory_bank_array_creator<8> m_bank; + memory_view m_view[8]; + required_device m_mm; + u32 m_region_offset; + u16 m_selected_bank[8]; + u8 m_control; + u8 m_bank9; + std::unique_ptr m_sram; +}; + + +#endif // MAME_BUS_MSX_SLOT_PANASONIC08R_H diff --git a/src/devices/bus/msx/slot/ram.cpp b/src/devices/bus/msx/slot/ram.cpp index 92f9a57929d..03219dbf824 100644 --- a/src/devices/bus/msx/slot/ram.cpp +++ b/src/devices/bus/msx/slot/ram.cpp @@ -14,10 +14,13 @@ msx_slot_ram_device::msx_slot_ram_device(const machine_config &mconfig, const ch void msx_slot_ram_device::device_start() { - m_ram.resize(m_size); - save_item(NAME(m_ram)); + if (m_size < m_end_address - m_start_address) + fatalerror("Invalid size %04x for address range %004x - %04x\n", m_start_address, m_end_address); - u8 *ram = m_ram.data(); + m_ram = std::make_unique(m_size); + save_pointer(NAME(m_ram), m_size); + + u8 *ram = &m_ram[0]; u32 start_address = m_start_address; for (int i = m_start_address >> 14; i < 4 && i * 0x4000 < m_end_address; i++) { diff --git a/src/devices/bus/msx/slot/ram.h b/src/devices/bus/msx/slot/ram.h index 9e8f08bc373..c1a5e78e9e8 100644 --- a/src/devices/bus/msx/slot/ram.h +++ b/src/devices/bus/msx/slot/ram.h @@ -20,7 +20,7 @@ class msx_slot_ram_device : public device_t, virtual void device_start() override; private: - std::vector m_ram; + std::unique_ptr m_ram; }; diff --git a/src/devices/bus/msx/slot/ram_mm.cpp b/src/devices/bus/msx/slot/ram_mm.cpp index b32264a02eb..bd0de812474 100644 --- a/src/devices/bus/msx/slot/ram_mm.cpp +++ b/src/devices/bus/msx/slot/ram_mm.cpp @@ -30,9 +30,8 @@ void msx_slot_ram_mm_device::device_start() default: fatalerror("Invalid memory mapper size specified\n"); } - m_ram.resize(m_total_size); - - save_item(NAME(m_ram)); + m_ram = std::make_unique(m_total_size); + save_pointer(NAME(m_ram), m_total_size); // Install IO read/write handlers using taps to prevent overwriting taps // installed by other (external) memory mapper devices. @@ -41,7 +40,7 @@ void msx_slot_ram_mm_device::device_start() for (int i = 0; i < 4; i++) { - m_rambank[i]->configure_entries(0, u32(m_bank_mask) + 1, m_ram.data(), 0x4000); + m_rambank[i]->configure_entries(0, u32(m_bank_mask) + 1, &m_ram[0], 0x4000); page(i)->install_readwrite_bank(0x4000 * i, (0x4000 * i) + 0x3fff, m_rambank[i]); } } diff --git a/src/devices/bus/msx/slot/ram_mm.h b/src/devices/bus/msx/slot/ram_mm.h index 69ce5f41053..8c4c1426264 100644 --- a/src/devices/bus/msx/slot/ram_mm.h +++ b/src/devices/bus/msx/slot/ram_mm.h @@ -15,6 +15,10 @@ class msx_slot_ram_mm_device : public device_t, public msx_internal_slot_interfa msx_slot_ram_mm_device &set_total_size(u32 total_size) { m_total_size = total_size; return *this; } msx_slot_ram_mm_device &set_unused_bits(u8 unused_bits) { m_unused_bits = unused_bits; return *this; } + // Backdoor for the Turbo-R firmware/internal mapper to access internal RAM. + u32 get_ram_size() { return m_total_size; } + u8 *get_ram_base() { return &m_ram[0]; } + protected: virtual void device_start() override; @@ -22,7 +26,7 @@ class msx_slot_ram_mm_device : public device_t, public msx_internal_slot_interfa u8 read_mapper_bank(offs_t offset); void write_mapper_bank(offs_t offset, u8 data); - std::vector m_ram; + std::unique_ptr m_ram; u32 m_total_size; u8 m_bank_mask; u8 m_unused_bits; diff --git a/src/devices/bus/msx/slot/sony08.cpp b/src/devices/bus/msx/slot/sony08.cpp index bf13f091ee1..29fd07cca93 100644 --- a/src/devices/bus/msx/slot/sony08.cpp +++ b/src/devices/bus/msx/slot/sony08.cpp @@ -38,8 +38,10 @@ void msx_slot_sony08_device::device_start() fatalerror("Memory region '%s' is too small for the SONY08 firmware\n", m_rom_region.finder_tag()); } - m_sram.resize(SRAM_SIZE); - m_nvram->set_base(m_sram.data(), SRAM_SIZE); + m_sram= std::make_unique(SRAM_SIZE); + m_nvram->set_base(&m_sram[0], SRAM_SIZE); + + save_pointer(NAME(m_sram), SRAM_SIZE); for (int i = 0; i < 4; i++) m_rombank[i]->configure_entries(0, 0x80, m_rom_region->base() + m_region_offset, 0x2000); @@ -48,7 +50,7 @@ void msx_slot_sony08_device::device_start() page(0)->install_view(0x0000, 0x3fff, m_view[0]); m_view[0][0]; - m_view[0][1].install_ram(0x0000, 0x3fff, m_sram.data()); + m_view[0][1].install_ram(0x0000, 0x3fff, &m_sram[0]); page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]); page(1)->install_write_handler(0x4fff, 0x4fff, emu::rw_delegate(*this, FUNC(msx_slot_sony08_device::bank_w<0>))); diff --git a/src/devices/bus/msx/slot/sony08.h b/src/devices/bus/msx/slot/sony08.h index 2fa9d9e89ca..c8e364612d0 100644 --- a/src/devices/bus/msx/slot/sony08.h +++ b/src/devices/bus/msx/slot/sony08.h @@ -36,7 +36,7 @@ class msx_slot_sony08_device : public device_t, public msx_internal_slot_interfa memory_bank_array_creator<6> m_rombank; memory_view m_view[2]; u32 m_region_offset; - std::vector m_sram; + std::unique_ptr m_sram; }; diff --git a/src/devices/bus/supracan/rom.cpp b/src/devices/bus/supracan/rom.cpp new file mode 100644 index 00000000000..ca3be333df6 --- /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 00000000000..a75cb26fa66 --- /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 00000000000..19f10c449f6 --- /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 00000000000..2c285377807 --- /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/devices/cpu/tlcs900/tlcs900.cpp b/src/devices/cpu/tlcs900/tlcs900.cpp index 166a07db6e8..0dcceeb0153 100644 --- a/src/devices/cpu/tlcs900/tlcs900.cpp +++ b/src/devices/cpu/tlcs900/tlcs900.cpp @@ -70,13 +70,12 @@ std::unique_ptr tlcs900_device::create_disassembler() } -/* Flag defines */ -#define FLAG_CF 0x01 -#define FLAG_NF 0x02 -#define FLAG_VF 0x04 -#define FLAG_HF 0x10 -#define FLAG_ZF 0x40 -#define FLAG_SF 0x80 +static constexpr u8 FLAG_CF = 0x01; +static constexpr u8 FLAG_NF = 0x02; +static constexpr u8 FLAG_VF = 0x04; +static constexpr u8 FLAG_HF = 0x10; +static constexpr u8 FLAG_ZF = 0x40; +static constexpr u8 FLAG_SF = 0x80; inline uint8_t tlcs900_device::RDOP() diff --git a/src/devices/cpu/tlcs900/tmp95c061.cpp b/src/devices/cpu/tlcs900/tmp95c061.cpp index d74d7baa0a1..6c126be5cb6 100644 --- a/src/devices/cpu/tlcs900/tmp95c061.cpp +++ b/src/devices/cpu/tlcs900/tmp95c061.cpp @@ -257,50 +257,52 @@ void tmp95c061_device::device_reset() } } +enum +{ + INTE0AD, + INTE45, + INTE67, + INTET10, + INTET32, + INTET54, + INTET76, + INTES0, + INTES1, + INTETC10, + INTETC32 +}; -#define TMP95C061_INTE0AD 0x0 -#define TMP95C061_INTE45 0x1 -#define TMP95C061_INTE67 0x2 -#define TMP95C061_INTET10 0x3 -#define TMP95C061_INTET32 0x4 -#define TMP95C061_INTET54 0x5 -#define TMP95C061_INTET76 0x6 -#define TMP95C061_INTES0 0x7 -#define TMP95C061_INTES1 0x8 -#define TMP95C061_INTETC10 0x9 -#define TMP95C061_INTETC32 0xa - -#define TMP95C061_NUM_MASKABLE_IRQS 22 static const struct { uint8_t reg; uint8_t iff; uint8_t vector; -} tmp95c061_irq_vector_map[TMP95C061_NUM_MASKABLE_IRQS] = -{ - { TMP95C061_INTETC32, 0x80, 0x80 }, /* INTTC3 */ - { TMP95C061_INTETC32, 0x08, 0x7c }, /* INTTC2 */ - { TMP95C061_INTETC10, 0x80, 0x78 }, /* INTTC1 */ - { TMP95C061_INTETC10, 0x08, 0x74 }, /* INTTC0 */ - { TMP95C061_INTE0AD, 0x80, 0x70 }, /* INTAD */ - { TMP95C061_INTES1, 0x80, 0x6c }, /* INTTX1 */ - { TMP95C061_INTES1, 0x08, 0x68 }, /* INTRX1 */ - { TMP95C061_INTES0, 0x80, 0x64 }, /* INTTX0 */ - { TMP95C061_INTES0, 0x08, 0x60 }, /* INTRX0 */ - { TMP95C061_INTET76, 0x80, 0x5c }, /* INTTR7 */ - { TMP95C061_INTET76, 0x08, 0x58 }, /* INTTR6 */ - { TMP95C061_INTET54, 0x80, 0x54 }, /* INTTR5 */ - { TMP95C061_INTET54, 0x08, 0x50 }, /* INTTR4 */ - { TMP95C061_INTET32, 0x80, 0x4c }, /* INTT3 */ - { TMP95C061_INTET32, 0x08, 0x48 }, /* INTT2 */ - { TMP95C061_INTET10, 0x80, 0x44 }, /* INTT1 */ - { TMP95C061_INTET10, 0x08, 0x40 }, /* INTT0 */ - /* 0x3c - reserved */ - { TMP95C061_INTE67, 0x80, 0x38 }, /* INT7 */ - { TMP95C061_INTE67, 0x08, 0x34 }, /* INT6 */ - { TMP95C061_INTE45, 0x80, 0x30 }, /* INT5 */ - { TMP95C061_INTE45, 0x08, 0x2c }, /* INT4 */ - { TMP95C061_INTE0AD, 0x08, 0x28 } /* INT0 */ +} tmp95c061_irq_vector_map[] = +{ + { INTETC32, 0x80, 0x80 }, // INTTC3 + { INTETC32, 0x08, 0x7c }, // INTTC2 + { INTETC10, 0x80, 0x78 }, // INTTC1 + { INTETC10, 0x08, 0x74 }, // INTTC0 + { INTE0AD, 0x80, 0x70 }, // INTAD + { INTES1, 0x80, 0x6c }, // INTTX1 + { INTES1, 0x08, 0x68 }, // INTRX1 + { INTES0, 0x80, 0x64 }, // INTTX0 + { INTES0, 0x08, 0x60 }, // INTRX0 + { INTET76, 0x80, 0x5c }, // INTTR7 + { INTET76, 0x08, 0x58 }, // INTTR6 + { INTET54, 0x80, 0x54 }, // INTTR5 + { INTET54, 0x08, 0x50 }, // INTTR4 + { INTET32, 0x80, 0x4c }, // INTT3 + { INTET32, 0x08, 0x48 }, // INTT2 + { INTET10, 0x80, 0x44 }, // INTT1 + { INTET10, 0x08, 0x40 }, // INTT0 + // 0x3c - reserved + { INTE67, 0x80, 0x38 }, // INT7 + { INTE67, 0x08, 0x34 }, // INT6 + { INTE45, 0x80, 0x30 }, // INT5 + { INTE45, 0x08, 0x2c }, // INT4 + { INTE0AD, 0x08, 0x28 } // INT0 }; +static constexpr u8 NUM_MASKABLE_IRQS = sizeof(tmp95c061_irq_vector_map) / 3; int tmp95c061_device::tlcs900_process_hdma( int channel ) @@ -312,11 +314,11 @@ int tmp95c061_device::tlcs900_process_hdma( int channel ) { int irq = 0; - while( irq < TMP95C061_NUM_MASKABLE_IRQS && tmp95c061_irq_vector_map[irq].vector != vector ) + while( irq < NUM_MASKABLE_IRQS && tmp95c061_irq_vector_map[irq].vector != vector ) irq++; /* Check if our interrupt flip-flop is set */ - if ( irq < TMP95C061_NUM_MASKABLE_IRQS && m_int_reg[tmp95c061_irq_vector_map[irq].reg] & tmp95c061_irq_vector_map[irq].iff ) + if ( irq < NUM_MASKABLE_IRQS && m_int_reg[tmp95c061_irq_vector_map[irq].reg] & tmp95c061_irq_vector_map[irq].iff ) { switch( m_dmam[channel].b.l & 0x1f ) { @@ -406,16 +408,16 @@ int tmp95c061_device::tlcs900_process_hdma( int channel ) switch( channel ) { case 0: - m_int_reg[TMP95C061_INTETC10] |= 0x08; + m_int_reg[INTETC10] |= 0x08; break; case 1: - m_int_reg[TMP95C061_INTETC10] |= 0x80; + m_int_reg[INTETC10] |= 0x80; break; case 2: - m_int_reg[TMP95C061_INTETC32] |= 0x08; + m_int_reg[INTETC32] |= 0x08; break; case 3: - m_int_reg[TMP95C061_INTETC32] |= 0x80; + m_int_reg[INTETC32] |= 0x80; break; } } @@ -475,7 +477,7 @@ void tmp95c061_device::tlcs900_check_irqs() } /* Check regular irqs */ - for( i = 0; i < TMP95C061_NUM_MASKABLE_IRQS; i++ ) + for( i = 0; i < NUM_MASKABLE_IRQS; i++ ) { if ( m_int_reg[tmp95c061_irq_vector_map[i].reg] & tmp95c061_irq_vector_map[i].iff ) { @@ -563,7 +565,7 @@ void tmp95c061_device::tlcs900_handle_ad() m_ad_mode &= ~ 0x40; m_ad_mode |= 0x80; - m_int_reg[TMP95C061_INTE0AD] |= 0x80; + m_int_reg[INTE0AD] |= 0x80; m_check_irqs = 1; /* AD repeat mode */ @@ -661,7 +663,7 @@ void tmp95c061_device::tlcs900_handle_timers() if ( ( m_t8_mode[0] & 0xc0 ) != 0x40 ) { m_timer[0] = 0; - m_int_reg[TMP95C061_INTET10] |= 0x08; + m_int_reg[INTET10] |= 0x08; } } } @@ -691,7 +693,7 @@ void tmp95c061_device::tlcs900_handle_timers() if ( m_timer[1] == m_t8_reg[1] ) { m_timer[1] = 0; - m_int_reg[TMP95C061_INTET10] |= 0x80; + m_int_reg[INTET10] |= 0x80; if ( m_t8_invert & 0x02 ) { @@ -738,7 +740,7 @@ void tmp95c061_device::tlcs900_handle_timers() if ( ( m_t8_mode[1] & 0xc0 ) != 0x40 ) { m_timer[2] = 0; - m_int_reg[TMP95C061_INTET32] |= 0x08; + m_int_reg[INTET32] |= 0x08; } } } @@ -768,7 +770,7 @@ void tmp95c061_device::tlcs900_handle_timers() if ( m_timer[3] == m_t8_reg[3] ) { m_timer[3] = 0; - m_int_reg[TMP95C061_INTET32] |= 0x80; + m_int_reg[INTET32] |= 0x80; if ( m_t8_invert & 0x20 ) { @@ -815,16 +817,16 @@ void tmp95c061_device::execute_set_input(int input, int level) { /* Leave HALT state */ m_halted = 0; - m_int_reg[TMP95C061_INTE0AD] |= 0x08; + m_int_reg[INTE0AD] |= 0x08; } } else { /* Level detect */ if ( level == ASSERT_LINE ) - m_int_reg[TMP95C061_INTE0AD] |= 0x08; + m_int_reg[INTE0AD] |= 0x08; else - m_int_reg[TMP95C061_INTE0AD] &= ~ 0x08; + m_int_reg[INTE0AD] &= ~ 0x08; } } m_level[TLCS900_INT0] = level; @@ -835,7 +837,7 @@ void tmp95c061_device::execute_set_input(int input, int level) { if ( m_level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE ) { - m_int_reg[TMP95C061_INTE45] |= 0x08; + m_int_reg[INTE45] |= 0x08; } } m_level[TLCS900_INT4] = level; @@ -846,7 +848,7 @@ void tmp95c061_device::execute_set_input(int input, int level) { if ( m_level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE ) { - m_int_reg[TMP95C061_INTE45] |= 0x80; + m_int_reg[INTE45] |= 0x80; } } m_level[TLCS900_INT5] = level; @@ -1262,7 +1264,7 @@ uint8_t tmp95c061_device::sc0buf_r() void tmp95c061_device::sc0buf_w(uint8_t data) { // Fake finish sending data - m_int_reg[TMP95C061_INTES0] |= 0x80; + m_int_reg[INTES0] |= 0x80; m_check_irqs = 1; } @@ -1307,7 +1309,7 @@ uint8_t tmp95c061_device::sc1buf_r() void tmp95c061_device::sc1buf_w(uint8_t data) { // Fake finish sending data - m_int_reg[TMP95C061_INTES1] |= 0x80; + m_int_reg[INTES1] |= 0x80; m_check_irqs = 1; } @@ -1364,7 +1366,7 @@ uint8_t tmp95c061_device::adreg_r(offs_t offset) return m_ad_result[offset >> 1] >> 2; // Reading data from the upper 8 bits clears INTE0AD IADC - m_int_reg[TMP95C061_INTE0AD] &= ~0x80; + m_int_reg[INTE0AD] &= ~0x80; return m_ad_result[offset >> 1] << 6 | 0x3f; } diff --git a/src/devices/cpu/tlcs900/tmp95c063.cpp b/src/devices/cpu/tlcs900/tmp95c063.cpp index c70a19e85cc..7de78938de9 100644 --- a/src/devices/cpu/tlcs900/tmp95c063.cpp +++ b/src/devices/cpu/tlcs900/tmp95c063.cpp @@ -176,64 +176,64 @@ void tmp95c063_device::device_config_complete() } } +enum +{ + INTE0AD, + INTE12, + INTE34, + INTE56, + INTE78, + INTET01, + INTET23, + INTET45, + INTET67, + INTET89, + INTETAB, + INTES0, + INTES1, + INTETC01, + INTETC23 +}; - -#define TMP95C063_INTE0AD 0x0 -#define TMP95C063_INTE12 0x1 -#define TMP95C063_INTE34 0x2 -#define TMP95C063_INTE56 0x3 -#define TMP95C063_INTE78 0x4 -#define TMP95C063_INTET01 0x5 -#define TMP95C063_INTET23 0x6 -#define TMP95C063_INTET45 0x7 -#define TMP95C063_INTET67 0x8 -#define TMP95C063_INTET89 0x9 -#define TMP95C063_INTETAB 0xa -#define TMP95C063_INTES0 0xb -#define TMP95C063_INTES1 0xc -#define TMP95C063_INTETC01 0xd -#define TMP95C063_INTETC23 0xe - - -#define TMP95C063_NUM_MASKABLE_IRQS 30 static const struct { uint8_t reg; uint8_t iff; uint8_t vector; -} tmp95c063_irq_vector_map[TMP95C063_NUM_MASKABLE_IRQS] = -{ - { TMP95C063_INTETC23, 0x80, 0xa0 }, /* INTTC3 */ - { TMP95C063_INTETC23, 0x08, 0x9c }, /* INTTC2 */ - { TMP95C063_INTETC01, 0x80, 0x98 }, /* INTTC1 */ - { TMP95C063_INTETC01, 0x08, 0x94 }, /* INTTC0 */ - { TMP95C063_INTE0AD, 0x80, 0x90 }, /* INTAD */ - { TMP95C063_INTES1, 0x80, 0x8c }, /* INTTX1 */ - { TMP95C063_INTES1, 0x08, 0x88 }, /* INTRX1 */ - { TMP95C063_INTES0, 0x80, 0x84 }, /* INTTX0 */ - { TMP95C063_INTES0, 0x08, 0x80 }, /* INTRX0 */ - { TMP95C063_INTETAB, 0x80, 0x7c }, /* INTTRB */ - { TMP95C063_INTETAB, 0x08, 0x78 }, /* INTTRA */ - { TMP95C063_INTET89, 0x80, 0x74 }, /* INTTR9 */ - { TMP95C063_INTET89, 0x80, 0x70 }, /* INTTR8 */ - { TMP95C063_INTET67, 0x80, 0x6c }, /* INTT7 */ - { TMP95C063_INTET67, 0x08, 0x68 }, /* INTT6 */ - { TMP95C063_INTET45, 0x80, 0x64 }, /* INTT5 */ - { TMP95C063_INTET45, 0x08, 0x60 }, /* INTT4 */ - { TMP95C063_INTET23, 0x80, 0x5c }, /* INTT3 */ - { TMP95C063_INTET23, 0x08, 0x58 }, /* INTT2 */ - { TMP95C063_INTET01, 0x80, 0x54 }, /* INTT1 */ - { TMP95C063_INTET01, 0x08, 0x50 }, /* INTT0 */ - { TMP95C063_INTE78, 0x80, 0x4c }, /* int8_t */ - { TMP95C063_INTE78, 0x08, 0x48 }, /* INT7 */ - { TMP95C063_INTE56, 0x80, 0x44 }, /* INT6 */ - { TMP95C063_INTE56, 0x08, 0x40 }, /* INT5 */ - /* 0x3c - reserved */ - { TMP95C063_INTE34, 0x80, 0x38 }, /* INT4 */ - { TMP95C063_INTE34, 0x08, 0x34 }, /* INT3 */ - { TMP95C063_INTE12, 0x80, 0x30 }, /* INT2 */ - { TMP95C063_INTE12, 0x08, 0x2c }, /* INT1 */ - { TMP95C063_INTE0AD, 0x08, 0x28 } /* INT0 */ +} tmp95c063_irq_vector_map[] = +{ + { INTETC23, 0x80, 0xa0 }, // INTTC3 + { INTETC23, 0x08, 0x9c }, // INTTC2 + { INTETC01, 0x80, 0x98 }, // INTTC1 + { INTETC01, 0x08, 0x94 }, // INTTC0 + { INTE0AD, 0x80, 0x90 }, // INTAD + { INTES1, 0x80, 0x8c }, // INTTX1 + { INTES1, 0x08, 0x88 }, // INTRX1 + { INTES0, 0x80, 0x84 }, // INTTX0 + { INTES0, 0x08, 0x80 }, // INTRX0 + { INTETAB, 0x80, 0x7c }, // INTTRB + { INTETAB, 0x08, 0x78 }, // INTTRA + { INTET89, 0x80, 0x74 }, // INTTR9 + { INTET89, 0x80, 0x70 }, // INTTR8 + { INTET67, 0x80, 0x6c }, // INTT7 + { INTET67, 0x08, 0x68 }, // INTT6 + { INTET45, 0x80, 0x64 }, // INTT5 + { INTET45, 0x08, 0x60 }, // INTT4 + { INTET23, 0x80, 0x5c }, // INTT3 + { INTET23, 0x08, 0x58 }, // INTT2 + { INTET01, 0x80, 0x54 }, // INTT1 + { INTET01, 0x08, 0x50 }, // INTT0 + { INTE78, 0x80, 0x4c }, // INT8 + { INTE78, 0x08, 0x48 }, // INT7 + { INTE56, 0x80, 0x44 }, // INT6 + { INTE56, 0x08, 0x40 }, // INT5 + // 0x3c - reserved + { INTE34, 0x80, 0x38 }, // INT4 + { INTE34, 0x08, 0x34 }, // INT3 + { INTE12, 0x80, 0x30 }, // INT2 + { INTE12, 0x08, 0x2c }, // INT1 + { INTE0AD, 0x08, 0x28 } // INT0 }; +static constexpr u8 NUM_MASKABLE_IRQS = sizeof(tmp95c063_irq_vector_map) / 3; void tmp95c063_device::tlcs900_handle_timers() { @@ -277,7 +277,7 @@ void tmp95c063_device::tlcs900_handle_timers() if ( ( m_t8_mode[0] & 0xc0 ) != 0x40 ) { m_timer[0] = 0; - m_int_reg[TMP95C063_INTET01] |= 0x08; + m_int_reg[INTET01] |= 0x08; } } } @@ -307,7 +307,7 @@ void tmp95c063_device::tlcs900_handle_timers() if ( m_timer[1] == m_t8_reg[1] ) { m_timer[1] = 0; - m_int_reg[TMP95C063_INTET01] |= 0x80; + m_int_reg[INTET01] |= 0x80; if ( m_t8_invert[0] & 0x02 ) { @@ -354,7 +354,7 @@ void tmp95c063_device::tlcs900_handle_timers() if ( ( m_t8_mode[1] & 0xc0 ) != 0x40 ) { m_timer[2] = 0; - m_int_reg[TMP95C063_INTET23] |= 0x08; + m_int_reg[INTET23] |= 0x08; } } } @@ -384,7 +384,7 @@ void tmp95c063_device::tlcs900_handle_timers() if ( m_timer[3] == m_t8_reg[3] ) { m_timer[3] = 0; - m_int_reg[TMP95C063_INTET23] |= 0x80; + m_int_reg[INTET23] |= 0x80; if ( m_t8_invert[1] & 0x20 ) { @@ -434,7 +434,7 @@ void tmp95c063_device::tlcs900_check_irqs() } /* Check regular irqs */ - for( i = 0; i < TMP95C063_NUM_MASKABLE_IRQS; i++ ) + for( i = 0; i < NUM_MASKABLE_IRQS; i++ ) { if ( m_int_reg[tmp95c063_irq_vector_map[i].reg] & tmp95c063_irq_vector_map[i].iff ) { @@ -544,7 +544,7 @@ void tmp95c063_device::tlcs900_handle_ad() m_ad_mode1 &= ~ 0x40; m_ad_mode1 |= 0x80; - m_int_reg[TMP95C063_INTE0AD] |= 0x80; + m_int_reg[INTE0AD] |= 0x80; m_check_irqs = 1; } } @@ -1225,7 +1225,7 @@ uint8_t tmp95c063_device::sc0buf_r() void tmp95c063_device::sc0buf_w(uint8_t data) { // Fake finish sending data - m_int_reg[TMP95C063_INTES0] |= 0x80; + m_int_reg[INTES0] |= 0x80; m_check_irqs = 1; } @@ -1270,7 +1270,7 @@ uint8_t tmp95c063_device::sc1buf_r() void tmp95c063_device::sc1buf_w(uint8_t data) { // Fake finish sending data - m_int_reg[TMP95C063_INTES1] |= 0x80; + m_int_reg[INTES1] |= 0x80; m_check_irqs = 1; } @@ -1503,16 +1503,16 @@ void tmp95c063_device::execute_set_input(int input, int level) { /* Leave HALT state */ m_halted = 0; - m_int_reg[TMP95C063_INTE0AD] |= 0x08; + m_int_reg[INTE0AD] |= 0x08; } } else { /* Level detect */ if (level == ASSERT_LINE) - m_int_reg[TMP95C063_INTE0AD] |= 0x08; + m_int_reg[INTE0AD] |= 0x08; else - m_int_reg[TMP95C063_INTE0AD] &= ~ 0x08; + m_int_reg[INTE0AD] &= ~ 0x08; } } m_level[TLCS900_INT0] = level; @@ -1521,11 +1521,11 @@ void tmp95c063_device::execute_set_input(int input, int level) case TLCS900_INT1: if (m_level[TLCS900_INT1] == CLEAR_LINE && level == ASSERT_LINE) { - m_int_reg[TMP95C063_INTE12] |= 0x08; + m_int_reg[INTE12] |= 0x08; } else if (m_level[TLCS900_INT1] == ASSERT_LINE && level == CLEAR_LINE) { - m_int_reg[TMP95C063_INTE12] &= ~0x08; + m_int_reg[INTE12] &= ~0x08; } m_level[TLCS900_INT1] = level; break; @@ -1533,11 +1533,11 @@ void tmp95c063_device::execute_set_input(int input, int level) case TLCS900_INT2: if (m_level[TLCS900_INT2] == CLEAR_LINE && level == ASSERT_LINE) { - m_int_reg[TMP95C063_INTE12] |= 0x80; + m_int_reg[INTE12] |= 0x80; } else if (m_level[TLCS900_INT2] == ASSERT_LINE && level == CLEAR_LINE) { - m_int_reg[TMP95C063_INTE12] &= ~0x80; + m_int_reg[INTE12] &= ~0x80; } m_level[TLCS900_INT2] = level; break; @@ -1545,11 +1545,11 @@ void tmp95c063_device::execute_set_input(int input, int level) case TLCS900_INT3: if (m_level[TLCS900_INT3] == CLEAR_LINE && level == ASSERT_LINE) { - m_int_reg[TMP95C063_INTE34] |= 0x08; + m_int_reg[INTE34] |= 0x08; } else if (m_level[TLCS900_INT3] == ASSERT_LINE && level == CLEAR_LINE) { - m_int_reg[TMP95C063_INTE34] &= ~0x08; + m_int_reg[INTE34] &= ~0x08; } m_level[TLCS900_INT3] = level; break; @@ -1559,7 +1559,7 @@ void tmp95c063_device::execute_set_input(int input, int level) { if ( m_level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE ) { - m_int_reg[TMP95C063_INTE34] |= 0x80; + m_int_reg[INTE34] |= 0x80; } } m_level[TLCS900_INT4] = level; @@ -1570,7 +1570,7 @@ void tmp95c063_device::execute_set_input(int input, int level) { if ( m_level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE ) { - m_int_reg[TMP95C063_INTE56] |= 0x08; + m_int_reg[INTE56] |= 0x08; } } m_level[TLCS900_INT5] = level; @@ -1579,11 +1579,11 @@ void tmp95c063_device::execute_set_input(int input, int level) case TLCS900_INT6: if (m_level[TLCS900_INT6] == CLEAR_LINE && level == ASSERT_LINE) { - m_int_reg[TMP95C063_INTE56] |= 0x80; + m_int_reg[INTE56] |= 0x80; } else if (m_level[TLCS900_INT6] == ASSERT_LINE && level == CLEAR_LINE) { - m_int_reg[TMP95C063_INTE56] &= ~0x80; + m_int_reg[INTE56] &= ~0x80; } m_level[TLCS900_INT6] = level; break; diff --git a/src/mame/funtech/supracan.cpp b/src/mame/funtech/supracan.cpp index b72028b0561..04a17f8d451 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; @@ -227,6 +227,12 @@ class supracan_state : public driver_device uint16_t m_tilemap_flags[3]{}; uint16_t m_tilemap_mode[3]{}; uint16_t m_tilemap_tile_mode[3]{}; + uint16_t m_tilemap_linescrollx_addr[3]{}; + + uint16_t m_window_control[2]{}; + uint16_t m_window_start_addr[2]{}; + uint16_t m_window_scrollx[2]{}; + uint16_t m_window_scrolly[2]{}; uint32_t m_roz_base_addr = 0; uint16_t m_roz_mode = 0; @@ -242,7 +248,6 @@ class supracan_state : public driver_device uint16_t m_roz_coeffc = 0; uint16_t m_roz_coeffd = 0; int32_t m_roz_changed = 0; - uint16_t m_unk_1d0 = 0; u8 m_pixel_mode = 0; u8 m_gfx_mode = 0; @@ -265,7 +270,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 +312,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) @@ -1015,7 +1019,6 @@ uint32_t supracan_state::screen_update(screen_device &screen, bitmap_ind16 &bitm // mix screen int xsize = 0, ysize = 0; // int tilemap_num; - int priority = 0; for (int pri = 7; pri >= 0; pri--) { @@ -1023,6 +1026,7 @@ uint32_t supracan_state::screen_update(screen_device &screen, bitmap_ind16 &bitm for (int layer = 0; layer < ROZ_LAYER_NUMBER + 1; layer ++) { int enabled = 0; + int layer_priority = 0; // ROZ if (layer == ROZ_LAYER_NUMBER) @@ -1030,17 +1034,17 @@ uint32_t supracan_state::screen_update(screen_device &screen, bitmap_ind16 &bitm enabled = BIT(m_video_flags, 2); if (!enabled) continue; - priority = ((m_roz_mode >> 13) & 7); + layer_priority = ((m_roz_mode >> 13) & 7); } else { enabled = BIT(m_video_flags, 7 - layer); if (!enabled) continue; - priority = ((m_tilemap_flags[layer] >> 13) & 7); + layer_priority = ((m_tilemap_flags[layer] >> 13) & 7); } - if (priority == pri) + if (layer_priority == pri) { int which_tilemap_size = get_tilemap_dimensions(xsize, ysize, layer); bitmap_ind16 &src_bitmap = m_tilemap_sizes[layer][which_tilemap_size]->pixmap(); @@ -1094,22 +1098,30 @@ uint32_t supracan_state::screen_update(screen_device &screen, bitmap_ind16 &bitm uint16_t *src = &src_bitmap.pix(realy & ((ysize * 8) - 1)); uint8_t *priop = &m_prio_bitmap.pix(y); + int line_scroll_x = scrollx; + + // formduel main menu + if (BIT(m_tilemap_tile_mode[layer], 14)) + { + int16_t linescrollx = (int16_t)m_vram[((m_tilemap_linescrollx_addr[layer] << 1) + y) & 0xffff]; + line_scroll_x += linescrollx; + } for (int x = cliprect.min_x; x <= cliprect.max_x; x++) { int actualx = x & mosaic_mask; - int realx = actualx + scrollx; + int realx = actualx + line_scroll_x; if (!wrap) - if (scrollx + x < 0 || scrollx + x > ((xsize * 8) - 1)) + if (line_scroll_x + x < 0 || line_scroll_x + x > ((xsize * 8) - 1)) continue; uint16_t srcpix = src[realx & ((xsize * 8) - 1)]; - if ((srcpix & transmask) != 0 && priority < (priop[x] >> 4)) + if ((srcpix & transmask) != 0 && layer_priority < (priop[x] >> 4)) { screen[x] = srcpix; - priop[x] = (priop[x] & 0x0f) | (priority << 4); + priop[x] = (priop[x] & 0x0f) | (layer_priority << 4); } } } @@ -1178,6 +1190,49 @@ uint32_t supracan_state::screen_update(screen_device &screen, bitmap_ind16 &bitm } } + + // TODO: secondary window control at $1d8-$1df (no SW sets it up so far) + if (BIT(m_video_flags, 1)) + { + // bit 15: enabled by magipool at circular intro, will show sprites above it if checked with. + int layer_priority = ((m_window_control[0] >> 13) & 3); + if (pri != layer_priority) + continue; + const u8 reverse_clip = BIT(m_window_control[0], 11); + // magipool enables this on title screen + // (for the white "overlay", revealing Funtech copyright progressively) + // TODO: confirm implementation + int window_scrollx = m_window_scrollx[0] & 0x3ff; + // TODO: window_scrolly + + if (window_scrollx & 0x200) + window_scrollx -= 0x400; + + const u8 window_pen = m_window_control[0] & 0xff; + + for (int y = cliprect.min_y; y <= cliprect.max_y; y++) + { + // bit 8 is unset by sangofgt, where it uses only two entries of the table on transitions. + const int ybase = BIT(m_window_control[0], 8) ? (y * 2) : 0; + const u32 clip_base = ((m_window_start_addr[0] << 1) + ybase) & 0xffff; + + const int16_t clip_min_x = (m_vram[clip_base + 0] + window_scrollx); + const int16_t clip_max_x = (m_vram[clip_base + 1] + window_scrollx); + uint8_t *priop = &m_prio_bitmap.pix(y); + + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) + { + if (layer_priority >= (priop[x] >> 4)) + continue; + + if ((x >= clip_min_x && x < clip_max_x) ^ reverse_clip) + { + bitmap.pix(y, x) = window_pen; + priop[x] = (priop[x] & 0x0f) | (layer_priority << 4); + } + } + } + } } @@ -1349,9 +1404,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 +1416,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 */ } @@ -1830,6 +1885,12 @@ TIMER_CALLBACK_MEMBER(supracan_state::scanline_cb) m_soundcpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); } break; + default: + // Effectively used by sangofgt only for clipping effects + // gamblord, monopoly, magipool also enables this but service is rte for all. + if (vpos < 240 && BIT(m_irq_mask, 4)) + m_maincpu->set_input_line(4, HOLD_LINE); + break; } m_video_timer->adjust(m_screen->time_until_pos((vpos + 1) % 262, 0)); @@ -1944,6 +2005,7 @@ void supracan_state::video_w(offs_t offset, uint16_t data, uint16_t mem_mask) visarea.set(0, (h320_mode ? 320 : 256) - 1, 8, 232 - 1); m_screen->configure(htotal, 262, visarea, attotime::from_ticks(htotal * 262, U13_CLOCK / divider).as_attoseconds()); + //m_screen->reset_origin(0, 0); } m_video_flags = data; @@ -1992,6 +2054,7 @@ void supracan_state::video_w(offs_t offset, uint16_t data, uint16_t mem_mask) case 0x106/2: m_tilemap_scrolly[0] = data; LOGMASKED(LOG_TILEMAP0, "tilemap_scrolly[0] = %04x\n", data); break; case 0x108/2: m_tilemap_base_addr[0] = data << 1; LOGMASKED(LOG_TILEMAP0, "tilemap_base_addr[0] = %05x\n", data << 2); break; case 0x10a/2: m_tilemap_mode[0] = data; LOGMASKED(LOG_TILEMAP0, "tilemap_mode[0] = %04x\n", data); break; + case 0x10c/2: m_tilemap_linescrollx_addr[0] = data; break; /* Tilemap 1 */ case 0x120/2: { @@ -2005,6 +2068,7 @@ void supracan_state::video_w(offs_t offset, uint16_t data, uint16_t mem_mask) case 0x126/2: m_tilemap_scrolly[1] = data; LOGMASKED(LOG_TILEMAP1, "tilemap_scrolly[1] = %04x\n", data); break; case 0x128/2: m_tilemap_base_addr[1] = data << 1; LOGMASKED(LOG_TILEMAP1, "tilemap_base_addr[1] = %05x\n", data << 2); break; case 0x12a/2: m_tilemap_mode[1] = data; LOGMASKED(LOG_TILEMAP1, "tilemap_mode[1] = %04x\n", data); break; + case 0x12c/2: m_tilemap_linescrollx_addr[1] = data; break; /* Tilemap 2 */ case 0x140/2: { @@ -2018,6 +2082,7 @@ void supracan_state::video_w(offs_t offset, uint16_t data, uint16_t mem_mask) case 0x146/2: m_tilemap_scrolly[2] = data; LOGMASKED(LOG_TILEMAP2, "tilemap_scrolly[2] = %04x\n", data); break; case 0x148/2: m_tilemap_base_addr[2] = data << 1; LOGMASKED(LOG_TILEMAP2, "tilemap_base_addr[2] = %05x\n", data << 2); break; case 0x14a/2: m_tilemap_mode[2] = data; LOGMASKED(LOG_TILEMAP2, "tilemap_mode[2] = %04x\n", data); break; + case 0x14c/2: m_tilemap_linescrollx_addr[2] = data; break; /* ROZ */ case 0x180/2: { @@ -2042,7 +2107,14 @@ void supracan_state::video_w(offs_t offset, uint16_t data, uint16_t mem_mask) case 0x19e/2: m_roz_unk_base2 = data << 2; LOGMASKED(LOG_ROZ, "roz_unk_base2 = %05x\n", data << 2); break; // color mixing stuff goes here - case 0x1d0/2: m_unk_1d0 = data; LOGMASKED(LOG_UNKNOWNS, "unk_1d0 = %04x\n", data); break; + case 0x1d0/2: COMBINE_DATA(&m_window_control[0]); break; + case 0x1d2/2: COMBINE_DATA(&m_window_start_addr[0]); break; + case 0x1d4/2: COMBINE_DATA(&m_window_scrollx[0]); break; + case 0x1d6/2: COMBINE_DATA(&m_window_scrolly[0]); break; + case 0x1d8/2: COMBINE_DATA(&m_window_control[1]); break; + case 0x1da/2: COMBINE_DATA(&m_window_start_addr[1]); break; + case 0x1dc/2: COMBINE_DATA(&m_window_scrollx[1]); break; + case 0x1de/2: COMBINE_DATA(&m_window_scrolly[1]); break; case 0x1f0/2: m_pixel_mode = data & 0x18; @@ -2060,20 +2132,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) @@ -2155,7 +2213,10 @@ void supracan_state::machine_start() save_item(NAME(m_roz_coeffc)); save_item(NAME(m_roz_coeffd)); save_item(NAME(m_roz_changed)); - save_item(NAME(m_unk_1d0)); + save_item(NAME(m_window_control)); + save_item(NAME(m_window_start_addr)); + save_item(NAME(m_window_scrollx)); + save_item(NAME(m_window_scrolly)); save_item(NAME(m_video_regs)); @@ -2275,6 +2336,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 +2378,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"); } diff --git a/src/mame/funtech/umc6619_sound.cpp b/src/mame/funtech/umc6619_sound.cpp index bf847eb12c7..40e08237e9c 100644 --- a/src/mame/funtech/umc6619_sound.cpp +++ b/src/mame/funtech/umc6619_sound.cpp @@ -14,6 +14,8 @@ #define VERBOSE (0) #include "logmacro.h" +#define LIVE_AUDIO_VIEW 0 + // device type definition DEFINE_DEVICE_TYPE(UMC6619_SOUND, umc6619_sound_device, "umc6619_sound", "UMC UM6619 Sound Engine") @@ -53,6 +55,7 @@ void umc6619_sound_device::device_start() save_item(STRUCT_MEMBER(m_channels, volume_l)); save_item(STRUCT_MEMBER(m_channels, volume_r)); save_item(STRUCT_MEMBER(m_channels, one_shot)); + save_item(STRUCT_MEMBER(m_channels, unk_upper_05)); save_item(NAME(m_regs)); } @@ -64,7 +67,20 @@ void umc6619_sound_device::device_reset() for (auto &channel : m_channels) { + channel.pitch = 0; + channel.length = 0; + channel.start_addr = 0; + channel.curr_addr = 0; + channel.end_addr = 0; + channel.addr_increment = 0; + channel.frac = 0; channel.register9 = 0; + std::fill(std::begin(channel.envelope), std::end(channel.envelope), 0); + channel.volume = 0; + channel.volume_l = 0; + channel.volume_r = 0; + channel.one_shot = false; + channel.unk_upper_05 = 0; } m_timer->reset(); @@ -84,10 +100,45 @@ TIMER_CALLBACK_MEMBER(umc6619_sound_device::channel_irq) } } +std::string umc6619_sound_device::print_audio_state() +{ + std::ostringstream outbuffer; + + util::stream_format(outbuffer, "channel | address | length | pitch | one? | vol | DMA? | (unk09) |\n"); + + for (int i = 0; i < 16; i++) + { + acan_channel &channel = m_channels[i]; + + util::stream_format(outbuffer, "%02d: %01d | %04x (%04x-%04x) | %04x | %04x | %d (%02x)| %02x | %02x | %02x %02x %02x %02x|\n" + , i + , BIT(m_active_channels, i) + , channel.curr_addr + , (channel.start_addr << 6) & 0xffff + , channel.end_addr + , channel.length + , channel.pitch + , channel.one_shot + , channel.unk_upper_05 + , channel.volume + , channel.register9 + , channel.envelope[0] + , channel.envelope[1] + , channel.envelope[2] + , channel.envelope[3] + ); + } + + return outbuffer.str(); +} + void umc6619_sound_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) { std::fill_n(&m_mix[0], outputs[0].samples() * 2, 0); + if (LIVE_AUDIO_VIEW) + popmessage(print_audio_state()); + for (int i = 0; i < 16 && m_active_channels != 0; i++) { if (BIT(m_active_channels, i)) @@ -244,6 +295,7 @@ void umc6619_sound_device::write(offs_t offset, uint8_t data) acan_channel &channel = m_channels[lower]; channel.length = 0x40 << ((data & 0x0e) >> 1); channel.one_shot = BIT(data, 0); + channel.unk_upper_05 = data & 0xf0; LOG("%s: Waveform length and attributes (voice %02x): %02x\n", machine().describe_context(), lower, data); break; } diff --git a/src/mame/funtech/umc6619_sound.h b/src/mame/funtech/umc6619_sound.h index d607735c7c9..17dff54dc46 100644 --- a/src/mame/funtech/umc6619_sound.h +++ b/src/mame/funtech/umc6619_sound.h @@ -49,6 +49,7 @@ class umc6619_sound_device : public device_t, public device_sound_interface uint8_t volume_l; uint8_t volume_r; bool one_shot; + uint8_t unk_upper_05; }; void keyon_voice(uint8_t voice); @@ -63,6 +64,8 @@ class umc6619_sound_device : public device_t, public device_sound_interface acan_channel m_channels[16]; uint8_t m_regs[256]; std::unique_ptr m_mix; + + std::string print_audio_state(); }; DECLARE_DEVICE_TYPE(UMC6619_SOUND, umc6619_sound_device) diff --git a/src/mame/igs/igs_m027.cpp b/src/mame/igs/igs_m027.cpp index def2669e40f..65a40c5e319 100644 --- a/src/mame/igs/igs_m027.cpp +++ b/src/mame/igs/igs_m027.cpp @@ -141,6 +141,7 @@ class igs_m027_state : public driver_device template void lamps_w(u8 data); void mahjong_output_w(u8 data); + void lhzb4_output_w(u8 data); void jking02_output_w(u8 data); void oceanpar_output_w(u8 data); @@ -154,8 +155,8 @@ class igs_m027_state : public driver_device void igs_mahjong_map(address_map &map) ATTR_COLD; void igs_mahjong_xor_map(address_map &map) ATTR_COLD; - void jking02_xor_map(address_map &map) ATTR_COLD; void lhdmg_xor_map(address_map &map) ATTR_COLD; + void jking02_xor_map(address_map &map) ATTR_COLD; void extradraw_map(address_map &map) ATTR_COLD; }; @@ -211,18 +212,18 @@ void igs_m027_state::igs_mahjong_xor_map(address_map &map) map(0x08000000, 0x0807ffff).r(FUNC(igs_m027_state::external_rom_r)); // Game ROM } -void igs_m027_state::jking02_xor_map(address_map &map) +void igs_m027_state::lhdmg_xor_map(address_map &map) { igs_mahjong_xor_map(map); - map(0x4000000c, 0x4000000f).portr("PLAYER"); + map(0x4000000c, 0x4000000f).r(FUNC(igs_m027_state::lhdmg_unk2_r)); } -void igs_m027_state::lhdmg_xor_map(address_map &map) +void igs_m027_state::jking02_xor_map(address_map &map) { igs_mahjong_xor_map(map); - map(0x4000000c, 0x4000000f).r(FUNC(igs_m027_state::lhdmg_unk2_r)); + map(0x4000000c, 0x4000000f).portr("PLAYER"); } void igs_m027_state::extradraw_map(address_map &map) @@ -322,22 +323,25 @@ INPUT_PORTS_START( base ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) INPUT_PORTS_END -INPUT_PORTS_START( mahjong ) - PORT_INCLUDE(igs_mahjong_matrix) - +INPUT_PORTS_START( mahjong_test ) PORT_START("TEST") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_TILT ) // 哈巴 - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MEMORY_RESET ) PORT_NAME("Clear") // 清除 - PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 查帐 - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) // TODO: default assignment clashes with mahjong I + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_TILT ) PORT_NAME("Hopper Switch") // 哈巴 + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MEMORY_RESET ) PORT_NAME("Clear") // 清除 + PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW ) // 测试 + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 查帐 + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) // 投币 + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) // 退币 TODO: default assignment clashes with mahjong I PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) INPUT_PORTS_END -INPUT_PORTS_START( mahjong_joy ) - PORT_INCLUDE(mahjong) +INPUT_PORTS_START( mahjong_kbd ) + PORT_INCLUDE(mahjong_test) + PORT_INCLUDE(igs_mahjong_matrix) +INPUT_PORTS_END + +INPUT_PORTS_START( mahjong_kbd_joy ) + PORT_INCLUDE(mahjong_kbd) PORT_MODIFY("TEST") PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) @@ -388,6 +392,56 @@ INPUT_PORTS_START( three_reel ) PORT_BIT( 0xfffe0000, IP_ACTIVE_LOW, IPT_UNKNOWN ) INPUT_PORTS_END +INPUT_PORTS_START( slqz3_dip_switches ) + PORT_START("DSW1") + PORT_DIPNAME( 0x03, 0x03, DEF_STR(Coin_A) ) PORT_DIPLOCATION("SW1:1,2") // 投币比率 + PORT_DIPSETTING( 0x03, DEF_STR(1C_1C) ) + PORT_DIPSETTING( 0x02, DEF_STR(1C_2C) ) + PORT_DIPSETTING( 0x01, DEF_STR(1C_3C) ) + PORT_DIPSETTING( 0x00, DEF_STR(1C_5C) ) + PORT_DIPNAME( 0x0c, 0x0c, "Key-In Rate" ) PORT_DIPLOCATION("SW1:3,4") // 开分比率 + PORT_DIPSETTING( 0x0c, "10" ) + PORT_DIPSETTING( 0x08, "20" ) + PORT_DIPSETTING( 0x04, "50" ) + PORT_DIPSETTING( 0x00, "100" ) + PORT_DIPNAME( 0x10, 0x10, "Credit Limit" ) PORT_DIPLOCATION("SW1:5") // 进分上限 + PORT_DIPSETTING( 0x10, "1000" ) + PORT_DIPSETTING( 0x00, "2000" ) + PORT_DIPNAME( 0x20, 0x20, "Credit Mode" ) PORT_DIPLOCATION("SW1:6") // 进分方式 (sets coin input function) + PORT_DIPSETTING( 0x20, "Coin Acceptor" ) // 投币 (uses coin A rate) + PORT_DIPSETTING( 0x00, "Key-In" ) // 开分 (uses key-in rate) + PORT_DIPNAME( 0x40, 0x40, "Payout Mode" ) PORT_DIPLOCATION("SW1:7") // 退分方式 + PORT_DIPSETTING( 0x40, "Return Coins" ) // 退币 (uses hopper to pay out credits) + PORT_DIPSETTING( 0x00, "Key-Out" ) // 洗分 (just clears credits) + PORT_DIPNAME( 0x80, 0x80, DEF_STR(Demo_Sounds) ) PORT_DIPLOCATION("SW1:8") // 示范音乐 + PORT_DIPSETTING( 0x00, DEF_STR(Off) ) // 无 + PORT_DIPSETTING( 0x80, DEF_STR(On) ) // 有 + + PORT_START("DSW2") + PORT_DIPNAME( 0x03, 0x03, "Double Up Jackpot" ) PORT_DIPLOCATION("SW2:1,2") // 比倍爆机 + PORT_DIPSETTING( 0x03, "500" ) + PORT_DIPSETTING( 0x02, "1000" ) + PORT_DIPSETTING( 0x01, "1500" ) + PORT_DIPSETTING( 0x00, "2000" ) + PORT_DIPNAME( 0x0c, 0x0c, "Minimum Bet" ) PORT_DIPLOCATION("SW2:3,4") // 最小押注 (all settings show 1 in service mode and function identically) + PORT_DIPSETTING( 0x0c, "1" ) + PORT_DIPSETTING( 0x08, "1" ) + PORT_DIPSETTING( 0x04, "1" ) + PORT_DIPSETTING( 0x00, "1" ) + PORT_DIPNAME( 0x10, 0x10, "Double Up Game" ) PORT_DIPLOCATION("SW2:5") // 比倍游戏 + PORT_DIPSETTING( 0x00, DEF_STR(Off) ) // 无 + PORT_DIPSETTING( 0x10, DEF_STR(On) ) // 有 + PORT_DIPNAME( 0x20, 0x20, "Double Up/Continue Play" ) PORT_DIPLOCATION("SW2:6") // 比倍续玩 + PORT_DIPSETTING( 0x20, "Double Up" ) // 比倍 + PORT_DIPSETTING( 0x00, "Continue Play" ) // 续玩 + PORT_DIPNAME( 0x40, 0x40, "Number Type" ) PORT_DIPLOCATION("SW2:7") // 数字型态 (affects credit and bet display) + PORT_DIPSETTING( 0x40, "Numbers" ) // 数字 (text and digits) + PORT_DIPSETTING( 0x00, "Blocks" ) // 方块 (pigs for credit, apples for bet, mahjong tong tiles for numbers) + PORT_DIPNAME( 0x80, 0x80, "Hidden Function" ) PORT_DIPLOCATION("SW2:8") // 隐分功能 (hides credits and bets, game plays normally) + PORT_DIPSETTING( 0x80, DEF_STR(Off) ) // 无 + PORT_DIPSETTING( 0x00, DEF_STR(On) ) // 有 +INPUT_PORTS_END + INPUT_PORTS_START( jking02 ) PORT_START("DSW1") PORT_DIPNAME( 0x1f, 0x1f, "ID Number") PORT_DIPLOCATION("SW1:1,2,3,4,5") @@ -517,6 +571,26 @@ INPUT_PORTS_START( jking02 ) PORT_BIT( 0xfff00000, IP_ACTIVE_LOW, IPT_UNKNOWN ) INPUT_PORTS_END +INPUT_PORTS_START( slqz3 ) + PORT_INCLUDE(mahjong_test) + PORT_INCLUDE(slqz3_dip_switches) + + PORT_MODIFY("TEST") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", hopper_device, line_r) // 哈巴 + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) // 功能 + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // 押注 + + PORT_START("JOY") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) // 开始 + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) // 上 + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) // 下 + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) // 左 + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) // 右 + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) // 摸/舍 +INPUT_PORTS_END + INPUT_PORTS_START( qlgs ) PORT_INCLUDE(base) @@ -527,58 +601,11 @@ INPUT_PORTS_START( qlgs ) INPUT_PORTS_END INPUT_PORTS_START( lhdmg ) - PORT_INCLUDE(mahjong) + PORT_INCLUDE(mahjong_kbd) + PORT_INCLUDE(slqz3_dip_switches) PORT_MODIFY("TEST") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", hopper_device, line_r) // 哈巴 - - PORT_START("DSW1") - PORT_DIPNAME( 0x03, 0x03, DEF_STR(Coin_A) ) PORT_DIPLOCATION("SW1:1,2") // 投币比率 - PORT_DIPSETTING( 0x03, DEF_STR(1C_1C) ) - PORT_DIPSETTING( 0x02, DEF_STR(1C_2C) ) - PORT_DIPSETTING( 0x01, DEF_STR(1C_3C) ) - PORT_DIPSETTING( 0x00, DEF_STR(1C_5C) ) - PORT_DIPNAME( 0x0c, 0x0c, "Key-In Rate" ) PORT_DIPLOCATION("SW1:3,4") // 开分比率 - PORT_DIPSETTING( 0x0c, "10" ) - PORT_DIPSETTING( 0x08, "20" ) - PORT_DIPSETTING( 0x04, "50" ) - PORT_DIPSETTING( 0x00, "100" ) - PORT_DIPNAME( 0x10, 0x10, "Credit Limit" ) PORT_DIPLOCATION("SW1:5") // 进分上限 - PORT_DIPSETTING( 0x10, "1000" ) - PORT_DIPSETTING( 0x00, "2000" ) - PORT_DIPNAME( 0x20, 0x20, "Credit Mode" ) PORT_DIPLOCATION("SW1:6") // 进分上方式 (sets coin input function) - PORT_DIPSETTING( 0x20, "Coin Acceptor" ) // 投币 (uses coin A rate) - PORT_DIPSETTING( 0x00, "Key-In" ) // 开分 (uses key-in rate) - PORT_DIPNAME( 0x40, 0x40, "Payout Mode" ) PORT_DIPLOCATION("SW1:7") // 退分上方式 - PORT_DIPSETTING( 0x40, "Return Coins" ) // 退币 (uses hopper to pay out credits) - PORT_DIPSETTING( 0x00, "Key-Out" ) // 洗分 (just clears credits) - PORT_DIPNAME( 0x80, 0x80, DEF_STR(Demo_Sounds) ) PORT_DIPLOCATION("SW1:8") // 示范音乐 - PORT_DIPSETTING( 0x00, DEF_STR(Off) ) // 无 - PORT_DIPSETTING( 0x80, DEF_STR(On) ) // 有 - - PORT_START("DSW2") - PORT_DIPNAME( 0x03, 0x03, "Double Up Jackpot" ) PORT_DIPLOCATION("SW2:1,2") // 比倍爆机 - PORT_DIPSETTING( 0x03, "500" ) - PORT_DIPSETTING( 0x02, "1000" ) - PORT_DIPSETTING( 0x01, "1500" ) - PORT_DIPSETTING( 0x00, "2000" ) - PORT_DIPNAME( 0x0c, 0x0c, "Minimum Bet" ) PORT_DIPLOCATION("SW2:3,4") // 最小押注 (all settings show 1 in service mode and function identically) - PORT_DIPSETTING( 0x0c, "1" ) - PORT_DIPSETTING( 0x08, "1" ) - PORT_DIPSETTING( 0x04, "1" ) - PORT_DIPSETTING( 0x00, "1" ) - PORT_DIPNAME( 0x10, 0x10, "Double Up Game" ) PORT_DIPLOCATION("SW2:5") // 比倍游戏 - PORT_DIPSETTING( 0x00, DEF_STR(Off) ) // 无 - PORT_DIPSETTING( 0x10, DEF_STR(On) ) // 有 - PORT_DIPNAME( 0x20, 0x20, "Double Up/Continue Play" ) PORT_DIPLOCATION("SW2:6") // 比倍续玩 - PORT_DIPSETTING( 0x20, "Double Up" ) // 比倍 - PORT_DIPSETTING( 0x00, "Continue Play" ) // 续玩 - PORT_DIPNAME( 0x40, 0x40, "Number Type" ) PORT_DIPLOCATION("SW2:7") // 数字型态 (affects credit and bet display) - PORT_DIPSETTING( 0x40, "Numbers" ) // 数字 (text and digits) - PORT_DIPSETTING( 0x00, "Blocks" ) // 方块 (pigs for credit, apples for bet, mahjong tong tiles for numbers) - PORT_DIPNAME( 0x80, 0x80, "Hidden Function" ) PORT_DIPLOCATION("SW2:8") // 隐分功能 (hides credits and bets, game plays normally) - PORT_DIPSETTING( 0x80, DEF_STR(Off) ) // 无 - PORT_DIPSETTING( 0x00, DEF_STR(On) ) // 有 INPUT_PORTS_END INPUT_PORTS_START( lhzb3 ) @@ -592,29 +619,46 @@ INPUT_PORTS_START( lhzb3 ) INPUT_PORTS_END INPUT_PORTS_START( lhzb4 ) - // TODO: this is very preliminary, mahjong inputs aren't hooked up + // TODO: this is very preliminary, mahjong keyboard inputs aren't hooked up - PORT_INCLUDE(mahjong) - - PORT_MODIFY("TEST") - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_START("TEST") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) // 下 + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x00 ) + PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW ) // 测试 + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 查帐 + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) // 投币 + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) // 上 + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) // 左 + PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x00 ) PORT_START("JOY") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("HP") // TODO: what is this? - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) // S3 + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) // S2 + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) // S1 + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) // 开始 + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) PORT_READ_LINE_DEVICE_MEMBER("hopper", hopper_device, line_r) // HP + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) // 右 + PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x00 ) + + PORT_START("PLAYER") + PORT_BIT( 0x000001ff, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x01 ) + PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CONDITION("DSW1", 0x01, EQUALS, 0x00 ) PORT_READ_LINE_DEVICE_MEMBER("hopper", hopper_device, line_r) // HP + PORT_BIT( 0x00000400, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x00000800, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) // 开分 + PORT_BIT( 0x0007f000, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) // 退币 + PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) // 洗分 + PORT_BIT( 0xffe00000, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_START("DSW1") PORT_DIPNAME( 0x01, 0x01, "Control Panel" ) PORT_DIPLOCATION("SW1:1") PORT_DIPSETTING( 0x01, "JAMMA" ) - PORT_DIPSETTING( 0x01, "Keyboard" ) + PORT_DIPSETTING( 0x00, "Keyboard" ) PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SW1:2" ) // remaining DIP switches not shown in test mode PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SW1:3" ) PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "SW1:4" ) @@ -645,7 +689,7 @@ INPUT_PORTS_START( lhzb4 ) INPUT_PORTS_END INPUT_PORTS_START( lthy ) - PORT_INCLUDE(mahjong_joy) + PORT_INCLUDE(mahjong_kbd_joy) PORT_MODIFY("TEST") PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) @@ -708,7 +752,7 @@ INPUT_PORTS_START( lthy ) INPUT_PORTS_END INPUT_PORTS_START( zhongguo ) - PORT_INCLUDE(mahjong_joy) + PORT_INCLUDE(mahjong_kbd_joy) PORT_MODIFY("TEST") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", hopper_device, line_r) // 哈巴 @@ -764,7 +808,7 @@ INPUT_PORTS_START( zhongguo ) INPUT_PORTS_END INPUT_PORTS_START( mgzz ) - PORT_INCLUDE(mahjong_joy) + PORT_INCLUDE(mahjong_kbd_joy) // TODO: missing HP input shown in test mode for joystick mode @@ -817,14 +861,14 @@ INPUT_PORTS_START( mgzz ) INPUT_PORTS_END INPUT_PORTS_START( mgzza ) - PORT_INCLUDE( mgzz ) + PORT_INCLUDE(mgzz) PORT_MODIFY("DSW2") PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SW2:3" ) // not shown in test mode INPUT_PORTS_END INPUT_PORTS_START( oceanpara ) - PORT_INCLUDE( three_reel ) + PORT_INCLUDE(three_reel) PORT_START("DSW1") PORT_DIPNAME( 0x01, 0x01, DEF_STR(Demo_Sounds) ) PORT_DIPLOCATION("SW1:1") @@ -875,7 +919,7 @@ INPUT_PORTS_START( oceanpara ) INPUT_PORTS_END INPUT_PORTS_START( oceanpar ) - PORT_INCLUDE( oceanpara ) + PORT_INCLUDE(oceanpara) PORT_MODIFY("DSW2") PORT_DIPNAME( 0x06, 0x06, "Score Box" ) PORT_DIPLOCATION("SW2:2,3") @@ -889,7 +933,7 @@ INPUT_PORTS_START( oceanpar ) INPUT_PORTS_END INPUT_PORTS_START( fruitpara ) - PORT_INCLUDE( oceanpara ) + PORT_INCLUDE(oceanpara) PORT_MODIFY("DSW2") PORT_DIPNAME( 0x02, 0x02, "Score Box" ) PORT_DIPLOCATION("SW2:2") @@ -1068,11 +1112,17 @@ void igs_m027_state::mahjong_output_w(u8 data) m_hopper->motor_w(BIT(data, 2)); } +void igs_m027_state::lhzb4_output_w(u8 data) +{ + machine().bookkeeping().coin_counter_w(1, BIT(data, 6)); // one pulse per key-out + machine().bookkeeping().coin_counter_w(0, BIT(data, 7)); // one pulse per key-in accepted +} + void igs_m027_state::jking02_output_w(u8 data) { machine().bookkeeping().coin_counter_w(0, BIT(data, 0)); // one pulse per coin 1 accepted (36+10) - machine().bookkeeping().coin_counter_w(2, BIT(data, 1)); // one pulse per key-in accepted (36+10 - machine().bookkeeping().coin_counter_w(1, BIT(data, 3)); // one pulse per key-in accepted (36+10) + machine().bookkeeping().coin_counter_w(2, BIT(data, 1)); // one pulse per key-in accepted (36+10) + machine().bookkeeping().coin_counter_w(1, BIT(data, 3)); // one pulse per coin 2 accepted (36+10) machine().bookkeeping().coin_counter_w(3, BIT(data, 4)); // one pulse per key-out (36+10) machine().bookkeeping().coin_counter_w(4, BIT(data, 5)); // one pulse per coin accepted (28-pin) machine().bookkeeping().coin_counter_w(5, BIT(data, 6)); // one pulse per key-out (28-pin) @@ -1160,18 +1210,15 @@ void igs_m027_state::slqz3_xor(machine_config &config) { m027_xor(config); - // TODO: PPI port A = input, port B = input, port C = output -} - -void igs_m027_state::jking02_xor(machine_config &config) -{ - m027_xor(config); + m_ppi->in_pa_callback().set_ioport("TEST"); + m_ppi->in_pb_callback().set_ioport("JOY"); + m_ppi->out_pc_callback().set(FUNC(igs_m027_state::mahjong_output_w)); - m_maincpu->set_addrmap(AS_PROGRAM, &igs_m027_state::jking02_xor_map); + m_igs017_igs031->in_pa_callback().set_ioport("DSW1"); + m_igs017_igs031->in_pb_callback().set_ioport("DSW2"); + m_igs017_igs031->in_pc_callback().set_constant(0xff); - m_ppi->out_pa_callback().set(FUNC(igs_m027_state::lamps_w<8>)); - m_ppi->out_pb_callback().set(FUNC(igs_m027_state::jking02_output_w)); - m_ppi->out_pc_callback().set(FUNC(igs_m027_state::lamps_w<0>)); + HOPPER(config, m_hopper, attotime::from_msec(50)); } void igs_m027_state::lhdmg_xor(machine_config &config) @@ -1195,13 +1242,18 @@ void igs_m027_state::lhzb4_xor(machine_config &config) { m027_xor(config); + m_maincpu->set_addrmap(AS_PROGRAM, &igs_m027_state::jking02_xor_map); + //m_ppi->out_pa_callback().set(...); - //m_ppi->out_pb_callback().set(...); + m_ppi->out_pb_callback().set(FUNC(igs_m027_state::lhzb4_output_w)); m_ppi->out_pc_callback().set(FUNC(igs_m027_state::io_select_w<0>)); + m_ppi->out_pc_callback().append(m_hopper, FUNC(hopper_device::motor_w)).bit(7); m_igs017_igs031->in_pa_callback().set(NAME((&igs_m027_state::dsw_r<1, 0>))); m_igs017_igs031->in_pb_callback().set_ioport("TEST"); m_igs017_igs031->in_pc_callback().set_ioport("JOY"); + + HOPPER(config, m_hopper, attotime::from_msec(50)); } void igs_m027_state::lthy_xor(machine_config &config) @@ -1224,6 +1276,17 @@ void igs_m027_state::zhongguo_xor(machine_config &config) HOPPER(config, m_hopper, attotime::from_msec(50)); } +void igs_m027_state::jking02_xor(machine_config &config) +{ + m027_xor(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &igs_m027_state::jking02_xor_map); + + m_ppi->out_pa_callback().set(FUNC(igs_m027_state::lamps_w<8>)); + m_ppi->out_pb_callback().set(FUNC(igs_m027_state::jking02_output_w)); + m_ppi->out_pc_callback().set(FUNC(igs_m027_state::lamps_w<0>)); +} + void igs_m027_state::mgzz_xor(machine_config &config) { m027_xor(config); @@ -2343,7 +2406,7 @@ void igs_m027_state::init_lhdmg() ***************************************************************************/ // Complete dumps -GAME( 1999, slqz3, 0, slqz3_xor, base, igs_m027_state, init_slqz3, ROT0, "IGS", "Mahjong Shuang Long Qiang Zhu 3 (China, VS107C)", MACHINE_NOT_WORKING ) +GAME( 1999, slqz3, 0, slqz3_xor, slqz3, igs_m027_state, init_slqz3, ROT0, "IGS", "Mahjong Shuang Long Qiang Zhu 3 (China, VS107C)", MACHINE_NOT_WORKING ) // 双龙抢珠Ⅲ GAME( 1999, qlgs, 0, m027_xor, qlgs, igs_m027_state, init_qlgs, ROT0, "IGS", "Que Long Gao Shou", MACHINE_NOT_WORKING ) GAME( 1999, lhdmg, 0, lhdmg_xor, lhdmg, igs_m027_state, init_lhdmg, ROT0, "IGS", "Long Hu Da Manguan", MACHINE_NOT_WORKING ) // 龙虎大满贯 GAME( 1999, lhdmgp, lhdmg, lhdmg_xor, lhdmg, igs_m027_state, init_lhdmg, ROT0, "IGS", "Long Hu Da Manguan Plus", MACHINE_NOT_WORKING ) // 龙虎大满贯 diff --git a/src/mame/sony/smc777.cpp b/src/mame/sony/smc777.cpp index dd06ae9f80b..8d338056b5f 100644 --- a/src/mame/sony/smc777.cpp +++ b/src/mame/sony/smc777.cpp @@ -21,20 +21,20 @@ #include "emu.h" -#include "cpu/z80/z80.h" #include "cpu/mcs48/mcs48.h" +#include "cpu/z80/z80.h" #include "imagedev/floppy.h" #include "imagedev/snapquik.h" #include "machine/74259.h" #include "machine/timer.h" #include "machine/wd_fdc.h" -#include "softlist_dev.h" #include "sound/beep.h" #include "sound/sn76496.h" #include "video/mc6845.h" #include "emupal.h" #include "screen.h" +#include "softlist_dev.h" #include "speaker.h" diff --git a/src/mame/taito/taito_f2.cpp b/src/mame/taito/taito_f2.cpp index a71ee071162..69416419c91 100644 --- a/src/mame/taito/taito_f2.cpp +++ b/src/mame/taito/taito_f2.cpp @@ -5021,6 +5021,7 @@ ROM_START( qzquest ) /* Quiz Quest */ /* no Delta-T samples */ ROM_END +// Dual PCB version (main and sound program ROMs cannot be used on the single PCB version) ROM_START( pulirula ) ROM_REGION( 0xc0000, "maincpu", 0 ) /* 768k for 68000 code */ ROM_LOAD16_BYTE( "c98-12.rom", 0x00000, 0x40000, CRC(816d6cde) SHA1(cac583440cca9aa57373f4a6c9a68c5442a5258b) ) @@ -5073,6 +5074,7 @@ ROM_START( pulirulaj ) /* no Delta-T samples */ ROM_END +// Single PCB version (main and sound program ROMs cannot be used on the dual PCB version) ROM_START( pulirulaa ) // dumped from an original PCB without original ROM labels. The maincpu and audiocpu ROMs differ from the parent. ROM_REGION( 0xc0000, "maincpu", 0 ) /* 768k for 68000 code */ ROM_LOAD16_BYTE( "ic46.bin", 0x00000, 0x40000, CRC(584ae599) SHA1(c114442d93080aaf0641c1a9204569f0017af000) ) @@ -5618,7 +5620,7 @@ GAME( 1990, mjnquestb, mjnquest, mjnquest, mjnquest, taitof2_state, init_mjn GAME( 1990, footchmp, 0, footchmp, footchmp, taitof2_state, empty_init, ROT0, "Taito Corporation Japan", "Football Champ / Euro Football Champ (World)", MACHINE_SUPPORTS_SAVE ) // title depends on dipswitch GAME( 1990, htherou, footchmp, footchmp, htherou, taitof2_state, empty_init, ROT0, "Taito Corporation", "Hat Trick Hero (US)", MACHINE_SUPPORTS_SAVE ) // Single PCB -GAME( 1990, htheroj, footchmp, hthero, htheroj, taitof2_state, empty_init, ROT0, "Taito Corporation", "Hat Trick Hero (Japan)", MACHINE_SUPPORTS_SAVE ) // Double PCB +GAME( 1990, htheroj, footchmp, hthero, htheroj, taitof2_state, empty_init, ROT0, "Taito Corporation", "Hat Trick Hero (Japan)", MACHINE_SUPPORTS_SAVE ) // Dual PCB GAME( 1992, footchmpbl, footchmp, footchmpbl,footchmpbl, taitof2_state, empty_init, ROT0, "bootleg", "Football Champ / Euro Football Champ (World) (bootleg)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) // very different hw register etc. GAME( 1992, euroch92, 0, footchmp, footchmp, taitof2_state, empty_init, ROT0, "Taito Corporation Japan", "Euro Champ '92 (World)", MACHINE_SUPPORTS_SAVE ) @@ -5636,8 +5638,8 @@ GAME( 1991, solfigtr, 0, solfigtr, solfigtr, taitof2_state, empty_in GAME( 1991, qzquest, 0, qzquest , qzquest, taitof2_state, empty_init, ROT0, "Taito Corporation", "Quiz Quest - Hime to Yuusha no Monogatari (Japan)", MACHINE_SUPPORTS_SAVE ) -GAME( 1991, pulirula, 0, pulirula, pulirula, taitof2_state, empty_init, ROT0, "Taito Corporation Japan", "PuLiRuLa (World)", MACHINE_SUPPORTS_SAVE ) -GAME( 1991, pulirulaa, pulirula, pulirula, pulirulaj, taitof2_state, empty_init, ROT0, "Taito Corporation", "PuLiRuLa (World, earlier?)", MACHINE_SUPPORTS_SAVE ) +GAME( 1991, pulirula, 0, pulirula, pulirula, taitof2_state, empty_init, ROT0, "Taito Corporation Japan", "PuLiRuLa (World, dual PCB)", MACHINE_SUPPORTS_SAVE ) +GAME( 1991, pulirulaa, pulirula, pulirula, pulirulaj, taitof2_state, empty_init, ROT0, "Taito Corporation", "PuLiRuLa (World, single PCB)", MACHINE_SUPPORTS_SAVE ) GAME( 1991, pulirulaj, pulirula, pulirula, pulirulaj, taitof2_state, empty_init, ROT0, "Taito Corporation", "PuLiRuLa (Japan)", MACHINE_SUPPORTS_SAVE ) GAME( 1991, metalb, 0, metalb, metalb, taitof2_state, empty_init, ROT0, "Taito Corporation Japan", "Metal Black (World)", MACHINE_SUPPORTS_SAVE )