Binary files xmame-0.78.1/mach3.png and xmame-laser/mach3.png differ diff --exclude-from=if --new-file -u -r xmame-0.78.1/makefile.unix xmame-laser/makefile.unix --- xmame-0.78.1/makefile.unix Fri Jan 9 01:54:22 2004 +++ xmame-laser/makefile.unix Mon Jan 19 21:53:09 2004 @@ -105,7 +105,7 @@ # If you want to use whatever CFLAGS are currently set in your # environment, then comment this out. -CFLAGS = +#CFLAGS = ########################################################################### @@ -114,15 +114,15 @@ ########################################################################### # gcc on x86 -CFLAGS = -O -Wall -Wno-unused +#CFLAGS = -O -Wall -Wno-unused # gcc on x86 with some optimizations # CFLAGS = -O2 -Wall -Wno-unused -mcpu=i686 -fomit-frame-pointer \ # -fstrict-aliasing -fstrength-reduce -ffast-math # gcc on Linux/PowerPC -# CFLAGS = -O2 -Wall -Wno-unused -funroll-loops -fstrength-reduce \ -# -fomit-frame-pointer -ffast-math -fsigned-char + CFLAGS = -O2 -Wall -Wno-unused -funroll-loops -fstrength-reduce \ + -fomit-frame-pointer -ffast-math -fsigned-char # gcc on OpenStep/Intel # CFLAGS = -O2 -Wall -Wno-unused -finline-functions -ffast-math \ @@ -258,7 +258,7 @@ # CFLAGS += -march=k6-3 # CFLAGS += -march=athlon # CFLAGS += -march=athlon-tbird - # CFLAGS += -march=athlon-xp + CFLAGS += -march=athlon-xp # CFLAGS += -march=athlon-mp # CFLAGS += -march=athlon-4 @@ -427,6 +427,8 @@ # UnixWare7 requires -lsocket. # LIBS = -L/usr/X11R6/lib -L/usr/local/lib # INCLUDES = -I/usr/X11R6/include -I/usr/local/include +INCLUDES = -I/usr/local/include/mpeg2dec +LIBS = -lmpeg2 -lvo -lFLAC ########################################################################### @@ -563,7 +565,7 @@ # If supported, you can use the standard joystick driver. Note that this # can work on non-x86 platforms. I just haven't come up with a good # replacement name for it. -# JOY_I386 = 1 +JOY_I386 = 1 # Linux FM-TOWNS game pad joystick emulation support. Thanks to Osamu # Kurati. @@ -596,7 +598,7 @@ # Choose any additonal sound drivers you want to include, besides the # native sound driver for your system. -# SOUND_ESOUND = 1 +SOUND_ESOUND = 1 # SOUND_ALSA = 1 # SOUND_ARTS_TEIRA = 1 # SOUND_ARTS_SMOTEK = 1 @@ -649,11 +651,11 @@ X11_MITSHM = 1 # Use Xv extension for hardware scaling. -X11_XV = 1 +# X11_XV = 1 # Enable XFree86 DGA. This also causes "make install" to set the suid bit # on the executable. -# X11_DGA = 1 + X11_DGA = 1 # Work around a bug in the XFree86 tdfx driver that prevents the original # mode from being restored when leaving DGA2 mode. diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/artwork.c xmame-laser/src/artwork.c --- xmame-0.78.1/src/artwork.c Fri Dec 26 23:29:06 2003 +++ xmame-laser/src/artwork.c Mon Jan 19 23:52:39 2004 @@ -306,6 +306,7 @@ #include "vidhrdw/vector.h" #include #include +#include "vidhrdw/laserdsk.h" /*************************************************************************** @@ -334,7 +335,8 @@ LAYER_MARQUEE, LAYER_PANEL, LAYER_SIDE, - LAYER_FLYER + LAYER_FLYER, + LAYER_VIDEO }; /* UI transparency hack */ @@ -352,39 +354,6 @@ ***************************************************************************/ -struct artwork_piece -{ - /* linkage */ - struct artwork_piece * next; - - /* raw data from the .art file */ - UINT8 layer; - UINT8 has_alpha; - int priority; - float alpha; - float brightness; - float top; - float left; - float bottom; - float right; - char * tag; - char * filename; - char * alpha_filename; - - /* bitmaps */ - struct mame_bitmap * rawbitmap; - struct mame_bitmap * prebitmap; - struct mame_bitmap * yrgbbitmap; - UINT32 * scanlinehint; - UINT8 blendflags; - - /* derived/dynamic data */ - int intersects_game; - int visible; - struct rectangle bounds; -}; - - /*************************************************************************** @@ -397,11 +366,11 @@ static UINT32 transparent_color; static struct artwork_piece *artwork_list; -static int num_underlays, num_overlays, num_bezels; +static int num_underlays, num_overlays, num_bezels, num_videos; static int num_pieces; -static struct mame_bitmap *underlay, *overlay, *overlay_yrgb, *bezel, *final; -static struct rectangle underlay_invalid, overlay_invalid, bezel_invalid; +static struct mame_bitmap *underlay, *overlay, *overlay_yrgb, *bezel, *final, *video; +static struct rectangle underlay_invalid, overlay_invalid, bezel_invalid, video_invalid; static struct rectangle gamerect, screenrect; static int gamescale; @@ -416,6 +385,9 @@ static const struct overlay_piece *overlay_list; +/* laserdisk tag */ +static const char *TAG_LASERDISK = "[laserdiscvideo]"; +static struct artwork_piece *video_piece; /*************************************************************************** @@ -429,7 +401,6 @@ static int compute_rgb_components(int depth, UINT32 rgb_components[3], UINT32 rgb32_components[3]); static int load_bitmap(const char *gamename, struct artwork_piece *piece); static int load_alpha_bitmap(const char *gamename, struct artwork_piece *piece, const struct png_info *original); -static int scale_bitmap(struct artwork_piece *piece, int newwidth, int newheight); static void trim_bitmap(struct artwork_piece *piece); static int parse_art_file(mame_file *file); static int validate_pieces(void); @@ -437,6 +408,7 @@ static void update_palette_lookup(struct mame_display *display); static int update_layers(void); static void render_game_bitmap(struct mame_bitmap *bitmap, const rgb_t *palette, struct mame_display *display); +static void render_game_bitmap_video(struct mame_bitmap *bitmap, const rgb_t *palette, struct mame_display *display); static void render_game_bitmap_underlay(struct mame_bitmap *bitmap, const rgb_t *palette, struct mame_display *display); static void render_game_bitmap_overlay(struct mame_bitmap *bitmap, const rgb_t *palette, struct mame_display *display); static void render_game_bitmap_underlay_overlay(struct mame_bitmap *bitmap, const rgb_t *palette, struct mame_display *display); @@ -558,6 +530,69 @@ } +/*------------------------------------------------- + blend the video with the game using the bottom 2 bits of blue as the blend + TODO: This is for firefox but should be made generic +-------------------------------------------------*/ + +INLINE UINT32 video_blend_and_clamp_firefox(UINT32 game, UINT32 underpix) +{ + UINT8 r,g,b; + UINT8 blend = RGB_BLUE(game) & 0x3; + + switch(blend) + { + case 0: return underpix; + case 1: + r = ((RGB_RED(game) << 1) + RGB_RED(underpix)) >> 1; + g = ((RGB_GREEN(game) << 1) + RGB_GREEN(underpix)) >> 1; + b = ((RGB_BLUE(game) << 1) + RGB_BLUE(underpix)) >> 1; + return MAKE_ARGB(0xff, r, g, b); + case 2: + r = ((RGB_RED(underpix) << 1) + RGB_RED(game)) >> 1; + g = ((RGB_GREEN(underpix) << 1) + RGB_GREEN(game)) >> 1; + b = ((RGB_BLUE(underpix) << 1) + RGB_BLUE(game)) >> 1; + return MAKE_ARGB(0xff, r, g, b); + default: + return game; + } +} + + +/*------------------------------------------------- + blend the video with the game any black area of the game is replaced with + the video +-------------------------------------------------*/ + +INLINE UINT32 video_blend_and_clamp_mach3(UINT32 game, UINT32 underpix) +{ + if(game) + return game; + else + return underpix; +} +struct rectangle *get_video_invalid() +{ + return(&video_invalid); +} + +struct rectangle *get_underlay_invalid() +{ + return(&underlay_invalid); +} + +struct artwork_piece * get_laser_disc_artwork_piece() +{ + struct artwork_piece *p = artwork_list; + while(p) + { + if(!strcmp(p->tag, TAG_LASERDISK)) + return(p); + else + p = p->next; + } + return(NULL); +} /*------------------------------------------------- blend_over - blend two pixels with overlay @@ -670,6 +705,7 @@ params->depth = 32; /* allocate memory for the bitmaps */ + video = auto_bitmap_alloc_depth(params->width, params->height, 32); underlay = auto_bitmap_alloc_depth(params->width, params->height, 32); overlay = auto_bitmap_alloc_depth(params->width, params->height, 32); overlay_yrgb = auto_bitmap_alloc_depth(params->width, params->height, 32); @@ -771,6 +807,7 @@ if (ui_changed) { union_rect(&underlay_invalid, &ui_changed_bounds); + union_rect(&video_invalid, &ui_changed_bounds); union_rect(&overlay_invalid, &ui_changed_bounds); union_rect(&bezel_invalid, &ui_changed_bounds); ui_changed--; @@ -780,6 +817,7 @@ if (!global_artwork_enable) { fillbitmap(final, MAKE_ARGB(0,0,0,0), NULL); + union_rect(&video_invalid, &screenrect); union_rect(&underlay_invalid, &screenrect); union_rect(&overlay_invalid, &screenrect); union_rect(&bezel_invalid, &screenrect); @@ -799,6 +837,10 @@ render_game_bitmap_underlay(display->game_bitmap, palette_lookup, display); else if (num_overlays) render_game_bitmap_overlay(display->game_bitmap, palette_lookup, display); + else if (num_videos) /* can only cope with video on its own */ + { + render_game_bitmap_video(display->game_bitmap, palette_lookup, display); + } else render_game_bitmap(display->game_bitmap, palette_lookup, display); @@ -985,6 +1027,10 @@ /* bezel */ else if (piece->layer >= LAYER_BEZEL) union_rect(&bezel_invalid, &piece->bounds); + + /* bezel */ + else if (piece->layer >= LAYER_VIDEO) + union_rect(&video_invalid, &piece->bounds); } } } @@ -1007,6 +1053,21 @@ struct rectangle combined; int changed = 0; + + /* update the video */ + /* assume only one video and just change the pointer */ + if (video_invalid.max_x != 0) + { + video = piece->prebitmap; + /* + sect_rect(&video_invalid, &screenrect); + erase_rect(video, &video_invalid, 0); + for (piece = artwork_list; piece; piece = piece->next) + if (piece->layer == LAYER_VIDEO && piece->visible && piece->prebitmap) + alpha_blend_intersecting_rect(video, &video_invalid, piece->prebitmap, &piece->bounds, piece->scanlinehint); + */ + } + /* update the underlays */ if (underlay_invalid.max_x != 0) { @@ -1038,17 +1099,23 @@ alpha_blend_intersecting_rect(bezel, &bezel_invalid, piece->prebitmap, &piece->bounds, piece->scanlinehint); } + /* combine the invalid rects */ combined = underlay_invalid; + union_rect(&combined, &video_invalid); union_rect(&combined, &overlay_invalid); union_rect(&combined, &bezel_invalid); if (combined.max_x != 0) { /* blend into the final bitmap */ erase_rect(final, &combined, 0); - alpha_blend_intersecting_rect(final, &combined, underlay, &screenrect, NULL); - add_intersecting_rect(final, &combined, overlay, &screenrect); - alpha_blend_intersecting_rect(final, &combined, bezel, &screenrect, NULL); + if(num_underlays) + alpha_blend_intersecting_rect(final, &combined, underlay, &screenrect, NULL); + if(num_overlays) + add_intersecting_rect(final, &combined, overlay, &screenrect); + if(num_bezels) + alpha_blend_intersecting_rect(final, &combined, bezel, &screenrect, NULL); + alpha_blend_intersecting_rect(final, &combined, video, &screenrect, NULL); changed = 1; } @@ -1056,6 +1123,8 @@ underlay_invalid.max_x = 0; overlay_invalid.max_x = 0; bezel_invalid.max_x = 0; + video_invalid.max_x = 0; + return changed; } @@ -1597,6 +1666,162 @@ /*------------------------------------------------- + render_game_bitmap_video - render the game over the video +-------------------------------------------------*/ + +static void render_game_bitmap_video(struct mame_bitmap *bitmap, const rgb_t *palette, struct mame_display *display) +{ + int srcrowpixels = bitmap->rowpixels; + int dstrowpixels = final->rowpixels; + void *srcbase, *dstbase, *undbase; + int width, height; + int x, y; + + /* compute common parameters */ + width = Machine->absolute_visible_area.max_x - Machine->absolute_visible_area.min_x + 1; + height = Machine->absolute_visible_area.max_y - Machine->absolute_visible_area.min_y + 1; + srcbase = (UINT8 *)bitmap->base + Machine->absolute_visible_area.min_y * bitmap->rowbytes; + dstbase = (UINT8 *)final->base + gamerect.min_y * final->rowbytes + gamerect.min_x * sizeof(UINT32); + undbase = (UINT8 *)video->base + gamerect.min_y * video->rowbytes + gamerect.min_x * sizeof(UINT32); + + /* vector case */ + if (display->changed_flags & VECTOR_PIXELS_CHANGED) + { + vector_pixel_t offset = VECTOR_PIXEL(gamerect.min_x, gamerect.min_y); + vector_pixel_t *list = display->vector_dirty_pixels; + + /* 16/15bpp case */ + if (bitmap->depth != 32) + { + while (*list != VECTOR_PIXEL_END) + { + vector_pixel_t coords = *list; + x = VECTOR_PIXEL_X(coords); + y = VECTOR_PIXEL_Y(coords); + *list++ = coords + offset; + logerror("VECTOR_PIXELS_CHANGED not implemented in render_game_bitmap_video\n"); + PIXEL(x,y,dst,dst,32) = add_and_clamp(palette[PIXEL(x,y,src,src,16)], PIXEL(x,y,und,dst,32)); + } + } + + /* 32bpp case */ + else + { + while (*list != VECTOR_PIXEL_END) + { + vector_pixel_t coords = *list; + x = VECTOR_PIXEL_X(coords); + y = VECTOR_PIXEL_Y(coords); + *list++ = coords + offset; + PIXEL(x,y,dst,dst,32) = add_and_clamp(PIXEL(x,y,src,src,32), PIXEL(x,y,und,dst,32)); + } + } + } + + /* 1x scale */ + else if (gamescale == 1) + { + /* 16/15bpp case, this is enough for MACH3 and Firefox */ + /* Do this with an if not a function pointer so it can remain INLINE */ + if (bitmap->depth != 32) + { + if(!video_piece->alpha_filename) + { + logerror("blending style not set in art file"); + return; + } + if(!strcmp(video_piece->alpha_filename, "mach3")) + { + for (y = 0; y < height; y++) + { + UINT16 *src = (UINT16 *)srcbase + y * srcrowpixels + Machine->absolute_visible_area.min_x; + UINT32 *dst = (UINT32 *)dstbase + y * dstrowpixels; + UINT32 *und = (UINT32 *)undbase + y * dstrowpixels; + for (x = 0; x < width; x++) + { + *dst++ = video_blend_and_clamp_mach3(palette[*src++], *und++); + } + } + } + else + { + for (y = 0; y < height; y++) + { + UINT16 *src = (UINT16 *)srcbase + y * srcrowpixels + Machine->absolute_visible_area.min_x; + UINT32 *dst = (UINT32 *)dstbase + y * dstrowpixels; + UINT32 *und = (UINT32 *)undbase + y * dstrowpixels; + for (x = 0; x < width; x++) + { + *dst++ = video_blend_and_clamp_firefox(palette[*src++], *und++); + } + } + } + } + + /* 32bpp case */ + else + { + for (y = 0; y < height; y++) + { + UINT32 *src = (UINT32 *)srcbase + y * srcrowpixels + Machine->absolute_visible_area.min_x; + UINT32 *dst = (UINT32 *)dstbase + y * dstrowpixels; + UINT32 *und = (UINT32 *)undbase + y * dstrowpixels; + for (x = 0; x < width; x++) + *dst++ = add_and_clamp(*src++, *und++); + } + } + } + + /* 2x scale */ + else if (gamescale == 2) + { + /* 16/15bpp case */ + if (bitmap->depth != 32) + { + for (y = 0; y < height; y++) + { + UINT16 *src = (UINT16 *)srcbase + y * srcrowpixels + Machine->absolute_visible_area.min_x; + UINT32 *dst = (UINT32 *)dstbase + y * 2 * dstrowpixels; + UINT32 *und = (UINT32 *)undbase + y * 2 * dstrowpixels; + for (x = 0; x < width; x++) + { + UINT32 val = palette[*src++]; + dst[0] = add_and_clamp(val, und[0]); + dst[1] = add_and_clamp(val, und[1]); + dst[dstrowpixels] = add_and_clamp(val, und[dstrowpixels]); + dst[dstrowpixels + 1] = add_and_clamp(val, und[dstrowpixels + 1]); + dst += 2; + und += 2; + } + } + } + + /* 32bpp case */ + else + { + for (y = 0; y < height; y++) + { + UINT32 *src = (UINT32 *)srcbase + y * srcrowpixels + Machine->absolute_visible_area.min_x; + UINT32 *dst = (UINT32 *)dstbase + y * 2 * dstrowpixels; + UINT32 *und = (UINT32 *)undbase + y * 2 * dstrowpixels; + for (x = 0; x < width; x++) + { + UINT32 val = *src++; + dst[0] = add_and_clamp(val, und[0]); + dst[1] = add_and_clamp(val, und[1]); + dst[dstrowpixels] = add_and_clamp(val, und[dstrowpixels]); + dst[dstrowpixels + 1] = add_and_clamp(val, und[dstrowpixels + 1]); + dst += 2; + und += 2; + } + } + } + } +} + + + +/*------------------------------------------------- render_game_bitmap_overlay - render the game bitmap blended with an overlay -------------------------------------------------*/ @@ -2005,6 +2230,7 @@ num_underlays = 0; num_overlays = 0; num_bezels = 0; + num_videos = 0; overlay_list = NULL; /* if the user turned artwork off, bail */ @@ -2050,12 +2276,21 @@ num_underlays++; else if (piece->layer == LAYER_OVERLAY) num_overlays++; - else if (piece->layer >= LAYER_BEZEL) + else if (piece->layer == LAYER_BEZEL) num_bezels++; + else if (piece->layer >= LAYER_VIDEO) + { + video_piece = piece; + num_videos++; + } /* load the graphics */ if (driver) load_bitmap(driver->name, piece); + + /* if its an mpeg piece then init it */ + if(!strcmp(piece->tag, TAG_LASERDISK)) + init_mpeg(driver->name); } /* debugging */ /* fprintf(stderr, "backdrops=%d overlays=%d bezels=%d\n", num_underlays, num_overlays, num_bezels); */ @@ -2309,6 +2544,7 @@ underlay_invalid = screenrect; overlay_invalid = screenrect; bezel_invalid = screenrect; + video_invalid = screenrect; /* loop through all the pieces, generating the scaled bitmaps */ for (piece = artwork_list; piece; piece = piece->next) @@ -2336,27 +2572,41 @@ given piece of artwork -------------------------------------------------*/ -static int scale_bitmap(struct artwork_piece *piece, int newwidth, int newheight) +/* TODO is this ok non-static? */ +int scale_bitmap(struct artwork_piece *piece, int newwidth, int newheight) { UINT32 sx, sxfrac, sxstep, sy, syfrac, systep; UINT32 global_brightness, global_alpha; + UINT32 sxadx, syady; int x, y; + int xweight, dx; + int yweight, dy; + int xwbyw; + int wc2, wc3, wc4; + int prevstate = 0, statex = 0; + rgb_t pix1, pix2, pix3, pix4; + int r, g, b, a; + int newstate; /* skip if no bitmap */ if (!piece->rawbitmap) return 1; - /* allocate two new bitmaps */ - piece->prebitmap = auto_bitmap_alloc_depth(newwidth, newheight, -32); - piece->yrgbbitmap = auto_bitmap_alloc_depth(newwidth, newheight, -32); - if (!piece->prebitmap || !piece->yrgbbitmap) - return 0; + /* no need to do this memory stuff all the time */ + if(!piece->prebitmap) + { + /* allocate two new bitmaps */ + piece->prebitmap = auto_bitmap_alloc_depth(newwidth, newheight, -32); + piece->yrgbbitmap = auto_bitmap_alloc_depth(newwidth, newheight, -32); + if (!piece->prebitmap || !piece->yrgbbitmap) + return 0; - /* also allocate memory for the scanline hints */ - piece->scanlinehint = auto_malloc(newheight * MAX_HINTS_PER_SCANLINE * sizeof(piece->scanlinehint[0])); - if (!piece->scanlinehint) - return 0; - memset(piece->scanlinehint, 0, newheight * MAX_HINTS_PER_SCANLINE * sizeof(piece->scanlinehint[0])); + /* also allocate memory for the scanline hints */ + piece->scanlinehint = auto_malloc(newheight * MAX_HINTS_PER_SCANLINE * sizeof(piece->scanlinehint[0])); + if (!piece->scanlinehint) + return 0; + memset(piece->scanlinehint, 0, newheight * MAX_HINTS_PER_SCANLINE * sizeof(piece->scanlinehint[0])); + } /* convert global brightness and alpha to fixed point */ global_brightness = (int)(piece->brightness * 65536.0); @@ -2373,7 +2623,6 @@ /* now do the scaling, using 4-point sampling */ for (y = 0; y < newheight; y++) { - int prevstate = 0, statex = 0; sxfrac = (sxstep / 2) & FRAC_MASK; sx = (sxstep / 2) >> FRAC_BITS; @@ -2381,11 +2630,6 @@ /* loop over columns */ for (x = 0; x < newwidth; x++) { - rgb_t pix1, pix2, pix3, pix4; - int xweight, dx; - int yweight, dy; - int r, g, b, a; - int newstate; /* determine the weights and which pixels to fetch */ if (sxfrac <= FRAC_HALF) @@ -2414,47 +2658,59 @@ xweight >>= FRAC_BITS - 8; yweight >>= FRAC_BITS - 8; + sxadx = sx + dx; + syady = sy + dy; /* fetch the pixels */ - pix1 = *((UINT32 *)piece->rawbitmap->base + (sy + dy + 0) * piece->rawbitmap->rowpixels + (sx + dx + 0)); - pix2 = *((UINT32 *)piece->rawbitmap->base + (sy + dy + 0) * piece->rawbitmap->rowpixels + (sx + dx + 1)); - pix3 = *((UINT32 *)piece->rawbitmap->base + (sy + dy + 1) * piece->rawbitmap->rowpixels + (sx + dx + 0)); - pix4 = *((UINT32 *)piece->rawbitmap->base + (sy + dy + 1) * piece->rawbitmap->rowpixels + (sx + dx + 1)); + pix1 = *((UINT32 *)piece->rawbitmap->base + (syady + 0) * piece->rawbitmap->rowpixels + (sxadx + 0)); + pix2 = *((UINT32 *)piece->rawbitmap->base + (syady + 0) * piece->rawbitmap->rowpixels + (sxadx + 1)); + pix3 = *((UINT32 *)piece->rawbitmap->base + (syady + 1) * piece->rawbitmap->rowpixels + (sxadx + 0)); + pix4 = *((UINT32 *)piece->rawbitmap->base + (syady + 1) * piece->rawbitmap->rowpixels + (sxadx + 1)); + + xwbyw = xweight * yweight; + wc2 = (0x100 - xweight) * yweight; + wc3 = xweight * (0x100 - yweight); + wc4 = (0x100 - xweight) * (0x100 - yweight); /* blend red */ - r = xweight * yweight * RGB_RED(pix1); - r += (0x100 - xweight) * yweight * RGB_RED(pix2); - r += xweight * (0x100 - yweight) * RGB_RED(pix3); - r += (0x100 - xweight) * (0x100 - yweight) * RGB_RED(pix4); + r = xwbyw * RGB_RED(pix1); + r += wc2 * RGB_RED(pix2); + r += wc3 * RGB_RED(pix3); + r += wc4 * RGB_RED(pix4); r >>= 16; r = (r * global_brightness) >> 16; if (r > 0xff) r = 0xff; /* blend green */ - g = xweight * yweight * RGB_GREEN(pix1); - g += (0x100 - xweight) * yweight * RGB_GREEN(pix2); - g += xweight * (0x100 - yweight) * RGB_GREEN(pix3); - g += (0x100 - xweight) * (0x100 - yweight) * RGB_GREEN(pix4); + g = xwbyw * RGB_GREEN(pix1); + g += wc2 * RGB_GREEN(pix2); + g += wc3 * RGB_GREEN(pix3); + g += wc4 * RGB_GREEN(pix4); g >>= 16; g = (g * global_brightness) >> 16; if (g > 0xff) g = 0xff; /* blend blue */ - b = xweight * yweight * RGB_BLUE(pix1); - b += (0x100 - xweight) * yweight * RGB_BLUE(pix2); - b += xweight * (0x100 - yweight) * RGB_BLUE(pix3); - b += (0x100 - xweight) * (0x100 - yweight) * RGB_BLUE(pix4); + b = xwbyw * RGB_BLUE(pix1); + b += wc2 * RGB_BLUE(pix2); + b += wc3 * RGB_BLUE(pix3); + b += wc4 * RGB_BLUE(pix4); b >>= 16; b = (b * global_brightness) >> 16; if (b > 0xff) b = 0xff; /* blend alpha */ - a = xweight * yweight * RGB_ALPHA(pix1); - a += (0x100 - xweight) * yweight * RGB_ALPHA(pix2); - a += xweight * (0x100 - yweight) * RGB_ALPHA(pix3); - a += (0x100 - xweight) * (0x100 - yweight) * RGB_ALPHA(pix4); - a >>= 16; - a = (a * global_alpha) >> 16; - if (a > 0xff) a = 0xff; + if(strcmp(piece->tag, TAG_LASERDISK)) + { + a = xwbyw * RGB_ALPHA(pix1); + a += wc2 * RGB_ALPHA(pix2); + a += wc3 * RGB_ALPHA(pix3); + a += wc4 * RGB_ALPHA(pix4); + a >>= 16; + a = (a * global_alpha) >> 16; + if (a > 0xff) a = 0xff; + } + else + a = 0xff; /* compute the two pixel types */ *((UINT32 *)piece->prebitmap->base + y * piece->prebitmap->rowpixels + x) = compute_pre_pixel(a,r,g,b); @@ -2615,6 +2871,7 @@ newpiece->alpha_filename = NULL; newpiece->intersects_game = 0; newpiece->visible = 1; + newpiece->prebitmap = NULL; /* force alloc of memory */ /* allocate space for the filename */ newpiece->tag = auto_malloc(strlen(tag) + 1); @@ -2668,6 +2925,7 @@ { switch (piece->layer) { + case LAYER_VIDEO: case LAYER_BACKDROP: if (options.use_artwork & ARTWORK_USE_BACKDROPS) array[i++] = piece; @@ -2975,6 +3233,8 @@ piece->layer = LAYER_SIDE; else if (!strcmp(value, "flyer")) piece->layer = LAYER_FLYER; + else if (!strcmp(value, "video")) + piece->layer = LAYER_VIDEO; else return 0; return 1; diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/artwork.h xmame-laser/src/artwork.h --- xmame-0.78.1/src/artwork.h Fri Dec 26 23:29:06 2003 +++ xmame-laser/src/artwork.h Mon Jan 19 21:34:57 2004 @@ -75,6 +75,39 @@ float left, top, right, bottom; }; +struct artwork_piece +{ + /* linkage */ + struct artwork_piece * next; + + /* raw data from the .art file */ + UINT8 layer; + UINT8 has_alpha; + int priority; + float alpha; + float brightness; + float top; + float left; + float bottom; + float right; + char * tag; + char * filename; + char * alpha_filename; + + /* bitmaps */ + struct mame_bitmap * rawbitmap; + struct mame_bitmap * prebitmap; + struct mame_bitmap * yrgbbitmap; + UINT32 * scanlinehint; + UINT8 blendflags; + + /* derived/dynamic data */ + int intersects_game; + int visible; + struct rectangle bounds; +}; + + /*************************************************************************** @@ -94,6 +127,11 @@ void artwork_set_overlay(const struct overlay_piece *overlist); void artwork_show(const char *tag, int show); + +struct artwork_piece *get_laser_disc_artwork_piece(); +struct rectangle *get_video_invalid(); +struct rectangle *get_underlay_invalid(); +int scale_bitmap(struct artwork_piece *piece, int newwidth, int newheight); mame_file *artwork_load_artwork_file(const struct GameDriver **driver); diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/driver.c xmame-laser/src/driver.c --- xmame-0.78.1/src/driver.c Fri Dec 26 23:29:12 2003 +++ xmame-laser/src/driver.c Mon Jan 19 21:34:57 2004 @@ -3795,6 +3795,7 @@ DRIVER( cloakgr ) /* 136023 (c) 1983 */ DRIVER( cloud9 ) /* (proto) (c) 1983 */ DRIVER( jedi ) /* 136030 (c) 1984 */ + DRIVER( firefox ) /* 136030 (c) 1984 */ /* Atari System 1 games */ DRIVER( peterpak ) /* 136028 (c) 1984 */ diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/drivers/firefox.c xmame-laser/src/drivers/firefox.c --- xmame-0.78.1/src/drivers/firefox.c Thu Jan 1 01:00:00 1970 +++ xmame-laser/src/drivers/firefox.c Tue Jan 20 00:24:33 2004 @@ -0,0 +1,1227 @@ +/* + +Fire Fox +-------- +Driver by smf & Chris Hardy & Scott Waye + +short term: + split driver/vidhrdw/sndhrdw/machine + partial screen updates? + tilemap + add option to centre joystick to enter test menu + +long term: + video/graphics mixing + shared riot code + +verify: + screen size + colours + sprites + interrupts + sound flags + video flags + clock speeds + priorities + +AV# 60626 +Atari "Firefox" V + +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + +Laser Disc - 30 minutes - Color - 1983 + +An interactive CAV laserdisc designed for use in the Atari video arcade game machine. +Contains over 100 visual and sound segments that include all of the branching possibilities of this game. +Each segment is two to five seconds long. This disc will play on any player, +but requires a special level III player for proper control. Video: CAV. Audio: Analog. + +according to ade's code: + +field length is 240 +vblank should start at line 240 & end at line 5 +irq should start at line 96 & end at 128 + +It's far too slow though, using irobot's interrupts makes +the game run faster ( maybe too fast ). +it needs more investigation but remember it's interlaced +so we have to multiply the scanlines by 2. + +he has breakpoints @ because it sits in a loop $E38D & $EE8B. +now we have the watchdog & reset handling emulated it +probably won't do this. + +According to my understanding of the circuit diagram, vblank will be set at scanline 496 and will go low at scan line 16. + +it uses a quad pokey package 137323-1221-406??? +the laser disc is a philips lvp 22vp931 +( but maybe this works too... Special Drive: Laser Disc Player - Philips VP-832A ) + +From the schematic it looks as though the video is blended with the graphics using the first 2 bits of the blue output and some 74ls4066 with 2000 or 1000 resistors: + +b0 b1 video graphic +0 0 1+2 0 +1 0 2 1 graphic is twice as strong as video ? +0 1 1 2 +1 1 0 1+2 + + + +*/ + +#include "mame.h" +#include "driver.h" +#include "artwork.h" +#include "vidhrdw/generic.h" +#include "vidhrdw/laserdsk.h" +#include "cpu/m6809/m6809.h" +#include "cpu/m6502/m6502.h" + +static int m_b_vblank; +static void *sound_timer; +static int n_adchannel; +static unsigned char *tileram; +static size_t tileram_size; +static unsigned char *tileredram; +static unsigned char *tilegreenram; +static unsigned char *tileblueram; +static unsigned char *spriteredram; +static unsigned char *spritegreenram; +static unsigned char *spriteblueram; +static int m_n_disc_lock; +static int m_n_disc_left_audio; +static int m_n_disc_right_audio; +static int m_n_disc_data; +static int m_n_disc_offset; +static int m_n_disc_packet[ 3 ]; +static int m_n_manchester[ 6 ]; +static int m_n_manchester_offset; +static int m_n_spritebank; +static int disc_reset; +static int disk_opr = 0; +static int irq_set = 0; +static int previous_irq_state = 0; +static int dav = 0x80; +static int dak_just_low = 0; /* simulate the 15 uS time for the player to read the data */ +static int dak = 0x40; /* DAK or DSKFULL active low indicates player has data, + reset when player has read data */ +static int disk_data; /* after a command is sent the first bit indicates an error, except of the data is 0x00 which indicates an invalid manchester data read (whatever that means) */ +static int disk_line = 0; + +static UINT8 nvram_store[ 256 ]; + +static int status1 = 0xff, status2 = 0xff, status3 = 0xff; + + +static NVRAM_HANDLER( firefox ) +{ + if( read_or_write ) + { + //mame_fwrite( file, generic_nvram, generic_nvram_size ); + mame_fwrite( file, generic_nvram, generic_nvram_size ); + } + else + { + if( file ) + { + mame_fread( file, generic_nvram, generic_nvram_size ); + } + else + { + memset( generic_nvram, 0xff, generic_nvram_size ); + } + memcpy( nvram_store, generic_nvram, generic_nvram_size ); + } +} + +WRITE_HANDLER( firefox_novram_recall_w ) +{ + if( ( data & 0x80 ) != 0 ) + { + memcpy( generic_nvram, nvram_store, generic_nvram_size ); + } +} + +WRITE_HANDLER( firefox_novram_store_w ) +{ + if( ( data & 0x80 ) != 0 ) + { + memcpy( nvram_store, generic_nvram, generic_nvram_size ); + } +} + +#define IRQ_EVERY ( 16 ) + +/* FXXXXX for first field + AXXXXX for second field */ +void firefox_scanline_callback( int scanline ) +{ + /* this is sort of how irobot works.. */ + /* +fprintf(stderr, "scanline cb %d\n", scanline); + cpu_set_irq_line( 0, M6809_IRQ_LINE, ( scanline & IRQ_EVERY ) ? ASSERT_LINE : CLEAR_LINE ); +*/ + + /* should be 96 according to page 28 of the schematic (G64V AND G32V)*/ + /* also should only trigger if has been reset and this is the rising edge */ + /* + cpu_set_irq_line( 0, M6809_IRQ_LINE, ( scanline & 96) ? ASSERT_LINE : CLEAR_LINE ); + */ + if(((scanline & 96) == 96) && !irq_set && !previous_irq_state) + { + irq_set = 1; + previous_irq_state = 1; + cpu_set_irq_line( 0, M6809_IRQ_LINE, ASSERT_LINE ); + } + + if((scanline & 96) != 96) + { + previous_irq_state = 0; + } + + if( scanline >= 496 ) + { + m_b_vblank = 1; +#if 1 + /* only sends manchester data when playing - is this correct ? */ + /*if( laser_disc_speed && (m_n_manchester_offset == 6) )*/ +#endif + } + else if(scanline >= 16) + { + m_b_vblank = 0; + } + if(scanline == disk_line) + { + if( laser_disc_speed) + { + m_n_manchester[ 0 ] = ( ( laser_disc_field & 0x01 )?0xA0:0xF0 ) | ( ( laser_disc_field / 20000 ) % 10 ); + m_n_manchester[ 1 ] = ( ( ( laser_disc_field / 2000 ) % 10 ) << 4 ) | ( ( laser_disc_field / 200 ) % 10 ); + m_n_manchester[ 2 ] = ( ( ( laser_disc_field / 20 ) % 10 ) << 4 ) | ( ( laser_disc_field / 2 ) % 10 ); + m_n_manchester[ 3 ] = status1; + m_n_manchester[ 4 ] = status2; + m_n_manchester[ 5 ] = status3; + m_n_manchester_offset = 0; + cpu_set_irq_line( 0, M6809_FIRQ_LINE, ASSERT_LINE ); + dav = 0; /* buffer contains info */ + } + laser_disc_field += laser_disc_speed; + } + scanline += IRQ_EVERY; + if(scanline >= 512) + scanline -= 512; + + /* interlace so multiply by 2. */ + timer_set( cpu_getscanlinetime( scanline ), scanline, firefox_scanline_callback ); +} + +/* +fff6=firq e4a2 when dav goes active/low +fff8=irq e38f This is through a flip-flop so goes off (high as active low) only when reset_irq is active - low. +fffa=??? e38d +fffc=??? e38d +fffe=reset e7cc +*/ + +/* 0x50-52 Used as a copy of the status + 0x59 = 6-length of laser disc return code + 0x53 = pointer to laser disc return + ( LaserDiscBits & 0x80 ) != 0 when return code available + DSKREAD = acknowledge + ReadDiscData = return code +*/ + +VIDEO_UPDATE( firefox ) +{ + int n_x; + int n_y; + int n_attr; + int offs; + int n_sprite; + int n_row; + + run_laser_disc(); + /* about 1.2 ms from here to end without debug text */ + UINT8 *p_sprite = spriteram + ( 0x200 * m_n_spritebank ); + + fillbitmap( bitmap, 256, &Machine->visible_area ); + + for( n_sprite = 0; n_sprite < 32; n_sprite++ ) + { + n_attr = p_sprite[ 0 ]; + n_y = p_sprite[ 1 ] + ( 256 * ( n_attr & 1 ) ); + n_x = p_sprite[ 2 ] + ( 256 * ( ( n_attr >> 1 ) & 1 ) ); + if( n_x != 0 ) + { + for( n_row = 0; n_row < 8; n_row++ ) + { + drawgfx( bitmap, Machine->gfx[ 1 ], p_sprite[ 15 - n_row ] + 256 * ( ( n_attr >> 6 ) & 3 ), + ( ( n_attr >> 2 ) & 0x03 ) * 2, n_attr & 0x20, n_attr & 0x10, n_x + 8, 500 - n_y, + &Machine->visible_area, TRANSPARENCY_PEN, 0 ); + n_y += 16; + } + } + p_sprite += 16; + } + + offs = 0; + for( n_y = 0; n_y < 64; n_y++ ) + { + for( n_x = 0; n_x < 64; n_x++ ) + { + drawgfx( bitmap, Machine->gfx[ 0 ], tileram[ offs++ ], + 0, 0, 0, n_x * 8, n_y * 8, &Machine->visible_area, TRANSPARENCY_PEN, 0 ); + } + } +#if 0 + { + struct DisplayText dt[ 2 ]; + char text1[ 256 ]; + if( m_n_disc_left_audio ) + { + text1[ 0 ] = 'L'; + } + else + { + text1[ 0 ] = '-'; + } + if( m_n_disc_right_audio ) + { + text1[ 1 ] = 'R'; + } + else + { + text1[ 1 ] = '-'; + } + if( m_n_disc_lock ) + { + text1[ 2 ] = 'G'; + } + else + { + text1[ 2 ] = 'D'; + } + sprintf( text1 + 3, "%03d,%03d", laser_disc_field / 1000, laser_disc_field % 1000 ); + + dt[ 0 ].text = text1; + dt[ 0 ].color = UI_COLOR_NORMAL; + dt[ 0 ].x = ( Machine->uiwidth - Machine->uifontwidth * strlen( dt[ 0 ].text ) ) / 2; + dt[ 0 ].y = Machine->uiheight - Machine->uifontheight; + dt[ 1 ].text = 0; /* terminate array */ + + displaytext( bitmap, dt ); + } +#endif +} + +#define MAINFLAG ( 0x80 ) +#define SOUNDFLAG ( 0x40 ) + +static int port_A = 0; /* 6532 port A data register */ + + /* Configured as follows: */ + /* d7 (in) Main Ready Flag */ + /* d6 (in) Sound Ready Flag */ + /* d5 (out) Mute Speech */ + /* d4 (in) Not Sound Self Test */ + /* d3 (out) Hold Main CPU in Reset? */ + /* + enable delay circuit? */ + /* d2 (in) TMS5220 Not Ready */ + /* d1 (out) TMS5220 Not Read */ + /* d0 (out) TMS5220 Not Write */ +static int port_B = 0; /* 6532 port B data register */ + /* (interfaces to TMS5220 data bus) */ +static int port_A_ddr = 0; /* 6532 Data Direction Register A */ +static int port_B_ddr = 0; /* 6532 Data Direction Register B */ +static int PA7_irq = 0; /* IRQ-on-write flag (sound CPU) */ +static int PA7_edge = 0; /* IRQ-on-write flag (sound CPU) */ +static int irq_flag = 0; /* 6532 interrupt flag register */ +static int soundflags = 0; +static int main_data = 0; +static int sound_data = 0; + +int firefox_soundflags( void ) +{ + return soundflags; +} + +READ_HANDLER( firefox_mainrd_r ) +{ + soundflags &= ~SOUNDFLAG; + return sound_data; +} + +WRITE_HANDLER( firefox_mainwr_w ) +{ + soundflags |= MAINFLAG; + main_data = data; + cpu_set_irq_line( 1, IRQ_LINE_NMI, PULSE_LINE ); +} + +WRITE_HANDLER( firefox_soundrst_w ) +{ + if( ( data & 0x80 ) != 0 ) + { + /* reset sound CPU */ + soundflags = 0; + cpu_set_reset_line( 1, ASSERT_LINE ); + } + else + { + cpu_set_reset_line( 1, CLEAR_LINE ); + } +} + +READ_HANDLER( firefox_soundrd_r ) +{ + soundflags &= ~MAINFLAG; + return main_data; +} + +WRITE_HANDLER( firefox_soundwr_w ) +{ + soundflags |= SOUNDFLAG; + sound_data = data; +} + +READ_HANDLER( firefox_pia_r ) +{ + int temp; + switch( offset ) + { + case 0x00: /* Read Port A */ + return ( port_A & port_A_ddr ) | ( ( soundflags | 0x10 | ( ( !tms5220_ready_r() ) << 2 ) ) & ~port_A_ddr ); + case 0x01: /* Read Port A DDR */ + return port_A_ddr; + case 0x02: /* Read Port B */ + return ( port_B & port_B_ddr ); /* speech data read? */ + case 0x03: /* Read Port B DDR */ + return port_B_ddr; + case 0x05: /* Read Interrupt Flag Register */ + temp = irq_flag; + irq_flag = 0; /* Clear int flags */ + cpu_set_irq_line( 1, M6502_IRQ_LINE, CLEAR_LINE ); + return temp; + default: + logerror( "unhandled pia_r %d\n", offset ); + return 0; + } +} + +static void pia_interrupt( int unused ) +{ + irq_flag = 0x80; /* set timer interrupt flag */ + cpu_set_irq_line( 1, M6502_IRQ_LINE, ASSERT_LINE ); +} + +static void stop_pia_timer( void ) +{ + timer_adjust( sound_timer, TIME_NEVER, 0, 0 ); + irq_flag = 0; /* Clear int flags */ + cpu_set_irq_line( 1, M6502_IRQ_LINE, CLEAR_LINE ); +} + +static void set_pia_timer( int data, int clock_divider ) +{ + timer_adjust( sound_timer, TIME_IN_HZ( 1000000 ) * ( data + 1 ) * clock_divider, 0, 0 ); + irq_flag = 0; /* Clear int flags */ + cpu_set_irq_line( 1, M6502_IRQ_LINE, CLEAR_LINE ); +} + +WRITE_HANDLER( firefox_pia_w ) +{ + static int old_port_A = 0; + + /* reg 0x0c - 0x0f mirror of 0x04 - 0x07?? */ + + switch( offset ) + { + case 0x00: /* Port A Write */ + port_A = data; + break; + case 0x01: /* Port A DDR Write */ + port_A_ddr = data; + break; + case 0x02: /* Port B Write */ + port_B = data; + break; + case 0x03: /* Port B DDR Write */ + port_B_ddr = data; + break; + case 0x04: /* Edge Detect Control */ + PA7_irq = 0; /* disabled */ + PA7_edge = 0; /* negative edge */ + break; + case 0x05: /* Edge Detect Control */ + PA7_irq = 0; /* disabled */ + PA7_edge = 1; /* positive edge */ + break; + case 0x06: /* Edge Detect Control */ + PA7_irq = 1; /* enabled */ + PA7_edge = 0; /* negative edge */ + break; + case 0x07: /* Edge Detect Control */ + PA7_irq = 1; /* enabled */ + PA7_edge = 1; /* positive edge */ + break; + case 0x14: /* timer divide by 1 */ + stop_pia_timer(); + break; + case 0x15: /* timer divide by 8 */ + stop_pia_timer(); + break; + case 0x16: /* timer divide by 64 */ + stop_pia_timer(); + break; + case 0x17: /* timer divide by 1024 */ + stop_pia_timer(); + break; + case 0x1c: /* timer divide by 1 */ + set_pia_timer( data, 1 ); + break; + case 0x1d: /* timer divide by 8 */ + set_pia_timer( data, 8 ); + break; + case 0x1e: /* timer divide by 64 */ + set_pia_timer( data, 64 ); + break; + case 0x1f: /* timer divide by 1024 */ + set_pia_timer( data, 1024 ); + break; + default: + logerror( "unhandled pia_w %d %d\n", offset, data ); + break; + } + if( ( old_port_A & 1 ) != 0 && ( port_A & port_A_ddr & 1 ) == 0 ) + { + tms5220_data_w( 0, port_B ); + } + if( ( old_port_A & 32 ) == 0 && ( port_A & port_A_ddr & 32 ) == 1 ) + { + tms5220_reset(); + } + old_port_A = port_A & port_A_ddr; +} + +READ_HANDLER( firefox_misc_r ) +{ + int n_return; + + n_return = readinputport( 1 ) | firefox_soundflags(); + if( m_b_vblank ) + { + n_return |= 0x20; + } + else + { + n_return &= ~0x20; + } + return n_return; +} + +READ_HANDLER( firefox_pot_r ) +{ + if( n_adchannel == 0 ) + { + return readinputport( 4 ); + } + return readinputport( 5 ); +} + +WRITE_HANDLER( firefox_objram_bank_w ) +{ + m_n_spritebank = data & 0x03; +} + +WRITE_HANDLER( firefox_rom_bank_w ) +{ + cpu_setbank( 2, memory_region( REGION_CPU1 ) + 0x10000 + ( ( data & 0x1f ) * 0x1000 ) ); +} + +static WRITE_HANDLER( firefox_clearirq_w ) +{ + irq_set = 0; + cpu_set_irq_line( 0, M6809_IRQ_LINE ,CLEAR_LINE ); +} + +static WRITE_HANDLER( firefox_clearfirq_w ) +{ + cpu_set_irq_line( 0, M6809_FIRQ_LINE ,CLEAR_LINE ); +} + +void mix_color( int offset, int red, int green, int blue ) +{ +#if 0 + int n_lvdpercent; + int n_videopercent; + + switch( blue & 0x03 ) + { + case 0: + n_lvdpercent = 100; + n_videopercent = 0; + break; + case 1: + n_lvdpercent = 66; + n_videopercent = 34; + break; + case 2: + n_lvdpercent = 33; + n_videopercent = 67; + break; + default: + n_lvdpercent = 0; + n_videopercent = 100; + break; + } + red = ( ( red * n_videopercent ) / 100 ) + ( ( 0x5f * n_lvdpercent ) / 100 ); + green = ( ( green * n_videopercent ) / 100 ) + ( ( 0x5f * n_lvdpercent ) / 100 ); + blue = ( ( blue * n_videopercent ) / 100 ) + ( ( 0x5f * n_lvdpercent ) / 100 ); + if( red > 0xff ) + { + red = 0xff; + } + if( green > 0xff ) + { + green = 0xff; + } + if( blue > 0xff ) + { + blue = 0xff; + } +#endif + palette_set_color( offset, red, green, blue ); +} + +void update_tile_colour( int offset, int data, unsigned char *ram ) +{ + ram[ offset ] = data; + mix_color( offset, tileredram[ offset ], tilegreenram[ offset ], tileblueram[ offset ] ); +} + +WRITE_HANDLER( firefox_tile_red_w ) +{ + update_tile_colour( offset, data, tileredram ); +} + +WRITE_HANDLER( firefox_tile_green_w ) +{ + update_tile_colour( offset, data, tilegreenram ); +} + +WRITE_HANDLER( firefox_tile_blue_w ) +{ + update_tile_colour( offset, data, tileblueram ); +} + +void update_sprite_colour( int offset, int data, unsigned char *ram ) +{ + ram[ offset ] = data; + mix_color( offset + 256, spriteredram[ offset ], spritegreenram[ offset ], spriteblueram[ offset ] ); +} + +WRITE_HANDLER( firefox_sprite_red_w ) +{ + update_sprite_colour( offset, data, spriteredram ); +} + +WRITE_HANDLER( firefox_sprite_green_w ) +{ + update_sprite_colour( offset, data, spritegreenram ); +} + +WRITE_HANDLER( firefox_sprite_blue_w ) +{ + update_sprite_colour( offset, data, spriteblueram ); +} + +WRITE_HANDLER( firefox_adchannel_w ) +{ + n_adchannel = offset; +} + +WRITE_HANDLER( firefox_reset_w ) +{ + cpu_set_reset_line( 0, PULSE_LINE ); +} + +WRITE_HANDLER( firefox_led_w ) +{ + if( ( data & 0x80 ) != 0 ) + { + set_led_status( offset, 0 ); + } + else + { + set_led_status( offset, 1 ); + } +} + +WRITE_HANDLER( firefox_coin_counter_w ) +{ + coin_counter_w( offset, data & 0x80 ); +} + +MACHINE_INIT( firefox ) +{ + n_adchannel = 0; + m_n_spritebank = 0; + m_b_vblank = 0; + + /* set an initial timer to go off on scanline 0 */ + timer_set( cpu_getscanlinetime( 0 ), 0, firefox_scanline_callback ); + + sound_timer = timer_alloc( pia_interrupt ); + + m_n_disc_packet[ 0 ] = 0; + m_n_disc_packet[ 1 ] = 0; + m_n_disc_packet[ 2 ] = 0; + m_n_disc_offset = 0; + laser_disc_field = 0; + laser_disc_speed = 0; + m_n_manchester_offset = 6; +} + +/* 20 = DISKOPR - Active low + 40 = DISKFULL - Active low + 80 = DISKDAV - Active low data available + */ +READ_HANDLER( firefox_disc_status_r ) +{ + int n_data; + n_data = dav | dak | disk_opr; /* always operational */ + logerror( "%08x: disc status r %02x\n", activecpu_get_pc(), n_data & ( 0x80 | 0x40 | 0x20 ) ); + /* + fprintf(stderr, "%08x: reading disc status r %02x\n", activecpu_get_pc(), n_data & ( 0x80 | 0x40 | 0x20 ) ); + */ + if(dak_just_low) + { + /* assume that the next status read will be after 15uS */ + dak = 0x40; + dak_just_low = 0; + } + return n_data; +} + +/* 4105 - DREAD */ +/* this reset RDDSK (&DSKRD) */ +READ_HANDLER( firefox_disc_data_r ) +{ + return disk_data; +} + +/* DISK READ ENABLE */ +/* 4218 - DSKREAD, set RDDSK */ +WRITE_HANDLER( firefox_disc_read_w ) +{ + dav=0x80; + if( m_n_manchester_offset < 6 ) + { + disk_data = m_n_manchester[ m_n_manchester_offset++ ]; + if(m_n_manchester_offset < 6) + { + dav = 0; /* more data */ + cpu_set_irq_line( 0, M6809_FIRQ_LINE, ASSERT_LINE ); + } + + } +} + +WRITE_HANDLER( firefox_disc_lock_w ) +{ + m_n_disc_lock = data & 0x80; +} + +WRITE_HANDLER( firefox_disc_right_audio_enable_w ) +{ + m_n_disc_right_audio = data & 0x80; +} + +WRITE_HANDLER( firefox_disc_left_audio_enable_w ) +{ + m_n_disc_left_audio = data & 0x80; +} + +WRITE_HANDLER( firefox_disc_reset_w ) +{ + disc_reset = (data & 0x80); + if(!disc_reset) + { + laser_disc_speed = 0; + m_n_manchester_offset = 6; /* no data available */ + m_n_disc_offset = 0; + dak = 0x40; + dav = 0x80; + } +} + +/* active low on dbb7 */ +WRITE_HANDLER( firefox_disc_write_w ) +{ + int f; + static int wrdsk = 0; + if( ( data & 0x80 ) == 0 ) + { + dak = 0; /* should go high after 15 uS */ + dak_just_low = 1; + m_n_disc_packet[ m_n_disc_offset++ ] = m_n_disc_data; + if( m_n_disc_offset == 3 ) + { + m_n_disc_offset = 0; + switch( m_n_disc_packet[ 0 ] & 0xf0 ) + { + case 0xf0: + logerror( "CMD: goto Frame #%01x%02x%02x & play forward\n", m_n_disc_packet[ 0 ] & 0x0f, m_n_disc_packet[ 1 ], m_n_disc_packet[ 2 ] ); + laser_disc_field = + ( ( m_n_disc_packet[ 0 ] & 0x0f ) * 20000 ) + + ( (( m_n_disc_packet[ 1 ] & 0xf0 ) >> 4) * 2000 ) + + ( ( m_n_disc_packet[ 1 ] & 0x0f ) * 200 ) + + ( (( m_n_disc_packet[ 2 ] & 0xf0 ) >> 4) * 20 ) + + ( ( m_n_disc_packet[ 2 ] & 0x0f ) * 2 ); + laser_seek_frame(laser_disc_field >> 1); + /* + fprintf(stderr, "CMD: goto frame #%01x%02x%02x & play forward disc_field %d\n", m_n_disc_packet[ 0 ] & 0x0f, m_n_disc_packet[ 1 ], m_n_disc_packet[ 2 ] , laser_disc_field); + */ + laser_disc_speed = 1; + return; + case 0xd0: + /* + fprintf(stderr, "CMD: goto Frame #%01x%02x%02x & halt (first field)\n", m_n_disc_packet[ 0 ] & 0x0f, m_n_disc_packet[ 1 ], m_n_disc_packet[ 2 ] ); + */ + laser_disc_field = + ( ( m_n_disc_packet[ 0 ] & 0x0f ) * 20000 ) + + ( (( m_n_disc_packet[ 1 ] & 0xf0 ) >> 4) * 2000 ) + + ( ( m_n_disc_packet[ 1 ] & 0x0f ) * 200 ) + + ( (( m_n_disc_packet[ 2 ] & 0xf0 ) >> 4) * 20 ) + + ( ( m_n_disc_packet[ 2 ] & 0x0f ) * 2 ); + laser_seek_frame(laser_disc_field >> 1); + laser_disc_speed = 0; + return; + case 0x00: + switch( m_n_disc_packet[ 0 ] & 0x0f ) + { + case 0x00: + switch( m_n_disc_packet[ 1 ] & 0xf0 ) + { + case 0x00: + laser_disc_speed = 1; + return; + case 0x10: + laser_disc_speed = -1; + return; + case 0x20: + laser_disc_speed = 0; + return; + case 0x40: + return; + case 0x50: + return; + case 0xa0: + laser_disc_speed = 75; + return; + case 0xb0: + laser_disc_speed = -75; + return; + case 0xe0: + return; + case 0xf0: + return; + } + break; + case 0x02: + switch( m_n_disc_packet[ 1 ] ) + { + case 0xb0: + logerror( "CMD: Video ON/OFF %02x\n", m_n_disc_packet[ 2 ] ); + return; + case 0xb1: + logerror( "CMD: Audio-I ON/OFF %02x\n", m_n_disc_packet[ 2 ] ); + return; + case 0xb2: + logerror( "CMD: Audio-II ON/OFF %02x\n", m_n_disc_packet[ 2 ] ); + return; + case 0xb3: + logerror( "CMD: CX ON/OFF %02x\n", m_n_disc_packet[ 2 ] ); + return; + } + break; + } + break; + } + logerror( "CMD: invalid %02x%02x%02x\n", m_n_disc_packet[ 0 ], m_n_disc_packet[ 1 ], m_n_disc_packet[ 2 ] ); + } + } +} + +/* latch the data */ +WRITE_HANDLER( firefox_disc_data_w ) +{ + m_n_disc_data = data; +} + +/************************************* + * + * Main CPU memory handlers + * + *************************************/ + +static MEMORY_READ_START( readmem ) + { 0x0000, 0x0fff, MRA_RAM }, + { 0x1000, 0x1fff, MRA_RAM }, + { 0x2000, 0x27ff, MRA_RAM }, + { 0x2800, 0x2fff, MRA_RAM }, + { 0x3000, 0x3fff, MRA_BANK2 }, + { 0x4000, 0x40ff, MRA_RAM }, + { 0x4100, 0x4100, input_port_0_r }, + { 0x4101, 0x4101, firefox_misc_r }, + { 0x4102, 0x4102, firefox_disc_status_r }, + { 0x4103, 0x4103, input_port_2_r }, + { 0x4104, 0x4104, input_port_3_r }, + { 0x4105, 0x4105, firefox_disc_data_r }, + { 0x4106, 0x4106, firefox_mainrd_r }, + { 0x4107, 0x4107, firefox_pot_r }, + { 0x4400, 0xffff, MRA_ROM }, +MEMORY_END + +static MEMORY_WRITE_START( writemem ) + { 0x0000, 0x0fff, MWA_RAM }, + { 0x1000, 0x1fff, MWA_RAM, &tileram, &tileram_size }, + { 0x2000, 0x27ff, MWA_RAM, &spriteram, &spriteram_size }, + { 0x2b00, 0x2b00, firefox_objram_bank_w }, + { 0x2b01, 0x2bff, MWA_RAM }, + { 0x2800, 0x28ff, firefox_sprite_red_w, &spriteredram }, + { 0x2900, 0x29ff, firefox_sprite_green_w, &spritegreenram }, + { 0x2a00, 0x2aff, firefox_sprite_blue_w, &spriteblueram }, + { 0x2c00, 0x2cff, firefox_tile_red_w, &tileredram }, + { 0x2d00, 0x2dff, firefox_tile_green_w, &tilegreenram }, + { 0x2e00, 0x2eff, firefox_tile_blue_w, &tileblueram }, + { 0x2f00, 0x3fff, MWA_RAM }, + { 0x4000, 0x40ff, MWA_RAM, &generic_nvram, &generic_nvram_size }, + { 0x4200, 0x4200, firefox_clearirq_w }, + { 0x4208, 0x4208, firefox_clearfirq_w }, + { 0x4210, 0x4210, watchdog_reset_w }, + { 0x4218, 0x4218, firefox_disc_read_w }, + { 0x4220, 0x4221, firefox_adchannel_w }, + { 0x4230, 0x4230, firefox_reset_w }, + { 0x4280, 0x4280, firefox_novram_recall_w }, + { 0x4281, 0x4281, firefox_soundrst_w }, + { 0x4282, 0x4282, firefox_novram_store_w }, + { 0x4283, 0x4283, firefox_disc_lock_w }, + { 0x4284, 0x4284, firefox_disc_right_audio_enable_w }, + { 0x4285, 0x4285, firefox_disc_left_audio_enable_w }, + { 0x4286, 0x4286, firefox_disc_reset_w }, + { 0x4287, 0x4287, firefox_disc_write_w }, + { 0x4288, 0x4289, firefox_coin_counter_w }, + { 0x428c, 0x428f, firefox_led_w }, + { 0x4290, 0x4290, firefox_rom_bank_w }, + { 0x4298, 0x4298, firefox_mainwr_w }, + { 0x42a0, 0x42a7, firefox_disc_data_w }, + { 0x4400, 0xffff, MWA_ROM }, +MEMORY_END + +/************************************* + * + * Sound CPU memory handlers + * + *************************************/ + +static MEMORY_READ_START( sound_readmem ) + { 0x0000, 0x07ff, MRA_RAM }, + { 0x0800, 0x087f, MRA_RAM }, /* pia ram */ + { 0x0880, 0x089f, firefox_pia_r }, + { 0x1000, 0x1000, firefox_soundrd_r }, + { 0x2000, 0x200f, pokey1_r }, + { 0x2800, 0x280f, pokey2_r }, + { 0x3000, 0x300f, pokey3_r }, + { 0x3800, 0x380f, pokey4_r }, + { 0x8000, 0xffff, MRA_ROM }, +MEMORY_END + +static MEMORY_WRITE_START( sound_writemem ) + { 0x0000, 0x07ff, MWA_RAM }, + { 0x0800, 0x087f, MWA_RAM }, /* pia ram */ + { 0x0880, 0x089f, firefox_pia_w }, + { 0x1800, 0x1800, firefox_soundwr_w }, + { 0x2000, 0x200f, pokey1_w }, + { 0x2800, 0x280f, pokey2_w }, + { 0x3000, 0x300f, pokey3_w }, + { 0x3800, 0x380f, pokey4_w }, + { 0x8000, 0xffff, MWA_ROM }, +MEMORY_END + +/************************************* + * + * Port definitions + * + *************************************/ + +INPUT_PORTS_START( firefox ) + PORT_START /* IN0 */ + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_TILT ) + PORT_SERVICE( 0x04, IP_ACTIVE_LOW ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START /* IN1 */ + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BITX( 0x10, IP_ACTIVE_LOW, IPT_SERVICE, "Diagnostic Step", KEYCODE_F1, IP_JOY_NONE ) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE1 ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN2 ) + + PORT_START /* IN2 */ + PORT_DIPNAME( 0x03, 0x00, "Coins Per Credit" ) + PORT_DIPSETTING( 0x00, "1 Coin 1 Credit" ) + PORT_DIPSETTING( 0x01, "2 Coins 1 Credit" ) + PORT_DIPSETTING( 0x02, "3 Coins 1 Credit" ) + PORT_DIPSETTING( 0x03, "4 Coins 1 Credit" ) + PORT_DIPNAME( 0x0c, 0x00, "Right Coin" ) + PORT_DIPSETTING( 0x00, "1 Coin for 1 Coin Unit" ) + PORT_DIPSETTING( 0x04, "1 Coin for 4 Coin Units" ) + PORT_DIPSETTING( 0x08, "1 Coin for 5 Coin Units" ) + PORT_DIPSETTING( 0x0c, "1 Coin for 6 Coin Units" ) + PORT_DIPNAME( 0x10, 0x00, "Left Coin" ) + PORT_DIPSETTING( 0x00, "1 Coin for 1 Coin Unit" ) + PORT_DIPSETTING( 0x10, "1 Coin for 2 Coin Units" ) + PORT_DIPNAME( 0xe0, 0x00, "Bonus Adder" ) + PORT_DIPSETTING( 0x00, "None" ) + PORT_DIPSETTING( 0x20, "1 Credit for 2 Coin Units" ) + PORT_DIPSETTING( 0xa0, "1 Credit for 3 Coin Units" ) + PORT_DIPSETTING( 0x40, "1 Credit for 4 Coin Units" ) + PORT_DIPSETTING( 0x80, "1 Credit for 5 Coin Units" ) + PORT_DIPSETTING( 0x60, "2 Credits for 4 Coin Units" ) + PORT_DIPSETTING( 0xe0, DEF_STR( Free_Play ) ) + + PORT_START /* IN3 */ + PORT_DIPNAME( 0x01, 0x00, "Missions" ) + PORT_DIPSETTING( 0x00, "All .50" ) + PORT_DIPSETTING( 0x01, ".50 .75" ) + PORT_DIPNAME( 0x06, 0x00, DEF_STR( Difficulty ) ) + PORT_DIPSETTING( 0x00, "Easy" ) + PORT_DIPSETTING( 0x02, "Moderate" ) + PORT_DIPSETTING( 0x04, "Hard" ) + PORT_DIPSETTING( 0x06, "Hardest" ) + PORT_DIPNAME( 0x18, 0x00, "Gas Usage" ) + PORT_DIPSETTING( 0x00, "Easy" ) + PORT_DIPSETTING( 0x08, "Moderate" ) + PORT_DIPSETTING( 0x10, "Hard" ) + PORT_DIPSETTING( 0x18, "Hardest" ) + PORT_DIPNAME( 0x60, 0x00, "Bonus Gas" ) + PORT_DIPSETTING( 0x00, "Easy" ) + PORT_DIPSETTING( 0x20, "Moderate" ) + PORT_DIPSETTING( 0x40, "Hard" ) + PORT_DIPSETTING( 0x60, "Hardest" ) + PORT_DIPNAME( 0x80, 0x00, "Pro Limit" ) + PORT_DIPSETTING( 0x00, "Moderate" ) + PORT_DIPSETTING( 0x80, "Hardest" ) + + PORT_START /* IN4 */ + PORT_ANALOG( 0xff, 0x80, IPT_AD_STICK_Y, 100, 10, 0, 255 ) + + PORT_START /* IN5 */ + PORT_ANALOG( 0xff, 0x80, IPT_AD_STICK_X, 100, 10, 0, 255 ) + + INPUT_PORTS_END + +/************************************* + * + * Graphics definitions + * + *************************************/ + +static struct GfxLayout tilelayout = +{ + 8, 8, /* 8*8 tiles */ + 256, /* 256 tiles */ + 4, /* 4 bits per pixel */ + { 0, 1, 2, 3 }, /* the bitplanes are packed in one nibble */ + { 0 * 4, 1 * 4, 2 * 4, 3 * 4, 4 * 4, 5 * 4, 6 * 4, 7 * 4 }, + { 0 * 32, 1 * 32, 2 * 32, 3 * 32, 4 * 32, 5 * 32, 6 * 32, 7 * 32 }, + 32 * 8 /* every tile takes 32 consecutive bytes */ +}; + +static struct GfxLayout spritelayout = +{ + 16,16, /* 16*16 sprites */ + RGN_FRAC(1,5), /* NUM characters */ + 5, /* 5 bits per pixel */ + { RGN_FRAC(0,5), RGN_FRAC(1,5), RGN_FRAC(2,5), RGN_FRAC(3,5), RGN_FRAC(4,5) }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16 }, + 32 * 8 /* every sprite takes 32 consecutive bytes */ +}; + +static struct GfxDecodeInfo gfxdecodeinfo[] = +{ + { REGION_GFX1, 0, &tilelayout, 0, 16 }, + { REGION_GFX2, 0, &spritelayout, 256, 32 }, + { -1 } /* end of array */ +}; + +/************************************* + * + * Sound interfaces + * + *************************************/ + +static struct POKEYinterface pokey_interface = +{ + 4, /* 4 chips */ + 1000000, /* 1MHz? */ + { 10, 10, 10, 10 }, /* volume */ + /* The 8 pot handlers */ + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + /* The allpot handler */ + { 0, 0, 0, 0 }, +}; + +static struct TMS5220interface tms5220_interface = +{ + 640000, /* clock speed (80*samplerate) */ + 50, /* volume */ + 0 /* IRQ handler */ +}; + +/************************************* + * + * Machine driver + * + *************************************/ + +static MACHINE_DRIVER_START( firefox ) + + /* basic machine hardware */ + MDRV_CPU_ADD(M6809,4000000) + MDRV_CPU_MEMORY(readmem,writemem) + + MDRV_CPU_ADD(M6502,2000000) + MDRV_CPU_MEMORY(sound_readmem,sound_writemem) + + MDRV_FRAMES_PER_SECOND(60) + MDRV_VBLANK_DURATION(DEFAULT_REAL_60HZ_VBLANK_DURATION) + + MDRV_MACHINE_INIT(firefox) + MDRV_NVRAM_HANDLER(firefox) + + /* video hardware */ + MDRV_VIDEO_ATTRIBUTES( VIDEO_TYPE_RASTER | VIDEO_PIXEL_ASPECT_RATIO_2_1 | VIDEO_NEEDS_6BITS_PER_GUN ) + MDRV_SCREEN_SIZE(64*8, 64*8) + MDRV_VISIBLE_AREA(6*8, 54*8-1, 1*8, 62*8-1) + MDRV_GFXDECODE(gfxdecodeinfo) + MDRV_PALETTE_LENGTH(512) + + MDRV_VIDEO_UPDATE(firefox) + + /* sound hardware */ + MDRV_SOUND_ADD(POKEY, pokey_interface) + MDRV_SOUND_ADD(TMS5220, tms5220_interface) + /* laser disk sound */ + MDRV_SOUND_ADD(CUSTOM, laserdisk_interface) +MACHINE_DRIVER_END + +/************************************* + * + * ROM definitions + * + *************************************/ + +ROM_START( firefox ) + ROM_REGION( 0x30000, REGION_CPU1, 0 ) /* 64k for code + data & 128k for banked roms */ + ROM_LOAD( "136026.209", 0x04000, 0x4000, CRC(9f559f1b) SHA1(142d14cb5158ea77f6fc6d9bf0ce723842f345e2) ) /* 8b/c */ + ROM_LOAD( "136026.210", 0x08000, 0x4000, CRC(d769b40d) SHA1(2d354649a381f3399cb0161267bd1c36a8f2bb4b) ) /* 7b/c */ + ROM_LOAD( "136026.211", 0x0c000, 0x4000, CRC(7293ab03) SHA1(73d0d173da295ad59e431bab0a9814a71146cbc2) ) /* 6b/c */ + ROM_LOAD( "136026.201", 0x10000, 0x4000, CRC(c118547a) SHA1(4d3502cbde3116588ed944bf1750bab50e4c813c) ) /* 8a */ + /* empty 7a */ + /* empty 6a */ + /* empty 5a */ + ROM_LOAD( "136026.205", 0x20000, 0x4000, CRC(dc21677f) SHA1(576a96c1e07e1362a0a367e76dc369ee8a950144) ) /* 4a */ + ROM_LOAD( "136026.127", 0x24000, 0x2000, CRC(c0c765ab) SHA1(79f6c8c1d00684d7143b2d33a5669bdf5cd01e96) ) /* 3a */ + ROM_RELOAD( 0x26000, 0x2000 ) + /* empty 2a */ + /* empty 1a */ + + ROM_REGION( 0x10000, REGION_CPU2, 0 ) /* 64k for code */ + /* empty 4k/l */ + ROM_LOAD( "136026.128", 0x08000, 0x2000, CRC(5358d870) SHA1(e8f2983a7e612e1a050a3c0b9f19b1077de4c146) ) /* 4m */ + ROM_RELOAD( 0x0a000, 0x2000 ) + ROM_LOAD( "136026.214", 0x0c000, 0x4000, CRC(92378b78) SHA1(62c7a1fee675fa3f9125f8e208b8207f0ce28bbe) ) /* 4n */ + + ROM_REGION( 0x2000, REGION_GFX1, ROMREGION_DISPOSE ) /* tiles */ + ROM_LOAD( "136026.125", 0x0000, 0x2000, CRC(8a32f9f1) SHA1(f899174f55cd4a24a3be4a0f4bb44d3e8e938586) ) /* 6p */ + + ROM_REGION( 0x28000, REGION_GFX2, ROMREGION_DISPOSE ) /* sprites */ + /* empty 6c */ + /* empty 6a */ + ROM_LOAD( "136026.124", 0x00000, 0x4000, CRC(5efe0f6c) SHA1(df35fd9267d966ab379c2f78ed418f4606741b28)) /* 5c */ + ROM_LOAD( "136026.123", 0x04000, 0x4000, CRC(dffe48b3) SHA1(559907651bb425e26a834b467959b15092d23d27)) /* 5a */ + ROM_LOAD( "136026.118", 0x08000, 0x4000, CRC(0ed4df15) SHA1(7aa599f428112fff4bfedf63fafc22f19fa66546)) /* 4c */ + ROM_LOAD( "136026.122", 0x0c000, 0x4000, CRC(8e2c6616) SHA1(59cbd585028bb634034a9dfd552275bd41f01989)) /* 4a */ + ROM_LOAD( "136026.117", 0x10000, 0x4000, CRC(79129084) SHA1(4219ff7cd444ad11e4cb9f1c30ac15fe0cfc5a17)) /* 3c */ + ROM_LOAD( "136026.121", 0x14000, 0x4000, CRC(494972d4) SHA1(fa0e24e911b233e9644d7794ba03f76bfd39aa8c)) /* 3a */ + ROM_LOAD( "136026.116", 0x18000, 0x4000, CRC(d5282d4e) SHA1(de5fdf82a615625aa77b39e035b4206216faaf9c)) /* 2c */ + ROM_LOAD( "136026.120", 0x1c000, 0x4000, CRC(e1b95923) SHA1(b6d0c0af0a8f55e728cd0f4c3222745eefd57f50)) /* 2a */ + ROM_LOAD( "136026.115", 0x20000, 0x4000, CRC(861abc82) SHA1(1845888d07162ae915364a2a91294731f1c5b3bd)) /* 1c */ + ROM_LOAD( "136026.119", 0x24000, 0x4000, CRC(959471b1) SHA1(a032209a209f51d34360d5c7ad32ec62150158d2)) /* 1a */ +ROM_END + +ROM_START( firefoxa ) + ROM_REGION( 0x30000, REGION_CPU1, 0 ) /* 64k for code + data & 128k for banked roms */ + ROM_LOAD( "136026.109", 0x04000, 0x4000, CRC(7639270c) SHA1(1)) /* 8b/c */ + ROM_LOAD( "136026.110", 0x08000, 0x4000, CRC(f3102944) SHA1(1)) /* 7b/c */ + ROM_LOAD( "136026.111", 0x0c000, 0x4000, CRC(8a230bb5) SHA1(1)) /* 6b/c */ + ROM_LOAD( "136026.101", 0x10000, 0x4000, CRC(91bba45a) SHA1(1)) /* 8a */ + ROM_LOAD( "136026.102", 0x14000, 0x4000, CRC(5f1e423d) SHA1(1)) /* 7a */ + /* empty 6a */ + /* empty 5a */ + ROM_LOAD( "136026.105", 0x20000, 0x4000, CRC(83f1d4ed) SHA1(1)) /* 4a */ + ROM_LOAD( "136026.106", 0x24000, 0x4000, CRC(c5d8d417) SHA1(1)) /* 3a */ + /* empty 2a */ + /* empty 1a */ + + ROM_REGION( 0x10000, REGION_CPU2, 0 ) /* 64k for code */ + /* empty 4k/l */ + ROM_LOAD( "136026.113", 0x08000, 0x4000, CRC(90988b3b) SHA1(1)) /* 4m */ + ROM_LOAD( "136026.114", 0x0c000, 0x4000, CRC(1437ce14) SHA1(1)) /* 4n */ + + ROM_REGION( 0x2000, REGION_GFX1, ROMREGION_DISPOSE ) /* tiles */ + ROM_LOAD( "136026.125", 0x0000, 0x2000, CRC(8a32f9f1) SHA1(1)) /* 6p */ + + ROM_REGION( 0x28000, REGION_GFX2, ROMREGION_DISPOSE ) /* sprites */ + /* empty 6c */ + /* empty 6a */ + ROM_LOAD( "136026.124", 0x00000, 0x4000, CRC(5efe0f6c) SHA1(1)) /* 5c */ + ROM_LOAD( "136026.123", 0x04000, 0x4000, CRC(dffe48b3) SHA1(1)) /* 5a */ + ROM_LOAD( "136026.118", 0x08000, 0x4000, CRC(0ed4df15) SHA1(1)) /* 4c */ + ROM_LOAD( "136026.122", 0x0c000, 0x4000, CRC(8e2c6616) SHA1(1)) /* 4a */ + ROM_LOAD( "136026.117", 0x10000, 0x4000, CRC(79129084) SHA1(1)) /* 3c */ + ROM_LOAD( "136026.121", 0x14000, 0x4000, CRC(494972d4) SHA1(1)) /* 3a */ + ROM_LOAD( "136026.116", 0x18000, 0x4000, CRC(d5282d4e) SHA1(1)) /* 2c */ + ROM_LOAD( "136026.120", 0x1c000, 0x4000, CRC(e1b95923) SHA1(1)) /* 2a */ + ROM_LOAD( "136026.115", 0x20000, 0x4000, CRC(861abc82) SHA1(1)) /* 1c */ + ROM_LOAD( "136026.119", 0x24000, 0x4000, CRC(959471b1) SHA1(1)) /* 1a */ +ROM_END + +/************************************* + * + * Game drivers + * + *************************************/ + +GAME( 1984, firefox, 0, firefox, firefox, 0, ROT0, "Atari", "Fire Fox (set 1)" ) +GAME( 1984, firefoxa, firefox, firefox, firefox, 0, ROT0, "Atari", "Fire Fox (set 2)" ) diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/drivers/gottlieb.c xmame-laser/src/drivers/gottlieb.c --- xmame-0.78.1/src/drivers/gottlieb.c Fri Dec 26 23:29:07 2003 +++ xmame-laser/src/drivers/gottlieb.c Tue Jan 20 00:02:55 2004 @@ -146,8 +146,11 @@ ***************************************************************************/ +#include "mame.h" #include "driver.h" +#include "artwork.h" #include "vidhrdw/generic.h" +#include "vidhrdw/laserdsk.h" extern UINT8 *gottlieb_charram; @@ -245,8 +248,6 @@ } -static int current_frame = 1; -static int laserdisc_playing; static int lasermpx; static int audioptr; static int audioready=1; @@ -277,12 +278,12 @@ switch (offset) { case 0: - tmp = current_frame % 100; + tmp = (laser_disc_field >> 1) % 100; logerror("LSB frame read: %d\n",tmp); return ((tmp / 10) << 4) | (tmp % 10); break; case 1: - tmp = (current_frame / 100) % 100; + tmp = ((laser_disc_field >> 1) / 100) % 100; logerror("MSB frame read: %d\n",tmp); return ((tmp / 10) << 4) | (tmp % 10); break; @@ -294,7 +295,7 @@ /* bit 5 disc ready */ /* bit 6 break in audio trasmission */ /* bit 7 missing audio clock */ - return ((current_frame / 10000) & 0x7) | (audioready << 3) | 0x10 | (discready << 5); + return (((laser_disc_field >> 1) / 10000) & 0x7) | (audioready << 3) | 0x10 | (discready << 5); } else { /* read audio buffer */ if (skipfirstbyte) audioptr++; skipfirstbyte = 0; @@ -322,6 +323,7 @@ { static int loop; int cmd; + static int current_frame = 0; /* commands are written in three steps, the first two the command is */ /* written (maybe one to load the latch, the other to start the send), */ @@ -353,23 +355,26 @@ { if (cmd == 0x04) /* step forward */ { - laserdisc_playing = 0; - current_frame++; + laser_disc_speed = 0; + laser_disc_step(1); + laser_disc_field += 2; } if (cmd == 0x05) /* play */ { - laserdisc_playing = 1; + laser_disc_speed = 1; discready = 1; } if (cmd == 0x0b) /* seek frame */ { - laserdisc_playing = 0; + laser_seek_frame(current_frame); + laser_disc_field = current_frame << 1; + laser_disc_speed = 0; discready = 0; access_time = 60; /* 1s access time */ } if (cmd == 0x0f) /* stop */ { - laserdisc_playing = 0; + laser_disc_speed = 0; discready = 0; } lastcmd = cmd; @@ -382,12 +387,13 @@ access_time--; if (access_time == 0) discready = 1; - } else if (laserdisc_playing) { - odd_field ^= 1; + } else if (laser_disc_speed) { + laser_disc_field += laser_disc_speed; + odd_field = laser_disc_field & 0x1; if (odd_field) /* the manual says the video frame number is only present in the odd field) */ { - current_frame++; -logerror("current frame : %d\n",current_frame); + int current_frame = laser_disc_field >> 1; + logerror("current frame : %d\n",current_frame); if (current_frame%53==0) { @@ -1388,8 +1394,6 @@ { 0 } }; - - /******************************************************************** * * Machine Driver macro @@ -1514,6 +1518,8 @@ MDRV_IMPORT_FROM(gottlieb2) MDRV_CPU_MODIFY("main") MDRV_CPU_MEMORY(gottlieb_readmem,usvsthem_writemem) + /* laser disk sound */ + MDRV_SOUND_ADD(CUSTOM, laserdisk_interface) MACHINE_DRIVER_END @@ -1858,7 +1864,7 @@ ROM_LOAD( "mach3fg0.bin", 0x6000, 0x2000, CRC(0bae12a5) SHA1(7bc0b82ccab0e4498a7a2a9dc85f03125f25826e) ) ROM_REGION( 1024*1024, REGION_USER1, 0) /* about 30 min of target data from laserdisc */ - ROM_LOAD( "m3target.bin", 0, 1024*1024, CRC(6e779a6f) SHA1(e556ad438e637a71f17ea04088de10b39b45f8df) ) + ROM_LOAD( "m3target.bin", 0, 0xed400, CRC(a2a9f8e5) SHA1(5ca2e4dd86882009ea1496f91e1fc8612ae4bf5e) ) ROM_END ROM_START( usvsthem ) diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/fileio.c xmame-laser/src/fileio.c --- xmame-0.78.1/src/fileio.c Fri Dec 26 23:29:12 2003 +++ xmame-laser/src/fileio.c Tue Jan 20 00:00:37 2004 @@ -106,6 +106,9 @@ case FILETYPE_ARTWORK: case FILETYPE_HISTORY: case FILETYPE_LANGUAGE: + case FILETYPE_LASERDISK_VIDEO: + case FILETYPE_LASERDISK_FLAC: + case FILETYPE_LASERDISK_FRAME_SEEKS: #ifndef MESS case FILETYPE_INI: #endif @@ -242,6 +245,11 @@ return generic_fopen(filetype, NULL, gamename, 0, openforwrite ? FILEFLAG_OPENWRITE : FILEFLAG_OPENREAD); #endif + case FILETYPE_LASERDISK_VIDEO: + case FILETYPE_LASERDISK_FLAC: + case FILETYPE_LASERDISK_FRAME_SEEKS: + return generic_fopen(filetype, gamename, filename, 0, FILEFLAG_OPENREAD); + /* anything else */ default: logerror("mame_fopen(): unknown filetype %02x\n", filetype); @@ -784,6 +792,9 @@ case FILETYPE_HIGHSCORE_DB: /* highscore database/history files */ case FILETYPE_HISTORY: /* game history files */ case FILETYPE_CHEAT: /* cheat file */ + case FILETYPE_LASERDISK_VIDEO: + case FILETYPE_LASERDISK_FLAC: + case FILETYPE_LASERDISK_FRAME_SEEKS: default: /* anything else */ extension = NULL; break; diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/fileio.h xmame-laser/src/fileio.h --- xmame-0.78.1/src/fileio.h Fri Dec 26 23:29:12 2003 +++ xmame-laser/src/fileio.h Mon Jan 19 22:00:24 2004 @@ -40,6 +40,9 @@ FILETYPE_LANGUAGE, FILETYPE_CTRLR, FILETYPE_INI, + FILETYPE_LASERDISK_FLAC, + FILETYPE_LASERDISK_VIDEO, + FILETYPE_LASERDISK_FRAME_SEEKS, #ifdef MESS FILETYPE_CRC, #endif diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/mame.c xmame-laser/src/mame.c --- xmame-0.78.1/src/mame.c Fri Jan 9 01:46:23 2004 +++ xmame-laser/src/mame.c Mon Jan 19 21:34:57 2004 @@ -1276,6 +1276,10 @@ } +struct mame_display *get_current_display() +{ + return ¤t_display; +} /*------------------------------------------------- recompute_fps - recompute the frame rate diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/mame.h xmame-laser/src/mame.h --- xmame-0.78.1/src/mame.h Fri Jan 9 01:46:25 2004 +++ xmame-laser/src/mame.h Mon Jan 19 21:34:57 2004 @@ -383,6 +383,8 @@ /* return the index of the given CPU, or -1 if not found */ int mame_find_cpu_index(const char *tag); +struct mame_display *get_current_display(); + #ifdef MESS #include "mess.h" #endif /* MESS */ diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/mame.mak xmame-laser/src/mame.mak --- xmame-0.78.1/src/mame.mak Fri Dec 26 23:28:54 2003 +++ xmame-laser/src/mame.mak Mon Jan 19 21:34:57 2004 @@ -325,7 +325,7 @@ $(OBJ)/vidhrdw/m107.o $(OBJ)/drivers/m107.o \ $(OBJ)/gottlieb.a: \ - $(OBJ)/vidhrdw/gottlieb.o $(OBJ)/sndhrdw/gottlieb.o $(OBJ)/drivers/gottlieb.o \ + $(OBJ)/vidhrdw/laserdsk.o $(OBJ)/vidhrdw/gottlieb.o $(OBJ)/sndhrdw/gottlieb.o $(OBJ)/drivers/gottlieb.o \ $(OBJ)/taito.a: \ $(OBJ)/drivers/sbowling.o \ @@ -619,6 +619,7 @@ $(OBJ)/machine/asteroid.o $(OBJ)/sndhrdw/asteroid.o \ $(OBJ)/sndhrdw/llander.o $(OBJ)/drivers/asteroid.o \ $(OBJ)/drivers/bwidow.o \ + $(OBJ)/drivers/firefox.o \ $(OBJ)/sndhrdw/bzone.o $(OBJ)/drivers/bzone.o \ $(OBJ)/sndhrdw/redbaron.o \ $(OBJ)/drivers/tempest.o \ diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/unix/fileio.c xmame-laser/src/unix/fileio.c --- xmame-0.78.1/src/unix/fileio.c Fri Dec 26 23:29:16 2003 +++ xmame-laser/src/unix/fileio.c Mon Jan 19 23:58:43 2004 @@ -348,6 +348,11 @@ list = &pathlist[FILETYPE_ROM]; break; #endif + case FILETYPE_LASERDISK_FLAC: + case FILETYPE_LASERDISK_VIDEO: + case FILETYPE_LASERDISK_FRAME_SEEKS: + list=&pathlist[FILETYPE_ROM]; + break; default: list = &pathlist[filetype]; diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/vidhrdw/gottlieb.c xmame-laser/src/vidhrdw/gottlieb.c --- xmame-0.78.1/src/vidhrdw/gottlieb.c Fri Dec 26 23:29:12 2003 +++ xmame-laser/src/vidhrdw/gottlieb.c Mon Jan 19 22:11:24 2004 @@ -9,6 +9,7 @@ #include "driver.h" #include "common.h" #include "vidhrdw/generic.h" +#include "vidhrdw/laserdsk.h" UINT8 *gottlieb_charram; @@ -198,6 +199,10 @@ VIDEO_UPDATE( gottlieb ) { + /* some of the games had a laserdisk */ + if(laser_disc_speed) + run_laser_disc(); + if (!background_priority) { tilemap_draw(bitmap, &Machine->visible_area, bg_tilemap, TILEMAP_IGNORE_TRANSPARENCY, 0); diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/vidhrdw/laserdsk.c xmame-laser/src/vidhrdw/laserdsk.c --- xmame-0.78.1/src/vidhrdw/laserdsk.c Thu Jan 1 01:00:00 1970 +++ xmame-laser/src/vidhrdw/laserdsk.c Mon Jan 19 23:59:25 2004 @@ -0,0 +1,402 @@ +#include +#include +#include +#include +#include + +#include "mame.h" +#include "driver.h" +#include "palette.h" +#include "common.h" +#include "mpeg2.h" +#include "convert.h" +#include "laserdsk.h" +#include "osdepend.h" +#include "FLAC/seekable_stream_decoder.h" +#include "artwork.h" + +#define TRUE 1 +#define FALSE 0 + +const static FLAC__Frame *decode_flac_frame; +const FLAC__int32 *decoded_flac_channel; +static char flacFilename[FILENAME_MAX]; +static FLAC__SeekableStreamDecoder *flacDecoder; +static void *flacFile; +static int decoded_samples = 0; // number of unstreamed samples in the decoded buffer +static int decode_buffer_pos = 0; // track position in the decoded buffer +typedef struct { + long frame; + long long seek_pos; + long long flac_seek_pos; +} FramePtr; + +FramePtr *frame_ptrs; +int no_ptrs; + + +char lsr_filename[20]; +const char *m_gamename; +mame_file *file; +mpeg2dec_t *mpeg2dec; +const mpeg2_info_t *info; +int framenum = 0; +#define BUFFER_SIZE 65536 +uint8_t buffer[BUFFER_SIZE]; +int g_width = 0, g_height; +int offset, flac_offset; /* allows the audio to come from a different source */ +int state = -1; + +#define PLAYER_FRAME (laser_disc_field >> 1) + + +int laser_disc_speed; +int mpeg_frame = -1; +int laser_disc_field = 0; /* 0 is the first field of the first frame + 1 is the second field of the first frame + etc */ +/* as some laser disc material is interlaced, we only get a full frame every + other field/screen refresh. Attempt to improve performance by doing + the mpeg decode in the first field and the scaling in the second */ +/* the PLAYER_FRAME will move to the next frame on the first field, + but should not be drawn until the second field */ +void run_laser_disc() +{ + struct artwork_piece *video; + struct mame_display *display; + struct timeval tv, tv2; + struct timeval tva, tva2; + struct rectangle *u_invalid; + static int last_scaled_field = -1; + + gettimeofday(&tv, NULL); + if(laser_disc_speed) + { + /* + fprintf(stderr, "field %d, mpeg %d", + laser_disc_field, mpeg_frame); + */ + if(mpeg_frame < PLAYER_FRAME) + { + laser_disc_step(1); + } + video = get_laser_disc_artwork_piece(); + display = get_current_display(); + if((last_scaled_field != laser_disc_field) && + (laser_disc_field & 1) && + (display->changed_flags & GAME_BITMAP_CHANGED)) + { + copy_current_mpeg_buf_to_bitmap(video->rawbitmap); + + scale_bitmap(video, video->bounds.max_x - video->bounds.min_x + 1, + video->bounds.max_y - video->bounds.min_y + 1); + u_invalid = get_video_invalid(); + /* mark the whole thing as invalid */ + u_invalid->min_x = u_invalid->min_y = 0; + u_invalid->max_x = video->bounds.max_x; + u_invalid->max_y = video->bounds.max_y; + } + } +} + +void load_frame_ptrs(const char *gamename, char *filename) +{ + mame_file *f = mame_fopen(gamename, filename, FILETYPE_LASERDISK_FRAME_SEEKS, + 0); + + UINT64 file_size; + int i; + + if(!f) + { + fprintf(stderr, "could not open file %s\n", filename); + exit(-1); + } + file_size = mame_fsize(f); + if((file_size - 2 * sizeof(int)) % sizeof(FramePtr)) + { + fprintf(stderr, "frame file not a multiple of struct size\n"); + return; + } + mame_fread(f, &offset, sizeof(offset)); + mame_fread(f, &flac_offset, sizeof(flac_offset)); + no_ptrs = (file_size - 2 * sizeof(int)) / sizeof(FramePtr); + frame_ptrs = (FramePtr *)(malloc(sizeof(FramePtr) * no_ptrs)); + for(i = 0; i < no_ptrs; i++) + { + mame_fread(f, &(frame_ptrs[i]), sizeof(FramePtr)); + } + + mame_fclose(f); +} + +void copy_current_mpeg_buf_to_bitmap(struct mame_bitmap *bm) +{ + int y; + uint8_t * buf; + + if(info->display_fbuf && g_width) + { + buf = info->display_fbuf->buf[0]; + bm->base = buf; + bm->rowpixels = g_width; /* no BITMAP_SAFETY */ + /* initialize the line pointers */ + for (y = 0; y < g_height; y++) + bm->line[y] = &buf[y * g_width * 4]; + } +} + + +int laser_disc_step (int convert_rgb) +{ + + int done = FALSE; + int size = 1; + + struct timeval tv, tv2; + + gettimeofday(&tv, NULL); + do { + state = mpeg2_parse (mpeg2dec); + switch (state) { + case STATE_BUFFER: + size = mame_fread(file, buffer, BUFFER_SIZE); + mpeg2_buffer (mpeg2dec, buffer, buffer + size); + break; + case STATE_SEQUENCE: + + if(convert_rgb) + { + mpeg2_convert (mpeg2dec, convert_rgb32, NULL); + } + break; + case STATE_SLICE: + case STATE_END: + if (info->display_fbuf) + { + g_width = info->sequence->width; + g_height = info->sequence->height; + } + mpeg_frame++; + done = TRUE; + break; + } + } while (!done && size); + + return(done); +} + + +void laser_seek_frame(int frame) +{ + int skip = 0; + int must_have = 3; + int desired_frame; + int flac_frame; + + + desired_frame = frame; + flac_frame = frame + flac_offset; + if(flac_frame < 0) flac_frame = 0; + + frame += offset; + + // seek the audio + if(flacDecoder && !FLAC__seekable_stream_decoder_seek_absolute(flacDecoder, + frame_ptrs[flac_frame].flac_seek_pos)) + { + logerror("could not seek flac\n"); + } + + /* clear buffer */ + mpeg2_reset(mpeg2dec, 0); + + while((must_have > 0) || (frame_ptrs[frame].seek_pos == -1)) + { + skip++; + must_have--; + frame --; + } + mame_fseek(file, frame_ptrs[frame].seek_pos, SEEK_SET); + + + while(skip-- > 1) + laser_disc_step(0); + + laser_disc_step(1); + mpeg_frame = desired_frame; +} + +void reset_mpeg() +{ + mame_fclose(file); + mpeg2_close(mpeg2dec); + init_mpeg(m_gamename); + framenum = 0; + g_width = 0; +} + + +void init_mpeg(const char *gamename) +{ + sprintf(lsr_filename, "%s.lsr", gamename); + m_gamename = gamename; + file = mame_fopen (gamename, lsr_filename, FILETYPE_LASERDISK_VIDEO, 0); + if (!file) { + fprintf (stderr, "Could not open file %s\n", lsr_filename); + exit (1); + } + + load_frame_ptrs(gamename, "frame.bin"); + + mpeg2dec = mpeg2_init (); + if (mpeg2dec == NULL) + exit (1); + + info = mpeg2_info (mpeg2dec); + mpeg_frame = 0; + laser_disc_step(1); /* load the stream */ + return; +} + +// callback for the stream +// we need to get length words from the flac decode into the buffer +static void flac_update(int param, INT16 *buffer, int length) +{ + FLAC__bool res = true; + + //TODO: check for playing? probably a better way to stop the sound + if(laser_disc_speed) + { + while(length && res) + { + // need to decode some more data + if(!decoded_samples) + { + res = FLAC__seekable_stream_decoder_process_single(flacDecoder); + } + + while(decoded_samples && length) + { + *buffer++ = decoded_flac_channel[decode_buffer_pos++]; + length--; + decoded_samples--; + } + } + } + else + { + /* clear the sound ? */ + memset(buffer, 0, length << 1); + } +} + +static FLAC__SeekableStreamDecoderReadStatus flac_read(const FLAC__SeekableStreamDecoder *decoder, + FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + *bytes = mame_fread(flacFile, buffer, *bytes); + return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; +} + +static FLAC__SeekableStreamDecoderSeekStatus flac_seek(const FLAC__SeekableStreamDecoder *decoder, + FLAC__uint64 absolute_byte_offset, void *client_data) +{ + mame_fseek(flacFile, absolute_byte_offset, SEEK_SET); + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; +} + +static FLAC__SeekableStreamDecoderTellStatus flac_tell(const FLAC__SeekableStreamDecoder *decoder, + FLAC__uint64 *absolute_byte_offset, void *client_data) +{ + *absolute_byte_offset = mame_ftell(flacFile); + return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; +} + +static FLAC__SeekableStreamDecoderLengthStatus flac_length(const FLAC__SeekableStreamDecoder *decoder, + FLAC__uint64 *stream_length, void *client_data) +{ + *stream_length = mame_fsize(flacFile); + return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; +} + +static FLAC__bool flac_eof(const FLAC__SeekableStreamDecoder *decoder, void *client_data) +{ + return(mame_feof(flacFile)); +} + +static FLAC__StreamDecoderWriteStatus flac_write(const FLAC__SeekableStreamDecoder *decoder, + const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + decode_flac_frame = frame; + decoded_flac_channel = buffer[0]; + decoded_samples = frame->header.blocksize; + decode_buffer_pos = 0; + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; // or ABORT +} + +static void flac_metadata(const FLAC__SeekableStreamDecoder *decoder, + const FLAC__StreamMetadata *metadata, void *client_data) +{ + +} + +static void flac_error(const FLAC__SeekableStreamDecoder *decoder, + FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + logerror("flac decode error %d\n", (int)status); +} + +static void init_flac() +{ + sprintf(flacFilename, "%s.flac", Machine->gamedrv->name); + flacFile = mame_fopen(Machine->gamedrv->name, flacFilename, FILETYPE_LASERDISK_FLAC, 0); + if(flacFile) + { + flacDecoder = FLAC__seekable_stream_decoder_new(); + FLAC__seekable_stream_decoder_set_read_callback(flacDecoder, flac_read); + FLAC__seekable_stream_decoder_set_seek_callback(flacDecoder, flac_seek); + FLAC__seekable_stream_decoder_set_tell_callback(flacDecoder, flac_tell); + FLAC__seekable_stream_decoder_set_length_callback(flacDecoder, flac_length); + FLAC__seekable_stream_decoder_set_eof_callback(flacDecoder, flac_eof); + FLAC__seekable_stream_decoder_set_write_callback(flacDecoder, flac_write); + FLAC__seekable_stream_decoder_set_metadata_callback(flacDecoder, flac_metadata); + FLAC__seekable_stream_decoder_set_error_callback(flacDecoder, flac_error); + if(FLAC__seekable_stream_decoder_init(flacDecoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) + { + logerror("flac init failed\n"); + } + } + else + { + fprintf(stderr, "flac file %s not found\n", flacFilename); + } +} + +/* laserdisk sound emulation */ +static int custom_start_flac(const struct MachineSound *msound) +{ + // name, mixing level, sample_rate, param, callback) + stream_init("laserdisk", 50, 44100, 0, flac_update); + init_flac(); + // return 1 if error + return 0; +} + +static void custom_stop_flac() +{ +} + +// this seems to be called for every frame? +static void custom_update_flac() +{ +} + +// What's all this for, perhaps to customise the sound chip per game? +// use the custom driver +struct CustomSound_interface laserdisk_interface = +{ + custom_start_flac, /* start */ + custom_stop_flac, /* stop */ + custom_update_flac /* update, could be called through stream_init? */ +}; + diff --exclude-from=if --new-file -u -r xmame-0.78.1/src/vidhrdw/laserdsk.h xmame-laser/src/vidhrdw/laserdsk.h --- xmame-0.78.1/src/vidhrdw/laserdsk.h Thu Jan 1 01:00:00 1970 +++ xmame-laser/src/vidhrdw/laserdsk.h Mon Jan 19 21:34:57 2004 @@ -0,0 +1,11 @@ +#include "FLAC/seekable_stream_decoder.h" +#include "sndintrf.h" + +extern int laser_disc_field; +extern int laser_disc_speed; +extern struct CustomSound_interface laserdisk_interface; +void init_mpeg(const char *gamename); +int laser_disc_step(int convert_rgb); +void copy_current_mpeg_buf_to_bitmap(struct mame_bitmap *bm); +void run_laser_disc(); +void laser_seek_frame(int frame);