/***************************************************************************
Williams 6809 system
***************************************************************************/
#include "driver.h"
#include "audio/williams.h"
#include "cpu/m6800/m6800.h"
#include "cpu/m6809/m6809.h"
#include "machine/6821pia.h"
#include "machine/ticket.h"
#include "williams.h"
#include "sound/dac.h"
#include "sound/hc55516.h"
/* timers */
static emu_timer *scanline_timer;
static emu_timer *scan240_timer;
static emu_timer *scan254_timer;
/* banking addresses set by the drivers */
UINT8 *mayday_protection;
/* internal bank switching tracking */
static UINT8 blaster_bank;
static UINT8 vram_bank;
/* other stuff */
static UINT16 joust2_current_sound_data;
/* older-Williams routines */
static void williams_main_irq(int state);
static void williams_main_firq(int state);
static void williams_snd_irq(int state);
static WRITE8_HANDLER( williams_snd_cmd_w );
static WRITE8_HANDLER( playball_snd_cmd_w );
/* input port mapping */
static UINT8 port_select;
static WRITE8_HANDLER( williams_port_select_w );
static READ8_HANDLER( williams_input_port_0_3_r );
static READ8_HANDLER( williams_input_port_49way_0_5_r );
static READ8_HANDLER( williams_input_port_1_4_r );
static READ8_HANDLER( williams_49way_port_0_r );
/* newer-Williams routines */
static WRITE8_HANDLER( williams2_snd_cmd_w );
/* Lotto Fun-specific code */
static READ8_HANDLER( lottofun_input_port_0_r );
/* Turkey Shoot-specific code */
static READ8_HANDLER( tshoot_input_port_0_3_r );
static WRITE8_HANDLER( tshoot_lamp_w );
static WRITE8_HANDLER( tshoot_maxvol_w );
/* Joust 2-specific code */
static WRITE8_HANDLER( joust2_snd_cmd_w );
static WRITE8_HANDLER( joust2_pia_3_cb1_w );
/*************************************
*
* Generic old-Williams PIA interfaces
*
*************************************/
/* Generic PIA 0, maps to input ports 0 and 1 */
const pia6821_interface williams_pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, input_port_1_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
/*irqs : A/B */ 0, 0
};
/* Generic muxing PIA 0, maps to input ports 0/3 and 1; port select is CB2 */
const pia6821_interface williams_muxed_pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_0_3_r, input_port_1_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, 0, williams_port_select_w,
/*irqs : A/B */ 0, 0
};
/* Generic dual muxing PIA 0, maps to input ports 0/3 and 1/4; port select is CB2 */
const pia6821_interface williams_dual_muxed_pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_0_3_r, williams_input_port_1_4_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, 0, williams_port_select_w,
/*irqs : A/B */ 0, 0
};
/* Generic 49-way joystick PIA 0 for Sinistar/Blaster */
const pia6821_interface williams_49way_pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ williams_49way_port_0_r, input_port_1_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
/*irqs : A/B */ 0, 0
};
/* Muxing 49-way joystick PIA 0 for Blaster kit */
const pia6821_interface williams_49way_muxed_pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_49way_0_5_r, input_port_1_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, 0, williams_port_select_w,
/*irqs : A/B */ 0, 0
};
/* Generic PIA 1, maps to input port 2, sound command out, and IRQs */
const pia6821_interface williams_pia_1_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, williams_snd_cmd_w, 0, 0,
/*irqs : A/B */ williams_main_irq, williams_main_irq
};
/* Generic PIA 2, maps to DAC data in and sound IRQs */
const pia6821_interface williams_snd_pia_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ DAC_0_data_w, 0, 0, 0,
/*irqs : A/B */ williams_snd_irq, williams_snd_irq
};
/*************************************
*
* Game-specific old-Williams PIA interfaces
*
*************************************/
/* Special PIA 0 for Lotto Fun, to handle the controls and ticket dispenser */
const pia6821_interface lottofun_pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ lottofun_input_port_0_r, input_port_1_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, ticket_dispenser_w, 0, 0,
/*irqs : A/B */ 0, 0
};
/* Special PIA 2 for Sinistar, to handle the CVSD */
const pia6821_interface sinistar_snd_pia_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ DAC_0_data_w, 0, hc55516_0_digit_w, hc55516_0_clock_w,
/*irqs : A/B */ williams_snd_irq, williams_snd_irq
};
/* Special PIA 1 for PlayBall, doesn't set the high bits on sound commands */
const pia6821_interface playball_pia_1_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, playball_snd_cmd_w, 0, 0,
/*irqs : A/B */ williams_main_irq, williams_main_irq
};
/* extra PIA 3 for Speed Ball */
const pia6821_interface spdball_pia_3_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ input_port_3_r, input_port_4_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
/*irqs : A/B */ 0, 0
};
/*************************************
*
* Generic later-Williams PIA interfaces
*
*************************************/
/* Generic muxing PIA 0, maps to input ports 0/3 and 1; port select is CA2 */
const pia6821_interface williams2_muxed_pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_0_3_r, input_port_1_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, williams_port_select_w, 0,
/*irqs : A/B */ 0, 0
};
/* Generic PIA 1, maps to input port 2, sound command out, and IRQs */
const pia6821_interface williams2_pia_1_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, williams2_snd_cmd_w, 0, pia_2_ca1_w,
/*irqs : A/B */ williams_main_irq, williams_main_irq
};
/* Generic PIA 2, maps to DAC data in and sound IRQs */
const pia6821_interface williams2_snd_pia_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ pia_1_portb_w, DAC_0_data_w, pia_1_cb1_w, 0,
/*irqs : A/B */ williams_snd_irq, williams_snd_irq
};
/*************************************
*
* Game-specific later-Williams PIA interfaces
*
*************************************/
/* Mystic Marathon PIA 0 */
const pia6821_interface mysticm_pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, input_port_1_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
/*irqs : A/B */ williams_main_firq, williams_main_irq
};
/* Turkey Shoot PIA 0 */
const pia6821_interface tshoot_pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ tshoot_input_port_0_3_r, input_port_1_r, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, tshoot_lamp_w, williams_port_select_w, 0,
/*irqs : A/B */ williams_main_irq, williams_main_irq
};
/* Turkey Shoot PIA 2 */
const pia6821_interface tshoot_snd_pia_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ pia_1_portb_w, DAC_0_data_w, pia_1_cb1_w, tshoot_maxvol_w,
/*irqs : A/B */ williams_snd_irq, williams_snd_irq
};
/* Joust 2 PIA 1 */
const pia6821_interface joust2_pia_1_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, joust2_snd_cmd_w, joust2_pia_3_cb1_w, pia_2_ca1_w,
/*irqs : A/B */ williams_main_irq, williams_main_irq
};
/*************************************
*
* Older Williams interrupts
*
*************************************/
static TIMER_CALLBACK( williams_va11_callback )
{
int scanline = param;
/* the IRQ signal comes into CB1, and is set to VA11 */
pia_1_cb1_w(0, scanline & 0x20);
/* update the screen while we're here */
video_screen_update_partial(0, scanline - 1);
/* set a timer for the next update */
scanline++;
if (scanline >= 256) scanline = 0;
timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, scanline, 0), scanline, attotime_zero);
}
static TIMER_CALLBACK( williams_count240_off_callback )
{
/* the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 */
pia_1_ca1_w(0, 0);
}
static TIMER_CALLBACK( williams_count240_callback )
{
/* the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 */
pia_1_ca1_w(0, 1);
/* set a timer to turn it off once the scanline counter resets */
timer_set(video_screen_get_time_until_pos(0, 0, 0), 0, williams_count240_off_callback);
/* set a timer for next frame */
timer_adjust(scan240_timer, video_screen_get_time_until_pos(0, 240, 0), 0, attotime_zero);
}
static void williams_main_irq(int state)
{
/* IRQ to the main CPU */
cpunum_set_input_line(0, M6809_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
}
static void williams_main_firq(int state)
{
/* FIRQ to the main CPU */
cpunum_set_input_line(0, M6809_FIRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
}
static void williams_snd_irq(int state)
{
/* IRQ to the sound CPU */
cpunum_set_input_line(1, M6800_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
}
/*************************************
*
* Older Williams initialization
*
*************************************/
static void williams_common_init(void)
{
/* reset the PIAs */
pia_reset();
/* reset the ticket dispenser (Lotto Fun) */
ticket_dispenser_init(70, TICKET_MOTOR_ACTIVE_LOW, TICKET_STATUS_ACTIVE_HIGH);
/* set a timer to go off every 16 scanlines, to toggle the VA11 line and update the screen */
scanline_timer = timer_alloc(williams_va11_callback);
timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, 0, 0), 0, attotime_zero);
/* also set a timer to go off on scanline 240 */
scan240_timer = timer_alloc(williams_count240_callback);
timer_adjust(scan240_timer, video_screen_get_time_until_pos(0, 240, 0), 0, attotime_zero);
state_save_register_global(vram_bank);
}
MACHINE_RESET( williams )
{
williams_common_init();
/* configure the memory bank */
memory_configure_bank(1, 0, 1, williams_videoram, 0);
memory_configure_bank(1, 1, 1, memory_region(REGION_CPU1) + 0x10000, 0);
}
/*************************************
*
* Newer Williams interrupts
*
*************************************/
static TIMER_CALLBACK( williams2_va11_callback )
{
int scanline = param;
/* the IRQ signal comes into CB1, and is set to VA11 */
pia_0_cb1_w(0, scanline & 0x20);
pia_1_ca1_w(0, scanline & 0x20);
/* update the screen while we're here */
video_screen_update_partial(0, scanline);
/* set a timer for the next update */
scanline++;
if (scanline >= 256) scanline = 0;
timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, scanline, 0), scanline, attotime_zero);
}
static TIMER_CALLBACK( williams2_endscreen_off_callback )
{
/* the /ENDSCREEN signal comes into CA1 */
pia_0_ca1_w(0, 1);
}
static TIMER_CALLBACK( williams2_endscreen_callback )
{
/* the /ENDSCREEN signal comes into CA1 */
pia_0_ca1_w(0, 0);
/* set a timer to turn it off once the scanline counter resets */
timer_set(video_screen_get_time_until_pos(0, 8, 0), 0, williams2_endscreen_off_callback);
/* set a timer for next frame */
timer_adjust(scan254_timer, video_screen_get_time_until_pos(0, 254, 0), 0, attotime_zero);
}
/*************************************
*
* Newer Williams initialization
*
*************************************/
static void williams2_postload(void)
{
williams2_bank_select_w(0, vram_bank);
}
MACHINE_RESET( williams2 )
{
/* reset the PIAs */
pia_reset();
/* configure memory banks */
memory_configure_bank(1, 0, 1, williams_videoram, 0);
memory_configure_bank(1, 1, 4, memory_region(REGION_CPU1) + 0x10000, 0x10000);
/* make sure our banking is reset */
williams2_bank_select_w(0, 0);
/* set a timer to go off every 16 scanlines, to toggle the VA11 line and update the screen */
scanline_timer = timer_alloc(williams2_va11_callback);
timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, 0, 0), 0, attotime_zero);
/* also set a timer to go off on scanline 254 */
scan254_timer = timer_alloc(williams2_endscreen_callback);
timer_adjust(scan254_timer, video_screen_get_time_until_pos(0, 254, 0), 0, attotime_zero);
state_save_register_global(vram_bank);
state_save_register_func_postload(williams2_postload);
}
/*************************************
*
* VRAM/ROM banking
*
*************************************/
WRITE8_HANDLER( williams_vram_select_w )
{
/* VRAM/ROM banking from bit 0 */
vram_bank = data & 0x01;
memory_set_bank(1, vram_bank);
/* cocktail flip from bit 1 */
williams_cocktail = data & 0x02;
}
WRITE8_HANDLER( williams2_bank_select_w )
{
vram_bank = data & 0x07;
/* the low two bits control the paging */
switch (vram_bank & 0x03)
{
/* page 0 is video ram */
case 0:
memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, 0x8fff, 0, 0, MRA8_BANK1);
memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0x87ff, 0, 0, MWA8_BANK4);
memory_set_bank(1, 0);
memory_set_bankptr(4, &williams_videoram[0x8000]);
break;
/* pages 1 and 2 are ROM */
case 1:
case 2:
memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, 0x8fff, 0, 0, MRA8_BANK1);
memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0x87ff, 0, 0, MWA8_BANK4);
memory_set_bank(1, 1 + ((vram_bank & 6) >> 1));
memory_set_bankptr(4, &williams_videoram[0x8000]);
break;
/* page 3 accesses palette RAM; the remaining areas are as if page 1 ROM was selected */
case 3:
memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0x87ff, 0, 0, williams2_paletteram_r);
memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0x87ff, 0, 0, williams2_paletteram_w);
memory_set_bank(1, 1 + ((vram_bank & 4) >> 1));
break;
}
}
/*************************************
*
* Sound commands
*
*************************************/
static TIMER_CALLBACK( williams_deferred_snd_cmd_w )
{
pia_2_portb_w(0, param);
pia_2_cb1_w(0, (param == 0xff) ? 0 : 1);
}
WRITE8_HANDLER( williams_snd_cmd_w )
{
/* the high two bits are set externally, and should be 1 */
timer_call_after_resynch(data | 0xc0, williams_deferred_snd_cmd_w);
}
WRITE8_HANDLER( playball_snd_cmd_w )
{
timer_call_after_resynch(data, williams_deferred_snd_cmd_w);
}
static TIMER_CALLBACK( williams2_deferred_snd_cmd_w )
{
pia_2_porta_w(0, param);
}
static WRITE8_HANDLER( williams2_snd_cmd_w )
{
timer_call_after_resynch(data, williams2_deferred_snd_cmd_w);
}
/*************************************
*
* General input port handlers
*
*************************************/
WRITE8_HANDLER( williams_port_select_w )
{
port_select = data;
}
READ8_HANDLER( williams_input_port_0_3_r )
{
return readinputport(port_select ? 3 : 0);
}
READ8_HANDLER( williams_input_port_1_4_r )
{
return readinputport(port_select ? 4 : 1);
}
/*
* Williams 49-way joystick
*
* The joystick works on a 7x7 grid system:
*
* + + + | + + +
* + + + | + + +
* + + + | + + +
* ------+------
* + + + | + + +
* + + + | + + +
* + + + | + + +
*
* Each axis has 7 positions, reported as follows
* in 4 bits/axis:
*
* 0000 = left/up full
* 0100 = left/up 2/3
* 0110 = left/up 1/3
* 0111 = center
* 1011 = right/down 1/3
* 1001 = right/down 2/3
* 1000 = right/down full
*/
READ8_HANDLER( williams_49way_port_0_r )
{
static const UINT8 translate49[7] = { 0x0, 0x4, 0x6, 0x7, 0xb, 0x9, 0x8 };
return (translate49[readinputportbytag("49WAYX") >> 4] << 4) | translate49[readinputportbytag("49WAYY") >> 4];
}
READ8_HANDLER( williams_input_port_49way_0_5_r )
{
if (port_select)
return williams_49way_port_0_r(0);
else
return readinputport(5);
}
/*************************************
*
* CMOS access
*
*************************************/
WRITE8_HANDLER( williams_cmos_w )
{
/* only 4 bits are valid */
generic_nvram[offset] = data | 0xf0;
}
WRITE8_HANDLER( bubbles_cmos_w )
{
/* bubbles has additional CMOS for a full 8 bits */
generic_nvram[offset] = data;
}
/*************************************
*
* Watchdog
*
*************************************/
WRITE8_HANDLER( williams_watchdog_reset_w )
{
/* yes, the data bits are checked for this specific value */
if (data == 0x39)
watchdog_reset_w(0,0);
}
WRITE8_HANDLER( williams2_watchdog_reset_w )
{
/* yes, the data bits are checked for this specific value */
if ((data & 0x3f) == 0x14)
watchdog_reset_w(0,0);
}
/*************************************
*
* Diagnostic controls
*
*************************************/
WRITE8_HANDLER( williams2_7segment_w )
{
int n;
char dot;
switch (data & 0x7F)
{
case 0x40: n = 0; break;
case 0x79: n = 1; break;
case 0x24: n = 2; break;
case 0x30: n = 3; break;
case 0x19: n = 4; break;
case 0x12: n = 5; break;
case 0x02: n = 6; break;
case 0x03: n = 6; break;
case 0x78: n = 7; break;
case 0x00: n = 8; break;
case 0x18: n = 9; break;
case 0x10: n = 9; break;
default: n =-1; break;
}
if ((data & 0x80) == 0x00)
dot = '.';
else
dot = ' ';
if (n == -1)
logerror("[ %c]\n", dot);
else
logerror("[%d%c]\n", n, dot);
}
/*************************************
*
* Defender-specific routines
*
*************************************/
static void defender_postload(void)
{
defender_bank_select_w(0, vram_bank);
}
MACHINE_RESET( defender )
{
williams_common_init();
/* configure the banking and make sure it is reset to 0 */
memory_configure_bank(1, 0, 9, &memory_region(REGION_CPU1)[0x10000], 0x1000);
defender_bank_select_w(0, 0);
state_save_register_func_postload(defender_postload);
}
WRITE8_HANDLER( defender_video_control_w )
{
williams_cocktail = data & 0x01;
}
WRITE8_HANDLER( defender_bank_select_w )
{
vram_bank = data & 0x0f;
/* set bank address */
switch (data)
{
/* page 0 is I/O space */
case 0:
defender_install_io_space();
break;
/* pages 1-9 map to ROM banks */
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MRA8_BANK1);
memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MWA8_UNMAP);
memory_set_bank(1, vram_bank - 1);
break;
/* pages A-F are not connected */
default:
memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MRA8_NOP);
memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MWA8_NOP);
break;
}
}
/*************************************
*
* Mayday-specific routines
*
*************************************/
READ8_HANDLER( mayday_protection_r )
{
/* Mayday does some kind of protection check that is not currently understood */
/* However, the results of that protection check are stored at $a190 and $a191 */
/* These are compared against $a193 and $a194, respectively. Thus, to prevent */
/* the protection from resetting the machine, we just return $a193 for $a190, */
/* and $a194 for $a191. */
return mayday_protection[offset + 3];
}
/*************************************
*
* Sinistar-specific routines
*
*************************************/
WRITE8_HANDLER( sinistar_vram_select_w )
{
/* low two bits are standard */
williams_vram_select_w(offset, data);
/* window enable from bit 2 (clips to 0x7400) */
williams_blitter_window_enable = data & 0x04;
}
/*************************************
*
* Blaster-specific routines
*
*************************************/
MACHINE_RESET( blaster )
{
williams_common_init();
/* banking is different for blaster */
memory_configure_bank(1, 0, 1, williams_videoram, 0);
memory_configure_bank(1, 1, 16, memory_region(REGION_CPU1) + 0x18000, 0x4000);
memory_configure_bank(2, 0, 1, williams_videoram + 0x4000, 0);
memory_configure_bank(2, 1, 16, memory_region(REGION_CPU1) + 0x10000, 0x0000);
state_save_register_global(blaster_bank);
}
INLINE void update_blaster_banking(void)
{
memory_set_bank(1, vram_bank * (blaster_bank + 1));
memory_set_bank(2, vram_bank * (blaster_bank + 1));
}
WRITE8_HANDLER( blaster_vram_select_w )
{
/* VRAM/ROM banking from bit 0 */
vram_bank = data & 0x01;
update_blaster_banking();
/* cocktail flip from bit 1 */
williams_cocktail = data & 0x02;
/* window enable from bit 2 (clips to 0x9700) */
williams_blitter_window_enable = data & 0x04;
}
WRITE8_HANDLER( blaster_bank_select_w )
{
blaster_bank = data & 15;
update_blaster_banking();
}
/*************************************
*
* Lotto Fun-specific routines
*
*************************************/
static READ8_HANDLER( lottofun_input_port_0_r )
{
/* merge in the ticket dispenser status */
return input_port_0_r(offset) | ticket_dispenser_r(offset);
}
/*************************************
*
* Turkey Shoot-specific routines
*
*************************************/
static READ8_HANDLER( tshoot_input_port_0_3_r )
{
/* merge in the gun inputs with the standard data */
int data = williams_input_port_0_3_r(offset);
int gun = (data & 0x3f) ^ ((data & 0x3f) >> 1);
return (data & 0xc0) | gun;
}
static WRITE8_HANDLER( tshoot_maxvol_w )
{
/* something to do with the sound volume */
logerror("tshoot maxvol = %d (pc:%x)\n", data, activecpu_get_pc());
}
static WRITE8_HANDLER( tshoot_lamp_w )
{
/* set the grenade lamp */
set_led_status(0,data & 0x04);
/* set the gun lamp */
set_led_status(1,data & 0x08);
#if 0
/* gun coil */
if (data & 0x10)
mame_printf_debug("[gun coil] ");
else
mame_printf_debug(" ");
/* feather coil */
if (data & 0x20)
mame_printf_debug("[feather coil] ");
else
mame_printf_debug(" ");
mame_printf_debug("\n");
#endif
}
/*************************************
*
* Joust 2-specific routines
*
*************************************/
MACHINE_START( joust2 )
{
williams_cvsd_init(3);
}
MACHINE_RESET( joust2 )
{
/* standard init */
machine_reset_williams2(machine);
pia_set_input_ca1(3, 1);
state_save_register_global(joust2_current_sound_data);
}
static TIMER_CALLBACK( joust2_deferred_snd_cmd_w )
{
pia_2_porta_w(0, param & 0xff);
}
static WRITE8_HANDLER( joust2_pia_3_cb1_w )
{
joust2_current_sound_data = (joust2_current_sound_data & ~0x100) | ((data << 8) & 0x100);
pia_3_cb1_w(offset, data);
}
static WRITE8_HANDLER( joust2_snd_cmd_w )
{
joust2_current_sound_data = (joust2_current_sound_data & ~0xff) | (data & 0xff);
williams_cvsd_data_w(joust2_current_sound_data);
timer_call_after_resynch(joust2_current_sound_data, joust2_deferred_snd_cmd_w);
}