// license:BSD-3-Clause // copyright-holders:Aaron Giles /*************************************************************************** mconfig.cpp Machine configuration macros and functions. ***************************************************************************/ #include "emu.h" #include "emuopts.h" #include "screen.h" #include #include #include //************************************************************************** // MACHINE CONFIGURATIONS //************************************************************************** class machine_config::current_device_stack { public: current_device_stack(current_device_stack const &) = delete; current_device_stack(machine_config &host) : m_host(host), m_device(host.m_current_device) { m_host.m_current_device = nullptr; } ~current_device_stack() { assert(!m_host.m_current_device); m_host.m_current_device = m_device; } private: machine_config &m_host; device_t *const m_device; }; //------------------------------------------------- // machine_config - constructor //------------------------------------------------- machine_config::machine_config(const game_driver &gamedrv, emu_options &options) : m_gamedrv(gamedrv) , m_options(options) , m_root_device() , m_default_layouts([] (char const *a, char const *b) { return 0 > std::strcmp(a, b); }) , m_current_device(nullptr) , m_maximum_quantums([] (char const *a, char const *b) { return 0 > std::strcmp(a, b); }) , m_perfect_quantum_device(nullptr, "") { // add the root device device_add("root", gamedrv.type, 0); // intialize slot devices - make sure that any required devices have been allocated for (device_slot_interface &slot : slot_interface_enumerator(root_device())) { device_t &owner = slot.device(); const char *slot_option_name = owner.tag() + 1; // figure out which device goes into this slot bool const has_option = options.has_slot_option(slot_option_name); const char *selval; bool is_default; if (!has_option) { // The only time we should be getting here is when emuopts.cpp is invoking // us to evaluate slot/image options, and the internal state of emuopts.cpp has // not caught up yet selval = slot.default_option(); is_default = true; } else { const slot_option &opt = options.slot_option(slot_option_name); selval = opt.value().c_str(); is_default = !opt.specified(); } if (selval && *selval) { // TODO: make this thing more self-contained so it can apply itself - shouldn't need to know all this here device_slot_interface::slot_option const *option = slot.option(selval); if (option && (is_default || option->selectable())) { // create the device token const tok(begin_configuration(owner)); device_t *const new_dev = device_add(option->name(), option->devtype(), option->clock()); slot.set_card_device(new_dev); char const *const default_bios = option->default_bios(); if (default_bios != nullptr) new_dev->set_default_bios_tag(default_bios); auto additions = option->machine_config(); if (additions) additions(new_dev); input_device_default const *const input_device_defaults = option->input_device_defaults(); if (input_device_defaults) new_dev->set_input_default(input_device_defaults); } else throw emu_fatalerror("Unknown slot option '%s' in slot '%s'", selval, owner.tag()+1); } } // then notify all devices that their configuration is complete for (device_t &device : device_enumerator(root_device())) if (!device.configured()) device.config_complete(); } //------------------------------------------------- // ~machine_config - destructor //------------------------------------------------- machine_config::~machine_config() { } //------------------------------------------------- // maximum_quantum - get smallest configured // maximum quantum //------------------------------------------------- attotime machine_config::maximum_quantum(attotime const &default_quantum) const { return std::accumulate( m_maximum_quantums.begin(), m_maximum_quantums.end(), default_quantum, [] (attotime const &lhs, maximum_quantum_map::value_type const &rhs) { return (std::min)(lhs, rhs.second); }); } //------------------------------------------------- // perfect_quantum_device - get device configured // for perfect quantum if any //------------------------------------------------- device_execute_interface *machine_config::perfect_quantum_device() const { if (!m_perfect_quantum_device.first) return nullptr; device_t *const found(m_perfect_quantum_device.first->subdevice(m_perfect_quantum_device.second)); if (!found) { throw emu_fatalerror( "Device %s relative to %s specified for perfect interleave is not present!\n", m_perfect_quantum_device.second, m_perfect_quantum_device.first->tag()); } device_execute_interface *result; if (!found->interface(result)) { throw emu_fatalerror("Device %s (%s) specified for perfect interleave does not implement device_execute_interface!\n", found->tag(), found->shortname()); } return result; } //------------------------------------------------- // set_default_layout - set layout for current // device //------------------------------------------------- void machine_config::set_default_layout(internal_layout const &layout) { std::pair const ins(m_default_layouts.emplace(current_device().tag(), &layout)); if (!ins.second) ins.first->second = &layout; } //------------------------------------------------- // set_maximum_quantum - set maximum scheduling // quantum for current device device //------------------------------------------------- void machine_config::set_maximum_quantum(attotime const &quantum) { std::pair const ins(m_maximum_quantums.emplace(current_device().tag(), quantum)); if (!ins.second) ins.first->second = quantum; } //------------------------------------------------- // device_add - configuration helper to add a // new device //------------------------------------------------- device_t *machine_config::device_add(const char *tag, device_type type, u32 clock) { std::pair const owner(resolve_owner(tag)); return &add_device(type.create(*this, owner.first, owner.second, clock), owner.second); } //------------------------------------------------- // device_replace - configuration helper to // replace one device with a new device //------------------------------------------------- device_t *machine_config::device_replace(const char *tag, device_type type, u32 clock) { std::tuple const existing(prepare_replace(tag)); std::unique_ptr device(type.create(*this, std::get<0>(existing), std::get<1>(existing), clock)); return &replace_device(std::move(device), *std::get<1>(existing), std::get<2>(existing)); } //------------------------------------------------- // device_remove - configuration helper to // remove a device //------------------------------------------------- device_t *machine_config::device_remove(const char *tag) { // find the original device by relative tag (must exist) assert(m_current_device); device_t *const device = m_current_device->subdevice(tag); if (device == nullptr) { osd_printf_warning("Warning: attempting to remove non-existent device '%s'\n", tag); } else { // make sure we have the old device's actual owner device_t *const owner = device->owner(); assert(owner); // remove references to the old device remove_references(*device); // let the device's owner do the work owner->subdevices().remove(*device); } return nullptr; } //------------------------------------------------- // resolve_owner - get the actual owner and base // tag given tag relative to current context //------------------------------------------------- std::pair machine_config::resolve_owner(const char *tag) const { assert(bool(m_current_device) == bool(m_root_device)); char const *const orig_tag = tag; device_t *owner(m_current_device); // if the device path is absolute, start from the root if (tag[0] == ':') { tag++; owner = m_root_device.get(); } // go down the path until we're done with it while (strchr(tag, ':')) { const char *next = strchr(tag, ':'); assert(next != tag);
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
/**********************************************************************

    Sega Saturn Joypad emulation

**********************************************************************/

