diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/makefile mame-firefox/makefile
*** mame/makefile	Wed Jan 28 18:59:16 2004
--- mame-firefox/makefile	Sun Feb 15 11:27:25 2004
***************
*** 95,111 ****
  
  DEFS = -DX86_ASM -DLSB_FIRST -DINLINE="static __inline__" -Dasm=__asm__
  
! CFLAGS = -std=gnu99 -Isrc -Isrc/includes -Isrc/$(MAMEOS) -I$(OBJ)/cpu/m68000 -Isrc/cpu/m68000
  
  ifdef SYMBOLS
! CFLAGS += -O0 -Werror -Wall -Wno-unused -g
  else
  CFLAGS += -DNDEBUG \
! 	$(ARCH) -O3 -fomit-frame-pointer -fstrict-aliasing \
! 	-Werror -Wall -Wno-sign-compare -Wunused \
  	-Wpointer-arith -Wbad-function-cast -Wcast-align -Waggregate-return \
  	-Wshadow -Wstrict-prototypes -Wundef \
! 	-Wformat-security -Wwrite-strings \
  	-Wdisabled-optimization \
  #	-Wredundant-decls
  #	-Wfloat-equal
--- 95,111 ----
  
  DEFS = -DX86_ASM -DLSB_FIRST -DINLINE="static __inline__" -Dasm=__asm__
  
! CFLAGS = -std=gnu99 -Isrc -Isrc/includes -Isrc/$(MAMEOS) -I$(OBJ)/cpu/m68000 -Isrc/cpu/m68000 -I/usr/local/include/mpeg2dec -I/usr/local/include
  
  ifdef SYMBOLS
! CFLAGS += -O0 -Wno-unused -g
  else
  CFLAGS += -DNDEBUG \
! 	$(ARCH) -O2 -fomit-frame-pointer -fstrict-aliasing \
! 	-Wno-sign-compare -Wunused \
  	-Wpointer-arith -Wbad-function-cast -Wcast-align -Waggregate-return \
  	-Wshadow -Wstrict-prototypes -Wundef \
! 	-Wformat -Wformat-security -Wwrite-strings \
  	-Wdisabled-optimization \
  #	-Wredundant-decls
  #	-Wfloat-equal
***************
*** 139,145 ****
  endif
  
  # platform .mak files will want to add to this
! LIBS = -lz
  
  OBJDIRS = obj $(OBJ) $(OBJ)/cpu $(OBJ)/sound $(OBJ)/$(MAMEOS) \
  	$(OBJ)/drivers $(OBJ)/machine $(OBJ)/vidhrdw $(OBJ)/sndhrdw
--- 139,145 ----
  endif
  
  # platform .mak files will want to add to this
! LIBS = -L/usr/local/lib -lz -lmpeg2 -lvo -lFLAC -lmpeg2convert
  
  OBJDIRS = obj $(OBJ) $(OBJ)/cpu $(OBJ)/sound $(OBJ)/$(MAMEOS) \
  	$(OBJ)/drivers $(OBJ)/machine $(OBJ)/vidhrdw $(OBJ)/sndhrdw
***************
*** 182,196 ****
  # always recompile the version string
  	$(CC) $(CDEFS) $(CFLAGSPEDANTIC) -c src/version.c -o $(OBJ)/version.o
  	@echo Linking $@...
! 	$(LD) $(LDFLAGS) $(OBJS) $(COREOBJS) $(OSOBJS) $(LIBS) $(DRVLIBS) -o $@ $(MAPFLAGS)
  
  romcmp$(EXE): $(OBJ)/romcmp.o $(OBJ)/unzip.o
  	@echo Linking $@...
! 	$(LD) $(LDFLAGS) $^ -lz -o $@
  
  chdman$(EXE): $(OBJ)/chdman.o $(OBJ)/chd.o $(OBJ)/md5.o $(OBJ)/sha1.o $(OBJ)/version.o
  	@echo Linking $@...
! 	$(LD) $(LDFLAGS) $^ -lz -o $@
  
  xml2info$(EXE): src/xml2info/xml2info.c
  	@echo Compiling $@...
--- 182,196 ----
  # always recompile the version string
  	$(CC) $(CDEFS) $(CFLAGSPEDANTIC) -c src/version.c -o $(OBJ)/version.o
  	@echo Linking $@...
! 	$(LD) $(LDFLAGS) $(OBJS) $(COREOBJS) $(OSOBJS) $(LIBS) $(DRVLIBS) -lmpeg2convert -lmpeg2 -lFLAC -lvo -o $@ $(MAPFLAGS)
  
  romcmp$(EXE): $(OBJ)/romcmp.o $(OBJ)/unzip.o
  	@echo Linking $@...
