// license:BSD-3-Clause // copyright-holders:hap // thanks-to:bataais /****************************************************************************** Conic Computer Chess (model 07012), also sold under the same name by Hanimex (model HMG 1200) and Westrak (model CC 1). It's also known as Tracer Chess, this title is from an advertisement flyer, the actual chess computer was simply named Computer Chess. The chessboard sensors aren't buttons or magnets, but 64 jacks. There is a metal plug under each chesspiece. From MAME's perspective, it works the same as a magnet sensorboard. After the player's move, the user needs to press Enter. This does not apply to the computer's move. Hardware notes: - Synertek 6504 @ ~1MHz - 2*Motorola MC6821P PIA - 4KB ROM(AMI), 1KB RAM(2*Synertek 1024x4) - beeper, 8*8 leds, plug board BTANB: - Learn button still works when in modify-mode ******************************************************************************/ #include "emu.h" #include "cpu/m6502/m6504.h" #include "machine/6821pia.h" #include "machine/sensorboard.h" #include "sound/dac.h" #include "sound/volt_reg.h" #include "video/pwm.h" #include "speaker.h" // internal artwork #include "conic_cchess2.lh" // clickable namespace { class cchess2_state : public driver_device { public: cchess2_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_pia(*this, "pia%u", 0), m_board(*this, "board"), m_display(*this, "display"), m_dac(*this, "dac"), m_inputs(*this, "IN.%u", 0) { } // machine configs void cncchess2(machine_config &config); // assume that RESET button is tied to 6504 reset pin DECLARE_INPUT_CHANGED_MEMBER(reset_button) { m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE); } protected: virtual void machine_start() override; private: // devices/pointers required_device m_maincpu; required_device_array m_pia; required_device m_board; required_device m_display; required_device m_dac; required_ioport_array<8> m_inputs; // address maps void main_map(address_map &map); // I/O handlers void update_display(); void update_dac(); void pia0_pa_w(u8 data); void pia0_pb_w(u8 data); u8 pia1_pa_r(); u8 pia1_pb_r(); void pia1_pb_w(u8 data); u8 m_inp_mux = 0; u8 m_led_data = 0; int m_dac_on = 0; }; void cchess2_state::machine_start() { save_item(NAME(m_inp_mux)); save_item(NAME(m_led_data)); save_item(NAME(m_dac_on)); } /****************************************************************************** I/O ******************************************************************************/ void cchess2_state::update_display() { m_display->matrix(m_inp_mux, m_led_data); } void cchess2_state::update_dac() { m_dac->write(m_dac_on & BIT(m_inp_mux, 1)); } void cchess2_state::pia0_pa_w(u8 data) { // d0-d7: input mux/led select // d1: dac data m_inp_mux = data; update_display(); update_dac(); } void cchess2_state::pia0_pb_w(u8 data) { // d0-d7: led data m_led_data = data; update_display(); } u8 cchess2_state::pia1_pa_r() { u8 data = 0; // d0-d7: chessboard sensors for (int i = 0; i < 8; i++) if (BIT(m_inp_mux, i)) data |= m_board->read_rank(i); return ~data; } u8 cchess2_state::pia1_pb_r() { u8 data = 0; // d0-d3: multiplexed inputs for (int i = 0; i < 8; i++) if (BIT(m_inp_mux, i)) data |= m_inputs[i]->read(); return data; } void cchess2_state::pia1_pb_w(u8 data) { // d7: dac on m_dac_on = BIT(data, 7); update_dac(); } /****************************************************************************** Address Maps ******************************************************************************/ void cchess2_state::main_map(address_map &map) { map.global_mask(0x1fff); map(0x0000, 0x03ff).ram(); map(0x0a00, 0x0a03).mirror(0x00fc).rw(m_pia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x0c00, 0x0c03).mirror(0x00fc).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x1000, 0x1fff).rom(); } /****************************************************************************** Input Ports ******************************************************************************/ static INPUT_PORTS_START( cncchess2 ) PORT_START("IN.0") PORT_BIT(0x03, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CONFNAME( 0x0c, 0x08, "Mode" ) PORT_CONFSETTING( 0x04, "Modify" ) PORT_CONFSETTING( 0x08, "Play" ) PORT_START("IN.1") PORT_CONFNAME( 0x03, 0x02, "Color" ) PORT_CONFSETTING( 0x01, "Black" ) // from the bottom PORT_CONFSETTING( 0x02, "White" ) PORT_BIT(0x0c, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_START("IN.2") PORT_BIT(0x0f, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_START("IN.3") PORT_BIT(0x0f, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_START("IN.4") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("Enter") PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_N) PORT_NAME("Learn") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_NAME("Level") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_NAME("6 / White King") PORT_START("IN.5") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_NAME("5 / White Queen") PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_NAME("4 / White Rook") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_NAME("3 / White Bishop") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_NAME("2 / White Knight") PORT_START("IN.6") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_NAME("1 / White Pawn") PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Clear") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) PORT_NAME("7 / Black Pawn") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) PORT_NAME("8 / Black Knight") PORT_START("IN.7") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_9) PORT_NAME("9 / Black Bishop") PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_0) PORT_NAME("10 / Black Rook") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_MINUS) PORT_NAME("11 / Black Queen") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_EQUALS) PORT_NAME("12 / Black King") PORT_START("RESET") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_CHANGED_MEMBER(DEVICE_SELF, cchess2_state, reset_button, 0) PORT_NAME("Reset") INPUT_PORTS_END /****************************************************************************** Machine Configs ******************************************************************************/ void cchess2_state::cncchess2(machine_config &config) { /* basic machine hardware */ M6504(config, m_maincpu, 1000000); // approximation, no XTAL m_maincpu->set_addrmap(AS_PROGRAM, &cchess2_state::main_map); PIA6821(config, m_pia[0], 0); m_pia[0]->writepa_handler().set(FUNC(cchess2_state::pia0_pa_w)); m_pia[0]->writepb_handler().set(FUNC(cchess2_state::pia0_pb_w)); PIA6821(config, m_pia[1], 0); m_pia[1]->readpa_handler().set(FUNC(cchess2_state::pia1_pa_r)); m_pia[1]->readpb_handler().set(FUNC(cchess2_state::pia1_pb_r)); m_pia[1]->writepb_handler().set(FUNC(cchess2_state::pia1_pb_w)); SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS); m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess)); m_board->set_delay(attotime::from_msec(150)); /* video hardware */ PWM_DISPLAY(config, m_display).set_size(8, 8); config.set_default_layout(layout_conic_cchess2); /* sound hardware */ SPEAKER(config, "speaker").front_center(); DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25); VOLTAGE_REGULATOR(config, "vref").add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT); } /****************************************************************************** ROM Definitions ******************************************************************************/ ROM_START( cncchess2 ) ROM_REGION( 0x10000, "maincpu", 0 ) ROM_LOAD("c11485.u2", 0x1000, 0x1000, CRC(b179d536) SHA1(0b1f9c247a4a3e2ccbf8d3ae5efa62b8938f572f) ) // AMI 2332 ROM_END } // anonymous namespace /****************************************************************************** Drivers ******************************************************************************/ // YEAR NAME PARENT CMP MACHINE INPUT STATE INIT COMPANY, FULLNAME, FLAGS CONS( 1980, cncchess2, 0, 0, cncchess2, cncchess2, cchess2_state, empty_init, "Conic", "Computer Chess (Conic, model 7012)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )