summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2008-08-05 16:30:35 +0000
committer Aaron Giles <aaron@aarongiles.com>2008-08-05 16:30:35 +0000
commit5e3764d0a09ec7e02f136cf33308135b9a1aa792 (patch)
tree0082d5dbdafd19f3a30cd86bdce245f78fcfed0a
parent1f1fd39a44766718a5afa5023ce8e3f29561dc1c (diff)
Removed obsolete makemeta tool. Replaced it with new ldverify
tool which walks through either an AVI or CHD capture from a laserdisc and ensures that there are no anomalies lurking in the VBI data. Added new option to chdman, where if you use -createav with a special filename (either 2:2 or 3:2) it will create a fake laserdisc files with the equivalent cadence. This can be used for testing until full captures are available. Most games used 2:2 apart from Dragon's Lair and Space Ace, which were 3:2. Note that even though these files are essentially blank, they are Huffman-compressed, meaning that the maximum compression ratio you will get is 8:1, so they still end up ~5GB. Moved error strings from chdman.c to chd.c, where they can be fetched from any caller via the new chd_error_string() function. Updated vbiparse to improve Manchester code decoding. It now assigns a confidence level per bit based on how solid the data is. Also added a new function vbi_parse_all which parses the white flag and all three lines of metadata from a laserdisc frame. It then compares line 17 and 18 against each other and selects the most likely candidate based on per-bit confidence and other factors. Added frame number display to laserdsc.c. It is off by default, though most players can be configured to turn it on (not sure if any actually do). It can be manually toggled via the backslash key during playback.
-rw-r--r--.gitattributes2
-rw-r--r--src/emu/machine/laserdsc.c243
-rw-r--r--src/emu/machine/laserdsc.h9
-rw-r--r--src/lib/util/chd.c58
-rw-r--r--src/lib/util/chd.h3
-rw-r--r--src/lib/util/vbiparse.c101
-rw-r--r--src/lib/util/vbiparse.h21
-rw-r--r--src/tools/chdman.c384
-rw-r--r--src/tools/ldverify.c650
-rw-r--r--src/tools/makemeta.c506
-rw-r--r--src/tools/tools.mak10
11 files changed, 1260 insertions, 727 deletions
diff --git a/.gitattributes b/.gitattributes
index e3a26784729..5ed754ade74 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -3439,7 +3439,7 @@ src/tools/chdcd.c svneol=native#text/plain
src/tools/chdcd.h svneol=native#text/plain
src/tools/chdman.c svneol=native#text/plain
src/tools/jedutil.c svneol=native#text/plain
-src/tools/makemeta.c svneol=native#text/plain
+src/tools/ldverify.c svneol=native#text/plain
src/tools/regrep.c svneol=native#text/plain
src/tools/romcmp.c svneol=native#text/plain
src/tools/runtest.cmd svneol=CRLF#text/plain eol=crlf
diff --git a/src/emu/machine/laserdsc.c b/src/emu/machine/laserdsc.c
index 551cc02e2f9..300cbc7213c 100644
--- a/src/emu/machine/laserdsc.c
+++ b/src/emu/machine/laserdsc.c
@@ -197,17 +197,6 @@ struct _vp932_info
};
-/* per-field metadata */
-typedef struct _field_metadata field_metadata;
-struct _field_metadata
-{
- UINT8 whiteflag; /* white flag */
- UINT32 line16; /* line 16 Philips code */
- UINT32 line17; /* line 17 Philips code */
- UINT32 line18; /* line 18 Philips code */
-};
-
-
/* generic data */
typedef struct _laserdisc_state laserdisc_state;
struct _laserdisc_state
@@ -238,7 +227,7 @@ struct _laserdisc_state
int samplerate; /* playback samplerate */
/* metadata */
- field_metadata metadata[2]; /* metadata parsed from the stream, for each field */
+ 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 */
@@ -274,6 +263,7 @@ struct _laserdisc_state
/* debugging */
char text[100]; /* buffer for the state */
+ UINT8 lastbackslash; /* state of last backslash key check */
/* filled in by player-specific init */
void (*writedata)(laserdisc_state *ld, UINT8 prev, UINT8 new); /* write callback */
@@ -312,8 +302,8 @@ struct _sound_token
static int update_position(laserdisc_state *ld);
static void read_track_data(laserdisc_state *ld);
static void process_track_data(const device_config *device);
-static void parse_metadata(const UINT16 *videodata, UINT32 rowpixels, UINT32 width, UINT32 track, UINT8 which, field_metadata *metadata);
-static void fake_metadata(UINT32 track, UINT8 which, field_metadata *metadata);
+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 struct CustomSound_interface *config);
static void custom_stream_callback(void *param, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
@@ -366,6 +356,100 @@ const struct CustomSound_interface laserdisc_custom_interface =
custom_start
};
+static const UINT8 numberfont[10][8] =
+{
+ {
+ 0x30, // ..xx....
+ 0x48, // .x..x...
+ 0x84, // x....x..
+ 0x84, // x....x..
+ 0x84, // x....x..
+ 0x48, // .x..x...
+ 0x30 // ..xx....
+ },
+ {
+ 0x10, // ...x....
+ 0x30, // ..xx....
+ 0x50, // .x.x....
+ 0x10, // ...x....
+ 0x10, // ...x....
+ 0x10, // ...x....
+ 0x7c // .xxxxx..
+ },
+ {
+ 0x78, // .xxxx...
+ 0x84, // x....x..
+ 0x04, // .....x..
+ 0x38, // ..xxx...
+ 0x40, // .x......
+ 0x80, // x.......
+ 0xfc // xxxxxx..
+ },
+ {
+ 0x78, // .xxxx...
+ 0x84, // x....x..
+ 0x04, // .....x..
+ 0x38, // ..xxx...
+ 0x04, // .....x..
+ 0x84, // x....x..
+ 0x78 // .xxxx...
+ },
+ {
+ 0x08, // ....x...
+ 0x18, // ...xx...
+ 0x28, // ..x.x...
+ 0x48, // .x..x...
+ 0xfc, // xxxxxx..
+ 0x08, // ....x...
+ 0x08 // ....x...
+ },
+ {
+ 0xfc, // xxxxxx..
+ 0x80, // x.......
+ 0x80, // x.......
+ 0xf8, // xxxxx...
+ 0x04, // .....x..
+ 0x84, // x....x..
+ 0x78 // .xxxx...
+ },
+ {
+ 0x38, // ..xxx...
+ 0x40, // .x......
+ 0x80, // x.......
+ 0xf8, // xxxxx...
+ 0x84, // x....x..
+ 0x84, // x....x..
+ 0x78 // .xxxx...
+ },
+ {
+ 0xfc, // xxxxxx..
+ 0x04, // .....x..
+ 0x08, // ....x...
+ 0x10, // ...x....
+ 0x20, // ..x.....
+ 0x20, // ..x.....
+ 0x20 // ..x.....
+ },
+ {
+ 0x78, // .xxxx...
+ 0x84, // x....x..
+ 0x84, // x....x..
+ 0x78, // .xxxx...
+ 0x84, // x....x..
+ 0x84, // x....x..
+ 0x78 // .xxxx...
+ },
+ {
+ 0x78, // .xxxx..
+ 0x84, // x....x.
+ 0x84, // x....x.
+ 0x7c, // .xxxxx.
+ 0x04, // .....x.
+ 0x08, // ....x..
+ 0x70, // .xxx...
+ }
+};
+
/***************************************************************************
@@ -607,17 +691,15 @@ INLINE int add_to_current_track(laserdisc_state *ld, INT32 delta)
encoded in the metadata, if present, or -1
-------------------------------------------------*/
-INLINE int frame_from_metadata(const field_metadata *metadata)
+INLINE int frame_from_metadata(const vbi_metadata *metadata)
{
UINT32 data;
- if ((metadata->line17 & 0xf80000) == 0xf80000)
- data = metadata->line17 & 0x7ffff;
- else if ((metadata->line18 & 0xf80000) == 0xf80000)
- data = metadata->line18 & 0x7ffff;
- else if (metadata->line17 == 0x88ffff || metadata->line18 == 0x88ffff)
+ if ((metadata->line1718 & 0xf80000) == 0xf80000)
+ data = metadata->line1718 & 0x7ffff;
+ else if (metadata->line1718 == 0x88ffff)
return 0;
- else if (metadata->line17 == 0x80eeee || metadata->line18 == 0x80eeee)
+ else if (metadata->line1718 == 0x80eeee)
return 99999;
else
return -1;
@@ -632,14 +714,12 @@ INLINE int frame_from_metadata(const field_metadata *metadata)
or -1
-------------------------------------------------*/
-INLINE int chapter_from_metadata(const field_metadata *metadata)
+INLINE int chapter_from_metadata(const vbi_metadata *metadata)
{
UINT32 data;
- if ((metadata->line17 & 0xf00fff) == 0x800ddd)
- data = metadata->line17 & 0x7f000;
- else if ((metadata->line18 & 0xf00fff) == 0x800ddd)
- data = metadata->line18 & 0x7f000;
+ if ((metadata->line1718 & 0xf00fff) == 0x800ddd)
+ data = metadata->line1718 & 0x7f000;
else
return -1;
@@ -709,6 +789,13 @@ void laserdisc_vsync(const device_config *device)
laserdisc_state *ld = get_safe_token(device);
UINT8 origstate = ld->state;
UINT8 hittarget;
+ int backslash;
+
+ /* allow the backslash key to toggle the frame display */
+ backslash = input_code_pressed(KEYCODE_BACKSLASH);
+ if (!ld->lastbackslash && backslash)
+ ld->display ^= 1;
+ ld->lastbackslash = backslash;
/* remember the time */
ld->lastvsynctime = timer_get_time();
@@ -988,7 +1075,7 @@ UINT32 laserdisc_get_field_code(const device_config *device, UINT8 code)
switch (code)
{
case LASERDISC_CODE_WHITE_FLAG:
- return ld->metadata[field].whiteflag;
+ return ld->metadata[field].white;
case LASERDISC_CODE_LINE16:
return ld->metadata[field].line16;
@@ -1057,7 +1144,7 @@ static int update_position(laserdisc_state *ld)
LOG_POSITION(("%d:track=%5d frame=%5d target=%5d ... ", fieldnum, tracknum, frame, ld->targetframe));
/* if we hit the first field of our frame, we're done */
- if (ld->last_frame == ld->targetframe && frame_from_metadata(&ld->metadata[fieldnum ^ 1]) == ld->targetframe && ld->metadata[fieldnum ^ 1].whiteflag)
+ if (ld->last_frame == ld->targetframe && frame_from_metadata(&ld->metadata[fieldnum ^ 1]) == ld->targetframe && ld->metadata[fieldnum ^ 1].white)
{
ld->curfractrack = INT_TO_FRAC(tracknum);
LOG_POSITION(("hit target\n"));
@@ -1180,7 +1267,7 @@ static void read_track_data(laserdisc_state *ld)
ld->avconfig.audio_xor = BYTE_XOR_BE(0);
/* if the previous field had the white flag, force the new field to pair with it */
- if (ld->metadata[fieldnum ^ 1].whiteflag)
+ if (ld->metadata[fieldnum ^ 1].white)
ld->videofields[ld->videoindex] = 1;
/* if we already have both fields on the current videoindex, advance */
@@ -1241,10 +1328,10 @@ static void process_track_data(const device_config *device)
/* parse the metadata */
if (ld->disc != NULL && ld->avconfig.video_buffer != NULL)
- parse_metadata((const UINT16 *)ld->avconfig.video_buffer, ld->avconfig.video_stride / 2, ld->videoframe[0]->width, tracknum, fieldnum, &ld->metadata[fieldnum]);
+ vbi_parse_all((const UINT16 *)ld->avconfig.video_buffer, ld->avconfig.video_stride / 2, ld->videoframe[0]->width, 8, &ld->metadata[fieldnum]);
else
fake_metadata(tracknum, fieldnum, &ld->metadata[fieldnum]);
- printf("Track %5d: Metadata = %d %08X %08X %08X\n", tracknum, ld->metadata[fieldnum].whiteflag, ld->metadata[fieldnum].line16, ld->metadata[fieldnum].line17, ld->metadata[fieldnum].line18);
+// printf("Track %5d: Metadata = %d %08X %08X %08X %08X\n", tracknum, ld->metadata[fieldnum].white, ld->metadata[fieldnum].line16, ld->metadata[fieldnum].line17, ld->metadata[fieldnum].line18, ld->metadata[fieldnum].line1718);
/* update the last seen frame and chapter */
frame = frame_from_metadata(&ld->metadata[fieldnum]);
@@ -1254,6 +1341,10 @@ static void process_track_data(const device_config *device)
if (chapter != -1)
ld->last_chapter = chapter;
+ /* render the display if present */
+ if (ld->display)
+ render_display((UINT16 *)ld->avconfig.video_buffer, ld->avconfig.video_stride / 2, ld->videoframe[0]->width, ld->last_frame);
+
/* update video ld */
if (rawdata != NULL && (ld->avconfig.decode_mask & AVCOMP_DECODE_VIDEO))
{
@@ -1309,44 +1400,15 @@ static void process_track_data(const device_config *device)
/*-------------------------------------------------
- parse_metadata - parse raw metadata into
- something more useful
--------------------------------------------------*/
-
-static void parse_metadata(const UINT16 *videodata, UINT32 rowpixels, UINT32 width, UINT32 track, UINT8 which, field_metadata *metadata)
-{
- UINT8 bits[24];
- UINT8 bitnum;
-
- metadata->whiteflag = vbi_parse_white_flag(videodata + 11 * rowpixels, width, 8);
-
- metadata->line16 = 0;
- if (vbi_parse_manchester_code(videodata + 16 * rowpixels, width, 8, 24, bits) == 24)
- for (bitnum = 0; bitnum < 24; bitnum++)
- metadata->line16 = (metadata->line16 << 1) | bits[bitnum];
-
- metadata->line17 = 0;
- if (vbi_parse_manchester_code(videodata + 17 * rowpixels, width, 8, 24, bits) == 24)
- for (bitnum = 0; bitnum < 24; bitnum++)
- metadata->line17 = (metadata->line17 << 1) | bits[bitnum];
-
- metadata->line18 = 0;
- if (vbi_parse_manchester_code(videodata + 18 * rowpixels, width, 8, 24, bits) == 24)
- for (bitnum = 0; bitnum < 24; bitnum++)
- metadata->line18 = (metadata->line18 << 1) | bits[bitnum];
-}
-
-
-/*-------------------------------------------------
fake_metadata - fake metadata when there's
no disc present
-------------------------------------------------*/
-static void fake_metadata(UINT32 track, UINT8 which, field_metadata *metadata)
+static void fake_metadata(UINT32 track, UINT8 which, vbi_metadata *metadata)
{
if (which == 0)
{
- metadata->whiteflag = 1;
+ metadata->white = 1;
metadata->line16 = 0;
metadata->line17 = metadata->line18 = 0xf80000 |
(((track / 10000) % 10) << 16) |
@@ -1361,6 +1423,63 @@ static void fake_metadata(UINT32 track, UINT8 which, field_metadata *metadata)
/*-------------------------------------------------
+ render_display - draw the frame display
+-------------------------------------------------*/
+
+static void render_display(UINT16 *videodata, UINT32 rowpixels, UINT32 width, int frame)
+{
+ const int xscale = 4, yscale = 2;
+ char buffer[10];
+ int x = width / 10;
+ int y = 50;
+ int ch;
+ int delta;
+
+ /* do nothing if no data */
+ if (videodata == NULL)
+ return;
+
+ /* convert to a character string and render */
+ sprintf(buffer, "%5d", frame);
+
+ /* iterate over 5 positions: (-1,-1), (-1,1), (1,-1), (1,1) and (0,0) */
+ /* render all in black except the last one */
+ for (delta = 0; delta < 5; delta++)
+ {
+ int color = (delta < 4) ? 0x0080 : 0xff80;
+ int dx = (delta < 4) ? ((delta & 1) ? -1 : 1) : 0;
+ int dy = (delta < 4) ? ((delta & 2) ? -1 : 1) : 0;
+
+ /* iterate over 5 characters */
+ for (ch = 0; ch < 5; ch++)
+ if (buffer[ch] >= '0' && buffer[ch] <= '9')
+ {
+ const UINT8 *fontdata = &numberfont[buffer[ch] - '0'][0];
+ int cy, cx;
+
+ /* iterate over the rows of the character */
+ for (cy = 0; cy < 8; cy++)
+ {
+ UINT8 bits = *fontdata++;
+
+ /* and over the columns */
+ for (cx = 0; cx < 8; cx++)
+ if (bits & (0x80 >> cx))
+ {
+ int ix, iy;
+
+ /* fill in an xscale x yscale pixel */
+ for (iy = 0; iy < yscale; iy++)
+ for (ix = 0; ix < xscale; ix++)
+ videodata[(y + cy * yscale + iy + dy) * rowpixels + (x + (ch * 9 + cx) * xscale + ix + dx)] = color;
+ }
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
custom_start - custom audio start
for laserdiscs
-------------------------------------------------*/
diff --git a/src/emu/machine/laserdsc.h b/src/emu/machine/laserdsc.h
index a77b4fbb689..31bf2fa1a69 100644
--- a/src/emu/machine/laserdsc.h
+++ b/src/emu/machine/laserdsc.h
@@ -43,10 +43,11 @@ enum
#define LASERDISC_OUTPUT_LINES 4
/* laserdisc field codes */
-#define LASERDISC_CODE_WHITE_FLAG 0
-#define LASERDISC_CODE_LINE16 1
-#define LASERDISC_CODE_LINE17 2
-#define LASERDISC_CODE_LINE18 3
+#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 */
/* device configuration */
enum
diff --git a/src/lib/util/chd.c b/src/lib/util/chd.c
index e8fda05e2ad..3c0fb3454e8 100644
--- a/src/lib/util/chd.c
+++ b/src/lib/util/chd.c
@@ -831,33 +831,45 @@ core_file *chd_core_file(chd_file *chd)
/*-------------------------------------------------
- chd_multi_filename - compute the indexed CHD
- filename
+ chd_error_string - return an error string for
+ the given CHD error
-------------------------------------------------*/
-#ifdef UNUSED_FUNCTION
-void chd_multi_filename(const char *origname, char *finalname, int index)
+const char *chd_error_string(chd_error err)
{
- char *extension;
- char findex[5];
-
- /* copy the original name */
- strcpy(finalname, origname);
-
- /* determine the offset of the extension period */
- extension = strchr(finalname, '.');
- if (extension == NULL)
- extension = finalname + strlen(finalname);
-
- /* compute our extension */
- sprintf(findex, ".%3d", index);
- if (findex[1] == ' ')
- findex[1] = 'c';
- if (findex[2] == ' ')
- findex[2] = 'h';
- strcpy(extension, findex);
+ switch (err)
+ {
+ case CHDERR_NONE: return "no error";
+ case CHDERR_NO_INTERFACE: return "no drive interface";
+ case CHDERR_OUT_OF_MEMORY: return "out of memory";
+ case CHDERR_INVALID_FILE: return "invalid file";
+ case CHDERR_INVALID_PARAMETER: return "invalid parameter";
+ case CHDERR_INVALID_DATA: return "invalid data";
+ case CHDERR_FILE_NOT_FOUND: return "file not found";
+ case CHDERR_REQUIRES_PARENT: return "requires parent";
+ case CHDERR_FILE_NOT_WRITEABLE: return "file not writeable";
+ case CHDERR_READ_ERROR: return "read error";
+ case CHDERR_WRITE_ERROR: return "write error";
+ case CHDERR_CODEC_ERROR: return "codec error";
+ case CHDERR_INVALID_PARENT: return "invalid parent";
+ case CHDERR_HUNK_OUT_OF_RANGE: return "hunk out of range";
+ case CHDERR_DECOMPRESSION_ERROR: return "decompression error";
+ case CHDERR_COMPRESSION_ERROR: return "compression error";
+ case CHDERR_CANT_CREATE_FILE: return "can't create file";
+ case CHDERR_CANT_VERIFY: return "can't verify file";
+ case CHDERR_NOT_SUPPORTED: return "operation not supported";
+ case CHDERR_METADATA_NOT_FOUND: return "can't find metadata";
+ case CHDERR_INVALID_METADATA_SIZE: return "invalid metadata size";
+ case CHDERR_UNSUPPORTED_VERSION: return "unsupported CHD version";
+ case CHDERR_VERIFY_INCOMPLETE: return "incomplete verify";
+ case CHDERR_INVALID_METADATA: return "invalid metadata";
+ case CHDERR_INVALID_STATE: return "invalid state";
+ case CHDERR_OPERATION_PENDING: return "operation pending";
+ case CHDERR_NO_ASYNC_OPERATION: return "no async operation in progress";
+ case CHDERR_UNSUPPORTED_FORMAT: return "unsupported format";
+ default: return "undocumented error";
+ }
}
-#endif
diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h
index 0e3af6f94f5..6e70e3e18f8 100644
--- a/src/lib/util/chd.h
+++ b/src/lib/util/chd.h
@@ -238,6 +238,9 @@ void chd_close(chd_file *chd);
/* return the associated core_file */
core_file *chd_core_file(chd_file *chd);
+/* return an error string for the given CHD error */
+const char *chd_error_string(chd_error err);
+
/* ----- CHD header management ----- */
diff --git a/src/lib/util/vbiparse.c b/src/lib/util/vbiparse.c
index 5d3099ab9a8..ba9f29e10cd 100644
--- a/src/lib/util/vbiparse.c
+++ b/src/lib/util/vbiparse.c
@@ -10,6 +10,8 @@
***************************************************************************/
#include "osdcore.h"
+#include "vbiparse.h"
+#include <math.h>
@@ -31,7 +33,7 @@
code from a line of video data
-------------------------------------------------*/
-int vbi_parse_manchester_code(const UINT16 *source, int sourcewidth, int sourceshift, int expectedbits, UINT8 *result)
+int vbi_parse_manchester_code(const UINT16 *source, int sourcewidth, int sourceshift, int expectedbits, UINT32 *result)
{
UINT8 srcabs[MAX_SOURCE_WIDTH];
UINT8 min, max, mid, srcabsval;
@@ -125,15 +127,36 @@ int vbi_parse_manchester_code(const UINT16 *source, int sourcewidth, int sources
/* now extract the bits */
for (x = 0; x < expectedbits; x++)
{
- int leftbit = firstedge + ((double)x - 0.25) * bestclock;
- int rightbit = firstedge + ((double)x + 0.25) * bestclock;
- int left = srcabs[leftbit];
- int right = srcabs[rightbit];
-
+ int leftstart = firstedge + ceil(((double)x - 0.5) * bestclock);
+// int leftmid = firstedge + ((double)x - 0.25) * bestclock;
+ int leftend = firstedge + floor(((double)x - 0.0) * bestclock);
+ int rightstart = firstedge + ceil(((double)x + 0.0) * bestclock);
+// int rightmid = firstedge + ((double)x + 0.25) * bestclock;
+ int rightend = firstedge + floor(((double)x + 0.5) * bestclock);
+ int leftavg, rightavg, leftabs, rightabs;
+ int confidence = 0;
+ int tx;
+
+ /* compute left and right average values */
+ leftavg = 0;
+ for (tx = leftstart; tx <= leftend; tx++)
+ leftavg += (UINT8)(source[tx] >> sourceshift) - mid;
+ leftabs = (leftavg >= 0);
+ leftavg = (leftavg < 0) ? -leftavg : leftavg;
+
+ rightavg = 0;
+ for (tx = rightstart; tx <= rightend; tx++)
+ rightavg += (UINT8)(source[tx] >> sourceshift) - mid;
+ rightabs = (rightavg >= 0);
+ rightavg = (rightavg < 0) ? -rightavg : rightavg;
+
/* all bits should be marked by transitions; fail if we don't get one */
- if (left == right)
+ if (leftabs == rightabs)
return 0;
- result[x] = (left < right);
+
+ /* store the bit and its confidence level */
+ confidence = leftavg + rightavg;
+ result[x] = (leftabs < rightabs) | (confidence << 1);
}
return expectedbits;
}
@@ -166,3 +189,65 @@ int vbi_parse_white_flag(const UINT16 *source, int sourcewidth, int sourceshift)
/* if there's a spread of at least 0x20, and the average is above 3/4 of the center, call it good */
return (diff >= 0x20) && (avgval >= minval + 3 * diff / 4);
}
+
+
+/*-------------------------------------------------
+ vbi_parse_all - parse everything from a video
+ frame
+-------------------------------------------------*/
+
+void vbi_parse_all(const UINT16 *source, int sourcerowpixels, int sourcewidth, int sourceshift, vbi_metadata *vbi)
+{
+ UINT32 bits[2][24];
+ UINT8 bitnum;
+
+ /* first reset it all */
+ memset(vbi, 0, sizeof(*vbi));
+
+ /* get the white flag */
+ vbi->white = vbi_parse_white_flag(source + 11 * sourcerowpixels, sourcewidth, sourceshift);
+
+ /* parse line 16 */
+ if (vbi_parse_manchester_code(source + 16 * sourcerowpixels, sourcewidth, sourceshift, 24, bits[0]) == 24)
+ for (bitnum = 0; bitnum < 24; bitnum++)
+ vbi->line16 = (vbi->line16 << 1) | (bits[0][bitnum] & 1);
+
+ /* parse line 17 */
+ if (vbi_parse_manchester_code(source + 17 * sourcerowpixels, sourcewidth, sourceshift, 24, bits[0]) == 24)
+ for (bitnum = 0; bitnum < 24; bitnum++)
+ vbi->line17 = (vbi->line17 << 1) | (bits[0][bitnum] & 1);
+
+ /* parse line 18 */
+ if (vbi_parse_manchester_code(source + 18 * sourcerowpixels, sourcewidth, sourceshift, 24, bits[1]) == 24)
+ for (bitnum = 0; bitnum < 24; bitnum++)
+ vbi->line18 = (vbi->line18 << 1) | (bits[1][bitnum] & 1);
+
+ /* pick the best out of lines 17/18 */
+ /* if we only got one or the other, that's all we have */
+ if (vbi->line17 == 0)
+ vbi->line1718 = vbi->line18;
+ else if (vbi->line18 == 0)
+ vbi->line1718 = vbi->line17;
+
+ /* if they agree, we're golden */
+ else if (vbi->line17 == vbi->line18)
+ vbi->line1718 = vbi->line17;
+
+ /* if they don't agree, we have to pick one */
+ 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 & 0xf000) > 0x9000 || (vbi->line17 & 0xf00) > 0x900 || (vbi->line17 & 0xf0) > 0x90 || (vbi->line17 & 0xf) > 0x9)
+ vbi->line1718 = vbi->line18;
+ else if ((vbi->line18 & 0xf000) > 0x9000 || (vbi->line18 & 0xf00) > 0x900 || (vbi->line18 & 0xf0) > 0x90 || (vbi->line18 & 0xf) > 0x9)
+ vbi->line1718 = vbi->line17;
+ }
+
+ /* if still nothing, then scan through the bits and pick the ones with the most confidence */
+ if (vbi->line1718 == 0)
+ for (bitnum = 0; bitnum < 24; bitnum++)
+ vbi->line1718 = (vbi->line1718 << 1) | ((bits[0][bitnum] > bits[1][bitnum]) ? (bits[0][bitnum] & 1) : (bits[1][bitnum] & 1));
+ }
+}
diff --git a/src/lib/util/vbiparse.h b/src/lib/util/vbiparse.h
index ed34592c159..5e4a594f6a1 100644
--- a/src/lib/util/vbiparse.h
+++ b/src/lib/util/vbiparse.h
@@ -16,14 +16,33 @@
/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _vbi_metadata vbi_metadata;
+struct _vbi_metadata
+{
+ UINT8 white; /* white flag: on or off */
+ UINT32 line16; /* line 16 code */
+ UINT32 line17; /* line 17 code */
+ UINT32 line18; /* line 18 code */
+ UINT32 line1718; /* most plausible value from lines 17/18 */
+};
+
+
+
+/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* parse a Manchester code from a line of video data */
-int vbi_parse_manchester_code(const UINT16 *source, int sourcewidth, int sourceshift, int expectedbits, UINT8 *result);
+int vbi_parse_manchester_code(const UINT16 *source, int sourcewidth, int sourceshift, int expectedbits, UINT32 *result);
/* compute the "white flag" from a line of video data */
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);
+
#endif /* __VBIPARSE_H__ */
diff --git a/src/tools/chdman.c b/src/tools/chdman.c
index d81e74aac68..5c70b9823df 100644
--- a/src/tools/chdman.c
+++ b/src/tools/chdman.c
@@ -32,6 +32,21 @@
#define OPERATION_MERGE 1
#define OPERATION_CHOMP 2
+#ifdef PTR64
+#define IS_FAKE_AVI_FILE(a) ((UINT64)(a) <= 2)
+#else
+#define IS_FAKE_AVI_FILE(a) ((UINT32)(a) <= 2)
+#endif
+#define AVI_FAKE_FILE_22 ((avi_file *)1)
+#define AVI_FAKE_FILE_32 ((avi_file *)2)
+
+#define AVI_FAKE_FRAMERATE 29970000
+#define AVI_FAKE_FRAMES 54004
+#define AVI_FAKE_WIDTH 720
+#define AVI_FAKE_HEIGHT 524
+#define AVI_FAKE_CHANNELS 2
+#define AVI_FAKE_SAMPLERATE 48000
+
/***************************************************************************
@@ -59,33 +74,6 @@ static chd_error chdman_compress_chd(chd_file *chd, chd_file *source, UINT32 tot
GLOBAL VARIABLES
***************************************************************************/
-static const char *const error_strings[] =
-{
- "no error",
- "no drive interface",
- "out of memory",
- "invalid file",
- "invalid parameter",
- "invalid data",
- "file not found",
- "requires parent",
- "file not writeable",
- "read error",
- "write error",
- "codec error",
- "invalid parent",
- "hunk out of range",
- "decompression error",
- "compression error",
- "can't create file",
- "can't verify file",
- "operation not supported",
- "can't find metadata",
- "invalid metadata size",
- "unsupported CHD version",
- "incomplete verify"
-};
-
static clock_t lastprogress = 0;
@@ -165,22 +153,6 @@ static void ATTR_PRINTF(2,3) progress(int forceit, const char *fmt, ...)
/*-------------------------------------------------
- error_string - return an error sting
--------------------------------------------------*/
-
-static const char *error_string(int err)
-{
- static char temp_buffer[100];
-
- if (err < sizeof(error_strings) / sizeof(error_strings[0]))
- return error_strings[err];
-
- sprintf(temp_buffer, "unknown error %d", err);
- return temp_buffer;
-}
-
-
-/*-------------------------------------------------
usage - generic usage error display
-------------------------------------------------*/
@@ -332,7 +304,7 @@ static int do_createhd(int argc, char *argv[], int param)
err = chd_create(outputfile, (UINT64)totalsectors * (UINT64)sectorsize, hunksize, CHDCOMPRESSION_ZLIB_PLUS, NULL);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error creating CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error creating CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -340,7 +312,7 @@ static int do_createhd(int argc, char *argv[], int param)
err = chd_open(outputfile, CHD_OPEN_READWRITE, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening new CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening new CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -349,14 +321,14 @@ static int do_createhd(int argc, char *argv[], int param)
err = chd_set_metadata(chd, HARD_DISK_METADATA_TAG, 0, metadata, strlen(metadata) + 1);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error adding hard disk metadata: %s\n", error_string(err));
+ fprintf(stderr, "Error adding hard disk metadata: %s\n", chd_error_string(err));
goto cleanup;
}
/* compress the hard drive */
err = chdman_compress_file(chd, inputfile, offset);
if (err != CHDERR_NONE)
- fprintf(stderr, "Error during compression: %s\n", error_string(err));
+ fprintf(stderr, "Error during compression: %s\n", chd_error_string(err));
cleanup:
/* close everything down */
@@ -403,7 +375,7 @@ static int do_createraw(int argc, char *argv[], int param)
err = chd_create(outputfile, logicalbytes, hunksize, CHDCOMPRESSION_ZLIB_PLUS, NULL);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error creating CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error creating CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -411,14 +383,14 @@ static int do_createraw(int argc, char *argv[], int param)
err = chd_open(outputfile, CHD_OPEN_READWRITE, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening new CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening new CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
/* compress the CHD */
err = chdman_compress_file(chd, inputfile, offset);
if (err != CHDERR_NONE)
- fprintf(stderr, "Error during compression: %s\n", error_string(err));
+ fprintf(stderr, "Error during compression: %s\n", chd_error_string(err));
cleanup:
/* close everything down */
@@ -474,7 +446,7 @@ static int do_createcd(int argc, char *argv[], int param)
err = chdcd_parse_toc(inputfile, &toc, &track_info);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error reading input file: %s\n", error_string(err));
+ fprintf(stderr, "Error reading input file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -498,7 +470,7 @@ static int do_createcd(int argc, char *argv[], int param)
err = chd_create(outputfile, (UINT64)totalsectors * (UINT64)sectorsize, hunksize, CHDCOMPRESSION_ZLIB_PLUS, NULL);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error creating CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error creating CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -506,7 +478,7 @@ static int do_createcd(int argc, char *argv[], int param)
err = chd_open(outputfile, CHD_OPEN_READWRITE, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening new CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening new CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -520,7 +492,7 @@ static int do_createcd(int argc, char *argv[], int param)
err = chd_set_metadata(chd, CDROM_TRACK_METADATA_TAG, i, metadata, strlen(metadata) + 1);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error adding CD-ROM metadata: %s\n", error_string(err));
+ fprintf(stderr, "Error adding CD-ROM metadata: %s\n", chd_error_string(err));
goto cleanup;
}
}
@@ -529,7 +501,7 @@ static int do_createcd(int argc, char *argv[], int param)
err = chd_compress_begin(chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error compressing: %s\n", error_string(err));
+ fprintf(stderr, "Error compressing: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -595,7 +567,7 @@ static int do_createcd(int argc, char *argv[], int param)
err = chd_compress_hunk(chd, cache, &ratio);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error during compression: %s\n", error_string(err));
+ fprintf(stderr, "Error during compression: %s\n", chd_error_string(err));
goto cleanup;
}
}
@@ -608,7 +580,7 @@ static int do_createcd(int argc, char *argv[], int param)
/* cleanup */
err = chd_compress_finish(chd);
if (err != CHDERR_NONE)
- fprintf(stderr, "Error during compression finalization: %s\n", error_string(err));
+ fprintf(stderr, "Error during compression finalization: %s\n", chd_error_string(err));
else
progress(TRUE, "Compression complete ... final ratio = %d%% \n", (int)(100.0 * ratio));
@@ -691,7 +663,7 @@ static avi_error read_avi_frame(avi_file *avi, UINT32 framenum, UINT8 *cache, bi
/* loop over the data and copy it to the cache */
for (y = framenum % interlace_factor; y < info->video_height; y += interlace_factor)
{
- UINT16 *source = (UINT16 *)bitmap->base + y * bitmap->rowpixels;
+ UINT16 *source = BITMAP_ADDR16(bitmap, y, 0);
for (x = 0; x < info->video_width; x++)
{
@@ -712,6 +684,161 @@ cleanup:
/*-------------------------------------------------
+ fake_avi_frame - fake an AVI frame
+-------------------------------------------------*/
+
+static avi_error fake_avi_frame(avi_file *avi, UINT32 framenum, UINT8 *cache, bitmap_t *bitmap, int interlaced, UINT32 hunkbytes)
+{
+ static int framecounter = 0;
+ int leftsamp = (framenum % 200 < 10) ? 10000 : 0;
+ int rightsamp = (framenum % 200 >= 100 && framenum % 200 < 110) ? 10000 : 0;
+ int interlace_factor = interlaced ? 2 : 1;
+ UINT32 first_sample, num_samples;
+ int chnum, sampnum, x, y;
+ int whiteflag, line1718;
+ UINT8 *dest = cache;
+ INT16 *temp;
+
+ /* reset framecounter to 1 on frame 0 */
+ if (framenum == 0)
+ framecounter = 1;
+
+ /* compute the number of samples in this frame */
+ first_sample = ((UINT64)AVI_FAKE_SAMPLERATE * (UINT64)framenum * (UINT64)1000000 + AVI_FAKE_FRAMERATE - 1) / AVI_FAKE_FRAMERATE;
+ num_samples = ((UINT64)AVI_FAKE_SAMPLERATE * (UINT64)(framenum + 1) * (UINT64)1000000 + AVI_FAKE_FRAMERATE - 1) / AVI_FAKE_FRAMERATE - first_sample;
+ if (interlaced)
+ {
+ if (framenum % 2 == 0)
+ num_samples = (num_samples + 1) / 2;
+ else
+ {
+ first_sample += (num_samples + 1) / 2;
+ num_samples -= (num_samples + 1) / 2;
+ }
+ }
+
+ /* allocate a temporary buffer */
+ temp = malloc(num_samples * 2);
+ if (temp == NULL)
+ return AVIERR_NO_MEMORY;
+
+ /* update the header with the actual number of samples in the frame */
+ dest[6] = num_samples >> 8;
+ dest[7] = num_samples;
+ dest += 12 + dest[4];
+
+ /* loop over channels and read the samples */
+ for (chnum = 0; chnum < AVI_FAKE_CHANNELS; chnum++)
+ {
+ int modcheck = AVI_FAKE_SAMPLERATE / ((chnum == 0) ? 110 : 220);
+ int samp = (chnum == 0) ? leftsamp : rightsamp;
+
+ /* store them big endian at the destination */
+ for (sampnum = 0; sampnum < num_samples; sampnum++)
+ {
+ INT16 sample = ((first_sample + sampnum) % modcheck < modcheck / 2) ? samp : -samp;
+ *dest++ = sample >> 8;
+ *dest++ = sample;
+ }
+ }
+
+ /* determine what metadata we should generate */
+ whiteflag = line1718 = 0;
+ if (framenum < 2)
+ {
+ whiteflag = (framenum == 0);
+ line1718 = 0x88ffff;
+ }
+ else if (framenum >= AVI_FAKE_FRAMES * 2 - 2)
+ {
+ whiteflag = (framenum == AVI_FAKE_FRAMES * 2 - 2);
+ line1718 = 0x80eeee;
+ }
+ else
+ {
+ int effnum = framenum - 2;
+ if (avi == AVI_FAKE_FILE_22 && effnum % 2 == 0)
+ whiteflag = 1;
+ else if (avi == AVI_FAKE_FILE_32 && (effnum % 5 == 0 || effnum % 5 == 2))
+ whiteflag = 1;
+ if (whiteflag)
+ {
+ line1718 = 0xf80000 | (((framecounter / 10000) % 10) << 16) | (((framecounter / 1000) % 10) << 12) |
+ (((framecounter / 100) % 10) << 8) | (((framecounter / 10) % 10) << 4) | (framecounter % 10);
+ framecounter++;
+ }
+ }
+
+ /* loop over the data and copy it to the cache */
+ for (y = framenum % interlace_factor; y < AVI_FAKE_HEIGHT; y += interlace_factor)
+ {
+ int effy = y / interlace_factor;
+
+ /* white flag? */
+ if (effy == 11 && whiteflag)
+ {
+ for (x = 0; x < AVI_FAKE_WIDTH; x++)
+ {
+ UINT16 pixel = (x > 10 && x < AVI_FAKE_WIDTH - 10) ? 0xff80 : 0x0080;
+ *dest++ = pixel;
+ *dest++ = pixel >> 8;
+ }
+ }
+
+ /* line 17/18 */
+ else if ((effy == 17 || effy == 18) && line1718 != 0)
+ {
+ for (x = 0; x < AVI_FAKE_WIDTH; x++)
+ {
+ UINT16 pixel = 0x0080;
+ if (x >= 20)
+ {
+ int bitnum = (x - 20) / 28;
+ if (bitnum < 24)
+ {
+ int bithalf = (x - (bitnum * 28 + 20)) / 14;
+ if ((line1718 << bitnum) & 0x800000) bithalf ^= 1;
+ pixel = bithalf ? 0x0080 : 0xff80;
+ }
+ }
+ *dest++ = pixel;
+ *dest++ = pixel >> 8;
+ }
+ }
+
+ /* anything else in VBI-land */
+ else if (effy < 22)
+ {
+ for (x = 0; x < AVI_FAKE_WIDTH; x++)
+ {
+ UINT16 pixel = 0x0080;
+ *dest++ = pixel;
+ *dest++ = pixel >> 8;
+ }
+ }
+
+ /* everything else */
+ else
+ {
+ for (x = 0; x < AVI_FAKE_WIDTH; x++)
+ {
+ UINT16 pixel = framenum;
+ *dest++ = pixel;
+ *dest++ = pixel >> 8;
+ }
+ }
+ }
+
+ /* fill the rest with 0 */
+ while (dest < &cache[hunkbytes])
+ *dest++ = 0;
+
+ free(temp);
+ return AVIERR_NONE;
+}
+
+
+/*-------------------------------------------------
do_createav - create a new A/V file from an
input AVI file and metadata
-------------------------------------------------*/
@@ -746,26 +873,44 @@ static int do_createav(int argc, char *argv[], int param)
/* print some info */
printf("Input file: %s\n", inputfile);
printf("Output file: %s\n", outputfile);
-
- /* open the source file */
- avierr = avi_open(inputfile, &avi);
- if (avierr != AVIERR_NONE)
- {
- fprintf(stderr, "Error opening AVI file: %s\n", avi_error_string(avierr));
- err = CHDERR_INVALID_FILE;
- goto cleanup;
+
+ /* special AVI files */
+ if (strcmp(inputfile, "2:2") == 0 || strcmp(inputfile, "3:2") == 0)
+ {
+ /* create a fake handle */
+ avi = (strcmp(inputfile, "2:2") == 0) ? AVI_FAKE_FILE_22 : AVI_FAKE_FILE_32;
+
+ /* fake the movie information */
+ fps_times_1million = AVI_FAKE_FRAMERATE;
+ width = AVI_FAKE_WIDTH;
+ height = AVI_FAKE_HEIGHT;
+ interlaced = TRUE;
+ channels = 2;
+ rate = AVI_FAKE_SAMPLERATE;
+ totalframes = AVI_FAKE_FRAMES;
}
+ else
+ {
+ /* open the source file */
+ avierr = avi_open(inputfile, &avi);
+ if (avierr != AVIERR_NONE)
+ {
+ fprintf(stderr, "Error opening AVI file: %s\n", avi_error_string(avierr));
+ err = CHDERR_INVALID_FILE;
+ goto cleanup;
+ }
- /* get the movie information */
- info = avi_get_movie_info(avi);
- fps_times_1million = (UINT64)info->video_timescale * 1000000 / info->video_sampletime;
- width = info->video_width;
- height = info->video_height;
- interlaced = ((fps_times_1million / 1000000) <= 30) && (height % 2 == 0) && (height > 288);
- channels = info->audio_channels;
- rate = info->audio_samplerate;
- totalframes = info->video_numsamples;
- numframes = MIN(totalframes - firstframe, numframes);
+ /* get the movie information */
+ info = avi_get_movie_info(avi);
+ fps_times_1million = (UINT64)info->video_timescale * 1000000 / info->video_sampletime;
+ width = info->video_width;
+ height = info->video_height;
+ interlaced = ((fps_times_1million / 1000000) <= 30) && (height % 2 == 0) && (height > 288);
+ channels = info->audio_channels;
+ rate = info->audio_samplerate;
+ totalframes = info->video_numsamples;
+ }
+ numframes = MIN(totalframes - firstframe, numframes);
/* allocate a video buffer */
videobitmap.base = malloc(width * height * 2);
@@ -809,7 +954,7 @@ static int do_createav(int argc, char *argv[], int param)
err = chd_create(outputfile, (UINT64)numframes * (UINT64)bytes_per_frame, bytes_per_frame, CHDCOMPRESSION_AV, NULL);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error creating CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error creating CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -817,7 +962,7 @@ static int do_createav(int argc, char *argv[], int param)
err = chd_open(outputfile, CHD_OPEN_READWRITE, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening new CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening new CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
header = chd_get_header(chd);
@@ -827,7 +972,7 @@ static int do_createav(int argc, char *argv[], int param)
err = chd_set_metadata(chd, AV_METADATA_TAG, 0, metadata, strlen(metadata) + 1);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error adding AV metadata: %s\n", error_string(err));
+ fprintf(stderr, "Error adding AV metadata: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -866,7 +1011,10 @@ static int do_createav(int argc, char *argv[], int param)
progress(framenum == 0, "Compressing hunk %d/%d... (ratio=%d%%) \r", framenum, header->totalhunks, (int)(100.0 * ratio));
/* read the frame into its proper format in the cache */
- avierr = read_avi_frame(avi, firstframe + framenum, cache, &videobitmap, interlaced, bytes_per_frame);
+ if (IS_FAKE_AVI_FILE(avi))
+ avierr = fake_avi_frame(avi, firstframe + framenum, cache, &videobitmap, interlaced, bytes_per_frame);
+ else
+ avierr = read_avi_frame(avi, firstframe + framenum, cache, &videobitmap, interlaced, bytes_per_frame);
if (avierr != AVIERR_NONE)
{
fprintf(stderr, "Error reading frame %d from AVI file: %s\n", firstframe + framenum, avi_error_string(avierr));
@@ -888,7 +1036,7 @@ static int do_createav(int argc, char *argv[], int param)
cleanup:
/* close everything down */
- if (avi != NULL)
+ if (avi != NULL && !IS_FAKE_AVI_FILE(avi))
avi_close(avi);
if (chd != NULL)
chd_close(chd);
@@ -943,7 +1091,7 @@ static int do_createblankhd(int argc, char *argv[], int param)
err = chd_create(outputfile, (UINT64)totalsectors * (UINT64)sectorsize, hunksize, CHDCOMPRESSION_NONE, NULL);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error creating CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error creating CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -951,7 +1099,7 @@ static int do_createblankhd(int argc, char *argv[], int param)
err = chd_open(outputfile, CHD_OPEN_READWRITE, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening new CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening new CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -960,7 +1108,7 @@ static int do_createblankhd(int argc, char *argv[], int param)
err = chd_set_metadata(chd, HARD_DISK_METADATA_TAG, 0, metadata, strlen(metadata) + 1);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error adding hard disk metadata: %s\n", error_string(err));
+ fprintf(stderr, "Error adding hard disk metadata: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -984,7 +1132,7 @@ static int do_createblankhd(int argc, char *argv[], int param)
err = chd_write(chd, hunknum, cache);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error writing CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error writing CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
}
@@ -1033,7 +1181,7 @@ static int do_copydata(int argc, char *argv[], int param)
err = chd_open(inputfile, CHD_OPEN_READ, NULL, &inputchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening src CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening src CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -1041,14 +1189,14 @@ static int do_copydata(int argc, char *argv[], int param)
err = chd_open(outputfile, CHD_OPEN_READWRITE, NULL, &outputchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening dest CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening dest CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
/* compress the source into the dest */
err = chdman_compress_chd(outputchd, inputchd, 0);
if (err != CHDERR_NONE)
- fprintf(stderr, "Error during compression: %s\n", error_string(err));
+ fprintf(stderr, "Error during compression: %s\n", chd_error_string(err));
cleanup:
/* close everything down */
@@ -1095,7 +1243,7 @@ static int do_extract(int argc, char *argv[], int param)
err = chd_open(inputfile, CHD_OPEN_READ, NULL, &infile);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, chd_error_string(err));
goto cleanup;
}
header = chd_get_header(infile);
@@ -1131,7 +1279,7 @@ static int do_extract(int argc, char *argv[], int param)
err = chd_read(infile, hunknum, hunk);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error reading hunk %d from CHD file: %s\n", hunknum, error_string(err));
+ fprintf(stderr, "Error reading hunk %d from CHD file: %s\n", hunknum, chd_error_string(err));
goto cleanup;
}
@@ -1141,7 +1289,7 @@ static int do_extract(int argc, char *argv[], int param)
byteswritten = core_fwrite(outfile, hunk, bytes_to_write);
if (byteswritten != bytes_to_write)
{
- fprintf(stderr, "Error writing hunk %d to output file: %s\n", hunknum, error_string(CHDERR_WRITE_ERROR));
+ fprintf(stderr, "Error writing hunk %d to output file: %s\n", hunknum, chd_error_string(CHDERR_WRITE_ERROR));
err = CHDERR_WRITE_ERROR;
goto cleanup;
}
@@ -1197,7 +1345,7 @@ static int do_extractcd(int argc, char *argv[], int param)
err = chd_open(inputfile, CHD_OPEN_READ, NULL, &inputchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, chd_error_string(err));
goto cleanup;
}
@@ -1299,7 +1447,7 @@ static int do_extractcd(int argc, char *argv[], int param)
byteswritten = core_fwrite(outfile2, sector, toc->tracks[track].datasize);
if (byteswritten != toc->tracks[track].datasize)
{
- fprintf(stderr, "Error writing frame %d to output file: %s\n", frame, error_string(CHDERR_WRITE_ERROR));
+ fprintf(stderr, "Error writing frame %d to output file: %s\n", frame, chd_error_string(CHDERR_WRITE_ERROR));
err = CHDERR_WRITE_ERROR;
goto cleanup;
}
@@ -1313,7 +1461,7 @@ static int do_extractcd(int argc, char *argv[], int param)
byteswritten = core_fwrite(outfile2, sector, toc->tracks[track].subsize);
if (byteswritten != toc->tracks[track].subsize)
{
- fprintf(stderr, "Error writing frame %d to output file: %s\n", frame, error_string(CHDERR_WRITE_ERROR));
+ fprintf(stderr, "Error writing frame %d to output file: %s\n", frame, chd_error_string(CHDERR_WRITE_ERROR));
err = CHDERR_WRITE_ERROR;
goto cleanup;
}
@@ -1453,7 +1601,7 @@ static int do_extractav(int argc, char *argv[], int param)
err = chd_open(inputfile, CHD_OPEN_READ, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, chd_error_string(err));
goto cleanup;
}
header = chd_get_header(chd);
@@ -1462,7 +1610,7 @@ static int do_extractav(int argc, char *argv[], int param)
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", error_string(err));
+ fprintf(stderr, "Error getting A/V metadata: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -1481,6 +1629,8 @@ static int do_extractav(int argc, char *argv[], int param)
{
fps_times_1million /= 2;
height *= 2;
+ firstframe *= 2;
+ numframes *= 2;
}
numframes = MIN(totalframes - firstframe, numframes);
@@ -1550,7 +1700,7 @@ static int do_extractav(int argc, char *argv[], int param)
err = chd_read(chd, firstframe + framenum, hunk);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error reading hunk %d from CHD file: %s\n", firstframe + framenum, error_string(err));
+ fprintf(stderr, "Error reading hunk %d from CHD file: %s\n", firstframe + framenum, chd_error_string(err));
goto cleanup;
}
@@ -1610,7 +1760,7 @@ static int do_verify(int argc, char *argv[], int param)
err = chd_open(inputfile, CHD_OPEN_READ, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
header = *chd_get_header(chd);
@@ -1642,7 +1792,7 @@ static int do_verify(int argc, char *argv[], int param)
if (err == CHDERR_CANT_VERIFY)
fprintf(stderr, "Can't verify this type of image (probably writeable)\n");
else
- fprintf(stderr, "\nError during verify: %s\n", error_string(err));
+ fprintf(stderr, "\nError during verify: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -1702,7 +1852,7 @@ static int do_verify(int argc, char *argv[], int param)
{
err = chd_set_header(inputfile, &header);
if (err != CHDERR_NONE)
- fprintf(stderr, "Error writing new header: %s\n", error_string(err));
+ fprintf(stderr, "Error writing new header: %s\n", chd_error_string(err));
else
printf("Updated header successfully\n");
}
@@ -1743,7 +1893,7 @@ static int do_info(int argc, char *argv[], int param)
err = chd_open(inputfile, CHD_OPEN_READ, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, chd_error_string(err));
goto cleanup;
}
header = *chd_get_header(chd);
@@ -1996,7 +2146,7 @@ static int do_merge_update_chomp(int argc, char *argv[], int param)
err = chd_open(parentfile, CHD_OPEN_READ, NULL, &parentchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s': %s\n", parentfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s': %s\n", parentfile, chd_error_string(err));
goto cleanup;
}
}
@@ -2005,7 +2155,7 @@ static int do_merge_update_chomp(int argc, char *argv[], int param)
err = chd_open(inputfile, CHD_OPEN_READ, parentchd, &inputchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, chd_error_string(err));
goto cleanup;
}
inputheader = chd_get_header(inputchd);
@@ -2021,7 +2171,7 @@ static int do_merge_update_chomp(int argc, char *argv[], int param)
err = chd_create(outputfile, inputheader->logicalbytes, inputheader->hunkbytes, inputheader->compression, NULL);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error creating CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error creating CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -2029,7 +2179,7 @@ static int do_merge_update_chomp(int argc, char *argv[], int param)
err = chd_open(outputfile, CHD_OPEN_READWRITE, NULL, &outputchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening new CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening new CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -2037,14 +2187,14 @@ static int do_merge_update_chomp(int argc, char *argv[], int param)
err = chd_clone_metadata(inputchd, outputchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error cloning metadata: %s\n", error_string(err));
+ fprintf(stderr, "Error cloning metadata: %s\n", chd_error_string(err));
goto cleanup;
}
/* do the compression; our interface will route reads for us */
err = chdman_compress_chd(outputchd, inputchd, (param == OPERATION_CHOMP) ? (maxhunk + 1) : 0);
if (err != CHDERR_NONE)
- fprintf(stderr, "Error during compression: %s\n", error_string(err));
+ fprintf(stderr, "Error during compression: %s\n", chd_error_string(err));
cleanup:
/* close everything down */
@@ -2091,7 +2241,7 @@ static int do_diff(int argc, char *argv[], int param)
err = chd_open(parentfile, CHD_OPEN_READ, NULL, &parentchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s': %s\n", parentfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s': %s\n", parentfile, chd_error_string(err));
goto cleanup;
}
@@ -2099,7 +2249,7 @@ static int do_diff(int argc, char *argv[], int param)
err = chd_open(inputfile, CHD_OPEN_READ, NULL, &inputchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s': %s\n", inputfile, chd_error_string(err));
goto cleanup;
}
@@ -2107,7 +2257,7 @@ static int do_diff(int argc, char *argv[], int param)
err = chd_create(outputfile, 0, 0, chd_get_header(parentchd)->compression, parentchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error creating CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error creating CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -2115,14 +2265,14 @@ static int do_diff(int argc, char *argv[], int param)
err = chd_open(outputfile, CHD_OPEN_READWRITE, parentchd, &outputchd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening new CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error opening new CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
/* do the compression; our interface will route reads for us */
err = chdman_compress_chd(outputchd, inputchd, 0);
if (err != CHDERR_NONE)
- fprintf(stderr, "Error during compression: %s\n", error_string(err));
+ fprintf(stderr, "Error during compression: %s\n", chd_error_string(err));
cleanup:
/* close everything down */
@@ -2175,7 +2325,7 @@ static int do_setchs(int argc, char *argv[], int param)
err = chd_open(inoutfile, CHD_OPEN_READ, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s' read-only: %s\n", inoutfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s' read-only: %s\n", inoutfile, chd_error_string(err));
goto cleanup;
}
header = *chd_get_header(chd);
@@ -2192,7 +2342,7 @@ static int do_setchs(int argc, char *argv[], int param)
err = chd_set_header(inoutfile, &header);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error making CHD file writeable: %s\n", error_string(err));
+ fprintf(stderr, "Error making CHD file writeable: %s\n", chd_error_string(err));
goto cleanup;
}
}
@@ -2201,7 +2351,7 @@ static int do_setchs(int argc, char *argv[], int param)
err = chd_open(inoutfile, CHD_OPEN_READWRITE, NULL, &chd);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error opening CHD file '%s' read/write: %s\n", inoutfile, error_string(err));
+ fprintf(stderr, "Error opening CHD file '%s' read/write: %s\n", inoutfile, chd_error_string(err));
goto cleanup;
}
@@ -2219,7 +2369,7 @@ static int do_setchs(int argc, char *argv[], int param)
err = chd_set_metadata(chd, HARD_DISK_METADATA_TAG, 0, metadata, strlen(metadata) + 1);
if (err != CHDERR_NONE)
{
- fprintf(stderr, "Error writing new metadata to CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error writing new metadata to CHD file: %s\n", chd_error_string(err));
goto cleanup;
}
@@ -2241,7 +2391,7 @@ static int do_setchs(int argc, char *argv[], int param)
{
err = chd_set_header(inoutfile, &header);
if (err != CHDERR_NONE)
- fprintf(stderr, "Error writing new header to CHD file: %s\n", error_string(err));
+ fprintf(stderr, "Error writing new header to CHD file: %s\n", chd_error_string(err));
}
/* print a warning if the size is different */
diff --git a/src/tools/ldverify.c b/src/tools/ldverify.c
new file mode 100644
index 00000000000..a7a3d22be63
--- /dev/null
+++ b/src/tools/ldverify.c
@@ -0,0 +1,650 @@
+/***************************************************************************
+
+ ldverify.c
+
+ Laserdisc AVI/CHD verifier.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+#include "aviio.h"
+#include "bitmap.h"
+#include "chd.h"
+#include "vbiparse.h"
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _movie_info movie_info;
+struct _movie_info
+{
+ double framerate;
+ int numframes;
+ int width;
+ int height;
+ int samplerate;
+ int channels;
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static UINT8 *chdbuffer;
+static UINT8 chdinterlaced;
+
+static int video_first_whitefield = -1;
+static int video_saw_leadin = FALSE;
+static int video_saw_leadout = FALSE;
+static int video_last_frame = -1;
+static int video_last_chapter = -1;
+static int video_cadence = -1;
+static UINT32 video_cadence_history = 0;
+static int video_prev_whitefield = -1;
+
+static int audio_min_lsample = 32767;
+static int audio_min_rsample = 32767;
+static int audio_max_lsample = -32768;
+static int audio_max_rsample = -32768;
+static int audio_min_lsample_count = 0;
+static int audio_min_rsample_count = 0;
+static int audio_max_lsample_count = 0;
+static int audio_max_rsample_count = 0;
+static int audio_sample_count = 0;
+
+
+
+/***************************************************************************
+ AVI HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ open_avi - open an AVI file and return
+ information about it
+-------------------------------------------------*/
+
+static void *open_avi(const char *filename, movie_info *info)
+{
+ const avi_movie_info *aviinfo;
+ avi_error avierr;
+ avi_file *avi;
+
+ /* open the file */
+ avierr = avi_open(filename, &avi);
+ if (avierr != AVIERR_NONE)
+ {
+ fprintf(stderr, "Error opening AVI file: %s\n", avi_error_string(avierr));
+ return NULL;
+ }
+
+ /* extract movie info */
+ aviinfo = avi_get_movie_info(avi);
+ info->framerate = (double)aviinfo->video_timescale / (double)aviinfo->video_sampletime;
+ info->numframes = aviinfo->video_numsamples;
+ info->width = aviinfo->video_width;
+ info->height = aviinfo->video_height;
+ info->samplerate = aviinfo->audio_samplerate;
+ info->channels = aviinfo->audio_channels;
+
+ return avi;
+}
+
+
+/*-------------------------------------------------
+ read_avi - read a frame from an AVI file
+-------------------------------------------------*/
+
+static int read_avi(void *file, int frame, bitmap_t *bitmap, INT16 *lsound, INT16 *rsound, int *samples)
+{
+ const avi_movie_info *aviinfo = avi_get_movie_info(file);
+ UINT32 firstsample = ((UINT64)aviinfo->audio_samplerate * (UINT64)frame * (UINT64)aviinfo->video_sampletime + aviinfo->video_timescale - 1) / (UINT64)aviinfo->video_timescale;
+ UINT32 lastsample = ((UINT64)aviinfo->audio_samplerate * (UINT64)(frame + 1) * (UINT64)aviinfo->video_sampletime + aviinfo->video_timescale - 1) / (UINT64)aviinfo->video_timescale;
+ avi_error avierr;
+
+ /* read the frame */
+ avierr = avi_read_video_frame_yuy16(file, frame, bitmap);
+ if (avierr != AVIERR_NONE)
+ return FALSE;
+
+ /* read the samples */
+ avierr = avi_read_sound_samples(file, 0, firstsample, lastsample - firstsample, lsound);
+ avierr = avi_read_sound_samples(file, 1, firstsample, lastsample - firstsample, rsound);
+ if (avierr != AVIERR_NONE)
+ return FALSE;
+ *samples = lastsample - firstsample;
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ close_avi - close an AVI file
+-------------------------------------------------*/
+
+static void close_avi(void *file)
+{
+ avi_close(file);
+}
+
+
+
+/***************************************************************************
+ CHD HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ open_chd - open a CHD file and return
+ information about it
+-------------------------------------------------*/
+
+static void *open_chd(const char *filename, movie_info *info)
+{
+ int fps, fpsfrac, width, height, interlaced, channels, rate;
+ char metadata[256];
+ chd_error chderr;
+ chd_file *chd;
+
+ /* open the file */
+ chderr = chd_open(filename, CHD_OPEN_READ, NULL, &chd);
+ if (chderr != CHDERR_NONE)
+ {
+ fprintf(stderr, "Error opening CHD file: %s\n", chd_error_string(chderr));
+ return NULL;
+ }
+
+ /* get the metadata */
+ chderr = chd_get_metadata(chd, AV_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL);
+ if (chderr != CHDERR_NONE)
+ {
+ fprintf(stderr, "Error getting A/V metadata: %s\n", chd_error_string(chderr));
+ chd_close(chd);
+ return NULL;
+ }
+
+ /* extract the info */
+ if (sscanf(metadata, AV_METADATA_FORMAT, &fps, &fpsfrac, &width, &height, &interlaced, &channels, &rate) != 7)
+ {
+ fprintf(stderr, "Improperly formatted metadata\n");
+ chd_close(chd);
+ return NULL;
+ }
+
+ /* extract movie info */
+ info->framerate = (fps * 1000000 + fpsfrac) / 1000000.0;
+ info->numframes = chd_get_header(chd)->totalhunks;
+ info->width = width;
+ info->height = height;
+ info->samplerate = rate;
+ info->channels = channels;
+
+ /* convert to an interlaced frame */
+ chdinterlaced = interlaced;
+ if (interlaced)
+ {
+ info->framerate /= 2;
+ info->numframes = (info->numframes + 1) / 2;
+ info->height *= 2;
+ }
+
+ /* allocate a buffer */
+ chdbuffer = malloc(chd_get_header(chd)->hunkbytes);
+ if (chdbuffer == NULL)
+ {
+ fprintf(stderr, "Out of memory allocating chd buffer\n");
+ chd_close(chd);
+ return NULL;
+ }
+
+ return chd;
+}
+
+
+/*-------------------------------------------------
+ read_chd - read a frame from a CHD file
+-------------------------------------------------*/
+
+static int read_chd(void *file, int frame, bitmap_t *bitmap, INT16 *lsound, INT16 *rsound, int *samples)
+{
+ int interlace_factor = chdinterlaced ? 2 : 1;
+ int fieldnum, chnum, sampnum, x, y;
+ int channels, width, height;
+ chd_error chderr;
+ UINT8 *source;
+
+ /* loop over fields */
+ *samples = 0;
+ for (fieldnum = 0; fieldnum < interlace_factor; fieldnum++)
+ {
+ int startsamples = *samples;
+
+ /* read the frame */
+ chderr = chd_read(file, frame * interlace_factor + fieldnum, chdbuffer);
+ if (chderr != CHDERR_NONE)
+ return FALSE;
+
+ /* parse out the info */
+ channels = chdbuffer[5];
+ *samples += (chdbuffer[6] << 8) | chdbuffer[7];
+ width = (chdbuffer[8] << 8) | chdbuffer[9];
+ height = ((chdbuffer[10] << 8) | chdbuffer[11]) & 0x7fff;
+ source = chdbuffer + 12 + chdbuffer[4];
+
+ /* make sure the data makes sense */
+ if (width != bitmap->width || height != bitmap->height / interlace_factor)
+ {
+ fprintf(stderr, "Inconsistent frame width/height!\n");
+ return FALSE;
+ }
+
+ /* copy in sample data */
+ for (chnum = 0; chnum < channels; chnum++)
+ {
+ INT16 *dest = (chnum == 0) ? lsound : rsound;
+ for (sampnum = startsamples; sampnum < *samples; sampnum++)
+ {
+ INT16 sample = *source++ << 8;
+ dest[sampnum] = sample | *source++;
+ }
+ }
+
+ /* copy in the bitmap data */
+ for (y = fieldnum; y < height * interlace_factor; y += interlace_factor)
+ {
+ UINT16 *dest = BITMAP_ADDR16(bitmap, y, 0);
+ for (x = 0; x < width; x++)
+ {
+ UINT16 pixel = *source++;
+ *dest++ = pixel | (*source++ << 8);
+ }
+ }
+ }
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ close_chd - close a CHD file
+-------------------------------------------------*/
+
+static void close_chd(void *file)
+{
+ if (chdbuffer != NULL)
+ free(chdbuffer);
+ chd_close(file);
+}
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ verify_video - verify video frame
+-------------------------------------------------*/
+
+static void verify_video(int frame, bitmap_t *bitmap)
+{
+ const int fields_per_frame = 2;
+ int fieldnum;
+
+ /* loop over fields */
+ for (fieldnum = 0; fieldnum < fields_per_frame; fieldnum++)
+ {
+ int field = frame * fields_per_frame + fieldnum;
+ vbi_metadata metadata;
+
+ /* output status */
+ if (frame % 10 == 0 && fieldnum == 0)
+ printf("%6d.%d...\r", frame, fieldnum);
+
+ /* parse the VBI data */
+ vbi_parse_all(BITMAP_ADDR16(bitmap, fieldnum, 0), bitmap->rowpixels * 2, bitmap->width, 8, &metadata);
+
+ /* if we have data in both 17 and 18, it should match */
+ if (metadata.line17 != 0 && metadata.line18 != 0 && metadata.line17 != metadata.line18)
+ {
+ printf("%6d.%d: line 17 and 18 data does not match (17=%06X 18=%06X) (WARNING)\n", frame, fieldnum, metadata.line17, metadata.line18);
+ printf("%6d.%d: selected %06X based on bit confidence\n", frame, fieldnum, metadata.line1718);
+ }
+
+ /* is this a lead-in code? */
+ if (metadata.line1718 == 0x88ffff)
+ {
+ /* if we haven't seen lead-in yet, detect it */
+ if (!video_saw_leadin)
+ {
+ video_saw_leadin = TRUE;
+ printf("%6d.%d: lead-in code detected\n", frame, fieldnum);
+ }
+
+ /* if we've previously seen chapters/frames, that's weird */
+ if (video_last_frame != -1 || video_last_chapter != -1)
+ printf("%6d.%d: lead-in code detected after frame/chapter data (WARNING)\n", frame, fieldnum);
+ }
+
+ /* is this a lead-out code? */
+ if (metadata.line1718 == 0x80eeee)
+ {
+ /* if we haven't seen lead-in yet, detect it */
+ if (!video_saw_leadout)
+ {
+ video_saw_leadout = TRUE;
+ printf("%6d.%d: lead-out code detected\n", frame, fieldnum);
+ if (video_last_frame != -1)
+ printf("%6d.%d: final frame number was %d\n", frame, fieldnum, video_last_frame);
+ else
+ printf("%6d.%d: never detected any frame numbers (ERROR)\n", frame, fieldnum);
+ }
+
+ /* if we've previously seen chapters/frames, that's weird */
+ if (video_last_frame == -1)
+ printf("%6d.%d: lead-out code detected with no frames detected beforehand (WARNING)\n", frame, fieldnum);
+ }
+
+ /* is this a frame code? */
+ if ((metadata.line1718 & 0xf80000) == 0xf80000)
+ {
+ int framenum = ((metadata.line1718 >> 0) & 15) * 1 + ((metadata.line1718 >> 4) & 15) * 10 + ((metadata.line1718 >> 8) & 15) * 100 + ((metadata.line1718 >> 12) & 15) * 1000 + ((metadata.line1718 >> 16) & 7) * 10000;
+
+ /* did we see any leadin? */
+ if (!video_saw_leadin)
+ {
+ printf("%6d.%d: detected frame number but never saw any lead-in (WARNING)\n", frame, fieldnum);
+ video_saw_leadin = TRUE;
+ }
+
+ /* if this is the first frame, make sure it's 1 */
+ if (video_last_frame == -1)
+ {
+ if (framenum == 1)
+ printf("%6d.%d: detected frame 1\n", frame, fieldnum);
+ else
+ printf("%6d.%d: first frame number is not 1 (%d) (ERROR)\n", frame, fieldnum, framenum);
+ }
+
+ /* print an update every 1000 frames */
+ if (framenum % 1000 == 0)
+ printf("%6d.%d: detected frame %d\n", frame, fieldnum, framenum);
+
+ /* if this frame is not consecutive, it's an error */
+ if (video_last_frame != -1 && framenum != video_last_frame + 1)
+ printf("%6d.%d: gap in frame number sequence (%d->%d) (ERROR)\n", frame, fieldnum, video_last_frame, framenum);
+
+ /* remember the frame number */
+ video_last_frame = framenum;
+ }
+
+ /* is the whiteflag set? */
+ if (metadata.white)
+ {
+ /* if this is the first white flag we see, count it */
+ if (video_first_whitefield == -1)
+ {
+ video_first_whitefield = field;
+ printf("%6d.%d: first white flag seen\n", frame, fieldnum);
+ }
+
+ /* if we've seen frames, but we're not yet to the lead-out, check the cadence */
+ if (video_last_frame != -1 && !video_saw_leadout)
+ {
+ /* make sure we have a proper history */
+ if (video_prev_whitefield != -1)
+ video_cadence_history = (video_cadence_history << 4) | ((field - video_prev_whitefield) & 0x0f);
+ video_prev_whitefield = field;
+
+ /* if we don't know our cadence yet, determine it */
+ if (video_cadence == -1 && (video_cadence_history & 0xf00) != 0)
+ {
+ if ((video_cadence_history & 0xfff) == 0x222)
+ {
+ printf("%6d.%d: detected 2:2 cadence\n", frame, fieldnum);
+ video_cadence = 4;
+ }
+ else if ((video_cadence_history & 0xfff) == 0x323)
+ {
+ printf("%6d.%d: detected 3:2 cadence\n", frame, fieldnum);
+ video_cadence = 5;
+ }
+ else if ((video_cadence_history & 0xfff) == 0x232)
+ {
+ printf("%6d.%d: detected 2:3 cadence\n", frame, fieldnum);
+ video_cadence = 5;
+ }
+ else
+ {
+ printf("%6d.%d: unknown cadence (history %d:%d:%d) (WARNING)\n", frame, fieldnum,
+ (video_cadence_history >> 8) & 15, (video_cadence_history >> 4) & 15, video_cadence_history & 15);
+ }
+ }
+
+ /* if we know our cadence, make sure we stick to it */
+ if (video_cadence != -1)
+ {
+ if (video_cadence == 4 && (video_cadence_history & 0xfff) != 0x222)
+ {
+ printf("%6d.%d: missed cadence (history %d:%d:%d) (WARNING)\n", frame, fieldnum,
+ (video_cadence_history >> 8) & 15, (video_cadence_history >> 4) & 15, video_cadence_history & 15);
+ video_cadence = -1;
+ video_cadence_history = 0;
+ }
+ else if (video_cadence == 5 && (video_cadence_history & 0xfff) != 0x323 && (video_cadence_history & 0xfff) != 0x232)
+ {
+ printf("%6d.%d: missed cadence (history %d:%d:%d) (WARNING)\n", frame, fieldnum,
+ (video_cadence_history >> 8) & 15, (video_cadence_history >> 4) & 15, video_cadence_history & 15);
+ video_cadence = -1;
+ video_cadence_history = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ verify_video_final - final verification
+-------------------------------------------------*/
+
+static void verify_video_final(int frame, bitmap_t *bitmap)
+{
+ int fields_per_frame = (bitmap->height >= 288) ? 2 : 1;
+ int field = frame * fields_per_frame;
+
+ /* did we ever see any lead-out? */
+ if (video_saw_leadin && !video_saw_leadout)
+ printf("Track %6d.%d: detected lead-in but never saw any lead-out (WARNING)\n", field / fields_per_frame, 0);
+}
+
+
+/*-------------------------------------------------
+ verify_audio - verify audio data
+-------------------------------------------------*/
+
+static void verify_audio(const INT16 *lsound, const INT16 *rsound, int samples)
+{
+ int sampnum;
+
+ /* count the overall samples */
+ audio_sample_count += samples;
+
+ /* iterate over samples, tracking min/max */
+ for (sampnum = 0; sampnum < samples; sampnum++)
+ {
+ /* did we hit a minimum on the left? */
+ if (lsound[sampnum] < audio_min_lsample)
+ {
+ audio_min_lsample = lsound[sampnum];
+ audio_min_lsample_count = 1;
+ }
+ else if (lsound[sampnum] == audio_min_lsample)
+ audio_min_lsample_count++;
+
+ /* did we hit a maximum on the left? */
+ if (lsound[sampnum] > audio_max_lsample)
+ {
+ audio_max_lsample = lsound[sampnum];
+ audio_max_lsample_count = 1;
+ }
+ else if (lsound[sampnum] == audio_max_lsample)
+ audio_max_lsample_count++;
+
+ /* did we hit a minimum on the right? */
+ if (rsound[sampnum] < audio_min_rsample)
+ {
+ audio_min_rsample = rsound[sampnum];
+ audio_min_rsample_count = 1;
+ }
+ else if (rsound[sampnum] == audio_min_rsample)
+ audio_min_rsample_count++;
+
+ /* did we hit a maximum on the right? */
+ if (rsound[sampnum] > audio_max_rsample)
+ {
+ audio_max_rsample = rsound[sampnum];
+ audio_max_rsample_count = 1;
+ }
+ else if (rsound[sampnum] == audio_max_rsample)
+ audio_max_rsample_count++;
+ }
+}
+
+
+/*-------------------------------------------------
+ verify_audio_final - final verification
+-------------------------------------------------*/
+
+static void verify_audio_final(void)
+{
+ printf("Audio summary:\n");
+ printf(" Channel 0 minimum: %6d (with %9d/%9d samples at minimum)\n", audio_min_lsample, audio_min_lsample_count, audio_sample_count);
+ printf(" Channel 0 maximum: %6d (with %9d/%9d samples at maximum)\n", audio_max_lsample, audio_max_lsample_count, audio_sample_count);
+ printf(" Channel 1 minimum: %6d (with %9d/%9d samples at minimum)\n", audio_min_rsample, audio_min_rsample_count, audio_sample_count);
+ printf(" Channel 1 maximum: %6d (with %9d/%9d samples at maximum)\n", audio_max_rsample, audio_max_rsample_count, audio_sample_count);
+}
+
+
+/*-------------------------------------------------
+ usage - display program usage
+-------------------------------------------------*/
+
+static int usage(void)
+{
+ fprintf(stderr, "Usage: \n");
+ fprintf(stderr, " ldverify [avifile.avi|chdfile.chd]\n");
+ return 1;
+}
+
+
+/*-------------------------------------------------
+ main - main entry point
+-------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+ movie_info info = { 0 };
+ INT16 *lsound, *rsound;
+ const char *srcfile;
+ bitmap_t *bitmap;
+ int srcfilelen;
+ int samples = 0;
+ void *file;
+ int isavi;
+ int frame;
+
+ /* verify arguments */
+ if (argc < 2)
+ return usage();
+ srcfile = argv[1];
+
+ /* check extension of file */
+ srcfilelen = strlen(srcfile);
+ if (srcfilelen < 4)
+ return usage();
+ if (tolower(srcfile[srcfilelen-3]) == 'a' && tolower(srcfile[srcfilelen-2]) == 'v' && tolower(srcfile[srcfilelen-1]) == 'i')
+ isavi = TRUE;
+ else if (tolower(srcfile[srcfilelen-3]) == 'c' && tolower(srcfile[srcfilelen-2]) == 'h' && tolower(srcfile[srcfilelen-1]) == 'd')
+ isavi = FALSE;
+ else
+ return usage();
+
+ /* open the file */
+ printf("Processing file: %s\n", srcfile);
+ file = isavi ? open_avi(srcfile, &info) : open_chd(srcfile, &info);
+ if (file == NULL)
+ {
+ fprintf(stderr, "Unable to open file '%s'\n", srcfile);
+ return 1;
+ }
+
+ /* comment on the video dimensions */
+ printf("Video dimensions: %dx%d\n", info.width, info.height);
+ if (info.width != 720)
+ printf("WARNING: Unexpected video width (should be 720)\n");
+ if (info.height != 524)
+ printf("WARNING: Unexpected video height (should be 262 or 524)\n");
+
+ /* comment on the video frame rate */
+ printf("Video frame rate: %.2fHz\n", info.framerate);
+ if ((int)(info.framerate * 100.0 + 0.5) != 2997)
+ printf("WARNING: Unexpected frame rate (should be 29.97Hz)\n");
+
+ /* comment on the sample rate */
+ printf("Sample rate: %dHz\n", info.samplerate);
+ if (info.samplerate != 48000)
+ printf("WARNING: Unexpected sampele rate (should be 48000Hz)\n");
+
+ /* allocate a bitmap */
+ bitmap = bitmap_alloc(info.width, info.height, BITMAP_FORMAT_YUY16);
+ if (bitmap == NULL)
+ {
+ fprintf(stderr, "Out of memory creating %dx%d bitmap\n", info.width, info.height);
+ return 1;
+ }
+
+ /* allocate sound buffers */
+ lsound = malloc(info.samplerate * sizeof(*lsound));
+ rsound = malloc(info.samplerate * sizeof(*rsound));
+ if (lsound == NULL || rsound == NULL)
+ {
+ fprintf(stderr, "Out of memory allocating sound buffers of %d bytes\n", info.samplerate * sizeof(*rsound));
+ return 1;
+ }
+
+ /* loop over frames */
+ frame = 0;
+ while (isavi ? read_avi(file, frame, bitmap, lsound, rsound, &samples) : read_chd(file, frame, bitmap, lsound, rsound, &samples))
+ {
+ verify_video(frame, bitmap);
+ verify_audio(lsound, rsound, samples);
+ frame++;
+ }
+
+ /* close the files */
+ isavi ? close_avi(file) : close_chd(file);
+
+ /* final output */
+ verify_video_final(frame, bitmap);
+ verify_audio_final();
+
+ /* free memory */
+ bitmap_free(bitmap);
+ free(lsound);
+ free(rsound);
+
+ return 0;
+}
diff --git a/src/tools/makemeta.c b/src/tools/makemeta.c
deleted file mode 100644
index 7cfb220f3f8..00000000000
--- a/src/tools/makemeta.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/***************************************************************************
-
- makemeta.c
-
- Laserdisc metadata generator.
-
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
-
-****************************************************************************
-
- Metadata format (12 bytes/field):
-
- Offset Description
- ------ ------------------------------------------
- 0 = version (currently 2)
- 1 = internal flags:
- bit 0 = previous field is the same frame
- bit 1 = next field is the same frame
- 2 = white flag (from line 11)
- 3-5 = line 16 Philips code
- 6-8 = line 17 Philips code
- 9-11 = line 18 Philips code
-
-***************************************************************************/
-
-#include <stdio.h>
-#include <ctype.h>
-#include "aviio.h"
-#include "bitmap.h"
-#include "vbiparse.h"
-
-
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#define INSERT_FRAME_CODE 0xff000000
-#define INSERT_FRAME_CODE_INC 0xff000001
-#define INVALID_CODE 0xffffffff
-
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-typedef struct _pattern_data pattern_data;
-struct _pattern_data
-{
- pattern_data *next;
- UINT32 line16, line17, line18;
- int white;
-};
-
-
-
-/***************************************************************************
- IMPLEMENTATION
-***************************************************************************/
-
-/*-------------------------------------------------
- output_meta - output a line of metadata
--------------------------------------------------*/
-
-static void output_meta(UINT8 flags, UINT8 white, UINT32 line16, UINT32 line17, UINT32 line18, UINT32 framenum, UINT32 chapternum)
-{
- /* start with the raw metadata, followed by a comment */
- printf("02%02X%02X%06X%06X%06X ; ",
- flags, white, line16, line17, line18);
-
- /* separate comments for leadin/leadout */
- if (line17 == 0x88ffff)
- printf("leadin\n");
- else if (line17 == 0x80eeee)
- printf("leadout\n");
-
- /* otherwise, display the frame and chapter, and indicate white flag/stop code */
- else
- {
- printf("frame %05x ch %02x", framenum, chapternum);
- if (white)
- printf(" (white)");
- if (line16 == 0x82cfff)
- printf(" (stop)");
- printf("\n");
- }
-}
-
-
-/*-------------------------------------------------
- generate_from_avi - generate the data from
- an AVI file
--------------------------------------------------*/
-
-static int generate_from_avi(const char *aviname)
-{
- UINT32 line16 = 0, line17 = 0, line18 = 0, framenum = 0, chapternum = 0;
- const avi_movie_info *info;
- bitmap_t *bitmap;
- avi_error avierr;
- avi_file *avi;
- int white = 0;
- int frame;
-
- /* open the file */
- avierr = avi_open(aviname, &avi);
- if (avierr != AVIERR_NONE)
- {
- fprintf(stderr, "Error opening AVI file: %s\n", avi_error_string(avierr));
- return 1;
- }
-
- /* extract movie info */
- info = avi_get_movie_info(avi);
- fprintf(stderr, "%dx%d - %d frames total\n", info->video_width, info->video_height, info->video_numsamples);
- if (info->video_height < 22*2)
- {
- fprintf(stderr, "Unknown VBI capture format: expected at least 44 rows\n");
- return 1;
- }
-
- /* allocate a bitmap to hold it */
- bitmap = bitmap_alloc(info->video_width, info->video_height, BITMAP_FORMAT_YUY16);
- if (bitmap == NULL)
- {
- fprintf(stderr, "Out of memory allocating %dx%d bitmap\n", info->video_width, info->video_height);
- return 1;
- }
-
- /* loop over frames */
- for (frame = 0; frame < info->video_numsamples; frame++)
- {
- int field;
- UINT8 bits[24];
-
- /* read the frame */
- avierr = avi_read_video_frame_yuy16(avi, frame, bitmap);
- if (avierr != AVIERR_NONE)
- {
- fprintf(stderr, "Error reading AVI frame %d: %s\n", frame, avi_error_string(avierr));
- break;
- }
-
- /* loop over two fields */
- for (field = 0; field < 2; field++)
- {
- int prevwhite = white;
- int i;
-
- /* line 11 contains the white flag */
- white = vbi_parse_white_flag(BITMAP_ADDR16(bitmap, 11*2 + field, 0), bitmap->width, 8);
-
- /* output metadata for *previous* field */
- if (frame > 0 || field > 0)
- {
- int flags = 0;
-
- if (!prevwhite) flags |= 0x01;
- if (!white) flags |= 0x02;
- output_meta(flags, prevwhite, line16, line17, line18, framenum, chapternum);
- }
-
- /* line 16 contains stop code and other interesting bits */
- line16 = 0;
- if (vbi_parse_manchester_code(BITMAP_ADDR16(bitmap, 16*2 + field, 0), bitmap->width, 8, 24, bits) == 24)
- for (i = 0; i < 24; i++)
- line16 = (line16 << 1) | bits[i];
-
- /* line 17 and 18 contain frame/chapter/lead in/out encodings */
- line17 = 0;
- if (vbi_parse_manchester_code(BITMAP_ADDR16(bitmap, 17*2 + field, 0), bitmap->width, 8, 24, bits) == 24)
- for (i = 0; i < 24; i++)
- line17 = (line17 << 1) | bits[i];
-
- line18 = 0;
- if (vbi_parse_manchester_code(BITMAP_ADDR16(bitmap, 18*2 + field, 0), bitmap->width, 8, 24, bits) == 24)
- for (i = 0; i < 24; i++)
- line18 = (line18 << 1) | bits[i];
-
- /* the two lines must match */
-// if (line17 != 0 && line18 != 0 && line17 != line18)
-// line17 = line18 = 0;
-
- /* is this a frame number? */
- if ((line17 & 0xf00000) == 0xf00000)
- framenum = line17 & 0x7ffff;
- if ((line17 & 0xf00fff) == 0x800ddd)
- chapternum = (line17 >> 12) & 0x7f;
- }
- }
-
- /* output metadata for *previous* field */
- {
- int flags = 0;
-
- if (!white) flags |= 0x01;
- output_meta(flags, white, line16, line17, line18, framenum, chapternum);
- }
-
- bitmap_free(bitmap);
- return 0;
-}
-
-
-/*-------------------------------------------------
- parse_philips_code - parse a single Philips
- code from a string, stopping at the given
- end characters
--------------------------------------------------*/
-
-static UINT32 parse_philips_code(char **argptr, const char *endchars)
-{
- char *arg = *argptr;
- UINT32 value = 0;
-
- /* look for special chars first */
- if (*arg == '+')
- {
- *argptr = arg + 1;
- return INSERT_FRAME_CODE_INC;
- }
- else if (*arg == '@')
- {
- *argptr = arg + 1;
- return INSERT_FRAME_CODE;
- }
-
- /* parse the rest as hex digits */
- for ( ; *arg != 0 && strchr(endchars, *arg) == NULL; arg++)
- {
- if (*arg >= '0' && *arg <= '9')
- value = (value << 4) + (*arg - '0');
- else if (*arg >= 'a' && *arg <= 'f')
- value = (value << 4) + 10 + (*arg - 'a');
- else if (*arg >= 'A' && *arg <= 'F')
- value = (value << 4) + 10 + (*arg - 'A');
- else
- return INVALID_CODE;
- }
-
- /* if we're too big, we're invalid */
- if (value > 0xffffff)
- return INVALID_CODE;
-
- *argptr = arg;
- return value;
-}
-
-
-/*-------------------------------------------------
- parse_pattern - parse a pattern into a series
- of pattern_data structs
--------------------------------------------------*/
-
-static pattern_data *parse_pattern(char *arg, int *countptr)
-{
- pattern_data *head = NULL;
- pattern_data **tailptr = &head;
- int count = 0;
-
- /* first parse the count */
- for ( ; *arg != 0 && *arg != '*'; arg++)
- {
- if (!isdigit(*arg))
- return NULL;
- count = count * 10 + (*arg - '0');
- }
- if (*arg == 0)
- return NULL;
- arg++;
- *countptr = count;
-
- /* loop until we hit the end */
- while (*arg != 0)
- {
- pattern_data *pat;
-
- /* allocate a new structure */
- pat = malloc(sizeof(*pat));
- if (pat == NULL)
- return NULL;
- memset(pat, 0, sizeof(*pat));
-
- /* bang at the beginning means white flag */
- if (*arg == '!')
- {
- arg++;
- pat->white = 1;
- }
-
- /* parse line16 until we hit a period or comma */
- pat->line16 = parse_philips_code(&arg, ".,");
- if (pat->line16 == INVALID_CODE)
- return NULL;
- if (*arg != '.' && *arg != ',' && *arg != 0)
- return NULL;
- if (*arg == '.')
- arg++;
-
- /* parse line17 until we hit a period */
- pat->line17 = parse_philips_code(&arg, ".,");
- if (pat->line17 == INVALID_CODE)
- return NULL;
- if (*arg != '.' && *arg != ',' && *arg != 0)
- return NULL;
- if (*arg == '.')
- arg++;
-
- /* parse line18 until we hit a comma */
- pat->line18 = parse_philips_code(&arg, ",");
- if (pat->line18 == INVALID_CODE)
- return NULL;
- if (*arg != ',' && *arg != 0)
- return NULL;
- if (*arg == ',')
- arg++;
-
- /* append to the end */
- *tailptr = pat;
- tailptr = &pat->next;
- }
-
- return head;
-}
-
-
-/*-------------------------------------------------
- generate_from_pattern - generate metadata
- from a pattern
--------------------------------------------------*/
-
-static int generate_from_pattern(pattern_data *pattern, int patcount)
-{
- pattern_data *curpat = pattern;
- int framenum = 0, bcdframenum = 0;
-
- /* loop until we exceed the pattern frame count */
- while (1)
- {
- UINT32 line16, line17, line18;
- int flags = 0;
-
- /* handle special codes for line 16 */
- line16 = curpat->line16;
- if (line16 == INSERT_FRAME_CODE_INC)
- {
- framenum++;
- bcdframenum = (((framenum / 10000) % 10) << 16) | (((framenum / 1000) % 10) << 12) | (((framenum / 100) % 10) << 8) | (((framenum / 10) % 10) << 4) | (framenum % 10);
- }
- if (line16 == INSERT_FRAME_CODE || line16 == INSERT_FRAME_CODE_INC)
- line16 = 0xf80000 | bcdframenum;
-
- /* handle special codes for line 17 */
- line17 = curpat->line17;
- if (line17 == INSERT_FRAME_CODE_INC)
- {
- framenum++;
- bcdframenum = (((framenum / 10000) % 10) << 16) | (((framenum / 1000) % 10) << 12) | (((framenum / 100) % 10) << 8) | (((framenum / 10) % 10) << 4) | (framenum % 10);
- }
- if (line17 == INSERT_FRAME_CODE || line17 == INSERT_FRAME_CODE_INC)
- line17 = 0xf80000 | bcdframenum;
-
- /* handle special codes for line 18 */
- line18 = curpat->line18;
- if (line18 == INSERT_FRAME_CODE_INC)
- {
- framenum++;
- bcdframenum = (((framenum / 10000) % 10) << 16) | (((framenum / 1000) % 10) << 12) | (((framenum / 100) % 10) << 8) | (((framenum / 10) % 10) << 4) | (framenum % 10);
- }
- if (line18 == INSERT_FRAME_CODE || line18 == INSERT_FRAME_CODE_INC)
- line18 = 0xf80000 | bcdframenum;
-
- /* bail if we passed the end */
- if (framenum > patcount)
- break;
-
- /* if we don't have a white flag, the previous frame must match us */
- if (!curpat->white) flags |= 0x01;
-
- /* advance to the next pattern piece */
- curpat = curpat->next;
- if (curpat == NULL)
- curpat = pattern;
-
- /* if the new field doesn't have a white flag, it must match our current frame */
- if (!curpat->white) flags |= 0x02;
-
- /* output the result */
- output_meta(flags, curpat->white, line16, line17, line18, bcdframenum, 0);
- }
- return 0;
-}
-
-
-/*-------------------------------------------------
- usage - display program usage
--------------------------------------------------*/
-
-static int usage(void)
-{
- fprintf(stderr, "Usage: \n");
- fprintf(stderr, " makemeta [avifile.avi] [<option> [<option> [...]]]\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "Options:\n");
- fprintf(stderr, " -leadin <count> -- prepend <count> fields of leadin codes\n");
- fprintf(stderr, " -leadout <count> -- append <count> fields of leadout codes\n");
- fprintf(stderr, " -pattern <frames>*<pat0>[,<pat1>[,...]] -- repeat Philips code pattern\n");
- fprintf(stderr, " in place of AVI. <pat0>, <pat1>, etc. are of the form: \n");
- fprintf(stderr, " [!]A[.B[.C]][,<pattern>] where A,B,C are either hexadecimal\n");
- fprintf(stderr, " values one of these special codes:\n");
- fprintf(stderr, " ! -- at the start of a pattern sets the white flag\n");
- fprintf(stderr, " + -- increments frame number and inserts frame code\n");
- fprintf(stderr, " @ -- inserts repeat of most recent frame code\n");
- fprintf(stderr, " non-present values are assumed to be 0\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "Examples:\n");
- fprintf(stderr, " makemeta -pattern 54000*!8da01e.+.@,8da01e,!8da01e.+.@,8da01e,8da01e\n");
- fprintf(stderr, " generates the following pattern of Philips codes:\n");
- fprintf(stderr, " 8da01e f80001 f80001 (white)\n");
- fprintf(stderr, " 8da01e 000000 000000\n");
- fprintf(stderr, " 8da01e f80002 f80002 (white)\n");
- fprintf(stderr, " 8da01e 000000 000000\n");
- fprintf(stderr, " 8da01e 000000 000000\n");
- fprintf(stderr, " <repeat until frame is 54000>\n");
- return 1;
-}
-
-
-/*-------------------------------------------------
- main - main entry point
--------------------------------------------------*/
-
-int main(int argc, char *argv[])
-{
- int leadin = 0, leadout = 0;
- const char *avifile = NULL;
- pattern_data *pattern = NULL;
- int patcount = 0;
- int arg;
- int i;
-
- /* iterate over arguments */
- for (arg = 1; arg < argc; arg++)
- {
- /* assume anything without a - is a filename */
- if (argv[arg][0] != '-')
- {
- if (avifile != NULL || pattern != NULL)
- return usage();
- avifile = argv[arg];
- }
-
- /* look for options */
- else if (strcmp(argv[arg], "-leadin") == 0)
- {
- if (++arg >= argc)
- return usage();
- leadin = atoi(argv[arg]);
- }
- else if (strcmp(argv[arg], "-leadout") == 0)
- {
- if (++arg >= argc)
- return usage();
- leadout = atoi(argv[arg]);
- }
- else if (strcmp(argv[arg], "-pattern") == 0)
- {
- if (avifile != NULL || pattern != NULL)
- return usage();
- if (++arg >= argc)
- return usage();
- pattern = parse_pattern(argv[arg], &patcount);
- if (pattern == NULL)
- return usage();
- }
- }
-
- /* must have an AVI file or a pattern */
- if (avifile == NULL && pattern == NULL)
- return usage();
-
- /* output header and leadin */
- printf("chdmeta 12\n");
- for (i = 0; i < leadin; i++)
- {
- int flags = (i == 0) ? 0x02 : (i == leadin - 1) ? 0x01 : 0x03;
- printf("02%02X%02X00000088FFFF88FFFF\n", flags, (i % 2));
- }
-
- /* if we got a file, output it */
- if (avifile != NULL)
- generate_from_avi(avifile);
- else if (pattern != NULL)
- generate_from_pattern(pattern, patcount);
-
- /* output leadout */
- for (i = 0; i < leadout; i++)
- {
- int flags = (i == 0) ? 0x02 : (i == leadout - 1) ? 0x01 : 0x03;
- printf("02%02X%02X00000080EEEE80EEEE\n", flags, (i % 2));
- }
-
- return 0;
-}
diff --git a/src/tools/tools.mak b/src/tools/tools.mak
index 9e03fbfcbc7..c9f73eac95a 100644
--- a/src/tools/tools.mak
+++ b/src/tools/tools.mak
@@ -26,7 +26,7 @@ TOOLS += \
romcmp$(EXE) \
chdman$(EXE) \
jedutil$(EXE) \
- makemeta$(EXE) \
+ ldverify$(EXE) \
regrep$(EXE) \
srcclean$(EXE) \
src2html$(EXE) \
@@ -74,13 +74,13 @@ jedutil$(EXE): $(JEDUTILOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB) $(EXPAT)
#-------------------------------------------------
-# makemeta
+# ldverify
#-------------------------------------------------
-MAKEMETAOBJS = \
- $(TOOLSOBJ)/makemeta.o \
+LDVERIFYOBJS = \
+ $(TOOLSOBJ)/ldverify.o \
-makemeta$(EXE): $(MAKEMETAOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB) $(EXPAT)
+ldverify$(EXE): $(LDVERIFYOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB) $(EXPAT)
@echo Linking $@...
$(LD) $(LDFLAGS) $^ $(LIBS) -o $@