! 	$(LD) $(LDFLAGS) -L/usr/local/lib $^ -lz -o $@
  
  chdman$(EXE): $(OBJ)/chdman.o $(OBJ)/chd.o $(OBJ)/md5.o $(OBJ)/sha1.o $(OBJ)/version.o
  	@echo Linking $@...
! 	$(LD) $(LDFLAGS) $^ -L/usr/local/lib -lz -lFLAC -o $@
  
  xml2info$(EXE): src/xml2info/xml2info.c
  	@echo Compiling $@...
diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/artwork.c mame-firefox/src/artwork.c
*** mame/src/artwork.c	Sun Oct 12 20:56:02 2003
--- mame-firefox/src/artwork.c	Sun Feb 15 11:29:47 2004
***************
*** 306,311 ****
--- 306,312 ----
  #include "vidhrdw/vector.h"
  #include <ctype.h>
  #include <math.h>
+ #include "vidhrdw/laserdsk.h"
  
  
  /***************************************************************************
***************
*** 334,340 ****
  	LAYER_MARQUEE,
  	LAYER_PANEL,
  	LAYER_SIDE,
! 	LAYER_FLYER
  };
  
  /* UI transparency hack */
--- 335,342 ----
  	LAYER_MARQUEE,
  	LAYER_PANEL,
  	LAYER_SIDE,
! 	LAYER_FLYER,
! 	LAYER_VIDEO
  };
  
  /* UI transparency hack */
***************
*** 352,390 ****
  
  ***************************************************************************/
  
- 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;
- };
- 
- 
  
  /***************************************************************************
  
--- 354,359 ----
***************
*** 397,407 ****
  static UINT32 transparent_color;
  
  static struct artwork_piece *artwork_list;
! static int num_underlays, num_overlays, num_bezels;
  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 rectangle gamerect, screenrect;
  static int gamescale;
  
--- 366,376 ----
  static UINT32 transparent_color;
  
  static struct artwork_piece *artwork_list;
! static int num_underlays, num_overlays, num_bezels, num_videos;
  static int num_pieces;
  
! 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,421 ****
--- 385,393 ----
  
  static const struct overlay_piece *overlay_list;
  
+ /* laserdisk tag */
+ static const char *TAG_LASERDISK = "[laserdiscvideo]";
+ static struct artwork_piece *video_piece;
  
  
  /***************************************************************************
***************
*** 429,435 ****
  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);
--- 401,406 ----
***************
*** 437,442 ****
--- 408,414 ----
  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,563 ****
--- 530,598 ----
  }
  
  
+ /*-------------------------------------------------
+ 	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,675 ****
--- 705,711 ----
  	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,776 ****
--- 807,813 ----
  		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,785 ****
--- 817,823 ----
  		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,804 ****
--- 837,846 ----
  				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,990 ****
--- 1027,1036 ----
  				/* 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,1012 ****
--- 1053,1073 ----
  	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)
  	{
***************
*** 1040,1045 ****
--- 1101,1107 ----
  
  	/* 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)
***************
*** 1056,1061 ****
--- 1118,1125 ----
  	underlay_invalid.max_x = 0;
  	overlay_invalid.max_x = 0;
  	bezel_invalid.max_x = 0;
+ 	video_invalid.max_x = 0;
+ 
  	return changed;
  }
  
***************
*** 1597,1602 ****
--- 1661,1822 ----
  
  
  /*-------------------------------------------------
+ 	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,2010 ****
--- 2225,2231 ----
  	num_underlays = 0;
  	num_overlays = 0;
  	num_bezels = 0;
+ 	num_videos = 0;
  	overlay_list = NULL;
  
  	/* if the user turned artwork off, bail */
***************
*** 2050,2061 ****
  			num_underlays++;
  		else if (piece->layer == LAYER_OVERLAY)
  			num_overlays++;
! 		else if (piece->layer >= LAYER_BEZEL)
  			num_bezels++;
  
  		/* load the graphics */
  		if (driver)
  			load_bitmap(driver->name, piece);
  	}
  // debugging
  //	fprintf(stderr, "backdrops=%d overlays=%d bezels=%d\n", num_underlays, num_overlays, num_bezels);
--- 2271,2291 ----
  			num_underlays++;
  		else if (piece->layer == LAYER_OVERLAY)
  			num_overlays++;
! 		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,2314 ****
--- 2539,2545 ----
  	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,2351 ****
  	given piece of artwork
  -------------------------------------------------*/
  
