mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
slot: add preliminary support for hotswapping rom cartridge
This commit is contained in:
parent
9de981104f
commit
8f49d7d62e
@ -95,6 +95,19 @@ void device_generic_cart_interface::rom_alloc(u32 size, int width, endianness_t
|
||||
m_rom_size = size;
|
||||
}
|
||||
|
||||
void device_generic_cart_interface::rom_free(char const *tag)
|
||||
{
|
||||
if (m_rom)
|
||||
{
|
||||
std::string fulltag(tag);
|
||||
fulltag.append(GENERIC_ROM_REGION_TAG);
|
||||
device().logerror("Deallocating ROM region with tag '%s'\n", fulltag);
|
||||
device().machine().memory().region_free(fulltag.c_str());
|
||||
m_rom = nullptr;
|
||||
m_rom_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void device_generic_cart_interface::ram_alloc(u32 size)
|
||||
{
|
||||
if (!m_ram.empty())
|
||||
@ -123,6 +136,7 @@ generic_slot_device::generic_slot_device(machine_config const &mconfig, device_t
|
||||
m_default_card("rom"),
|
||||
m_extensions("bin"),
|
||||
m_must_be_loaded(false),
|
||||
m_reset_on_load(true),
|
||||
m_width(GENERIC_ROM8_WIDTH),
|
||||
m_endianness(ENDIANNESS_LITTLE),
|
||||
m_cart(nullptr),
|
||||
@ -186,6 +200,8 @@ void generic_slot_device::call_unload()
|
||||
{
|
||||
if (!m_device_image_unload.isnull())
|
||||
return m_device_image_unload(*this);
|
||||
else if (m_cart)
|
||||
rom_free();
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
virtual void write_ram(offs_t offset, u8 data);
|
||||
|
||||
virtual void rom_alloc(u32 size, int width, endianness_t end, char const *tag);
|
||||
virtual void rom_free(char const *tag);
|
||||
virtual void ram_alloc(u32 size);
|
||||
|
||||
u8 *get_rom_base() { return m_rom; }
|
||||
@ -114,7 +115,8 @@ public:
|
||||
void set_interface(char const *interface) { m_interface = interface; }
|
||||
void set_default_card(char const *def) { m_default_card = def; }
|
||||
void set_extensions(char const *exts) { m_extensions = exts; }
|
||||
void set_must_be_loaded(bool mandatory) { m_must_be_loaded = mandatory; }
|
||||
void set_must_be_loaded(bool mandatory) { m_must_be_loaded = mandatory; } // default false
|
||||
void set_reset_on_load(bool reset) { m_reset_on_load = reset; } // default true
|
||||
void set_width(int width) { m_width = width; }
|
||||
void set_endian(endianness_t end) { m_endianness = end; }
|
||||
|
||||
@ -126,7 +128,7 @@ public:
|
||||
virtual bool is_writeable() const noexcept override { return false; }
|
||||
virtual bool is_creatable() const noexcept override { return false; }
|
||||
virtual bool must_be_loaded() const noexcept override { return m_must_be_loaded; }
|
||||
virtual bool is_reset_on_load() const noexcept override { return true; }
|
||||
virtual bool is_reset_on_load() const noexcept override { return m_reset_on_load; }
|
||||
virtual char const *image_interface() const noexcept override { return m_interface; }
|
||||
virtual char const *file_extensions() const noexcept override { return m_extensions; }
|
||||
|
||||
@ -145,7 +147,8 @@ public:
|
||||
virtual void write_ram(offs_t offset, u8 data);
|
||||
|
||||
virtual void rom_alloc(u32 size, int width, endianness_t end) { if (m_cart) m_cart->rom_alloc(size, width, end, tag()); }
|
||||
virtual void ram_alloc(u32 size) { if (m_cart) m_cart->ram_alloc(size); }
|
||||
virtual void rom_free() { if (m_cart) m_cart->rom_free(tag()); }
|
||||
virtual void ram_alloc(u32 size) { if (m_cart) m_cart->ram_alloc(size); }
|
||||
|
||||
u8* get_rom_base()
|
||||
{
|
||||
@ -182,6 +185,7 @@ protected:
|
||||
char const *m_default_card;
|
||||
char const *m_extensions;
|
||||
bool m_must_be_loaded;
|
||||
bool m_reset_on_load;
|
||||
int m_width;
|
||||
endianness_t m_endianness;
|
||||
device_generic_cart_interface *m_cart;
|
||||
|
@ -113,6 +113,8 @@ void menu_software_parts::populate(float &customtop, float &custombottom)
|
||||
item_append(m_info->shortname(), menu_part_name, 0, &entry);
|
||||
}
|
||||
}
|
||||
|
||||
item_append(menu_item_type::SEPARATOR);
|
||||
}
|
||||
|
||||
|
||||
@ -234,6 +236,8 @@ void menu_software_list::populate(float &customtop, float &custombottom)
|
||||
// append all of the menu entries
|
||||
for (auto &entry : m_entrylist)
|
||||
item_append(entry.short_name, entry.long_name, 0, &entry);
|
||||
|
||||
item_append(menu_item_type::SEPARATOR);
|
||||
}
|
||||
|
||||
|
||||
@ -395,6 +399,8 @@ void menu_software::populate(float &customtop, float &custombottom)
|
||||
}
|
||||
have_compatible = true;
|
||||
}
|
||||
|
||||
item_append(menu_item_type::SEPARATOR);
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,8 +25,9 @@ Known chess cartridges (*denotes not dumped):
|
||||
- Steinitz Edition-4 - Master Chess
|
||||
- *Monitor Edition - Master Kriegspiel
|
||||
|
||||
The opening/endgame cartridges are meant to be ejected/inserted while
|
||||
playing (put the power switch in "MEM" first).
|
||||
The opening/endgame cartridges are meant to be ejected/inserted while playing:
|
||||
switch power switch to MEM, swap cartridge, switch power switch back to ON.
|
||||
In other words, don't power cycle the machine (or MAME).
|
||||
|
||||
Other games:
|
||||
- *Borchek Edition - Master Checkers
|
||||
@ -50,7 +51,6 @@ TODO:
|
||||
#include "bus/generic/carts.h"
|
||||
#include "cpu/m6502/m6502.h"
|
||||
#include "machine/6522via.h"
|
||||
#include "machine/nvram.h"
|
||||
#include "machine/timer.h"
|
||||
#include "sound/dac.h"
|
||||
#include "video/pwm.h"
|
||||
@ -105,7 +105,8 @@ private:
|
||||
void update_display();
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(ca1_off) { m_via->write_ca1(0); }
|
||||
|
||||
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cartridge);
|
||||
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(load_cart);
|
||||
DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER(unload_cart);
|
||||
u8 cartridge_r(offs_t offset);
|
||||
|
||||
void select_w(u8 data);
|
||||
@ -165,7 +166,7 @@ void ggm_state::update_reset(ioport_value state)
|
||||
|
||||
// cartridge
|
||||
|
||||
DEVICE_IMAGE_LOAD_MEMBER(ggm_state::cartridge)
|
||||
DEVICE_IMAGE_LOAD_MEMBER(ggm_state::load_cart)
|
||||
{
|
||||
u32 size = m_cart->common_get_size("rom");
|
||||
m_cart_mask = ((1 << (31 - count_leading_zeros(size))) - 1) & 0xffff;
|
||||
@ -184,6 +185,18 @@ DEVICE_IMAGE_LOAD_MEMBER(ggm_state::cartridge)
|
||||
return image_init_result::PASS;
|
||||
}
|
||||
|
||||
DEVICE_IMAGE_UNLOAD_MEMBER(ggm_state::unload_cart)
|
||||
{
|
||||
m_cart->rom_free();
|
||||
|
||||
// unmap extra ram
|
||||
if (image.get_feature("ram"))
|
||||
{
|
||||
m_maincpu->space(AS_PROGRAM).nop_readwrite(0x0800, 0x0fff);
|
||||
memset(m_extram, 0, m_extram.bytes());
|
||||
}
|
||||
}
|
||||
|
||||
u8 ggm_state::cartridge_r(offs_t offset)
|
||||
{
|
||||
return m_cart->read_rom(offset & m_cart_mask);
|
||||
@ -255,7 +268,7 @@ void ggm_state::main_map(address_map &map)
|
||||
{
|
||||
// external slot has potential bus conflict with RAM/VIA
|
||||
map(0x0000, 0xffff).r(FUNC(ggm_state::cartridge_r));
|
||||
map(0x0000, 0x07ff).ram().share("nvram");
|
||||
map(0x0000, 0x07ff).ram();
|
||||
map(0x8000, 0x800f).m(m_via, FUNC(via6522_device::map));
|
||||
}
|
||||
|
||||
@ -430,8 +443,6 @@ void ggm_state::ggm(machine_config &config)
|
||||
m_via->cb2_handler().set(FUNC(ggm_state::shift_data_w));
|
||||
TIMER(config, m_ca1_off).configure_generic(FUNC(ggm_state::ca1_off));
|
||||
|
||||
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
|
||||
|
||||
/* video hardware */
|
||||
PWM_DISPLAY(config, m_display).set_size(8, 16);
|
||||
m_display->set_segmask(0xff, 0x3fff);
|
||||
@ -444,8 +455,10 @@ void ggm_state::ggm(machine_config &config)
|
||||
|
||||
/* cartridge */
|
||||
GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "ggm");
|
||||
m_cart->set_device_load(FUNC(ggm_state::cartridge));
|
||||
m_cart->set_device_load(FUNC(ggm_state::load_cart));
|
||||
m_cart->set_device_unload(FUNC(ggm_state::unload_cart));
|
||||
m_cart->set_must_be_loaded(true);
|
||||
m_cart->set_reset_on_load(false);
|
||||
|
||||
SOFTWARE_LIST(config, "cart_list").set_original("ggm");
|
||||
}
|
||||
|
@ -180,6 +180,7 @@ void chessmst_state::chessmst_io(address_map &map)
|
||||
|
||||
INPUT_CHANGED_MEMBER(chessmst_state::halt_button)
|
||||
{
|
||||
// halt button goes to PIO(0) ASTB pin
|
||||
m_pio[0]->strobe_a(newval);
|
||||
reset_button(field, param, oldval, newval);
|
||||
}
|
||||
@ -203,8 +204,8 @@ static INPUT_PORTS_START( chessmst )
|
||||
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("New Game / 0 / Pawn") PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(KEYCODE_N)
|
||||
|
||||
PORT_START("IN.1")
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Halt") PORT_CODE(KEYCODE_F2) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmst_state, halt_button, 0) // -> PIO(0) ASTB pin
|
||||
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F1) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmst_state, reset_button, 0) // -> Z80 RESET pin if HALT is pressed too
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Halt") PORT_CODE(KEYCODE_F2) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmst_state, halt_button, 0)
|
||||
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F1) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmst_state, reset_button, 0)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
|
@ -7,6 +7,9 @@ Chess-Master Diamond (G-5004-500), by VEB Mikroelektronik "Karl Marx" Erfurt
|
||||
The chess engine is a continuation of the older Chess-Master model. So it
|
||||
plays quite weak when compared with other chess computers from 1987.
|
||||
|
||||
PM10 and PM11 modules were included (not separate purchases). No other modules
|
||||
were released. The player is supposed to hotswap them with the [CH M] option.
|
||||
|
||||
Hardware notes:
|
||||
- UA880 Z80 @ 4MHz
|
||||
- 2*Z80 PIO
|
||||
@ -54,7 +57,8 @@ public:
|
||||
m_digits(*this, "digit%u", 0U)
|
||||
{ }
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(reset_button);
|
||||
DECLARE_INPUT_CHANGED_MEMBER(monitor_button);
|
||||
DECLARE_INPUT_CHANGED_MEMBER(view_button);
|
||||
|
||||
void chessmstdm(machine_config &config);
|
||||
|
||||
@ -75,6 +79,7 @@ private:
|
||||
void chessmstdm_mem(address_map &map);
|
||||
void chessmstdm_io(address_map &map);
|
||||
|
||||
u8 reset_r();
|
||||
void digits_w(u8 data);
|
||||
void pio1_port_a_w(u8 data);
|
||||
void pio1_port_b_w(u8 data);
|
||||
@ -118,6 +123,18 @@ void chessmstdm_state::machine_reset()
|
||||
I/O
|
||||
******************************************************************************/
|
||||
|
||||
u8 chessmstdm_state::reset_r()
|
||||
{
|
||||
// reading from 9cxx asserts a reset
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
||||
machine_reset();
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void chessmstdm_state::update_digits()
|
||||
{
|
||||
u16 digit_data = bitswap<16>(m_digit_data, 3,5,12,10,14,1,2,13,8,6,11,15,7,9,4,0);
|
||||
@ -200,6 +217,7 @@ void chessmstdm_state::chessmstdm_mem(address_map &map)
|
||||
map(0x0000, 0x3fff).rom();
|
||||
map(0x4000, 0x7fff).r("cartslot", FUNC(generic_slot_device::read_rom));
|
||||
map(0x8000, 0x8bff).ram();
|
||||
map(0x9c00, 0x9c00).mirror(0x0300).r(FUNC(chessmstdm_state::reset_r));
|
||||
}
|
||||
|
||||
void chessmstdm_state::chessmstdm_io(address_map &map)
|
||||
@ -209,7 +227,7 @@ void chessmstdm_state::chessmstdm_io(address_map &map)
|
||||
//map(0x00, 0x03).mirror(0x70) read/write to both PIOs, but not used by software
|
||||
map(0x04, 0x07).mirror(0x70).rw(m_pio[0], FUNC(z80pio_device::read), FUNC(z80pio_device::write));
|
||||
map(0x08, 0x0b).mirror(0x70).rw(m_pio[1], FUNC(z80pio_device::read), FUNC(z80pio_device::write));
|
||||
map(0x4c, 0x4c).mirror(0x03).w(FUNC(chessmstdm_state::digits_w));
|
||||
map(0x4c, 0x4c).mirror(0x33).w(FUNC(chessmstdm_state::digits_w));
|
||||
}
|
||||
|
||||
|
||||
@ -218,14 +236,20 @@ void chessmstdm_state::chessmstdm_io(address_map &map)
|
||||
Input Ports
|
||||
******************************************************************************/
|
||||
|
||||
INPUT_CHANGED_MEMBER(chessmstdm_state::reset_button)
|
||||
INPUT_CHANGED_MEMBER(chessmstdm_state::monitor_button)
|
||||
{
|
||||
// releasing monitor button clears reset
|
||||
if (!newval && oldval)
|
||||
m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
|
||||
|
||||
view_button(field, param, oldval, newval);
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(chessmstdm_state::view_button)
|
||||
{
|
||||
// pressing both monitor+view buttons buttons causes a reset
|
||||
const bool reset = (m_inputs[1]->read() & 0x03) == 0x03;
|
||||
m_maincpu->set_input_line(INPUT_LINE_RESET, reset ? ASSERT_LINE : CLEAR_LINE);
|
||||
|
||||
if (reset)
|
||||
machine_reset();
|
||||
if ((m_inputs[1]->read() & 0x03) == 0x03)
|
||||
reset_r();
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START( chessmstdm )
|
||||
@ -240,8 +264,8 @@ static INPUT_PORTS_START( chessmstdm )
|
||||
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD)
|
||||
|
||||
PORT_START("IN.1")
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Monitor") PORT_CODE(KEYCODE_F1) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmstdm_state, reset_button, 0)
|
||||
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("View") PORT_CODE(KEYCODE_F2) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmstdm_state, reset_button, 0)
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Monitor") PORT_CODE(KEYCODE_F1) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmstdm_state, monitor_button, 0)
|
||||
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("View") PORT_CODE(KEYCODE_F2) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmstdm_state, view_button, 0)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -296,7 +320,7 @@ void chessmstdm_state::chessmstdm(machine_config &config)
|
||||
BEEP(config, m_beeper, 1000).add_route(ALL_OUTPUTS, "speaker", 0.25);
|
||||
|
||||
// cartridge
|
||||
GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "chessmstdm_cart");
|
||||
GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "chessmstdm_cart").set_reset_on_load(false);
|
||||
SOFTWARE_LIST(config, "cart_list").set_original("chessmstdm");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user