From a79525b2717246393c407b8e327e9f6adafd8d17 Mon Sep 17 00:00:00 2001 From: Scott Stone Date: Sun, 15 Apr 2012 00:50:27 +0000 Subject: [PATCH] icecold.c [Sandro Ronco] - This game has mechanical parts so it's not exactly playable, but it is possible try it until the end giving the expected inputs. - Imported the i8279 device from MESS and updated to support sensor mode and mask nibble. - Made a simple layout and the defined input ports. New clones marked as GAME_NOT_WORKING ------------------------------------ Zeke's Peak [Sandro Ronco] --- .gitattributes | 2 + src/emu/emu.mak | 1 + src/emu/machine/i8279.c | 499 ++++++++++++++++++++++++++++++++++++ src/mame/drivers/icecold.c | 432 ++++++++++++++++++++++++++++++- src/mame/layout/icecold.lay | 131 ++++++++++ src/mame/mame.lst | 1 + src/mame/mame.mak | 2 + 7 files changed, 1058 insertions(+), 10 deletions(-) create mode 100644 src/emu/machine/i8279.c create mode 100644 src/mame/layout/icecold.lay diff --git a/.gitattributes b/.gitattributes index 390b4dd5ae6..cf7e21d56bb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -869,6 +869,7 @@ src/emu/machine/i8251.c svneol=native#text/plain src/emu/machine/i8251.h svneol=native#text/plain src/emu/machine/i8255.c svneol=native#text/plain src/emu/machine/i8255.h svneol=native#text/plain +src/emu/machine/i8279.c svneol=native#text/plain src/emu/machine/i8355.c svneol=native#text/plain src/emu/machine/i8355.h svneol=native#text/plain src/emu/machine/idectrl.c svneol=native#text/plain @@ -4032,6 +4033,7 @@ src/mame/layout/gorf.lay svneol=native#text/plain src/mame/layout/grchamp.lay svneol=native#text/plain src/mame/layout/gridiron.lay svneol=native#text/plain src/mame/layout/gypsyjug.lay svneol=native#text/plain +src/mame/layout/icecold.lay svneol=native#text/plain src/mame/layout/igspoker.lay svneol=native#text/plain src/mame/layout/invad2ct.lay svneol=native#text/plain src/mame/layout/invaders.lay svneol=native#text/plain diff --git a/src/emu/emu.mak b/src/emu/emu.mak index 0f49ef864d4..2bface55244 100644 --- a/src/emu/emu.mak +++ b/src/emu/emu.mak @@ -185,6 +185,7 @@ EMUMACHINEOBJS = \ $(EMUMACHINE)/i8243.o \ $(EMUMACHINE)/i8251.o \ $(EMUMACHINE)/i8255.o \ + $(EMUMACHINE)/i8279.o \ $(EMUMACHINE)/i8355.o \ $(EMUMACHINE)/idectrl.o \ $(EMUMACHINE)/im6402.o \ diff --git a/src/emu/machine/i8279.c b/src/emu/machine/i8279.c new file mode 100644 index 00000000000..11f41254c01 --- /dev/null +++ b/src/emu/machine/i8279.c @@ -0,0 +1,499 @@ +/********************************************************************** + + i8279 + +2012-JAN-08 First draft [Robbbert] +2012-JAN-12 Implemented + +Notes: +- All keys MUST be ACTIVE_LOW + + +ToDo: +- Command 5 (Nibble masking and blanking) +- Command 7 (Error Mode) +- Interrupts +- BD pin +- Sensor ram stuff +- save state + + +What has been done: +CMD 0: +- Display Mode +-- Left & Right with no increment are the same thing +-- Right with increment is not emulated yet *** +- Keyboard Mode +-- No particular code has been added for 2-key/N-key rollover, no need +-- Sensor mode is not complete yet *** +-- Encoded and Decoded are done +-- Strobe is done +-- Sensor and FIFO may share the same internal RAM, not sure +CMD 1: +- Clock Divider +-- Value is stored, but internally a fixed value is always used +CMD 2: +- Read FIFO/Sensor RAM +-- FIFO works +-- Sensor RAM works +CMD 3: +- Read Display RAM +-- This works +CMD 4: +- Write Display RAM +-- Right with increment does nothing, the rest is working *** +CMD 5: +- Blank Nibble +-- Not done *** +- Mask Nibble +-- Implemented +CMD 6: +-- All implemented +CMD 7: +- Interrupt +-- Not done +- Error Mode +-- No need to do. + +Interface: +-- All done except BD pin *** + +Status word: +- FIFO bits +-- All done +- Error bit +-- Not done (no need) +- Display unavailable +-- Not done (no need) + + +Items marked (***) can be added if a system appears +that uses this feature. + +**********************************************************************/ + +#include "i8279.h" + +#define LOG 0 + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +// device type definition +const device_type I8279 = &device_creator; + +//------------------------------------------------- +// i8279_device - constructor +//------------------------------------------------- + +i8279_device::i8279_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, I8279, "Intel 8279", tag, owner, clock) +{ +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void i8279_device::device_config_complete() +{ + // inherit a copy of the static data + const i8279_interface *intf = reinterpret_cast(static_config()); + if (intf != NULL) + { + *static_cast(this) = *intf; + } + + // or initialize to defaults if none provided + else + { + memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb)); + memset(&m_out_sl_cb, 0, sizeof(m_out_sl_cb)); + memset(&m_out_disp_cb, 0, sizeof(m_out_disp_cb)); + memset(&m_out_bd_cb, 0, sizeof(m_out_bd_cb)); + memset(&m_in_rl_cb, 0, sizeof(m_in_rl_cb)); + memset(&m_in_shift_cb, 0, sizeof(m_in_shift_cb)); + memset(&m_in_ctrl_cb, 0, sizeof(m_in_ctrl_cb)); + } +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void i8279_device::device_start() +{ + /* resolve callbacks */ + m_out_irq_func.resolve(m_out_irq_cb, *this); + m_out_sl_func.resolve(m_out_sl_cb, *this); + m_out_disp_func.resolve(m_out_disp_cb, *this); + m_out_bd_func.resolve(m_out_bd_cb, *this); + m_in_rl_func.resolve(m_in_rl_cb, *this); + m_in_shift_func.resolve(m_in_shift_cb, *this); + m_in_ctrl_func.resolve(m_in_ctrl_cb, *this); + m_clock = clock(); + m_timer = machine().scheduler().timer_alloc(FUNC(timerproc_callback), (void *)this); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void i8279_device::device_reset() +{ + UINT8 i; + + // startup values are unknown: setting to 0 + for (i = 2; i < 8; i++) m_cmd[i] = 0; + for (i = 0; i < 8; i++) m_fifo[i] = 0; + for (i = 0; i < 8; i++) m_s_ram[i] = 0; + for (i = 0; i < 16; i++) m_d_ram[i] = 0; + m_status = 0; + m_autoinc = 1; + m_d_ram_ptr = 0; + m_s_ram_ptr = 0; + m_read_flag = 0; + m_scanner = 0; + m_ctrl_key = 1; + m_key_down = 0xffff; + + // from here is confirmed + m_cmd[0] = 8; + m_cmd[1] = 31; + logerror("Initial clock = 3100kHz\n"); + timer_adjust(); +} + + +void i8279_device::timer_adjust() +{ +// Real device runs at about 100kHz internally, clock divider is chosen so that +// this is the case. We do not need such speed, 200Hz is enough. + + //UINT8 divider = (m_cmd[1]) ? m_cmd[1] : 1; + //m_clock = clock() / divider; + + m_clock = 200; + m_timer->adjust(attotime::from_hz(m_clock), 0, attotime::from_hz(m_clock)); +} + + +void i8279_device::clear_display() +{ + // clear all digits + UINT8 i,patterns[4] = { 0, 0, 0x20, 0xff }; + UINT8 data = patterns[(m_cmd[6] & 12) >> 2]; + + // The CD high bit (also done by CA) + if (m_cmd[6] & 0x11) + for (i = 0; i < 16; i++) + m_d_ram[i] = data; + + m_status &= 0x7f; // bit 7 not emulated, but do it anyway + m_d_ram_ptr = 0; // not in the datasheet, but needed + + // The CF bit (also done by CA) + if (m_cmd[6] & 3) + { + m_status &= 0xc0; // blow away fifo + m_s_ram_ptr = 0; // reset sensor pointer + set_irq(0); // reset irq + } +} + + +void i8279_device::set_irq(bool state) +{ + if ( !m_out_irq_func.isnull() ) + m_out_irq_func( state ); +} + + +void i8279_device::new_key(UINT8 data, bool skey, bool ckey) +{ + UINT8 i, rl, sl; + for (i = 0; BIT(data, i); i++); + rl = i; + if (BIT(m_cmd[0], 0)) + { + for (i = 0; !BIT(data, i); i++); + sl = i; + } + else + sl = m_scanner; + + new_fifo( (ckey << 7) | (skey << 6) | (sl << 3) | rl); +} + + +void i8279_device::new_fifo(UINT8 data) +{ + // see if already overrun + if (BIT(m_status, 5)) + return; + + // set overrun flag if full + if (BIT(m_status, 3)) + { + m_status |= 0x20; + return; + } + + m_fifo[m_status & 7] = data; + + // bump fifo size & turn off underrun + UINT8 fifo_size = m_status & 7; + if ((fifo_size)==7) + m_status |= 8; // full + else + m_status = (m_status & 0xe8) + fifo_size + 1; + + if (!fifo_size) + set_irq(1); // something just went into fifo, so int +} + + +TIMER_CALLBACK( i8279_device::timerproc_callback ) +{ + reinterpret_cast(ptr)->timer_mainloop(); +} + + +void i8279_device::timer_mainloop() +{ + // control byte 0 + // bit 0 - encoded or decoded keyboard scan + // bits 1,2 - keyboard type + // bit 3 - number of digits to display + // bit 4 - left or right entry + + UINT8 scanner_mask = BIT(m_cmd[0], 0) ? 15 : BIT(m_cmd[0], 3) ? 15 : 7; + bool decoded = BIT(m_cmd[0], 0); + UINT8 kbd_type = (m_cmd[0] & 6) >> 1; + bool shift_key = 1; + bool ctrl_key = 1; + bool strobe_pulse = 0; + + // keyboard + // type 0 = kbd, 2-key lockout + // type 1 = kdb, n-key + // type 2 = sensor + // type 3 = strobed + + // Get shift keys + if ( !m_in_shift_func.isnull() ) + shift_key = m_in_shift_func(); + + if ( !m_in_ctrl_func.isnull() ) + ctrl_key = m_in_ctrl_func(); + + if (ctrl_key && !m_ctrl_key) + strobe_pulse = 1; // low-to-high is a strobe + + m_ctrl_key = ctrl_key; + + // Read a row of keys + + if ( !m_in_rl_func.isnull() ) + { + UINT8 rl = m_in_rl_func(0); + + // see if key still down from last time + UINT16 key_down = (m_scanner << 8) | rl; + if (key_down == m_key_down) + rl = 0xff; + else + if ((rl == 0xff) && (m_scanner == m_key_down >> 8)) + m_key_down = 0xffff; + + // now process new key + if (rl < 0xff || kbd_type == 2) + { + m_key_down = key_down; + switch (kbd_type) + { + case 0: + case 1: + new_key(rl, shift_key, ctrl_key); + break; + case 2: + { + UINT8 addr = m_scanner; + + if (decoded) + for (addr=0; !BIT(m_scanner, addr); addr++); + + rl ^= 0xff; // inverted + if (m_s_ram[addr] != rl) + { + m_s_ram[addr] = rl; + + // IRQ line goes high if a row change value + set_irq(1); + } + } + break; + case 3: + if (strobe_pulse) new_fifo(rl); + break; + } + } + } + + // Increment scanline + + if (decoded) + { + m_scanner<<= 1; + if ((m_scanner & 15)==0) + m_scanner = 1; + } + else + m_scanner++; + + m_scanner &= scanner_mask; // 4-bit port + + if ( !m_out_sl_func.isnull() ) + m_out_sl_func(0, m_scanner); + + // output a digit + + if ( !m_out_disp_func.isnull() ) + m_out_disp_func(0, m_d_ram[m_scanner] ); +} + + +READ8_MEMBER( i8279_device::status_r ) +{ + return m_status; +} + + +READ8_MEMBER( i8279_device::data_r ) +{ + UINT8 i; + bool sensor_mode = ((m_cmd[0] & 6)==4); + UINT8 data; + if (m_read_flag) + { + // read the display ram + data = m_d_ram[m_d_ram_ptr]; + if (m_autoinc) + m_d_ram_ptr++; + } + else + if (sensor_mode) + { + // read sensor ram + data = m_s_ram[m_s_ram_ptr]; + if (m_autoinc) + m_s_ram_ptr++; + else + set_irq(0); + } + else + { + // read a key from fifo + data = m_fifo[0]; + UINT8 fifo_size = m_status & 7; + switch (m_status & 0x38) + { + case 0x00: // no errors + if (!fifo_size) + m_status |= 0x10; // underrun + else + { + for (i = 1; i < 8; i++) + m_fifo[i-1] = m_fifo[i]; + fifo_size--; + if (!fifo_size) + set_irq(0); + } + break; + case 0x28: // overrun + case 0x08: // fifo full + for (i = 1; i < 8; i++) + m_fifo[i-1] = m_fifo[i]; + break; + case 0x10: // underrun + if (!fifo_size) + break; + default: + printf("Invalid status: %X\n", m_status); + } + m_status = (m_status & 0xd0) | fifo_size; // turn off overrun & full + } + + m_d_ram_ptr &= 15; + m_s_ram_ptr &= 7; + return data; +} + + +WRITE8_MEMBER( i8279_device::cmd_w ) +{//printf("Command: %X=%X ",data>>5,data&31); + UINT8 cmd = data >> 5; + data &= 0x1f; + m_cmd[cmd] = data; + switch (cmd) + { + case 0: + if (LOG) logerror("I8279 '%s' kb mode %x, display mode %x\n", tag(), data & 7, (data>>3) & 3); + break; + case 1: + if (data > 1) + { + logerror("Clock set to %dkHz\n",data*100); + timer_adjust(); + } + break; + case 2: + m_read_flag = 0; + if ((m_cmd[0] & 6)==4) // sensor mode only + { + m_autoinc = BIT(data, 4); + m_s_ram_ptr = data & 7; + if (LOG) logerror("I8279 '%s' selct sensor row %x, AI %d\n", tag(), m_s_ram_ptr, m_autoinc); + } + break; + case 3: + m_read_flag = 1; + m_d_ram_ptr = data & 15; + m_autoinc = BIT(data, 4); + break; + case 4: + m_d_ram_ptr = data & 15; + m_autoinc = BIT(data, 4); + break; + case 6: + if (LOG) logerror("I8279 '%s' clear cmd %x\n", tag(), data); + clear_display(); + break; + } +} + + +WRITE8_MEMBER( i8279_device::data_w ) +{//printf("Data: %X ",data); + if (BIT(m_cmd[0], 4) & m_autoinc) + { + // right-entry autoincrement not implemented yet + } + else + { + if (!(m_cmd[5] & 0x04)) + m_d_ram[m_d_ram_ptr] = (m_d_ram[m_d_ram_ptr] & 0xf0) | (data & 0x0f); + if (!(m_cmd[5] & 0x08)) + m_d_ram[m_d_ram_ptr] = (m_d_ram[m_d_ram_ptr] & 0x0f) | (data & 0xf0); + + if (m_autoinc) + m_d_ram_ptr++; + } + m_d_ram_ptr &= 15; +} + diff --git a/src/mame/drivers/icecold.c b/src/mame/drivers/icecold.c index 06b7e1cc008..b3ddd391e38 100644 --- a/src/mame/drivers/icecold.c +++ b/src/mame/drivers/icecold.c @@ -1,44 +1,446 @@ +/*************************************************************************** + + Ice Cold Beer mechanical arcade game (c) Taito 1983 + +****************************************************************************/ #include "emu.h" #include "cpu/m6809/m6809.h" +#include "machine/6821pia.h" +#include "machine/i8279.h" +#include "sound/ay8910.h" +#include "icecold.lh" class icecold_state : public driver_device { public: icecold_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu") + m_maincpu(*this, "maincpu"), + m_ay8910_0(*this, "ay0"), + m_ay8910_1(*this, "ay1"), + m_pia1(*this, "pia1") { } -protected: - - // devices - required_device m_maincpu; + DECLARE_INPUT_CHANGED_MEMBER( test_switch_press ); + DECLARE_CUSTOM_INPUT_MEMBER( motors_limit_r ); + DECLARE_WRITE8_MEMBER( scanlines_w ); + DECLARE_WRITE8_MEMBER( digit_w ); + DECLARE_READ8_MEMBER( kbd_r ); + DECLARE_WRITE8_MEMBER( snd_ctrl_w ); + DECLARE_WRITE8_MEMBER( ay_w ); + DECLARE_READ8_MEMBER( ay_r ); + DECLARE_WRITE8_MEMBER( ay8910_0_b_w ); + DECLARE_WRITE8_MEMBER( ay8910_1_a_w ); + DECLARE_WRITE8_MEMBER( ay8910_1_b_w ); + DECLARE_READ_LINE_MEMBER( sint_r ); + DECLARE_WRITE8_MEMBER( motors_w ); // driver_device overrides virtual void machine_reset(); + + // devices + required_device m_maincpu; + required_device m_ay8910_0; + required_device m_ay8910_1; + required_device m_pia1; + + UINT8 m_digit; // scanlines from i8279 + UINT8 m_sound_latch; // sound bus latch + UINT8 m_ay_ctrl; // ay controls line + UINT8 m_motors_ctrl; // motors control + int m_sint; // SINT line + int m_motenbl; // /MOTENBL line + int m_ball_gate_sw; // ball gate switch + + // motors positions + int m_rmotor; // right motor position (0-100) + int m_lmotor; // left motor position (0-100) }; - static ADDRESS_MAP_START( icecold_map, AS_PROGRAM, 8, icecold_state ) - AM_RANGE(0x0000, 0xffff) AM_NOP + AM_RANGE(0x0000, 0x07ff) AM_RAM + AM_RANGE(0x4010, 0x4013) AM_DEVREADWRITE("pia0", pia6821_device, read, write) + AM_RANGE(0x4020, 0x4023) AM_DEVREADWRITE("pia1", pia6821_device, read, write) + AM_RANGE(0x4040, 0x4043) AM_DEVREADWRITE("pia2", pia6821_device, read, write) // not used + AM_RANGE(0x4080, 0x4080) AM_DEVREADWRITE("i8279", i8279_device, data_r, data_w ) + AM_RANGE(0x4081, 0x4081) AM_DEVREADWRITE("i8279", i8279_device, status_r, cmd_w) + AM_RANGE(0x4100, 0x4100) AM_WRITE(motors_w) + AM_RANGE(0xa000, 0xffff) AM_ROM ADDRESS_MAP_END static INPUT_PORTS_START( icecold ) + PORT_START("DSW3") + PORT_DIPNAME( 0x01, 0x01, "Automatic Attract Mode" ) PORT_DIPLOCATION("SW3:1") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "Rounds to Complete to Light Star" ) PORT_DIPLOCATION("SW3:2") + PORT_DIPSETTING( 0x00, "1 Frame" ) + PORT_DIPSETTING( 0x02, "2 Frames" ) + PORT_DIPNAME( 0x0c, 0x00, "Automatic Attract Mode Delay" ) PORT_DIPLOCATION("SW3:3,SW3:4") + PORT_DIPSETTING( 0x00, "1 Min" ) + PORT_DIPSETTING( 0x04, "5 Min" ) + PORT_DIPSETTING( 0x08, "10 Min" ) + PORT_DIPSETTING( 0x0c, "15 Min" ) + PORT_DIPNAME( 0x30, 0x00, "Manual Attract Mode Delay" ) PORT_DIPLOCATION("SW3:5,SW3:6") + PORT_DIPSETTING( 0x00, "0 Min" ) + PORT_DIPSETTING( 0x10, "2 Min" ) + PORT_DIPSETTING( 0x20, "5 Min" ) + PORT_DIPSETTING( 0x30, "10 Min" ) + PORT_DIPNAME( 0xc0, 0x00, "Difficulty (Prompt Time)" ) PORT_DIPLOCATION("SW3:7,SW3:8") + PORT_DIPSETTING( 0x00, "Easy (5, 4, 2, 1)" ) + PORT_DIPSETTING( 0x40, "Factory (4, 2, 1, 1)" ) + PORT_DIPSETTING( 0x80, "Hard (2, 2, 1, 1)" ) + PORT_DIPSETTING( 0xc0, "X-Hard (1, 1, 1, 1)" ) + + PORT_START("DSW4") + PORT_DIPNAME( 0x07, 0x00, "Dispense Option" ) PORT_DIPLOCATION("SW4:1,SW4:2,SW4:3") + PORT_DIPSETTING( 0x00, "Disabled" ) + PORT_DIPSETTING( 0x01, "2 Tickets after Hole 6, 3 Tickets after Hole 10" ) + PORT_DIPSETTING( 0x02, "1 Ticket after Holes 5 - 10" ) + PORT_DIPSETTING( 0x03, "No Tickets Dispensed" ) + PORT_DIPSETTING( 0x04, "5 Tickets after Hole 5" ) + PORT_DIPSETTING( 0x05, "No Tickets Dispensed" ) + PORT_DIPSETTING( 0x06, "5 Tickets after Hole 10" ) + PORT_DIPSETTING( 0x07, "No Tickets Dispensed" ) + PORT_DIPNAME( 0x08, 0x08, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW4:4") + PORT_DIPSETTING( 0x00, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x08, DEF_STR( 1C_1C ) ) + PORT_DIPNAME( 0x30, 0x00, "Score for Extra Ball" ) PORT_DIPLOCATION("SW4:5,SW4:6") + PORT_DIPSETTING( 0x00, "No Extra Ball" ) + PORT_DIPSETTING( 0x10, "2000" ) + PORT_DIPSETTING( 0x20, "4000" ) + PORT_DIPSETTING( 0x30, "8000" ) + PORT_DIPNAME( 0xc0, 0x00, "Bonus Countdown Speed" ) PORT_DIPLOCATION("SW4:7,SW4:8") + PORT_DIPSETTING( 0x00, "Slow" ) + PORT_DIPSETTING( 0x40, "Factory" ) + PORT_DIPSETTING( 0x80, "Fast" ) + PORT_DIPSETTING( 0xc0, "X-Fast" ) + + PORT_START("TEST") // service switch is directly hard-wired with the NMI line + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_SERVICE) PORT_CHANGED_MEMBER(DEVICE_SELF, icecold_state, test_switch_press, 1) + + PORT_START("JOY") + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP) + PORT_BIT(0x55, IP_ACTIVE_LOW, IPT_SPECIAL) PORT_CUSTOM_MEMBER(DEVICE_SELF, icecold_state, motors_limit_r, NULL) + + PORT_START("X0") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_START1) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_COIN1) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Ball Gate") PORT_CODE(KEYCODE_0) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_TILT1) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME(DEF_STR( Free_Play )) PORT_CODE(KEYCODE_3) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hopper cycle sensor") PORT_CODE(KEYCODE_6) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hopper empty") PORT_CODE(KEYCODE_7) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X1") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 1") PORT_CODE(KEYCODE_1_PAD) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 2") PORT_CODE(KEYCODE_2_PAD) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 3") PORT_CODE(KEYCODE_3_PAD) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 4") PORT_CODE(KEYCODE_4_PAD) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 5") PORT_CODE(KEYCODE_5_PAD) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 6") PORT_CODE(KEYCODE_6_PAD) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 7") PORT_CODE(KEYCODE_7_PAD) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X2") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 8") PORT_CODE(KEYCODE_8_PAD) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 9") PORT_CODE(KEYCODE_9_PAD) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Hole 10") PORT_CODE(KEYCODE_0_PAD) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Ticket feed") PORT_CODE(KEYCODE_8) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Errant Ball") PORT_CODE(KEYCODE_9) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) INPUT_PORTS_END void icecold_state::machine_reset() { + // CH-C is used for generate a 30hz clock + ay8910_set_volume(m_ay8910_0, 2, 0); + + m_rmotor = m_lmotor = 10; + m_sint = 0; + m_motenbl = 0; + m_ball_gate_sw = 1; } -static DRIVER_INIT( icecold ) +CUSTOM_INPUT_MEMBER( icecold_state::motors_limit_r ) { + UINT8 data = 0; + + if (m_rmotor <= 1) data |= 0x01; // right down limit + if (m_lmotor <= 1) data |= 0x04; // left down limit + if (m_rmotor >= 99) data |= 0x10; // right up limit + if (m_lmotor >= 99) data |= 0x40; // left up limit + + return data; } +INPUT_CHANGED_MEMBER( icecold_state::test_switch_press ) +{ + m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? ASSERT_LINE : CLEAR_LINE); +} + +WRITE8_MEMBER( icecold_state::motors_w ) +{ + m_motors_ctrl = data; +} + +WRITE8_MEMBER( icecold_state::scanlines_w ) +{ + m_digit = data; +} + +WRITE8_MEMBER( icecold_state::digit_w ) +{ + output_set_digit_value(m_digit, data & 0x7f); +} + +READ8_MEMBER( icecold_state::kbd_r ) +{ + switch(m_digit) + { + case 0: + // override the ball gate switch + return input_port_read(machine(), "X0") & ~(m_ball_gate_sw<<2); + case 1: + return input_port_read(machine(), "X1"); + case 2: + return input_port_read(machine(), "X2"); + default: + return 0xff; + } +} + + +WRITE8_MEMBER( icecold_state::snd_ctrl_w ) +{ + if (m_ay_ctrl & ~data & 0x04) + ay8910_data_address_w(m_ay8910_0, m_ay_ctrl & 0x01, m_sound_latch); + if (m_ay_ctrl & ~data & 0x20) + ay8910_data_address_w(m_ay8910_1, (m_ay_ctrl>>3) & 0x01, m_sound_latch); + + m_ay_ctrl = data; +} + +WRITE8_MEMBER( icecold_state::ay_w ) +{ + m_sound_latch = data; +} + +READ8_MEMBER( icecold_state::ay_r ) +{ + if (m_ay_ctrl & 0x02) + return ay8910_r(m_ay8910_0, 0); + if (m_ay_ctrl & 0x10) + return ay8910_r(m_ay8910_1, 0); + + return 0; +} + +WRITE8_MEMBER( icecold_state::ay8910_0_b_w ) +{ + output_set_lamp_value(1, BIT(data, 0)); + output_set_lamp_value(2, BIT(data, 1)); + output_set_lamp_value(3, BIT(data, 2)); + output_set_lamp_value(4, BIT(data, 3)); + output_set_lamp_value(5, BIT(data, 4)); + output_set_value("in_play", BIT(data, 5)); + output_set_value("good_game", BIT(data, 6)); + m_motenbl = BIT(data, 7); +} + +WRITE8_MEMBER( icecold_state::ay8910_1_a_w ) +{ + output_set_lamp_value(6, BIT(data, 0)); + output_set_lamp_value(7, BIT(data, 1)); + output_set_lamp_value(8, BIT(data, 2)); + output_set_lamp_value(9, BIT(data, 3)); + output_set_lamp_value(10, BIT(data, 4)); + output_set_value("game_over", BIT(data, 5)); + output_set_value("tilt", BIT(data, 6)); + // BIT 7 watchdog reset +} + +WRITE8_MEMBER( icecold_state::ay8910_1_b_w ) +{ + if (m_motenbl == 0) + { + output_set_value("start", BIT(data, 0)); + coin_counter_w(machine(), 1, BIT(data, 1)); // hopper counter + coin_counter_w(machine(), 2, BIT(data, 2)); // good game counter + coin_lockout_w(machine(), 0, BIT(data, 3)); // not used ?? + coin_counter_w(machine(), 0, BIT(data, 4)); // coin counter + // BIT 5 errant ball solenoid + // BIT 7 hopper motor + } +} + +READ_LINE_MEMBER( icecold_state::sint_r ) +{ + return m_sint; +} + +static TIMER_DEVICE_CALLBACK( icecold_sint_timer ) +{ + icecold_state *state = timer.machine().driver_data(); + state->m_sint = !state->m_sint; + state->m_pia1->ca1_w(state->m_sint); +} + +static TIMER_DEVICE_CALLBACK( icecold_motors_timer ) +{ + icecold_state *state = timer.machine().driver_data(); + + // /MOTENBL is set high during reset for disable the motors control + if (state->m_motenbl == 0) + { + int lmotor_dir = ((state->m_motors_ctrl & 0x0f) == 0x06) ? -1 : ((state->m_motors_ctrl & 0x0f) == 0x09) ? +1 : 0; + int rmotor_dir = ((state->m_motors_ctrl & 0xf0) == 0x60) ? -1 : ((state->m_motors_ctrl & 0xf0) == 0x90) ? +1 : 0; + + // update motors position + state->m_lmotor += lmotor_dir; + state->m_rmotor += rmotor_dir; + + // if one motor is at the top of the playfield, closes the ball gate switch, to simulate ball movement + if (state->m_lmotor >= 99 || state->m_rmotor >= 99 ) + state->m_ball_gate_sw = 1; + // if the motors are at the bottom of the playfield, opens the ball gate switch for start the game + else if (state->m_lmotor <= 1 && state->m_rmotor <= 1 ) + state->m_ball_gate_sw = 0; + + // motors are keep in range 0-100 + state->m_lmotor = MIN(state->m_lmotor, 100); + state->m_lmotor = MAX(state->m_lmotor, 0); + state->m_rmotor = MIN(state->m_rmotor, 100); + state->m_rmotor = MAX(state->m_rmotor, 0); + + if (lmotor_dir != 0 || rmotor_dir != 0) + { + output_set_value("lmotor", state->m_lmotor); + output_set_value("rmotor", state->m_rmotor); + + popmessage("Left Motor Right Motor\n%-4s %-4s\n%02d\\100 %02d\\100", + (lmotor_dir > 0) ? " up" : ((lmotor_dir < 0) ? "down" : "off"), + (rmotor_dir > 0) ? " up" : ((rmotor_dir < 0) ? "down" : "off"), state->m_lmotor, state->m_rmotor); + } + } +} + +static const pia6821_interface icecold_pia0_intf = +{ + DEVCB_INPUT_PORT("JOY"), // Port A joystick and motors limits + DEVCB_INPUT_PORT("DSW3"), // Port B DSW3 + DEVCB_NULL, // CA1 not connected + DEVCB_NULL, // CB1 input SWIRQ (IRQ from I8279) + DEVCB_NULL, // CA2 not connected + DEVCB_NULL, // CB2 LPFON + DEVCB_NULL, // Port A not used as output + DEVCB_NULL, // Port B not used as output + DEVCB_NULL, // CA2 not connected + DEVCB_NULL, // CB2 not used as output + DEVCB_CPU_INPUT_LINE("maincpu", M6809_IRQ_LINE), // IRQA connected to IRQ + DEVCB_CPU_INPUT_LINE("maincpu", M6809_IRQ_LINE) // IRQB connected to IRQ +}; + +static const pia6821_interface icecold_pia1_intf = +{ + DEVCB_DRIVER_MEMBER(icecold_state, ay_r), // Port A input sound bus + DEVCB_NULL, // Port B not used as input + DEVCB_DRIVER_LINE_MEMBER(icecold_state, sint_r), // CA1 input SINT + DEVCB_NULL, // CB1 not connected + DEVCB_NULL, // CA2 not connected + DEVCB_NULL, // CB2 not connected + DEVCB_DRIVER_MEMBER(icecold_state, ay_w), // Port A output sound bus + DEVCB_DRIVER_MEMBER(icecold_state, snd_ctrl_w), // Port B output ay controls + DEVCB_NULL, // CA2 not used as output + DEVCB_NULL, // CB2 not connected + DEVCB_CPU_INPUT_LINE("maincpu", M6809_FIRQ_LINE), // IRQA connected to FIRQ + DEVCB_CPU_INPUT_LINE("maincpu", M6809_FIRQ_LINE) // IRQB connected to FIRQ +}; + +static const pia6821_interface icecold_pia2_intf = +{ + DEVCB_NULL, // Port A not connected + DEVCB_NULL, // Port B not connected + DEVCB_NULL, // CA1 not connected + DEVCB_NULL, // CB1 not connected + DEVCB_NULL, // CA2 not connected + DEVCB_NULL, // CB2 not connected + DEVCB_NULL, // Port A not connected + DEVCB_NULL, // Port B not connected + DEVCB_NULL, // CA2 not connected + DEVCB_NULL, // CB2 not connected + DEVCB_CPU_INPUT_LINE("maincpu", M6809_IRQ_LINE), // IRQA connected to IRQ + DEVCB_CPU_INPUT_LINE("maincpu", M6809_IRQ_LINE) // IRQB connected to IRQ +}; + +static I8279_INTERFACE( icecold_i8279_intf ) +{ + DEVCB_DEVICE_LINE_MEMBER("pia0", pia6821_device, cb1_w), // irq + DEVCB_DRIVER_MEMBER(icecold_state, scanlines_w), // scan SL lines + DEVCB_DRIVER_MEMBER(icecold_state, digit_w), // display A&B + DEVCB_NULL, // BD + DEVCB_DRIVER_MEMBER(icecold_state, kbd_r), // kbd RL lines + DEVCB_NULL, // Shift key + DEVCB_NULL // Ctrl-Strobe line +}; + +static const ay8910_interface icecold_ay8910_0_intf = +{ + AY8910_LEGACY_OUTPUT, + AY8910_DEFAULT_LOADS, + DEVCB_INPUT_PORT("DSW4"), + DEVCB_NULL, + DEVCB_NULL, + DEVCB_DRIVER_MEMBER(icecold_state, ay8910_0_b_w) +}; + +static const ay8910_interface icecold_ay8910_1_intf = +{ + AY8910_LEGACY_OUTPUT, + AY8910_DEFAULT_LOADS, + DEVCB_NULL, + DEVCB_NULL, + DEVCB_DRIVER_MEMBER(icecold_state, ay8910_1_a_w), + DEVCB_DRIVER_MEMBER(icecold_state, ay8910_1_b_w) +}; + + static MACHINE_CONFIG_START( icecold, icecold_state ) /* basic machine hardware */ - MCFG_CPU_ADD("maincpu", M6809, 1000000) + MCFG_CPU_ADD("maincpu", M6809, XTAL_6MHz/4) MCFG_CPU_PROGRAM_MAP(icecold_map) + + MCFG_PIA6821_ADD( "pia0", icecold_pia0_intf ) + MCFG_PIA6821_ADD( "pia1", icecold_pia1_intf ) + MCFG_PIA6821_ADD( "pia2", icecold_pia2_intf ) + + MCFG_I8279_ADD("i8279", XTAL_6MHz/4, icecold_i8279_intf) + + // 30Hz signal from CH-C of ay0 + MCFG_TIMER_ADD_PERIODIC("sint_timer", icecold_sint_timer, attotime::from_hz(30)) + + // for update motors position + MCFG_TIMER_ADD_PERIODIC("motors_timer", icecold_motors_timer, attotime::from_msec(50)) + + // video hardware + MCFG_DEFAULT_LAYOUT(layout_icecold) + + // sound hardware + MCFG_SPEAKER_STANDARD_MONO("mono") + MCFG_SOUND_ADD("ay0", AY8910, XTAL_6MHz/4) + MCFG_SOUND_CONFIG(icecold_ay8910_0_intf) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) + + MCFG_SOUND_ADD("ay1", AY8910, XTAL_6MHz/4) + MCFG_SOUND_CONFIG(icecold_ay8910_1_intf) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) MACHINE_CONFIG_END /*------------------------------------------------------------------- @@ -50,5 +452,15 @@ ROM_START(icecold) ROM_LOAD("icb24.bin", 0xc000, 0x2000, CRC(2d1e7282) SHA1(6f170e24f71d1504195face5f67176b55c933eef)) ROM_END +/*------------------------------------------------------------------- +/ Zeke's Peak +/-------------------------------------------------------------------*/ +ROM_START(zekepeak) + ROM_REGION(0x10000, "maincpu", 0) + ROM_LOAD("zp23.bin", 0xe000, 0x2000, CRC(ef959586) SHA1(7f8a4787b340bfa34180164806b181b5fb4e5cfa)) + ROM_LOAD("zp24.bin", 0xc000, 0x2000, CRC(ee90c8f5) SHA1(27a513000e90536e485ccdf43786b415b3c95bd7)) +ROM_END -GAME(1983, icecold, 0, icecold, icecold, icecold, ROT0, "Taito", "Ice Cold Beer", GAME_NOT_WORKING | GAME_NO_SOUND | GAME_MECHANICAL) + +GAME(1983, icecold , 0 , icecold, icecold, 0, ROT0, "Taito", "Ice Cold Beer", GAME_NOT_WORKING | GAME_NO_SOUND | GAME_MECHANICAL) +GAME(1983, zekepeak, icecold, icecold, icecold, 0, ROT0, "Taito", "Zeke's Peak" , GAME_NOT_WORKING | GAME_NO_SOUND | GAME_MECHANICAL) diff --git a/src/mame/layout/icecold.lay b/src/mame/layout/icecold.lay new file mode 100644 index 00000000000..5d9edaa3682 --- /dev/null +++ b/src/mame/layout/icecold.lay @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 52a73b2a9a3..403145bd188 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -20315,6 +20315,7 @@ empsback // icecold.c icecold +zekepeak // inder.c ind250cc diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 390ce885c3b..6ca4c978b34 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -2012,6 +2012,8 @@ $(DRIVERS)/grchamp.o: $(LAYOUT)/grchamp.lh $(DRIVERS)/highvdeo.o: $(LAYOUT)/fashion.lh +$(DRIVERS)/icecold.o: $(LAYOUT)/icecold.lh + $(DRIVERS)/igspoker.o: $(LAYOUT)/igspoker.lh $(DRIVERS)/jankenmn.o: $(LAYOUT)/jankenmn.lh