diff options
Diffstat (limited to 'trunk/src/emu/machine/ldv1000.c')
-rw-r--r-- | trunk/src/emu/machine/ldv1000.c | 761 |
1 files changed, 761 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/ldv1000.c b/trunk/src/emu/machine/ldv1000.c new file mode 100644 index 00000000000..7ee15ce8179 --- /dev/null +++ b/trunk/src/emu/machine/ldv1000.c @@ -0,0 +1,761 @@ +/************************************************************************* + + ldv1000.c + + Pioneer LD-V1000 laserdisc emulation. + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +************************************************************************** + + Still to do: + + * fix issues + * add OSD + +*************************************************************************/ + +#include "emu.h" +#include "ldcore.h" +#include "machine/8255ppi.h" +#include "machine/z80ctc.h" +#include "cpu/z80/z80.h" +#include "cpu/z80/z80daisy.h" + + + +/*************************************************************************** + DEBUGGING +***************************************************************************/ + +#define LOG_PORT_IO 0 +#define LOG_STATUS_CHANGES 0 +#define LOG_FRAMES_SEEN 0 +#define LOG_COMMANDS 0 + + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define SCAN_SPEED (2000 / 30) /* 2000 frames/second */ +#define SEEK_FAST_SPEED (4000 / 30) /* 4000 frames/second */ + +#define MULTIJUMP_TRACK_TIME attotime::from_usec(50) + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +/* player-specific data */ +struct _ldplayer_data +{ + /* low-level emulation data */ + device_t *cpu; /* CPU index of the Z80 */ + device_t *ctc; /* CTC device */ + timer_device * multitimer; /* multi-jump timer device */ + + /* communication status */ + UINT8 command; /* command byte to the player */ + UINT8 status; /* status byte from the player */ + UINT8 vsync; /* VSYNC state */ + + /* I/O port states */ + UINT8 counter_start; /* starting value for counter */ + UINT8 counter; /* current counter value */ + UINT8 portc0; /* port C on PPI 0 */ + UINT8 portb1; /* port B on PPI 1 */ + UINT8 portc1; /* port C on PPI 1 */ + + /* display/decode circuit emulation */ + UINT8 portselect; /* selection of which port to access */ + UINT8 display[2][20]; /* display lines */ + UINT8 dispindex; /* index within the display line */ + UINT8 vbi[7*3]; /* VBI data */ + UINT8 vbiready; /* VBI ready flag */ + UINT8 vbiindex; /* index within the VBI data */ +}; + + + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +static void ldv1000_init(laserdisc_state *ld); +static void ldv1000_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime); +static INT32 ldv1000_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime); +static void ldv1000_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data); +static UINT8 ldv1000_status_strobe_r(laserdisc_state *ld); +static UINT8 ldv1000_command_strobe_r(laserdisc_state *ld); +static UINT8 ldv1000_status_r(laserdisc_state *ld); + +static TIMER_CALLBACK( vsync_off ); +static TIMER_CALLBACK( vbi_data_fetch ); +static TIMER_DEVICE_CALLBACK( multijump_timer ); + +static void ctc_interrupt(device_t *device, int state); + +static WRITE8_HANDLER( decoder_display_port_w ); +static READ8_HANDLER( decoder_display_port_r ); +static READ8_HANDLER( controller_r ); +static WRITE8_HANDLER( controller_w ); +static WRITE8_DEVICE_HANDLER( ppi0_porta_w ); +static READ8_DEVICE_HANDLER( ppi0_portb_r ); +static READ8_DEVICE_HANDLER( ppi0_portc_r ); +static WRITE8_DEVICE_HANDLER( ppi0_portc_w ); +static READ8_DEVICE_HANDLER( ppi1_porta_r ); +static WRITE8_DEVICE_HANDLER( ppi1_portb_w ); +static WRITE8_DEVICE_HANDLER( ppi1_portc_w ); + + + +/*************************************************************************** + LD-V1000 ROM AND MACHINE INTERFACES +***************************************************************************/ + +static ADDRESS_MAP_START( ldv1000_map, AS_PROGRAM, 8 ) + AM_RANGE(0x0000, 0x1fff) AM_MIRROR(0x6000) AM_ROM + AM_RANGE(0x8000, 0x87ff) AM_MIRROR(0x3800) AM_RAM + AM_RANGE(0xc000, 0xc003) AM_MIRROR(0x9ff0) AM_DEVREADWRITE("ldvppi0", ppi8255_r, ppi8255_w) + AM_RANGE(0xc004, 0xc007) AM_MIRROR(0x9ff0) AM_DEVREADWRITE("ldvppi1", ppi8255_r, ppi8255_w) +ADDRESS_MAP_END + + +static ADDRESS_MAP_START( ldv1000_portmap, AS_IO, 8 ) + ADDRESS_MAP_GLOBAL_MASK(0xff) + AM_RANGE(0x00, 0x07) AM_MIRROR(0x38) AM_READWRITE(decoder_display_port_r, decoder_display_port_w) + AM_RANGE(0x40, 0x40) AM_MIRROR(0x3f) AM_READ(controller_r) + AM_RANGE(0x80, 0x80) AM_MIRROR(0x3f) AM_WRITE(controller_w) + AM_RANGE(0xc0, 0xc3) AM_MIRROR(0x3c) AM_DEVREADWRITE("ldvctc", z80ctc_r, z80ctc_w) +ADDRESS_MAP_END + + +static const ppi8255_interface ppi0intf = +{ + DEVCB_NULL, DEVCB_HANDLER(ppi0_portb_r), DEVCB_HANDLER(ppi0_portc_r), + DEVCB_HANDLER(ppi0_porta_w), DEVCB_NULL, DEVCB_HANDLER(ppi0_portc_w) +}; + + +static const ppi8255_interface ppi1intf = +{ + DEVCB_HANDLER(ppi1_porta_r), DEVCB_NULL, DEVCB_NULL, + DEVCB_NULL, DEVCB_HANDLER(ppi1_portb_w), DEVCB_HANDLER(ppi1_portc_w) +}; + + +static Z80CTC_INTERFACE( ctcintf ) +{ + 0, + DEVCB_LINE(ctc_interrupt), + DEVCB_NULL, + DEVCB_NULL, + DEVCB_NULL +}; + + +static const z80_daisy_config daisy_chain[] = +{ + { "ldvctc" }, + { NULL } +}; + + +static MACHINE_CONFIG_FRAGMENT( ldv1000 ) + MCFG_CPU_ADD("ldv1000", Z80, XTAL_5MHz/2) + MCFG_CPU_CONFIG(daisy_chain) + MCFG_CPU_PROGRAM_MAP(ldv1000_map) + MCFG_CPU_IO_MAP(ldv1000_portmap) + + MCFG_Z80CTC_ADD("ldvctc", XTAL_5MHz/2 /* same as "ldv1000" */, ctcintf) + MCFG_PPI8255_ADD("ldvppi0", ppi0intf) + MCFG_PPI8255_ADD("ldvppi1", ppi1intf) + MCFG_TIMER_ADD("multitimer", multijump_timer) +MACHINE_CONFIG_END + + +ROM_START( ldv1000 ) + ROM_REGION( 0x2000, "ldv1000", 0 ) + ROM_LOAD( "z03_1001_vyw-053_v1-0.bin", 0x0000, 0x2000, CRC(31ec4687) SHA1(52f91c304a878ba02b2fa1cda1a9489d6dd5a34f) ) +ROM_END + + + +/*************************************************************************** + INTERFACES +***************************************************************************/ + +const ldplayer_interface ldv1000_interface = +{ + LASERDISC_TYPE_PIONEER_LDV1000, /* type of the player */ + sizeof(ldplayer_data), /* size of the state */ + "Pioneer LD-V1000", /* name of the player */ + "ldv1000", /* shortname of the player */ + ROM_NAME(ldv1000), /* pointer to ROM region information */ + MACHINE_CONFIG_NAME(ldv1000), /* pointer to machine configuration */ + ldv1000_init, /* initialization callback */ + ldv1000_vsync, /* vsync callback */ + ldv1000_update, /* update callback */ + NULL, /* overlay callback */ + ldv1000_data_w, /* parallel data write */ + { /* single line write: */ + NULL, /* LASERDISC_LINE_ENTER */ + NULL /* LASERDISC_LINE_CONTROL */ + }, + ldv1000_status_r, /* parallel data read */ + { /* single line read: */ + NULL, /* LASERDISC_LINE_READY */ + ldv1000_status_strobe_r, /* LASERDISC_LINE_STATUS */ + ldv1000_command_strobe_r, /* LASERDISC_LINE_COMMAND */ + NULL, /* LASERDISC_LINE_DATA_AVAIL */ + } +}; + + + +/*************************************************************************** + PIONEER LD-V1000 IMPLEMENTATION +***************************************************************************/ + +/*------------------------------------------------- + ldv1000_init - player-specific initialization +-------------------------------------------------*/ + +static void ldv1000_init(laserdisc_state *ld) +{ + astring tempstring; + ldplayer_data *player = ld->player; + + /* reset our state */ + memset(player, 0, sizeof(*player)); + + /* find our devices */ + player->cpu = ld->device->subdevice("ldv1000"); + player->ctc = ld->device->subdevice("ldvctc"); + player->multitimer = downcast<timer_device *>(ld->device->subdevice("multitimer")); + player->multitimer->set_ptr(ld); +} + + +/*------------------------------------------------- + ldv1000_vsync - VSYNC callback, called at the + start of the blanking period +-------------------------------------------------*/ + +static void ldv1000_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime) +{ + slider_position sliderpos = ldcore_get_slider_position(ld); + ldplayer_data *player = ld->player; + + /* generate interrupts if we hit the edges */ + z80ctc_trg1_w(player->ctc, sliderpos == SLIDER_MINIMUM); + z80ctc_trg2_w(player->ctc, sliderpos == SLIDER_MAXIMUM); + + /* signal VSYNC and set a timer to turn it off */ + player->vsync = TRUE; + ld->device->machine().scheduler().timer_set(ld->screen->scan_period() * 4, FUNC(vsync_off), 0, ld); + + /* also set a timer to fetch the VBI data when it is ready */ + ld->device->machine().scheduler().timer_set(ld->screen->time_until_pos(19*2), FUNC(vbi_data_fetch), 0, ld); + + /* boost interleave for the first 1ms to improve communications */ + ld->device->machine().scheduler().boost_interleave(attotime::zero, attotime::from_msec(1)); +} + + +/*------------------------------------------------- + ldv1000_update - update callback, called on + the first visible line of the frame +-------------------------------------------------*/ + +static INT32 ldv1000_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime) +{ + if (LOG_FRAMES_SEEN) + { + int frame = frame_from_metadata(vbi); + if (frame != FRAME_NOT_PRESENT) printf("== %d\n", frame); + } + return fieldnum; +} + + +/*------------------------------------------------- + ldv1000_data_w - handle a parallel data write + to the LD-V1000 +-------------------------------------------------*/ + +static void ldv1000_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data) +{ + ld->player->command = data; + if (LOG_COMMANDS) + printf("-> COMMAND = %02X (%s)\n", data, (ld->player->portc1 & 0x10) ? "valid" : "invalid"); +} + + +/*------------------------------------------------- + ldv1000_status_strobe_r - return state of the + status strobe +-------------------------------------------------*/ + +static UINT8 ldv1000_status_strobe_r(laserdisc_state *ld) +{ + return (ld->player->portc1 & 0x20) ? ASSERT_LINE : CLEAR_LINE; +} + + +/*------------------------------------------------- + ldv1000_command_strobe_r - return state of the + command strobe +-------------------------------------------------*/ + +static UINT8 ldv1000_command_strobe_r(laserdisc_state *ld) +{ + return (ld->player->portc1 & 0x10) ? ASSERT_LINE : CLEAR_LINE; +} + + +/*------------------------------------------------- + ldv1000_status_r - handle a parallel data read + from the LD-V1000 +-------------------------------------------------*/ + +static UINT8 ldv1000_status_r(laserdisc_state *ld) +{ + return ld->player->status; +} + + +/*------------------------------------------------- + vsync_off - timer callback to clear the VSYNC + flag +-------------------------------------------------*/ + +static TIMER_CALLBACK( vsync_off ) +{ + laserdisc_state *ld = (laserdisc_state *)ptr; + ld->player->vsync = FALSE; +} + + +/*------------------------------------------------- + vbi_data_fetch - timer callback to update the + VBI data in the PIA as soon as it is ready; + this must happy early in the frame because + the player logic relies on fetching it here +-------------------------------------------------*/ + +static TIMER_CALLBACK( vbi_data_fetch ) +{ + laserdisc_state *ld = (laserdisc_state *)ptr; + ldplayer_data *player = ld->player; + UINT8 focus_on = !(player->portb1 & 0x01); + UINT8 laser_on = (player->portb1 & 0x40); + UINT32 lines[3]; + + /* appears to return data in reverse order */ + lines[0] = laserdisc_get_field_code(ld->device, LASERDISC_CODE_LINE1718, FALSE); + lines[1] = laserdisc_get_field_code(ld->device, LASERDISC_CODE_LINE17, FALSE); + lines[2] = laserdisc_get_field_code(ld->device, LASERDISC_CODE_LINE16, FALSE); + + /* fill in the details */ + memset(player->vbi, 0, sizeof(player->vbi)); + if (focus_on && laser_on) + { + int line; + + /* loop over lines */ + for (line = 0; line < 3; line++) + { + UINT8 *dest = &player->vbi[line * 7]; + UINT32 data = lines[line]; + + /* the logic only processes leadin/leadout/frame number codes */ + if (data == VBI_CODE_LEADIN || data == VBI_CODE_LEADOUT || (data & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE) + { + *dest++ = 0x09 | (((data & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE) ? 0x02 : 0x00); + *dest++ = 0x08; + *dest++ = (data >> 16) & 0x0f; + *dest++ = (data >> 12) & 0x0f; + *dest++ = (data >> 8) & 0x0f; + *dest++ = (data >> 4) & 0x0f; + *dest++ = (data >> 0) & 0x0f; + } + } + } + + /* signal that data is ready and reset the readback index */ + player->vbiready = TRUE; + player->vbiindex = 0; +} + + +/*------------------------------------------------- + multijump_timer - called once for each track + in a multijump sequence; we decrement the + down counter and autostop when we hit 0 +-------------------------------------------------*/ + +static TIMER_DEVICE_CALLBACK( multijump_timer ) +{ + laserdisc_state *ld = (laserdisc_state *)ptr; + ldplayer_data *player = ld->player; + int direction; + + /* bit 5 of port B on PPI 1 selects the direction of slider movement */ + direction = (player->portb1 & 0x20) ? 1 : -1; + ldcore_advance_slider(ld, direction); + + /* update down counter and reschedule */ + if (--player->counter != 0) + timer.adjust(MULTIJUMP_TRACK_TIME); +} + + +/*------------------------------------------------- + ctc_interrupt - called when the CTC triggers + an interrupt in the daisy chain +-------------------------------------------------*/ + +static WRITE_LINE_DEVICE_HANDLER( ctc_interrupt ) +{ + laserdisc_state *ld = ldcore_get_safe_token(device->owner()); + if (ld->player->cpu != NULL) + device_set_input_line(ld->player->cpu, 0, state ? ASSERT_LINE : CLEAR_LINE); +} + + +/*------------------------------------------------- + decoder_display_port_w - handle writes to the + decoder/display chips +-------------------------------------------------*/ + +static WRITE8_HANDLER( decoder_display_port_w ) +{ + /* + TX/RX = /A0 (A0=0 -> TX, A0=1 -> RX) + + Display is 6-bit + Decoder is 4-bit + */ + laserdisc_state *ld = ldcore_get_safe_token(space->device().owner()); + ldplayer_data *player = ld->player; + + /* writes to offset 0 select the target for reads/writes of actual data */ + if (offset == 0) + { + player->portselect = data; + player->dispindex = 0; + } + + /* writes to offset 2 constitute actual writes targeted toward the display and decoder chips */ + else if (offset == 2) + { + /* selections 0 and 1 represent the two display lines; only 6 bits are transferred */ + if (player->portselect < 2) + player->display[player->portselect][player->dispindex++ % 20] = data & 0x3f; + } +} + + +/*------------------------------------------------- + decoder_display_port_r - handle reads from the + decoder/display chips +-------------------------------------------------*/ + +static READ8_HANDLER( decoder_display_port_r ) +{ + laserdisc_state *ld = ldcore_get_safe_token(space->device().owner()); + ldplayer_data *player = ld->player; + UINT8 result = 0; + + /* reads from offset 3 constitute actual reads from the display and decoder chips */ + if (offset == 3) + { + /* selection 4 represents the VBI data reading */ + if (player->portselect == 4) + { + player->vbiready = FALSE; + result = player->vbi[player->vbiindex++ % ARRAY_LENGTH(player->vbi)]; + } + } + return result; +} + + +/*------------------------------------------------- + controller_r - handle read of the data from + the controlling system +-------------------------------------------------*/ + +static READ8_HANDLER( controller_r ) +{ + laserdisc_state *ld = ldcore_get_safe_token(space->device().owner()); + + /* note that this is a cheesy implementation; the real thing relies on exquisite timing */ + UINT8 result = ld->player->command ^ 0xff; + ld->player->command = 0xff; + return result; +} + + +/*------------------------------------------------- + controller_w - handle status latch writes +-------------------------------------------------*/ + +static WRITE8_HANDLER( controller_w ) +{ + laserdisc_state *ld = ldcore_get_safe_token(space->device().owner()); + if (LOG_STATUS_CHANGES && data != ld->player->status) + printf("%04X:CONTROLLER.W=%02X\n", cpu_get_pc(&space->device()), data); + ld->player->status = data; +} + + +/*------------------------------------------------- + ppi0_porta_w - handle writes to port A of + PPI #0 +-------------------------------------------------*/ + +static WRITE8_DEVICE_HANDLER( ppi0_porta_w ) +{ + laserdisc_state *ld = ldcore_get_safe_token(device->owner()); + ld->player->counter_start = data; + if (LOG_PORT_IO) + printf("%s:PORTA.0=%02X\n", device->machine().describe_context(), data); +} + + +/*------------------------------------------------- + ppi0_portb_r - handle reads from port B of + PPI #0 +-------------------------------------------------*/ + +static READ8_DEVICE_HANDLER( ppi0_portb_r ) +{ + laserdisc_state *ld = ldcore_get_safe_token(device->owner()); + return ld->player->counter; +} + + +/*------------------------------------------------- + ppi0_portc_r - handle reads from port C of + PPI #0 +-------------------------------------------------*/ + +static READ8_DEVICE_HANDLER( ppi0_portc_r ) +{ + /* + $10 = /VSYNC + $20 = IRQ from decoder chip + $40 = TRKG LOOP (N24-1) + $80 = DUMP (N20-1) -- code reads the state and waits for it to change + */ + laserdisc_state *ld = ldcore_get_safe_token(device->owner()); + ldplayer_data *player = ld->player; + UINT8 result = 0x00; + + if (!player->vsync) + result |= 0x10; + if (!player->vbiready) + result |= 0x20; + + return result; +} + + +/*------------------------------------------------- + ppi0_portc_w - handle writes to port C of + PPI #0 +-------------------------------------------------*/ + +static WRITE8_DEVICE_HANDLER( ppi0_portc_w ) +{ + /* + $01 = preload on up/down counters + $02 = /MULTI JUMP TRIG + $04 = SCAN MODE + $08 = n/c + */ + laserdisc_state *ld = ldcore_get_safe_token(device->owner()); + ldplayer_data *player = ld->player; + UINT8 prev = player->portc0; + + /* set the new value */ + player->portc0 = data; + if (LOG_PORT_IO && ((data ^ prev) & 0x0f) != 0) + { + printf("%s:PORTC.0=%02X", device->machine().describe_context(), data); + if (data & 0x01) printf(" PRELOAD"); + if (!(data & 0x02)) printf(" /MULTIJUMP"); + if (data & 0x04) printf(" SCANMODE"); + printf("\n"); + } + + /* on the rising edge of bit 0, clock the down counter load */ + if ((data & 0x01) && !(prev & 0x01)) + player->counter = player->counter_start; + + /* on the falling edge of bit 1, start the multi-jump timer */ + if (!(data & 0x02) && (prev & 0x02)) + player->multitimer->adjust(MULTIJUMP_TRACK_TIME); +} + + +/*------------------------------------------------- + ppi1_porta_r - handle reads from port A of + PPI #1 +-------------------------------------------------*/ + +static READ8_DEVICE_HANDLER( ppi1_porta_r ) +{ + /* + $01 = /FOCS LOCK + $02 = /SPDL LOCK + $04 = INSIDE + $08 = OUTSIDE + $10 = MOTOR STOP + $20 = +5V/test point + $40 = /INT LOCK + $80 = 8 INCH CHK + */ + laserdisc_state *ld = ldcore_get_safe_token(device->owner()); + ldplayer_data *player = ld->player; + slider_position sliderpos = ldcore_get_slider_position(ld); + UINT8 focus_on = !(player->portb1 & 0x01); + UINT8 spdl_on = !(player->portb1 & 0x02); + UINT8 result = 0x00; + + /* bit 0: /FOCUS LOCK */ + if (!focus_on) + result |= 0x01; + + /* bit 1: /SPDL LOCK */ + if (!spdl_on) + result |= 0x02; + + /* bit 2: INSIDE signal */ + if (sliderpos == SLIDER_MINIMUM) + result |= 0x04; + + /* bit 3: OUTSIDE signal */ + if (sliderpos == SLIDER_MAXIMUM) + result |= 0x08; + + /* bit 4: MOTOR STOP */ + + /* bit 5: +5V/test point */ + result |= 0x20; + + /* bit 6: /INT LOCK */ + + /* bit 7: 8 INCH CHK */ + + return result; +} + + +/*------------------------------------------------- + ppi1_portb_w - handle writes to port B of + PPI #1 +-------------------------------------------------*/ + +static WRITE8_DEVICE_HANDLER( ppi1_portb_w ) +{ + /* + $01 = /FOCS ON + $02 = /SPDL RUN + $04 = /JUMP TRIG + $08 = /SCAN A + $10 = SCAN B + $20 = SCAN C + $40 = /LASER ON + $80 = /SYNC ST0 + */ + laserdisc_state *ld = ldcore_get_safe_token(device->owner()); + ldplayer_data *player = ld->player; + UINT8 prev = player->portb1; + int direction; + + /* set the new value */ + player->portb1 = data; + if (LOG_PORT_IO && ((data ^ prev) & 0xff) != 0) + { + printf("%s:PORTB.1=%02X:", device->machine().describe_context(), data); + if (!(data & 0x01)) printf(" FOCSON"); + if (!(data & 0x02)) printf(" SPDLRUN"); + if (!(data & 0x04)) printf(" JUMPTRIG"); + if (!(data & 0x08)) printf(" SCANA (%c %c)", (data & 0x10) ? 'L' : 'H', (data & 0x20) ? 'F' : 'R'); + if ( (data & 0x40)) printf(" LASERON"); + if (!(data & 0x80)) printf(" SYNCST0"); + printf("\n"); + } + + /* bit 5 selects the direction of slider movement for JUMP TRG and scanning */ + direction = (data & 0x20) ? 1 : -1; + + /* on the falling edge of bit 2, jump one track in either direction */ + if (!(data & 0x04) && (prev & 0x04)) + ldcore_advance_slider(ld, direction); + + /* bit 3 low enables scanning */ + if (!(data & 0x08)) + { + /* bit 4 selects the speed */ + int delta = (data & 0x10) ? SCAN_SPEED : SEEK_FAST_SPEED; + ldcore_set_slider_speed(ld, delta * direction); + } + + /* bit 3 high stops scanning */ + else + ldcore_set_slider_speed(ld, 0); +} + + +/*------------------------------------------------- + ppi1_portc_w - handle writes to port C of + PPI #1 +-------------------------------------------------*/ + +static WRITE8_DEVICE_HANDLER( ppi1_portc_w ) +{ + /* + $01 = AUD 1 + $02 = AUD 2 + $04 = AUDIO ENABLE + $08 = /VIDEO SQ + $10 = COMMAND + $20 = STATUS + $40 = SIZE 8/12 + $80 = /LED CAV + */ + laserdisc_state *ld = ldcore_get_safe_token(device->owner()); + ldplayer_data *player = ld->player; + UINT8 prev = player->portc1; + + /* set the new value */ + player->portc1 = data; + if (LOG_PORT_IO && ((data ^ prev) & 0xcf) != 0) + { + printf("%s:PORTC.1=%02X", device->machine().describe_context(), data); + if (data & 0x01) printf(" AUD1"); + if (data & 0x02) printf(" AUD2"); + if (data & 0x04) printf(" AUDEN"); + if (!(data & 0x08)) printf(" VIDEOSQ"); + if (data & 0x10) printf(" COMMAND"); + if (data & 0x20) printf(" STATUS"); + if (data & 0x40) printf(" SIZE8"); + if (!(data & 0x80)) printf(" CAV"); + printf("\n"); + } + + /* video squelch is controlled by bit 3 */ + ldcore_set_video_squelch(ld, (data & 0x08) == 0); + + /* audio squelch is controlled by bits 0-2 */ + ldcore_set_audio_squelch(ld, !(data & 0x04) || !(data & 0x01), !(data & 0x04) || !(data & 0x02)); +} |