! static int scale_bitmap(struct artwork_piece *piece, int newwidth, int newheight)
  {
  	UINT32 sx, sxfrac, sxstep, sy, syfrac, systep;
  	UINT32 global_brightness, global_alpha;
  	int x, y;
  
  	/* 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);
--- 2567,2595 ----
  	given piece of artwork
  -------------------------------------------------*/
  
! /* 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;
+ 	int 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;
  
+ 	/* 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);
***************
*** 2357,2362 ****
--- 2601,2607 ----
  	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,2379 ****
  	/* 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;
--- 2618,2623 ----
***************
*** 2381,2391 ****
  		/* 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)
--- 2625,2630 ----
***************
*** 2414,2460 ****
  			xweight >>= FRAC_BITS - 8;
  			yweight >>= FRAC_BITS - 8;
  
  			/* 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));
  
  			/* 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 >>= 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 >>= 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 >>= 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;
  
  			/* compute the two pixel types */
  			*((UINT32 *)piece->prebitmap->base + y * piece->prebitmap->rowpixels + x) = compute_pre_pixel(a,r,g,b);
--- 2653,2716 ----
  			xweight >>= FRAC_BITS - 8;
  			yweight >>= FRAC_BITS - 8;
  
+ 			sxadx = sx + dx;
+ 			syady = sy + dy;
  			/* fetch the pixels */
! 			if(syady == -1)
! 			{
! 				syady = 0;
! 			}
! 
! 			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 = 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 = 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 = 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 */
! 			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,2620 ****
--- 2871,2877 ----
  	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,2673 ****
--- 2925,2931 ----
  	{
  		switch (piece->layer)
  		{
+ 			case LAYER_VIDEO:
  			case LAYER_BACKDROP:
  				if (options.use_artwork & ARTWORK_USE_BACKDROPS)
  					array[i++] = piece;
***************
*** 2975,2980 ****
--- 3233,3240 ----
  			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 -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/artwork.h mame-firefox/src/artwork.h
*** mame/src/artwork.h	Sun Oct 12 20:56:02 2003
--- mame-firefox/src/artwork.h	Sun Feb 15 11:27:25 2004
***************
*** 75,80 ****
--- 75,113 ----
  	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;
+ };
+ 
+ 
  
  
  /***************************************************************************
***************
*** 95,100 ****
--- 128,138 ----
  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(void);
+ struct rectangle *get_video_invalid(void);
+ struct rectangle *get_underlay_invalid(void);
+ int scale_bitmap(struct artwork_piece *piece, int newwidth, int newheight);
+ 
  mame_file *artwork_load_artwork_file(const struct GameDriver **driver);
  
  #endif /* ARTWORK_H */
diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/core.mak mame-firefox/src/core.mak
*** mame/src/core.mak	Wed Dec 24 16:31:10 2003
--- mame-firefox/src/core.mak	Sun Feb 15 12:11:12 2004
***************
*** 22,27 ****
--- 22,28 ----
  	$(OBJ)/vidhrdw/avgdvg.o $(OBJ)/machine/mathbox.o \
  	$(OBJ)/vidhrdw/poly.o $(OBJ)/vidhrdw/matrix3d.o \
  	$(OBJ)/vidhrdw/tlc34076.o \
+ 	$(OBJ)/vidhrdw/laserdsk.o \
  	$(OBJ)/machine/ticket.o $(OBJ)/machine/eeprom.o \
  	$(OBJ)/machine/6522via.o $(OBJ)/machine/mb87078.o \
  	$(OBJ)/machine/random.o \
diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/driver.c mame-firefox/src/driver.c
*** mame/src/driver.c	Wed Jan 28 19:03:52 2004
--- mame-firefox/src/driver.c	Sun Feb 15 11:27:25 2004
***************
*** 3800,3805 ****
--- 3800,3806 ----
  	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 -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/drivers/firefox.c mame-firefox/src/drivers/firefox.c
*** mame/src/drivers/firefox.c	Thu Jan  1 00:00:00 1970
--- mame-firefox/src/drivers/firefox.c	Sun Feb 15 12:59:23 2004
***************
*** 0 ****
--- 1,1224 ----
+ /*
+ 
+ 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 )
+ {
+ 	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 ADDRESS_MAP_START( readmem , ADDRESS_SPACE_PROGRAM, 8)
+ 	AM_RANGE(0x0000, 0x0fff) AM_READ(MRA8_RAM)
+ 	AM_RANGE( 0x1000, 0x1fff) AM_READ(MRA8_RAM)
+ 	AM_RANGE( 0x2000, 0x27ff) AM_READ(MRA8_RAM)
+ 	AM_RANGE( 0x2800, 0x2fff) AM_READ(MRA8_RAM)
+ 	AM_RANGE( 0x3000, 0x3fff) AM_READ(MRA8_BANK2)
+ 	AM_RANGE( 0x4000, 0x40ff) AM_READ(MRA8_RAM)
+ 	AM_RANGE( 0x4100, 0x4100) AM_READ(input_port_0_r)
+ 	AM_RANGE( 0x4101, 0x4101) AM_READ(firefox_misc_r)
+ 	AM_RANGE( 0x4102, 0x4102) AM_READ(firefox_disc_status_r)
+ 	AM_RANGE( 0x4103, 0x4103) AM_READ(input_port_2_r)
+ 	AM_RANGE( 0x4104, 0x4104) AM_READ(input_port_3_r)
+ 	AM_RANGE( 0x4105, 0x4105) AM_READ(firefox_disc_data_r)
+ 	AM_RANGE( 0x4106, 0x4106) AM_READ(firefox_mainrd_r)
+ 	AM_RANGE( 0x4107, 0x4107) AM_READ(firefox_pot_r)
+ 	AM_RANGE( 0x4400, 0xffff) AM_READ(MRA8_ROM)
+ ADDRESS_MAP_END
+ 
+ static ADDRESS_MAP_START( writemem , ADDRESS_SPACE_PROGRAM, 8)
+ 	AM_RANGE( 0x0000, 0x0fff) AM_WRITE(MWA8_RAM)
+ 	AM_RANGE( 0x1000, 0x1fff) AM_WRITE(MWA8_RAM) AM_BASE(&tileram) AM_SIZE(&tileram_size)
+ 	AM_RANGE( 0x2000, 0x27ff) AM_WRITE(MWA8_RAM) AM_BASE(&spriteram) AM_SIZE(&spriteram_size)
+ 	AM_RANGE( 0x2b00, 0x2b00) AM_WRITE(firefox_objram_bank_w)
+ 	AM_RANGE( 0x2b01, 0x2bff) AM_WRITE(MWA8_RAM)
+ 	AM_RANGE( 0x2800, 0x28ff) AM_WRITE(firefox_sprite_red_w) AM_BASE(&spriteredram )
+ 	AM_RANGE( 0x2900, 0x29ff) AM_WRITE(firefox_sprite_green_w) AM_BASE(&spritegreenram )
+ 	AM_RANGE( 0x2a00, 0x2aff) AM_WRITE(firefox_sprite_blue_w) AM_BASE(&spriteblueram )
+ 	AM_RANGE( 0x2c00, 0x2cff) AM_WRITE(firefox_tile_red_w) AM_BASE(&tileredram )
+ 	AM_RANGE( 0x2d00, 0x2dff) AM_WRITE(firefox_tile_green_w) AM_BASE(&tilegreenram)
+ 	AM_RANGE( 0x2e00, 0x2eff) AM_WRITE(firefox_tile_blue_w) AM_BASE(&tileblueram)
+ 	AM_RANGE( 0x2f00, 0x3fff) AM_WRITE(MWA8_RAM )
+ 	AM_RANGE( 0x4000, 0x40ff) AM_WRITE(MWA8_RAM) AM_BASE(&generic_nvram) AM_SIZE(&generic_nvram_size )
+ 	AM_RANGE( 0x4200, 0x4200) AM_WRITE(firefox_clearirq_w)
+ 	AM_RANGE( 0x4208, 0x4208) AM_WRITE(firefox_clearfirq_w)
+ 	AM_RANGE( 0x4210, 0x4210) AM_WRITE(watchdog_reset_w )
+ 	AM_RANGE( 0x4218, 0x4218) AM_WRITE(firefox_disc_read_w )
+ 	AM_RANGE( 0x4220, 0x4221) AM_WRITE(firefox_adchannel_w )
+ 	AM_RANGE( 0x4230, 0x4230) AM_WRITE(firefox_reset_w )
+ 	AM_RANGE( 0x4280, 0x4280) AM_WRITE(firefox_novram_recall_w )
+ 	AM_RANGE( 0x4281, 0x4281) AM_WRITE(firefox_soundrst_w )
+ 	AM_RANGE( 0x4282, 0x4282) AM_WRITE(firefox_novram_store_w )
+ 	AM_RANGE( 0x4283, 0x4283) AM_WRITE(firefox_disc_lock_w )
+ 	AM_RANGE( 0x4284, 0x4284) AM_WRITE(firefox_disc_right_audio_enable_w )
+ 	AM_RANGE( 0x4285, 0x4285) AM_WRITE(firefox_disc_left_audio_enable_w )
+ 	AM_RANGE( 0x4286, 0x4286) AM_WRITE(firefox_disc_reset_w )
+ 	AM_RANGE( 0x4287, 0x4287) AM_WRITE(firefox_disc_write_w )
+ 	AM_RANGE( 0x4288, 0x4289) AM_WRITE(firefox_coin_counter_w )
+ 	AM_RANGE( 0x428c, 0x428f) AM_WRITE(firefox_led_w )
+ 	AM_RANGE( 0x4290, 0x4290) AM_WRITE(firefox_rom_bank_w )
+ 	AM_RANGE( 0x4298, 0x4298) AM_WRITE(firefox_mainwr_w )
+ 	AM_RANGE( 0x42a0, 0x42a7) AM_WRITE(firefox_disc_data_w )
+ 	AM_RANGE( 0x4400, 0xffff) AM_WRITE(MWA8_ROM )
+ ADDRESS_MAP_END
+ 
+ /*************************************
+  *
+  *	Sound CPU memory handlers
+  *
+  *************************************/
+ 
+ static ADDRESS_MAP_START( sound_readmem, ADDRESS_SPACE_PROGRAM, 8)
+ 	AM_RANGE(0x0000, 0x07ff) AM_READ(MRA8_RAM )
+ 	AM_RANGE( 0x0800, 0x087f) AM_READ(MRA8_RAM ) /* pia ram */
+ 	AM_RANGE( 0x0880, 0x089f) AM_READ(firefox_pia_r )
+ 	AM_RANGE( 0x1000, 0x1000) AM_READ(firefox_soundrd_r )
+ 	AM_RANGE( 0x2000, 0x200f) AM_READ(pokey1_r )
+ 	AM_RANGE( 0x2800, 0x280f) AM_READ(pokey2_r )
+ 	AM_RANGE( 0x3000, 0x300f) AM_READ(pokey3_r )
+ 	AM_RANGE( 0x3800, 0x380f) AM_READ(pokey4_r )
+ 	AM_RANGE( 0x8000, 0xffff) AM_READ(MRA8_ROM )
+ ADDRESS_MAP_END
+ 
+ static ADDRESS_MAP_START( sound_writemem, ADDRESS_SPACE_PROGRAM, 8 )
+ 	AM_RANGE(0x0000, 0x07ff) AM_WRITE(MWA8_RAM )
+ 	AM_RANGE( 0x0800, 0x087f) AM_WRITE(MWA8_RAM ) /* pia ram */
+ 	AM_RANGE( 0x0880, 0x089f) AM_WRITE(firefox_pia_w )
+ 	AM_RANGE( 0x1800, 0x1800) AM_WRITE(firefox_soundwr_w )
+ 	AM_RANGE( 0x2000, 0x200f) AM_WRITE(pokey1_w )
+ 	AM_RANGE( 0x2800, 0x280f) AM_WRITE(pokey2_w )
+ 	AM_RANGE( 0x3000, 0x300f) AM_WRITE(pokey3_w )
+ 	AM_RANGE( 0x3800, 0x380f) AM_WRITE(pokey4_w )
+ 	AM_RANGE( 0x8000, 0xffff) AM_WRITE(MWA8_ROM )
+ ADDRESS_MAP_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_PROGRAM_MAP(readmem,writemem)
+ 
+ 	MDRV_CPU_ADD(M6502,2000000)
+ 	MDRV_CPU_PROGRAM_MAP(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 -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/drivers/gottlieb.c mame-firefox/src/drivers/gottlieb.c
*** mame/src/drivers/gottlieb.c	Wed Jan 28 19:01:24 2004
--- mame-firefox/src/drivers/gottlieb.c	Sun Feb 15 11:27:25 2004
***************
*** 146,153 ****
--- 146,156 ----
  
  ***************************************************************************/
  
+ #include "mame.h"
  #include "driver.h"
+ #include "artwork.h"
  #include "vidhrdw/generic.h"
+ #include "vidhrdw/laserdsk.h"
  
  extern UINT8 *gottlieb_charram;
  
***************
*** 242,249 ****
  }
  
  
- static int current_frame = 1;
- static int laserdisc_playing;
  static int lasermpx;
  static int audioptr;
  static int audioready=1;
--- 245,250 ----
***************
*** 274,285 ****
  	switch (offset)
  	{
  		case 0:
! 			tmp = current_frame % 100;
  			logerror("LSB frame read: %d\n",tmp);
  			return ((tmp / 10) << 4) | (tmp % 10);
  			break;
  		case 1:
! 			tmp = (current_frame / 100) % 100;
  			logerror("MSB frame read: %d\n",tmp);
  			return ((tmp / 10) << 4) | (tmp % 10);
  			break;
--- 275,286 ----
  	switch (offset)
  	{
  		case 0:
! 			tmp = (laser_disc_field >> 1) % 100;
  			logerror("LSB frame read: %d\n",tmp);
  			return ((tmp / 10) << 4) | (tmp % 10);
  			break;
  		case 1:
! 			tmp = ((laser_disc_field >> 1) / 100) % 100;
  			logerror("MSB frame read: %d\n",tmp);
  			return ((tmp / 10) << 4) | (tmp % 10);
  			break;
***************
*** 291,297 ****
  				/* 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);
  			} else {	/* read audio buffer */
  				if (skipfirstbyte) audioptr++;
  				skipfirstbyte = 0;
--- 292,298 ----
  				/* bit 5 disc ready */
  				/* bit 6 break in audio trasmission */
  				/* bit 7 missing audio clock */
! 				return (((laser_disc_field >> 1) / 10000) & 0x7) | (audioready << 3) | 0x10 | (discready << 5);
  			} else {	/* read audio buffer */
  				if (skipfirstbyte) audioptr++;
  				skipfirstbyte = 0;
***************
*** 319,324 ****
--- 320,326 ----
  {
  	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), */
***************
*** 350,372 ****
  	{
  		if (cmd == 0x04)					/* step forward */
  		{
! 			laserdisc_playing = 0;
! 			current_frame++;
  		}
  		if (cmd == 0x05) 					/* play */
  		{
! 			laserdisc_playing = 1;
  			discready = 1;
  		}
  		if (cmd == 0x0b)					/* seek frame */
  		{
! 			laserdisc_playing = 0;
  			discready = 0;
  			access_time = 60;		/* 1s access time */
  		}
  		if (cmd == 0x0f)	 				/* stop */
  		{
! 			laserdisc_playing = 0;
  			discready = 0;
  		}
  		lastcmd = cmd;
--- 352,377 ----
  	{
  		if (cmd == 0x04)					/* step forward */
  		{
! 			laser_disc_speed = 0;
! 			laser_disc_step(1);
! 			laser_disc_field += 2;
  		}
  		if (cmd == 0x05) 					/* play */
  		{
! 			laser_disc_speed = 1;
  			discready = 1;
  		}
  		if (cmd == 0x0b)					/* seek frame */
  		{
! 			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 */
  		{
! 			laser_disc_speed = 0;
  			discready = 0;
  		}
  		lastcmd = cmd;
***************
*** 379,390 ****
  		access_time--;
  		if (access_time == 0)
  			discready = 1;
! 	} else if (laserdisc_playing) {
! 		odd_field ^= 1;
  		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);
  
  			if (current_frame%53==0)
  			{
--- 384,396 ----
  		access_time--;
  		if (access_time == 0)
  			discready = 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) */
  		{
! 			int current_frame = laser_disc_field >> 1;
! 			logerror("current frame : %d\n",current_frame);
  
  			if (current_frame%53==0)
  			{
***************
*** 1336,1343 ****
  	{ 0 }
  };
  
- 
- 
  /********************************************************************
  *
  *  Machine Driver macro
--- 1342,1347 ----
***************
*** 1462,1467 ****
--- 1466,1473 ----
  	MDRV_IMPORT_FROM(gottlieb2)
  	MDRV_CPU_MODIFY("main")
  	MDRV_CPU_PROGRAM_MAP(stooges_readmem,stooges_writemem)
+ 	/* laser disk sound */
+ 	MDRV_SOUND_ADD(CUSTOM, laserdisk_interface)
  
  	/* video hardware */
  	MDRV_GFXDECODE(charRAM_gfxdecodeinfo)
***************
*** 1813,1819 ****
  	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_END
  
  ROM_START( usvsthem )
--- 1819,1825 ----
  	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, 0xed400, CRC(a2a9f8e5) SHA1(5ca2e4dd86882009ea1496f91e1fc8612ae4bf5e) )
  ROM_END
  
  ROM_START( usvsthem )
diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/fileio.c mame-firefox/src/fileio.c
*** mame/src/fileio.c	Tue Nov 11 22:25:56 2003
--- mame-firefox/src/fileio.c	Sun Feb 15 11:27:25 2004
***************
*** 106,111 ****
--- 106,114 ----
  		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,247 ****
--- 245,255 ----
  			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,789 ****
--- 792,800 ----
  		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 -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/fileio.h mame-firefox/src/fileio.h
*** mame/src/fileio.h	Fri May 23 16:51:20 2003
--- mame-firefox/src/fileio.h	Sun Feb 15 11:27:25 2004
***************
*** 40,45 ****
--- 40,48 ----
  	FILETYPE_LANGUAGE,
  	FILETYPE_CTRLR,
  	FILETYPE_INI,
+  	FILETYPE_LASERDISK_FLAC,
+  	FILETYPE_LASERDISK_VIDEO,
+  	FILETYPE_LASERDISK_FRAME_SEEKS,
  #ifdef MESS
  	FILETYPE_CRC,
  #endif
diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/mame.c mame-firefox/src/mame.c
*** mame/src/mame.c	Wed Jan 28 19:01:24 2004
--- mame-firefox/src/mame.c	Sun Feb 15 11:27:25 2004
***************
*** 1294,1299 ****
--- 1294,1303 ----
  }
  
  
+ struct mame_display *get_current_display()
+ {
+ 	return &current_display;
+ }
  
  /*-------------------------------------------------
  	recompute_fps - recompute the frame rate
diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/mame.h mame-firefox/src/mame.h
*** mame/src/mame.h	Wed Jan 28 19:01:24 2004
--- mame-firefox/src/mame.h	Sun Feb 15 11:27:25 2004
***************
*** 383,388 ****
--- 383,390 ----
  /* 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(void);
+ 
  #ifdef MESS
  #include "mess.h"
  #endif /* MESS */
diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/mame.mak mame-firefox/src/mame.mak
*** mame/src/mame.mak	Wed Jan 28 19:01:24 2004
--- mame-firefox/src/mame.mak	Sun Feb 15 12:12:57 2004
***************
*** 619,624 ****
--- 619,625 ----
  	$(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 -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/md5.c mame-firefox/src/md5.c
*** mame/src/md5.c	Thu May 15 04:59:00 2003
--- mame-firefox/src/md5.c	Sun Feb 15 11:27:25 2004
***************
*** 44,49 ****
--- 44,50 ----
   * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
   * initialization constants.
   */
+ /*
  void
  MD5Init(struct MD5Context *ctx)
  {
***************
*** 55,136 ****
  	ctx->bytes[0] = 0;
  	ctx->bytes[1] = 0;
  }
  
  /*
   * Update context to reflect the concatenation of another buffer full
   * of bytes.
   */
- void
- MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len)
- {
- 	UWORD32 t;
- 
- 	/* Update byte count */
- 
- 	t = ctx->bytes[0];
- 	if ((ctx->bytes[0] = t + len) < t)
- 		ctx->bytes[1]++;	/* Carry from low to high */
- 
- 	t = 64 - (t & 0x3f);	/* Space available in ctx->in (at least 1) */
- 	if (t > len) {
- 		memcpy((md5byte *)ctx->in + 64 - t, buf, len);
- 		return;
- 	}
- 	/* First chunk is an odd size */
- 	memcpy((md5byte *)ctx->in + 64 - t, buf, t);
- 	byteSwap(ctx->in, 16);
- 	MD5Transform(ctx->buf, ctx->in);
- 	buf += t;
- 	len -= t;
- 
- 	/* Process data in 64-byte chunks */
- 	while (len >= 64) {
- 		memcpy(ctx->in, buf, 64);
- 		byteSwap(ctx->in, 16);
- 		MD5Transform(ctx->buf, ctx->in);
- 		buf += 64;
- 		len -= 64;
- 	}
- 
- 	/* Handle any remaining bytes of data. */
- 	memcpy(ctx->in, buf, len);
- }
  
  /*
   * Final wrapup - pad to 64-byte boundary with the bit pattern
   * 1 0* (64-bit count of bits processed, MSB-first)
   */
- void
- MD5Final(md5byte digest[16], struct MD5Context *ctx)
- {
- 	int count = ctx->bytes[0] & 0x3f;	/* Number of bytes in ctx->in */
- 	md5byte *p = (md5byte *)ctx->in + count;
- 
- 	/* Set the first char of padding to 0x80.  There is always room. */
- 	*p++ = 0x80;
- 
- 	/* Bytes of padding needed to make 56 bytes (-8..55) */
- 	count = 56 - 1 - count;
- 
- 	if (count < 0) {	/* Padding forces an extra block */
- 		memset(p, 0, count + 8);
- 		byteSwap(ctx->in, 16);
- 		MD5Transform(ctx->buf, ctx->in);
- 		p = (md5byte *)ctx->in;
- 		count = 56;
- 	}
- 	memset(p, 0, count);
- 	byteSwap(ctx->in, 14);
- 
- 	/* Append length in bits and transform */
- 	ctx->in[14] = ctx->bytes[0] << 3;
- 	ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
- 	MD5Transform(ctx->buf, ctx->in);
- 
- 	byteSwap(ctx->buf, 4);
- 	memcpy(digest, ctx->buf, 16);
- 	memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
- }
  
  #ifndef ASM_MD5
  
--- 56,72 ----
  	ctx->bytes[0] = 0;
  	ctx->bytes[1] = 0;
  }
+ */
  
  /*
   * Update context to reflect the concatenation of another buffer full
   * of bytes.
   */
  
  /*
   * Final wrapup - pad to 64-byte boundary with the bit pattern
   * 1 0* (64-bit count of bits processed, MSB-first)
   */
  
  #ifndef ASM_MD5
  
***************
*** 151,156 ****
--- 87,93 ----
   * reflect the addition of 16 longwords of new data.  MD5Update blocks
   * the data and converts bytes into longwords for this routine.
   */
+ 	/*
  void
  MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
  {
***************
*** 234,239 ****
--- 171,177 ----
  	buf[2] += c;
  	buf[3] += d;
  }
+ */
  
  #endif
  
diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/vidhrdw/gottlieb.c mame-firefox/src/vidhrdw/gottlieb.c
*** mame/src/vidhrdw/gottlieb.c	Fri Jul  4 19:16:30 2003
--- mame-firefox/src/vidhrdw/gottlieb.c	Sun Feb 15 11:27:25 2004
***************
*** 9,14 ****
--- 9,15 ----
  #include "driver.h"
  #include "common.h"
  #include "vidhrdw/generic.h"
+ #include "vidhrdw/laserdsk.h"
  
  UINT8 *gottlieb_charram;
  
***************
*** 198,203 ****
--- 199,208 ----
  
  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 -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/vidhrdw/laserdsk.c mame-firefox/src/vidhrdw/laserdsk.c
*** mame/src/vidhrdw/laserdsk.c	Thu Jan  1 00:00:00 1970
--- mame-firefox/src/vidhrdw/laserdsk.c	Sun Feb 15 13:11:58 2004
***************
*** 0 ****
--- 1,408 ----
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <inttypes.h>
+ #include <sys/time.h>
+ #include <unistd.h>
+ 
+ #include "mame.h"
+ #include "driver.h"
+ #include "palette.h"
+ #include "common.h"
+ #include <mpeg2.h>
+ #include "mpeg2convert.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 = NULL;
+ 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(void)
+ {
+ 	struct artwork_piece *video;
+ 	struct mame_display *display;
+ 	struct rectangle *u_invalid;
+ 	static int last_scaled_field = -1;
+ 
+ 	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++)
+ 	{
+ 	  /*  gcc on windows makes this struct bigger (32) than on Linux (24), so do it by element */
+ 		mame_fread(f, &(frame_ptrs[i].frame), sizeof(long));
+ 		mame_fread(f, &(frame_ptrs[i].seek_pos), sizeof(long long));
+ 		mame_fread(f, &(frame_ptrs[i].flac_seek_pos), sizeof(long long));
+ 	}
+ 
+ 	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;
+ 
+ 
+ 		if(!mpeg2dec)
+ 		{
+ 			fprintf(stderr, "mpeg decoder not initialised - is there a laserdisc layer in the artwork file?\n");
+ 			return 0;
+ 		}
+ 
+     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, mpeg2convert_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(void)
+ {
+ 	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);
+ 	}
+ 
+ 	mame_fseek(file, 0, SEEK_SET);
+ 
+ 	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(void)
+ {
+ 	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(void)
+ {
+ }
+ 
+ // this seems to be called for every frame?
+ static void custom_update_flac(void)
+ {
+ }
+ 
+ // 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 -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/vidhrdw/laserdsk.h mame-firefox/src/vidhrdw/laserdsk.h
*** mame/src/vidhrdw/laserdsk.h	Thu Jan  1 00:00:00 1970
--- mame-firefox/src/vidhrdw/laserdsk.h	Sun Feb 15 11:27:26 2004
***************
*** 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);
+ void laser_seek_frame(int frame);
diff -c -b -B -N -x *.png -x *.swo -x *.exe -x artwork.h.orig -x cfg -x *.txt -x *.swp -x *.orig -x *.rej -x obj -x nvram -x mame.ini -x ChangeLog -x INDEX -x *.com -x *zlib* -x error.log -x *~ -r mame/src/windows/fileio.c mame-firefox/src/windows/fileio.c
*** mame/src/windows/fileio.c	Wed Dec 24 16:31:12 2003
--- mame-firefox/src/windows/fileio.c	Sun Feb 15 11:27:26 2004
***************
*** 361,366 ****
--- 361,371 ----
  			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];