#include "emu.h"
#include "joy.h"

//**************************************************************************
//  DEVICE DEFINITIONS
//**************************************************************************

DEFINE_DEVICE_TYPE(SATURN_JOY, saturn_joy_device, "saturn_joy", "Sega Saturn Joypad")


static INPUT_PORTS_START( saturn_joy )
	PORT_START("JOY")
	PORT_BIT(0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT)
	PORT_BIT(0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT)
	PORT_BIT(0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN)
	PORT_BIT(0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP)
	PORT_BIT(0x0800, IP_ACTIVE_LOW, IPT_START)
	PORT_BIT(0x0400, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("A")
	PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("C")
	PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("B")
	PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_BUTTON8) PORT_NAME("R")
	PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("X")
	PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("Y")
	PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME("Z")
	PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_BUTTON7) PORT_NAME("L")
	// Note: unused bits must stay high, Bug 2 relies on this.
	PORT_BIT(0x0007, IP_ACTIVE_LOW, IPT_UNUSED)
INPUT_PORTS_END


//-------------------------------------------------
//  input_ports - device-specific input ports
//-------------------------------------------------

ioport_constructor saturn_joy_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( saturn_joy );
}


//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  saturn_joy_device - constructor
//-------------------------------------------------

saturn_joy_device::saturn_joy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, SATURN_JOY, tag, owner, clock),
	device_saturn_control_port_interface(mconfig, *this),
	m_joy(*this, "JOY")
{
	m_ctrl_id = 0x02;
}


//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void saturn_joy_device::device_start()
{
}


//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void saturn_joy_device::device_reset()
{
}


//-------------------------------------------------
//  read_ctrl
//-------------------------------------------------

uint8_t saturn_joy_device::read_ctrl(uint8_t offset)
{
	uint8_t res = 0;
	switch (offset)
	{
		case 0:
		default:
			res = m_joy->read() >> 8;
			break;
		case 1:
			res = m_joy->read() & 0xff;
			break;
	}
	return res;
}

//-------------------------------------------------
//  read_direct
//-------------------------------------------------

uint16_t saturn_joy_device::read_direct()
{
	return m_joy->read();
}