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]
This commit is contained in:
Scott Stone 2012-04-15 00:50:27 +00:00
parent 299ce60427
commit a79525b271
7 changed files with 1058 additions and 10 deletions

2
.gitattributes vendored
View File

@ -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

View File

@ -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 \

499
src/emu/machine/i8279.c Normal file
View File

@ -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>;
//-------------------------------------------------
// 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<const i8279_interface *>(static_config());
if (intf != NULL)
{
*static_cast<i8279_interface *>(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<i8279_device*>(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;
}

View File

@ -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<cpu_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<cpu_device> m_maincpu;
required_device<device_t> m_ay8910_0;
required_device<device_t> m_ay8910_1;
required_device<pia6821_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<icecold_state>();
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<icecold_state>();
// /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)

131
src/mame/layout/icecold.lay Normal file
View File

@ -0,0 +1,131 @@
<?xml version="1.0"?>
<mamelayout version="2">
<element name="digit" defstate="0">
<led7seg>
<color red="1.0" green="0.0" blue="0.0" />
</led7seg>
</element>
<element name="lamp" defstate="0">
<disk state="0">
<color red="0.4" green="0.4" blue="0.0" />
</disk>
<disk state="1">
<color red="0.9" green="0.9" blue="0.0" />
</disk>
</element>
<element name="str_holes">
<text string="Playfiel Holes"/>
</element>
<element name="str_play">
<text string="Play" align="2"/>
</element>
<element name="str_good_game">
<text string="Good Game" align="2"/>
</element>
<element name="str_game_over">
<text string="Game Over" align="2"/>
</element>
<element name="str_tilt">
<text string="Tilt" align="2"/>
</element>
<element name="str_start">
<text string="Start" align="2"/>
</element>
<view name="Simple">
<!-- Display line -->
<bezel name="digit0" element="digit">
<bounds x="10" y="190" width="50" height="80" />
</bezel>
<bezel name="digit1" element="digit">
<bounds x="70" y="190" width="50" height="80" />
</bezel>
<bezel name="digit2" element="digit">
<bounds x="130" y="190" width="50" height="80" />
</bezel>
<bezel name="digit3" element="digit">
<bounds x="190" y="190" width="50" height="80" />
</bezel>
<bezel name="digit4" element="digit">
<bounds x="10" y="100" width="50" height="80" />
</bezel>
<bezel name="digit5" element="digit">
<bounds x="70" y="100" width="50" height="80" />
</bezel>
<bezel name="digit6" element="digit">
<bounds x="130" y="100" width="50" height="80" />
</bezel>
<bezel name="digit7" element="digit">
<bounds x="10" y="10" width="50" height="80" />
</bezel>
<!-- Playfiel Holes lamps -->
<bezel name="lbl_holes" element="str_holes">
<bounds x="100" y="27" width="100" height="10" />
</bezel>
<bezel name="lamp1" element="lamp">
<bounds x="100" y="40" width="8" height="8" />
</bezel>
<bezel name="lamp2" element="lamp">
<bounds x="110" y="40" width="8" height="8" />
</bezel>
<bezel name="lamp3" element="lamp">
<bounds x="120" y="40" width="8" height="8" />
</bezel>
<bezel name="lamp4" element="lamp">
<bounds x="130" y="40" width="8" height="8" />
</bezel>
<bezel name="lamp5" element="lamp">
<bounds x="140" y="40" width="8" height="8" />
</bezel>
<bezel name="lamp6" element="lamp">
<bounds x="150" y="40" width="8" height="8" />
</bezel>
<bezel name="lamp7" element="lamp">
<bounds x="160" y="40" width="8" height="8" />
</bezel>
<bezel name="lamp8" element="lamp">
<bounds x="170" y="40" width="8" height="8" />
</bezel>
<bezel name="lamp9" element="lamp">
<bounds x="180" y="40" width="8" height="8" />
</bezel>
<bezel name="lamp10" element="lamp">
<bounds x="190" y="40" width="8" height="8" />
</bezel>
<!-- Panels -->
<bezel name="lbl_play" element="str_play">
<bounds x="235" y="40" width="13" height="10" />
</bezel>
<bezel name="in_play" element="lamp">
<bounds x="250" y="40" width="8" height="8" />
</bezel>
<bezel name="lbl_good_game" element="str_good_game">
<bounds x="218" y="50" width="30" height="10" />
</bezel>
<bezel name="good_game" element="lamp">
<bounds x="250" y="50" width="8" height="8" />
</bezel>
<bezel name="lbl_game_over" element="str_game_over">
<bounds x="218" y="60" width="30" height="10" />
</bezel>
<bezel name="game_over" element="lamp">
<bounds x="250" y="60" width="8" height="8" />
</bezel>
<bezel name="lbl_tilt" element="str_tilt">
<bounds x="237" y="70" width="11" height="10" />
</bezel>
<bezel name="tilt" element="lamp">
<bounds x="250" y="70" width="8" height="8" />
</bezel>
<bezel name="lbl_start" element="str_start">
<bounds x="232" y="80" width="16" height="10" />
</bezel>
<bezel name="start" element="lamp">
<bounds x="250" y="80" width="8" height="8" />
</bezel>
</view>
</mamelayout>

View File

@ -20315,6 +20315,7 @@ empsback
// icecold.c
icecold
zekepeak
// inder.c
ind250cc

View File

@ -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