summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/ldpr8210.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/machine/ldpr8210.c')
-rw-r--r--src/emu/machine/ldpr8210.c250
1 files changed, 218 insertions, 32 deletions
diff --git a/src/emu/machine/ldpr8210.c b/src/emu/machine/ldpr8210.c
index f3940cc46d4..54683584b1e 100644
--- a/src/emu/machine/ldpr8210.c
+++ b/src/emu/machine/ldpr8210.c
@@ -76,6 +76,7 @@ struct _ldplayer_data
/* low-level emulation data */
int cpunum;
UINT8 pia[0x100];
+ UINT8 vsync;
UINT8 porta;
UINT8 portb;
UINT8 pia_porta;
@@ -92,9 +93,12 @@ static void pr8210_init(laserdisc_state *ld);
static void pr8210_soft_reset(laserdisc_state *ld);
static void pr8210_update_squelch(laserdisc_state *ld);
static int pr8210_switch_state(laserdisc_state *ld, UINT8 newstate, INT32 stateparam);
+static INT32 pr8210_hle_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+#if (EMULATE_PR8210_ROM)
+static void pr8210_vsync(laserdisc_state *ld);
static INT32 pr8210_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
-#if (!EMULATE_PR8210_ROM)
-static void pr8210_command(laserdisc_state *ld);
+#else
+static void pr8210_hle_command(laserdisc_state *ld);
#endif
static void pr8210_control_w(laserdisc_state *ld, UINT8 prev, UINT8 data);
@@ -131,12 +135,16 @@ const ldplayer_interface pr8210_interface =
#if EMULATE_PR8210_ROM
rom_pr8210, /* pointer to ROM region information */
machine_config_pr8210, /* pointer to machine configuration */
+ pr8210_init, /* initialization callback */
+ pr8210_vsync, /* vsync callback */
+ pr8210_update, /* update callback */
#else
NULL, /* pointer to ROM region information */
NULL, /* pointer to machine configuration */
-#endif
pr8210_init, /* initialization callback */
- pr8210_update, /* update callback */
+ NULL, /* vsync callback */
+ pr8210_hle_update, /* update callback */
+#endif
NULL, /* parallel data write */
{ /* single line write: */
NULL, /* LASERDISC_LINE_ENTER */
@@ -160,7 +168,8 @@ const ldplayer_interface simutrek_interface =
NULL, /* pointer to ROM region information */
NULL, /* pointer to machine configuration */
simutrek_init, /* initialization callback */
- pr8210_update, /* update callback */
+ NULL, /* vsync callback */
+ pr8210_hle_update, /* update callback */
simutrek_data_w, /* parallel data write */
{ /* single line write: */
NULL, /* LASERDISC_LINE_ENTER */
@@ -178,7 +187,7 @@ const ldplayer_interface simutrek_interface =
/***************************************************************************
- PIONEER PR-8210 IMPLEMENTATION
+ INLINE FUNCTIONS
***************************************************************************/
/*-------------------------------------------------
@@ -193,6 +202,20 @@ INLINE int requires_state_save(UINT8 state)
}
+/*-------------------------------------------------
+ requires_state_save - returns TRUE if the
+ given state will return to the previous
+ state when done
+-------------------------------------------------*/
+
+INLINE void update_audio_squelch(laserdisc_state *ld)
+{
+ ldplayer_data *player = ld->player;
+ ldcore_set_audio_squelch(ld, (player->porta & 0x40) || !(player->pia_portb & 0x01), (player->porta & 0x40) || !(player->pia_portb & 0x02));
+}
+
+
+
/***************************************************************************
PIONEER PR-8210 IMPLEMENTATION
@@ -350,12 +373,103 @@ static int pr8210_switch_state(laserdisc_state *ld, UINT8 newstate, INT32 parame
/*-------------------------------------------------
+ pr8210_vsync - Start of VSYNC callback
+-------------------------------------------------*/
+
+#if (EMULATE_PR8210_ROM)
+static TIMER_CALLBACK( vsync_off )
+{
+ ldplayer_data *player = ptr;
+ player->vsync = FALSE;
+}
+
+static void pr8210_vsync(laserdisc_state *ld)
+{
+ ldplayer_data *player = ld->player;
+ player->vsync = TRUE;
+ timer_set(attotime_mul(video_screen_get_scan_period(ld->screen), 4), player, 0, vsync_off);
+}
+#endif
+
+
+/*-------------------------------------------------
pr8210_update - Pioneer PR-8210-specific
- update callback
+ update callback when using a ROM
-------------------------------------------------*/
+#if (EMULATE_PR8210_ROM)
+
static INT32 pr8210_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
{
+ ldplayer_data *player = ld->player;
+ UINT8 focus_on = !(player->porta & 0x08);
+ UINT8 laser_on = !(player->portb & 0x01);
+ UINT8 spdl_on = !(player->porta & 0x10);
+ INT32 advanceby = 0;
+ int frame, chapter;
+
+ /* update PIA registers based on vbi code */
+ frame = frame_from_metadata(vbi);
+ chapter = chapter_from_metadata(vbi);
+ if (focus_on && laser_on && !(player->pia[0x80] & 1))
+ {
+ if (frame == FRAME_LEAD_IN)
+ player->pia[0xc0] = 0x10; /* or 0x12 */
+ else if (frame == FRAME_LEAD_OUT)
+ player->pia[0xc0] = 0x11;
+ else if (frame != FRAME_NOT_PRESENT)
+ {
+ player->pia[0xc0] = 0x00;
+ player->pia[0x22] = 0xf0 | ((frame / 10000) % 10);
+ player->pia[0x23] = 0xf0 | ((frame / 1000) % 10);
+ player->pia[0x24] = 0xf0 | ((frame / 100) % 10);
+ player->pia[0x25] = 0xf0 | ((frame / 10) % 10);
+ player->pia[0x26] = 0xf0 | ((frame / 1) % 10);
+ }
+ else if (chapter != CHAPTER_NOT_PRESENT)
+ {
+ player->pia[0xc0] = 0x13;
+ player->pia[0x20] = 0xf0 | ((chapter / 10) % 10);
+ player->pia[0x21] = 0xf0 | ((chapter / 1) % 10);
+ }
+ }
+ player->pia[0xc0] |= 4;//fieldnum << 2;
+
+ if (spdl_on)
+ advanceby = fieldnum;
+
+ /* update overlay */
+ if ((player->pia[0x80] & 1) || player->framedisplay)
+ {
+ char buffer[16] = { 0 };
+ int i;
+ for (i = 0; i < 15; i++)
+ {
+ UINT8 c = player->pia[0x22 + i];
+ if (c >= 0xf0 && c <= 0xf9)
+ c = '0' + (c - 0xf0);
+ else if (c < 0x20 || c > 0x7f)
+ c = '?';
+ buffer[i] = c;
+ }
+ popmessage("%s", buffer);
+ }
+ player->framedisplay = 0;
+
+if (advanceby != 0)
+ printf("Advancing by %d\n", advanceby);
+ return advanceby;
+}
+#endif
+
+
+/*-------------------------------------------------
+ pr8210_hle_update - Pioneer PR-8210-specific
+ update callback when using HLE
+-------------------------------------------------*/
+
+static INT32 pr8210_hle_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
+{
ldplayer_state newstate;
INT32 advanceby = 0;
int frame;
@@ -422,13 +536,14 @@ static INT32 pr8210_update(laserdisc_state *ld, const vbi_metadata *vbi, int fie
}
+
/*-------------------------------------------------
- pr8210_command - Pioneer PR-8210-specific
+ pr8210_hle_command - Pioneer PR-8210-specific
command processing
-------------------------------------------------*/
#if (!EMULATE_PR8210_ROM)
-static void pr8210_command(laserdisc_state *ld)
+static void pr8210_hle_command(laserdisc_state *ld)
{
ldplayer_data *player = ld->player;
UINT8 cmd = player->lastcommand;
@@ -623,12 +738,14 @@ static void pr8210_control_w(laserdisc_state *ld, UINT8 prev, UINT8 data)
//printf("New command = %02X (last=%02X)\n", newcommand, player->lastcommand);
#if EMULATE_PR8210_ROM
+ printf("Command = %02X\n", newcommand);
+// player->pia_porta = BITSWAP8(newcommand, 4,3,2,1,0,5,6,7);
player->pia_porta = BITSWAP8(newcommand, 0,1,2,3,4,5,6,7);
#else
/* if we got a double command, act on it */
if (newcommand == player->lastcommand)
{
- pr8210_command(ld);
+ pr8210_hle_command(ld);
player->lastcommand = 0;
}
else
@@ -783,22 +900,33 @@ void simutrek_set_cmd_ack_callback(const device_config *device, void (*callback)
*
*************************************/
-static ldplayer_data *find_pr8210(running_machine *machine)
+static laserdisc_state *find_pr8210(running_machine *machine)
{
- return ldcore_get_safe_token(device_list_first(machine->config->devicelist, LASERDISC))->player;
+ return ldcore_get_safe_token(device_list_first(machine->config->devicelist, LASERDISC));
}
static READ8_HANDLER( pr8210_pia_r )
{
- ldplayer_data *player = find_pr8210(machine);
+ laserdisc_state *ld = find_pr8210(machine);
+ ldplayer_data *player = ld->player;
UINT8 result = player->pia[offset];
switch (offset)
{
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0xc0:
+ case 0xe0:
+ break;
+
case 0xa0:
// printf("%03X:pia_r(%02X) = %02X\n", activecpu_get_pc(), offset, player->pia_porta);
result = player->pia_porta;
- player->pia_porta = 0;
+// player->pia_porta = 0;
break;
default:
@@ -837,21 +965,30 @@ static WRITE8_HANDLER( pr8210_pia_w )
$C0 (R) = stored to ($2E)
$E0 (R) = stored to ($2F)
*/
- ldplayer_data *player = find_pr8210(machine);
+ laserdisc_state *ld = find_pr8210(machine);
+ ldplayer_data *player = ld->player;
if (player->pia[offset] != data)
{
switch (offset)
{
+ case 0x40:
+ if (!(data & 0x02) && (player->pia[offset] & 0x02))
+ player->framedisplay = 1;
+ break;
+
case 0x60:
printf("%03X:pia_w(%02X) = %02X (PORT B LEDS:", activecpu_get_pc(), offset, data);
- if (!(data & 0x01)) printf(" AUDIO1");
- if (!(data & 0x02)) printf(" AUDIO2");
- if (!(data & 0x04)) printf(" CLV");
- if (!(data & 0x08)) printf(" CAV");
- printf(" LED123=%c%c%c", (data & 0x10) ? 'H' : 'L', (data & 0x20) ? 'H' : 'L', (data & 0x40) ? 'H' : 'L');
+ output_set_value("pr8210_audio1", (data & 0x01) != 0);
+ output_set_value("pr8210_audio2", (data & 0x02) != 0);
+ output_set_value("pr8210_clv", (data & 0x04) != 0);
+ output_set_value("pr8210_cav", (data & 0x08) != 0);
+ output_set_value("pr8210_led1", (data & 0x10) == 0);
+ output_set_value("pr8210_led2", (data & 0x20) == 0);
+ output_set_value("pr8210_led3", (data & 0x40) == 0);
if (!(data & 0x80)) printf(" ???");
printf(")\n");
player->pia_portb = data;
+ update_audio_squelch(ld);
break;
default:
@@ -866,7 +1003,7 @@ static READ8_HANDLER( pr8210_bus_r )
{
/*
$80 = n/c
- $40 = (in) slide pot interrupt source (slider position limit detector, inside and outside)
+ $40 = (in) slider pot interrupt source (slider position limit detector, inside and outside)
$20 = n/c
$10 = (in) /FOCUS LOCK
$08 = (in) /SPDL LOCK
@@ -874,12 +1011,31 @@ static READ8_HANDLER( pr8210_bus_r )
$02 = (in) FG via op-amp (spindle motor stop detector)
$01 = (in) SLOW TIMER OUT
*/
- offs_t pc = activecpu_get_pc();
- if (pc != 0x11c)
- printf("%03X:bus_r\n", pc);
+ laserdisc_state *ld = find_pr8210(machine);
+ ldplayer_data *player = ld->player;
+ slider_position sliderpos = ldcore_get_slider_position(ld);
+ UINT8 focus_on = !(player->porta & 0x08);
+ UINT8 spdl_on = !(player->porta & 0x10);
+ UINT8 result = 0x00;
+
+ /* bus bit 6: slider position limit detector, inside and outside */
+ if (sliderpos != SLIDER_MINIMUM && sliderpos != SLIDER_MAXIMUM)
+ result |= 0x40;
+
+ /* bus bit 4: /FOCUS LOCK */
+ if (!focus_on)
+ result |= 0x10;
+
+ /* bus bit 3: /SPDL LOCK */
+ if (!spdl_on)
+ result |= 0x08;
+
+ /* bus bit 1: spindle motor stop detector */
+ if (!spdl_on)
+ result |= 0x02;
/* loop at beginning waits for $40=0, $02=1 */
- return 0xff & ~0x40 & ~0x04;
+ return result;
}
static WRITE8_HANDLER( pr8210_porta_w )
@@ -894,21 +1050,33 @@ static WRITE8_HANDLER( pr8210_porta_w )
$02 = (out) SCAN A (/SCAN)
$01 = (out) JUMP TRG (jump back trigger, clock on high->low)
*/
- ldplayer_data *player = find_pr8210(machine);
- if (data != player->porta)
+ laserdisc_state *ld = find_pr8210(machine);
+ ldplayer_data *player = ld->player;
+ if ((data & 0xfe) != (player->porta & 0xfe))
{
+ int direction = (data & 0x80) ? 1 : -1;
+
printf("%03X:porta_w = %02X", activecpu_get_pc(), data);
- if (!(data & 0x01)) printf(" JUMPTRG");
+ if (!(data & 0x01) && (player->porta & 0x01))
+ ldcore_advance_slider(ld, direction);
if (!(data & 0x02))
- {
printf(" SCAN:%c:%c", (data & 0x80) ? 'F' : 'R', (data & 0x04) ? 'L' : 'H');
- }
if (!(data & 0x08)) printf(" /FOCUSON");
if (!(data & 0x10)) printf(" /SPDLON");
if (data & 0x20) printf(" VIDEOSQ");
if (data & 0x40) printf(" AUDIOSQ");
printf("\n");
player->porta = data;
+
+ ldcore_set_video_squelch(ld, (data & 0x20) != 0);
+ update_audio_squelch(ld);
+ if (!(data & 0x02))
+ {
+ int delta = (data & 0x04) ? PR8210_SCAN_SPEED : PR8210_SEEK_FAST_SPEED;
+ ldcore_set_slider_speed(ld, delta * direction);
+ }
+ else
+ ldcore_set_slider_speed(ld, 0);
}
}
@@ -924,7 +1092,8 @@ static WRITE8_HANDLER( pr8210_portb_w )
$02 = (out) ???
$01 = (out) LASER ON
*/
- ldplayer_data *player = find_pr8210(machine);
+ laserdisc_state *ld = find_pr8210(machine);
+ ldplayer_data *player = ld->player;
cpunum_set_input_line(machine, player->cpunum, 0, (data & 0x40) ? CLEAR_LINE : ASSERT_LINE);
if ((data & 0x7f) != (player->portb & 0x7f))
{
@@ -933,7 +1102,7 @@ static WRITE8_HANDLER( pr8210_portb_w )
if (!(data & 0x02)) printf(" ???");
if (!(data & 0x04)) printf(" TP1");
if (!(data & 0x08)) printf(" TP2");
- if (!(data & 0x10)) printf(" STANDBYLED");
+ output_set_value("pr8210_standby", !(data & 0x10));
if (!(data & 0x20)) printf(" SLOWTRG");
if (!(data & 0x40)) printf(" IRQGEN");
// if (data & 0x80) printf(" PIASEL");
@@ -943,6 +1112,21 @@ static WRITE8_HANDLER( pr8210_portb_w )
}
+static READ8_HANDLER( pr8210_t0_r )
+{
+ /* returns VSYNC state */
+ laserdisc_state *ld = find_pr8210(machine);
+ return !ld->player->vsync;
+}
+
+
+static READ8_HANDLER( pr8210_t1_r )
+{
+ /* must return 1 or else it tries to jump to an external ROM */
+ return 1;
+}
+
+
static ADDRESS_MAP_START( pr8210_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x000, 0x7ff) AM_ROM
ADDRESS_MAP_END
@@ -953,6 +1137,8 @@ static ADDRESS_MAP_START( pr8210_portmap, ADDRESS_SPACE_IO, 8 )
AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READ(pr8210_bus_r)
AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_WRITE(pr8210_porta_w)
AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_WRITE(pr8210_portb_w)
+ AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(pr8210_t0_r)
+ AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(pr8210_t1_r)
ADDRESS_MAP_END