Added 22VP931 emulation, which is mostly working. Communication works

fine and basic searching/playback/skipping is functional. Still a bit
glitchy.

Firefox improvements:
 - removed need for deprecat.h
 - memory map is complete from schematics
 - gutted laserdisc hacks in favor of actual laserdisc implementation
 - fixed all CPU and sound clocks
 
Removed old laserdsc.c implementation.

Added generic timer devices, which simply allocate a timer but don't
prime it. This is the preferred method for allocating timers, and may 
eventually be the only mechanism for doing so in the future.
This commit is contained in:
Aaron Giles 2008-09-25 16:21:35 +00:00
parent e4dc04a323
commit 9b72b5abc4
11 changed files with 1056 additions and 4440 deletions

2
.gitattributes vendored
View File

@ -630,7 +630,6 @@ src/emu/machine/idectrl.c svneol=native#text/plain
src/emu/machine/idectrl.h svneol=native#text/plain
src/emu/machine/intelfsh.c svneol=native#text/plain
src/emu/machine/intelfsh.h svneol=native#text/plain
src/emu/machine/laserdsc.c svneol=native#text/plain
src/emu/machine/laserdsc.h svneol=native#text/plain
src/emu/machine/latch8.c svneol=native#text/plain
src/emu/machine/latch8.h svneol=native#text/plain
@ -638,6 +637,7 @@ src/emu/machine/ldcore.c svneol=native#text/plain
src/emu/machine/ldcore.h svneol=native#text/plain
src/emu/machine/ldpr8210.c svneol=native#text/plain
src/emu/machine/ldv1000.c svneol=native#text/plain
src/emu/machine/ldvp931.c svneol=native#text/plain
src/emu/machine/mb3773.c svneol=native#text/plain
src/emu/machine/mb3773.h svneol=native#text/plain
src/emu/machine/mb87078.c svneol=native#text/plain

View File

@ -142,6 +142,7 @@ EMUMACHINEOBJS = \
$(EMUMACHINE)/ldcore.o \
$(EMUMACHINE)/ldpr8210.o \
$(EMUMACHINE)/ldv1000.o \
$(EMUMACHINE)/ldvp931.o \
$(EMUMACHINE)/mb3773.o \
$(EMUMACHINE)/mb87078.o \
$(EMUMACHINE)/mc146818.o \

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,8 @@ enum
/* laserdisc control lines */
#define LASERDISC_LINE_ENTER 0 /* "ENTER" key/line */
#define LASERDISC_LINE_CONTROL 1 /* "CONTROL" line */
#define LASERDISC_INPUT_LINES 2
#define LASERDISC_LINE_RESET 2 /* "RESET" line */
#define LASERDISC_INPUT_LINES 3
/* laserdisc status lines */
#define LASERDISC_LINE_READY 0 /* "READY" line */
@ -47,11 +48,11 @@ enum
#define LASERDISC_OUTPUT_LINES 4
/* laserdisc field codes */
#define LASERDISC_CODE_WHITE_FLAG 0 /* boolean white flag */
#define LASERDISC_CODE_LINE16 1 /* 24-bit line 16 code */
#define LASERDISC_CODE_LINE17 2 /* 24-bit line 17 code */
#define LASERDISC_CODE_LINE18 3 /* 24-bit line 18 code */
#define LASERDISC_CODE_LINE1718 4 /* 24-bit best of line 17/18 code */
#define LASERDISC_CODE_WHITE_FLAG 11 /* boolean white flag */
#define LASERDISC_CODE_LINE16 16 /* 24-bit line 16 code */
#define LASERDISC_CODE_LINE17 17 /* 24-bit line 17 code */
#define LASERDISC_CODE_LINE18 18 /* 24-bit line 18 code */
#define LASERDISC_CODE_LINE1718 1718 /* 24-bit best of line 17/18 code */
/* device configuration */
enum
@ -161,7 +162,7 @@ extern const custom_sound_interface laserdisc_custom_interface;
int laserdisc_get_video(const device_config *device, bitmap_t **bitmap);
/* return the raw philips or white flag codes */
UINT32 laserdisc_get_field_code(const device_config *device, UINT8 code);
UINT32 laserdisc_get_field_code(const device_config *device, UINT32 code);
@ -186,6 +187,9 @@ UINT8 laserdisc_line_r(const device_config *device, UINT8 line);
/* specify the "slow" speed of the Pioneer PR-7820 */
void pr7820_set_slow_speed(const device_config *device, double frame_rate_scaler);
/* set a callback for data ready on the Phillips 22VP931 */
void vp931_set_data_ready_callback(const device_config *device, void (*callback)(const device_config *device, int state));
/* control the audio squelch of the Simutrek modified players */
void simutrek_set_audio_squelch(const device_config *device, int state);

View File

@ -151,7 +151,8 @@ static const ldplayer_interface *player_interfaces[] =
&simutrek_interface,
&ldv1000_interface,
// &ldp1450_interface,
// &vp932_interface
// &vp932_interface,
&vp931_interface
};
const custom_sound_interface laserdisc_custom_interface =
@ -560,7 +561,7 @@ int laserdisc_get_video(const device_config *device, bitmap_t **bitmap)
information read from the disc
-------------------------------------------------*/
UINT32 laserdisc_get_field_code(const device_config *device, UINT8 code)
UINT32 laserdisc_get_field_code(const device_config *device, UINT32 code)
{
laserdisc_state *ld = get_safe_token(device);
ldcore_data *ldcore = ld->core;
@ -888,27 +889,44 @@ static void read_track_data(laserdisc_state *ld)
ldcore_data *ldcore = ld->core;
UINT32 tracknum = ldcore->curtrack;
UINT32 fieldnum = ldcore->fieldnum;
UINT32 curfield = tracknum * 2 + fieldnum;
frame_data *frame;
UINT32 vbiframe;
UINT32 readhunk;
INT32 chdtrack;
/* if the previous field had a frame number, and the new field immediately follows it,
force the new field to pair with the previous one */
frame = &ldcore->frame[ldcore->videoindex];
if ((ldcore->metadata[fieldnum ^ 1].line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE && (tracknum * 2 + fieldnum == frame->lastfield + 1))
frame->numfields = 1;
/* otherwise, keep the frames in sync with the absolute field numbers */
else if (frame->numfields == 2 && fieldnum != 0)
frame->numfields--;
/* if we already have both fields on the current videoindex, advance */
else if (frame->numfields >= 2)
/* special cases for playing forward */
if (curfield == frame->lastfield + 1)
{
ldcore->videoindex = (ldcore->videoindex + 1) % ARRAY_LENGTH(ldcore->frame);
frame = &ldcore->frame[ldcore->videoindex];
frame->numfields = 0;
/* if the previous field had a frame number, force the new field to pair with the previous one */
if ((ldcore->metadata[fieldnum ^ 1].line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
frame->numfields = 1;
/* if the twice-previous field was a frame number, and we've moved one since then, consider this one done */
else if (frame->numfields >= 2 && (ldcore->metadata[fieldnum].line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
{
ldcore->videoindex = (ldcore->videoindex + 1) % ARRAY_LENGTH(ldcore->frame);
frame = &ldcore->frame[ldcore->videoindex];
frame->numfields = 0;
}
}
/* all other cases */
else
{
/* otherwise, keep the frames in sync with the absolute field numbers */
if (frame->numfields == 2 && fieldnum != 0)
frame->numfields--;
/* if we already have both fields on the current videoindex, advance */
else if (frame->numfields >= 2)
{
ldcore->videoindex = (ldcore->videoindex + 1) % ARRAY_LENGTH(ldcore->frame);
frame = &ldcore->frame[ldcore->videoindex];
frame->numfields = 0;
}
}
/* if we're squelched, reset the frame counter */
@ -1333,8 +1351,8 @@ VIDEO_UPDATE( laserdisc )
rectangle clip = *cliprect;
/* scale the cliprect to the overlay size and then call the update callback */
clip.min_x = 0;
clip.max_x = ldcore->config.overwidth - 1;
clip.min_x = ldcore->config.overclip.min_x;
clip.max_x = ldcore->config.overclip.max_x;
clip.min_y = cliprect->min_y * overbitmap->height / bitmap->height;
if (cliprect->min_y == visarea->min_y)
clip.min_y = MIN(clip.min_y, ldcore->config.overclip.min_y);

View File

@ -172,6 +172,7 @@ extern const ldplayer_interface pr8210_interface;
extern const ldplayer_interface simutrek_interface;
extern const ldplayer_interface ldv1000_interface;
extern const ldplayer_interface ldp1450_interface;
extern const ldplayer_interface vp931_interface;
extern const ldplayer_interface vp932_interface;

View File

@ -349,7 +349,7 @@ static INT32 pr8210_update(laserdisc_state *ld, const vbi_metadata *vbi, int fie
player data
-------------------------------------------------*/
void pr8210_overlay(laserdisc_state *ld, bitmap_t *bitmap)
static void pr8210_overlay(laserdisc_state *ld, bitmap_t *bitmap)
{
// ldplayer_data *player = ld->player;
}

772
src/emu/machine/ldvp931.c Normal file
View File

@ -0,0 +1,772 @@
/*************************************************************************
ldvp931.c
Philips 22VP931 laserdisc emulation.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
**************************************************************************
Still to do:
* determine actual slow/fast speeds
*
*************************************************************************/
#include "ldcore.h"
#include "cpu/mcs48/mcs48.h"
/***************************************************************************
DEBUGGING
***************************************************************************/
#define LOG_COMMANDS 0
#define LOG_PORTS 0
/***************************************************************************
CONSTANTS
***************************************************************************/
/* Philips 22VP931 specific information */
#define VP931_SCAN_SPEED (2000 / 30) /* 2000 frames/second */
#define VP931_SCAN_FAST_SPEED (4000 / 30) /* 4000 frames/second */
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
/* player-specific data */
struct _ldplayer_data
{
/* low-level emulation data */
int cpunum; /* CPU index of the 8049 */
const device_config *tracktimer; /* timer device */
int lastframe;
UINT8 out0; /* output 0 state */
UINT8 out1; /* output 1 state */
UINT8 port1; /* port 1 state */
UINT8 daticval; /* latched DATIC value */
UINT8 daticerp; /* /ERP value from DATIC */
UINT8 datastrobe; /* DATA STROBE line from DATIC */
UINT8 fromcontroller; /* command byte from the controller */
UINT8 fromcontroller_pending; /* TRUE if data is pending */
UINT8 tocontroller; /* command byte to the controller */
UINT8 tocontroller_pending; /* TRUE if data is pending */
INT8 trackdir; /* direction of tracking */
UINT8 trackstate; /* state of tracking */
UINT8 cmdbuf[3]; /* 3 bytes worth of commands */
UINT8 cmdcount; /* number of command bytes seen */
INT16 advanced; /* number of frames advanced */
void (*data_ready_cb)(const device_config *device, int state); /* data ready callback */
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
static void vp931_init(laserdisc_state *ld);
static void vp931_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
static INT32 vp931_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
static void vp931_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data);
static UINT8 vp931_data_r(laserdisc_state *ld);
static UINT8 vp931_ready(laserdisc_state *ld);
static UINT8 vp931_data_ready(laserdisc_state *ld);
static WRITE8_HANDLER( output0_w );
static WRITE8_HANDLER( output1_w );
static WRITE8_HANDLER( lcd_w );
static READ8_HANDLER( keypad_r );
static READ8_HANDLER( datic_r );
static READ8_HANDLER( from_controller_r );
static WRITE8_HANDLER( to_controller_w );
static READ8_HANDLER( port1_r );
static WRITE8_HANDLER( port1_w );
static READ8_HANDLER( port2_r );
static WRITE8_HANDLER( port2_w );
static READ8_HANDLER( t0_r );
static READ8_HANDLER( t1_r );
static TIMER_CALLBACK( vbi_data_fetch );
static TIMER_CALLBACK( deferred_data_w );
static TIMER_CALLBACK( irq_off );
static TIMER_CALLBACK( datastrobe_off );
static TIMER_CALLBACK( erp_off );
static TIMER_DEVICE_CALLBACK( track_timer );
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
/*-------------------------------------------------
find_vp931 - find our device; assumes there
is only one
-------------------------------------------------*/
INLINE laserdisc_state *find_vp931(running_machine *machine)
{
return ldcore_get_safe_token(device_list_first(machine->config->devicelist, LASERDISC));
}
/***************************************************************************
22VP931 ROM AND MACHINE INTERFACES
***************************************************************************/
static ADDRESS_MAP_START( vp931_portmap, ADDRESS_SPACE_IO, 8 )
AM_RANGE(0x00, 0x00) AM_MIRROR(0xcf) AM_READWRITE(keypad_r, output0_w)
AM_RANGE(0x10, 0x10) AM_MIRROR(0xcf) AM_WRITE(output1_w)
AM_RANGE(0x20, 0x20) AM_MIRROR(0xcf) AM_READWRITE(datic_r, lcd_w)
AM_RANGE(0x30, 0x30) AM_MIRROR(0xcf) AM_READWRITE(from_controller_r, to_controller_w)
AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(port1_r, port1_w)
AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(port2_r, port2_w)
AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(t0_r)
AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_r)
ADDRESS_MAP_END
static MACHINE_DRIVER_START( vp931 )
MDRV_CPU_ADD("vp931", I8049, XTAL_11MHz)
MDRV_CPU_IO_MAP(vp931_portmap,0)
MDRV_TIMER_ADD("tracktimer", track_timer)
MACHINE_DRIVER_END
ROM_START( vp931 )
ROM_REGION( 0x800, "vp931", ROMREGION_LOADBYNAME )
ROM_LOAD( "at-6-1_a.bin", 0x000, 0x800, CRC(e11b3c8d) SHA1(ea2d7f6a044ed085ce5e09d8b1b1a21c37f0e9b8) )
ROM_END
/***************************************************************************
PR-8210 PLAYER INTERFACE
***************************************************************************/
const ldplayer_interface vp931_interface =
{
LASERDISC_TYPE_PHILLIPS_22VP931, /* type of the player */
sizeof(ldplayer_data), /* size of the state */
"Phillips 22VP931", /* name of the player */
rom_vp931, /* pointer to ROM region information */
machine_config_vp931, /* pointer to machine configuration */
vp931_init, /* initialization callback */
vp931_vsync, /* vsync callback */
vp931_update, /* update callback */
NULL, /* overlay callback */
vp931_data_w, /* parallel data write */
{ /* single line write: */
NULL, /* LASERDISC_LINE_ENTER */
NULL /* LASERDISC_LINE_CONTROL */
},
vp931_data_r, /* parallel data read */
{ /* single line read: */
vp931_ready, /* LASERDISC_LINE_READY */
NULL, /* LASERDISC_LINE_STATUS */
NULL, /* LASERDISC_LINE_COMMAND */
vp931_data_ready, /* LASERDISC_LINE_DATA_AVAIL */
}
};
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/*-------------------------------------------------
vp931_set_data_ready_callback - set the data
ready callback
-------------------------------------------------*/
void vp931_set_data_ready_callback(const device_config *device, void (*callback)(const device_config *device, int state))
{
laserdisc_state *ld = ldcore_get_safe_token(device);
ld->player->data_ready_cb = callback;
}
/***************************************************************************
PHILLIPS 22VP931 IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
vp931_init - Pioneer PR-8210-specific
initialization
-------------------------------------------------*/
static void vp931_init(laserdisc_state *ld)
{
astring *tempstring = astring_alloc();
ldplayer_data *player = ld->player;
/* find our CPU */
astring_printf(tempstring, "%s:%s", ld->device->tag, "vp931");
player->cpunum = mame_find_cpu_index(ld->device->machine, astring_c(tempstring));
/* find our timer */
astring_printf(tempstring, "%s:%s", ld->device->tag, "tracktimer");
player->tracktimer = device_list_find_by_tag(ld->device->machine->config->devicelist, TIMER, astring_c(tempstring));
timer_device_set_ptr(player->tracktimer, ld);
astring_free(tempstring);
}
/*-------------------------------------------------
vp931_vsync - VSYNC callback, called at the
start of the blanking period
-------------------------------------------------*/
static void vp931_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
{
/* reset our command counter (debugging only) */
ld->player->cmdcount = 0;
/* set the ERP signal to 1 to indicate start of frame, and set a timer to turn it off */
ld->player->daticerp = 1;
timer_set(video_screen_get_time_until_pos(ld->screen, 15*2, 0), ld, 0, erp_off);
}
/*-------------------------------------------------
vp931_update - update callback, called on
the first visible line of the frame
-------------------------------------------------*/
static INT32 vp931_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
{
/* set the first VBI timer to go at the start of line 16 */
timer_set(video_screen_get_time_until_pos(ld->screen, 16*2, 0), ld, LASERDISC_CODE_LINE16 << 2, vbi_data_fetch);
/* play forward by default */
return fieldnum;
}
/*-------------------------------------------------
vp931_data_w - handle a parallel data write
to the 22VP931
-------------------------------------------------*/
static void vp931_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data)
{
/* set a timer to synchronize execution before sending the data */
timer_call_after_resynch(ld, data, deferred_data_w);
}
/*-------------------------------------------------
vp931_data_r - handle a parallel data read
from the 22VP931
-------------------------------------------------*/
static UINT8 vp931_data_r(laserdisc_state *ld)
{
ldplayer_data *player = ld->player;
/* if data is pending, clear the pending flag and notify any callbacks */
if (player->tocontroller_pending)
{
player->tocontroller_pending = FALSE;
if (player->data_ready_cb != NULL)
(*player->data_ready_cb)(ld->device, FALSE);
}
/* also boost interleave for 4 scanlines to ensure proper communications */
cpu_boost_interleave(attotime_zero, attotime_mul(video_screen_get_scan_period(ld->screen), 4));
return player->tocontroller;
}
/*-------------------------------------------------
vp931_ready - return the status of "ready"
to the caller (ready to accept another
command)
-------------------------------------------------*/
static UINT8 vp931_ready(laserdisc_state *ld)
{
/* if data is pending, we are not ready */
ldplayer_data *player = ld->player;
return player->fromcontroller_pending ? CLEAR_LINE : ASSERT_LINE;
}
/*-------------------------------------------------
vp931_data_ready - return the status of
"data available" to the caller
-------------------------------------------------*/
static UINT8 vp931_data_ready(laserdisc_state *ld)
{
ldplayer_data *player = ld->player;
return player->tocontroller_pending ? ASSERT_LINE : CLEAR_LINE;
}
/*-------------------------------------------------
output0_w - controls audio/video squelch
and other bits
-------------------------------------------------*/
static WRITE8_HANDLER( output0_w )
{
laserdisc_state *ld = find_vp931(machine);
ldplayer_data *player = ld->player;
/*
$80 = n/c
$40 = LED (?) -> C335
$20 = LED (?)
$10 = LED (?) -> CX
$08 = EJECT
$04 = inverted -> AUDIO MUTE II
$02 = inverted -> AUDIO MUTE I
$01 = inverted -> VIDEO MUTE
*/
if (LOG_PORTS && (player->out0 ^ data) & 0xff)
{
printf("%03X:out0:", activecpu_get_pc());
if ( (data & 0x80)) printf(" ???");
if ( (data & 0x40)) printf(" LED1");
if ( (data & 0x20)) printf(" LED2");
if ( (data & 0x10)) printf(" LED3");
if ( (data & 0x08)) printf(" EJECT");
if (!(data & 0x04)) printf(" AUDMUTE2");
if (!(data & 0x02)) printf(" AUDMUTE1");
if (!(data & 0x01)) printf(" VIDMUTE");
printf("\n");
player->out0 = data;
}
/* update a/v squelch */
ldcore_set_audio_squelch(ld, !(data & 0x02), !(data & 0x04));
ldcore_set_video_squelch(ld, !(data & 0x01));
}
/*-------------------------------------------------
output1_w - controls scanning behaviors
-------------------------------------------------*/
static WRITE8_HANDLER( output1_w )
{
laserdisc_state *ld = find_vp931(machine);
ldplayer_data *player = ld->player;
INT32 speed = 0;
/*
$80 = n/c
$40 = n/c
$20 = n/c
$10 = n/c
$08 = inverted -> SMS
$04 = inverted -> SSS
$02 = inverted -> SCAN CMD
$01 = OSM
*/
if (LOG_PORTS && (player->out1 ^ data) & 0x08)
{
mame_printf_debug("%03X:out1:", activecpu_get_pc());
if (!(data & 0x08)) mame_printf_debug(" SMS");
mame_printf_debug("\n");
player->out1 = data;
}
/* speed is 0 unless SCAN CMD is clear */
speed = 0;
if (!(data & 0x02))
{
/* fast/slow is based on bit 2 */
speed = (data & 0x04) ? VP931_SCAN_FAST_SPEED : VP931_SCAN_SPEED;
/* direction is based on bit 0 */
if (data & 0x01)
speed = -speed;
}
/* update the speed */
ldcore_set_slider_speed(ld, speed);
}
/*-------------------------------------------------
lcd_w - vestigial LCD frame display
-------------------------------------------------*/
static WRITE8_HANDLER( lcd_w )
{
/*
Frame number is written as 5 digits here; however, it is not actually
connected
*/
}
/*-------------------------------------------------
keypad_r - vestigial keypad/button controls
-------------------------------------------------*/
static READ8_HANDLER( keypad_r )
{
/*
From the code, this is apparently a vestigial keypad with basic controls:
$01 = play
$02 = still
$04 = jump 25 frames backward
$08 = jump 25 frames forward
$10 = search for frame 50(?)
$20 = search for frame 350(?)
$40 = reset
$80 = play reverse
*/
return 0x00;
}
/*-------------------------------------------------
datic_r - read the latched value from the
DATIC circuit
-------------------------------------------------*/
static READ8_HANDLER( datic_r )
{
laserdisc_state *ld = find_vp931(machine);
return ld->player->daticval;
}
/*-------------------------------------------------
from_controller_r - read the value the
external controller wrote
-------------------------------------------------*/
static READ8_HANDLER( from_controller_r )
{
laserdisc_state *ld = find_vp931(machine);
ldplayer_data *player = ld->player;
/* clear the pending flag and return the data */
player->fromcontroller_pending = FALSE;
return player->fromcontroller;
}
/*-------------------------------------------------
to_controller_w - write a value back to the
external controller
-------------------------------------------------*/
static WRITE8_HANDLER( to_controller_w )
{
laserdisc_state *ld = find_vp931(machine);
ldplayer_data *player = ld->player;
/* set the pending flag and stash the data */
player->tocontroller_pending = TRUE;
player->tocontroller = data;
/* signal to the callback if provided */
if (player->data_ready_cb != NULL)
(*player->data_ready_cb)(ld->device, TRUE);
/* also boost interleave for 4 scanlines to ensure proper communications */
cpu_boost_interleave(attotime_zero, attotime_mul(video_screen_get_scan_period(ld->screen), 4));
}
/*-------------------------------------------------
port1_r - read the 8048 I/O port 1
-------------------------------------------------*/
static READ8_HANDLER( port1_r )
{
laserdisc_state *ld = find_vp931(machine);
ldplayer_data *player = ld->player;
UINT8 result = 0x00;
/*
$80 = P17 = (in) unsure
$40 = P16 = (in) /ERP from datic circuit
$20 = P15 = (in) D105
*/
if (!player->daticerp)
result |= 0x40;
return result;
}
/*-------------------------------------------------
port1_w - write the 8048 I/O port 1
-------------------------------------------------*/
static WRITE8_HANDLER( port1_w )
{
laserdisc_state *ld = find_vp931(machine);
ldplayer_data *player = ld->player;
/*
$10 = P14 = (out) D104 -> /SPEED
$08 = P13 = (out) D103 -> /TIMER ENABLE
$04 = P12 = (out) D102 -> /REV
$02 = P11 = (out) D101 -> /FORW
$01 = P10 = (out) D100 -> some op-amp then to C334, B56, B332
*/
if (LOG_PORTS && (player->port1 ^ data) & 0x1f)
{
printf("%03X:port1:", activecpu_get_pc());
if (!(data & 0x10)) printf(" SPEED");
if (!(data & 0x08)) printf(" TIMENABLE");
if (!(data & 0x04)) printf(" REV");
if (!(data & 0x02)) printf(" FORW");
if (!(data & 0x01)) printf(" OPAMP");
printf("\n");
}
/* if bit 0 is set, we are not tracking */
if (data & 0x01)
player->trackdir = 0;
/* if bit 0 is clear and we weren't tracking before, initialize the state */
else if (player->trackdir == 0)
{
player->advanced = 0;
/* if bit 2 is clear, we are moving backwards */
if (!(data & 0x04))
{
player->trackdir = -1;
player->trackstate = 1;
}
/* if bit 1 is clear, we are moving forward */
else if (!(data & 0x02))
{
player->trackdir = 1;
player->trackstate = 0;
}
}
/* if we have a timer, adjust it */
if (player->tracktimer != NULL)
{
/* turn it off if we're not tracking */
if (player->trackdir == 0)
timer_device_adjust_periodic(player->tracktimer, attotime_never, 0, attotime_never);
/* if we just started tracking, or if the speed was changed, reprime the timer */
else if (((player->port1 ^ data) & 0x11) != 0)
{
/* speeds here are just guesses, but work with the player logic; this is the time per half-track */
attotime speed = (data & 0x10) ? ATTOTIME_IN_USEC(60) : ATTOTIME_IN_USEC(10);
/* always start with an initial long delay; the code expects this */
timer_device_adjust_periodic(player->tracktimer, ATTOTIME_IN_USEC(100), 0, speed);
}
}
player->port1 = data;
}
/*-------------------------------------------------
port2_r - read from the 8048 I/O port 2
-------------------------------------------------*/
static READ8_HANDLER( port2_r )
{
laserdisc_state *ld = find_vp931(machine);
ldplayer_data *player = ld->player;
UINT8 result = 0x00;
/*
$80 = P27 = (in) set/reset latch; set by FOC LS, reset by IGR
$20 = P25 = (in) D125 -> 0 when data written to controller is preset, reset to 1 when read
$10 = P24 = (in) D124 -> 0 when data from controller is present, reset to 1 on a read
*/
if (!player->tocontroller_pending)
result |= 0x20;
if (!player->fromcontroller_pending)
result |= 0x10;
return result;
}
/*-------------------------------------------------
port2_w - write the 8048 I/O port 2
-------------------------------------------------*/
static WRITE8_HANDLER( port2_w )
{
/*
$40 = P26 = (out) cleared while data is sent back & forth; set afterwards
[Not actually connected, but this is done in the code]
*/
}
/*-------------------------------------------------
t0_r - return the T0 line status, which is
connected to the DATIC's data strobe line
-------------------------------------------------*/
static READ8_HANDLER( t0_r )
{
laserdisc_state *ld = find_vp931(machine);
return ld->player->datastrobe;
}
/*-------------------------------------------------
t1_r - return the T1 line status, which is
connected to the tracking state and is used
to count the number of tracks advanced
-------------------------------------------------*/
static READ8_HANDLER( t1_r )
{
laserdisc_state *ld = find_vp931(machine);
return ld->player->trackstate;
}
/*-------------------------------------------------
vbi_data_fetch - called 4 times per scanline
on lines 16, 17, and 18 to feed the VBI data
through one byte at a time
-------------------------------------------------*/
static TIMER_CALLBACK( vbi_data_fetch )
{
laserdisc_state *ld = ptr;
ldplayer_data *player = ld->player;
int which = param & 3;
int line = param >> 2;
UINT32 code = 0;
/* fetch the code and compute the DATIC latched value */
if (line >= LASERDISC_CODE_LINE16 && line <= LASERDISC_CODE_LINE18)
code = laserdisc_get_field_code(ld->device, line);
/* at the start of each line, signal an interrupt and use a timer to turn it off */
if (which == 0)
{
cpunum_set_input_line(machine, player->cpunum, MCS48_INPUT_IRQ, ASSERT_LINE);
timer_set(ATTOTIME_IN_NSEC(5580), ld, 0, irq_off);
}
/* clock the data strobe on each subsequent callback */
else if (code != 0)
{
player->daticval = code >> (8 * (3 - which));
player->datastrobe = 1;
timer_set(ATTOTIME_IN_NSEC(5000), ld, 0, datastrobe_off);
}
/* determine the next bit to fetch and reprime ourself */
if (++which == 4)
{
which = 0;
line++;
}
if (line <= LASERDISC_CODE_LINE18 + 1)
timer_set(video_screen_get_time_until_pos(ld->screen, line*2, which * 2 * video_screen_get_width(ld->screen) / 4), ld, (line << 2) | which, vbi_data_fetch);
}
/*-------------------------------------------------
deferred_data_w - handle a write from the
external controller
-------------------------------------------------*/
static TIMER_CALLBACK( deferred_data_w )
{
laserdisc_state *ld = ptr;
ldplayer_data *player = ld->player;
/* set the value and mark it pending */
player->fromcontroller = param;
player->fromcontroller_pending = TRUE;
/* track the commands for debugging purposes */
if (player->cmdcount < ARRAY_LENGTH(player->cmdbuf))
{
player->cmdbuf[player->cmdcount++] = param;
if (LOG_COMMANDS && player->cmdcount == 3)
printf("Cmd: %02X %02X %02X\n", player->cmdbuf[0], player->cmdbuf[1], player->cmdbuf[2]);
}
}
/*-------------------------------------------------
irq_off - turn off the 8048 IRQ signal
-------------------------------------------------*/
static TIMER_CALLBACK( irq_off )
{
laserdisc_state *ld = ptr;
cpunum_set_input_line(machine, ld->player->cpunum, MCS48_INPUT_IRQ, CLEAR_LINE);
}
/*-------------------------------------------------
datastrobe_off - turn off the DATIC data
strobe signal
-------------------------------------------------*/
static TIMER_CALLBACK( datastrobe_off )
{
laserdisc_state *ld = ptr;
ld->player->datastrobe = 0;
}
/*-------------------------------------------------
erp_off - turn off the DATIC ERP signal
-------------------------------------------------*/
static TIMER_CALLBACK( erp_off )
{
laserdisc_state *ld = ptr;
ld->player->daticerp = 0;
}
/*-------------------------------------------------
track_timer - advance by one half-track
-------------------------------------------------*/
static TIMER_DEVICE_CALLBACK( track_timer )
{
laserdisc_state *ld = ptr;
ldplayer_data *player = ld->player;
/* advance by the count and toggle the state */
player->trackstate ^= 1;
if ((player->trackdir < 0 && !player->trackstate) || (player->trackdir > 0 && player->trackstate))
{
ldcore_advance_slider(ld, player->trackdir);
player->advanced += player->trackdir;
}
}

View File

@ -572,11 +572,11 @@ void timer_adjust_oneshot(emu_timer *which, attotime duration, INT32 param)
void timer_device_adjust_oneshot(const device_config *timer, attotime duration, INT32 param)
{
#ifndef NDEBUG
#ifdef MAME_DEBUG
timer_config *config = timer->inline_config;
/* only makes sense for periodic timers */
assert(config->type == TIMER_TYPE_PERIODIC);
/* doesn't make sense for scanline timers */
assert(config->type != TIMER_TYPE_SCANLINE);
#endif
timer_device_adjust_periodic(timer, duration, param, attotime_never);
@ -624,11 +624,11 @@ void timer_adjust_periodic(emu_timer *which, attotime start_delay, INT32 param,
void timer_device_adjust_periodic(const device_config *timer, attotime start_delay, INT32 param, attotime period)
{
timer_state *state = get_safe_token(timer);
#ifndef NDEBUG
#ifdef MAME_DEBUG
timer_config *config = timer->inline_config;
/* only makes sense for periodic timers */
assert(config->type == TIMER_TYPE_PERIODIC);
/* doesn't make sense for scanline timers */
assert(config->type != TIMER_TYPE_SCANLINE);
#endif
state->start_delay = start_delay;
@ -688,11 +688,11 @@ void timer_reset(emu_timer *which, attotime duration)
void timer_device_reset(const device_config *timer)
{
timer_state *state = get_safe_token(timer);
#ifndef NDEBUG
#ifdef MAME_DEBUG
timer_config *config = timer->inline_config;
/* only makes sense for periodic timers */
assert(config->type == TIMER_TYPE_PERIODIC);
/* doesn't make sense for scanline timers */
assert(config->type != TIMER_TYPE_SCANLINE);
#endif
timer_adjust_periodic(state->timer, state->start_delay, 0, state->period);
@ -745,8 +745,7 @@ int timer_device_enabled(const device_config *timer)
/*-------------------------------------------------
timer_get_param
timer_get_param_ptr - returns the callback
timer_get_param - returns the callback
parameter of a timer
-------------------------------------------------*/
@ -759,30 +758,79 @@ int timer_get_param(emu_timer *which)
int timer_device_get_param(const device_config *timer)
{
timer_state *state = get_safe_token(timer);
#ifndef NDEBUG
#ifdef MAME_DEBUG
timer_config *config = timer->inline_config;
/* only makes sense for periodic timers */
assert(config->type == TIMER_TYPE_PERIODIC);
/* doesn't make sense for scanline timers */
assert(config->type != TIMER_TYPE_SCANLINE);
#endif
return state->param;
}
void *timer_get_param_ptr(emu_timer *which)
/*-------------------------------------------------
timer_set_param - changes the callback
parameter of a timer
-------------------------------------------------*/
void timer_set_param(emu_timer *which, int param)
{
which->param = param;
}
void timer_device_set_param(const device_config *timer, int param)
{
timer_state *state = get_safe_token(timer);
#ifdef MAME_DEBUG
timer_config *config = timer->inline_config;
/* doesn't make sense for scanline timers */
assert(config->type != TIMER_TYPE_SCANLINE);
#endif
state->param = param;
}
/*-------------------------------------------------
timer_get_ptr - returns the callback pointer
of a timer
-------------------------------------------------*/
void *timer_get_ptr(emu_timer *which)
{
return which->ptr;
}
void *timer_device_get_param_ptr(const device_config *timer)
void *timer_device_get_ptr(const device_config *timer)
{
timer_state *state = get_safe_token(timer);
return state->ptr;
}
/*-------------------------------------------------
timer_set_ptr - changes the callback pointer
of a timer
-------------------------------------------------*/
void timer_set_ptr(emu_timer *which, void *ptr)
{
which->ptr = ptr;
}
void timer_device_set_ptr(const device_config *timer, void *ptr)
{
timer_state *state = get_safe_token(timer);
state->ptr = ptr;
}
/***************************************************************************
TIMING FUNCTIONS
***************************************************************************/
@ -994,7 +1042,7 @@ static DEVICE_START( timer )
/* get and validate the configuration */
config = device->inline_config;
assert((config->type == TIMER_TYPE_PERIODIC) || (config->type == TIMER_TYPE_SCANLINE));
assert(config->type == TIMER_TYPE_PERIODIC || config->type == TIMER_TYPE_SCANLINE || config->type == TIMER_TYPE_GENERIC);
assert(config->callback != NULL);
/* copy the pointer parameter */
@ -1007,6 +1055,29 @@ static DEVICE_START( timer )
/* type based configuration */
switch (config->type)
{
case TIMER_TYPE_GENERIC:
/* make sure that only the applicable parameters are filled in */
assert(config->screen == NULL);
assert(config->first_vpos == 0);
assert(config->increment == 0);
assert(config->start_delay == 0);
assert(config->period == 0);
/* copy the optional integer parameter */
state->param = config->param;
/* convert the start_delay and period into attotime */
state->period = attotime_never;
state->start_delay = attotime_zero;
/* register for state saves */
state_save_register_item(unique_tag, 0, state->param);
/* allocate the backing timer */
param = (void *)device;
state->timer = timer_alloc(periodic_timer_device_timer_callback, param);
break;
case TIMER_TYPE_PERIODIC:
/* make sure that only the applicable parameters are filled in */
assert(config->screen == NULL);

View File

@ -28,7 +28,8 @@
enum
{
TIMER_TYPE_PERIODIC = 0,
TIMER_TYPE_SCANLINE
TIMER_TYPE_SCANLINE,
TIMER_TYPE_GENERIC
};
@ -105,6 +106,11 @@ typedef struct _emu_timer emu_timer;
TIMER DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MDRV_TIMER_ADD(_tag, _callback) \
MDRV_DEVICE_ADD(_tag, TIMER) \
MDRV_DEVICE_CONFIG_DATA32(timer_config, type, TIMER_TYPE_GENERIC) \
MDRV_DEVICE_CONFIG_DATAPTR(timer_config, callback, _callback) \
#define MDRV_TIMER_ADD_PERIODIC(_tag, _callback, _period) \
MDRV_DEVICE_ADD(_tag, TIMER) \
MDRV_DEVICE_CONFIG_DATA32(timer_config, type, TIMER_TYPE_PERIODIC) \
@ -224,8 +230,17 @@ int timer_device_enabled(const device_config *timer);
int timer_get_param(emu_timer *which);
int timer_device_get_param(const device_config *timer);
void *timer_get_param_ptr(emu_timer *which);
void *timer_device_get_param_ptr(const device_config *timer);
/* changes the callback parameter of a timer */
void timer_set_param(emu_timer *which, int param);
void timer_device_set_param(const device_config *timer, int param);
/* returns the callback pointer of a timer */
void *timer_get_ptr(emu_timer *which);
void *timer_device_get_ptr(const device_config *timer);
/* changes the callback pointer of a timer */
void timer_set_ptr(emu_timer *which, void *ptr);
void timer_device_set_ptr(const device_config *timer, void *ptr);

View File

@ -26,7 +26,6 @@ but requires a special level III player for proper control. Video: CAV. Audio: A
*/
#include "mame.h"
#include "deprecat.h"
#include "driver.h"
#include "cpu/m6809/m6809.h"
#include "cpu/m6502/m6502.h"
@ -37,6 +36,10 @@ but requires a special level III player for proper control. Video: CAV. Audio: A
#include "machine/6532riot.h"
#include "machine/x2212.h"
#define MASTER_XTAL XTAL_14_31818MHz
/*
fff6=firq e4a2 when dav goes active/low
fff8=irq e38f This is through a flip-flop so goes off (high as active low) only when reset_irq is active - low.
@ -56,226 +59,77 @@ fffe=reset e7cc
/* FXXXXX for first field
AXXXXX for second field */
static const device_config *laserdisc;
static int m_n_disc_lock;
static int m_n_disc_left_audio;
static int m_n_disc_right_audio;
static int m_n_disc_data;
static int command_offset;
static int command_data[ 3 ];
static int manchester_data[ 6 ];
static int manchester_offset;
static int disc_reset;
static int disk_opr = 0;
static int dav = 0x80;
static int dak_just_low = 0; /* simulate the 15 uS time for the player to read the data */
static int dak = 0x40; /* DAK or DSKFULL active low indicates player has data,
reset when player has read data */
static int disk_data; /* after a command is sent the first bit indicates an error, except of the data is 0x00 which indicates an invalid manchester data read (whatever that means) */
int laser_disc_speed = 0;
int laser_disc_field = 0;
void laser_seek_frame( int frame )
{
}
static int m_n_disc_read_data;
/* 20 = DISKOPR - Active low
40 = DISKFULL - Active low
80 = DISKDAV - Active low data available
*/
READ8_HANDLER( firefox_disc_status_r )
static READ8_HANDLER( firefox_disc_status_r )
{
int n_data;
n_data = dav | dak | disk_opr; /* always operational */
logerror( "%08x: disc status r %02x\n", activecpu_get_pc(), n_data & ( 0x80 | 0x40 | 0x20 ) );
/*
fprintf(stderr, "%08x: reading disc status r %02x\n", activecpu_get_pc(), n_data & ( 0x80 | 0x40 | 0x20 ) );
*/
if(dak_just_low)
{
/* assume that the next status read will be after 15uS */
dak = 0x40;
dak_just_low = 0;
}
return n_data;
UINT8 result = 0xff;
result ^= 0x20;
if (!laserdisc_line_r(laserdisc, LASERDISC_LINE_READY))
result ^= 0x40;
if (laserdisc_line_r(laserdisc, LASERDISC_LINE_DATA_AVAIL))
result ^= 0x80;
return result;
}
/* 4105 - DREAD */
/* this reset RDDSK (&DSKRD) */
READ8_HANDLER( firefox_disc_data_r )
static READ8_HANDLER( firefox_disc_data_r )
{
return disk_data;
return m_n_disc_read_data;
}
/* DISK READ ENABLE */
/* 4218 - DSKREAD, set RDDSK */
WRITE8_HANDLER( firefox_disc_read_w )
static WRITE8_HANDLER( firefox_disc_read_w )
{
dav=0x80;
if( manchester_offset < 6 )
{
disk_data = manchester_data[ manchester_offset++ ];
if(manchester_offset < 6)
{
dav = 0; /* more data */
cpunum_set_input_line( machine, 0, M6809_FIRQ_LINE, ASSERT_LINE );
}
}
m_n_disc_read_data = laserdisc_data_r(laserdisc);
}
WRITE8_HANDLER( firefox_disc_lock_w )
static WRITE8_HANDLER( firefox_disc_lock_w )
{
m_n_disc_lock = data & 0x80;
}
WRITE8_HANDLER( firefox_disc_right_audio_enable_w )
static WRITE8_HANDLER( audio_enable_w )
{
m_n_disc_right_audio = data & 0x80;
if (!(offset & 1))
m_n_disc_right_audio = data & 0x80;
else
m_n_disc_left_audio = data & 0x80;
}
WRITE8_HANDLER( firefox_disc_left_audio_enable_w )
static WRITE8_HANDLER( firefox_disc_reset_w )
{
m_n_disc_left_audio = data & 0x80;
}
WRITE8_HANDLER( firefox_disc_reset_w )
{
disc_reset = (data & 0x80);
if(!disc_reset)
{
laser_disc_speed = 0;
manchester_offset = 6; /* no data available */
command_offset = 0;
dak = 0x40;
dav = 0x80;
}
laserdisc_line_w(laserdisc, LASERDISC_LINE_RESET, (data & 0x80) ? CLEAR_LINE : ASSERT_LINE);
}
/* active low on dbb7 */
WRITE8_HANDLER( firefox_disc_write_w )
static WRITE8_HANDLER( firefox_disc_write_w )
{
if( ( data & 0x80 ) == 0 )
{
dak = 0; /* should go high after 15 uS */
dak_just_low = 1;
command_data[ command_offset++ ] = m_n_disc_data;
if( command_offset == 3 )
{
command_offset = 0;
switch( command_data[ 0 ] & 0xf0 )
{
case 0xf0:
logerror( "CMD: goto Frame #%01x%02x%02x & play forward\n", command_data[ 0 ] & 0x0f, command_data[ 1 ], command_data[ 2 ] );
laser_disc_field =
( ( command_data[ 0 ] & 0x0f ) * 20000 ) +
( (( command_data[ 1 ] & 0xf0 ) >> 4) * 2000 ) +
( ( command_data[ 1 ] & 0x0f ) * 200 ) +
( (( command_data[ 2 ] & 0xf0 ) >> 4) * 20 ) +
( ( command_data[ 2 ] & 0x0f ) * 2 );
laser_seek_frame(laser_disc_field >> 1);
/*
fprintf(stderr, "CMD: goto frame #%01x%02x%02x & play forward disc_field %d\n", command_data[ 0 ] & 0x0f, command_data[ 1 ], command_data[ 2 ] , laser_disc_field);
*/
laser_disc_speed = 1;
return;
case 0xd0:
/*
fprintf(stderr, "CMD: goto Frame #%01x%02x%02x & halt (first field)\n", command_data[ 0 ] & 0x0f, command_data[ 1 ], command_data[ 2 ] );
*/
laser_disc_field =
( ( command_data[ 0 ] & 0x0f ) * 20000 ) +
( (( command_data[ 1 ] & 0xf0 ) >> 4) * 2000 ) +
( ( command_data[ 1 ] & 0x0f ) * 200 ) +
( (( command_data[ 2 ] & 0xf0 ) >> 4) * 20 ) +
( ( command_data[ 2 ] & 0x0f ) * 2 );
laser_seek_frame(laser_disc_field >> 1);
laser_disc_speed = 0;
return;
case 0x00:
switch( command_data[ 0 ] & 0x0f )
{
case 0x00:
switch( command_data[ 1 ] & 0xf0 )
{
case 0x00:
laser_disc_speed = 1;
return;
case 0x10:
laser_disc_speed = -1;
return;
case 0x20:
laser_disc_speed = 0;
return;
case 0x40:
return;
case 0x50:
return;
case 0xa0:
laser_disc_speed = 75;
return;
case 0xb0:
laser_disc_speed = -75;
return;
case 0xe0:
return;
case 0xf0:
return;
}
break;
case 0x02:
switch( command_data[ 1 ] )
{
case 0xb0:
logerror( "CMD: Video ON/OFF %02x\n", command_data[ 2 ] );
return;
case 0xb1:
logerror( "CMD: Audio-I ON/OFF %02x\n", command_data[ 2 ] );
return;
case 0xb2:
logerror( "CMD: Audio-II ON/OFF %02x\n", command_data[ 2 ] );
return;
case 0xb3:
logerror( "CMD: CX ON/OFF %02x\n", command_data[ 2 ] );
return;
}
break;
}
break;
}
logerror( "CMD: invalid %02x%02x%02x\n", command_data[ 0 ], command_data[ 1 ], command_data[ 2 ] );
}
}
if ( ( data & 0x80 ) == 0 )
laserdisc_data_w(laserdisc, m_n_disc_data);
}
/* latch the data */
WRITE8_HANDLER( firefox_disc_data_w )
static WRITE8_HANDLER( firefox_disc_data_w )
{
m_n_disc_data = data;
}
static TIMER_DEVICE_CALLBACK( laserdisk_timer_callback )
{
if(param == 0 && laser_disc_speed != 0)
{
manchester_data[ 0 ] = ( ( laser_disc_field & 0x01 )?0xA0:0xF0 ) | ( ( laser_disc_field / 20000 ) % 10 );
manchester_data[ 1 ] = ( ( ( laser_disc_field / 2000 ) % 10 ) << 4 ) | ( ( laser_disc_field / 200 ) % 10 );
manchester_data[ 2 ] = ( ( ( laser_disc_field / 20 ) % 10 ) << 4 ) | ( ( laser_disc_field / 2 ) % 10 );
manchester_data[ 3 ] = 0xff;
manchester_data[ 4 ] = 0xff;
manchester_data[ 5 ] = 0xff;
manchester_offset = 0;
cpunum_set_input_line( Machine, 0, M6809_FIRQ_LINE, ASSERT_LINE );
dav = 0; /* buffer contains info */
laser_disc_field += laser_disc_speed;
}
}
static unsigned char *tileram;
static size_t tileram_size;
static unsigned char *tile_palette;
static unsigned char *sprite_palette;
static const device_config *nvram_1c;
@ -292,20 +146,20 @@ static int sprite_bank;
*
*************************************/
VIDEO_UPDATE( firefox )
static VIDEO_UPDATE( firefox )
{
int x;
int y;
int sprite;
const rectangle *visarea = video_screen_get_visible_area( Machine->primary_screen );
int gfxtop = video_screen_get_visible_area(screen)->min_y;
fillbitmap( bitmap, 256, visarea );
fillbitmap( bitmap, 256, cliprect );
for( y = 0; y < 64; y++ )
{
for( x = 0; x < 64; x++ )
{
drawgfx( bitmap, Machine->gfx[ 0 ], tileram[ x + ( y * 64 ) ], 0, 0, 0, x * 8, y * 8, visarea, TRANSPARENCY_PEN, 0 );
drawgfx( bitmap, screen->machine->gfx[ 0 ], tileram[ x + ( y * 64 ) ], 0, 0, 0, x * 8, gfxtop + y * 8, cliprect, TRANSPARENCY_PEN, 0 );
}
}
@ -327,7 +181,7 @@ VIDEO_UPDATE( firefox )
int flipx = flags & 0x20;
int code = sprite_data[ 15 - row ] + ( 256 * ( ( flags >> 6 ) & 3 ) );
drawgfx( bitmap, Machine->gfx[ 1 ], code, color, flipx, flipy, x + 16, 500 - y - ( row * 16 ), visarea, TRANSPARENCY_PEN, 0 );
drawgfx( bitmap, screen->machine->gfx[ 1 ], code, color, flipx, flipy, x + 16, gfxtop + 500 - y - ( row * 16 ), cliprect, TRANSPARENCY_PEN, 0 );
}
}
}
@ -339,33 +193,33 @@ static TIMER_DEVICE_CALLBACK( video_timer_callback )
{
video_screen_update_now(timer->machine->primary_screen);
cpunum_set_input_line( Machine, 0, M6809_IRQ_LINE, ASSERT_LINE );
cputag_set_input_line( timer->machine, "main", M6809_IRQ_LINE, ASSERT_LINE );
}
static void set_rgba( int start, int index, unsigned char *palette_ram )
static void set_rgba( running_machine *machine, int start, int index, unsigned char *palette_ram )
{
int r = palette_ram[ index ];
int g = palette_ram[ index + 256 ];
int b = palette_ram[ index + 512 ];
int a = ( b & 3 ) * 0x55;
palette_set_color( Machine, start + index, MAKE_RGB( r, g, b ) );
render_container_set_palette_alpha(render_container_get_screen(Machine->primary_screen), start + index, a);
palette_set_color( machine, start + index, MAKE_RGB( r, g, b ) );
render_container_set_palette_alpha(render_container_get_screen(machine->primary_screen), start + index, a);
}
static WRITE8_HANDLER( tile_palette_w )
{
tile_palette[ offset ] = data;
set_rgba( 0, offset & 0xff, tile_palette );
set_rgba( machine, 0, offset & 0xff, tile_palette );
}
static WRITE8_HANDLER( sprite_palette_w )
{
sprite_palette[ offset ] = data;
set_rgba( 256, offset & 0xff, sprite_palette );
set_rgba( machine, 256, offset & 0xff, sprite_palette );
}
WRITE8_HANDLER( firefox_objram_bank_w )
static WRITE8_HANDLER( firefox_objram_bank_w )
{
sprite_bank = data & 0x03;
}
@ -397,8 +251,8 @@ static READ8_HANDLER( sound_to_main_r )
static WRITE8_HANDLER( main_to_sound_w )
{
main_to_sound_flag = 1;
soundlatch_w(Machine, 0, data);
cputag_set_input_line(Machine, "audio", INPUT_LINE_NMI, PULSE_LINE);
soundlatch_w(machine, 0, data);
cputag_set_input_line(machine, "audio", INPUT_LINE_NMI, PULSE_LINE);
}
static WRITE8_HANDLER( sound_reset_w )
@ -411,13 +265,13 @@ static WRITE8_HANDLER( sound_reset_w )
static READ8_HANDLER( main_to_sound_r )
{
main_to_sound_flag = 0;
return soundlatch_r(Machine, 0);
return soundlatch_r(machine, 0);
}
static WRITE8_HANDLER( sound_to_main_w )
{
sound_to_main_flag = 1;
soundlatch2_w(Machine, 0, data);
soundlatch2_w(machine, 0, data);
}
@ -472,10 +326,10 @@ static READ8_HANDLER( adc_r )
{
if( control_num == 0 )
{
return input_port_read( Machine, "PITCH" );
return input_port_read( machine, "PITCH" );
}
return input_port_read( Machine, "YAW" );
return input_port_read( machine, "YAW" );
}
static WRITE8_HANDLER( adc_select_w )
@ -522,24 +376,24 @@ static WRITE8_HANDLER( novram_store_w )
*
*************************************/
WRITE8_HANDLER( rom_bank_w )
static WRITE8_HANDLER( rom_bank_w )
{
memory_set_bank(1, data & 0x1f);
}
static WRITE8_HANDLER( main_irq_clear_w )
{
cpunum_set_input_line( machine, 0, M6809_IRQ_LINE, CLEAR_LINE );
cputag_set_input_line( machine, "main", M6809_IRQ_LINE, CLEAR_LINE );
}
static WRITE8_HANDLER( main_firq_clear_w )
{
cpunum_set_input_line( machine, 0, M6809_FIRQ_LINE, CLEAR_LINE );
cputag_set_input_line( machine, "main", M6809_FIRQ_LINE, CLEAR_LINE );
}
WRITE8_HANDLER( self_reset_w )
static WRITE8_HANDLER( self_reset_w )
{
cpunum_set_input_line( Machine, 0, INPUT_LINE_RESET, PULSE_LINE );
cputag_set_input_line( machine, "main", INPUT_LINE_RESET, PULSE_LINE );
}
@ -550,42 +404,36 @@ WRITE8_HANDLER( self_reset_w )
*
*************************************/
WRITE8_HANDLER( led_w )
static WRITE8_HANDLER( led_w )
{
if( ( data & 0x80 ) != 0 )
{
set_led_status( offset, 0 );
}
else
{
set_led_status( offset, 1 );
}
set_led_status( offset, ( data & 0x80 ) == 0 );
}
WRITE8_HANDLER( firefox_coin_counter_w )
static WRITE8_HANDLER( firefox_coin_counter_w )
{
coin_counter_w( offset, data & 0x80 );
}
MACHINE_START( firefox )
static void firq_gen(const device_config *device, int state)
{
if (state)
cputag_set_input_line( device->machine, "main", M6809_FIRQ_LINE, ASSERT_LINE );
}
static MACHINE_START( firefox )
{
memory_configure_bank(1, 0, 32, memory_region(machine, "main") + 0x10000, 0x1000);
nvram_1c = device_list_find_by_tag(machine->config->devicelist, X2212, "nvram_1c");
nvram_1d = device_list_find_by_tag(machine->config->devicelist, X2212, "nvram_1d");
laserdisc = device_list_find_by_tag(machine->config->devicelist, LASERDISC, "laserdisc");
vp931_set_data_ready_callback(laserdisc, firq_gen);
control_num = 0;
sprite_bank = 0;
command_data[ 0 ] = 0;
command_data[ 1 ] = 0;
command_data[ 2 ] = 0;
command_offset = 0;
laser_disc_field = 0;
laser_disc_speed = 0;
manchester_offset = 6;
}
@ -595,44 +443,41 @@ MACHINE_START( firefox )
*
*************************************/
static ADDRESS_MAP_START( main_map , ADDRESS_SPACE_PROGRAM, 8)
static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 8)
AM_RANGE(0x0000, 0x0fff) AM_RAM
AM_RANGE(0x1000, 0x1fff) AM_RAM AM_BASE(&tileram) AM_SIZE(&tileram_size)
AM_RANGE(0x2000, 0x27ff) AM_RAM AM_BASE(&spriteram) AM_SIZE(&spriteram_size)
AM_RANGE(0x1000, 0x1fff) AM_RAM AM_BASE(&tileram)
AM_RANGE(0x2000, 0x27ff) AM_RAM AM_BASE(&spriteram)
AM_RANGE(0x2800, 0x2aff) AM_READWRITE(SMH_RAM, sprite_palette_w) AM_BASE(&sprite_palette)
AM_RANGE(0x2b00, 0x2b00) AM_WRITE(firefox_objram_bank_w)
AM_RANGE(0x2b01, 0x2bff) AM_RAM
AM_RANGE(0x2b00, 0x2b00) AM_MIRROR(0x04ff) AM_WRITE(firefox_objram_bank_w)
AM_RANGE(0x2c00, 0x2eff) AM_READWRITE(SMH_RAM, tile_palette_w) AM_BASE(&tile_palette)
AM_RANGE(0x2f00, 0x2fff) AM_RAM
AM_RANGE(0x3000, 0x3fff) AM_ROMBANK(1)
AM_RANGE(0x4000, 0x40ff) AM_READWRITE(nvram_r, nvram_w)
AM_RANGE(0x4100, 0x4100) AM_READ_PORT("IN0")
AM_RANGE(0x4101, 0x4101) AM_READ_PORT("IN1")
AM_RANGE(0x4102, 0x4102) AM_READ(firefox_disc_status_r)
AM_RANGE(0x4103, 0x4103) AM_READ_PORT("IN3")
AM_RANGE(0x4104, 0x4104) AM_READ_PORT("IN4")
AM_RANGE(0x4105, 0x4105) AM_READ(firefox_disc_data_r)
AM_RANGE(0x4106, 0x4106) AM_READ(sound_to_main_r)
AM_RANGE(0x4107, 0x4107) AM_READ(adc_r)
AM_RANGE(0x4200, 0x4200) AM_WRITE(main_irq_clear_w)
AM_RANGE(0x4208, 0x4208) AM_WRITE(main_firq_clear_w)
AM_RANGE(0x4210, 0x4210) AM_WRITE(watchdog_reset_w)
AM_RANGE(0x4218, 0x4218) AM_WRITE(firefox_disc_read_w)
AM_RANGE(0x4220, 0x4221) AM_WRITE(adc_select_w)
AM_RANGE(0x4230, 0x4230) AM_WRITE(self_reset_w)
AM_RANGE(0x4280, 0x4280) AM_WRITE(novram_recall_w)
AM_RANGE(0x4281, 0x4281) AM_WRITE(sound_reset_w)
AM_RANGE(0x4282, 0x4282) AM_WRITE(novram_store_w)
AM_RANGE(0x4283, 0x4283) AM_WRITE(firefox_disc_lock_w)
AM_RANGE(0x4284, 0x4284) AM_WRITE(firefox_disc_right_audio_enable_w)
AM_RANGE(0x4285, 0x4285) AM_WRITE(firefox_disc_left_audio_enable_w)
AM_RANGE(0x4286, 0x4286) AM_WRITE(firefox_disc_reset_w)
AM_RANGE(0x4287, 0x4287) AM_WRITE(firefox_disc_write_w)
AM_RANGE(0x4288, 0x4289) AM_WRITE(firefox_coin_counter_w)
AM_RANGE(0x428c, 0x428f) AM_WRITE(led_w)
AM_RANGE(0x4290, 0x4290) AM_WRITE(rom_bank_w)
AM_RANGE(0x4298, 0x4298) AM_WRITE(main_to_sound_w)
AM_RANGE(0x42a0, 0x42a7) AM_WRITE(firefox_disc_data_w)
AM_RANGE(0x4000, 0x40ff) AM_READWRITE(nvram_r, nvram_w) /* NOVRAM */
AM_RANGE(0x4100, 0x4100) AM_MIRROR(0x00f8) AM_READ_PORT("rdin0") /* RDIN0 */
AM_RANGE(0x4101, 0x4101) AM_MIRROR(0x00f8) AM_READ_PORT("rdin1") /* RDIN1 */
AM_RANGE(0x4102, 0x4102) AM_MIRROR(0x00f8) AM_READ(firefox_disc_status_r) /* RDIN2 */
AM_RANGE(0x4103, 0x4103) AM_MIRROR(0x00f8) AM_READ_PORT("opt0") /* OPT0 */
AM_RANGE(0x4104, 0x4104) AM_MIRROR(0x00f8) AM_READ_PORT("opt1") /* OPT1 */
AM_RANGE(0x4105, 0x4105) AM_MIRROR(0x00f8) AM_READ(firefox_disc_data_r) /* DREAD */
AM_RANGE(0x4106, 0x4106) AM_MIRROR(0x00f8) AM_READ(sound_to_main_r) /* RDSOUND */
AM_RANGE(0x4107, 0x4107) AM_MIRROR(0x00f8) AM_READ(adc_r) /* ADC */
AM_RANGE(0x4200, 0x4200) AM_MIRROR(0x0047) AM_WRITE(main_irq_clear_w) /* RSTIRQ */
AM_RANGE(0x4208, 0x4208) AM_MIRROR(0x0047) AM_WRITE(main_firq_clear_w) /* RSTFIRQ */
AM_RANGE(0x4210, 0x4210) AM_MIRROR(0x0047) AM_WRITE(watchdog_reset_w) /* WDCLK */
AM_RANGE(0x4218, 0x4218) AM_MIRROR(0x0047) AM_WRITE(firefox_disc_read_w) /* DSKREAD */
AM_RANGE(0x4220, 0x4223) AM_MIRROR(0x0044) AM_WRITE(adc_select_w) /* ADCSTART */
AM_RANGE(0x4230, 0x4230) AM_MIRROR(0x0047) AM_WRITE(self_reset_w) /* AMUCK */
AM_RANGE(0x4280, 0x4280) AM_MIRROR(0x0040) AM_WRITE(novram_recall_w) /* LATCH0 -> NVRECALL */
AM_RANGE(0x4281, 0x4281) AM_MIRROR(0x0040) AM_WRITE(sound_reset_w) /* LATCH0 -> RSTSOUND */
AM_RANGE(0x4282, 0x4282) AM_MIRROR(0x0040) AM_WRITE(novram_store_w) /* LATCH0 -> NVRSTORE */
AM_RANGE(0x4283, 0x4283) AM_MIRROR(0x0040) AM_WRITE(firefox_disc_lock_w) /* LATCH0 -> LOCK */
AM_RANGE(0x4284, 0x4285) AM_MIRROR(0x0040) AM_WRITE(audio_enable_w) /* LATCH0 -> SWDSKR, SWDSKL */
AM_RANGE(0x4286, 0x4286) AM_MIRROR(0x0040) AM_WRITE(firefox_disc_reset_w) /* LATCH0 -> RSTDSK */
AM_RANGE(0x4287, 0x4287) AM_MIRROR(0x0040) AM_WRITE(firefox_disc_write_w) /* LATCH0 -> WRDSK */
AM_RANGE(0x4288, 0x4289) AM_MIRROR(0x0040) AM_WRITE(firefox_coin_counter_w) /* LATCH1 -> COIN COUNTERR, COUNTERL */
AM_RANGE(0x428c, 0x428f) AM_MIRROR(0x0040) AM_WRITE(led_w) /* LATCH1 -> LEDs */
AM_RANGE(0x4290, 0x4290) AM_MIRROR(0x0047) AM_WRITE(rom_bank_w) /* WRTREG */
AM_RANGE(0x4298, 0x4298) AM_MIRROR(0x0047) AM_WRITE(main_to_sound_w) /* WRSOUND */
AM_RANGE(0x42a0, 0x42a0) AM_MIRROR(0x0047) AM_WRITE(firefox_disc_data_w) /* DSKLATCH */
AM_RANGE(0x4400, 0xffff) AM_ROM
ADDRESS_MAP_END
@ -666,7 +511,7 @@ ADDRESS_MAP_END
*************************************/
INPUT_PORTS_START( firefox )
PORT_START("IN0")
PORT_START("rdin0")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 )
@ -676,7 +521,7 @@ INPUT_PORTS_START( firefox )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("IN1")
PORT_START("rdin1")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(mainflag_r, NULL)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(soundflag_r, NULL)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_VBLANK )
@ -686,7 +531,7 @@ INPUT_PORTS_START( firefox )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_START("IN3")
PORT_START("opt0")
PORT_DIPNAME( 0x03, 0x00, "Coins Per Credit" )
PORT_DIPSETTING( 0x00, "1 Coin 1 Credit" )
PORT_DIPSETTING( 0x01, "2 Coins 1 Credit" )
@ -709,7 +554,7 @@ INPUT_PORTS_START( firefox )
PORT_DIPSETTING( 0x60, "2 Credits for 4 Coin Units" )
PORT_DIPSETTING( 0xe0, DEF_STR( Free_Play ) )
PORT_START("IN4")
PORT_START("opt1")
PORT_DIPNAME( 0x01, 0x00, "Missions" )
PORT_DIPSETTING( 0x00, "All .50" )
PORT_DIPSETTING( 0x01, ".50 .75" )
@ -770,7 +615,7 @@ static const gfx_layout spritelayout =
};
static GFXDECODE_START( firefox )
GFXDECODE_ENTRY("tiles", 0, tilelayout, 0, 16)
GFXDECODE_ENTRY("tiles", 0, tilelayout, 0, 16)
GFXDECODE_ENTRY("sprites", 0, spritelayout, 256, 32)
GFXDECODE_END
@ -795,14 +640,18 @@ static const riot6532_interface riot_intf =
static MACHINE_DRIVER_START( firefox )
/* basic machine hardware */
MDRV_CPU_ADD("main", M6809, 4000000)
MDRV_CPU_ADD("main", M6809E, MASTER_XTAL/2)
MDRV_CPU_PROGRAM_MAP(main_map, 0)
MDRV_TIMER_ADD_SCANLINE("32v", video_timer_callback, "main", 96, 128)
/* interrupts count starting at end of VBLANK, which is 44, so add 44 */
MDRV_TIMER_ADD_SCANLINE("32v", video_timer_callback, "main", 96+44, 128)
MDRV_CPU_ADD("audio", M6502, 2000000)
MDRV_CPU_ADD("audio", M6502, MASTER_XTAL/8)
MDRV_CPU_PROGRAM_MAP(audio_map, 0)
MDRV_INTERLEAVE(100)
MDRV_MACHINE_START(firefox)
MDRV_WATCHDOG_TIME_INIT(UINT64_ATTOTIME_IN_HZ((double)MASTER_XTAL/8/16/16/16/16))
/* video hardware */
MDRV_LASERDISC_SCREEN_ADD_NTSC("main", BITMAP_FORMAT_INDEXED16)
@ -810,35 +659,34 @@ static MACHINE_DRIVER_START( firefox )
MDRV_GFXDECODE(firefox)
MDRV_PALETTE_LENGTH(512)
MDRV_LASERDISC_ADD("laserdisc", PIONEER_PR8210, "main", "ldsound")
MDRV_LASERDISC_OVERLAY(firefox, 64*8, 64*8, BITMAP_FORMAT_INDEXED16)
MDRV_LASERDISC_OVERLAY_CLIP(7*8, 53*8-1, 1*8, 62*8-1)
MDRV_TIMER_ADD_SCANLINE("laserdisk", laserdisk_timer_callback, "main", 0, 0)
MDRV_LASERDISC_ADD("laserdisc", PHILLIPS_22VP931, "main", "ldsound")
MDRV_LASERDISC_OVERLAY(firefox, 64*8, 525, BITMAP_FORMAT_INDEXED16)
MDRV_LASERDISC_OVERLAY_CLIP(7*8, 53*8-1, 44, 480+44)
MDRV_DEVICE_ADD("nvram_1c",X2212)
MDRV_DEVICE_ADD("nvram_1d",X2212)
MDRV_RIOT6532_ADD("riot", 1500000, riot_intf)
MDRV_RIOT6532_ADD("riot", MASTER_XTAL/8, riot_intf)
/* sound hardware */
MDRV_SPEAKER_STANDARD_STEREO("left", "right")
MDRV_SOUND_ADD("pokey1", POKEY, 1500000)
MDRV_SOUND_ADD("pokey1", POKEY, MASTER_XTAL/8)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "left", 0.20)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "right", 0.20)
MDRV_SOUND_ADD("pokey2", POKEY, 1500000)
MDRV_SOUND_ADD("pokey2", POKEY, MASTER_XTAL/8)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "left", 0.20)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "right", 0.20)
MDRV_SOUND_ADD("pokey3", POKEY, 1500000)
MDRV_SOUND_ADD("pokey3", POKEY, MASTER_XTAL/8)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "left", 0.20)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "right", 0.20)
MDRV_SOUND_ADD("pokey4", POKEY, 1500000)
MDRV_SOUND_ADD("pokey4", POKEY, MASTER_XTAL/8)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "left", 0.20)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "right", 0.20)
MDRV_SOUND_ADD("tms", TMS5220, 640000)
MDRV_SOUND_ADD("tms", TMS5220, MASTER_XTAL/2/10)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "left", 0.50)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "right", 0.50)
@ -846,7 +694,6 @@ static MACHINE_DRIVER_START( firefox )
MDRV_SOUND_CONFIG(laserdisc_custom_interface)
MDRV_SOUND_ROUTE(0, "left", 1.0)
MDRV_SOUND_ROUTE(1, "right", 1.0)
MACHINE_DRIVER_END
@ -894,6 +741,9 @@ ROM_START( firefox )
ROM_LOAD( "136026.120", 0x1c000, 0x4000, CRC(e1b95923) SHA1(b6d0c0af0a8f55e728cd0f4c3222745eefd57f50)) /* 2a */
ROM_LOAD( "136026.115", 0x20000, 0x4000, CRC(861abc82) SHA1(1845888d07162ae915364a2a91294731f1c5b3bd)) /* 1c */
ROM_LOAD( "136026.119", 0x24000, 0x4000, CRC(959471b1) SHA1(a032209a209f51d34360d5c7ad32ec62150158d2)) /* 1a */
DISK_REGION( "laserdisc" )
DISK_IMAGE_READONLY( "firefox", 0, NO_DUMP )
ROM_END
ROM_START( firefoxa )
@ -931,6 +781,9 @@ ROM_START( firefoxa )
ROM_LOAD( "136026.120", 0x1c000, 0x4000, CRC(e1b95923) SHA1(b6d0c0af0a8f55e728cd0f4c3222745eefd57f50)) /* 2a */
ROM_LOAD( "136026.115", 0x20000, 0x4000, CRC(861abc82) SHA1(1845888d07162ae915364a2a91294731f1c5b3bd)) /* 1c */
ROM_LOAD( "136026.119", 0x24000, 0x4000, CRC(959471b1) SHA1(a032209a209f51d34360d5c7ad32ec62150158d2)) /* 1a */
DISK_REGION( "laserdisc" )
DISK_IMAGE_READONLY( "firefox", 0, NO_DUMP )
ROM_END