// license:BSD-3-Clause // copyright-holders:hap // thanks-to:Alex_LG, Berger /****************************************************************************** Интеллект-02 (Intellect-02) driver This is a Soviet electronic board game console, a dozen or so cartridge games were announced(can't say for certain how many released). PCB labels have prefix ДМП, it's assumed to have been designed by НИИ БРЭА (SRI BREA). First shown in 1983, produced during around 1985-1992. hardware notes: - КР580ВМ80А CPU (i8080A clone) @ 1.5MHz - КР580ИК55 (i8255 clone) - 1 KB RAM (8*КР565РУ2), cartridge port - 4-digit 7seg panel, 2 leds, 16 buttons, game board above it The chess/checkers board is detachable, with a board for Kalah underneath it. The hardware is very similar to Fidelity Chess Challenger 3. Actually, one of the first cartridges for this system, a Chess program, is a modified Chess Challenger 3 ROM. The chess engine was kept identical. (note: the "lose" LED is used for "check" in this game) The 2nd(4-level) chess cartridge is completely different, not a CC3 clone. Intellect-01 looks like it didn't get further than a prototype. It was a dedicated chess computer, probably a clone of CC3. keypad legend: СБ - сброс (reset) ВВ - ввод (input) ВИ - выбор игры (game select) СТ - стирание (erase) ПП - просмотр позиции (view position) УИ - уровень игры (game level) ******************************************************************************/ #include "emu.h" #include "cpu/i8085/i8085.h" #include "machine/i8255.h" #include "sound/beep.h" #include "video/pwm.h" #include "bus/generic/slot.h" #include "bus/generic/carts.h" #include "softlist.h" #include "speaker.h" // internal artwork #include "intellect02.lh" // clickable namespace { class intel02_state : public driver_device { public: intel02_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_ppi8255(*this, "ppi8255"), m_display(*this, "display"), m_beeper(*this, "beeper"), m_inputs(*this, "IN.%u", 0) { } // machine configs void intel02(machine_config &config); DECLARE_INPUT_CHANGED_MEMBER(reset_button); protected: virtual void machine_start() override; private: // devices/pointers required_device m_maincpu; required_device m_ppi8255; required_device m_display; required_device m_beeper; required_ioport_array<2> m_inputs; // address maps void main_map(address_map &map); void main_io(address_map &map); // I/O handlers void update_display(); u8 input_r(); void digit_w(u8 data); void control_w(u8 data); u8 m_digit_data; u8 m_led_select; }; void intel02_state::machine_start() { // zerofill m_digit_data = 0; m_led_select = 0; // register for savestates save_item(NAME(m_digit_data)); save_item(NAME(m_led_select)); } INPUT_CHANGED_MEMBER(intel02_state::reset_button) { // reset button goes to 8080/8255 RESET pins simultaneously (via 7474, and also a maze of NAND gates to who knows where) m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE); if (newval) m_ppi8255->reset(); } /****************************************************************************** I/O ******************************************************************************/ // I8255 PPI void intel02_state::update_display() { m_display->matrix(m_led_select, m_digit_data); } u8 intel02_state::input_r() { // d0-d3: buttons through a maze of logic gates // basically giving each button its own 4-bit scancode u8 data = count_leading_zeros(m_inputs[0]->read()) - 17; // d4: Vcc, d5-d7: buttons (direct) return data | (~m_inputs[1]->read() << 4 & 0xf0); } void intel02_state::digit_w(u8 data) { // d0-d6: digit segment data, d7: N/C m_digit_data = bitswap<7>(data,0,1,2,3,4,5,6); update_display(); } void intel02_state::control_w(u8 data) { // d0-d5: select digit/leds m_led_select = data; update_display(); // d6: N/C (it's a delay timer on CC3) // d7: enable beeper m_beeper->set_state(BIT(data, 7)); } /****************************************************************************** Address Maps ******************************************************************************/ void intel02_state::main_map(address_map &map) { map(0x0000, 0x1fff).r("cartslot", FUNC(generic_slot_device::read_rom)); map(0xf000, 0xf3ff).ram(); } void intel02_state::main_io(address_map &map) { map.global_mask(0xff); map(0xf4, 0xf7).rw(m_ppi8255, FUNC(i8255_device::read), FUNC(i8255_device::write)); } /****************************************************************************** Input Ports ******************************************************************************/ static INPUT_PORTS_START( intel02 ) PORT_START("IN.0") PORT_BIT(0x0007, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_V) PORT_NAME(u8"ПП (View Position)") PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_NAME(u8"УИ (Game Level)") PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9") PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_H) PORT_NAME("H8") PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_CODE(KEYCODE_G) PORT_NAME("G7") PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_F) PORT_NAME("F6") PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_CODE(KEYCODE_E) PORT_NAME("E5") PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_D) PORT_NAME("D4") PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_CODE(KEYCODE_C) PORT_NAME("C3") PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_B) PORT_NAME("B2") PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_CODE(KEYCODE_A) PORT_NAME("A1") PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("0") PORT_START("IN.1") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME(u8"ВВ (Input)") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S) PORT_NAME(u8"ВИ (Game Select)") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME(u8"СТ (Erase)") PORT_START("RESET") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_CHANGED_MEMBER(DEVICE_SELF, intel02_state, reset_button, 0) PORT_NAME(u8"СБ (Reset)") INPUT_PORTS_END /****************************************************************************** Machine Configs ******************************************************************************/ void intel02_state::intel02(machine_config &config) { /* basic machine hardware */ I8080A(config, m_maincpu, 1500000); // measured (no XTAL) m_maincpu->set_addrmap(AS_PROGRAM, &intel02_state::main_map); m_maincpu->set_addrmap(AS_IO, &intel02_state::main_io); I8255(config, m_ppi8255); m_ppi8255->in_pa_callback().set(FUNC(intel02_state::input_r)); m_ppi8255->out_pb_callback().set(FUNC(intel02_state::digit_w)); m_ppi8255->tri_pb_callback().set_constant(0); m_ppi8255->out_pc_callback().set(FUNC(intel02_state::control_w)); m_ppi8255->tri_pc_callback().set_constant(0x80); /* video hardware */ PWM_DISPLAY(config, m_display).set_size(6, 7); m_display->set_segmask(0xf, 0x7f); config.set_default_layout(layout_intellect02); /* sound hardware */ SPEAKER(config, "speaker").front_center(); BEEP(config, m_beeper, 3640); // measured, from RC circuit m_beeper->add_route(ALL_OUTPUTS, "speaker", 0.25); /* cartridge */ GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "intellect02").set_must_be_loaded(true); SOFTWARE_LIST(config, "cart_list").set_original("intellect02"); } /****************************************************************************** ROM Definitions ******************************************************************************/ ROM_START( intel02 ) ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 ) // nothing here, it's on a cartridge ROM_END } // anonymous namespace /****************************************************************************** Drivers ******************************************************************************/ // YEAR NAME PARENT CMP MACHINE INPUT STATE INIT COMPANY, FULLNAME, FLAGS CONS( 1985, intel02, 0, 0, intel02, intel02, intel02_state, empty_init, "BREA Research Institute", "Intellect-02", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )