mirror of
https://github.com/holub/mame
synced 2025-04-21 16:01:56 +03:00
Changed requirements for laserdisc CHDs to require a new chunk of
metadata with pre-decoded frame information. Modified chdman to automatically produce this for CHDs that are of the appropriate parameters. To fix up existing CHDs, use chdman -fixavdata on the CHD. Modified the laserdisc core to leverage the pre-decoded frame metadata, which is now required. This improves seek times when searching and allows the player-specific emulation access to the VBI data as soon as it would really be available. Changed update callback timing to fire just before the first line of VBI data would be read; at that point, the frame selection is assumed to be committed. Converted PR-8210 emulation over to using the actual MCU from the laserdisc player. This MCU controls low-level functions such as slider position and laser on/off, and receives decoded vertical blanking data in order to make decisions. Removed old HLE behavior. Note that the overlay text is displayed via the UI; this is temporary and will be fixed shortly. Converted Simutrek-hacked laserdisc emulation to using the actual MCU from the game, which in turn hands off commands to the PR-8210 MCU. This is still not 100% but is pretty close at this point and achieves the correct behaviors in most cases. Fixed Cube Quest overlay scaling to cover the whole screen. Changed laserdisc video parameters to position the screen area at the bottom rather than the top, since this corresponds more closely to standard line numbering. Extended the vbiparse code to support pack/unpack, and to more fully document all the meanings of the VBI codes. Updated ldplayer to support slow/fast forward movement, frame/chapter display, and separate controls for scanning/stepping. Added new built-in variable "frame" to the debugger. Fixed device-based ROM loading to support loading ROMs from the game's ZIP as well.
This commit is contained in:
parent
8e4ed69247
commit
1eb3c2d964
@ -1114,10 +1114,11 @@ static void mcs48_get_info(UINT32 state, cpuinfo *info)
|
||||
case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Mirko Buffoni\nBased on the original work Copyright Dan Boris"); break;
|
||||
|
||||
case CPUINFO_STR_FLAGS:
|
||||
sprintf(info->s, "%c %c%c%c%c%c%c%c%c",
|
||||
mcs48.a11 ? 'M':'.',
|
||||
sprintf(info->s, "%c%c %c%c%c%c%c%c%c%c",
|
||||
mcs48.irq_state ? 'I':'.',
|
||||
mcs48.a11 ? 'M':'.',
|
||||
PSW & 0x80 ? 'C':'.',
|
||||
PSW & 0x40 ? 'a':'.',
|
||||
PSW & 0x40 ? 'A':'.',
|
||||
PSW & 0x20 ? 'F':'.',
|
||||
PSW & 0x10 ? 'B':'.',
|
||||
PSW & 0x08 ? '?':'.',
|
||||
|
@ -278,8 +278,8 @@ offs_t mcs48_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opra
|
||||
cp++;
|
||||
switch (*cp++)
|
||||
{
|
||||
case 'A': sprintf(num,"$%04X",a); break;
|
||||
case 'J': sprintf(num,"$%04X",((pc+1) & 0xf00) | a); break;
|
||||
case 'A': sprintf(num,"$%03X",a); break;
|
||||
case 'J': sprintf(num,"$%03X",((pc+1) & 0xf00) | a); break;
|
||||
case 'B': sprintf(num,"%d",b); break;
|
||||
case 'D': sprintf(num,"%d",d); break;
|
||||
case 'X': sprintf(num,"%X",d); break;
|
||||
|
@ -120,6 +120,7 @@ static UINT64 get_tempvar(void *ref);
|
||||
static UINT64 get_logunmap(void *ref);
|
||||
static UINT64 get_beamx(void *ref);
|
||||
static UINT64 get_beamy(void *ref);
|
||||
static UINT64 get_frame(void *ref);
|
||||
static void set_tempvar(void *ref, UINT64 value);
|
||||
static void set_logunmap(void *ref, UINT64 value);
|
||||
static UINT64 get_current_pc(void *ref);
|
||||
@ -200,6 +201,7 @@ void debug_cpu_init(running_machine *machine)
|
||||
symtable_add_register(global_symtable, "logunmapi", (void *)ADDRESS_SPACE_IO, get_logunmap, set_logunmap);
|
||||
symtable_add_register(global_symtable, "beamx", NULL, get_beamx, NULL);
|
||||
symtable_add_register(global_symtable, "beamy", NULL, get_beamy, NULL);
|
||||
symtable_add_register(global_symtable, "frame", NULL, get_frame, NULL);
|
||||
|
||||
/* add the temporary variables to the global symbol table */
|
||||
for (regnum = 0; regnum < NUM_TEMP_VARIABLES; regnum++)
|
||||
@ -2815,6 +2817,22 @@ static UINT64 get_beamy(void *ref)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
get_frame - get current frame number
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 get_frame(void *ref)
|
||||
{
|
||||
UINT64 ret = 0;
|
||||
const device_config *screen = device_list_find_by_index(Machine->config->devicelist, VIDEO_SCREEN, 0);
|
||||
|
||||
if (screen != NULL)
|
||||
ret = video_screen_get_frame_number(screen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
set_logunmap - setter callback for the logumap
|
||||
symbols
|
||||
|
@ -1086,7 +1086,7 @@ UINT8 laserdisc_line_r(const device_config *device, UINT8 line)
|
||||
video frame
|
||||
-------------------------------------------------*/
|
||||
|
||||
UINT32 laserdisc_get_video(const device_config *device, bitmap_t **bitmap)
|
||||
int laserdisc_get_video(const device_config *device, bitmap_t **bitmap)
|
||||
{
|
||||
laserdisc_state *ld = get_safe_token(device);
|
||||
int frameindex;
|
||||
@ -1100,12 +1100,12 @@ UINT32 laserdisc_get_video(const device_config *device, bitmap_t **bitmap)
|
||||
if (!video_active(ld) || ld->videofields[frameindex] < 2)
|
||||
{
|
||||
*bitmap = ld->emptyframe;
|
||||
return 0;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*bitmap = ld->videovisframe[frameindex];
|
||||
return ld->videoframenum[frameindex];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ struct _laserdisc_config
|
||||
\
|
||||
MDRV_SCREEN_ADD(_tag, RASTER) \
|
||||
MDRV_SCREEN_FORMAT(_overlayformat) \
|
||||
MDRV_SCREEN_RAW_PARAMS(XTAL_14_31818MHz*2, 910, 0, 704, 525, 0, 480) \
|
||||
MDRV_SCREEN_RAW_PARAMS(XTAL_14_31818MHz*2, 910, 0, 704, 525, 44, 524) \
|
||||
|
||||
/* not correct yet; fix me... */
|
||||
#define MDRV_LASERDISC_SCREEN_ADD_PAL(_tag, _format) \
|
||||
@ -157,8 +157,8 @@ extern const custom_sound_interface laserdisc_custom_interface;
|
||||
|
||||
/* ----- core control and status ----- */
|
||||
|
||||
/* get a bitmap for the current frame (and the frame number) */
|
||||
UINT32 laserdisc_get_video(const device_config *device, bitmap_t **bitmap);
|
||||
/* get a bitmap for the current frame; return TRUE if valid or FALSE if video off */
|
||||
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);
|
||||
@ -189,9 +189,6 @@ void pr7820_set_slow_speed(const device_config *device, double frame_rate_scaler
|
||||
/* control the audio squelch of the Simutrek modified players */
|
||||
void simutrek_set_audio_squelch(const device_config *device, int state);
|
||||
|
||||
/* set the callback */
|
||||
void simutrek_set_cmd_ack_callback(const device_config *device, void (*callback)(void));
|
||||
|
||||
|
||||
|
||||
/* ----- video interface ----- */
|
||||
|
@ -23,7 +23,7 @@
|
||||
DEBUGGING
|
||||
***************************************************************************/
|
||||
|
||||
#define LOG_POSITION(x) /*printf x*/
|
||||
#define LOG_SLIDER 0
|
||||
|
||||
|
||||
|
||||
@ -42,6 +42,17 @@
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* video frame data */
|
||||
typedef struct _frame_data frame_data;
|
||||
struct _frame_data
|
||||
{
|
||||
bitmap_t * bitmap; /* cached bitmap */
|
||||
bitmap_t * visbitmap; /* wrapper around bitmap with only visible lines */
|
||||
UINT8 numfields; /* number of fields in this frame */
|
||||
INT32 lastfield; /* last absolute field number */
|
||||
};
|
||||
|
||||
|
||||
/* core-specific data */
|
||||
struct _ldcore_data
|
||||
{
|
||||
@ -51,11 +62,12 @@ struct _ldcore_data
|
||||
|
||||
/* disc parameters */
|
||||
chd_file * disc; /* handle to the disc itself */
|
||||
UINT8 * vbidata; /* pointer to precomputed VBI data */
|
||||
int width; /* width of video */
|
||||
int height; /* height of video */
|
||||
UINT32 fps_times_1million; /* frame rate of video */
|
||||
int samplerate; /* audio samplerate */
|
||||
UINT8 readpending; /* true if a read is pending */
|
||||
chd_error readresult; /* result of the most recent read */
|
||||
UINT32 chdtracks; /* number of tracks in the CHD */
|
||||
av_codec_decompress_config avconfig; /* decompression configuration */
|
||||
|
||||
@ -69,10 +81,7 @@ struct _ldcore_data
|
||||
attotime sliderupdate; /* time of last slider update */
|
||||
|
||||
/* video data */
|
||||
bitmap_t * videoframe[3]; /* currently cached frames */
|
||||
bitmap_t * videovisframe[3]; /* wrapper around videoframe with only visible lines */
|
||||
UINT8 videofields[3]; /* number of fields in each frame */
|
||||
UINT32 videoframenum[3]; /* frame number contained in each frame */
|
||||
frame_data frame[3]; /* circular list of frames */
|
||||
UINT8 videoindex; /* index of the current video buffer */
|
||||
bitmap_t videotarget; /* fake target bitmap for decompression */
|
||||
bitmap_t * emptyframe; /* blank frame */
|
||||
@ -88,8 +97,6 @@ struct _ldcore_data
|
||||
|
||||
/* metadata */
|
||||
vbi_metadata metadata[2]; /* metadata parsed from the stream, for each field */
|
||||
int last_frame; /* last seen frame number */
|
||||
int last_chapter; /* last seen chapter number */
|
||||
|
||||
/* I/O data */
|
||||
UINT8 datain; /* current input data value */
|
||||
@ -122,9 +129,9 @@ struct _sound_token
|
||||
***************************************************************************/
|
||||
|
||||
/* generic helper functions */
|
||||
static TIMER_CALLBACK( perform_player_update );
|
||||
static void read_track_data(laserdisc_state *ld);
|
||||
static void process_track_data(const device_config *device);
|
||||
static void fake_metadata(UINT32 track, UINT8 which, vbi_metadata *metadata);
|
||||
//static void render_display(UINT16 *videodata, UINT32 rowpixels, UINT32 width, int frame);
|
||||
static void *custom_start(int clock, const custom_sound_interface *config);
|
||||
static void custom_stream_callback(void *param, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
@ -377,17 +384,35 @@ static void vblank_state_changed(const device_config *screen, void *param, int v
|
||||
/* update current track based on slider speed */
|
||||
update_slider_pos(ldcore, curtime);
|
||||
|
||||
/* on rising edge, call the player-specific VSYNC function */
|
||||
/* on rising edge, process previously-read frame and inform the player */
|
||||
if (vblank_state)
|
||||
{
|
||||
/* call the player's VSYNC callback */
|
||||
if (ldcore->intf.vsync != NULL)
|
||||
(*ldcore->intf.vsync)(ld);
|
||||
return;
|
||||
(*ldcore->intf.vsync)(ld, &ldcore->metadata[ldcore->fieldnum], ldcore->fieldnum, curtime);
|
||||
|
||||
/* set a timer to begin fetching the next frame just before the VBI data would be fetched */
|
||||
timer_set(video_screen_get_time_until_pos(screen, 16*2, 0), ld, 0, perform_player_update);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
vblank_state_changed - called on each state
|
||||
change of the VBLANK signal
|
||||
-------------------------------------------------*/
|
||||
|
||||
static TIMER_CALLBACK( perform_player_update )
|
||||
{
|
||||
laserdisc_state *ld = ptr;
|
||||
ldcore_data *ldcore = ld->core;
|
||||
attotime curtime = timer_get_time();
|
||||
|
||||
/* on falling edge, do the bulk of the processing */
|
||||
/* wait for previous read and decode to finish */
|
||||
process_track_data(device);
|
||||
process_track_data(ld->device);
|
||||
|
||||
/* update current track based on slider speed */
|
||||
update_slider_pos(ldcore, curtime);
|
||||
|
||||
/* update the state */
|
||||
if (ldcore->intf.update != NULL)
|
||||
@ -501,30 +526,31 @@ UINT8 laserdisc_line_r(const device_config *device, UINT8 line)
|
||||
|
||||
/*-------------------------------------------------
|
||||
laserdisc_get_video - return the current
|
||||
video frame
|
||||
video frame; return TRUE if valid or FALSE
|
||||
if video off
|
||||
-------------------------------------------------*/
|
||||
|
||||
UINT32 laserdisc_get_video(const device_config *device, bitmap_t **bitmap)
|
||||
int laserdisc_get_video(const device_config *device, bitmap_t **bitmap)
|
||||
{
|
||||
laserdisc_state *ld = get_safe_token(device);
|
||||
ldcore_data *ldcore = ld->core;
|
||||
int frameindex;
|
||||
frame_data *frame;
|
||||
|
||||
/* determine the most recent live set of frames */
|
||||
frameindex = ldcore->videoindex;
|
||||
if (ldcore->videofields[frameindex] < 2)
|
||||
frameindex = (frameindex + ARRAY_LENGTH(ldcore->videofields) - 1) % ARRAY_LENGTH(ldcore->videofields);
|
||||
frame = &ldcore->frame[ldcore->videoindex];
|
||||
if (frame->numfields < 2)
|
||||
frame = &ldcore->frame[(ldcore->videoindex + ARRAY_LENGTH(ldcore->frame) - 1) % ARRAY_LENGTH(ldcore->frame)];
|
||||
|
||||
/* if no video present, return the empty frame */
|
||||
if (ldcore->videosquelch || ldcore->videofields[frameindex] < 2)
|
||||
if (ldcore->videosquelch || frame->numfields < 2)
|
||||
{
|
||||
*bitmap = ldcore->emptyframe;
|
||||
return 0;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*bitmap = ldcore->videovisframe[frameindex];
|
||||
return ldcore->videoframenum[frameindex];
|
||||
*bitmap = frame->visbitmap;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -538,11 +564,7 @@ UINT32 laserdisc_get_field_code(const device_config *device, UINT8 code)
|
||||
{
|
||||
laserdisc_state *ld = get_safe_token(device);
|
||||
ldcore_data *ldcore = ld->core;
|
||||
int field = ldcore->fieldnum ^ 1;
|
||||
|
||||
/* if no video present, return */
|
||||
if (ldcore->videosquelch)
|
||||
return 0;
|
||||
int field = ldcore->fieldnum;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
@ -557,6 +579,9 @@ UINT32 laserdisc_get_field_code(const device_config *device, UINT8 code)
|
||||
|
||||
case LASERDISC_CODE_LINE18:
|
||||
return ldcore->metadata[field].line18;
|
||||
|
||||
case LASERDISC_CODE_LINE1718:
|
||||
return ldcore->metadata[field].line1718;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -626,7 +651,8 @@ void ldcore_set_slider_speed(laserdisc_state *ld, INT32 tracks_per_vsync)
|
||||
else
|
||||
ldcore->attospertrack = -attotime_to_attoseconds(attotime_div(vsyncperiod, -tracks_per_vsync));
|
||||
|
||||
printf("Slider speed = %d\n", tracks_per_vsync);
|
||||
if (LOG_SLIDER)
|
||||
printf("Slider speed = %d\n", tracks_per_vsync);
|
||||
}
|
||||
|
||||
|
||||
@ -641,7 +667,8 @@ void ldcore_advance_slider(laserdisc_state *ld, INT32 numtracks)
|
||||
|
||||
update_slider_pos(ldcore, timer_get_time());
|
||||
add_and_clamp_track(ldcore, numtracks);
|
||||
printf("Advance by %d\n", numtracks);
|
||||
if (LOG_SLIDER)
|
||||
printf("Advance by %d\n", numtracks);
|
||||
}
|
||||
|
||||
|
||||
@ -861,21 +888,38 @@ static void read_track_data(laserdisc_state *ld)
|
||||
ldcore_data *ldcore = ld->core;
|
||||
UINT32 tracknum = ldcore->curtrack;
|
||||
UINT32 fieldnum = ldcore->fieldnum;
|
||||
chd_error err;
|
||||
frame_data *frame;
|
||||
UINT32 vbiframe;
|
||||
UINT32 readhunk;
|
||||
INT32 chdtrack;
|
||||
|
||||
/* if the previous field had the white flag, force the new field to pair with it */
|
||||
if (ldcore->metadata[fieldnum ^ 1].white)
|
||||
ldcore->videofields[ldcore->videoindex] = 1;
|
||||
/* 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 */
|
||||
if (ldcore->videofields[ldcore->videoindex] >= 2)
|
||||
else if (frame->numfields >= 2)
|
||||
{
|
||||
ldcore->videoindex = (ldcore->videoindex + 1) % ARRAY_LENGTH(ldcore->videofields);
|
||||
ldcore->videofields[ldcore->videoindex] = 0;
|
||||
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 */
|
||||
if (ldcore->videosquelch)
|
||||
frame->numfields = 0;
|
||||
|
||||
/* remember the last field number */
|
||||
frame->lastfield = tracknum * 2 + fieldnum;
|
||||
|
||||
/* set the video target information */
|
||||
ldcore->videotarget = *ldcore->videoframe[ldcore->videoindex];
|
||||
ldcore->videotarget = *frame->bitmap;
|
||||
ldcore->videotarget.base = BITMAP_ADDR16(&ldcore->videotarget, fieldnum, 0);
|
||||
ldcore->videotarget.height /= 2;
|
||||
ldcore->videotarget.rowpixels *= 2;
|
||||
@ -900,20 +944,23 @@ static void read_track_data(laserdisc_state *ld)
|
||||
ldcore->avconfig.actsamples = &ldcore->audiocursamples;
|
||||
ldcore->audiocursamples = 0;
|
||||
|
||||
/* configure the codec and then read */
|
||||
if (ldcore->disc != NULL)
|
||||
{
|
||||
err = chd_codec_config(ldcore->disc, AV_CODEC_DECOMPRESS_CONFIG, &ldcore->avconfig);
|
||||
if (err == CHDERR_NONE)
|
||||
{
|
||||
INT32 chdtrack = tracknum - 1 - VIRTUAL_LEAD_IN_TRACKS;
|
||||
/* compute the chdhunk number we are going to read */
|
||||
chdtrack = tracknum - 1 - VIRTUAL_LEAD_IN_TRACKS;
|
||||
chdtrack = MAX(chdtrack, 0);
|
||||
chdtrack = MIN(chdtrack, ldcore->chdtracks - 1);
|
||||
readhunk = chdtrack * 2 + fieldnum;
|
||||
|
||||
/* set the VBI data for the new field from our precomputed data */
|
||||
if (ldcore->vbidata != NULL)
|
||||
vbi_metadata_unpack(&ldcore->metadata[fieldnum], &vbiframe, &ldcore->vbidata[readhunk * VBI_PACKED_BYTES]);
|
||||
|
||||
/* clamp the track */
|
||||
chdtrack = MAX(chdtrack, 0);
|
||||
chdtrack = MIN(chdtrack, ldcore->chdtracks - 1);
|
||||
err = chd_read_async(ldcore->disc, chdtrack * 2 + fieldnum, NULL);
|
||||
ldcore->readpending = TRUE;
|
||||
}
|
||||
/* configure the codec and then read */
|
||||
ldcore->readresult = CHDERR_FILE_NOT_FOUND;
|
||||
if (ldcore->disc != NULL && !ldcore->videosquelch)
|
||||
{
|
||||
ldcore->readresult = chd_codec_config(ldcore->disc, AV_CODEC_DECOMPRESS_CONFIG, &ldcore->avconfig);
|
||||
if (ldcore->readresult == CHDERR_NONE)
|
||||
ldcore->readresult = chd_read_async(ldcore->disc, readhunk, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -927,47 +974,23 @@ static void process_track_data(const device_config *device)
|
||||
{
|
||||
laserdisc_state *ld = get_safe_token(device);
|
||||
ldcore_data *ldcore = ld->core;
|
||||
UINT32 tracknum = ldcore->curtrack;
|
||||
UINT32 fieldnum = ldcore->fieldnum;
|
||||
int frame, chapter;
|
||||
chd_error chderr;
|
||||
|
||||
/* wait for the async operation to complete */
|
||||
if (ldcore->disc != NULL && ldcore->readpending)
|
||||
{
|
||||
/* complete the async operation */
|
||||
chderr = chd_async_complete(ldcore->disc);
|
||||
if (chderr != CHDERR_NONE && chderr != CHDERR_NO_ASYNC_OPERATION)
|
||||
ldcore->avconfig.video = NULL;
|
||||
}
|
||||
ldcore->readpending = FALSE;
|
||||
|
||||
/* parse the metadata */
|
||||
if (ldcore->disc != NULL && ldcore->avconfig.video != NULL)
|
||||
vbi_parse_all((const UINT16 *)ldcore->avconfig.video->base, ldcore->avconfig.video->rowpixels, ldcore->avconfig.video->width, 8, &ldcore->metadata[fieldnum]);
|
||||
else
|
||||
fake_metadata(tracknum, fieldnum, &ldcore->metadata[fieldnum]);
|
||||
// printf("Track %5d: Metadata = %d %08X %08X %08X %08X\n", tracknum, ldcore->metadata[fieldnum].white, ldcore->metadata[fieldnum].line16, ldcore->metadata[fieldnum].line17, ldcore->metadata[fieldnum].line18, ldcore->metadata[fieldnum].line1718);
|
||||
|
||||
/* update the last seen frame and chapter */
|
||||
frame = frame_from_metadata(&ldcore->metadata[fieldnum]);
|
||||
if (frame >= 1 && frame < 99999)
|
||||
ldcore->last_frame = frame;
|
||||
chapter = chapter_from_metadata(&ldcore->metadata[fieldnum]);
|
||||
if (chapter != -1)
|
||||
ldcore->last_chapter = chapter;
|
||||
if (ldcore->readresult == CHDERR_OPERATION_PENDING)
|
||||
ldcore->readresult = chd_async_complete(ldcore->disc);
|
||||
|
||||
/* remove the video if we had an error */
|
||||
if (ldcore->readresult != CHDERR_NONE)
|
||||
ldcore->avconfig.video = NULL;
|
||||
|
||||
/* count the field as read if we are successful */
|
||||
if (ldcore->avconfig.video != NULL)
|
||||
ldcore->frame[ldcore->videoindex].numfields++;
|
||||
|
||||
/* render the display if present */
|
||||
// if (ldcore->display && ldcore->avconfig.video != NULL)
|
||||
// render_display((UINT16 *)ldcore->avconfig.video->base, ldcore->avconfig.video->rowpixels, ldcore->avconfig.video->width, ldcore->last_frame);
|
||||
|
||||
/* update video field */
|
||||
if (ldcore->avconfig.video != NULL)
|
||||
{
|
||||
ldcore->videofields[ldcore->videoindex]++;
|
||||
ldcore->videoframenum[ldcore->videoindex] = ldcore->last_frame;
|
||||
}
|
||||
|
||||
/* pass the audio to the callback */
|
||||
if (ldcore->config.audio != NULL)
|
||||
(*ldcore->config.audio)(device, ldcore->samplerate, ldcore->audiocursamples, ldcore->avconfig.audio[0], ldcore->avconfig.audio[1]);
|
||||
@ -999,29 +1022,6 @@ static void process_track_data(const device_config *device)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
fake_metadata - fake metadata when there's
|
||||
no disc present
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void fake_metadata(UINT32 track, UINT8 which, vbi_metadata *metadata)
|
||||
{
|
||||
if (which == 0)
|
||||
{
|
||||
metadata->white = 1;
|
||||
metadata->line16 = 0;
|
||||
metadata->line17 = metadata->line18 = 0xf80000 |
|
||||
(((track / 10000) % 10) << 16) |
|
||||
(((track / 1000) % 10) << 12) |
|
||||
(((track / 100) % 10) << 8) |
|
||||
(((track / 10) % 10) << 4) |
|
||||
(((track / 1) % 10) << 0);
|
||||
}
|
||||
else
|
||||
memset(metadata, 0, sizeof(*metadata));
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
render_display - draw the frame display
|
||||
-------------------------------------------------*/
|
||||
@ -1321,6 +1321,7 @@ VIDEO_UPDATE( laserdisc )
|
||||
const device_config *laserdisc = device_list_first(screen->machine->config->devicelist, LASERDISC);
|
||||
if (laserdisc != NULL)
|
||||
{
|
||||
const rectangle *visarea = video_screen_get_visible_area(screen);
|
||||
laserdisc_state *ld = laserdisc->token;
|
||||
ldcore_data *ldcore = ld->core;
|
||||
bitmap_t *overbitmap = ldcore->overbitmap[ldcore->overindex];
|
||||
@ -1335,12 +1336,14 @@ VIDEO_UPDATE( laserdisc )
|
||||
clip.min_x = 0;
|
||||
clip.max_x = ldcore->config.overwidth - 1;
|
||||
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);
|
||||
clip.max_y = (cliprect->max_y + 1) * overbitmap->height / bitmap->height - 1;
|
||||
(*ldcore->config.overupdate)(screen, overbitmap, &clip);
|
||||
}
|
||||
|
||||
/* if this is the last update, do the rendering */
|
||||
if (cliprect->max_y == video_screen_get_visible_area(screen)->max_y)
|
||||
if (cliprect->max_y == visarea->max_y)
|
||||
{
|
||||
float x0, y0, x1, y1;
|
||||
|
||||
@ -1443,8 +1446,10 @@ static void init_disc(const device_config *device)
|
||||
ldcore->maxtrack = VIRTUAL_LEAD_IN_TRACKS + MAX_TOTAL_TRACKS + VIRTUAL_LEAD_OUT_TRACKS;
|
||||
if (ldcore->disc != NULL)
|
||||
{
|
||||
UINT32 totalhunks = chd_get_header(ldcore->disc)->totalhunks;
|
||||
int fps, fpsfrac, interlaced, channels;
|
||||
char metadata[256];
|
||||
UINT32 vbilength;
|
||||
|
||||
/* require the A/V codec */
|
||||
if (chd_get_header(ldcore->disc)->compression != CHDCOMPRESSION_AV)
|
||||
@ -1466,7 +1471,13 @@ static void init_disc(const device_config *device)
|
||||
fatalerror("Laserdisc video must be interlaced!");
|
||||
|
||||
/* determine the maximum track and allocate a frame buffer */
|
||||
ldcore->chdtracks = chd_get_header(ldcore->disc)->totalhunks / 2;
|
||||
ldcore->chdtracks = totalhunks / 2;
|
||||
|
||||
/* allocate memory for the precomputed per-frame metadata */
|
||||
ldcore->vbidata = auto_malloc(totalhunks * VBI_PACKED_BYTES);
|
||||
err = chd_get_metadata(ldcore->disc, AV_LD_METADATA_TAG, 0, ldcore->vbidata, totalhunks * VBI_PACKED_BYTES, &vbilength, NULL);
|
||||
if (err != CHDERR_NONE || vbilength != totalhunks * VBI_PACKED_BYTES)
|
||||
fatalerror("Precomputed VBI metadata missing or incorrect size");
|
||||
}
|
||||
ldcore->maxtrack = MAX(ldcore->maxtrack, VIRTUAL_LEAD_IN_TRACKS + VIRTUAL_LEAD_OUT_TRACKS + ldcore->chdtracks);
|
||||
}
|
||||
@ -1487,18 +1498,20 @@ static void init_video(const device_config *device)
|
||||
video_screen_register_vblank_callback(ld->screen, vblank_state_changed, (void *)device);
|
||||
|
||||
/* allocate video frames */
|
||||
for (index = 0; index < ARRAY_LENGTH(ldcore->videofields); index++)
|
||||
for (index = 0; index < ARRAY_LENGTH(ldcore->frame); index++)
|
||||
{
|
||||
frame_data *frame = &ldcore->frame[index];
|
||||
|
||||
/* first allocate a YUY16 bitmap at 2x the height */
|
||||
ldcore->videoframe[index] = auto_bitmap_alloc(ldcore->width, ldcore->height * 2, BITMAP_FORMAT_YUY16);
|
||||
fillbitmap_yuy16(ldcore->videoframe[index], 40, 109, 240);
|
||||
frame->bitmap = auto_bitmap_alloc(ldcore->width, ldcore->height * 2, BITMAP_FORMAT_YUY16);
|
||||
fillbitmap_yuy16(frame->bitmap, 40, 109, 240);
|
||||
|
||||
/* make a copy of the bitmap that clips out the VBI and horizontal blanking areas */
|
||||
ldcore->videovisframe[index] = auto_malloc(sizeof(*ldcore->videovisframe[index]));
|
||||
*ldcore->videovisframe[index] = *ldcore->videoframe[index];
|
||||
ldcore->videovisframe[index]->base = BITMAP_ADDR16(ldcore->videovisframe[index], 44, ldcore->videoframe[index]->width * 8 / 720);
|
||||
ldcore->videovisframe[index]->height -= 44;
|
||||
ldcore->videovisframe[index]->width -= 2 * ldcore->videoframe[index]->width * 8 / 720;
|
||||
frame->visbitmap = auto_malloc(sizeof(*frame->visbitmap));
|
||||
*frame->visbitmap = *frame->bitmap;
|
||||
frame->visbitmap->base = BITMAP_ADDR16(frame->visbitmap, 44, frame->bitmap->width * 8 / 720);
|
||||
frame->visbitmap->height -= 44;
|
||||
frame->visbitmap->width -= 2 * frame->bitmap->width * 8 / 720;
|
||||
}
|
||||
|
||||
/* allocate an empty frame of the same size */
|
||||
@ -1674,10 +1687,6 @@ static DEVICE_RESET( laserdisc )
|
||||
ldcore->attospertrack = 0;
|
||||
ldcore->sliderupdate = curtime;
|
||||
|
||||
/* reset metadata */
|
||||
ldcore->last_frame = 0;
|
||||
ldcore->last_chapter = 0;
|
||||
|
||||
/* reset the I/O lines */
|
||||
for (line = 0; line < LASERDISC_INPUT_LINES; line++)
|
||||
ldcore->linein[line] = CLEAR_LINE;
|
||||
|
@ -134,8 +134,9 @@ struct _laserdisc_state
|
||||
|
||||
/* player-specific callbacks */
|
||||
typedef void (*laserdisc_init_func)(laserdisc_state *ld);
|
||||
typedef void (*laserdisc_vsync_func)(laserdisc_state *ld);
|
||||
typedef void (*laserdisc_vsync_func)(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
|
||||
typedef INT32 (*laserdisc_update_func)(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
|
||||
typedef void (*laserdisc_overlay_func)(laserdisc_state *ld, bitmap_t *bitmap);
|
||||
typedef void (*laserdisc_w_func)(laserdisc_state *ld, UINT8 prev, UINT8 new);
|
||||
typedef UINT8 (*laserdisc_r_func)(laserdisc_state *ld);
|
||||
|
||||
@ -151,7 +152,8 @@ struct _ldplayer_interface
|
||||
const machine_config_token *machine_config; /* pointer to machine configuration */
|
||||
laserdisc_init_func init; /* initialization callback */
|
||||
laserdisc_vsync_func vsync; /* vsync begin callback */
|
||||
laserdisc_update_func update; /* update callback (vblank end) */
|
||||
laserdisc_update_func update; /* update callback (line 16) */
|
||||
laserdisc_overlay_func overlay; /* overlay callback */
|
||||
laserdisc_w_func writedata; /* parallel data write */
|
||||
laserdisc_w_func writeline[LASERDISC_INPUT_LINES]; /* single line write */
|
||||
laserdisc_r_func readdata; /* parallel data read */
|
||||
@ -234,18 +236,13 @@ INLINE int is_start_of_frame(const vbi_metadata *vbi)
|
||||
|
||||
INLINE int frame_from_metadata(const vbi_metadata *metadata)
|
||||
{
|
||||
UINT32 data;
|
||||
|
||||
if ((metadata->line1718 & 0xf80000) == 0xf80000)
|
||||
data = metadata->line1718 & 0x7ffff;
|
||||
else if (metadata->line1718 == 0x88ffff)
|
||||
if ((metadata->line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
|
||||
return VBI_CAV_PICTURE(metadata->line1718);
|
||||
else if (metadata->line1718 == VBI_CODE_LEADIN)
|
||||
return FRAME_LEAD_IN;
|
||||
else if (metadata->line1718 == 0x80eeee)
|
||||
else if (metadata->line1718 == VBI_CODE_LEADOUT)
|
||||
return FRAME_LEAD_OUT;
|
||||
else
|
||||
return FRAME_NOT_PRESENT;
|
||||
|
||||
return (((data >> 16) & 0x0f) * 10000) + (((data >> 12) & 0x0f) * 1000) + (((data >> 8) & 0x0f) * 100) + (((data >> 4) & 0x0f) * 10) + (data & 0x0f);
|
||||
return FRAME_NOT_PRESENT;
|
||||
}
|
||||
|
||||
|
||||
@ -257,18 +254,13 @@ INLINE int frame_from_metadata(const vbi_metadata *metadata)
|
||||
|
||||
INLINE int chapter_from_metadata(const vbi_metadata *metadata)
|
||||
{
|
||||
UINT32 data;
|
||||
|
||||
if ((metadata->line1718 & 0xf00fff) == 0x800ddd)
|
||||
data = metadata->line1718 & 0x7f000;
|
||||
else if (metadata->line1718 == 0x88ffff)
|
||||
return VBI_CHAPTER(metadata->line1718);
|
||||
else if (metadata->line1718 == VBI_CODE_LEADIN)
|
||||
return CHAPTER_LEAD_IN;
|
||||
else if (metadata->line1718 == 0x80eeee)
|
||||
else if (metadata->line1718 == VBI_CODE_LEADOUT)
|
||||
return CHAPTER_LEAD_OUT;
|
||||
else
|
||||
return CHAPTER_NOT_PRESENT;
|
||||
|
||||
return (((data >> 16) & 0x0f) * 10) + ((data >> 12) & 0x0f);
|
||||
return CHAPTER_NOT_PRESENT;
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -631,7 +631,7 @@ static int open_rom_file(running_machine *machine, rom_load_data *romdata, const
|
||||
}
|
||||
|
||||
/* if the region is load by name, load the ROM from there */
|
||||
if (regiontag != NULL)
|
||||
if (romdata->file == NULL && regiontag != NULL)
|
||||
{
|
||||
astring *fname = astring_assemble_3(astring_alloc(), regiontag, PATH_SEPARATOR, ROM_GETNAME(romp));
|
||||
if (has_crc)
|
||||
|
@ -29,12 +29,18 @@ enum
|
||||
{
|
||||
CMD_SCAN_REVERSE,
|
||||
CMD_STEP_REVERSE,
|
||||
CMD_SLOW_REVERSE,
|
||||
CMD_FAST_REVERSE,
|
||||
CMD_SCAN_FORWARD,
|
||||
CMD_STEP_FORWARD,
|
||||
CMD_SLOW_FORWARD,
|
||||
CMD_FAST_FORWARD,
|
||||
CMD_PLAY,
|
||||
CMD_PAUSE,
|
||||
CMD_DISPLAY_ON,
|
||||
CMD_DISPLAY_OFF,
|
||||
CMD_FRAME_TOGGLE,
|
||||
CMD_CHAPTER_TOGGLE,
|
||||
CMD_CH1_TOGGLE,
|
||||
CMD_CH2_TOGGLE,
|
||||
CMD_0,
|
||||
CMD_1,
|
||||
CMD_2,
|
||||
@ -60,7 +66,6 @@ static astring *filename;
|
||||
|
||||
static input_port_value last_controls;
|
||||
static UINT8 playing;
|
||||
static UINT8 displaying;
|
||||
|
||||
static emu_timer *pr8210_bit_timer;
|
||||
static UINT32 pr8210_command_buffer_in, pr8210_command_buffer_out;
|
||||
@ -81,51 +86,68 @@ static void process_commands(const device_config *laserdisc)
|
||||
input_port_value controls = input_port_read(laserdisc->machine, "controls");
|
||||
int number;
|
||||
|
||||
/* scan/step backwards */
|
||||
if (playing)
|
||||
{
|
||||
if (controls & 0x01)
|
||||
(*execute_command)(laserdisc, CMD_SCAN_REVERSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(last_controls & 0x01) && (controls & 0x01))
|
||||
(*execute_command)(laserdisc, CMD_STEP_REVERSE);
|
||||
}
|
||||
/* step backwards */
|
||||
if (!(last_controls & 0x01) && (controls & 0x01))
|
||||
(*execute_command)(laserdisc, CMD_STEP_REVERSE);
|
||||
|
||||
/* scan/step forwards */
|
||||
if (playing)
|
||||
{
|
||||
if (controls & 0x02)
|
||||
(*execute_command)(laserdisc, CMD_SCAN_FORWARD);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(last_controls & 0x02) && (controls & 0x02))
|
||||
(*execute_command)(laserdisc, CMD_STEP_FORWARD);
|
||||
}
|
||||
/* step forwards */
|
||||
if (!(last_controls & 0x02) && (controls & 0x02))
|
||||
(*execute_command)(laserdisc, CMD_STEP_FORWARD);
|
||||
|
||||
/* scan backwards */
|
||||
if (controls & 0x04)
|
||||
(*execute_command)(laserdisc, CMD_SCAN_REVERSE);
|
||||
|
||||
/* scan forwards */
|
||||
if (controls & 0x08)
|
||||
(*execute_command)(laserdisc, CMD_SCAN_FORWARD);
|
||||
|
||||
/* slow backwards */
|
||||
if (!(last_controls & 0x10) && (controls & 0x10))
|
||||
(*execute_command)(laserdisc, CMD_SLOW_REVERSE);
|
||||
|
||||
/* slow forwards */
|
||||
if (!(last_controls & 0x20) && (controls & 0x20))
|
||||
(*execute_command)(laserdisc, CMD_SLOW_FORWARD);
|
||||
|
||||
/* fast backwards */
|
||||
if (controls & 0x40)
|
||||
(*execute_command)(laserdisc, CMD_FAST_REVERSE);
|
||||
|
||||
/* fast forwards */
|
||||
if (controls & 0x80)
|
||||
(*execute_command)(laserdisc, CMD_FAST_FORWARD);
|
||||
|
||||
/* play/pause */
|
||||
if (!(last_controls & 0x10) && (controls & 0x10))
|
||||
if (!(last_controls & 0x100) && (controls & 0x100))
|
||||
{
|
||||
playing = !playing;
|
||||
(*execute_command)(laserdisc, playing ? CMD_PLAY : CMD_PAUSE);
|
||||
}
|
||||
|
||||
/* toggle display */
|
||||
if (!(last_controls & 0x20) && (controls & 0x20))
|
||||
{
|
||||
displaying = !displaying;
|
||||
(*execute_command)(laserdisc, displaying ? CMD_DISPLAY_ON : CMD_DISPLAY_OFF);
|
||||
}
|
||||
/* toggle frame display */
|
||||
if (!(last_controls & 0x200) && (controls & 0x200))
|
||||
(*execute_command)(laserdisc, CMD_FRAME_TOGGLE);
|
||||
|
||||
/* toggle chapter display */
|
||||
if (!(last_controls & 0x400) && (controls & 0x400))
|
||||
(*execute_command)(laserdisc, CMD_CHAPTER_TOGGLE);
|
||||
|
||||
/* toggle left channel */
|
||||
if (!(last_controls & 0x800) && (controls & 0x800))
|
||||
(*execute_command)(laserdisc, CMD_CH1_TOGGLE);
|
||||
|
||||
/* toggle right channel */
|
||||
if (!(last_controls & 0x1000) && (controls & 0x1000))
|
||||
(*execute_command)(laserdisc, CMD_CH2_TOGGLE);
|
||||
|
||||
/* numbers */
|
||||
for (number = 0; number < 10; number++)
|
||||
if (!(last_controls & (0x100 << number)) && (controls & (0x100 << number)))
|
||||
if (!(last_controls & (0x10000 << number)) && (controls & (0x10000 << number)))
|
||||
(*execute_command)(laserdisc, CMD_0 + number);
|
||||
|
||||
/* enter */
|
||||
if (!(last_controls & 0x40000) && (controls & 0x40000))
|
||||
if (!(last_controls & 0x4000000) && (controls & 0x4000000))
|
||||
(*execute_command)(laserdisc, CMD_SEARCH);
|
||||
|
||||
last_controls = controls;
|
||||
@ -162,7 +184,6 @@ static TIMER_CALLBACK( autoplay )
|
||||
/* start playing */
|
||||
(*execute_command)(laserdisc, CMD_PLAY);
|
||||
playing = TRUE;
|
||||
displaying = FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -185,7 +206,6 @@ static MACHINE_RESET( ldplayer )
|
||||
|
||||
INLINE void pr8210_add_command(UINT8 command)
|
||||
{
|
||||
pr8210_command_buffer[pr8210_command_buffer_in++ % ARRAY_LENGTH(pr8210_command_buffer)] = (command & 0x1f) | 0x20;
|
||||
pr8210_command_buffer[pr8210_command_buffer_in++ % ARRAY_LENGTH(pr8210_command_buffer)] = (command & 0x1f) | 0x20;
|
||||
pr8210_command_buffer[pr8210_command_buffer_in++ % ARRAY_LENGTH(pr8210_command_buffer)] = 0x00 | 0x20;
|
||||
}
|
||||
@ -252,7 +272,8 @@ static void pr8210_execute(const device_config *laserdisc, int command)
|
||||
switch (command)
|
||||
{
|
||||
case CMD_SCAN_REVERSE:
|
||||
if (pr8210_command_buffer_in == pr8210_command_buffer_out)
|
||||
if (pr8210_command_buffer_in == pr8210_command_buffer_out ||
|
||||
pr8210_command_buffer_in == (pr8210_command_buffer_out + 1) % ARRAY_LENGTH(pr8210_command_buffer))
|
||||
{
|
||||
pr8210_add_command(0x1c);
|
||||
playing = TRUE;
|
||||
@ -264,8 +285,23 @@ static void pr8210_execute(const device_config *laserdisc, int command)
|
||||
playing = FALSE;
|
||||
break;
|
||||
|
||||
case CMD_SLOW_REVERSE:
|
||||
pr8210_add_command(0x02);
|
||||
playing = TRUE;
|
||||
break;
|
||||
|
||||
case CMD_FAST_REVERSE:
|
||||
if (pr8210_command_buffer_in == pr8210_command_buffer_out ||
|
||||
pr8210_command_buffer_in == (pr8210_command_buffer_out + 1) % ARRAY_LENGTH(pr8210_command_buffer))
|
||||
{
|
||||
pr8210_add_command(0x0c);
|
||||
playing = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_SCAN_FORWARD:
|
||||
if (pr8210_command_buffer_in == pr8210_command_buffer_out)
|
||||
if (pr8210_command_buffer_in == pr8210_command_buffer_out ||
|
||||
pr8210_command_buffer_in == (pr8210_command_buffer_out + 1) % ARRAY_LENGTH(pr8210_command_buffer))
|
||||
{
|
||||
pr8210_add_command(0x08);
|
||||
playing = TRUE;
|
||||
@ -277,6 +313,20 @@ static void pr8210_execute(const device_config *laserdisc, int command)
|
||||
playing = FALSE;
|
||||
break;
|
||||
|
||||
case CMD_SLOW_FORWARD:
|
||||
pr8210_add_command(0x18);
|
||||
playing = TRUE;
|
||||
break;
|
||||
|
||||
case CMD_FAST_FORWARD:
|
||||
if (pr8210_command_buffer_in == pr8210_command_buffer_out ||
|
||||
pr8210_command_buffer_in == (pr8210_command_buffer_out + 1) % ARRAY_LENGTH(pr8210_command_buffer))
|
||||
{
|
||||
pr8210_add_command(0x10);
|
||||
playing = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_PLAY:
|
||||
pr8210_add_command(0x14);
|
||||
playing = TRUE;
|
||||
@ -287,11 +337,22 @@ static void pr8210_execute(const device_config *laserdisc, int command)
|
||||
playing = FALSE;
|
||||
break;
|
||||
|
||||
case CMD_DISPLAY_ON:
|
||||
case CMD_DISPLAY_OFF:
|
||||
case CMD_FRAME_TOGGLE:
|
||||
pr8210_add_command(0x0b);
|
||||
break;
|
||||
|
||||
case CMD_CHAPTER_TOGGLE:
|
||||
pr8210_add_command(0x06);
|
||||
break;
|
||||
|
||||
case CMD_CH1_TOGGLE:
|
||||
pr8210_add_command(0x0e);
|
||||
break;
|
||||
|
||||
case CMD_CH2_TOGGLE:
|
||||
pr8210_add_command(0x16);
|
||||
break;
|
||||
|
||||
case CMD_0:
|
||||
case CMD_1:
|
||||
case CMD_2:
|
||||
@ -355,13 +416,7 @@ static void ldv1000_execute(const device_config *laserdisc, int command)
|
||||
playing = FALSE;
|
||||
break;
|
||||
|
||||
case CMD_DISPLAY_ON:
|
||||
laserdisc_data_w(laserdisc, digits[1]);
|
||||
laserdisc_data_w(laserdisc, 0xf1);
|
||||
break;
|
||||
|
||||
case CMD_DISPLAY_OFF:
|
||||
laserdisc_data_w(laserdisc, digits[0]);
|
||||
case CMD_FRAME_TOGGLE:
|
||||
laserdisc_data_w(laserdisc, 0xf1);
|
||||
break;
|
||||
|
||||
@ -395,23 +450,30 @@ static void ldv1000_execute(const device_config *laserdisc, int command)
|
||||
|
||||
static INPUT_PORTS_START( ldplayer )
|
||||
PORT_START("controls")
|
||||
PORT_BIT( 0x00001, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )
|
||||
PORT_BIT( 0x00002, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT )
|
||||
PORT_BIT( 0x00004, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )
|
||||
PORT_BIT( 0x00008, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )
|
||||
PORT_BIT( 0x00010, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CODE(KEYCODE_SPACE)
|
||||
PORT_BIT( 0x00020, IP_ACTIVE_HIGH, IPT_BUTTON2 )
|
||||
PORT_BIT( 0x00100, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(KEYCODE_0)
|
||||
PORT_BIT( 0x00200, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_1_PAD) PORT_CODE(KEYCODE_1)
|
||||
PORT_BIT( 0x00400, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_2)
|
||||
PORT_BIT( 0x00800, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_3_PAD) PORT_CODE(KEYCODE_3)
|
||||
PORT_BIT( 0x01000, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_4)
|
||||
PORT_BIT( 0x02000, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_5_PAD) PORT_CODE(KEYCODE_5)
|
||||
PORT_BIT( 0x04000, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_6)
|
||||
PORT_BIT( 0x08000, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_7_PAD) PORT_CODE(KEYCODE_7)
|
||||
PORT_BIT( 0x10000, IP_ACTIVE_HIGH, IPT_BUTTON9 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_8)
|
||||
PORT_BIT( 0x20000, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_9_PAD) PORT_CODE(KEYCODE_9)
|
||||
PORT_BIT( 0x40000, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_PLAYER(2) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CODE(KEYCODE_ENTER)
|
||||
PORT_BIT( 0x0000001, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Step reverse") PORT_CODE(KEYCODE_LEFT)
|
||||
PORT_BIT( 0x0000002, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Step forward") PORT_CODE(KEYCODE_RIGHT)
|
||||
PORT_BIT( 0x0000004, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Scan reverse") PORT_CODE(KEYCODE_UP)
|
||||
PORT_BIT( 0x0000008, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Scan forward") PORT_CODE(KEYCODE_DOWN)
|
||||
PORT_BIT( 0x0000010, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Slow reverse") PORT_CODE(KEYCODE_OPENBRACE)
|
||||
PORT_BIT( 0x0000020, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Slow forward") PORT_CODE(KEYCODE_CLOSEBRACE)
|
||||
PORT_BIT( 0x0000040, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Fast reverse") PORT_CODE(KEYCODE_COMMA)
|
||||
PORT_BIT( 0x0000080, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Fast forward") PORT_CODE(KEYCODE_STOP)
|
||||
PORT_BIT( 0x0000100, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Play/Pause") PORT_CODE(KEYCODE_SPACE)
|
||||
PORT_BIT( 0x0000200, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Toggle frame display") PORT_CODE(KEYCODE_F)
|
||||
PORT_BIT( 0x0000400, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Toggle chapter display") PORT_CODE(KEYCODE_C)
|
||||
PORT_BIT( 0x0000800, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Toggle left channel") PORT_CODE(KEYCODE_L)
|
||||
PORT_BIT( 0x0001000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Toggle right channel") PORT_CODE(KEYCODE_R)
|
||||
PORT_BIT( 0x0010000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("0") PORT_PLAYER(2) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(KEYCODE_0)
|
||||
PORT_BIT( 0x0020000, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("1") PORT_PLAYER(2) PORT_CODE(KEYCODE_1_PAD) PORT_CODE(KEYCODE_1)
|
||||
PORT_BIT( 0x0040000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("2") PORT_PLAYER(2) PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_2)
|
||||
PORT_BIT( 0x0080000, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("3") PORT_PLAYER(2) PORT_CODE(KEYCODE_3_PAD) PORT_CODE(KEYCODE_3)
|
||||
PORT_BIT( 0x0100000, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("4") PORT_PLAYER(2) PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_4)
|
||||
PORT_BIT( 0x0200000, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("5") PORT_PLAYER(2) PORT_CODE(KEYCODE_5_PAD) PORT_CODE(KEYCODE_5)
|
||||
PORT_BIT( 0x0400000, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("6") PORT_PLAYER(2) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_6)
|
||||
PORT_BIT( 0x0800000, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_NAME("7") PORT_PLAYER(2) PORT_CODE(KEYCODE_7_PAD) PORT_CODE(KEYCODE_7)
|
||||
PORT_BIT( 0x1000000, IP_ACTIVE_HIGH, IPT_BUTTON9 ) PORT_NAME("8") PORT_PLAYER(2) PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_8)
|
||||
PORT_BIT( 0x2000000, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("9") PORT_PLAYER(2) PORT_CODE(KEYCODE_9_PAD) PORT_CODE(KEYCODE_9)
|
||||
PORT_BIT( 0x4000000, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Enter") PORT_PLAYER(2) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CODE(KEYCODE_ENTER)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
|
@ -130,6 +130,9 @@
|
||||
#define AV_METADATA_TAG 0x41564156 /* 'AVAV' */
|
||||
#define AV_METADATA_FORMAT "FPS:%d.%06d WIDTH:%d HEIGHT:%d INTERLACED:%d CHANNELS:%d SAMPLERATE:%d"
|
||||
|
||||
/* A/V laserdisc frame metadata */
|
||||
#define AV_LD_METADATA_TAG 0x41564C44 /* 'AVLD' */
|
||||
|
||||
/* CHD open values */
|
||||
#define CHD_OPEN_READ 1
|
||||
#define CHD_OPEN_READWRITE 2
|
||||
|
@ -318,7 +318,7 @@ void vbi_parse_all(const UINT16 *source, int sourcerowpixels, int sourcewidth, i
|
||||
else
|
||||
{
|
||||
/* if both are frame numbers, and one is not valid BCD, pick the other */
|
||||
if ((vbi->line17 & 0xf80000) == 0xf80000 && (vbi->line18 & 0xf80000) == 0xf80000)
|
||||
if ((vbi->line17 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE && (vbi->line18 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
|
||||
{
|
||||
if ((vbi->line17 & 0xf000) > 0x9000 || (vbi->line17 & 0xf00) > 0x900 || (vbi->line17 & 0xf0) > 0x90 || (vbi->line17 & 0xf) > 0x9)
|
||||
vbi->line1718 = vbi->line18;
|
||||
@ -332,3 +332,46 @@ void vbi_parse_all(const UINT16 *source, int sourcerowpixels, int sourcewidth, i
|
||||
vbi->line1718 = (vbi->line1718 << 1) | ((bits[0][bitnum] > bits[1][bitnum]) ? (bits[0][bitnum] & 1) : (bits[1][bitnum] & 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
vbi_metadata_pack - pack the VBI data down
|
||||
into a smaller form for storage
|
||||
-------------------------------------------------*/
|
||||
|
||||
void vbi_metadata_pack(UINT8 *dest, UINT32 framenum, const vbi_metadata *vbi)
|
||||
{
|
||||
dest[0] = framenum >> 16;
|
||||
dest[1] = framenum >> 8;
|
||||
dest[2] = framenum >> 0;
|
||||
dest[3] = vbi->white;
|
||||
dest[4] = vbi->line16 >> 16;
|
||||
dest[5] = vbi->line16 >> 8;
|
||||
dest[6] = vbi->line16 >> 0;
|
||||
dest[7] = vbi->line17 >> 16;
|
||||
dest[8] = vbi->line17 >> 8;
|
||||
dest[9] = vbi->line17 >> 0;
|
||||
dest[10] = vbi->line18 >> 16;
|
||||
dest[11] = vbi->line18 >> 8;
|
||||
dest[12] = vbi->line18 >> 0;
|
||||
dest[13] = vbi->line1718 >> 16;
|
||||
dest[14] = vbi->line1718 >> 8;
|
||||
dest[15] = vbi->line1718 >> 0;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
vbi_metadata_unpack - unpack the VBI data
|
||||
from a smaller form into the full structure
|
||||
-------------------------------------------------*/
|
||||
|
||||
void vbi_metadata_unpack(vbi_metadata *vbi, UINT32 *framenum, const UINT8 *source)
|
||||
{
|
||||
*framenum = (source[0] << 16) | (source[1] << 8) | source[2];
|
||||
vbi->white = source[3];
|
||||
vbi->line16 = (source[4] << 16) | (source[5] << 8) | source[6];
|
||||
vbi->line17 = (source[7] << 16) | (source[8] << 8) | source[9];
|
||||
vbi->line18 = (source[10] << 16) | (source[11] << 8) | source[12];
|
||||
vbi->line1718 = (source[13] << 16) | (source[14] << 8) | source[15];
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,46 @@
|
||||
#define __VBIPARSE_H__
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
/* size of packed VBI data */
|
||||
#define VBI_PACKED_BYTES 16
|
||||
|
||||
/* these codes are full 24-bit codes with no parameter data */
|
||||
#define VBI_CODE_LEADIN 0x88ffff
|
||||
#define VBI_CODE_LEADOUT 0x80eeee
|
||||
#define VBI_CODE_STOP 0x82cfff
|
||||
#define VBI_CODE_CLV 0x87ffff
|
||||
|
||||
/* these codes require a mask because some bits are parameters */
|
||||
#define VBI_MASK_CAV_PICTURE 0xf00000
|
||||
#define VBI_CODE_CAV_PICTURE 0xf00000
|
||||
#define VBI_MASK_CHAPTER 0xf00fff
|
||||
#define VBI_CODE_CHAPTER 0x800ddd
|
||||
#define VBI_MASK_CLV_TIME 0xf0ff00
|
||||
#define VBI_CODE_CLV_TIME 0xf0dd00
|
||||
#define VBI_MASK_STATUS_CX_ON 0xfff000
|
||||
#define VBI_CODE_STATUS_CX_ON 0x8dc000
|
||||
#define VBI_MASK_STATUS_CX_OFF 0xfff000
|
||||
#define VBI_CODE_STATUS_CX_OFF 0x8bc000
|
||||
#define VBI_MASK_USER 0xf0f000
|
||||
#define VBI_CODE_USER 0x80d000
|
||||
#define VBI_MASK_CLV_PICTURE 0xf0f000
|
||||
#define VBI_CODE_CLV_PICTURE 0x80e000
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
|
||||
#define VBI_CAV_PICTURE(x) (((((x) >> 16) & 0x07) * 10000) + ((((x) >> 12) & 0x0f) * 1000) + ((((x) >> 8) & 0x0f) * 100) + ((((x) >> 4) & 0x0f) * 10) + ((((x) >> 0) & 0x0f) * 1))
|
||||
#define VBI_CHAPTER(x) (((((x) >> 16) & 0x07) * 10) + ((((x) >> 12) & 0x0f) * 1))
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
@ -44,5 +84,11 @@ int vbi_parse_white_flag(const UINT16 *source, int sourcewidth, int sourceshift)
|
||||
/* parse everything from a video frame */
|
||||
void vbi_parse_all(const UINT16 *source, int sourcerowpixels, int sourcewidth, int sourceshift, vbi_metadata *vbi);
|
||||
|
||||
/* pack the VBI data down into a smaller form for storage */
|
||||
void vbi_metadata_pack(UINT8 *dest, UINT32 framenum, const vbi_metadata *vbi);
|
||||
|
||||
/* unpack the VBI data from a smaller form into the full structure */
|
||||
void vbi_metadata_unpack(vbi_metadata *vbi, UINT32 *framenum, const UINT8 *source);
|
||||
|
||||
|
||||
#endif /* __VBIPARSE_H__ */
|
||||
|
@ -5,7 +5,6 @@
|
||||
driver by Phil Bennett
|
||||
|
||||
TODO:
|
||||
* Emulate D8478 laserdisc interface MCU
|
||||
* Accurate video timings
|
||||
- Derive from PROMs
|
||||
* More accurate line fill circuitry emulation
|
||||
@ -61,7 +60,6 @@ static UINT8 io_latch;
|
||||
static UINT8 reset_latch;
|
||||
|
||||
static int disk_on;
|
||||
static int ldp_command_flag;
|
||||
static const device_config *laserdisc;
|
||||
|
||||
/*************************************
|
||||
@ -222,22 +220,16 @@ static INTERRUPT_GEN( vblank )
|
||||
|
||||
static WRITE16_HANDLER( laserdisc_w )
|
||||
{
|
||||
ldp_command_flag = 1;
|
||||
laserdisc_data_w(laserdisc, data & 0xff);
|
||||
}
|
||||
|
||||
/* Called by the player emulation to acknowledge the 68000 command */
|
||||
void ldp_ack_callback(void)
|
||||
{
|
||||
ldp_command_flag = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
D0: Command acknowledge
|
||||
D1: Seek status (0 = searching, 1 = ready)
|
||||
*/
|
||||
static READ16_HANDLER( laserdisc_r )
|
||||
{
|
||||
int ldp_command_flag = (laserdisc_line_r(laserdisc, LASERDISC_LINE_READY) == ASSERT_LINE) ? 0 : 1;
|
||||
int ldp_seek_status = (laserdisc_line_r(laserdisc, LASERDISC_LINE_STATUS) == ASSERT_LINE) ? 1 : 0;
|
||||
|
||||
return (ldp_seek_status << 1) | ldp_command_flag;
|
||||
@ -444,16 +436,12 @@ ADDRESS_MAP_END
|
||||
static MACHINE_START( cubeqst )
|
||||
{
|
||||
laserdisc = device_list_find_by_tag(machine->config->devicelist, LASERDISC, "laserdisc");
|
||||
simutrek_set_cmd_ack_callback(laserdisc, ldp_ack_callback);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( cubeqst )
|
||||
{
|
||||
reset_latch = 0;
|
||||
|
||||
/* Do this until we sort out the laserdisc interface properly */
|
||||
ldp_command_flag = 0;
|
||||
|
||||
/* Auxillary CPUs are held in reset */
|
||||
cpunum_set_input_line(machine, SOUND_CPU, INPUT_LINE_RESET, ASSERT_LINE);
|
||||
cpunum_set_input_line(machine, ROTATE_CPU, INPUT_LINE_RESET, ASSERT_LINE);
|
||||
@ -558,12 +546,6 @@ static MACHINE_DRIVER_START( cubeqst )
|
||||
MDRV_CPU_PROGRAM_MAP(line_sound_map, 0)
|
||||
MDRV_CPU_CONFIG(snd_config)
|
||||
|
||||
#if 0
|
||||
MDRV_CPU_ADD("ldp_cpu", I8048, XTAL_10MHz / 2)
|
||||
MDRV_CPU_PROGRAM_MAP(ldp_mem, 0)
|
||||
MDRV_CPU_IO_MAP(ldp_io, 0)
|
||||
#endif
|
||||
|
||||
MDRV_INTERLEAVE(700)
|
||||
|
||||
MDRV_MACHINE_START(cubeqst)
|
||||
@ -580,6 +562,7 @@ static MACHINE_DRIVER_START( cubeqst )
|
||||
MDRV_LASERDISC_OVERLAY(cubeqst, CUBEQST_HBLANK, CUBEQST_VCOUNT, BITMAP_FORMAT_INDEXED16)
|
||||
MDRV_LASERDISC_OVERLAY_CLIP(0, 320-1, 0, 256-8)
|
||||
MDRV_LASERDISC_OVERLAY_POSITION(0.002, -0.018)
|
||||
MDRV_LASERDISC_OVERLAY_SCALE(1.0, 1.030)
|
||||
|
||||
MDRV_SPEAKER_STANDARD_STEREO("left", "right")
|
||||
|
||||
@ -658,9 +641,6 @@ ROM_START( cubeqst )
|
||||
ROMX_LOAD( "mother_sounds_82s129.9e", 0x4, 0x100, CRC(598687e7) SHA1(c5045ddaab7123ff0a4c8f4c2489f9d70b63fc76), ROM_NIBBLE | ROM_SHIFT_NIBBLE_HI | ROM_SKIP(7))
|
||||
ROMX_LOAD( "mother_sounds_82s129.8e", 0x4, 0x100, CRC(68de17ed) SHA1(efefcb4ccdd012b767c4765304c6022b0c091066), ROM_NIBBLE | ROM_SHIFT_NIBBLE_LO | ROM_SKIP(7))
|
||||
|
||||
ROM_REGION( 0x10000, "ldp_cpu", 0)
|
||||
ROM_LOAD( "laser_player_interface_d8748_a308.bin", 0x0000, 0x0400, CRC(eed3e728) SHA1(1eb3467f1c41553375b2c21952cd593b167f5416) )
|
||||
|
||||
ROM_REGION16_BE( 0x1000, "soundproms", 0)
|
||||
ROMX_LOAD( "mother_sounds_82s185.17f", 0x0, 0x800, CRC(0f49d40e) SHA1(40340833ab27ccb5b60baf44ad01930f204f5318), ROM_NIBBLE | ROM_SHIFT_NIBBLE_LO | ROM_SKIP(1) )
|
||||
ROMX_LOAD( "mother_sounds_82s185.19f", 0x0, 0x800, CRC(a041ce92) SHA1(9bc92992de22b830e479933c50650c7dc23f5713), ROM_NIBBLE | ROM_SHIFT_NIBBLE_HI | ROM_SKIP(1) )
|
||||
|
@ -680,7 +680,7 @@ static INTERRUPT_GEN( gottlieb_interrupt )
|
||||
bitmap_t *dummy;
|
||||
|
||||
/* set the "disc ready" bit, which basically indicates whether or not we have a proper video frame */
|
||||
if (laserdisc_get_video(laserdisc, &dummy) == 0)
|
||||
if (!laserdisc_get_video(laserdisc, &dummy))
|
||||
laserdisc_status &= ~0x20;
|
||||
else
|
||||
laserdisc_status |= 0x20;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "bitmap.h"
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include "vbiparse.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
@ -84,7 +85,8 @@ static clock_t lastprogress = 0;
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
print_big_int - 64-bit int printing with commas
|
||||
print_big_int - 64-bit int printing with
|
||||
commas
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void print_big_int(UINT64 intvalue, char *output)
|
||||
@ -105,7 +107,8 @@ static void print_big_int(UINT64 intvalue, char *output)
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
big_int_string - return a string for a big int
|
||||
big_int_string - return a string for a big
|
||||
integer
|
||||
-------------------------------------------------*/
|
||||
|
||||
static char *big_int_string(UINT64 intvalue)
|
||||
@ -162,6 +165,7 @@ static int usage(void)
|
||||
printf(" or: chdman -merge parent.chd diff.chd output.chd\n");
|
||||
printf(" or: chdman -diff parent.chd compare.chd diff.chd\n");
|
||||
printf(" or: chdman -setchs inout.chd cylinders heads sectors\n");
|
||||
printf(" or: chdman -fixavdata inout.chd\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -755,6 +759,7 @@ static int do_createav(int argc, char *argv[], int param)
|
||||
const char *inputfile, *outputfile;
|
||||
bitmap_t *fullbitmap = NULL;
|
||||
const avi_movie_info *info;
|
||||
UINT8 *ldframedata = NULL;
|
||||
const chd_header *header;
|
||||
chd_file *chd = NULL;
|
||||
avi_file *avi = NULL;
|
||||
@ -837,6 +842,19 @@ static int do_createav(int argc, char *argv[], int param)
|
||||
firstframe *= 2;
|
||||
numframes *= 2;
|
||||
}
|
||||
|
||||
/* allocate space for the frame data */
|
||||
if (height == 524/2 || height == 624/2)
|
||||
{
|
||||
ldframedata = malloc(numframes * VBI_PACKED_BYTES);
|
||||
if (ldframedata == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory allocating frame metadata\n");
|
||||
err = CHDERR_OUT_OF_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(ldframedata, 0, numframes * VBI_PACKED_BYTES);
|
||||
}
|
||||
|
||||
/* determine the number of bytes per frame */
|
||||
max_samples_per_frame = ((UINT64)rate * 1000000 + fps_times_1million - 1) / fps_times_1million;
|
||||
@ -919,6 +937,15 @@ static int do_createav(int argc, char *argv[], int param)
|
||||
fprintf(stderr, "Error reading frame %d from AVI file: %s\n", effframe, avi_error_string(avierr));
|
||||
err = CHDERR_COMPRESSION_ERROR;
|
||||
}
|
||||
|
||||
/* update metadata for this frame */
|
||||
if (ldframedata != NULL)
|
||||
{
|
||||
/* parse the data and pack it */
|
||||
vbi_metadata vbi;
|
||||
vbi_parse_all((const UINT16 *)avconfig.video->base, avconfig.video->rowpixels, avconfig.video->width, 8, &vbi);
|
||||
vbi_metadata_pack(&ldframedata[framenum * VBI_PACKED_BYTES], framenum, &vbi);
|
||||
}
|
||||
|
||||
/* configure the compressor for this frame */
|
||||
chd_codec_config(chd, AV_CODEC_COMPRESS_CONFIG, &avconfig);
|
||||
@ -929,6 +956,17 @@ static int do_createav(int argc, char *argv[], int param)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* write the final metadata */
|
||||
if (ldframedata != NULL)
|
||||
{
|
||||
err = chd_set_metadata(chd, AV_LD_METADATA_TAG, 0, ldframedata, numframes * VBI_PACKED_BYTES);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
fprintf(stderr, "Error adding AVLD metadata: %s\n", chd_error_string(err));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* finish compression */
|
||||
err = chd_compress_finish(chd);
|
||||
if (err != CHDERR_NONE)
|
||||
@ -947,6 +985,8 @@ cleanup:
|
||||
free(avconfig.audio[chnum]);
|
||||
if (fullbitmap != NULL)
|
||||
bitmap_free(fullbitmap);
|
||||
if (ldframedata != NULL)
|
||||
free(ldframedata);
|
||||
if (err != CHDERR_NONE)
|
||||
osd_rmfile(outputfile);
|
||||
return (err != CHDERR_NONE);
|
||||
@ -1466,7 +1506,7 @@ static int do_extractav(int argc, char *argv[], int param)
|
||||
numframes = MIN(totalframes - firstframe, numframes);
|
||||
|
||||
/* allocate a video buffer */
|
||||
fullbitmap = bitmap_alloc(width, height * (interlaced ? 2 : 1), BITMAP_FORMAT_YUY16);
|
||||
fullbitmap = bitmap_alloc(width, height, BITMAP_FORMAT_YUY16);
|
||||
if (fullbitmap == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory allocating temporary bitmap\n");
|
||||
@ -1723,6 +1763,236 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
do_fixavdata - fix the AV metadata for an
|
||||
A/V file
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int do_fixavdata(int argc, char *argv[], int param)
|
||||
{
|
||||
int fps, fpsfrac, width, height, interlaced, channels, rate;
|
||||
av_codec_decompress_config avconfig = { 0 };
|
||||
bitmap_t *fullbitmap = NULL;
|
||||
const char *inputfile;
|
||||
UINT8 *vbidata = NULL;
|
||||
int writeable = FALSE;
|
||||
chd_file *chd = NULL;
|
||||
bitmap_t fakebitmap;
|
||||
char metadata[256];
|
||||
chd_header header;
|
||||
UINT32 actlength;
|
||||
UINT32 framenum;
|
||||
chd_error err;
|
||||
int fixframes = 0;
|
||||
int fixes = 0;
|
||||
|
||||
/* require 3 args total */
|
||||
if (argc != 3)
|
||||
return usage();
|
||||
|
||||
/* extract the data */
|
||||
inputfile = argv[2];
|
||||
|
||||
/* print some info */
|
||||
printf("Input file: %s\n", inputfile);
|
||||
|
||||
/* get the header */
|
||||
err = chd_open(inputfile, CHD_OPEN_READ, NULL, &chd);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, chd_error_string(err));
|
||||
goto cleanup;
|
||||
}
|
||||
header = *chd_get_header(chd);
|
||||
|
||||
/* get the metadata */
|
||||
err = chd_get_metadata(chd, AV_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
fprintf(stderr, "Error getting A/V metadata: %s\n", chd_error_string(err));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* extract the info */
|
||||
if (sscanf(metadata, AV_METADATA_FORMAT, &fps, &fpsfrac, &width, &height, &interlaced, &channels, &rate) != 7)
|
||||
{
|
||||
fprintf(stderr, "Improperly formatted metadata\n");
|
||||
err = CHDERR_INVALID_METADATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* allocate space for the frame data */
|
||||
if ((height != 524/2 && height != 624/2) || !interlaced)
|
||||
{
|
||||
fprintf(stderr, "This file does not need VBI metadata\n");
|
||||
err = CHDERR_INVALID_METADATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* allocate a video buffer */
|
||||
fullbitmap = bitmap_alloc(width, height, BITMAP_FORMAT_YUY16);
|
||||
if (fullbitmap == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory allocating temporary bitmap\n");
|
||||
err = CHDERR_OUT_OF_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
avconfig.video = &fakebitmap;
|
||||
|
||||
/* allocate memory for VBI data */
|
||||
vbidata = malloc(header.totalhunks * VBI_PACKED_BYTES);
|
||||
if (vbidata == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory allocating VBI data\n");
|
||||
err = CHDERR_OUT_OF_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* read the metadata */
|
||||
err = chd_get_metadata(chd, AV_LD_METADATA_TAG, 0, vbidata, header.totalhunks * VBI_PACKED_BYTES, &actlength, NULL);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
fprintf(stderr, "Error getting VBI metadata: %s\n", chd_error_string(err));
|
||||
memset(vbidata, 0, header.totalhunks * VBI_PACKED_BYTES);
|
||||
fixes++;
|
||||
}
|
||||
if (actlength != header.totalhunks * VBI_PACKED_BYTES)
|
||||
{
|
||||
fprintf(stderr, "VBI metadata incorrect size\n");
|
||||
memset(vbidata, 0, header.totalhunks * VBI_PACKED_BYTES);
|
||||
fixes++;
|
||||
}
|
||||
|
||||
/* loop over hunks, reading */
|
||||
for (framenum = 0; framenum < header.totalhunks; framenum++)
|
||||
{
|
||||
vbi_metadata origvbi;
|
||||
vbi_metadata vbi;
|
||||
UINT32 vbiframe;
|
||||
|
||||
/* progress */
|
||||
progress(framenum == 0, "Processing hunk %d/%d... \r", framenum, header.totalhunks);
|
||||
|
||||
/* set up the fake bitmap for this frame */
|
||||
*avconfig.video = *fullbitmap;
|
||||
|
||||
/* configure the decompressor for this frame */
|
||||
chd_codec_config(chd, AV_CODEC_DECOMPRESS_CONFIG, &avconfig);
|
||||
|
||||
/* read the hunk into the buffers */
|
||||
err = chd_read(chd, framenum, NULL);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
fprintf(stderr, "Error reading hunk %d from CHD file: %s\n", framenum, chd_error_string(err));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* unpack the current data for this frame */
|
||||
vbi_metadata_unpack(&origvbi, &vbiframe, &vbidata[framenum * VBI_PACKED_BYTES]);
|
||||
|
||||
/* parse the video data */
|
||||
vbi_parse_all((const UINT16 *)avconfig.video->base, avconfig.video->rowpixels, avconfig.video->width, 8, &vbi);
|
||||
|
||||
/* verify the data */
|
||||
if (vbiframe != 0 || origvbi.white != 0 || origvbi.line16 != 0 || origvbi.line17 != 0 || origvbi.line18 != 0 || origvbi.line1718 != 0)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (vbiframe != framenum)
|
||||
{
|
||||
fprintf(stderr, "%d:Frame mismatch in VBI data (%d, should be %d)\n", framenum, vbiframe, framenum);
|
||||
errors++;
|
||||
}
|
||||
if (vbi.white != origvbi.white)
|
||||
{
|
||||
fprintf(stderr, "%d:White flag mismatch in VBI data (%d, should be %d)\n", framenum, origvbi.white, vbi.white);
|
||||
errors++;
|
||||
}
|
||||
if (vbi.line16 != origvbi.line16)
|
||||
{
|
||||
fprintf(stderr, "%d:Line 16 mismatch in VBI data (%06X, should be %06X)\n", framenum, origvbi.line16, vbi.line16);
|
||||
errors++;
|
||||
}
|
||||
if (vbi.line17 != origvbi.line17)
|
||||
{
|
||||
fprintf(stderr, "%d:Line 17 mismatch in VBI data (%06X, should be %06X)\n", framenum, origvbi.line17, vbi.line17);
|
||||
errors++;
|
||||
}
|
||||
if (vbi.line18 != origvbi.line18)
|
||||
{
|
||||
fprintf(stderr, "%d:Line 18 mismatch in VBI data (%06X, should be %06X)\n", framenum, origvbi.line18, vbi.line18);
|
||||
errors++;
|
||||
}
|
||||
if (vbi.line1718 != origvbi.line1718)
|
||||
{
|
||||
fprintf(stderr, "%d:Line 17/18 mismatch in VBI data (%06X, should be %06X)\n", framenum, origvbi.line1718, vbi.line1718);
|
||||
errors++;
|
||||
}
|
||||
fixes += errors;
|
||||
fixframes += (errors != 0);
|
||||
}
|
||||
|
||||
/* pack the new data */
|
||||
vbi_metadata_pack(&vbidata[framenum * VBI_PACKED_BYTES], framenum, &vbi);
|
||||
}
|
||||
progress(TRUE, "Processing complete! \n");
|
||||
|
||||
/* print final results */
|
||||
if (fixes == 0)
|
||||
printf("\nNo fixes required\n");
|
||||
else
|
||||
printf("\nFound %d errors on %d frames\n", fixes, fixframes);
|
||||
|
||||
/* close the drive */
|
||||
chd_close(chd);
|
||||
chd = NULL;
|
||||
|
||||
/* apply fixes */
|
||||
if (fixes > 0)
|
||||
{
|
||||
/* mark the CHD writeable */
|
||||
header.flags |= CHDFLAGS_IS_WRITEABLE;
|
||||
err = chd_set_header(inputfile, &header);
|
||||
if (err != CHDERR_NONE)
|
||||
fprintf(stderr, "Error writing new header: %s\n", chd_error_string(err));
|
||||
header.flags &= ~CHDFLAGS_IS_WRITEABLE;
|
||||
writeable = TRUE;
|
||||
|
||||
/* open the file */
|
||||
err = chd_open(inputfile, CHD_OPEN_READWRITE, NULL, &chd);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, chd_error_string(err));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* write new metadata */
|
||||
err = chd_set_metadata(chd, AV_LD_METADATA_TAG, 0, vbidata, header.totalhunks * VBI_PACKED_BYTES);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
fprintf(stderr, "Error adding AVLD metadata: %s\n", chd_error_string(err));
|
||||
goto cleanup;
|
||||
}
|
||||
else
|
||||
printf("Updated metadata written successfully\n");
|
||||
|
||||
/* allow cleanup code to close the file and revert the header */
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* clean up our mess */
|
||||
if (fullbitmap != NULL)
|
||||
bitmap_free(fullbitmap);
|
||||
if (vbidata != NULL)
|
||||
free(vbidata);
|
||||
if (chd != NULL)
|
||||
chd_close(chd);
|
||||
if (writeable)
|
||||
chd_set_header(inputfile, &header);
|
||||
return (err != CHDERR_NONE);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
do_info - dump the header information from
|
||||
a drive image
|
||||
@ -2535,7 +2805,8 @@ int CLIB_DECL main(int argc, char **argv)
|
||||
{ "-info", do_info, 0 },
|
||||
{ "-merge", do_merge_update_chomp, OPERATION_MERGE },
|
||||
{ "-diff", do_diff, 0 },
|
||||
{ "-setchs", do_setchs, 0 }
|
||||
{ "-setchs", do_setchs, 0 },
|
||||
{ "-fixavdata", do_fixavdata, 0 }
|
||||
};
|
||||
extern char build_version[];
|
||||
int i;
|
||||
|
Loading…
Reference in New Issue
Block a user