From 85fd7f8c45794284c7423d917795e9c96e08decb Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Tue, 13 Dec 2022 08:00:03 +1100 Subject: -bus/sms_ctrl: Added raphnet DIY SMS/Mark III paddle. -cpu/avr8: Added minimal ADC support (in particular, ADC interrupts are not implemented). -sega/megadriv.cpp: Further broke up base Mega Drive class. * Created a light-weight base class with just the core functionality, used for "Genie" hardware (Puckman Pockimon). * Moved built-in controller emulation to a derived class so it isn't lurking underneath the consoles with pluggable controllers. * Moved the Sun Mixing Mega Drive bootlegs to their own source file - they're substantially different, not using the I/O blocks for input. -sega/sms.cpp: Untangled SG-1000 Mark III slightly. --- scripts/src/bus.lua | 2 + src/devices/bus/sms_ctrl/controllers.cpp | 3 + src/devices/bus/sms_ctrl/controllers.h | 1 + src/devices/bus/sms_ctrl/diypaddle.cpp | 227 ++++++++++++++++++++ src/devices/bus/sms_ctrl/diypaddle.h | 18 ++ src/devices/cpu/avr8/avr8.cpp | 183 +++++++++++++++- src/devices/cpu/avr8/avr8.h | 33 ++- src/mame/mame.lst | 6 +- src/mame/sega/hshavoc.cpp | 2 - src/mame/sega/megadriv.cpp | 211 ++++++++++-------- src/mame/sega/megadriv.h | 109 +++++++--- src/mame/sega/megadriv_acbl.cpp | 287 +------------------------ src/mame/sega/megadriv_acbl.h | 12 +- src/mame/sega/megadriv_rad.cpp | 136 ++++++++++-- src/mame/sega/megadriv_rad.h | 100 --------- src/mame/sega/megadriv_sunmix.cpp | 340 ++++++++++++++++++++++++++++++ src/mame/sega/megadriv_sunplus_hybrid.cpp | 21 +- src/mame/sega/megadriv_vt_hybrid.cpp | 17 +- src/mame/sega/megaplay.cpp | 17 +- src/mame/sega/megatech.cpp | 16 +- src/mame/sega/puckpkmn.cpp | 31 ++- src/mame/sega/sms.cpp | 20 +- src/mame/sega/sms.h | 41 +++- src/mame/sega/sms_m.cpp | 48 ++--- 24 files changed, 1263 insertions(+), 618 deletions(-) create mode 100644 src/devices/bus/sms_ctrl/diypaddle.cpp create mode 100644 src/devices/bus/sms_ctrl/diypaddle.h delete mode 100644 src/mame/sega/megadriv_rad.h create mode 100644 src/mame/sega/megadriv_sunmix.cpp diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 85906111ee4..749d453b783 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -3545,6 +3545,8 @@ if (BUSES["SMS_CTRL"]~=null) then files { MAME_DIR .. "src/devices/bus/sms_ctrl/controllers.cpp", MAME_DIR .. "src/devices/bus/sms_ctrl/controllers.h", + MAME_DIR .. "src/devices/bus/sms_ctrl/diypaddle.cpp", + MAME_DIR .. "src/devices/bus/sms_ctrl/diypaddle.h", MAME_DIR .. "src/devices/bus/sms_ctrl/graphic.cpp", MAME_DIR .. "src/devices/bus/sms_ctrl/graphic.h", MAME_DIR .. "src/devices/bus/sms_ctrl/joypad.cpp", diff --git a/src/devices/bus/sms_ctrl/controllers.cpp b/src/devices/bus/sms_ctrl/controllers.cpp index 77d5241c450..a4679c7aeb1 100644 --- a/src/devices/bus/sms_ctrl/controllers.cpp +++ b/src/devices/bus/sms_ctrl/controllers.cpp @@ -9,6 +9,7 @@ #include "emu.h" #include "controllers.h" +#include "diypaddle.h" #include "graphic.h" #include "joypad.h" #include "lphaser.h" @@ -22,6 +23,7 @@ #include "sportsjp.h" +char const *const SMS_CTRL_OPTION_DIY_PADDLE = "diypaddle"; char const *const SMS_CTRL_OPTION_GRAPHIC = "graphic"; char const *const SMS_CTRL_OPTION_LPHASER = "lphaser"; char const *const SMS_CTRL_OPTION_MD_6BUTTON = "md6button"; @@ -38,6 +40,7 @@ char const *const SMS_CTRL_OPTION_SPORTS_JP = "sportsjp"; void sms_control_port_devices(device_slot_interface &device) { + device.option_add(SMS_CTRL_OPTION_DIY_PADDLE, SMS_DIY_PADDLE); device.option_add(SMS_CTRL_OPTION_GRAPHIC, SMS_GRAPHIC); device.option_add(SMS_CTRL_OPTION_LPHASER, SMS_LIGHT_PHASER); device.option_add(SMS_CTRL_OPTION_MD_6BUTTON, SMS_MD6BUTTON); diff --git a/src/devices/bus/sms_ctrl/controllers.h b/src/devices/bus/sms_ctrl/controllers.h index ecb0083c706..0e128a2404c 100644 --- a/src/devices/bus/sms_ctrl/controllers.h +++ b/src/devices/bus/sms_ctrl/controllers.h @@ -11,6 +11,7 @@ #pragma once +extern char const *const SMS_CTRL_OPTION_DIY_PADDLE; extern char const *const SMS_CTRL_OPTION_GRAPHIC; extern char const *const SMS_CTRL_OPTION_LPHASER; extern char const *const SMS_CTRL_OPTION_MD_6BUTTON; diff --git a/src/devices/bus/sms_ctrl/diypaddle.cpp b/src/devices/bus/sms_ctrl/diypaddle.cpp new file mode 100644 index 00000000000..5c4e181c826 --- /dev/null +++ b/src/devices/bus/sms_ctrl/diypaddle.cpp @@ -0,0 +1,227 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Raphaël Assenat's DIY SMS/Mark III Paddle Controller + + English description: + https://www.raphnet.net/electronique/sms_paddle/index_en.php + + French description: + https://www.raphnet.net/electronique/sms_paddle/index.php + + Firmware source: + https://github.com/raphnet/sms_paddle + + TODO: + * Add ATmega8 variant - need CPU core. + +**********************************************************************/ + +#include "emu.h" +#include "diypaddle.h" + +#include "cpu/avr8/avr8.h" + + +namespace { + +ROM_START( sms_diy_paddle ) + ROM_REGION(0x4000, "u1", ROMREGION_ERASEFF) + ROM_LOAD( "sms_paddle.bin", 0x0000, 0x0138, CRC(97c7d334) SHA1(dd9e20f2447c43dbe29a49bb3a4fd8049775acd3) ) + + ROM_REGION(0x200, "eeprom", ROMREGION_ERASEFF) +ROM_END + + +INPUT_PORTS_START( sms_diy_paddle ) + PORT_START("BUTTON") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) + + PORT_START("PADDLE") + PORT_BIT( 0x3ff, 0x200, IPT_PADDLE) PORT_MINMAX(0, 1023) PORT_REVERSE PORT_SENSITIVITY(160) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) + + PORT_START("MODE") + PORT_CONFNAME( 0x01, 0x00, "Mode" ) + PORT_CONFSETTING( 0x00, "HPD-200" ) + PORT_CONFSETTING( 0x01, "Export paddle" ) +INPUT_PORTS_END + + + +class sms_diy_paddle_device : public device_t, public device_sms_control_interface +{ +public: + sms_diy_paddle_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + + virtual u8 in_r() override; + virtual void out_w(u8 data, u8 mem_mask) override; + +protected: + virtual tiny_rom_entry const *device_rom_region() const override { return ROM_NAME(sms_diy_paddle); } + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_diy_paddle); } + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + +private: + void program_map(address_map &map); + void data_map(address_map &map); + + u8 portb_in(); + u8 portc_in(); + u8 portd_in(); + void portb_out(u8 data); + void portc_out(u8 data); + + TIMER_CALLBACK_MEMBER(set_lines); + TIMER_CALLBACK_MEMBER(set_portd); + + required_device m_mcu; + required_ioport m_button; + required_ioport m_paddle; + required_ioport m_mode; + + u8 m_lines; + u8 m_portb; + u8 m_portc; + u8 m_portd; +}; + + +sms_diy_paddle_device::sms_diy_paddle_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, SMS_DIY_PADDLE, tag, owner, clock), + device_sms_control_interface(mconfig, *this), + m_mcu(*this, "u1"), + m_button(*this, "BUTTON"), + m_paddle(*this, "PADDLE"), + m_mode(*this, "MODE"), + m_lines(0x2f), + m_portb(0xff), + m_portc(0xff), + m_portd(0xff) +{ +} + + +u8 sms_diy_paddle_device::in_r() +{ + if (!machine().side_effects_disabled()) + machine().scheduler().add_quantum(attotime::from_usec(5), attotime::from_usec(100)); + + // button connected to TL directly + return m_lines | (BIT(m_button->read(), 0) << 4); +} + + +void sms_diy_paddle_device::out_w(u8 data, u8 mem_mask) +{ + // TH connected to PD2 + machine().scheduler().synchronize( + timer_expired_delegate(FUNC(sms_diy_paddle_device::set_portd), this), + 0xfb | (BIT(data, 6) << 2)); + machine().scheduler().add_quantum(attotime::from_usec(1), attotime::from_usec(20)); +} + + +void sms_diy_paddle_device::device_add_mconfig(machine_config &config) +{ + ATMEGA168(config, m_mcu, 8'000'000); // internally-generated clock + m_mcu->set_addrmap(AS_PROGRAM, &sms_diy_paddle_device::program_map); + m_mcu->set_addrmap(AS_DATA, &sms_diy_paddle_device::data_map); + m_mcu->set_eeprom_tag("eeprom"); + m_mcu->set_low_fuses(0xe2); + m_mcu->set_high_fuses(0xdd); + m_mcu->set_extended_fuses(0xf9); + m_mcu->gpio_in().set(FUNC(sms_diy_paddle_device::portb_in)); + m_mcu->gpio_in().set(FUNC(sms_diy_paddle_device::portc_in)); + m_mcu->gpio_in().set(FUNC(sms_diy_paddle_device::portd_in)); + m_mcu->gpio_out().set(FUNC(sms_diy_paddle_device::portb_out)); + m_mcu->gpio_out().set(FUNC(sms_diy_paddle_device::portc_out)); + m_mcu->adc_in().set_ioport("PADDLE"); +} + + +void sms_diy_paddle_device::device_start() +{ + m_lines = 0x2f; + m_portb = 0xff; + m_portc = 0xff; + m_portd = 0xff; + + save_item(NAME(m_lines)); + save_item(NAME(m_portb)); + save_item(NAME(m_portc)); + save_item(NAME(m_portd)); +} + + +void sms_diy_paddle_device::program_map(address_map &map) +{ + map(0x0000, 0x3fff).rom(); +} + + +void sms_diy_paddle_device::data_map(address_map &map) +{ + map(0x0100, 0x04ff).ram(); +} + + +u8 sms_diy_paddle_device::portb_in() +{ + // PB0 looped back to PB1 via mode switch + if (BIT(m_mode->read(), 0)) + return 0xfc | bitswap<2>(m_portb, 0, 0); + else + return 0xfe | BIT(m_portb, 0); +} + + +u8 sms_diy_paddle_device::portc_in() +{ + return (m_portc & 0x3e) | 0xc0 | ((m_paddle->read() > 0x1ff) ? 0x01 : 0x00); +} + + +u8 sms_diy_paddle_device::portd_in() +{ + return m_portd; +} + + +void sms_diy_paddle_device::portb_out(u8 data) +{ + m_portb = data; +} + + +void sms_diy_paddle_device::portc_out(u8 data) +{ + // PC1 -> TR, PC2 -> Up, PC3 -> Down, PC4 -> Left, PC5 -> Right + if (data != m_portc) + { + m_portc = data; + machine().scheduler().synchronize( + timer_expired_delegate(FUNC(sms_diy_paddle_device::set_lines), this), + (BIT(data, 1) << 5) | BIT(data, 2, 4)); + machine().scheduler().add_quantum(attotime::from_usec(1), attotime::from_usec(20)); + } +} + + +TIMER_CALLBACK_MEMBER(sms_diy_paddle_device::set_lines) +{ + m_lines = param & 0x2f; +} + + +TIMER_CALLBACK_MEMBER(sms_diy_paddle_device::set_portd) +{ + m_portd = param & 0xff; +} + +} // anonymous namespace + + + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_DIY_PADDLE, device_sms_control_interface, sms_diy_paddle_device, "sms_diypaddle", "raphnet DIY SMS/Mark III Paddle Controller") diff --git a/src/devices/bus/sms_ctrl/diypaddle.h b/src/devices/bus/sms_ctrl/diypaddle.h new file mode 100644 index 00000000000..75a3ef4514f --- /dev/null +++ b/src/devices/bus/sms_ctrl/diypaddle.h @@ -0,0 +1,18 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Raphaël Assenat's DIY SMS/Mark III Paddle Controller + +**********************************************************************/ +#ifndef MAME_BUS_SMS_CTRL_DIYPADDLE_H +#define MAME_BUS_SMS_CTRL_DIYPADDLE_H + +#pragma once + +#include "smsctrl.h" + + +DECLARE_DEVICE_TYPE(SMS_DIY_PADDLE, device_sms_control_interface) + +#endif // MAME_BUS_SMS_CTRL_DIYPADDLE_H diff --git a/src/devices/cpu/avr8/avr8.cpp b/src/devices/cpu/avr8/avr8.cpp index f650a53bbb3..ba7c21b079c 100644 --- a/src/devices/cpu/avr8/avr8.cpp +++ b/src/devices/cpu/avr8/avr8.cpp @@ -94,8 +94,10 @@ | LOG_OSC | LOG_PINCHG | LOG_EXTMEM | LOG_ADC | LOG_DIGINPUT | LOG_ASYNC | LOG_TWI | LOG_UART) #define VERBOSE (0) +//#define LOG_OUTPUT_FUNC osd_printf_info #include "logmacro.h" + //************************************************************************** // ENUMS AND MACROS //************************************************************************** @@ -587,6 +589,37 @@ static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' }; #define AVR8_EECR_EEPE ((AVR8_EECR & AVR8_EECR_EEPE_MASK) >> 1) #define AVR8_EECR_EERE ((AVR8_EECR & AVR8_EECR_EERE_MASK) >> 0) +//--------------------------------------------------------------- + +#define AVR8_ADMUX (m_r[AVR8_REGIDX_ADMUX]) +#define AVR8_ADMUX_REFS_MASK 0xc0 +#define AVR8_ADMUX_ADLAR_MASK 0x20 +#define AVR8_ADMUX_MUX_MASK 0x0f +#define AVR8_ADMUX_REFS ((AVR8_ADMUX & AVR8_ADMUX_REFS_MASK) >> 6) +#define AVR8_ADMUX_ADLAR ((AVR8_ADMUX & AVR8_ADMUX_ADLAR_MASK) >> 5) +#define AVR8_ADMUX_MUX ((AVR8_ADMUX & AVR8_ADMUX_MUX_MASK) >> 0) + +#define AVR8_ADCSRB (m_r[AVR8_REGIDX_ADCSRB]) +#define AVR8_ADCSRB_ACME_MASK 0x40 +#define AVR8_ADCSRB_ADTS_MASK 0x07 +#define AVR8_ADCSRB_ACME ((AVR8_ADCSRB & AVR8_ADCSRB_ACME_MASK) >> 6) +#define AVR8_ADCSRB_ADTS ((AVR8_ADCSRB & AVR8_ADCSRB_ADTS_MASK) >> 0) + +#define AVR8_ADCSRA (m_r[AVR8_REGIDX_ADCSRA]) +#define AVR8_ADCSRA_ADEN_MASK 0x80 +#define AVR8_ADCSRA_ADSC_MASK 0x40 +#define AVR8_ADCSRA_ADATE_MASK 0x20 +#define AVR8_ADCSRA_ADIF_MASK 0x10 +#define AVR8_ADCSRA_ADIE_MASK 0x08 +#define AVR8_ADCSRA_ADPS_MASK 0x07 +#define AVR8_ADCSRA_ADEN ((AVR8_ADCSRA & AVR8_ADCSRA_ADEN_MASK) >> 7) +#define AVR8_ADCSRA_ADSC ((AVR8_ADCSRA & AVR8_ADCSRA_ADSC_MASK) >> 6) +#define AVR8_ADCSRA_ADATE ((AVR8_ADCSRA & AVR8_ADCSRA_ADATE_MASK) >> 5) +#define AVR8_ADCSRA_ADIF ((AVR8_ADCSRA & AVR8_ADCSRA_ADIF_MASK) >> 4) +#define AVR8_ADCSRA_ADIE ((AVR8_ADCSRA & AVR8_ADCSRA_ADIE_MASK) >> 3) +#define AVR8_ADCSRA_ADPS ((AVR8_ADCSRA & AVR8_ADCSRA_ADPS_MASK) >> 0) + + //************************************************************************** // DEVICE INTERFACE //************************************************************************** @@ -719,6 +752,8 @@ avr8_device::avr8_device(const machine_config &mconfig, const char *tag, device_ , m_num_timers(num_timers) , m_gpio_out_cb(*this) , m_gpio_in_cb(*this) + , m_adc_in_cb(*this) + , m_adc_timer(nullptr) , m_spi_active(false) , m_spi_prescale(0) , m_spi_prescale_count(0) @@ -817,6 +852,9 @@ void avr8_device::device_start() m_gpio_out_cb.resolve_all_safe(); m_gpio_in_cb.resolve_all_safe(0); + m_adc_in_cb.resolve_all_safe(0); + m_adc_timer = timer_alloc(FUNC(avr8_device::adc_conversion_complete), this); + // register our state for the debugger state_add(STATE_GENPC, "GENPC", m_shifted_pc).noshow(); state_add(STATE_GENPCBASE, "CURPC", m_shifted_pc).noshow(); @@ -878,6 +916,13 @@ void avr8_device::device_start() save_item(NAME(m_ocr1)); save_item(NAME(m_timer1_count)); + // ADC + save_item(NAME(m_adc_sample)); + save_item(NAME(m_adc_result)); + save_item(NAME(m_adc_data)); + save_item(NAME(m_adc_first)); + save_item(NAME(m_adc_hold)); + // SPI save_item(NAME(m_spi_active)); save_item(NAME(m_spi_prescale)); @@ -960,6 +1005,12 @@ void avr8_device::device_reset() m_r[i] = 0; } + m_adc_sample = 0; + m_adc_result = 0; + m_adc_data = 0; + m_adc_first = true; + m_adc_hold = false; + m_spi_active = false; m_spi_prescale = 0; m_spi_prescale_count = 0; @@ -2234,6 +2285,103 @@ void avr8_device::changed_tccr5b(uint8_t data) /************************************************************************************************/ +/****************/ +/* ADC Handling */ +/****************/ + +void avr8_device::adc_start_conversion() +{ + // set capture in progress flag + AVR8_ADCSRA |= AVR8_ADCSRA_ADSC_MASK; + + // get a sample - the sample-and-hold circuit will hold this for the duration of the conversion + if (AVR8_ADMUX_MUX < 0x8) + { + m_adc_sample = m_adc_in_cb[AVR8_ADMUX_MUX](); + } + else if (AVR8_ADMUX_MUX == 0xe) + { + // 1.1V (Vbg) + // FIXME: the value this acquires depends on what the reference source is set to + logerror("%s: Using unimplemented 1.1V reference voltage as ADC input\n", machine().describe_context()); + m_adc_sample = 0x3ff; + } + else if (AVR8_ADMUX_MUX == 0x0f) + { + // 0V (GND) + m_adc_sample = 0; + } + else + { + logerror("%s: Using reserved ADC input 0x%X\n", machine().describe_context(), AVR8_ADMUX_MUX); + m_adc_sample = 0; + } + + // wait for conversion to complete + int const scale = 1 << std::max(AVR8_ADCSRA_ADPS, 1); + m_adc_timer->adjust(attotime::from_ticks((m_adc_first ? 25 : 13) * scale, clock())); +} + +TIMER_CALLBACK_MEMBER(avr8_device::adc_conversion_complete) +{ + // set conversion result + m_adc_result = m_adc_sample; + if (!m_adc_hold) + m_adc_data = m_adc_result; + + // clear conversion in progress flag, set conversion interrupt flag + AVR8_ADCSRA &= ~AVR8_ADCSRA_ADSC_MASK; + AVR8_ADCSRA |= AVR8_ADCSRA_ADIF_MASK; + + // trigger another conversion if appropriate + if (AVR8_ADCSRA_ADATE && (AVR8_ADCSRB_ADTS == 0)) + adc_start_conversion(); +} + +void avr8_device::change_adcsra(uint8_t data) +{ + // set auto trigger enable, interrupt enable, and prescaler directly + AVR8_ADCSRA = (AVR8_ADCSRA & ~(AVR8_ADCSRA_ADATE_MASK | AVR8_ADCSRA_ADIE_MASK | AVR8_ADCSRA_ADPS_MASK)) | (data & (AVR8_ADCSRA_ADATE_MASK | AVR8_ADCSRA_ADIE_MASK | AVR8_ADCSRA_ADPS_MASK)); + + // check enable bit + if (!(data & AVR8_ADCSRA_ADEN_MASK)) + { + // disable ADC, terminate any conversion in progress + AVR8_ADCSRA &= ~(AVR8_ADCSRA_ADEN_MASK | AVR8_ADCSRA_ADSC_MASK); + m_adc_timer->reset(); + } + else + { + // first conversion after initial enable takes longer + if (!AVR8_ADCSRA_ADEN) + { + m_adc_first = true; + AVR8_ADCSRA |= AVR8_ADCSRA_ADEN_MASK; + } + + // trigger conversion if necessary + if (!AVR8_ADCSRA_ADSC && (data & AVR8_ADCSRA_ADSC_MASK)) + adc_start_conversion(); + } + + // writing with ADIF set clears the interrupt flag manually + if (data & AVR8_ADCSRA_ADIF_MASK) + AVR8_ADCSRA &= ~AVR8_ADCSRA_ADIF_MASK; + + if (AVR8_ADCSRA_ADIE) + logerror("%s: Unimplemented ADC interrupt enabled\n"); +} + +void avr8_device::change_adcsrb(uint8_t data) +{ + AVR8_ADCSRB = data & (AVR8_ADCSRB_ACME_MASK | AVR8_ADCSRB_ADTS_MASK); + if (AVR8_ADCSRB_ADTS != 0x00) + logerror("%s: Unimplemented ADC auto trigger source %X selected\n", machine().describe_context(), AVR8_ADCSRB_ADTS); +} + +/************************************************************************************************/ + + /****************/ /* SPI Handling */ /****************/ @@ -2690,23 +2838,26 @@ void avr8_device::regs_w(offs_t offset, uint8_t data) break; case AVR8_REGIDX_ADCL: - LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADCL = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_ADC, "%s: ADCL = %02x\n", machine().describe_context(), data); break; case AVR8_REGIDX_ADCH: - LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADCH = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_ADC, "%s: ADCH = %02x\n", machine().describe_context(), data); break; case AVR8_REGIDX_ADCSRA: - LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADCSRA = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_ADC, "%s: ADCSRA = %02x\n", machine().describe_context(), data); + change_adcsra(data); break; case AVR8_REGIDX_ADCSRB: - LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADCSRB = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_ADC, "%s: ADCSRB = %02x\n", machine().describe_context(), data); + change_adcsrb(data); break; case AVR8_REGIDX_ADMUX: - LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADMUX = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_ADC, "%s: ADMUX = %02x\n", machine().describe_context(), data); + AVR8_ADMUX = data & (AVR8_ADMUX_REFS_MASK | AVR8_ADMUX_ADLAR_MASK | AVR8_ADMUX_MUX_MASK); break; case AVR8_REGIDX_DIDR0: @@ -3147,6 +3298,28 @@ uint8_t avr8_device::regs_r(offs_t offset) case AVR8_REGIDX_UCSR0A: return m_r[offset]; + case AVR8_REGIDX_ADCL: + if (!machine().side_effects_disabled()) + m_adc_hold = true; + if (AVR8_ADMUX_ADLAR) + return (m_adc_data & 0x03) << 6; + else + return uint8_t(m_adc_data); + case AVR8_REGIDX_ADCH: + { + uint8_t const result = AVR8_ADMUX_ADLAR ? BIT(m_adc_data, 2, 8) : BIT(m_adc_data, 8, 2); + if (!machine().side_effects_disabled()) + { + m_adc_data = m_adc_result; + m_adc_hold = false; + } + return result; + } + case AVR8_REGIDX_ADCSRA: + case AVR8_REGIDX_ADCSRB: + case AVR8_REGIDX_ADMUX: + return m_r[offset]; + default: LOGMASKED(LOG_UNKNOWN, "%s: Unknown Register Read: %03X\n", machine().describe_context(), offset); return 0; diff --git a/src/devices/cpu/avr8/avr8.h b/src/devices/cpu/avr8/avr8.h index 85f05e8cea6..960cbda6eed 100644 --- a/src/devices/cpu/avr8/avr8.h +++ b/src/devices/cpu/avr8/avr8.h @@ -15,8 +15,6 @@ // TYPE DEFINITIONS //************************************************************************** -class avr8_device; - // ======================> avr8_device // Used by core CPU interface @@ -44,6 +42,9 @@ public: template auto gpio_out() { return m_gpio_out_cb[Port].bind(); } template auto gpio_in() { return m_gpio_in_cb[Port].bind(); } + // ADC + template auto adc_in() { return m_adc_in_cb[Pin].bind(); } + protected: avr8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, uint32_t address_mask, address_map_constructor internal_map, int32_t num_timers); @@ -115,6 +116,19 @@ protected: devcb_write8::array<11> m_gpio_out_cb; devcb_read8::array<11> m_gpio_in_cb; + // ADC + devcb_read16::array<8> m_adc_in_cb; + emu_timer *m_adc_timer; + uint16_t m_adc_sample; + uint16_t m_adc_result; + uint16_t m_adc_data; + bool m_adc_first; + bool m_adc_hold; + void adc_start_conversion(); + TIMER_CALLBACK_MEMBER(adc_conversion_complete); + void change_adcsra(uint8_t data); + void change_adcsrb(uint8_t data); + // SPI bool m_spi_active; uint8_t m_spi_prescale; @@ -822,7 +836,8 @@ enum : uint16_t //0x1FF: Reserved }; -enum : uint8_t { +enum : uint8_t +{ AVR8_IO_PORTA = 0, AVR8_IO_PORTB, AVR8_IO_PORTC, @@ -836,6 +851,18 @@ enum : uint8_t { AVR8_IO_PORTL }; +enum : uint8_t +{ + AVR8_ADC_ADC0 = 0, + AVR8_ADC_ADC1, + AVR8_ADC_ADC2, + AVR8_ADC_ADC3, + AVR8_ADC_ADC4, + AVR8_ADC_ADC5, + AVR8_ADC_ADC6, + AVR8_ADC_ADC7 +}; + enum : uint8_t { AVR8_REG_A = 0, diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 5abc4de4967..6b5e026c80a 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -23331,12 +23331,10 @@ barek3mb // MegaDrive-based hack bk3ssrmb // MegaDrive-based hack jparkmb // MegaDrive-based hack mk3mdb // MegaDrive-based hack -sbubsm // (c) 1996 Sun Mixing sonic2mb // MegaDrive-based hack sonic3mb // MegaDrive-based hack srmdb // MegaDrive-based hack ssf2mdb // MegaDrive-based hack -topshoot // (c) 1995 Sun Mixing twinktmb // MegaDrive-based hack @source:sega/megadriv_rad.cpp @@ -23354,6 +23352,10 @@ msi_sf2 dgunl3227 ra145 +@source:sega/megadriv_sunmix.cpp +sbubsm // (c) 1996 Sun Mixing +topshoot // (c) 1995 Sun Mixing + @source:sega/megadriv_sunplus_hybrid.cpp reactmd diff --git a/src/mame/sega/hshavoc.cpp b/src/mame/sega/hshavoc.cpp index ea552fc47ba..00cc6640683 100644 --- a/src/mame/sega/hshavoc.cpp +++ b/src/mame/sega/hshavoc.cpp @@ -38,8 +38,6 @@ help with figuring out the encryption on the coin-op parts of the program. #include "emu.h" - -#include "megadriv.h" #include "megadriv_acbl.h" #include "cpu/m68000/m68000.h" diff --git a/src/mame/sega/megadriv.cpp b/src/mame/sega/megadriv.cpp index c012b265dd1..a0f90da458b 100644 --- a/src/mame/sega/megadriv.cpp +++ b/src/mame/sega/megadriv.cpp @@ -98,7 +98,7 @@ void md_base_state::megadriv_68k_YM2612_write(offs_t offset, uint8_t data, uint8 } // this is used by 6 button pads and gets installed in machine_start for drivers requiring it -TIMER_CALLBACK_MEMBER(md_base_state::ioport_timeout) +TIMER_CALLBACK_MEMBER(md_ctrl_state::ioport_timeout) { m_ioport_phase[param] = 0; } @@ -175,7 +175,7 @@ INPUT_PORTS_END template -uint8_t md_base_state::ioport_in_3button() +uint8_t md_ctrl_state::ioport_in_3button() { ioport_value const pad = m_io_pad[N]->read(); if (m_ioport_th[N]) @@ -185,7 +185,7 @@ uint8_t md_base_state::ioport_in_3button() } template -uint8_t md_base_state::ioport_in_6button() +uint8_t md_ctrl_state::ioport_in_6button() { ioport_value const pad = m_io_pad[N]->read(); switch (m_ioport_phase[N]) @@ -211,13 +211,13 @@ uint8_t md_base_state::ioport_in_6button() } template -void md_base_state::ioport_out_3button(uint8_t data, uint8_t mem_mask) +void md_ctrl_state::ioport_out_3button(uint8_t data, uint8_t mem_mask) { m_ioport_th[N] = BIT(data, 6); } template -void md_base_state::ioport_out_6button(uint8_t data, uint8_t mem_mask) +void md_ctrl_state::ioport_out_6button(uint8_t data, uint8_t mem_mask) { uint8_t const th = BIT(data, 6); if (!th) @@ -232,15 +232,6 @@ void md_base_state::ioport_out_6button(uint8_t data, uint8_t mem_mask) m_ioport_th[N] = th; } -template uint8_t md_base_state::ioport_in_3button<0>(); -template uint8_t md_base_state::ioport_in_3button<1>(); -template uint8_t md_base_state::ioport_in_6button<0>(); -template uint8_t md_base_state::ioport_in_6button<1>(); -template void md_base_state::ioport_out_3button<0>(uint8_t, uint8_t); -template void md_base_state::ioport_out_3button<1>(uint8_t, uint8_t); -template void md_base_state::ioport_out_6button<0>(uint8_t, uint8_t); -template void md_base_state::ioport_out_6button<1>(uint8_t, uint8_t); - uint16_t md_base_state::m68k_version_read() { @@ -648,9 +639,9 @@ void md_base_state::megadriv_z80_io_map(address_map &map) map(0x00, 0xff).noprw(); } -uint32_t md_base_state::screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +uint32_t md_core_state::screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - /* Copy our screen buffer here */ + // Copy our screen buffer here for (int y = cliprect.min_y; y <= cliprect.max_y; y++) { uint32_t *const desty = &bitmap.pix(y, 0); @@ -674,16 +665,21 @@ uint32_t md_base_state::screen_update_megadriv(screen_device &screen, bitmap_rgb /*****************************************************************************************/ -void md_base_state::machine_start() +void md_core_state::machine_reset() { - m_ioport_idle[0] = timer_alloc(FUNC(md_base_state::ioport_timeout), this); - m_ioport_idle[1] = timer_alloc(FUNC(md_base_state::ioport_timeout), this); + if (!m_vdp->m_use_alt_timing) + { + m_vdp->m_megadriv_scanline_timer = m_scan_timer; + m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); + } - std::fill(std::begin(m_ioport_th), std::end(m_ioport_th), 1); - std::fill(std::begin(m_ioport_phase), std::end(m_ioport_phase), 0); + m_vdp->device_reset_old(); +} - save_item(NAME(m_ioport_th)); - save_item(NAME(m_ioport_phase)); + +void md_base_state::machine_start() +{ + md_core_state::machine_start(); if (m_z80snd) m_genz80.z80_run_timer = timer_alloc(FUNC(md_base_state::megadriv_z80_run_state), this); @@ -691,7 +687,9 @@ void md_base_state::machine_start() void md_base_state::machine_reset() { - /* default state of z80 = reset, with bus */ + md_core_state::machine_reset(); + + // default state of z80 = reset, with bus osd_printf_debug("Resetting Megadrive / Genesis\n"); if (m_z80snd) @@ -703,18 +701,26 @@ void md_base_state::machine_reset() m_genz80.z80_run_timer->adjust(attotime::zero); } - if (!m_vdp->m_use_alt_timing) - { - m_vdp->m_megadriv_scanline_timer = m_scan_timer; - m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); - } - if (m_megadrive_ram) memset(m_megadrive_ram, 0x00, 0x10000); +} - m_vdp->device_reset_old(); + +void md_ctrl_state::machine_start() +{ + md_base_state::machine_start(); + + m_ioport_idle[0] = timer_alloc(FUNC(md_ctrl_state::ioport_timeout), this); + m_ioport_idle[1] = timer_alloc(FUNC(md_ctrl_state::ioport_timeout), this); + + std::fill(std::begin(m_ioport_th), std::end(m_ioport_th), 1); + std::fill(std::begin(m_ioport_phase), std::end(m_ioport_phase), 0); + + save_item(NAME(m_ioport_th)); + save_item(NAME(m_ioport_phase)); } + void md_base_state::megadriv_stop_scanline_timer() { if (!m_vdp->m_use_alt_timing) @@ -741,7 +747,7 @@ WRITE_LINE_MEMBER(md_base_state::vdp_sndirqline_callback_genesis_z80) } // this comes from the vdp, and is connected to 68k irq level 6 (main vbl interrupt) -WRITE_LINE_MEMBER(md_base_state::vdp_lv6irqline_callback_genesis_68k) +WRITE_LINE_MEMBER(md_core_state::vdp_lv6irqline_callback_genesis_68k) { if (state == ASSERT_LINE) m_maincpu->set_input_line(6, HOLD_LINE); @@ -750,7 +756,7 @@ WRITE_LINE_MEMBER(md_base_state::vdp_lv6irqline_callback_genesis_68k) } // this comes from the vdp, and is connected to 68k irq level 4 (raster interrupt) -WRITE_LINE_MEMBER(md_base_state::vdp_lv4irqline_callback_genesis_68k) +WRITE_LINE_MEMBER(md_core_state::vdp_lv4irqline_callback_genesis_68k) { if (state == ASSERT_LINE) m_maincpu->set_input_line(4, HOLD_LINE); @@ -759,7 +765,7 @@ WRITE_LINE_MEMBER(md_base_state::vdp_lv4irqline_callback_genesis_68k) } /* Callback when the 68k takes an IRQ */ -IRQ_CALLBACK_MEMBER(md_base_state::genesis_int_callback) +IRQ_CALLBACK_MEMBER(md_core_state::genesis_int_callback) { if (irqline==4) { @@ -775,11 +781,64 @@ IRQ_CALLBACK_MEMBER(md_base_state::genesis_int_callback) } -void md_base_state::megadriv_timers(machine_config &config) +void md_core_state::megadriv_timers(machine_config &config) { TIMER(config, m_scan_timer).configure_generic(m_vdp, FUNC(sega315_5313_device::megadriv_scanline_timer_callback)); } +void md_core_state::md_core_ntsc(machine_config &config) +{ + M68000(config, m_maincpu, MASTER_CLOCK_NTSC / 7); // 7.67 MHz + m_maincpu->set_irq_acknowledge_callback(FUNC(md_core_state::genesis_int_callback)); + // IRQs are handled via the timers + + megadriv_timers(config); + + SEGA315_5313(config, m_vdp, MASTER_CLOCK_NTSC, m_maincpu); + m_vdp->set_is_pal(false); + m_vdp->lv6_irq().set(FUNC(md_core_state::vdp_lv6irqline_callback_genesis_68k)); + m_vdp->lv4_irq().set(FUNC(md_core_state::vdp_lv4irqline_callback_genesis_68k)); + m_vdp->set_screen("megadriv"); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 10.0 / 262.0 / 342.0); // same as SMS? +// m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 8.0 / 262.0 / 427.0); // or 427 Htotal? + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. + m_screen->set_size(64*8, 620); + m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); + m_screen->set_screen_update(FUNC(md_core_state::screen_update_megadriv)); /* Copies a bitmap */ + m_screen->screen_vblank().set(FUNC(md_core_state::screen_vblank_megadriv)); /* Used to Sync the timing */ + + YM2612(config, m_ymsnd, MASTER_CLOCK_NTSC/7); // 7.67 MHz +} + +void md_core_state::md_core_pal(machine_config &config) +{ + M68000(config, m_maincpu, MASTER_CLOCK_PAL / 7); // 7.67 MHz + m_maincpu->set_irq_acknowledge_callback(FUNC(md_core_state::genesis_int_callback)); + // IRQs are handled via the timers + + megadriv_timers(config); + + SEGA315_5313(config, m_vdp, MASTER_CLOCK_PAL, m_maincpu); + m_vdp->set_is_pal(true); + m_vdp->lv6_irq().set(FUNC(md_core_state::vdp_lv6irqline_callback_genesis_68k)); + m_vdp->lv4_irq().set(FUNC(md_core_state::vdp_lv4irqline_callback_genesis_68k)); + m_vdp->set_screen("megadriv"); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 10.0 / 313.0 / 342.0); // same as SMS? +// m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 8.0 / 313.0 / 423.0); // or 423 Htotal? + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. + m_screen->set_size(64*8, 620); + m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); + m_screen->set_screen_update(FUNC(md_core_state::screen_update_megadriv)); /* Copies a bitmap */ + m_screen->screen_vblank().set(FUNC(md_core_state::screen_vblank_megadriv)); /* Used to Sync the timing */ + + YM2612(config, m_ymsnd, MASTER_CLOCK_PAL / 7); // 7.67 MHz +} + + void md_base_state::megadriv_ioports(machine_config &config) { // TODO: this latches video counters as well as setting interrupt level 2 @@ -787,13 +846,9 @@ void md_base_state::megadriv_ioports(machine_config &config) hl.output_handler().set_inputline(m_maincpu, 2); MEGADRIVE_IO_PORT(config, m_ioports[0], 0); - m_ioports[0]->set_in_handler(FUNC(md_base_state::ioport_in_3button<0>)); - m_ioports[0]->set_out_handler(FUNC(md_base_state::ioport_out_3button<0>)); m_ioports[0]->hl_handler().set("hl", FUNC(input_merger_device::in_w<0>)); MEGADRIVE_IO_PORT(config, m_ioports[1], 0); - m_ioports[1]->set_in_handler(FUNC(md_base_state::ioport_in_3button<1>)); - m_ioports[1]->set_out_handler(FUNC(md_base_state::ioport_out_3button<1>)); m_ioports[1]->hl_handler().set("hl", FUNC(input_merger_device::in_w<1>)); MEGADRIVE_IO_PORT(config, m_ioports[2], 0); @@ -801,47 +856,53 @@ void md_base_state::megadriv_ioports(machine_config &config) } +void md_ctrl_state::ctrl1_3button(machine_config &config) +{ + m_ioports[0]->set_in_handler(FUNC(md_ctrl_state::ioport_in_3button<0>)); + m_ioports[0]->set_out_handler(FUNC(md_ctrl_state::ioport_out_3button<0>)); +} + +void md_ctrl_state::ctrl2_3button(machine_config &config) +{ + m_ioports[1]->set_in_handler(FUNC(md_ctrl_state::ioport_in_3button<1>)); + m_ioports[1]->set_out_handler(FUNC(md_ctrl_state::ioport_out_3button<1>)); +} + +void md_ctrl_state::ctrl1_6button(machine_config &config) +{ + m_ioports[0]->set_in_handler(FUNC(md_ctrl_state::ioport_in_6button<0>)); + m_ioports[0]->set_out_handler(FUNC(md_ctrl_state::ioport_out_6button<0>)); +} + +void md_ctrl_state::ctrl2_6button(machine_config &config) +{ + m_ioports[1]->set_in_handler(FUNC(md_ctrl_state::ioport_in_6button<1>)); + m_ioports[1]->set_out_handler(FUNC(md_ctrl_state::ioport_out_6button<1>)); +} + + void md_base_state::md_ntsc(machine_config &config) { - M68000(config, m_maincpu, MASTER_CLOCK_NTSC / 7); /* 7.67 MHz */ - m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_68k_map); - m_maincpu->set_irq_acknowledge_callback(FUNC(md_base_state::genesis_int_callback)); + md_core_ntsc(config); - /* IRQs are handled via the timers */ + m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_68k_map); Z80(config, m_z80snd, MASTER_CLOCK_NTSC / 15); /* 3.58 MHz */ m_z80snd->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_z80_map); m_z80snd->set_addrmap(AS_IO, &md_base_state::megadriv_z80_io_map); /* IRQ handled via the timers */ - megadriv_timers(config); - /* I/O port controllers */ megadriv_ioports(config); - SEGA315_5313(config, m_vdp, MASTER_CLOCK_NTSC, m_maincpu); - m_vdp->set_is_pal(false); m_vdp->snd_irq().set(FUNC(md_base_state::vdp_sndirqline_callback_genesis_z80)); - m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k)); - m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k)); - m_vdp->set_screen("megadriv"); m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50); m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50); - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 10.0 / 262.0 / 342.0); // same as SMS? -// m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 8.0 / 262.0 / 427.0); // or 427 Htotal? - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. - m_screen->set_size(64*8, 620); - m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); - m_screen->set_screen_update(FUNC(md_base_state::screen_update_megadriv)); /* Copies a bitmap */ - m_screen->screen_vblank().set(FUNC(md_base_state::screen_vblank_megadriv)); /* Used to Sync the timing */ - /* sound hardware */ SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); - YM2612(config, m_ymsnd, MASTER_CLOCK_NTSC/7); /* 7.67 MHz */ m_ymsnd->add_route(0, "lspeaker", 0.50); m_ymsnd->add_route(1, "rspeaker", 0.50); } @@ -860,44 +921,26 @@ void md_base_state::md2_ntsc(machine_config &config) void md_base_state::md_pal(machine_config &config) { - M68000(config, m_maincpu, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ + md_core_pal(config); + m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_68k_map); - m_maincpu->set_irq_acknowledge_callback(FUNC(md_base_state::genesis_int_callback)); - /* IRQs are handled via the timers */ Z80(config, m_z80snd, MASTER_CLOCK_PAL / 15); /* 3.58 MHz */ m_z80snd->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_z80_map); m_z80snd->set_addrmap(AS_IO, &md_base_state::megadriv_z80_io_map); /* IRQ handled via the timers */ - megadriv_timers(config); - /* I/O port controllers */ megadriv_ioports(config); - SEGA315_5313(config, m_vdp, MASTER_CLOCK_PAL, m_maincpu); - m_vdp->set_is_pal(true); m_vdp->snd_irq().set(FUNC(md_base_state::vdp_sndirqline_callback_genesis_z80)); - m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k)); - m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k)); - m_vdp->set_screen("megadriv"); m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50); m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50); - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 10.0 / 313.0 / 342.0); // same as SMS? -// m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 8.0 / 313.0 / 423.0); // or 423 Htotal? - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. - m_screen->set_size(64*8, 620); - m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); - m_screen->set_screen_update(FUNC(md_base_state::screen_update_megadriv)); /* Copies a bitmap */ - m_screen->screen_vblank().set(FUNC(md_base_state::screen_vblank_megadriv)); /* Used to Sync the timing */ - /* sound hardware */ SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); - YM2612(config, m_ymsnd, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ m_ymsnd->add_route(0, "lspeaker", 0.50); m_ymsnd->add_route(1, "rspeaker", 0.50); } @@ -913,7 +956,7 @@ void md_base_state::md2_pal(machine_config &config) } -void md_base_state::megadriv_tas_callback(offs_t offset, uint8_t data) +void md_core_state::megadriv_tas_callback(offs_t offset, uint8_t data) { // writeback not allowed } @@ -938,7 +981,7 @@ void md_base_state::init_megadriv() { megadriv_init_common(); - // todo: move this to the device interface? + // TODO: move this to the device interface? m_vdp->set_use_cram(1); m_vdp->set_vdp_pal(false); m_vdp->set_framerate(60); @@ -951,7 +994,7 @@ void md_base_state::init_megadrij() { megadriv_init_common(); - // todo: move this to the device interface? + // TODO: move this to the device interface? m_vdp->set_use_cram(1); m_vdp->set_vdp_pal(false); m_vdp->set_framerate(60); @@ -973,7 +1016,7 @@ void md_base_state::init_megadrie() m_version_hi_nibble = 0xe0; // Export PAL no-SCD } -WRITE_LINE_MEMBER(md_base_state::screen_vblank_megadriv) +WRITE_LINE_MEMBER(md_core_state::screen_vblank_megadriv) { if (m_io_reset.read_safe(0) & 0x01) m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); diff --git a/src/mame/sega/megadriv.h b/src/mame/sega/megadriv.h index 8c1f29fed7c..03c3a808a58 100644 --- a/src/mame/sega/megadriv.h +++ b/src/mame/sega/megadriv.h @@ -1,7 +1,7 @@ // license:BSD-3-Clause // copyright-holders:David Haywood -#ifndef MAME_SHARED_MEGADRIV_H -#define MAME_SHARED_MEGADRIV_H +#ifndef MAME_SEGA_MEGADRIV_H +#define MAME_SEGA_MEGADRIV_H #pragma once @@ -23,34 +23,61 @@ INPUT_PORTS_EXTERN( md_common ); INPUT_PORTS_EXTERN( megadriv ); -class md_base_state : public driver_device +class md_core_state : public driver_device { -public: - md_base_state(const machine_config &mconfig, device_type type, const char *tag) : +protected: + md_core_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this,"maincpu"), - m_z80snd(*this,"genesis_snd_z80"), - m_ymsnd(*this,"ymsnd"), m_scan_timer(*this, "md_scan_timer"), m_vdp(*this,"gen_vdp"), - m_megadrive_ram(*this,"megadrive_ram"), m_screen(*this,"megadriv"), - m_io_reset(*this, "RESET"), - m_ioports(*this, "ioport%u", 1U), - m_io_pad(*this, "PAD%u", 1U), - m_io_extra(*this, "EXTRA%u", 1U) - { } + m_ymsnd(*this,"ymsnd"), + m_io_reset(*this, "RESET") + { + } + + virtual void machine_reset() override; + + void md_core_ntsc(machine_config &config); + void md_core_pal(machine_config &config); + + void megadriv_tas_callback(offs_t offset, uint8_t data); + + uint32_t screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(screen_vblank_megadriv); required_device m_maincpu; - optional_device m_z80snd; - optional_device m_ymsnd; - optional_device m_scan_timer; + required_device m_scan_timer; required_device m_vdp; - optional_shared_ptr m_megadrive_ram; optional_device m_screen; + optional_device m_ymsnd; optional_ioport m_io_reset; +private: + IRQ_CALLBACK_MEMBER(genesis_int_callback); + + WRITE_LINE_MEMBER(vdp_lv6irqline_callback_genesis_68k); + WRITE_LINE_MEMBER(vdp_lv4irqline_callback_genesis_68k); + + void megadriv_timers(machine_config &config); +}; + + +class md_base_state : public md_core_state +{ +public: + md_base_state(const machine_config &mconfig, device_type type, const char *tag) : + md_core_state(mconfig, type, tag), + m_z80snd(*this,"genesis_snd_z80"), + m_megadrive_ram(*this,"megadrive_ram"), + m_ioports(*this, "ioport%u", 1U) + { } + + optional_device m_z80snd; + optional_shared_ptr m_megadrive_ram; + struct genesis_z80_vars { int z80_is_reset = 0; @@ -69,7 +96,7 @@ public: uint8_t megadriv_68k_YM2612_read(offs_t offset, uint8_t mem_mask = ~0); void megadriv_68k_YM2612_write(offs_t offset, uint8_t data, uint8_t mem_mask = ~0); - IRQ_CALLBACK_MEMBER(genesis_int_callback); + void megadriv_init_common(); void megadriv_z80_bank_w(uint16_t data); @@ -88,16 +115,9 @@ public: TIMER_CALLBACK_MEMBER(megadriv_z80_run_state); WRITE_LINE_MEMBER(vdp_sndirqline_callback_genesis_z80); - WRITE_LINE_MEMBER(vdp_lv6irqline_callback_genesis_68k); - WRITE_LINE_MEMBER(vdp_lv4irqline_callback_genesis_68k); void megadriv_stop_scanline_timer(); - uint32_t screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(screen_vblank_megadriv); - - void megadriv_tas_callback(offs_t offset, uint8_t data); - void md_ntsc(machine_config &config); void md2_ntsc(machine_config &config); void md_pal(machine_config &config); @@ -113,12 +133,6 @@ protected: void megadriv_z80_io_map(address_map &map); void megadriv_z80_map(address_map &map); - template uint8_t ioport_in_3button(); - template uint8_t ioport_in_6button(); - - template void ioport_out_3button(uint8_t data, uint8_t mem_mask); - template void ioport_out_6button(uint8_t data, uint8_t mem_mask); - required_device_array m_ioports; private: @@ -134,10 +148,35 @@ private: template void m68k_ioport_txdata_write(uint16_t data); template void m68k_ioport_s_ctrl_write(uint16_t data); - TIMER_CALLBACK_MEMBER(ioport_timeout); - - void megadriv_timers(machine_config &config); void megadriv_ioports(machine_config &config); +}; + + +class md_ctrl_state : public md_base_state +{ +protected: + md_ctrl_state(const machine_config &mconfig, device_type type, const char *tag) : + md_base_state(mconfig, type, tag), + m_io_pad(*this, "PAD%u", 1U), + m_io_extra(*this, "EXTRA%u", 1U) + { + } + + void ctrl1_3button(machine_config &config); + void ctrl2_3button(machine_config &config); + void ctrl1_6button(machine_config &config); + void ctrl2_6button(machine_config &config); + + virtual void machine_start() override; + +private: + template uint8_t ioport_in_3button(); + template uint8_t ioport_in_6button(); + + template void ioport_out_3button(uint8_t data, uint8_t mem_mask); + template void ioport_out_6button(uint8_t data, uint8_t mem_mask); + + TIMER_CALLBACK_MEMBER(ioport_timeout); optional_ioport_array<2> m_io_pad; optional_ioport_array<2> m_io_extra; @@ -148,4 +187,4 @@ private: uint8_t m_ioport_phase[2]; }; -#endif // MAME_SHARED_MEGADRIV_H +#endif // MAME_SEGA_MEGADRIV_H diff --git a/src/mame/sega/megadriv_acbl.cpp b/src/mame/sega/megadriv_acbl.cpp index abb62544ec1..43903ceda56 100644 --- a/src/mame/sega/megadriv_acbl.cpp +++ b/src/mame/sega/megadriv_acbl.cpp @@ -15,7 +15,6 @@ * Sonic The Hedgehog 3 * Super Street Fighter II - The New Challengers * Sunset Riders - * Top Shooter * Twinkle Tale @@ -145,118 +144,6 @@ Sunset Riders info - title raster effect is broken (bug in Mega Drive code, happens with normal set too) -**************************************************************************** - -Top Shooter PCB info -==================== - - Sun Mixing board, looks like a hacked up Genesis clone. - - Original driver by David Haywood - Inputs by Mariusz Wojcieszek - - Top Shooter - (c)1995 - older board, look more like an actual hacked cart system, has an MCU - -TOP SHOOTER - Sun Mixing Co. Ltd. 1995 - -To me it seems like an original cartridge-based arcade board -hacked to use an external ROM board and a standard JAMMA -connector, but of course, I can be wrong. - - - UPPER BOARD - - _________________________________________________________ - | ___________ ___________ _____ __ | - | 74LS245P |U14 Empty | |U12 ROM1 | |IC1| |B| | - | 74LS245P |__________| |__________| |___| | - | 74LS245P ___________ ___________ _____________ | - __| |U13 Empty | |U11 ROM2 | | AT89C51 | | - |_ J |__________| |__________| |____________| |_ - |_ A ______________________ _____ |_ J - |_ M | U10 MC68000P10 | |OSC| |_ P - |_ M | Motorola | |_ 2 - |_ A |______________________| 74HC00P |_ - |_ 74LS245P ______________________ ________ | - |_ | U9 Empty | |HM6116L | - |_ | | |_______| |_ J - |_ |______________________| |_ P - |_ 74LS245P TD62oo3AP 74LS373P |_ 3 - |_ __________ | - |_ 74LS245P |GALv20V8B| | - |_ ______ | - |_ _____ |DIPS| |_ P - | |U24 | |_ 1 - | 74LS245P | - | TD62oo3AP | - | | - |_ 97 ____________ _____| - |_|_|_|_|_|_|_|_|_|_|_|_|_|_| |_|_|_|_| - - - IC1 = Surface scratched out, don't know what it is - U24 = Surface scratched out, seems like a PROM - DIPs = Fixed as: 00001000 - ROMs = Toshiba TC574000AD - - JP2, JP3 and P1 connects both boards, also another - on-board connector is used, see notes for the 68K socket - for the lower board. - - - LOWER BOARD - - _________________________________________________________ - | ____ ____ | - | ___ | I| | I| | - | |I| | C| | C| | - | |C| | 3| | 2| | - | |1| |__| |__| | - | |3| |__ - | _ _________________________ __| - | |_| ||||||||||||||||||||||||| __| - | IC14 ---------- SLOT --------- __| - | ______________________ __| - | | | __| - | ___ | 68K (to upper board) | _______ __| - | |I| |______________________| |SE-94| __| - | |C| |JDDB | _| - | |1| _______ |_____| | - | |2| |SE-93| IC4 | - | |JDDA | | - | |_____| ___________ |_ - | IC8 |Z8400A PS| | - | |_________| | - | ______ _________ _________ | - | | OSC| | IC11 | | IC7 | | - | _____________ |_______| |_______| | - | RST | | CN5 CN6 | - |___________| |______________________________| - - - IC3 = IC2 = Winbond W24257V - IC7 = 6264LD 9440 - IC11 = SE-95 JDDC - IC12 = Sony CXA1634P - IC13 = Sony CXA1145P - IC14 = GL358 N16 - - RST is a reset button. - - OSC = 53.693175 MHz - - CN5 and CN6 are 9-pin connectors... serial ports? - - There are two wires soldered directly to two connectors - of the slot, going to the upper board (via P1). - - The whole upper board is plugged using the 68000 socket, - there is no 68K on the lower board. - - There is an edge connector, but it isn't JAMMA. - - "HK-986 (KINYO)" is written on the PCB, near the slot. - ****************************************************************************/ #include "emu.h" @@ -274,30 +161,6 @@ void md_boot_state::md_bootleg_map(address_map &map) map(0x200000, 0x2023ff).ram(); // Tested } -void md_boot_state::topshoot_68k_map(address_map &map) -{ - md_bootleg_map(map); - - // these are shared RAM, MCU puts the inputs here - map(0x200042, 0x200043).portr("IN0"); - map(0x200044, 0x200045).portr("IN1"); - map(0x200046, 0x200047).portr("IN2"); - map(0x200048, 0x200049).portr("IN3"); - map(0x200050, 0x200051).r(FUNC(md_boot_state::topshoot_200051_r)); -} - -void md_boot_state::sbubsm_68k_map(address_map &map) -{ - topshoot_68k_map(map); - - // these are shared RAM, MCU puts the inputs here - map(0x20007e, 0x20007f).portr("IN4"); - - // needed to boot, somme kind of hardware ident? - map(0x400000, 0x400001).r(FUNC(md_boot_state::sbubsm_400000_r)); - map(0x400002, 0x400003).r(FUNC(md_boot_state::sbubsm_400002_r)); -} - void md_boot_6button_state::ssf2mdb_68k_map(address_map &map) { megadriv_68k_map(map); @@ -312,6 +175,9 @@ void md_boot_state::megadrvb(machine_config &config) { md_ntsc(config); + ctrl1_3button(config); + ctrl2_3button(config); + m_ioports[2]->set_in_handler(NAME([this] () { return m_io_exp.read_safe(0x3f); })); } @@ -322,20 +188,6 @@ void md_boot_state::md_bootleg(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &md_boot_state::md_bootleg_map); } -void md_boot_state::topshoot(machine_config &config) -{ - megadrvb(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &md_boot_state::topshoot_68k_map); -} - -void md_boot_state::sbubsm(machine_config &config) -{ - megadrvb(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &md_boot_state::sbubsm_68k_map); -} - /************************************* * @@ -450,23 +302,6 @@ uint16_t md_boot_state::dsw_r(offs_t offset) return ioport(dswname[offset])->read(); } -uint16_t md_boot_state::topshoot_200051_r() -{ - return -0x5b; -} - -uint16_t md_boot_state::sbubsm_400000_r() -{ - logerror("%s: sbubsm_400000_r\n", machine().describe_context().c_str()); - return 0x5500; -} - -uint16_t md_boot_state::sbubsm_400002_r() -{ - logerror("%s: sbubsm_400002_r\n", machine().describe_context().c_str()); - return 0x0f00; -} - /************************************* * @@ -784,94 +619,6 @@ INPUT_PORTS_START( srmdb ) PORT_DIPSETTING( 0x00, "6" ) INPUT_PORTS_END -static INPUT_PORTS_START( topshoot ) // Top Shooter Input Ports - PORT_START("PAD1") - PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("PAD2") - PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IN0") - PORT_BIT( 0x4f, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Bet") PORT_IMPULSE(1) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Start") PORT_IMPULSE(1) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Fire") PORT_IMPULSE(1) - - PORT_START("IN1") - PORT_BIT( 0xe7, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_SERVICE_NO_TOGGLE( 0x08, IP_ACTIVE_LOW ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Test mode down") PORT_IMPULSE(1) - - PORT_START("IN2") - PORT_BIT( 0xfd, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(1) - - PORT_START("IN3") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(1) - PORT_BIT( 0xfe, IP_ACTIVE_LOW, IPT_UNKNOWN ) -INPUT_PORTS_END - -static INPUT_PORTS_START( sbubsm ) - PORT_START("PAD1") - PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("PAD2") - PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) - - // the bit ordering in the ports is strange here because this is being read through shared RAM, the MCU presumably reads the real inputs then scrambles them in RAM for the 68k to sort out - PORT_START("IN0") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 ) - - PORT_START("IN1") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IN2") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(1) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IN3") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IN4") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) - - // no service mode here? -INPUT_PORTS_END - INPUT_PORTS_START( barekch ) // TODO: identify dips. PCB has 3 x 8-dip banks, but probably most unused PORT_INCLUDE( md_common ) @@ -1110,11 +857,8 @@ void md_boot_6button_state::megadrvb_6b(machine_config &config) { megadrvb(config); - m_ioports[0]->set_in_handler(FUNC(md_boot_6button_state::ioport_in_6button<0>)); - m_ioports[0]->set_out_handler(FUNC(md_boot_6button_state::ioport_out_6button<0>)); - - m_ioports[1]->set_in_handler(FUNC(md_boot_6button_state::ioport_in_6button<1>)); - m_ioports[1]->set_out_handler(FUNC(md_boot_6button_state::ioport_out_6button<1>)); + ctrl1_6button(config); + ctrl2_6button(config); } void md_boot_6button_state::ssf2mdb(machine_config &config) @@ -1406,25 +1150,6 @@ ROM_START( srmdb ) ROM_LOAD16_BYTE( "u4", 0x040000, 0x020000, CRC(fc2aed41) SHA1(27eb3957f5ed26ee5276523b1df46fa7eb298e1f) ) ROM_END -ROM_START( topshoot ) // Top Shooter (c)1995 Sun Mixing - ROM_REGION( 0x200000, "maincpu", 0 ) - ROM_LOAD16_BYTE( "tc574000ad_u11_2.bin", 0x000000, 0x080000, CRC(b235c4d9) SHA1(fbb308a5f6e769f3277824cb6a3b50c308969ac2) ) - ROM_LOAD16_BYTE( "tc574000ad_u12_1.bin", 0x000001, 0x080000, CRC(e826f6ad) SHA1(23ec8bb608f954d3b915f061e7076c0c63b8259e) ) - - // Not hooked up yet - ROM_REGION( 0x1000, "mcu", 0 ) - ROM_LOAD( "89c51.bin", 0x0000, 0x1000, CRC(595475c8) SHA1(8313819ba06cc92b54f88c1ca9f34be8d1ec94d0) ) -ROM_END - -ROM_START( sbubsm ) - ROM_REGION( 0x200000, "maincpu", 0 ) - ROM_LOAD16_BYTE( "u11.bin", 0x000000, 0x080000, CRC(4f9337ea) SHA1(b245eb615f80afd25e29b2efdddb7f61c1deff6b) ) - ROM_LOAD16_BYTE( "u12.bin", 0x000001, 0x080000, CRC(f5374835) SHA1(3a97910f5f7327ec7ad6425dfdfa72c86196ed33) ) - - ROM_REGION( 0x1000, "mcu", 0 ) // could be the same as topshoot (same PCB) - ROM_LOAD( "89c51.bin", 0x0000, 0x1000, NO_DUMP ) -ROM_END - ROM_START( sonic2mb ) ROM_REGION( 0x400000, "maincpu", 0 ) // 68000 Code ROM_LOAD16_BYTE( "m1", 0x000001, 0x080000, CRC(7b40aa24) SHA1(247882cd1f412366d61aeb4d85bbeefd5f108e1d) ) @@ -1523,8 +1248,6 @@ GAME( 1993, aladmdb, 0, megadrvb, aladmdb, md_boot_state, init_ala GAME( 1996, mk3mdb, 0, megadrvb_6b, mk3mdb, md_boot_6button_state, init_mk3mdb, ROT0, "bootleg / Midway", "Mortal Kombat 3 (bootleg of Mega Drive version)", 0 ) GAME( 1994, ssf2mdb, 0, ssf2mdb, ssf2mdb, md_boot_6button_state, init_megadrij, ROT0, "bootleg / Capcom", "Super Street Fighter II - The New Challengers (bootleg of Japanese Mega Drive version)", 0 ) GAME( 1993, srmdb, 0, megadrvb, srmdb, md_boot_state, init_srmdb, ROT0, "bootleg / Konami", "Sunset Riders (bootleg of Mega Drive version)", 0 ) -GAME( 1995, topshoot, 0, topshoot, topshoot, md_boot_state, init_megadriv, ROT0, "Sun Mixing", "Top Shooter", 0 ) -GAME( 1996, sbubsm, 0, sbubsm, sbubsm, md_boot_state, init_megadriv, ROT0, "Sun Mixing", "Super Bubble Bobble (Sun Mixing, Mega Drive clone hardware)", 0 ) GAME( 1993, sonic2mb, 0, md_bootleg, sonic2mb, md_boot_state, init_sonic2mb, ROT0, "bootleg / Sega", "Sonic The Hedgehog 2 (bootleg of Mega Drive version)", 0 ) // Flying wires going through the empty PIC space aren't completely understood GAME( 1993, sonic3mb, 0, md_bootleg, sonic3mb, md_sonic3bl_state, init_sonic3mb, ROT0, "bootleg / Sega", "Sonic The Hedgehog 3 (bootleg of Mega Drive version)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // undumped PIC GAME( 1994, barek2mb, 0, md_bootleg, barek2, md_boot_state, init_barek2, ROT0, "bootleg / Sega", "Bare Knuckle II (bootleg of Mega Drive version)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // Needs PIC hook up diff --git a/src/mame/sega/megadriv_acbl.h b/src/mame/sega/megadriv_acbl.h index 87036021190..11496a4c610 100644 --- a/src/mame/sega/megadriv_acbl.h +++ b/src/mame/sega/megadriv_acbl.h @@ -6,18 +6,16 @@ #include "megadriv.h" -class md_boot_state : public md_base_state +class md_boot_state : public md_ctrl_state { public: md_boot_state(const machine_config &mconfig, device_type type, const char *tag) : - md_base_state(mconfig, type, tag), + md_ctrl_state(mconfig, type, tag), m_io_exp(*this, "EXP") { } void megadrvb(machine_config &config); void md_bootleg(machine_config &config); - void topshoot(machine_config &config); - void sbubsm(machine_config &config); void init_aladmdb(); void init_srmdb(); @@ -39,12 +37,6 @@ private: uint16_t barek2mb_r(); uint16_t jparkmb_r(); uint16_t twinktmb_r(); - uint16_t topshoot_200051_r(); - uint16_t sbubsm_400000_r(); - uint16_t sbubsm_400002_r(); - - void topshoot_68k_map(address_map &map); - void sbubsm_68k_map(address_map &map); optional_ioport m_io_exp; diff --git a/src/mame/sega/megadriv_rad.cpp b/src/mame/sega/megadriv_rad.cpp index 9e878b3fdbc..5a589d9e62a 100644 --- a/src/mame/sega/megadriv_rad.cpp +++ b/src/mame/sega/megadriv_rad.cpp @@ -20,7 +20,99 @@ */ #include "emu.h" -#include "megadriv_rad.h" +#include "megadriv.h" + + +namespace { + +class megadriv_radica_state_base : public md_ctrl_state +{ +public: + megadriv_radica_state_base(const machine_config &mconfig, device_type type, const char *tag) : + md_ctrl_state(mconfig, type, tag), + m_bank(0), + m_romsize(0x400000), + m_rom(*this, "maincpu") + { } + +protected: + uint16_t read(offs_t offset); + uint16_t read_a13(offs_t offset); + + void megadriv_radica_map(address_map &map); + + void radica_base_map(address_map &map); + + int m_bank; + int m_romsize; + +private: + required_region_ptr m_rom; +}; + + +class megadriv_radica_state : public megadriv_radica_state_base +{ +public: + megadriv_radica_state(const machine_config& mconfig, device_type type, const char* tag) : + megadriv_radica_state_base(mconfig, type, tag) + { } + + void megadriv_radica_3button_ntsc(machine_config &config); + void megadriv_radica_3button_pal(machine_config &config); + + void megadriv_radica_6button_ntsc(machine_config &config); + void megadriv_radica_6button_pal(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; +}; + + +class megadriv_dgunl_state : public megadriv_radica_state +{ +public: + megadriv_dgunl_state(const machine_config& mconfig, device_type type, const char* tag) : + megadriv_radica_state(mconfig, type, tag) + { } + + void megadriv_dgunl_ntsc(machine_config &config); + + void init_dgunl3227(); + +protected: + virtual void machine_start() override; + + uint16_t m_a1630a = 0; + +private: + uint16_t read_a16300(offs_t offset, uint16_t mem_mask); + uint16_t read_a16302(offs_t offset, uint16_t mem_mask); + virtual void write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask); + + void megadriv_dgunl_map(address_map &map); +}; + + +class megadriv_ra145_state : public megadriv_dgunl_state +{ +public: + megadriv_ra145_state(const machine_config& mconfig, device_type type, const char* tag) : + megadriv_dgunl_state(mconfig, type, tag) + { } + + void megadriv_ra145_ntsc(machine_config &config); + + void init_ra145(); + +protected: + virtual void machine_reset() override; + +private: + virtual void write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask) override; +}; + void megadriv_radica_state_base::radica_base_map(address_map &map) @@ -368,13 +460,13 @@ void megadriv_dgunl_state::machine_start() void megadriv_ra145_state::machine_reset() { m_bank = 4; - md_base_state::machine_reset(); + megadriv_radica_state_base::machine_reset(); } void megadriv_radica_state::machine_reset() { m_bank = 0; - md_base_state::machine_reset(); + megadriv_radica_state_base::machine_reset(); } @@ -382,42 +474,45 @@ void megadriv_radica_state::megadriv_radica_3button_ntsc(machine_config &config) { md_ntsc(config); - m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state_base::megadriv_radica_map); + ctrl1_3button(config); + ctrl2_3button(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); } void megadriv_radica_state::megadriv_radica_3button_pal(machine_config &config) { md_pal(config); - m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state_base::megadriv_radica_map); + ctrl1_3button(config); + ctrl2_3button(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); } void megadriv_radica_state::megadriv_radica_6button_pal(machine_config &config) { megadriv_radica_3button_pal(config); - m_ioports[0]->set_in_handler(FUNC(megadriv_radica_state::ioport_in_6button<0>)); - m_ioports[0]->set_out_handler(FUNC(megadriv_radica_state::ioport_out_6button<0>)); - - m_ioports[1]->set_in_handler(FUNC(megadriv_radica_state::ioport_in_6button<1>)); - m_ioports[1]->set_out_handler(FUNC(megadriv_radica_state::ioport_out_6button<1>)); + ctrl1_6button(config); + ctrl2_6button(config); } void megadriv_radica_state::megadriv_radica_6button_ntsc(machine_config &config) { megadriv_radica_3button_ntsc(config); - m_ioports[0]->set_in_handler(FUNC(megadriv_radica_state::ioport_in_6button<0>)); - m_ioports[0]->set_out_handler(FUNC(megadriv_radica_state::ioport_out_6button<0>)); - - m_ioports[1]->set_in_handler(FUNC(megadriv_radica_state::ioport_in_6button<1>)); - m_ioports[1]->set_out_handler(FUNC(megadriv_radica_state::ioport_out_6button<1>)); + ctrl1_6button(config); + ctrl2_6button(config); } void megadriv_dgunl_state::megadriv_dgunl_ntsc(machine_config &config) { md_ntsc(config); + ctrl1_3button(config); + ctrl2_3button(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_dgunl_state::megadriv_dgunl_map); } @@ -425,11 +520,8 @@ void megadriv_ra145_state::megadriv_ra145_ntsc(machine_config &config) { megadriv_dgunl_ntsc(config); - m_ioports[0]->set_in_handler(FUNC(megadriv_ra145_state::ioport_in_6button<0>)); - m_ioports[0]->set_out_handler(FUNC(megadriv_ra145_state::ioport_out_6button<0>)); - - m_ioports[1]->set_in_handler(FUNC(megadriv_ra145_state::ioport_in_6button<1>)); - m_ioports[1]->set_out_handler(FUNC(megadriv_ra145_state::ioport_out_6button<1>)); + ctrl1_6button(config); + ctrl2_6button(config); } @@ -612,6 +704,9 @@ void megadriv_ra145_state::init_ra145() init_megadriv(); } +} // anonymous namespace + + // US versions show 'Genesis' on the menu, show a www.radicagames.com splash screen, and use NTSC versions of the ROMs, sometimes region locked // EU versions show 'Mega Drive' on the menu, show a www.radicagames.com splash screen, and use PAL versions of the ROMs, sometimes region locked // UK versions show "Mega Drive' on the menu, show a www.radicauk.com splash screen, and use PAL versions of the ROMs, sometimes region locked @@ -657,4 +752,3 @@ CONS( 2018, msi_sf2, 0, 0, megadriv_radica_6button_ntsc, msi_6button, CONS( 2018, dgunl3227, 0, 0, megadriv_dgunl_ntsc, dgunl_1player, megadriv_dgunl_state, init_dgunl3227, "dreamGEAR", "My Arcade Pac-Man Pocket Player (DGUNL-3227)", 0 ) CONS( 2018, ra145, 0, 0, megadriv_ra145_ntsc, msi_6button, megadriv_ra145_state, init_ra145, "", "Retro Arcade 16 Bits Classic Edition Mini TV Game Console - 145 Classic Games - TV Arcade Plug and Play (Mega Drive bootlegs)", MACHINE_NOT_WORKING ) - diff --git a/src/mame/sega/megadriv_rad.h b/src/mame/sega/megadriv_rad.h deleted file mode 100644 index 9d43a31eb4e..00000000000 --- a/src/mame/sega/megadriv_rad.h +++ /dev/null @@ -1,100 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood - -#ifndef MAME_INCLUDES_MEGADRIV_RAD_H -#define MAME_INCLUDES_MEGADRIV_RAD_H - -#pragma once - -#include "megadriv.h" - - -class megadriv_radica_state_base : public md_base_state -{ -public: - megadriv_radica_state_base(const machine_config &mconfig, device_type type, const char *tag) : - md_base_state(mconfig, type, tag), - m_bank(0), - m_romsize(0x400000), - m_rom(*this, "maincpu") - { } - - uint16_t read(offs_t offset); - uint16_t read_a13(offs_t offset); - - void megadriv_radica_map(address_map &map); - -protected: - void radica_base_map(address_map &map); - int m_bank; - int m_romsize; - -private: - required_region_ptr m_rom; -}; - - -class megadriv_radica_state : public megadriv_radica_state_base -{ -public: - megadriv_radica_state(const machine_config& mconfig, device_type type, const char* tag) : - megadriv_radica_state_base(mconfig, type, tag) - { } - - void megadriv_radica_3button_ntsc(machine_config &config); - void megadriv_radica_3button_pal(machine_config &config); - - void megadriv_radica_6button_ntsc(machine_config &config); - void megadriv_radica_6button_pal(machine_config &config); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; -}; - - -class megadriv_dgunl_state : public megadriv_radica_state -{ -public: - megadriv_dgunl_state(const machine_config& mconfig, device_type type, const char* tag) : - megadriv_radica_state(mconfig, type, tag) - { } - - void megadriv_dgunl_ntsc(machine_config &config); - - void init_dgunl3227(); - -protected: - virtual void machine_start() override; - - uint16_t m_a1630a = 0; - -private: - uint16_t read_a16300(offs_t offset, uint16_t mem_mask); - uint16_t read_a16302(offs_t offset, uint16_t mem_mask); - virtual void write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask); - - void megadriv_dgunl_map(address_map &map); -}; - - -class megadriv_ra145_state : public megadriv_dgunl_state -{ -public: - megadriv_ra145_state(const machine_config& mconfig, device_type type, const char* tag) : - megadriv_dgunl_state(mconfig, type, tag) - { } - - void megadriv_ra145_ntsc(machine_config &config); - - void init_ra145(); - -protected: - virtual void machine_reset() override; - -private: - virtual void write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask) override; -}; - - -#endif // MAME_INCLUDES_MEGADRIV_RAD_H diff --git a/src/mame/sega/megadriv_sunmix.cpp b/src/mame/sega/megadriv_sunmix.cpp new file mode 100644 index 00000000000..87c3a3cdcae --- /dev/null +++ b/src/mame/sega/megadriv_sunmix.cpp @@ -0,0 +1,340 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +/*************************************************************************** + + Sega Mega Drive/Genesis-based bootlegs + + Games supported: + * Top Shooter + +Top Shooter PCB info +==================== + + Sun Mixing board, looks like a hacked up Genesis clone. + + Original driver by David Haywood + Inputs by Mariusz Wojcieszek + + Top Shooter - (c)1995 - older board, look more like an actual hacked cart system, has an MCU + +TOP SHOOTER - Sun Mixing Co. Ltd. 1995 + +To me it seems like an original cartridge-based arcade board +hacked to use an external ROM board and a standard JAMMA +connector, but of course, I can be wrong. + + + UPPER BOARD + + _________________________________________________________ + | ___________ ___________ _____ __ | + | 74LS245P |U14 Empty | |U12 ROM1 | |IC1| |B| | + | 74LS245P |__________| |__________| |___| | + | 74LS245P ___________ ___________ _____________ | + __| |U13 Empty | |U11 ROM2 | | AT89C51 | | + |_ J |__________| |__________| |____________| |_ + |_ A ______________________ _____ |_ J + |_ M | U10 MC68000P10 | |OSC| |_ P + |_ M | Motorola | |_ 2 + |_ A |______________________| 74HC00P |_ + |_ 74LS245P ______________________ ________ | + |_ | U9 Empty | |HM6116L | + |_ | | |_______| |_ J + |_ |______________________| |_ P + |_ 74LS245P TD62oo3AP 74LS373P |_ 3 + |_ __________ | + |_ 74LS245P |GALv20V8B| | + |_ ______ | + |_ _____ |DIPS| |_ P + | |U24 | |_ 1 + | 74LS245P | + | TD62oo3AP | + | | + |_ 97 ____________ _____| + |_|_|_|_|_|_|_|_|_|_|_|_|_|_| |_|_|_|_| + + + IC1 = Surface scratched out, don't know what it is + U24 = Surface scratched out, seems like a PROM + DIPs = Fixed as: 00001000 + ROMs = Toshiba TC574000AD + + JP2, JP3 and P1 connects both boards, also another + on-board connector is used, see notes for the 68K socket + for the lower board. + + + LOWER BOARD + + _________________________________________________________ + | ____ ____ | + | ___ | I| | I| | + | |I| | C| | C| | + | |C| | 3| | 2| | + | |1| |__| |__| | + | |3| |__ + | _ _________________________ __| + | |_| ||||||||||||||||||||||||| __| + | IC14 ---------- SLOT --------- __| + | ______________________ __| + | | | __| + | ___ | 68K (to upper board) | _______ __| + | |I| |______________________| |SE-94| __| + | |C| |JDDB | _| + | |1| _______ |_____| | + | |2| |SE-93| IC4 | + | |JDDA | | + | |_____| ___________ |_ + | IC8 |Z8400A PS| | + | |_________| | + | ______ _________ _________ | + | | OSC| | IC11 | | IC7 | | + | _____________ |_______| |_______| | + | RST | | CN5 CN6 | + |___________| |______________________________| + + + IC3 = IC2 = Winbond W24257V + IC7 = 6264LD 9440 + IC11 = SE-95 JDDC + IC12 = Sony CXA1634P + IC13 = Sony CXA1145P + IC14 = GL358 N16 + + RST is a reset button. + + OSC = 53.693175 MHz + + CN5 and CN6 are 9-pin connectors... serial ports? + + There are two wires soldered directly to two connectors + of the slot, going to the upper board (via P1). + + The whole upper board is plugged using the 68000 socket, + there is no 68K on the lower board. + + There is an edge connector, but it isn't JAMMA. + + "HK-986 (KINYO)" is written on the PCB, near the slot. + +****************************************************************************/ + +#include "emu.h" +#include "megadriv.h" + + +namespace { + +class md_sunmixing_state : public md_base_state +{ +public: + md_sunmixing_state(machine_config const &mconfig, device_type type, char const *tag) : + md_base_state(mconfig, type, tag) + { + } + + void topshoot(machine_config &config); + void sbubsm(machine_config &config); + +private: + void topshoot_68k_map(address_map &map); + void sbubsm_68k_map(address_map &map); + + uint16_t topshoot_200051_r(); + uint16_t sbubsm_400000_r(); + uint16_t sbubsm_400002_r(); +}; + + +/************************************* + * + * Machine Configuration + * + *************************************/ + +void md_sunmixing_state::topshoot(machine_config &config) +{ + md_ntsc(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &md_sunmixing_state::topshoot_68k_map); +} + +void md_sunmixing_state::sbubsm(machine_config &config) +{ + md_ntsc(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &md_sunmixing_state::sbubsm_68k_map); +} + + +void md_sunmixing_state::topshoot_68k_map(address_map &map) +{ + megadriv_68k_base_map(map); + + map(0x000000, 0x1fffff).rom(); // Cartridge Program ROM + map(0x200000, 0x2023ff).ram(); // Tested + + // these are shared RAM, MCU puts the inputs here + map(0x200042, 0x200043).portr("IN0"); + map(0x200044, 0x200045).portr("IN1"); + map(0x200046, 0x200047).portr("IN2"); + map(0x200048, 0x200049).portr("IN3"); + map(0x200050, 0x200051).r(FUNC(md_sunmixing_state::topshoot_200051_r)); +} + +void md_sunmixing_state::sbubsm_68k_map(address_map &map) +{ + topshoot_68k_map(map); + + // these are shared RAM, MCU puts the inputs here + map(0x20007e, 0x20007f).portr("IN4"); + + // needed to boot, somme kind of hardware ident? + map(0x400000, 0x400001).r(FUNC(md_sunmixing_state::sbubsm_400000_r)); + map(0x400002, 0x400003).r(FUNC(md_sunmixing_state::sbubsm_400002_r)); +} + + +/************************************* + * + * Games memory handlers + * + *************************************/ + +uint16_t md_sunmixing_state::topshoot_200051_r() +{ + return -0x5b; +} + +uint16_t md_sunmixing_state::sbubsm_400000_r() +{ + logerror("%s: sbubsm_400000_r\n", machine().describe_context().c_str()); + return 0x5500; +} + +uint16_t md_sunmixing_state::sbubsm_400002_r() +{ + logerror("%s: sbubsm_400002_r\n", machine().describe_context().c_str()); + return 0x0f00; +} + + +/************************************* + * + * Game-specific port definitions + * + *************************************/ + +static INPUT_PORTS_START( topshoot ) // Top Shooter Input Ports + PORT_START("IN0") + PORT_BIT( 0x4f, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Bet") PORT_IMPULSE(1) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Start") PORT_IMPULSE(1) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Fire") PORT_IMPULSE(1) + + PORT_START("IN1") + PORT_BIT( 0xe7, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_SERVICE_NO_TOGGLE( 0x08, IP_ACTIVE_LOW ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Test mode down") PORT_IMPULSE(1) + + PORT_START("IN2") + PORT_BIT( 0xfd, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(1) + + PORT_START("IN3") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(1) + PORT_BIT( 0xfe, IP_ACTIVE_LOW, IPT_UNKNOWN ) +INPUT_PORTS_END + +static INPUT_PORTS_START( sbubsm ) + // the bit ordering in the ports is strange here because this is being read through shared RAM, the MCU presumably reads the real inputs then scrambles them in RAM for the 68k to sort out + PORT_START("IN0") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 ) + + PORT_START("IN1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("IN2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(1) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("IN3") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("IN4") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + // no service mode here? +INPUT_PORTS_END + + +/************************************* + * + * ROM definitions + * + *************************************/ + +ROM_START( topshoot ) // Top Shooter (c)1995 Sun Mixing + ROM_REGION( 0x200000, "maincpu", 0 ) + ROM_LOAD16_BYTE( "tc574000ad_u11_2.bin", 0x000000, 0x080000, CRC(b235c4d9) SHA1(fbb308a5f6e769f3277824cb6a3b50c308969ac2) ) + ROM_LOAD16_BYTE( "tc574000ad_u12_1.bin", 0x000001, 0x080000, CRC(e826f6ad) SHA1(23ec8bb608f954d3b915f061e7076c0c63b8259e) ) + + // Not hooked up yet + ROM_REGION( 0x1000, "mcu", 0 ) + ROM_LOAD( "89c51.bin", 0x0000, 0x1000, CRC(595475c8) SHA1(8313819ba06cc92b54f88c1ca9f34be8d1ec94d0) ) +ROM_END + +ROM_START( sbubsm ) + ROM_REGION( 0x200000, "maincpu", 0 ) + ROM_LOAD16_BYTE( "u11.bin", 0x000000, 0x080000, CRC(4f9337ea) SHA1(b245eb615f80afd25e29b2efdddb7f61c1deff6b) ) + ROM_LOAD16_BYTE( "u12.bin", 0x000001, 0x080000, CRC(f5374835) SHA1(3a97910f5f7327ec7ad6425dfdfa72c86196ed33) ) + + ROM_REGION( 0x1000, "mcu", 0 ) // could be the same as topshoot (same PCB) + ROM_LOAD( "89c51.bin", 0x0000, 0x1000, NO_DUMP ) +ROM_END + +} // anonymous namespace + + +/************************************* + * + * Game drivers + * + *************************************/ + +GAME( 1995, topshoot, 0, topshoot, topshoot, md_sunmixing_state, init_megadriv, ROT0, "Sun Mixing", "Top Shooter", 0 ) +GAME( 1996, sbubsm, 0, sbubsm, sbubsm, md_sunmixing_state, init_megadriv, ROT0, "Sun Mixing", "Super Bubble Bobble (Sun Mixing, Mega Drive clone hardware)", 0 ) diff --git a/src/mame/sega/megadriv_sunplus_hybrid.cpp b/src/mame/sega/megadriv_sunplus_hybrid.cpp index cfe41e3d4c2..9c6ce401577 100644 --- a/src/mame/sega/megadriv_sunplus_hybrid.cpp +++ b/src/mame/sega/megadriv_sunplus_hybrid.cpp @@ -16,12 +16,14 @@ #include "emu.h" #include "megadriv.h" -class megadriv_sunplus_state : public md_base_state +namespace { + +class megadriv_sunplus_state : public md_ctrl_state { public: megadriv_sunplus_state(const machine_config &mconfig, device_type type, const char *tag) : // Mega Drive part - md_base_state(mconfig, type, tag), + md_ctrl_state(mconfig, type, tag), m_md_is_running(true), m_bank(0), m_rom(*this, "maincpu") @@ -30,7 +32,6 @@ public: // Mega Drive part uint16_t read(offs_t offset); void megadriv_sunplus_pal(machine_config &config); - void megadriv_sunplus_map(address_map &map); void init_reactmd(); @@ -44,9 +45,11 @@ private: // Mega Drive part int m_bank; required_region_ptr m_rom; + uint32_t screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); DECLARE_WRITE_LINE_MEMBER(screen_vblank_hybrid); + void megadriv_sunplus_map(address_map &map); }; @@ -87,7 +90,7 @@ INPUT_PORTS_END void megadriv_sunplus_state::machine_start() { logerror("megadriv_sunplus_state::machine_start\n"); - md_base_state::machine_start(); + md_ctrl_state::machine_start(); m_vdp->stop_timers(); save_item(NAME(m_bank)); @@ -96,7 +99,7 @@ void megadriv_sunplus_state::machine_start() void megadriv_sunplus_state::machine_reset() { logerror("megadriv_sunplus_state::machine_reset\n"); - md_base_state::machine_reset(); + md_ctrl_state::machine_reset(); } uint32_t megadriv_sunplus_state::screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) @@ -115,7 +118,7 @@ WRITE_LINE_MEMBER(megadriv_sunplus_state::screen_vblank_hybrid) if (m_md_is_running) { /* Used to Sync the timing */ - md_base_state::screen_vblank_megadriv(state); + md_ctrl_state::screen_vblank_megadriv(state); } } @@ -123,10 +126,14 @@ WRITE_LINE_MEMBER(megadriv_sunplus_state::screen_vblank_hybrid) void megadriv_sunplus_state::megadriv_sunplus_pal(machine_config &config) { md_pal(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_sunplus_state::megadriv_sunplus_map); m_screen->set_screen_update(FUNC(megadriv_sunplus_state::screen_update_hybrid)); m_screen->screen_vblank().set(FUNC(megadriv_sunplus_state::screen_vblank_hybrid)); + + ctrl1_3button(config); + ctrl2_3button(config); } @@ -156,6 +163,8 @@ ROM_START( reactmd ) ROM_IGNORE(0x4000000) // the 2nd half of the ROM can't be accessed by the PCB (address line tied low) (contains garbage? data) ROM_END +} // anonymous namespace + // Two systems in one unit - Genesis on a Chip and SunPlus, only the SunPlus part is currently emulated. Genesis on a chip is a very poor implementation with many issues on real hardware. // This should actually boot to a menu on the MD side, with the SunPlus only being enabled if selected from that menu. MD side menu runs in some enhanced / custom MD mode though. diff --git a/src/mame/sega/megadriv_vt_hybrid.cpp b/src/mame/sega/megadriv_vt_hybrid.cpp index d51d881f312..f80845911aa 100644 --- a/src/mame/sega/megadriv_vt_hybrid.cpp +++ b/src/mame/sega/megadriv_vt_hybrid.cpp @@ -17,12 +17,12 @@ namespace { -class megadriv_vt0203_state : public md_base_state +class megadriv_vt0203_state : public md_ctrl_state { public: megadriv_vt0203_state(const machine_config &mconfig, device_type type, const char *tag) : // Mega Drive part - md_base_state(mconfig, type, tag), + md_ctrl_state(mconfig, type, tag), m_md_is_running(true), m_bank(0), m_rom(*this, "maincpu") @@ -31,7 +31,6 @@ public: // Mega Drive part uint16_t read(offs_t offset); void megadriv_vt0203_pal(machine_config &config); - void megadriv_vt0203_map(address_map &map); protected: virtual void machine_start() override; @@ -43,9 +42,11 @@ private: // Mega Drive part int m_bank; required_region_ptr m_rom; + uint32_t screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); DECLARE_WRITE_LINE_MEMBER(screen_vblank_hybrid); + void megadriv_vt0203_map(address_map &map); }; @@ -92,7 +93,7 @@ INPUT_PORTS_END void megadriv_vt0203_state::machine_start() { logerror("megadriv_vt0203_state::machine_start\n"); - md_base_state::machine_start(); + md_ctrl_state::machine_start(); m_vdp->stop_timers(); save_item(NAME(m_bank)); @@ -101,7 +102,7 @@ void megadriv_vt0203_state::machine_start() void megadriv_vt0203_state::machine_reset() { logerror("megadriv_vt0203_state::machine_reset\n"); - md_base_state::machine_reset(); + md_ctrl_state::machine_reset(); } uint32_t megadriv_vt0203_state::screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) @@ -120,7 +121,7 @@ WRITE_LINE_MEMBER(megadriv_vt0203_state::screen_vblank_hybrid) if (m_md_is_running) { /* Used to Sync the timing */ - md_base_state::screen_vblank_megadriv(state); + md_ctrl_state::screen_vblank_megadriv(state); } } @@ -128,11 +129,15 @@ WRITE_LINE_MEMBER(megadriv_vt0203_state::screen_vblank_hybrid) void megadriv_vt0203_state::megadriv_vt0203_pal(machine_config &config) { md_pal(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_vt0203_state::megadriv_vt0203_map); m_screen->set_screen_update(FUNC(megadriv_vt0203_state::screen_update_hybrid)); m_screen->screen_vblank().set(FUNC(megadriv_vt0203_state::screen_vblank_hybrid)); + ctrl1_3button(config); + ctrl2_3button(config); + // TODO: add the VT part, this might require refactoring of the VT stuff as the SoC currently contains the screen // but instead we'll need to use a shared screen that is reconfigured depending on which part is enabled } diff --git a/src/mame/sega/megaplay.cpp b/src/mame/sega/megaplay.cpp index 39a14efc029..4c6b29b7b01 100644 --- a/src/mame/sega/megaplay.cpp +++ b/src/mame/sega/megaplay.cpp @@ -36,17 +36,20 @@ this reason. #include "cpu/z80/z80.h" #include "machine/cxd1095.h" + +namespace { + #define MASTER_CLOCK 53693100 #define MP_ROM 1 #define MP_GAME 0 -class mplay_state : public md_base_state +class mplay_state : public md_ctrl_state { public: mplay_state(const machine_config &mconfig, device_type type, const char *tag) : - md_base_state(mconfig, type, tag), + md_ctrl_state(mconfig, type, tag), m_ic3_ram(*this, "ic3_ram"), m_vdp1(*this, "vdp1"), m_bioscpu(*this, "mtbios") @@ -429,6 +432,7 @@ void mplay_state::bios_gamesel_w(uint8_t data) void mplay_state::mp_io_exp_out(uint8_t data, uint8_t mem_mask) { + // TODO: TH (bit 6) is configured as an output and seems to be used for something, too m_io_exp_data = (data & 0x07) | (m_io_exp_data & 0xf8); } @@ -650,7 +654,7 @@ void mplay_state::machine_reset() m_bios_mode = MP_ROM; m_bios_bank_addr = 0; m_readpos = 1; - md_base_state::machine_reset(); + md_ctrl_state::machine_reset(); } void mplay_state::megaplay(machine_config &config) @@ -658,6 +662,10 @@ void mplay_state::megaplay(machine_config &config) // basic machine hardware md_ntsc(config); + // integrated 3-button controllers + ctrl1_3button(config); + ctrl2_3button(config); + // for now ... m_ioports[2]->set_in_handler(FUNC(mplay_state::mp_io_exp_in)); m_ioports[2]->set_out_handler(FUNC(mplay_state::mp_io_exp_out)); @@ -971,6 +979,9 @@ void mplay_state::init_megaplay() m_maincpu->space(AS_PROGRAM).install_write_handler(0xa02000, 0xa03fff, write16s_delegate(*this, FUNC(mplay_state::extra_ram_w))); } +} // anonymous namespace + + /* Sega Mega Play Cartridges ------------------------- diff --git a/src/mame/sega/megatech.cpp b/src/mame/sega/megatech.cpp index 13dfca65ad4..70b13811916 100644 --- a/src/mame/sega/megatech.cpp +++ b/src/mame/sega/megatech.cpp @@ -93,11 +93,11 @@ Sonic Hedgehog 2 171-6215A 837-6963-62 610-0239-62 MPR namespace { -class mtech_state : public md_base_state +class mtech_state : public md_ctrl_state { public: mtech_state(const machine_config &mconfig, device_type type, const char *tag) : - md_base_state(mconfig, type, tag), + md_ctrl_state(mconfig, type, tag), m_vdp1(*this, "vdp1"), m_cart1(*this, "mt_slot1"), m_cart2(*this, "mt_slot2"), @@ -652,7 +652,7 @@ WRITE_LINE_MEMBER(mtech_state::screen_vblank_main) void mtech_state::machine_start() { - md_base_state::machine_start(); + md_ctrl_state::machine_start(); m_alarm_sound.resolve(); m_flash_screen.resolve(); @@ -661,7 +661,7 @@ void mtech_state::machine_start() void mtech_state::machine_reset() { m_mt_bank_addr = 0; - md_base_state::machine_reset(); + md_ctrl_state::machine_reset(); for (int i = 0; i < 8; i++) m_cart_reg[i] = nullptr; @@ -697,10 +697,14 @@ uint32_t mtech_state::screen_update_menu(screen_device &screen, bitmap_rgb32 &bi void mtech_state::megatech(machine_config &config) { - /* basic machine hardware */ + // basic machine hardware md_ntsc(config); - /* Megatech has an extra SMS based bios *and* an additional screen */ + // integrated 3-button controllers + ctrl1_3button(config); + ctrl2_3button(config); + + // Megatech has an extra SMS-based BIOS *and* an additional screen Z80(config, m_bioscpu, MASTER_CLOCK / 15); /* ?? */ m_bioscpu->set_addrmap(AS_PROGRAM, &mtech_state::megatech_bios_map); m_bioscpu->set_addrmap(AS_IO, &mtech_state::megatech_bios_portmap); diff --git a/src/mame/sega/puckpkmn.cpp b/src/mame/sega/puckpkmn.cpp index b71c7ded2ba..54f5592f0bf 100644 --- a/src/mame/sega/puckpkmn.cpp +++ b/src/mame/sega/puckpkmn.cpp @@ -52,13 +52,18 @@ Notes: #include "sound/sn76496.h" #include "sound/ymopn.h" +#include "speaker.h" + namespace { -class puckpkmn_state : public md_base_state +class puckpkmn_state : public md_core_state { public: - using md_base_state::md_base_state; + puckpkmn_state(const machine_config &mconfig, device_type type, const char *tag) : + md_core_state(mconfig, type, tag) + { + } void puckpkmn(machine_config &config) ATTR_COLD; void puckpkmna(machine_config &config) ATTR_COLD; @@ -266,7 +271,7 @@ void puckpkmn_state::puckpkmn_base_map(address_map &map) map(0x700016, 0x700017).portr("DSW1"); map(0x700018, 0x700019).portr("DSW2"); map(0x700023, 0x700023).rw("oki", FUNC(okim6295_device::read), FUNC(okim6295_device::write)); - map(0xa04000, 0xa04003).rw(FUNC(puckpkmn_state::megadriv_68k_YM2612_read), FUNC(puckpkmn_state::megadriv_68k_YM2612_write)); + map(0xa04000, 0xa04003).rw(m_ymsnd, FUNC(ym_generic_device::read), FUNC(ym_generic_device::write)); map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000); @@ -390,11 +395,19 @@ uint16_t jzth_state::bl_710000_r() void puckpkmn_state::puckpkmn(machine_config &config) { - md_ntsc(config); + md_core_ntsc(config); m_maincpu->set_addrmap(AS_PROGRAM, &puckpkmn_state::puckpkmn_map); - config.device_remove("genesis_snd_z80"); + m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50); + m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50); + + // sound hardware + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + m_ymsnd->add_route(0, "lspeaker", 0.50); + m_ymsnd->add_route(1, "rspeaker", 0.50); okim6295_device &oki(OKIM6295(config, "oki", XTAL(4'000'000) / 4, okim6295_device::PIN7_HIGH)); oki.add_route(ALL_OUTPUTS, "lspeaker", 0.25); @@ -513,7 +526,13 @@ void puckpkmn_state::init_puckpkmn() for (size_t i = 0; i < len; i++) rom[i] = bitswap<8>(rom[i], 1, 4, 2, 0, 7, 5, 3, 6); - init_megadriv(); + m_maincpu->set_tas_write_callback(*this, FUNC(puckpkmn_state::megadriv_tas_callback)); + + // TODO: move this to the device interface? + m_vdp->set_use_cram(1); + m_vdp->set_vdp_pal(false); + m_vdp->set_framerate(60); + m_vdp->set_total_scanlines(262); } ROM_START( puckpkmn ) /* Puckman Pockimon (c)2000 Genie */ diff --git a/src/mame/sega/sms.cpp b/src/mame/sega/sms.cpp index 6c091f0935d..1584e2797c6 100644 --- a/src/mame/sega/sms.cpp +++ b/src/mame/sega/sms.cpp @@ -297,20 +297,22 @@ void smssdisp_state::sms_store_mem(address_map &map) } // I/O ports $3E and $3F do not exist on Mark III -void sms_state::sg1000m3_io(address_map &map) +void sg1000m3_state::sg1000m3_io(address_map &map) { map.global_mask(0xff); map.unmap_value_high(); - map(0x40, 0x7f).r(FUNC(sms_state::sms_count_r)).w(m_vdp, FUNC(sega315_5124_device::psg_w)); + + map(0x40, 0x7f).r(FUNC(sg1000m3_state::sms_count_r)).w(m_vdp, FUNC(sega315_5124_device::psg_w)); map(0x80, 0x80).mirror(0x3e).rw(m_vdp, FUNC(sega315_5124_device::data_read), FUNC(sega315_5124_device::data_write)); map(0x81, 0x81).mirror(0x3e).rw(m_vdp, FUNC(sega315_5124_device::control_read), FUNC(sega315_5124_device::control_write)); - map(0xc0, 0xc7).mirror(0x38).rw(FUNC(sms_state::sg1000m3_peripheral_r), FUNC(sms_state::sg1000m3_peripheral_w)); + map(0xc0, 0xc7).mirror(0x38).rw(FUNC(sg1000m3_state::sg1000m3_peripheral_r), FUNC(sg1000m3_state::sg1000m3_peripheral_w)); } void sms_state::sms_io(address_map &map) { map.global_mask(0xff); map.unmap_value_high(); + map(0x00, 0x00).mirror(0x3e).w(FUNC(sms_state::sms_mem_control_w)); map(0x01, 0x01).mirror(0x3e).w(FUNC(sms_state::sms_io_control_w)); map(0x40, 0x7f).r(FUNC(sms_state::sms_count_r)).w(m_vdp, FUNC(sega315_5124_device::psg_w)); @@ -345,6 +347,7 @@ void sms_state::smsj_io(address_map &map) { map.global_mask(0xff); map.unmap_value_high(); + map(0x3e, 0x3e).w(FUNC(sms_state::sms_mem_control_w)); map(0x3f, 0x3f).w(FUNC(sms_state::sms_io_control_w)); map(0x40, 0x7f).r(FUNC(sms_state::sms_count_r)).w(m_vdp, FUNC(sega315_5124_device::psg_w)); @@ -366,6 +369,7 @@ void gamegear_state::gg_io(address_map &map) { map.global_mask(0xff); map.unmap_value_high(); + map(0x00, 0x00).r(FUNC(gamegear_state::gg_input_port_00_r)); map(0x01, 0x05).rw(FUNC(gamegear_state::gg_sio_r), FUNC(gamegear_state::gg_sio_w)); map(0x06, 0x06).w(FUNC(gamegear_state::gg_psg_stereo_w)); @@ -484,7 +488,7 @@ static INPUT_PORTS_START( gg ) PORT_START("START") PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("Start") /* Game Gear START */ + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("Start") PORT_START("PERSISTENCE") PORT_CONFNAME( 0x01, 0x01, "LCD Persistence Hack" ) @@ -920,11 +924,11 @@ void sms1_state::smsj(machine_config &config) m_is_smsj = true; } -void sms1_state::sg1000m3(machine_config &config) +void sg1000m3_state::sg1000m3(machine_config &config) { sms1_ntsc(config); - m_maincpu->set_addrmap(AS_IO, &sms1_state::sg1000m3_io); + m_maincpu->set_addrmap(AS_IO, &sg1000m3_state::sg1000m3_io); // Remove and reinsert all media slots, as done with the sms1_kr config, // and also replace the expansion slot with the SG-1000 version. @@ -933,7 +937,7 @@ void sms1_state::sg1000m3(machine_config &config) config.device_remove("smsexp"); SG1000MK3_CART_SLOT(config, "slot", sg1000mk3_cart, nullptr); SMS_CARD_SLOT(config, "mycard", sms_cart, nullptr); - SG1000_EXPANSION_SLOT(config, "sgexp", sg1000_expansion_devices, nullptr, false); + SG1000_EXPANSION_SLOT(config, m_sgexpslot, sg1000_expansion_devices, nullptr, false); SOFTWARE_LIST(config, "cart_list2").set_original("sg1000"); @@ -1241,7 +1245,7 @@ ROM_END ***************************************************************************/ /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ -CONS( 1985, sg1000m3, sms, 0, sg1000m3, sg1000m3, sms1_state, empty_init, "Sega", "Mark III", MACHINE_SUPPORTS_SAVE ) +CONS( 1985, sg1000m3, sms, 0, sg1000m3, sg1000m3, sg1000m3_state, empty_init, "Sega", "Mark III", MACHINE_SUPPORTS_SAVE ) CONS( 1986, sms1, sms, 0, sms1_ntsc, sms1, sms1_state, empty_init, "Sega", "Master System I", MACHINE_SUPPORTS_SAVE ) CONS( 1986, sms1pal, sms, 0, sms1_pal, sms1, sms1_state, empty_init, "Sega", "Master System I (PAL)" , MACHINE_SUPPORTS_SAVE ) CONS( 1986, smssdisp, sms, 0, sms_sdisp, smssdisp, smssdisp_state, empty_init, "Sega", "Master System Store Display Unit", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/sega/sms.h b/src/mame/sega/sms.h index e3d2b204f96..59834cfab00 100644 --- a/src/mame/sega/sms.h +++ b/src/mame/sega/sms.h @@ -59,8 +59,7 @@ public: m_has_pwr_led(false), m_slot(*this, "slot"), m_cardslot(*this, "mycard"), - m_smsexpslot(*this, "smsexp"), - m_sgexpslot(*this, "sgexp") + m_smsexpslot(*this, "smsexp") { } void sms_base(machine_config &config); @@ -94,8 +93,6 @@ protected: uint8_t sms_count_r(offs_t offset); uint8_t sms_input_port_dc_r(); uint8_t sms_input_port_dd_r(); - uint8_t sg1000m3_peripheral_r(offs_t offset); - void sg1000m3_peripheral_w(offs_t offset, uint8_t data); uint8_t smsj_audio_control_r(); void smsj_audio_control_w(uint8_t data); void smsj_ym2413_register_port_w(uint8_t data); @@ -105,7 +102,6 @@ protected: DECLARE_WRITE_LINE_MEMBER(sms_ctrl1_th_input); DECLARE_WRITE_LINE_MEMBER(sms_ctrl2_th_input); - void sg1000m3_io(address_map &map); void sms_io(address_map &map); void sms_mem(address_map &map); void smsj_io(address_map &map); @@ -143,7 +139,7 @@ protected: std::unique_ptr m_mainram; uint8_t *m_BIOS; - // for gamegear LCD persistence hack + // for Game Gear LCD persistence hack bitmap_rgb32 m_prev_bitmap; bool m_prev_bitmap_copied; @@ -192,9 +188,9 @@ protected: optional_device m_slot; optional_device m_cardslot; optional_device m_smsexpslot; - optional_device m_sgexpslot; }; + class sms1_state : public sms_state { public: @@ -212,7 +208,6 @@ public: void sms1_br(machine_config &config); void sms1_kr(machine_config &config); void smsj(machine_config &config); - void sg1000m3(machine_config &config); protected: virtual void video_start() override; @@ -241,6 +236,7 @@ private: uint8_t m_frame_sscope_state; }; + class smssdisp_state : public sms1_state { public: @@ -278,6 +274,30 @@ private: uint8_t m_store_cart_selection_data; }; + +class sg1000m3_state : public sms1_state +{ +public: + sg1000m3_state(const machine_config &mconfig, device_type type, const char *tag) : + sms1_state(mconfig, type, tag), + m_sgexpslot(*this, "sgexp") + { } + + void sg1000m3(machine_config &config); + +protected: + virtual void machine_reset() override; + +private: + uint8_t sg1000m3_peripheral_r(offs_t offset); + void sg1000m3_peripheral_w(offs_t offset, uint8_t data); + + void sg1000m3_io(address_map &map); + + required_device m_sgexpslot; +}; + + class gamegear_state : public sms_state { public: @@ -312,9 +332,10 @@ private: // for gamegear SMS mode scaling bitmap_rgb32 m_gg_sms_mode_bitmap; + // line_buffer will be used to hold 4 lines of line data as a kind of cache for - // vertical scaling in the gamegear sms compatibility mode. - std::unique_ptr m_line_buffer; + // vertical scaling in the Game Gear SMS compatibility mode. + std::unique_ptr m_line_buffer; uint8_t m_gg_sio[5]{}; int m_gg_paused = 0; diff --git a/src/mame/sega/sms_m.cpp b/src/mame/sega/sms_m.cpp index 6c57c77f155..254a79af9d9 100644 --- a/src/mame/sega/sms_m.cpp +++ b/src/mame/sega/sms_m.cpp @@ -290,12 +290,6 @@ WRITE_LINE_MEMBER(sms_state::rapid_n_csync_callback) uint8_t sms_state::sms_input_port_dc_r() { - if (m_is_mark_iii) - { - sms_get_inputs(); - return m_port_dc_reg; - } - if (m_is_gamegear) { // If SMS mode is disabled, just return the data read from the @@ -337,12 +331,6 @@ uint8_t sms_state::sms_input_port_dc_r() uint8_t sms_state::sms_input_port_dd_r() { - if (m_is_mark_iii) - { - sms_get_inputs(); - return m_port_dd_reg; - } - if (m_is_gamegear) { if (!(m_cartslot->exists() && m_cartslot->get_sms_mode())) @@ -763,9 +751,9 @@ void sms_state::sms_mem_control_w(uint8_t data) } -uint8_t sms_state::sg1000m3_peripheral_r(offs_t offset) +uint8_t sg1000m3_state::sg1000m3_peripheral_r(offs_t offset) { - bool joy_ports_disabled = m_sgexpslot->is_readable(offset); + bool const joy_ports_disabled = m_sgexpslot->is_readable(offset); if (joy_ports_disabled) { @@ -773,22 +761,21 @@ uint8_t sms_state::sg1000m3_peripheral_r(offs_t offset) } else { + sms_get_inputs(); if (offset & 0x01) - return sms_input_port_dd_r(); + return m_port_dd_reg; else - return sms_input_port_dc_r(); + return m_port_dc_reg; } } -void sms_state::sg1000m3_peripheral_w(offs_t offset, uint8_t data) +void sg1000m3_state::sg1000m3_peripheral_w(offs_t offset, uint8_t data) { - bool joy_ports_disabled = m_sgexpslot->is_writeable(offset); + bool const joy_ports_disabled = m_sgexpslot->is_writeable(offset); if (joy_ports_disabled) - { m_sgexpslot->write(offset, data); - } } @@ -1053,7 +1040,7 @@ void sms_state::machine_start() void smssdisp_state::machine_start() { - sms_state::machine_start(); + sms1_state::machine_start(); save_item(NAME(m_store_control)); save_item(NAME(m_store_cart_selection_data)); @@ -1092,13 +1079,7 @@ void sms_state::machine_reset() m_led_pwr = 1; } - if (m_is_mark_iii) - { - // pin 7 is tied to ground on the Mark III - m_port_ctrl1->out_w(0x3f, 0x40); - m_port_ctrl2->out_w(0x3f, 0x40); - } - else + if (!m_is_mark_iii) { m_io_ctrl_reg = 0xff; m_ctrl1_th_latch = 0; @@ -1115,7 +1096,16 @@ void smssdisp_state::machine_reset() m_store_cart_selection_data = 0; store_select_cart(m_store_cart_selection_data); - sms_state::machine_reset(); + sms1_state::machine_reset(); +} + +void sg1000m3_state::machine_reset() +{ + sms1_state::machine_reset(); + + // controller port pin 7 is tied to ground on the Mark III + m_port_ctrl1->out_w(0x3f, 0x40); + m_port_ctrl2->out_w(0x3f, 0x40); } void gamegear_state::machine_reset() -- cgit v1.2.3