summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/taito_f3.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/taito_f3.c')
-rw-r--r--src/mame/video/taito_f3.c3321
1 files changed, 3321 insertions, 0 deletions
diff --git a/src/mame/video/taito_f3.c b/src/mame/video/taito_f3.c
new file mode 100644
index 00000000000..b82411d3b9b
--- /dev/null
+++ b/src/mame/video/taito_f3.c
@@ -0,0 +1,3321 @@
+/***************************************************************************
+
+ Taito F3 Video emulation - Bryan McPhail, mish@tendril.co.uk
+
+****************************************************************************
+
+Brief overview:
+
+ 4 scrolling layers (512x512 or 1024x512) of 4/5/6 bpp tiles.
+ 1 scrolling text layer (512x512, characters generated in vram), 4bpp chars.
+ 1 scrolling pixel layer (512x256 pixels generated in pivot ram), 4bpp pixels.
+ 2 sprite banks (for double buffering of sprites)
+ Sprites can be 4, 5 or 6 bpp
+ Sprite scaling.
+ Rowscroll on all playfields
+ Line by line zoom on all playfields
+ Column scroll on all playfields
+ Line by line sprite and playfield priority mixing
+
+Notes:
+ All special effects are controlled by an area in 'line ram'. Typically
+ there are 256 values, one for each line of the screen (including clipped
+ lines at the top of the screen). For example, at 0x8000 in lineram,
+ there are 4 sets of 256 values (one for each playfield) and each value
+ is the scale control for that line in the destination bitmap (screen).
+ Therefore each line can have a different zoom value for special effects.
+
+ This also applies to playfield priority, rowscroll, column scroll, sprite
+ priority and VRAM/pivot layers.
+
+ However - at the start of line ram there are also sets of 256 values
+ controlling each effect - effects can be selectively applied to individual
+ playfields or only certain lines out of the 256 can be active - in which
+ case the last allowed value can be latched (typically used so a game can
+ use one zoom or row value over the whole playfield).
+
+ The programmers of some of these games made strange use of flipscreen -
+ some games have all their graphics flipped in ROM, and use the flipscreen
+ bit to display them correctly!.
+
+ Most games display 232 scanlines, but some use lineram effects to clip
+ themselves to 224 or less.
+
+****************************************************************************
+
+Line ram memory map:
+
+ Here 'playfield 1' refers to the first playfield in memory, etc
+
+ 0x0000: Column line control ram (256 lines)
+ 100x: Where bit 0 of x enables effect on playfield 1
+ Where bit 1 of x enables effect on playfield 2
+ Where bit 2 of x enables effect on playfield 3
+ Where bit 3 of x enables effect on playfield 4
+ 0x0200: Line control ram for 0x5000 section.
+ 0x0400: Line control ram for 0x6000 section.
+ 180x: Where bit 0 of x latches sprite alpha value
+ Where bit 1 of x latches tilemap alpha value
+ 0x0600: Sprite control ram
+ 1c0x: Where x enables sprite control word for that line
+ 0x0800: Zoom line control ram (256 lines)
+ 200x: Where bit 0 of x enables effect on playfield 1
+ Where bit 1 of x enables effect on playfield 2
+ Where bit 2 of x enables effect on playfield 3
+ Where bit 3 of x enables effect on playfield 4
+ 0x0a00: Assumed unused.
+ 0x0c00: Rowscroll line control ram (256 lines)
+ 280x: Where bit 0 of x enables effect on playfield 1
+ Where bit 1 of x enables effect on playfield 2
+ Where bit 2 of x enables effect on playfield 3
+ Where bit 3 of x enables effect on playfield 4
+ 0x0e00: Priority line control ram (256 lines)
+ 2c0x: Where bit 0 of x enables effect on playfield 1
+ Where bit 1 of x enables effect on playfield 2
+ Where bit 2 of x enables effect on playfield 3
+ Where bit 3 of x enables effect on playfield 4
+
+ 0x4000: Column scroll & clipping info
+
+ 0x5000: Clip plane 0 (low bits)
+ 0x5200: Clip plane 1 (low bits)
+ 0x5400: Unused?
+ 0x5600: Unused?
+
+ 0x6000: Sync register
+ 0x6004: Sprite alpha control
+ 0xff00: VRAM/Pixel layer control
+ 0xa000 enables pixel layer for this line (Disables VRAM layer)
+ 0x2000 enables garbage pixels for this line (maybe another pixel bank?) [unemulated]
+ 0x0800 seems to set the vram layer to be opaque [unemulated]
+ Effect of other bits is unknown.
+ 0x00c0: Alpha mode for sprites with pri value 0x00
+ 0x0030: Alpha mode for sprites with pri value 0x00
+ 0x000c: Alpha mode for sprites with pri value 0x00
+ 0x0003: Alpha mode for sprites with pri value 0x00
+ 0x6200: Alpha blending control
+
+ 0x6400 - controls X zoom of tile - each tile collapses to 16 single colour lines
+ xxx1 - affects bottom playfield
+ xxx2 -
+ xxx4 -
+ xxx8 - affects top playfield
+ xxfx - x zoom - 0 = 1st pixel 16 times
+ 1 = 1st pixel 8, then 2nd 8
+ 8 = 2 per pixel
+
+ (these effects only known to be used on spcinvdj title screen and riding fight - not emulated)
+
+ 1xxx = interpret palette ram for this playfield line as 15 bit and bilinear filter framebuffer(??)
+ 3xxx = interpret palette ram for this playfield line as 15 bit
+ 7xxx = interpret palette ram for this playfield line as 24 bit palette
+ 8xxx = interpret palette ram for this playfield line as 21 bit palette
+
+ (effect not emulated)
+
+ 0x6600: Background - background palette entry (under all tilemaps) (takes part in alpha blending)
+
+ (effect not emulated)
+
+ 0x7000: Pivot/vram layer enable
+ 0x7200: Cram layer priority
+ 0x7400: Sprite clipping
+ 0x7600: Sprite priority values
+ 0xf000: Relative priority for sprites with pri value 0xc0
+ 0x0f00: Relative priority for sprites with pri value 0x80
+ 0x00f0: Relative priority for sprites with pri value 0x40
+ 0x000f: Relative priority for sprites with pri value 0x00
+
+ 0x8000: Playfield 1 scale (1 word per line, 256 lines, 0x80 = default no scale)
+ 0x8200: Playfield 2/4 scale
+ 0x8400: Playfield 3 scale
+ 0x8600: Playfield 2/4 scale
+ 0x00ff = Y scale (0x80 = no scale, > 0x80 is zoom in, < 0x80 is zoom out [0xc0 is half height of 0x80])
+ 0xff00 = X scale (0 = no scale, > 0 = zoom in, [0x8000 would be double length])
+
+ Playfield 2 & 4 registers seem to be interleaved, playfield 2 Y zoom is stored where you would
+ expect playfield 4 y zoom to be and vice versa.
+
+ 0x9000: Palette add (can affect opacity) [ not emulated ]
+
+ 0xa000: Playfield 1 rowscroll (1 word per line, 256 lines)
+ 0xa200: Playfield 2 rowscroll
+ 0xa400: Playfield 3 rowscroll
+ 0xa600: Playfield 4 rowscroll
+
+ 0xb000: Playfield 1 priority (1 word per line, 256 lines)
+ 0xb200: Playfield 2 priority
+ 0xb400: Playfield 3 priority
+ 0xb600: Playfield 4 priority
+ 0xf000 = Blend mode, 0x3000 = Normal, 0x7000 = Alpha A, 0xb000 = Alpha B, others disable line
+ 0x0800 = Clip line (totally disable line)
+ 0x0400 = Assumed unused
+ 0x0200 = If set enable clip plane 1
+ 0x0100 = If set enable clip plane 0
+ 0x00c0 = Assumed unused
+ 0x0020 = Enable clip inverse mode for plane 1
+ 0x0010 = Enable clip inverse mode for plane 0
+ 0x000f = Layer priority
+
+ 0xc000 - 0xffff: Unused.
+
+ When sprite priority==playfield priority sprite takes precedence (Bubble Symph title)
+
+****************************************************************************
+
+ F3 sprite format:
+
+ Word 0: 0xffff Tile number (LSB)
+ Word 1: 0xff00 X zoom
+ 0x00ff Y zoom
+ Word 2: 0x03ff X position
+ Word 3: 0x03ff Y position
+ Word 4: 0xf000 Sprite block controls
+ 0x0800 Sprite block start
+ 0x0400 Use same colour on this sprite as block start
+ 0x0200 Y flip
+ 0x0100 X flip
+ 0x00ff Colour
+ Word 5: 0xffff Tile number (MSB), probably only low bits used
+ Word 6: 0x8000 If set, jump to sprite location in low bits
+ 0x03ff Location to jump to.
+ Word 7: 0xffff Unused? Always zero?
+
+****************************************************************************
+
+ Playfield control information (0x660000-1f):
+
+ Word 0- 3: X scroll values for the 4 playfields.
+ Word 4- 7: Y scroll values for the 4 playfields.
+ Word 8-11: Unused. Always zero.
+ Word 12: Pixel + VRAM playfields X scroll
+ Word 13: Pixel + VRAM playfields Y scroll
+ Word 14: Unused. Always zero.
+ Word 15: If set to 0x80, then 1024x512 playfields are used, else 512x512
+
+ top bits unused - writing to low 4 bits is desync or blank tilemap
+
+Playfield tile info:
+ 0xc000 0000 - X/Y Flip
+ 0x3000 ffff - Tile index
+ 0x0dff 0000 - Colour (top 2 bits use not clear, always set)
+ 0x0200 0000 - Alpha blend mode
+
+***************************************************************************/
+
+#include "driver.h"
+#include "taito_f3.h"
+#include "ui.h"
+
+#define VERBOSE 0
+#define DARIUSG_KLUDGE
+//#define DEBUG_F3 1
+
+static tilemap *pf1_tilemap,*pf2_tilemap,*pf3_tilemap,*pf4_tilemap;
+static tilemap *pixel_layer,*vram_layer;
+static UINT32 *spriteram32_buffered;
+static int vram_dirty[256];
+static int pivot_changed,vram_changed;
+static UINT32 f3_control_0[8];
+static UINT32 f3_control_1[8];
+static int flipscreen;
+
+static UINT8 *pivot_dirty;
+
+static UINT32 *f3_pf_data_1,*f3_pf_data_2,*f3_pf_data_3,*f3_pf_data_4;
+
+UINT32 *f3_vram,*f3_line_ram;
+UINT32 *f3_pf_data,*f3_pivot_ram;
+
+static int f3_skip_this_frame;
+
+/* Game specific data, some of this can be
+removed when the software values are figured out */
+struct F3config
+{
+ int name;
+ int extend;
+ int sprite_lag;
+};
+
+static const struct F3config *f3_game_config;
+
+static const struct F3config f3_config_table[] =
+{
+ /* Name Extend Sprite Lag */
+ { RINGRAGE, 0, 2 },
+ { ARABIANM, 0, 2 },
+ { RIDINGF, 1, 1 },
+ { GSEEKER, 0, 1 },
+ { TRSTAR, 1, 0 },
+ { GUNLOCK, 1, 2 },
+ { TWINQIX, 1, 1 },
+ { SCFINALS, 0, 1 },
+ { LIGHTBR, 1, 2 },
+ { KAISERKN, 0, 2 },
+ { DARIUSG, 0, 2 },
+ { BUBSYMPH, 1, 1 },
+ { SPCINVDX, 1, 1 },
+ { QTHEATER, 1, 1 },
+ { HTHERO95, 0, 1 },
+ { SPCINV95, 0, 1 },
+ { EACTION2, 1, 2 },
+ { QUIZHUHU, 1, 1 },
+ { PBOBBLE2, 0, 1 },
+ { GEKIRIDO, 0, 1 },
+ { KTIGER2, 0, 0 },
+ { BUBBLEM, 1, 1 },
+ { CLEOPATR, 0, 1 },
+ { PBOBBLE3, 0, 1 },
+ { ARKRETRN, 1, 1 },
+ { KIRAMEKI, 0, 1 },
+ { PUCHICAR, 1, 1 },
+ { PBOBBLE4, 0, 1 },
+ { POPNPOP, 1, 1 },
+ { LANDMAKR, 1, 1 },
+ { RECALH, 1, 1 },
+ { COMMANDW, 1, 1 },
+ {0}
+};
+
+
+struct tempsprite
+{
+ int code,color;
+ int flipx,flipy;
+ int x,y;
+ int zoomx,zoomy;
+ int pri;
+};
+static struct tempsprite *spritelist;
+static const struct tempsprite *sprite_end;
+
+static void get_sprite_info(running_machine *machine, const UINT32 *spriteram32_ptr);
+static int sprite_lag=1;
+static UINT8 sprite_pri_usage=0;
+
+struct f3_playfield_line_inf
+{
+ int alpha_mode[256];
+ int pri[256];
+
+ /* use for draw_scanlines */
+ UINT16 *src[256],*src_s[256],*src_e[256];
+ UINT8 *tsrc[256],*tsrc_s[256];
+ int x_count[256];
+ UINT32 x_zoom[256];
+ UINT32 clip0[256];
+ UINT32 clip1[256];
+};
+
+struct f3_spritealpha_line_inf
+{
+ UINT16 alpha_level[256];
+ UINT16 spri[256];
+ UINT16 sprite_alpha[256];
+ UINT32 sprite_clip0[256];
+ UINT32 sprite_clip1[256];
+ INT16 clip0_l[256];
+ INT16 clip0_r[256];
+ INT16 clip1_l[256];
+ INT16 clip1_r[256];
+};
+
+/*
+alpha_mode
+---- --xx 0:disable 1:nomal 2:alpha 7000 3:alpha b000
+---1 ---- alpha level a
+--1- ---- alpha level b
+1-------- opaque line
+*/
+
+static struct f3_playfield_line_inf *pf_line_inf;
+static struct f3_spritealpha_line_inf *sa_line_inf;
+
+
+static mame_bitmap *pri_alp_bitmap;
+/*
+pri_alp_bitmap
+---- ---1 sprite priority 0
+---- --1- sprite priority 1
+---- -1-- sprite priority 2
+---- 1--- sprite priority 3
+---1 ---- alpha level a 7000
+--1- ---- alpha level b 7000
+-1-- ---- alpha level a b000
+1--- ---- alpha level b b000
+1111 1111 opaque pixel
+*/
+static int f3_alpha_level_2as=127;
+static int f3_alpha_level_2ad=127;
+static int f3_alpha_level_3as=127;
+static int f3_alpha_level_3ad=127;
+static int f3_alpha_level_2bs=127;
+static int f3_alpha_level_2bd=127;
+static int f3_alpha_level_3bs=127;
+static int f3_alpha_level_3bd=127;
+
+static void init_alpha_blend_func(void);
+
+static int width_mask=0x1ff;
+static int twidth_mask=0x1f,twidth_mask_bit=5;
+static UINT8 *tile_opaque_sp;
+static UINT8 *tile_opaque_pf;
+
+
+/******************************************************************************/
+
+static void print_debug_info(mame_bitmap *bitmap)
+{
+ int l[16];
+ char buf[64*16];
+ char *bufptr = buf;
+
+ bufptr += sprintf(bufptr,"%04X %04X %04X %04X\n",f3_control_0[0]>>22,(f3_control_0[0]&0xffff)>>6,f3_control_0[1]>>22,(f3_control_0[1]&0xffff)>>6);
+ bufptr += sprintf(bufptr,"%04X %04X %04X %04X\n",f3_control_0[2]>>23,(f3_control_0[2]&0xffff)>>7,f3_control_0[3]>>23,(f3_control_0[3]&0xffff)>>7);
+ bufptr += sprintf(bufptr,"%04X %04X %04X %04X\n",f3_control_1[0]>>16,f3_control_1[0]&0xffff,f3_control_1[1]>>16,f3_control_1[1]&0xffff);
+ bufptr += sprintf(bufptr,"%04X %04X %04X %04X\n",f3_control_1[2]>>16,f3_control_1[2]&0xffff,f3_control_1[3]>>16,f3_control_1[3]&0xffff);
+
+ bufptr += sprintf(bufptr,"%04X %04X %04X %04X %04X %04X %04X %04X\n",spriteram32_buffered[0]>>16,spriteram32_buffered[0]&0xffff,spriteram32_buffered[1]>>16,spriteram32_buffered[1]&0xffff,spriteram32_buffered[2]>>16,spriteram32_buffered[2]&0xffff,spriteram32_buffered[3]>>16,spriteram32_buffered[3]&0xffff);
+ bufptr += sprintf(bufptr,"%04X %04X %04X %04X %04X %04X %04X %04X\n",spriteram32_buffered[4]>>16,spriteram32_buffered[4]&0xffff,spriteram32_buffered[5]>>16,spriteram32_buffered[5]&0xffff,spriteram32_buffered[6]>>16,spriteram32_buffered[6]&0xffff,spriteram32_buffered[7]>>16,spriteram32_buffered[7]&0xffff);
+ bufptr += sprintf(bufptr,"%04X %04X %04X %04X %04X %04X %04X %04X\n",spriteram32_buffered[8]>>16,spriteram32_buffered[8]&0xffff,spriteram32_buffered[9]>>16,spriteram32_buffered[9]&0xffff,spriteram32_buffered[10]>>16,spriteram32_buffered[10]&0xffff,spriteram32_buffered[11]>>16,spriteram32_buffered[11]&0xffff);
+
+ l[0]=f3_line_ram[0x0040]&0xffff;
+ l[1]=f3_line_ram[0x00c0]&0xffff;
+ l[2]=f3_line_ram[0x0140]&0xffff;
+ l[3]=f3_line_ram[0x01c0]&0xffff;
+ bufptr += sprintf(bufptr,"Ctr1: %04x %04x %04x %04x\n",l[0],l[1],l[2],l[3]);
+
+ l[0]=f3_line_ram[0x0240]&0xffff;
+ l[1]=f3_line_ram[0x02c0]&0xffff;
+ l[2]=f3_line_ram[0x0340]&0xffff;
+ l[3]=f3_line_ram[0x03c0]&0xffff;
+ bufptr += sprintf(bufptr,"Ctr2: %04x %04x %04x %04x\n",l[0],l[1],l[2],l[3]);
+
+ l[0]=f3_line_ram[0x2c60]&0xffff;
+ l[1]=f3_line_ram[0x2ce0]&0xffff;
+ l[2]=f3_line_ram[0x2d60]&0xffff;
+ l[3]=f3_line_ram[0x2de0]&0xffff;
+ bufptr += sprintf(bufptr,"Pri : %04x %04x %04x %04x\n",l[0],l[1],l[2],l[3]);
+
+ l[0]=f3_line_ram[0x2060]&0xffff;
+ l[1]=f3_line_ram[0x20e0]&0xffff;
+ l[2]=f3_line_ram[0x2160]&0xffff;
+ l[3]=f3_line_ram[0x21e0]&0xffff;
+ bufptr += sprintf(bufptr,"Zoom: %04x %04x %04x %04x\n",l[0],l[1],l[2],l[3]);
+
+ l[0]=f3_line_ram[0x2860]&0xffff;
+ l[1]=f3_line_ram[0x28e0]&0xffff;
+ l[2]=f3_line_ram[0x2960]&0xffff;
+ l[3]=f3_line_ram[0x29e0]&0xffff;
+ bufptr += sprintf(bufptr,"Line: %04x %04x %04x %04x\n",l[0],l[1],l[2],l[3]);
+
+ l[0]=f3_line_ram[0x1c60]&0xffff;
+ l[1]=f3_line_ram[0x1ce0]&0xffff;
+ l[2]=f3_line_ram[0x1d60]&0xffff;
+ l[3]=f3_line_ram[0x1de0]&0xffff;
+ bufptr += sprintf(bufptr,"Sprt: %04x %04x %04x %04x\n",l[0],l[1],l[2],l[3]);
+
+ l[0]=f3_line_ram[0x1860]&0xffff;
+ l[1]=f3_line_ram[0x18e0]&0xffff;
+ l[2]=f3_line_ram[0x1960]&0xffff;
+ l[3]=f3_line_ram[0x19e0]&0xffff;
+ bufptr += sprintf(bufptr,"Pivt: %04x %04x %04x %04x\n",l[0],l[1],l[2],l[3]);
+
+ l[0]=f3_line_ram[0x1060]&0xffff;
+ l[1]=f3_line_ram[0x10e0]&0xffff;
+ l[2]=f3_line_ram[0x1160]&0xffff;
+ l[3]=f3_line_ram[0x11e0]&0xffff;
+ bufptr += sprintf(bufptr,"Colm: %04x %04x %04x %04x\n",l[0],l[1],l[2],l[3]);
+
+ l[0]=f3_line_ram[0x1460]&0xffff;
+ l[1]=f3_line_ram[0x14e0]&0xffff;
+ l[2]=f3_line_ram[0x1560]&0xffff;
+ l[3]=f3_line_ram[0x15e0]&0xffff;
+ bufptr += sprintf(bufptr,"5000: %04x %04x %04x %04x\n",l[0],l[1],l[2],l[3]);
+
+ ui_draw_text(buf, 60, 40);
+}
+
+/******************************************************************************/
+
+INLINE void get_tile_info(running_machine *machine, tile_data *tileinfo, int tile_index, UINT32 *gfx_base)
+{
+ UINT32 tile=gfx_base[tile_index];
+ UINT8 abtype=(tile>>(16+9))&0x1f;
+
+ SET_TILE_INFO(
+ 1,
+ tile&0xffff,
+ (tile>>16)&0x1ff,
+ TILE_FLIPYX( tile >> 30 ));
+ tileinfo->category = abtype&1; /* alpha blending type */
+}
+
+static TILE_GET_INFO( get_tile_info1 )
+{
+ get_tile_info(machine,tileinfo,tile_index,f3_pf_data_1);
+}
+
+static TILE_GET_INFO( get_tile_info2 )
+{
+ get_tile_info(machine,tileinfo,tile_index,f3_pf_data_2);
+}
+
+static TILE_GET_INFO( get_tile_info3 )
+{
+ get_tile_info(machine,tileinfo,tile_index,f3_pf_data_3);
+}
+
+static TILE_GET_INFO( get_tile_info4 )
+{
+ get_tile_info(machine,tileinfo,tile_index,f3_pf_data_4);
+}
+
+static TILE_GET_INFO( get_tile_info_vram )
+{
+ int vram_tile;
+ int flags=0;
+
+ if (tile_index&1)
+ vram_tile = (videoram32[tile_index>>1]&0xffff);
+ else
+ vram_tile = (videoram32[tile_index>>1]>>16);
+
+ if (vram_tile&0x0100) flags|=TILE_FLIPX;
+ if (vram_tile&0x8000) flags|=TILE_FLIPY;
+
+ SET_TILE_INFO(
+ 0,
+ vram_tile&0xff,
+ (vram_tile>>9)&0x3f,
+ flags);
+}
+
+static TILE_GET_INFO( get_tile_info_pixel )
+{
+ int vram_tile,col_off;
+ int flags=0;
+ int y_offs=(f3_control_1[2]&0x1ff);
+ if (flipscreen) y_offs+=0x100;
+
+ /* Colour is shared with VRAM layer */
+ if ((((tile_index%32)*8 + y_offs)&0x1ff)>0xff)
+ col_off=0x800+((tile_index%32)*0x40)+((tile_index&0xfe0)>>5);
+ else
+ col_off=((tile_index%32)*0x40)+((tile_index&0xfe0)>>5);
+
+ if (col_off&1)
+ vram_tile = (videoram32[col_off>>1]&0xffff);
+ else
+ vram_tile = (videoram32[col_off>>1]>>16);
+
+ if (vram_tile&0x0100) flags|=TILE_FLIPX;
+ if (vram_tile&0x8000) flags|=TILE_FLIPY;
+
+ SET_TILE_INFO(
+ 3,
+ tile_index,
+ (vram_tile>>9)&0x3f,
+ flags);
+}
+
+/******************************************************************************/
+
+VIDEO_EOF( f3 )
+{
+ if (sprite_lag==2)
+ {
+ if (video_skip_this_frame() == 0)
+ {
+ get_sprite_info(machine, spriteram32_buffered);
+ }
+ memcpy(spriteram32_buffered,spriteram32,spriteram_size);
+ }
+ else if (sprite_lag==1)
+ {
+ if (video_skip_this_frame() == 0)
+ {
+ get_sprite_info(machine, spriteram32);
+ }
+ }
+}
+
+VIDEO_START( f3 )
+{
+ const struct F3config *pCFG=&f3_config_table[0];
+ int tile;
+
+ spritelist=0;
+ spriteram32_buffered=0;
+ pivot_dirty=0;
+ pf_line_inf=0;
+ pri_alp_bitmap=0;
+ tile_opaque_sp=0;
+ tile_opaque_pf=0;
+
+ /* Setup individual game */
+ do {
+ if (pCFG->name==f3_game)
+ {
+ break;
+ }
+ pCFG++;
+ } while(pCFG->name);
+
+ f3_game_config=pCFG;
+
+ if (f3_game_config->extend) {
+ pf1_tilemap = tilemap_create(get_tile_info1,tilemap_scan_rows,TILEMAP_TYPE_PEN,16,16,64,32);
+ pf2_tilemap = tilemap_create(get_tile_info2,tilemap_scan_rows,TILEMAP_TYPE_PEN,16,16,64,32);
+ pf3_tilemap = tilemap_create(get_tile_info3,tilemap_scan_rows,TILEMAP_TYPE_PEN,16,16,64,32);
+ pf4_tilemap = tilemap_create(get_tile_info4,tilemap_scan_rows,TILEMAP_TYPE_PEN,16,16,64,32);
+
+ f3_pf_data_1=f3_pf_data+0x0000;
+ f3_pf_data_2=f3_pf_data+0x0800;
+ f3_pf_data_3=f3_pf_data+0x1000;
+ f3_pf_data_4=f3_pf_data+0x1800;
+
+ width_mask=0x3ff;
+ twidth_mask=0x3f;
+ twidth_mask_bit=6;
+
+ } else {
+ pf1_tilemap = tilemap_create(get_tile_info1,tilemap_scan_rows,TILEMAP_TYPE_PEN,16,16,32,32);
+ pf2_tilemap = tilemap_create(get_tile_info2,tilemap_scan_rows,TILEMAP_TYPE_PEN,16,16,32,32);
+ pf3_tilemap = tilemap_create(get_tile_info3,tilemap_scan_rows,TILEMAP_TYPE_PEN,16,16,32,32);
+ pf4_tilemap = tilemap_create(get_tile_info4,tilemap_scan_rows,TILEMAP_TYPE_PEN,16,16,32,32);
+
+ f3_pf_data_1=f3_pf_data+0x0000;
+ f3_pf_data_2=f3_pf_data+0x0400;
+ f3_pf_data_3=f3_pf_data+0x0800;
+ f3_pf_data_4=f3_pf_data+0x0c00;
+
+ width_mask=0x1ff;
+ twidth_mask=0x1f;
+ twidth_mask_bit=5;
+ }
+
+ spriteram32_buffered = (UINT32 *)auto_malloc(0x10000);
+ spritelist = auto_malloc(0x400 * sizeof(*spritelist));
+ sprite_end = spritelist;
+ vram_layer = tilemap_create(get_tile_info_vram,tilemap_scan_rows,TILEMAP_TYPE_PEN,8,8,64,64);
+ pixel_layer = tilemap_create(get_tile_info_pixel,tilemap_scan_cols,TILEMAP_TYPE_PEN,8,8,64,32);
+ pivot_dirty = (UINT8 *)auto_malloc(2048);
+ pf_line_inf = auto_malloc(5 * sizeof(struct f3_playfield_line_inf));
+ sa_line_inf = auto_malloc(1 * sizeof(struct f3_spritealpha_line_inf));
+ pri_alp_bitmap = auto_bitmap_alloc( machine->screen[0].width, machine->screen[0].height, BITMAP_FORMAT_INDEXED8 );
+ tile_opaque_sp = (UINT8 *)auto_malloc(machine->gfx[2]->total_elements);
+ tile_opaque_pf = (UINT8 *)auto_malloc(machine->gfx[1]->total_elements);
+
+ tilemap_set_transparent_pen(pf1_tilemap,0);
+ tilemap_set_transparent_pen(pf2_tilemap,0);
+ tilemap_set_transparent_pen(pf3_tilemap,0);
+ tilemap_set_transparent_pen(pf4_tilemap,0);
+ tilemap_set_transparent_pen(vram_layer,0);
+ tilemap_set_transparent_pen(pixel_layer,0);
+
+ /* Palettes have 4 bpp indexes despite up to 6 bpp data */
+ machine->gfx[1]->color_granularity=16;
+ machine->gfx[2]->color_granularity=16;
+
+ flipscreen = 0;
+ memset(spriteram32_buffered,0,spriteram_size);
+ memset(spriteram32,0,spriteram_size);
+
+ state_save_register_global_array(f3_control_0);
+ state_save_register_global_array(f3_control_1);
+
+ for (tile = 0;tile < 256;tile++)
+ vram_dirty[tile]=1;
+ for (tile = 0;tile < 2048;tile++)
+ pivot_dirty[tile]=1;
+
+ f3_skip_this_frame=0;
+
+ sprite_lag=f3_game_config->sprite_lag;
+
+ init_alpha_blend_func();
+
+ {
+ const gfx_element *sprite_gfx = machine->gfx[2];
+ int c;
+
+ for (c = 0;c < sprite_gfx->total_elements;c++)
+ {
+ int x,y;
+ int chk_trans_or_opa=0;
+ UINT8 *dp = sprite_gfx->gfxdata + c * sprite_gfx->char_modulo;
+ for (y = 0;y < sprite_gfx->height;y++)
+ {
+ for (x = 0;x < sprite_gfx->width;x++)
+ {
+ if(!dp[x]) chk_trans_or_opa|=2;
+ else chk_trans_or_opa|=1;
+ }
+ dp += sprite_gfx->line_modulo;
+ }
+ if(chk_trans_or_opa==1) tile_opaque_sp[c]=1;
+ else tile_opaque_sp[c]=0;
+ }
+ }
+
+
+ {
+ const gfx_element *pf_gfx = machine->gfx[1];
+ int c;
+
+ for (c = 0;c < pf_gfx->total_elements;c++)
+ {
+ int x,y;
+ int chk_trans_or_opa=0;
+ UINT8 *dp = pf_gfx->gfxdata + c * pf_gfx->char_modulo;
+ for (y = 0;y < pf_gfx->height;y++)
+ {
+ for (x = 0;x < pf_gfx->width;x++)
+ {
+ if(!dp[x]) chk_trans_or_opa|=2;
+ else chk_trans_or_opa|=1;
+ }
+ dp += pf_gfx->line_modulo;
+ }
+ tile_opaque_pf[c]=chk_trans_or_opa;
+ }
+ }
+}
+
+/******************************************************************************/
+
+WRITE32_HANDLER( f3_pf_data_w )
+{
+ COMBINE_DATA(&f3_pf_data[offset]);
+
+ if (f3_game_config->extend) {
+ if (offset<0x800) tilemap_mark_tile_dirty(pf1_tilemap,offset-0x0000);
+ else if (offset<0x1000) tilemap_mark_tile_dirty(pf2_tilemap,offset-0x0800);
+ else if (offset<0x1800) tilemap_mark_tile_dirty(pf3_tilemap,offset-0x1000);
+ else if (offset<0x2000) tilemap_mark_tile_dirty(pf4_tilemap,offset-0x1800);
+ } else {
+ if (offset<0x400) tilemap_mark_tile_dirty(pf1_tilemap,offset-0x0000);
+ else if (offset<0x800) tilemap_mark_tile_dirty(pf2_tilemap,offset-0x0400);
+ else if (offset<0xc00) tilemap_mark_tile_dirty(pf3_tilemap,offset-0x0800);
+ else if (offset<0x1000) tilemap_mark_tile_dirty(pf4_tilemap,offset-0xc00);
+ }
+}
+
+WRITE32_HANDLER( f3_control_0_w )
+{
+ COMBINE_DATA(&f3_control_0[offset]);
+}
+
+WRITE32_HANDLER( f3_control_1_w )
+{
+ COMBINE_DATA(&f3_control_1[offset]);
+}
+
+WRITE32_HANDLER( f3_videoram_w )
+{
+ int tile,col_off;
+ COMBINE_DATA(&videoram32[offset]);
+
+ tilemap_mark_tile_dirty(vram_layer,offset<<1);
+ tilemap_mark_tile_dirty(vram_layer,(offset<<1)+1);
+
+ if (offset>0x3ff) offset-=0x400;
+
+ tile=offset<<1;
+ col_off=((tile&0x3f)*32)+((tile&0xfc0)>>6);
+
+ tilemap_mark_tile_dirty(pixel_layer,col_off);
+ tilemap_mark_tile_dirty(pixel_layer,col_off+32);
+}
+
+WRITE32_HANDLER( f3_vram_w )
+{
+ COMBINE_DATA(&f3_vram[offset]);
+ vram_dirty[offset/8]=1;
+ vram_changed=1;
+}
+
+WRITE32_HANDLER( f3_pivot_w )
+{
+ COMBINE_DATA(&f3_pivot_ram[offset]);
+ pivot_dirty[offset/8]=1;
+ pivot_changed=1;
+}
+
+WRITE32_HANDLER( f3_lineram_w )
+{
+ /* DariusGX has an interesting bug at the start of Round D - the clearing of lineram
+ (0xa000->0x0xa7ff) overflows into priority RAM (0xb000) and creates garbage priority
+ values. I'm not sure what the real machine would do with these values, and this
+ emulation certainly doesn't like it, so I've chosen to catch the bug here, and prevent
+ the trashing of priority ram. If anyone has information on what the real machine does,
+ please let me know! */
+ if (f3_game==DARIUSG) {
+ if (f3_skip_this_frame)
+ return;
+ if (offset==0xb000/4 && data==0x003f0000) {
+ f3_skip_this_frame=1;
+ return;
+ }
+ }
+
+ COMBINE_DATA(&f3_line_ram[offset]);
+}
+
+WRITE32_HANDLER( f3_palette_24bit_w )
+{
+ int r,g,b;
+
+ COMBINE_DATA(&paletteram32[offset]);
+
+ /* 12 bit palette games - there has to be a palette select bit somewhere */
+ if (f3_game==SPCINVDX || f3_game==RIDINGF || f3_game==ARABIANM || f3_game==RINGRAGE) {
+ b = 15 * ((paletteram32[offset] >> 4) & 0xf);
+ g = 15 * ((paletteram32[offset] >> 8) & 0xf);
+ r = 15 * ((paletteram32[offset] >> 12) & 0xf);
+ }
+
+ /* This is weird - why are only the sprites and VRAM palettes 21 bit? */
+ else if (f3_game==CLEOPATR) {
+ if (offset<0x100 || offset>0x1000) {
+ r = ((paletteram32[offset] >>16) & 0x7f)<<1;
+ g = ((paletteram32[offset] >> 8) & 0x7f)<<1;
+ b = ((paletteram32[offset] >> 0) & 0x7f)<<1;
+ } else {
+ r = (paletteram32[offset] >>16) & 0xff;
+ g = (paletteram32[offset] >> 8) & 0xff;
+ b = (paletteram32[offset] >> 0) & 0xff;
+ }
+ }
+
+ /* Another weird couple - perhaps this is alpha blending related? */
+ else if (f3_game==TWINQIX || f3_game==RECALH) {
+ if (offset>0x1c00) {
+ r = ((paletteram32[offset] >>16) & 0x7f)<<1;
+ g = ((paletteram32[offset] >> 8) & 0x7f)<<1;
+ b = ((paletteram32[offset] >> 0) & 0x7f)<<1;
+ } else {
+ r = (paletteram32[offset] >>16) & 0xff;
+ g = (paletteram32[offset] >> 8) & 0xff;
+ b = (paletteram32[offset] >> 0) & 0xff;
+ }
+ }
+
+ /* All other games - standard 24 bit palette */
+ else {
+ r = (paletteram32[offset] >>16) & 0xff;
+ g = (paletteram32[offset] >> 8) & 0xff;
+ b = (paletteram32[offset] >> 0) & 0xff;
+ }
+
+ palette_set_color(Machine,offset,MAKE_RGB(r,g,b));
+}
+
+/******************************************************************************/
+
+static UINT8 add_sat[256][256];
+
+static int alpha_s_1_1;
+static int alpha_s_1_2;
+static int alpha_s_1_4;
+static int alpha_s_1_5;
+static int alpha_s_1_6;
+static int alpha_s_1_8;
+static int alpha_s_1_9;
+static int alpha_s_1_a;
+
+static int alpha_s_2a_0;
+static int alpha_s_2a_4;
+static int alpha_s_2a_8;
+
+static int alpha_s_2b_0;
+static int alpha_s_2b_4;
+static int alpha_s_2b_8;
+
+static int alpha_s_3a_0;
+static int alpha_s_3a_1;
+static int alpha_s_3a_2;
+
+static int alpha_s_3b_0;
+static int alpha_s_3b_1;
+static int alpha_s_3b_2;
+
+static UINT32 dval;
+static UINT8 pval;
+static UINT8 tval;
+static UINT8 pdest_2a = 0x10;
+static UINT8 pdest_2b = 0x20;
+static int tr_2a = 0;
+static int tr_2b = 1;
+static UINT8 pdest_3a = 0x40;
+static UINT8 pdest_3b = 0x80;
+static int tr_3a = 0;
+static int tr_3b = 1;
+
+static int (*dpix_n[8][16])(UINT32 s_pix);
+static int (**dpix_lp[5])(UINT32 s_pix);
+static int (**dpix_sp[9])(UINT32 s_pix);
+
+/*============================================================================*/
+
+#define SET_ALPHA_LEVEL(d,s) \
+{ \
+ int level = s; \
+ if(level == 0) level = -1; \
+ d = level+1; \
+}
+
+INLINE void f3_alpha_set_level(void)
+{
+// SET_ALPHA_LEVEL(alpha_s_1_1, f3_alpha_level_2ad)
+ SET_ALPHA_LEVEL(alpha_s_1_1, 255-f3_alpha_level_2as)
+// SET_ALPHA_LEVEL(alpha_s_1_2, f3_alpha_level_2bd)
+ SET_ALPHA_LEVEL(alpha_s_1_2, 255-f3_alpha_level_2bs)
+ SET_ALPHA_LEVEL(alpha_s_1_4, f3_alpha_level_3ad)
+// SET_ALPHA_LEVEL(alpha_s_1_5, f3_alpha_level_3ad*f3_alpha_level_2ad/255)
+ SET_ALPHA_LEVEL(alpha_s_1_5, f3_alpha_level_3ad*(255-f3_alpha_level_2as)/255)
+// SET_ALPHA_LEVEL(alpha_s_1_6, f3_alpha_level_3ad*f3_alpha_level_2bd/255)
+ SET_ALPHA_LEVEL(alpha_s_1_6, f3_alpha_level_3ad*(255-f3_alpha_level_2bs)/255)
+ SET_ALPHA_LEVEL(alpha_s_1_8, f3_alpha_level_3bd)
+// SET_ALPHA_LEVEL(alpha_s_1_9, f3_alpha_level_3bd*f3_alpha_level_2ad/255)
+ SET_ALPHA_LEVEL(alpha_s_1_9, f3_alpha_level_3bd*(255-f3_alpha_level_2as)/255)
+// SET_ALPHA_LEVEL(alpha_s_1_a, f3_alpha_level_3bd*f3_alpha_level_2bd/255)
+ SET_ALPHA_LEVEL(alpha_s_1_a, f3_alpha_level_3bd*(255-f3_alpha_level_2bs)/255)
+
+ SET_ALPHA_LEVEL(alpha_s_2a_0, f3_alpha_level_2as)
+ SET_ALPHA_LEVEL(alpha_s_2a_4, f3_alpha_level_2as*f3_alpha_level_3ad/255)
+ SET_ALPHA_LEVEL(alpha_s_2a_8, f3_alpha_level_2as*f3_alpha_level_3bd/255)
+
+ SET_ALPHA_LEVEL(alpha_s_2b_0, f3_alpha_level_2bs)
+ SET_ALPHA_LEVEL(alpha_s_2b_4, f3_alpha_level_2bs*f3_alpha_level_3ad/255)
+ SET_ALPHA_LEVEL(alpha_s_2b_8, f3_alpha_level_2bs*f3_alpha_level_3bd/255)
+
+ SET_ALPHA_LEVEL(alpha_s_3a_0, f3_alpha_level_3as)
+ SET_ALPHA_LEVEL(alpha_s_3a_1, f3_alpha_level_3as*f3_alpha_level_2ad/255)
+ SET_ALPHA_LEVEL(alpha_s_3a_2, f3_alpha_level_3as*f3_alpha_level_2bd/255)
+
+ SET_ALPHA_LEVEL(alpha_s_3b_0, f3_alpha_level_3bs)
+ SET_ALPHA_LEVEL(alpha_s_3b_1, f3_alpha_level_3bs*f3_alpha_level_2ad/255)
+ SET_ALPHA_LEVEL(alpha_s_3b_2, f3_alpha_level_3bs*f3_alpha_level_2bd/255)
+}
+#undef SET_ALPHA_LEVEL
+
+/*============================================================================*/
+
+#ifdef LSB_FIRST
+#define COLOR1 0
+#define COLOR2 1
+#define COLOR3 2
+#else
+#define COLOR1 3
+#define COLOR2 2
+#define COLOR3 1
+#endif
+
+
+
+INLINE void f3_alpha_blend32_s( int alphas, UINT32 s )
+{
+ UINT8 *sc = (UINT8 *)&s;
+ UINT8 *dc = (UINT8 *)&dval;
+ dc[COLOR1] = (alphas * sc[COLOR1]) >> 8;
+ dc[COLOR2] = (alphas * sc[COLOR2]) >> 8;
+ dc[COLOR3] = (alphas * sc[COLOR3]) >> 8;
+}
+
+INLINE void f3_alpha_blend32_d( int alphas, UINT32 s )
+{
+ UINT8 *sc = (UINT8 *)&s;
+ UINT8 *dc = (UINT8 *)&dval;
+ dc[COLOR1] = add_sat[dc[COLOR1]][(alphas * sc[COLOR1]) >> 8];
+ dc[COLOR2] = add_sat[dc[COLOR2]][(alphas * sc[COLOR2]) >> 8];
+ dc[COLOR3] = add_sat[dc[COLOR3]][(alphas * sc[COLOR3]) >> 8];
+}
+
+/*============================================================================*/
+
+INLINE void f3_alpha_blend_1_1( UINT32 s ){f3_alpha_blend32_d(alpha_s_1_1,s);}
+INLINE void f3_alpha_blend_1_2( UINT32 s ){f3_alpha_blend32_d(alpha_s_1_2,s);}
+INLINE void f3_alpha_blend_1_4( UINT32 s ){f3_alpha_blend32_d(alpha_s_1_4,s);}
+INLINE void f3_alpha_blend_1_5( UINT32 s ){f3_alpha_blend32_d(alpha_s_1_5,s);}
+INLINE void f3_alpha_blend_1_6( UINT32 s ){f3_alpha_blend32_d(alpha_s_1_6,s);}
+INLINE void f3_alpha_blend_1_8( UINT32 s ){f3_alpha_blend32_d(alpha_s_1_8,s);}
+INLINE void f3_alpha_blend_1_9( UINT32 s ){f3_alpha_blend32_d(alpha_s_1_9,s);}
+INLINE void f3_alpha_blend_1_a( UINT32 s ){f3_alpha_blend32_d(alpha_s_1_a,s);}
+
+INLINE void f3_alpha_blend_2a_0( UINT32 s ){f3_alpha_blend32_s(alpha_s_2a_0,s);}
+INLINE void f3_alpha_blend_2a_4( UINT32 s ){f3_alpha_blend32_d(alpha_s_2a_4,s);}
+INLINE void f3_alpha_blend_2a_8( UINT32 s ){f3_alpha_blend32_d(alpha_s_2a_8,s);}
+
+INLINE void f3_alpha_blend_2b_0( UINT32 s ){f3_alpha_blend32_s(alpha_s_2b_0,s);}
+INLINE void f3_alpha_blend_2b_4( UINT32 s ){f3_alpha_blend32_d(alpha_s_2b_4,s);}
+INLINE void f3_alpha_blend_2b_8( UINT32 s ){f3_alpha_blend32_d(alpha_s_2b_8,s);}
+
+INLINE void f3_alpha_blend_3a_0( UINT32 s ){f3_alpha_blend32_s(alpha_s_3a_0,s);}
+INLINE void f3_alpha_blend_3a_1( UINT32 s ){f3_alpha_blend32_d(alpha_s_3a_1,s);}
+INLINE void f3_alpha_blend_3a_2( UINT32 s ){f3_alpha_blend32_d(alpha_s_3a_2,s);}
+
+INLINE void f3_alpha_blend_3b_0( UINT32 s ){f3_alpha_blend32_s(alpha_s_3b_0,s);}
+INLINE void f3_alpha_blend_3b_1( UINT32 s ){f3_alpha_blend32_d(alpha_s_3b_1,s);}
+INLINE void f3_alpha_blend_3b_2( UINT32 s ){f3_alpha_blend32_d(alpha_s_3b_2,s);}
+
+/*============================================================================*/
+
+static int dpix_1_noalpha(UINT32 s_pix) {dval = s_pix; return 1;}
+static int dpix_ret1(UINT32 s_pix) {return 1;}
+static int dpix_ret0(UINT32 s_pix) {return 0;}
+static int dpix_1_1(UINT32 s_pix) {if(s_pix) f3_alpha_blend_1_1(s_pix); return 1;}
+static int dpix_1_2(UINT32 s_pix) {if(s_pix) f3_alpha_blend_1_2(s_pix); return 1;}
+static int dpix_1_4(UINT32 s_pix) {if(s_pix) f3_alpha_blend_1_4(s_pix); return 1;}
+static int dpix_1_5(UINT32 s_pix) {if(s_pix) f3_alpha_blend_1_5(s_pix); return 1;}
+static int dpix_1_6(UINT32 s_pix) {if(s_pix) f3_alpha_blend_1_6(s_pix); return 1;}
+static int dpix_1_8(UINT32 s_pix) {if(s_pix) f3_alpha_blend_1_8(s_pix); return 1;}
+static int dpix_1_9(UINT32 s_pix) {if(s_pix) f3_alpha_blend_1_9(s_pix); return 1;}
+static int dpix_1_a(UINT32 s_pix) {if(s_pix) f3_alpha_blend_1_a(s_pix); return 1;}
+
+static int dpix_2a_0(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_2a_0(s_pix);
+ else dval = 0;
+ if(pdest_2a) {pval |= pdest_2a;return 0;}
+ return 1;
+}
+static int dpix_2a_4(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_2a_4(s_pix);
+ if(pdest_2a) {pval |= pdest_2a;return 0;}
+ return 1;
+}
+static int dpix_2a_8(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_2a_8(s_pix);
+ if(pdest_2a) {pval |= pdest_2a;return 0;}
+ return 1;
+}
+
+static int dpix_3a_0(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_3a_0(s_pix);
+ else dval = 0;
+ if(pdest_3a) {pval |= pdest_3a;return 0;}
+ return 1;
+}
+static int dpix_3a_1(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_3a_1(s_pix);
+ if(pdest_3a) {pval |= pdest_3a;return 0;}
+ return 1;
+}
+static int dpix_3a_2(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_3a_2(s_pix);
+ if(pdest_3a) {pval |= pdest_3a;return 0;}
+ return 1;
+}
+
+static int dpix_2b_0(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_2b_0(s_pix);
+ else dval = 0;
+ if(pdest_2b) {pval |= pdest_2b;return 0;}
+ return 1;
+}
+static int dpix_2b_4(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_2b_4(s_pix);
+ if(pdest_2b) {pval |= pdest_2b;return 0;}
+ return 1;
+}
+static int dpix_2b_8(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_2b_8(s_pix);
+ if(pdest_2b) {pval |= pdest_2b;return 0;}
+ return 1;
+}
+
+static int dpix_3b_0(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_3b_0(s_pix);
+ else dval = 0;
+ if(pdest_3b) {pval |= pdest_3b;return 0;}
+ return 1;
+}
+static int dpix_3b_1(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_3b_1(s_pix);
+ if(pdest_3b) {pval |= pdest_3b;return 0;}
+ return 1;
+}
+static int dpix_3b_2(UINT32 s_pix)
+{
+ if(s_pix) f3_alpha_blend_3b_2(s_pix);
+ if(pdest_3b) {pval |= pdest_3b;return 0;}
+ return 1;
+}
+
+static int dpix_2_0(UINT32 s_pix)
+{
+ UINT8 tr2=tval&1;
+ if(s_pix)
+ {
+ if(tr2==tr_2b) {f3_alpha_blend_2b_0(s_pix);if(pdest_2b) pval |= pdest_2b;else return 1;}
+ else if(tr2==tr_2a) {f3_alpha_blend_2a_0(s_pix);if(pdest_2a) pval |= pdest_2a;else return 1;}
+ }
+ else
+ {
+ if(tr2==tr_2b) {dval = 0;if(pdest_2b) pval |= pdest_2b;else return 1;}
+ else if(tr2==tr_2a) {dval = 0;if(pdest_2a) pval |= pdest_2a;else return 1;}
+ }
+ return 0;
+}
+static int dpix_2_4(UINT32 s_pix)
+{
+ UINT8 tr2=tval&1;
+ if(s_pix)
+ {
+ if(tr2==tr_2b) {f3_alpha_blend_2b_4(s_pix);if(pdest_2b) pval |= pdest_2b;else return 1;}
+ else if(tr2==tr_2a) {f3_alpha_blend_2a_4(s_pix);if(pdest_2a) pval |= pdest_2a;else return 1;}
+ }
+ else
+ {
+ if(tr2==tr_2b) {if(pdest_2b) pval |= pdest_2b;else return 1;}
+ else if(tr2==tr_2a) {if(pdest_2a) pval |= pdest_2a;else return 1;}
+ }
+ return 0;
+}
+static int dpix_2_8(UINT32 s_pix)
+{
+ UINT8 tr2=tval&1;
+ if(s_pix)
+ {
+ if(tr2==tr_2b) {f3_alpha_blend_2b_8(s_pix);if(pdest_2b) pval |= pdest_2b;else return 1;}
+ else if(tr2==tr_2a) {f3_alpha_blend_2a_8(s_pix);if(pdest_2a) pval |= pdest_2a;else return 1;}
+ }
+ else
+ {
+ if(tr2==tr_2b) {if(pdest_2b) pval |= pdest_2b;else return 1;}
+ else if(tr2==tr_2a) {if(pdest_2a) pval |= pdest_2a;else return 1;}
+ }
+ return 0;
+}
+
+static int dpix_3_0(UINT32 s_pix)
+{
+ UINT8 tr2=tval&1;
+ if(s_pix)
+ {
+ if(tr2==tr_3b) {f3_alpha_blend_3b_0(s_pix);if(pdest_3b) pval |= pdest_3b;else return 1;}
+ else if(tr2==tr_3a) {f3_alpha_blend_3a_0(s_pix);if(pdest_3a) pval |= pdest_3a;else return 1;}
+ }
+ else
+ {
+ if(tr2==tr_3b) {dval = 0;if(pdest_3b) pval |= pdest_3b;else return 1;}
+ else if(tr2==tr_3a) {dval = 0;if(pdest_3a) pval |= pdest_3a;else return 1;}
+ }
+ return 0;
+}
+static int dpix_3_1(UINT32 s_pix)
+{
+ UINT8 tr2=tval&1;
+ if(s_pix)
+ {
+ if(tr2==tr_3b) {f3_alpha_blend_3b_1(s_pix);if(pdest_3b) pval |= pdest_3b;else return 1;}
+ else if(tr2==tr_3a) {f3_alpha_blend_3a_1(s_pix);if(pdest_3a) pval |= pdest_3a;else return 1;}
+ }
+ else
+ {
+ if(tr2==tr_3b) {if(pdest_3b) pval |= pdest_3b;else return 1;}
+ else if(tr2==tr_3a) {if(pdest_3a) pval |= pdest_3a;else return 1;}
+ }
+ return 0;
+}
+static int dpix_3_2(UINT32 s_pix)
+{
+ UINT8 tr2=tval&1;
+ if(s_pix)
+ {
+ if(tr2==tr_3b) {f3_alpha_blend_3b_2(s_pix);if(pdest_3b) pval |= pdest_3b;else return 1;}
+ else if(tr2==tr_3a) {f3_alpha_blend_3a_2(s_pix);if(pdest_3a) pval |= pdest_3a;else return 1;}
+ }
+ else
+ {
+ if(tr2==tr_3b) {if(pdest_3b) pval |= pdest_3b;else return 1;}
+ else if(tr2==tr_3a) {if(pdest_3a) pval |= pdest_3a;else return 1;}
+ }
+ return 0;
+}
+
+INLINE void dpix_1_sprite(UINT32 s_pix)
+{
+ if(s_pix)
+ {
+ UINT8 p1 = pval&0xf0;
+ if (p1==0x10) f3_alpha_blend_1_1(s_pix);
+ else if(p1==0x20) f3_alpha_blend_1_2(s_pix);
+ else if(p1==0x40) f3_alpha_blend_1_4(s_pix);
+ else if(p1==0x50) f3_alpha_blend_1_5(s_pix);
+ else if(p1==0x60) f3_alpha_blend_1_6(s_pix);
+ else if(p1==0x80) f3_alpha_blend_1_8(s_pix);
+ else if(p1==0x90) f3_alpha_blend_1_9(s_pix);
+ else if(p1==0xa0) f3_alpha_blend_1_a(s_pix);
+ }
+}
+
+INLINE void dpix_bg(UINT32 bgcolor)
+{
+ UINT8 p1 = pval&0xf0;
+ if(!p1) dval = bgcolor;
+ else if(p1==0x10) f3_alpha_blend_1_1(bgcolor);
+ else if(p1==0x20) f3_alpha_blend_1_2(bgcolor);
+ else if(p1==0x40) f3_alpha_blend_1_4(bgcolor);
+ else if(p1==0x50) f3_alpha_blend_1_5(bgcolor);
+ else if(p1==0x60) f3_alpha_blend_1_6(bgcolor);
+ else if(p1==0x80) f3_alpha_blend_1_8(bgcolor);
+ else if(p1==0x90) f3_alpha_blend_1_9(bgcolor);
+ else if(p1==0xa0) f3_alpha_blend_1_a(bgcolor);
+}
+
+/******************************************************************************/
+
+static void init_alpha_blend_func(void)
+{
+ int i,j;
+
+ dpix_n[0][0x0]=dpix_1_noalpha;
+ dpix_n[0][0x1]=dpix_1_noalpha;
+ dpix_n[0][0x2]=dpix_1_noalpha;
+ dpix_n[0][0x3]=dpix_1_noalpha;
+ dpix_n[0][0x4]=dpix_1_noalpha;
+ dpix_n[0][0x5]=dpix_1_noalpha;
+ dpix_n[0][0x6]=dpix_1_noalpha;
+ dpix_n[0][0x7]=dpix_1_noalpha;
+ dpix_n[0][0x8]=dpix_1_noalpha;
+ dpix_n[0][0x9]=dpix_1_noalpha;
+ dpix_n[0][0xa]=dpix_1_noalpha;
+ dpix_n[0][0xb]=dpix_1_noalpha;
+ dpix_n[0][0xc]=dpix_1_noalpha;
+ dpix_n[0][0xd]=dpix_1_noalpha;
+ dpix_n[0][0xe]=dpix_1_noalpha;
+ dpix_n[0][0xf]=dpix_1_noalpha;
+
+ dpix_n[1][0x0]=dpix_1_noalpha;
+ dpix_n[1][0x1]=dpix_1_1;
+ dpix_n[1][0x2]=dpix_1_2;
+ dpix_n[1][0x3]=dpix_ret1;
+ dpix_n[1][0x4]=dpix_1_4;
+ dpix_n[1][0x5]=dpix_1_5;
+ dpix_n[1][0x6]=dpix_1_6;
+ dpix_n[1][0x7]=dpix_ret1;
+ dpix_n[1][0x8]=dpix_1_8;
+ dpix_n[1][0x9]=dpix_1_9;
+ dpix_n[1][0xa]=dpix_1_a;
+ dpix_n[1][0xb]=dpix_ret1;
+ dpix_n[1][0xc]=dpix_ret1;
+ dpix_n[1][0xd]=dpix_ret1;
+ dpix_n[1][0xe]=dpix_ret1;
+ dpix_n[1][0xf]=dpix_ret1;
+
+ dpix_n[2][0x0]=dpix_2a_0;
+ dpix_n[2][0x1]=dpix_ret0;
+ dpix_n[2][0x2]=dpix_ret0;
+ dpix_n[2][0x3]=dpix_ret0;
+ dpix_n[2][0x4]=dpix_2a_4;
+ dpix_n[2][0x5]=dpix_ret0;
+ dpix_n[2][0x6]=dpix_ret0;
+ dpix_n[2][0x7]=dpix_ret0;
+ dpix_n[2][0x8]=dpix_2a_8;
+ dpix_n[2][0x9]=dpix_ret0;
+ dpix_n[2][0xa]=dpix_ret0;
+ dpix_n[2][0xb]=dpix_ret0;
+ dpix_n[2][0xc]=dpix_ret0;
+ dpix_n[2][0xd]=dpix_ret0;
+ dpix_n[2][0xe]=dpix_ret0;
+ dpix_n[2][0xf]=dpix_ret0;
+
+ dpix_n[3][0x0]=dpix_3a_0;
+ dpix_n[3][0x1]=dpix_3a_1;
+ dpix_n[3][0x2]=dpix_3a_2;
+ dpix_n[3][0x3]=dpix_ret0;
+ dpix_n[3][0x4]=dpix_ret0;
+ dpix_n[3][0x5]=dpix_ret0;
+ dpix_n[3][0x6]=dpix_ret0;
+ dpix_n[3][0x7]=dpix_ret0;
+ dpix_n[3][0x8]=dpix_ret0;
+ dpix_n[3][0x9]=dpix_ret0;
+ dpix_n[3][0xa]=dpix_ret0;
+ dpix_n[3][0xb]=dpix_ret0;
+ dpix_n[3][0xc]=dpix_ret0;
+ dpix_n[3][0xd]=dpix_ret0;
+ dpix_n[3][0xe]=dpix_ret0;
+ dpix_n[3][0xf]=dpix_ret0;
+
+ dpix_n[4][0x0]=dpix_2b_0;
+ dpix_n[4][0x1]=dpix_ret0;
+ dpix_n[4][0x2]=dpix_ret0;
+ dpix_n[4][0x3]=dpix_ret0;
+ dpix_n[4][0x4]=dpix_2b_4;
+ dpix_n[4][0x5]=dpix_ret0;
+ dpix_n[4][0x6]=dpix_ret0;
+ dpix_n[4][0x7]=dpix_ret0;
+ dpix_n[4][0x8]=dpix_2b_8;
+ dpix_n[4][0x9]=dpix_ret0;
+ dpix_n[4][0xa]=dpix_ret0;
+ dpix_n[4][0xb]=dpix_ret0;
+ dpix_n[4][0xc]=dpix_ret0;
+ dpix_n[4][0xd]=dpix_ret0;
+ dpix_n[4][0xe]=dpix_ret0;
+ dpix_n[4][0xf]=dpix_ret0;
+
+ dpix_n[5][0x0]=dpix_3b_0;
+ dpix_n[5][0x1]=dpix_3b_1;
+ dpix_n[5][0x2]=dpix_3b_2;
+ dpix_n[5][0x3]=dpix_ret0;
+ dpix_n[5][0x4]=dpix_ret0;
+ dpix_n[5][0x5]=dpix_ret0;
+ dpix_n[5][0x6]=dpix_ret0;
+ dpix_n[5][0x7]=dpix_ret0;
+ dpix_n[5][0x8]=dpix_ret0;
+ dpix_n[5][0x9]=dpix_ret0;
+ dpix_n[5][0xa]=dpix_ret0;
+ dpix_n[5][0xb]=dpix_ret0;
+ dpix_n[5][0xc]=dpix_ret0;
+ dpix_n[5][0xd]=dpix_ret0;
+ dpix_n[5][0xe]=dpix_ret0;
+ dpix_n[5][0xf]=dpix_ret0;
+
+ dpix_n[6][0x0]=dpix_2_0;
+ dpix_n[6][0x1]=dpix_ret0;
+ dpix_n[6][0x2]=dpix_ret0;
+ dpix_n[6][0x3]=dpix_ret0;
+ dpix_n[6][0x4]=dpix_2_4;
+ dpix_n[6][0x5]=dpix_ret0;
+ dpix_n[6][0x6]=dpix_ret0;
+ dpix_n[6][0x7]=dpix_ret0;
+ dpix_n[6][0x8]=dpix_2_8;
+ dpix_n[6][0x9]=dpix_ret0;
+ dpix_n[6][0xa]=dpix_ret0;
+ dpix_n[6][0xb]=dpix_ret0;
+ dpix_n[6][0xc]=dpix_ret0;
+ dpix_n[6][0xd]=dpix_ret0;
+ dpix_n[6][0xe]=dpix_ret0;
+ dpix_n[6][0xf]=dpix_ret0;
+
+ dpix_n[7][0x0]=dpix_3_0;
+ dpix_n[7][0x1]=dpix_3_1;
+ dpix_n[7][0x2]=dpix_3_2;
+ dpix_n[7][0x3]=dpix_ret0;
+ dpix_n[7][0x4]=dpix_ret0;
+ dpix_n[7][0x5]=dpix_ret0;
+ dpix_n[7][0x6]=dpix_ret0;
+ dpix_n[7][0x7]=dpix_ret0;
+ dpix_n[7][0x8]=dpix_ret0;
+ dpix_n[7][0x9]=dpix_ret0;
+ dpix_n[7][0xa]=dpix_ret0;
+ dpix_n[7][0xb]=dpix_ret0;
+ dpix_n[7][0xc]=dpix_ret0;
+ dpix_n[7][0xd]=dpix_ret0;
+ dpix_n[7][0xe]=dpix_ret0;
+ dpix_n[7][0xf]=dpix_ret0;
+
+ for(i=0;i<256;i++)
+ for(j=0;j<256;j++)
+ add_sat[i][j] = (i + j < 256) ? i + j : 255;
+}
+
+/******************************************************************************/
+
+#define GET_PIXMAP_POINTER(pf_num) \
+{ \
+ const struct f3_playfield_line_inf *line_tmp=line_t[pf_num]; \
+ src##pf_num=line_tmp->src[y]; \
+ src_s##pf_num=line_tmp->src_s[y]; \
+ src_e##pf_num=line_tmp->src_e[y]; \
+ tsrc##pf_num=line_tmp->tsrc[y]; \
+ tsrc_s##pf_num=line_tmp->tsrc_s[y]; \
+ x_count##pf_num=line_tmp->x_count[y]; \
+ x_zoom##pf_num=line_tmp->x_zoom[y]; \
+ clip_al##pf_num=line_tmp->clip0[y]&0xffff; \
+ clip_ar##pf_num=line_tmp->clip0[y]>>16; \
+ clip_bl##pf_num=line_tmp->clip1[y]&0xffff; \
+ clip_br##pf_num=line_tmp->clip1[y]>>16; \
+}
+
+#define CULC_PIXMAP_POINTER(pf_num) \
+{ \
+ x_count##pf_num += x_zoom##pf_num; \
+ if(x_count##pf_num>>16) \
+ { \
+ x_count##pf_num &= 0xffff; \
+ src##pf_num++; \
+ tsrc##pf_num++; \
+ if(src##pf_num==src_e##pf_num) {src##pf_num=src_s##pf_num; tsrc##pf_num=tsrc_s##pf_num;} \
+ } \
+}
+
+/*============================================================================*/
+
+INLINE void draw_scanlines(running_machine *machine,
+ mame_bitmap *bitmap,int xsize,INT16 *draw_line_num,
+ const struct f3_playfield_line_inf **line_t,
+ const int *sprite,
+ UINT32 orient,
+ int skip_layer_num)
+{
+ const pen_t *clut = &machine->remapped_colortable[0];
+ UINT32 bgcolor=clut[0];
+ int length;
+
+ const int x=46;
+
+ UINT32 sprite_noalp_0=sprite[0]&0x100;
+ UINT32 sprite_noalp_1=sprite[1]&0x100;
+ UINT32 sprite_noalp_2=sprite[2]&0x100;
+ UINT32 sprite_noalp_3=sprite[3]&0x100;
+ UINT32 sprite_noalp_4=sprite[4]&0x100;
+ UINT32 sprite_noalp_5=sprite[5]&0x100;
+
+ static UINT16 *src0=0,*src_s0=0,*src_e0=0,clip_al0=0,clip_ar0=0,clip_bl0=0,clip_br0=0;
+ static UINT8 *tsrc0=0,*tsrc_s0=0;
+ static UINT32 x_count0=0,x_zoom0=0;
+
+ static UINT16 *src1=0,*src_s1=0,*src_e1=0,clip_al1=0,clip_ar1=0,clip_bl1=0,clip_br1=0;
+ static UINT8 *tsrc1=0,*tsrc_s1=0;
+ static UINT32 x_count1=0,x_zoom1=0;
+
+ static UINT16 *src2=0,*src_s2=0,*src_e2=0,clip_al2=0,clip_ar2=0,clip_bl2=0,clip_br2=0;
+ static UINT8 *tsrc2=0,*tsrc_s2=0;
+ static UINT32 x_count2=0,x_zoom2=0;
+
+ static UINT16 *src3=0,*src_s3=0,*src_e3=0,clip_al3=0,clip_ar3=0,clip_bl3=0,clip_br3=0;
+ static UINT8 *tsrc3=0,*tsrc_s3=0;
+ static UINT32 x_count3=0,x_zoom3=0;
+
+ static UINT16 *src4=0,*src_s4=0,*src_e4=0,clip_al4=0,clip_ar4=0,clip_bl4=0,clip_br4=0;
+ static UINT8 *tsrc4=0,*tsrc_s4=0;
+ static UINT32 x_count4=0,x_zoom4=0;
+
+ UINT16 clip_als=0, clip_ars=0, clip_bls=0, clip_brs=0;
+
+ UINT8 *dstp0,*dstp;
+
+ int yadv = bitmap->rowpixels;
+ int i=0,y=draw_line_num[0];
+ int ty = y;
+
+ if (orient & ORIENTATION_FLIP_Y)
+ {
+ ty = bitmap->height - 1 - ty;
+ yadv = -yadv;
+ }
+
+ dstp0 = BITMAP_ADDR8(pri_alp_bitmap, ty, x);
+
+ pdest_2a = f3_alpha_level_2ad ? 0x10 : 0;
+ pdest_2b = f3_alpha_level_2bd ? 0x20 : 0;
+ tr_2a =(f3_alpha_level_2as==0 && f3_alpha_level_2ad==255) ? -1 : 0;
+ tr_2b =(f3_alpha_level_2bs==0 && f3_alpha_level_2bd==255) ? -1 : 1;
+ pdest_3a = f3_alpha_level_3ad ? 0x40 : 0;
+ pdest_3b = f3_alpha_level_3bd ? 0x80 : 0;
+ tr_3a =(f3_alpha_level_3as==0 && f3_alpha_level_3ad==255) ? -1 : 0;
+ tr_3b =(f3_alpha_level_3bs==0 && f3_alpha_level_3bd==255) ? -1 : 1;
+
+ {
+ UINT32 *dsti0,*dsti;
+ dsti0 = BITMAP_ADDR32(bitmap, ty, x);
+ while(1)
+ {
+ int cx=0;
+
+ clip_als=sa_line_inf->sprite_clip0[y]&0xffff;
+ clip_ars=sa_line_inf->sprite_clip0[y]>>16;
+ clip_bls=sa_line_inf->sprite_clip1[y]&0xffff;
+ clip_brs=sa_line_inf->sprite_clip1[y]>>16;
+
+ length=xsize;
+ dsti = dsti0;
+ dstp = dstp0;
+
+ switch(skip_layer_num)
+ {
+ case 0: GET_PIXMAP_POINTER(0)
+ case 1: GET_PIXMAP_POINTER(1)
+ case 2: GET_PIXMAP_POINTER(2)
+ case 3: GET_PIXMAP_POINTER(3)
+ case 4: GET_PIXMAP_POINTER(4)
+ }
+
+ while (1)
+ {
+ pval=*dstp;
+ if (pval!=0xff)
+ {
+ UINT8 sprite_pri;
+ switch(skip_layer_num)
+ {
+ case 0: if(cx>=clip_als && cx<clip_ars && !(cx>=clip_bls && cx<clip_brs) && (sprite_pri=sprite[0]&pval))
+ {
+ if(sprite_noalp_0) break;
+ if(!dpix_sp[sprite_pri]) break;
+ if(dpix_sp[sprite_pri][pval>>4](*dsti)) {*dsti=dval;break;}
+ }
+ if (cx>=clip_al0 && cx<clip_ar0 && !(cx>=clip_bl0 && cx<clip_br0)) {tval=*tsrc0;if(tval&0xf0) if(dpix_lp[0][pval>>4](clut[*src0])) {*dsti=dval;break;}}
+ case 1: if(cx>=clip_als && cx<clip_ars && !(cx>=clip_bls && cx<clip_brs) && (sprite_pri=sprite[1]&pval))
+ {
+ if(sprite_noalp_1) break;
+ if(!dpix_sp[sprite_pri])
+ {
+ if(!(pval&0xf0)) break;
+ else {dpix_1_sprite(*dsti);*dsti=dval;break;}
+ }
+ if(dpix_sp[sprite_pri][pval>>4](*dsti)) {*dsti=dval;break;}
+ }
+ if (cx>=clip_al1 && cx<clip_ar1 && !(cx>=clip_bl1 && cx<clip_br1)) {tval=*tsrc1;if(tval&0xf0) if(dpix_lp[1][pval>>4](clut[*src1])) {*dsti=dval;break;}}
+ case 2: if(cx>=clip_als && cx<clip_ars && !(cx>=clip_bls && cx<clip_brs) && (sprite_pri=sprite[2]&pval))
+ {
+ if(sprite_noalp_2) break;
+ if(!dpix_sp[sprite_pri])
+ {
+ if(!(pval&0xf0)) break;
+ else {dpix_1_sprite(*dsti);*dsti=dval;break;}
+ }
+ if(dpix_sp[sprite_pri][pval>>4](*dsti)) {*dsti=dval;break;}
+ }
+ if (cx>=clip_al2 && cx<clip_ar2 && !(cx>=clip_bl2 && cx<clip_br2)) {tval=*tsrc2;if(tval&0xf0) if(dpix_lp[2][pval>>4](clut[*src2])) {*dsti=dval;break;}}
+ case 3: if(cx>=clip_als && cx<clip_ars && !(cx>=clip_bls && cx<clip_brs) && (sprite_pri=sprite[3]&pval))
+ {
+ if(sprite_noalp_3) break;
+ if(!dpix_sp[sprite_pri])
+ {
+ if(!(pval&0xf0)) break;
+ else {dpix_1_sprite(*dsti);*dsti=dval;break;}
+ }
+ if(dpix_sp[sprite_pri][pval>>4](*dsti)) {*dsti=dval;break;}
+ }
+ if (cx>=clip_al3 && cx<clip_ar3 && !(cx>=clip_bl3 && cx<clip_br3)) {tval=*tsrc3;if(tval&0xf0) if(dpix_lp[3][pval>>4](clut[*src3])) {*dsti=dval;break;}}
+
+ case 4: if(cx>=clip_als && cx<clip_ars && !(cx>=clip_bls && cx<clip_brs) && (sprite_pri=sprite[4]&pval))
+ {
+ if(sprite_noalp_4) break;
+ if(!dpix_sp[sprite_pri])
+ {
+ if(!(pval&0xf0)) break;
+ else {dpix_1_sprite(*dsti);*dsti=dval;break;}
+ }
+ if(dpix_sp[sprite_pri][pval>>4](*dsti)) {*dsti=dval;break;}
+ }
+ if (cx>=clip_al4 && cx<clip_ar4 && !(cx>=clip_bl4 && cx<clip_br4)) {
+ tval=*tsrc4;
+ if(tval&0xf0)
+ {
+ if(dpix_lp[4][pval>>4](clut[*src4]))
+ {
+ *dsti=dval;
+ break;
+ }
+ }
+ }
+
+
+ case 5: if(cx>=clip_als && cx<clip_ars && !(cx>=clip_bls && cx<clip_brs) && (sprite_pri=sprite[5]&pval))
+ {
+ if(sprite_noalp_5) break;
+ if(!dpix_sp[sprite_pri])
+ {
+ if(!(pval&0xf0)) break;
+ else {dpix_1_sprite(*dsti);*dsti=dval;break;}
+ }
+ if(dpix_sp[sprite_pri][pval>>4](*dsti)) {*dsti=dval;break;}
+ }
+ if(!bgcolor) {if(!(pval&0xf0)) {*dsti=0;break;}}
+ else dpix_bg(bgcolor);
+ *dsti=dval;
+ }
+ }
+
+ if(!(--length)) break;
+ dsti++;
+ dstp++;
+ cx++;
+
+ switch(skip_layer_num)
+ {
+ case 0: CULC_PIXMAP_POINTER(0)
+ case 1: CULC_PIXMAP_POINTER(1)
+ case 2: CULC_PIXMAP_POINTER(2)
+ case 3: CULC_PIXMAP_POINTER(3)
+ case 4: CULC_PIXMAP_POINTER(4)
+ }
+ }
+
+ i++;
+ if(draw_line_num[i]<0) break;
+ if(draw_line_num[i]==y+1)
+ {
+ dsti0 += yadv;
+ dstp0 += yadv;
+ y++;
+ continue;
+ }
+ else
+ {
+ int dy=(draw_line_num[i]-y)*yadv;
+ dsti0 += dy;
+ dstp0 += dy;
+ y=draw_line_num[i];
+ }
+ }
+ }
+}
+#undef GET_PIXMAP_POINTER
+#undef CULC_PIXMAP_POINTER
+
+/******************************************************************************/
+
+static void visible_tile_check(running_machine *machine,
+ struct f3_playfield_line_inf *line_t,
+ int line,
+ UINT32 x_index_fx,UINT32 y_index,
+ UINT32 *f3_pf_data_n)
+{
+ UINT32 *pf_base;
+ int i,trans_all,tile_index,tile_num;
+ int alpha_type,alpha_mode;
+ int opaque_all;
+ int total_elements;
+
+ if(!(alpha_mode=line_t->alpha_mode[line])) return;
+
+ total_elements=machine->gfx[1]->total_elements;
+
+ tile_index=x_index_fx>>16;
+ tile_num=(((line_t->x_zoom[line]*320+(x_index_fx & 0xffff)+0xffff)>>16)+(tile_index%16)+15)/16;
+ tile_index/=16;
+
+ if (flipscreen)
+ {
+ pf_base=f3_pf_data_n+((31-(y_index/16))<<twidth_mask_bit);
+ tile_index=(twidth_mask-tile_index)-tile_num+1;
+ }
+ else pf_base=f3_pf_data_n+((y_index/16)<<twidth_mask_bit);
+
+
+ trans_all=1;
+ opaque_all=1;
+ alpha_type=0;
+ for(i=0;i<tile_num;i++)
+ {
+ UINT32 tile=pf_base[(tile_index)&twidth_mask];
+ if(tile&0xffff)
+ {
+ trans_all=0;
+ if(opaque_all)
+ {
+ if(tile_opaque_pf[(tile&0xffff)%total_elements]!=1) opaque_all=0;
+ }
+
+ if(alpha_mode==1)
+ {
+ if(!opaque_all) return;
+ }
+ else
+ {
+ if(alpha_type!=3)
+ {
+ if((tile>>(16+9))&1) alpha_type|=2;
+ else alpha_type|=1;
+ }
+ else if(!opaque_all) break;
+ }
+ }
+ else if(opaque_all) opaque_all=0;
+
+ tile_index++;
+ }
+
+ if(trans_all) {line_t->alpha_mode[line]=0;return;}
+
+ if(alpha_mode>1)
+ {
+ line_t->alpha_mode[line]|=alpha_type<<4;
+ }
+
+ if(opaque_all)
+ line_t->alpha_mode[line]|=0x80;
+}
+
+/******************************************************************************/
+
+static void calculate_clip(int y, UINT16 pri, UINT32* clip0, UINT32* clip1, int* line_enable)
+{
+ const struct f3_spritealpha_line_inf *sa_line_t=&sa_line_inf[0];
+
+ switch (pri)
+ {
+ case 0x0100: /* Clip plane 1 enable */
+ {
+ if (sa_line_t->clip0_l[y] > sa_line_t->clip0_r[y])
+ *line_enable=0;
+ else
+ *clip0=(sa_line_t->clip0_l[y]) | (sa_line_t->clip0_r[y]<<16);
+ *clip1=0;
+ }
+ break;
+ case 0x0110: /* Clip plane 1 enable, inverted */
+ {
+ *clip1=(sa_line_t->clip0_l[y]) | (sa_line_t->clip0_r[y]<<16);
+ *clip0=0x7fff0000;
+ }
+ break;
+ case 0x0200: /* Clip plane 2 enable */
+ {
+ if (sa_line_t->clip1_l[y] > sa_line_t->clip1_r[y])
+ *line_enable=0;
+ else
+ *clip0=(sa_line_t->clip1_l[y]) | (sa_line_t->clip1_r[y]<<16);
+ *clip1=0;
+ }
+ break;
+ case 0x0220: /* Clip plane 2 enable, inverted */
+ {
+ *clip1=(sa_line_t->clip1_l[y]) | (sa_line_t->clip1_r[y]<<16);
+ *clip0=0x7fff0000;
+ }
+ break;
+ case 0x0300: /* Clip plane 1 & 2 enable */
+ {
+ int clipl=0,clipr=0;
+
+ if (sa_line_t->clip1_l[y] > sa_line_t->clip0_l[y])
+ clipl=sa_line_t->clip1_l[y];
+ else
+ clipl=sa_line_t->clip0_l[y];
+
+ if (sa_line_t->clip1_r[y] < sa_line_t->clip0_r[y])
+ clipr=sa_line_t->clip1_r[y];
+ else
+ clipr=sa_line_t->clip0_r[y];
+
+ if (clipl > clipr)
+ *line_enable=0;
+ else
+ *clip0=(clipl) | (clipr<<16);
+ *clip1=0;
+ }
+ break;
+ case 0x0310: /* Clip plane 1 & 2 enable, plane 1 inverted */
+ {
+ if (sa_line_t->clip1_l[y] > sa_line_t->clip1_r[y])
+ line_enable=0;
+ else
+ *clip0=(sa_line_t->clip1_l[y]) | (sa_line_t->clip1_r[y]<<16);
+
+ *clip1=(sa_line_t->clip0_l[y]) | (sa_line_t->clip0_r[y]<<16);
+ }
+ break;
+ case 0x0320: /* Clip plane 1 & 2 enable, plane 2 inverted */
+ {
+ if (sa_line_t->clip0_l[y] > sa_line_t->clip0_r[y])
+ line_enable=0;
+ else
+ *clip0=(sa_line_t->clip0_l[y]) | (sa_line_t->clip0_r[y]<<16);
+
+ *clip1=(sa_line_t->clip1_l[y]) | (sa_line_t->clip1_r[y]<<16);
+ }
+ break;
+ case 0x0330: /* Clip plane 1 & 2 enable, both inverted */
+ {
+ int clipl=0,clipr=0;
+
+ if (sa_line_t->clip1_l[y] < sa_line_t->clip0_l[y])
+ clipl=sa_line_t->clip1_l[y];
+ else
+ clipl=sa_line_t->clip0_l[y];
+
+ if (sa_line_t->clip1_r[y] > sa_line_t->clip0_r[y])
+ clipr=sa_line_t->clip1_r[y];
+ else
+ clipr=sa_line_t->clip0_r[y];
+
+ if (clipl > clipr)
+ *line_enable=0;
+ else
+ *clip1=(clipl) | (clipr<<16);
+ *clip0=0x7fff0000;
+ }
+ break;
+ default:
+ // popmessage("Illegal clip mode");
+ break;
+ }
+}
+
+static void get_spritealphaclip_info(void)
+{
+ struct f3_spritealpha_line_inf *line_t=&sa_line_inf[0];
+
+ int y,y_end,y_inc;
+
+ int spri_base,clip_base_low,clip_base_high,inc;
+
+ UINT16 spri=0;
+ UINT16 sprite_clip=0;
+ UINT16 clip0_low=0, clip0_high=0, clip1_low=0;
+ int alpha_level=0;
+ UINT16 sprite_alpha=0;
+
+ if (flipscreen)
+ {
+ spri_base=0x77fe;
+ clip_base_low=0x51fe;
+ clip_base_high=0x45fe;
+ inc=-2;
+ y=255;
+ y_end=-1;
+ y_inc=-1;
+
+ }
+ else
+ {
+ spri_base=0x7600;
+ clip_base_low=0x5000;
+ clip_base_high=0x4400;
+ inc=2;
+ y=0;
+ y_end=256;
+ y_inc=1;
+ }
+
+ while(y!=y_end)
+ {
+ /* The zoom, column and row values can latch according to control ram */
+ if (y&1)
+ {
+ if (f3_line_ram[0x080+(y>>1)]&1)
+ clip0_low=(f3_line_ram[clip_base_low/4]>> 0)&0xffff;
+ if (f3_line_ram[0x000+(y>>1)]&4)
+ clip0_high=(f3_line_ram[clip_base_high/4]>> 0)&0xffff;
+ if (f3_line_ram[0x080+(y>>1)]&2)
+ clip1_low=(f3_line_ram[(clip_base_low+0x200)/4]>> 0)&0xffff;
+
+ if (f3_line_ram[(0x0600/4)+(y>>1)]&0x8)
+ spri=f3_line_ram[spri_base/4]&0xffff;
+ if (f3_line_ram[(0x0600/4)+(y>>1)]&0x4)
+ sprite_clip=f3_line_ram[(spri_base-0x200)/4]&0xffff;
+ if (f3_line_ram[(0x0400/4)+(y>>1)]&0x1)
+ sprite_alpha=f3_line_ram[(spri_base-0x1600)/4]&0xffff;
+ if (f3_line_ram[(0x0400/4)+(y>>1)]&0x2)
+ alpha_level=f3_line_ram[(spri_base-0x1400)/4]&0xffff;
+ }
+ else
+ {
+ if (f3_line_ram[0x080+(y>>1)]&0x10000)
+ clip0_low=(f3_line_ram[clip_base_low/4]>>16)&0xffff;
+ if (f3_line_ram[0x000+(y>>1)]&0x40000)
+ clip0_high=(f3_line_ram[clip_base_high/4]>>16)&0xffff;
+ if (f3_line_ram[0x080+(y>>1)]&0x20000)
+ clip1_low=(f3_line_ram[(clip_base_low+0x200)/4]>>16)&0xffff;
+
+ if (f3_line_ram[(0x0600/4)+(y>>1)]&0x80000)
+ spri=f3_line_ram[spri_base/4]>>16;
+ if (f3_line_ram[(0x0600/4)+(y>>1)]&0x40000)
+ sprite_clip=f3_line_ram[(spri_base-0x200)/4]>>16;
+ if (f3_line_ram[(0x0400/4)+(y>>1)]&0x10000)
+ sprite_alpha=f3_line_ram[(spri_base-0x1600)/4]>>16;
+ if (f3_line_ram[(0x0400/4)+(y>>1)]&0x20000)
+ alpha_level=f3_line_ram[(spri_base-0x1400)/4]>>16;
+ }
+
+ line_t->alpha_level[y]=alpha_level;
+ line_t->spri[y]=spri;
+ line_t->sprite_alpha[y]=sprite_alpha;
+ line_t->clip0_l[y]=((clip0_low&0xff)|((clip0_high&0x1000)>>4)) - 47;
+ line_t->clip0_r[y]=(((clip0_low&0xff00)>>8)|((clip0_high&0x2000)>>5)) - 47;
+ line_t->clip1_l[y]=((clip1_low&0xff)|((clip0_high&0x4000)>>6)) - 47;
+ line_t->clip1_r[y]=(((clip1_low&0xff00)>>8)|((clip0_high&0x8000)>>7)) - 47;
+ if (line_t->clip0_l[y]<0) line_t->clip0_l[y]=0;
+ if (line_t->clip0_r[y]<0) line_t->clip0_r[y]=0;
+ if (line_t->clip1_l[y]<0) line_t->clip1_l[y]=0;
+ if (line_t->clip1_r[y]<0) line_t->clip1_r[y]=0;
+
+ /* Evaluate sprite clipping */
+ if (sprite_clip&0x080)
+ {
+ line_t->sprite_clip0[y]=0x7fff7fff;
+ line_t->sprite_clip1[y]=0;
+ }
+ else if (sprite_clip&0x33)
+ {
+ int line_enable=1;
+ calculate_clip(y, ((sprite_clip&0x33)<<4), &line_t->sprite_clip0[y], &line_t->sprite_clip1[y], &line_enable);
+ if (line_enable==0)
+ line_t->sprite_clip0[y]=0x7fff7fff;
+ }
+ else
+ {
+ line_t->sprite_clip0[y]=0x7fff0000;
+ line_t->sprite_clip1[y]=0;
+ }
+
+ spri_base+=inc;
+ clip_base_low+=inc;
+ clip_base_high+=inc;
+ y +=y_inc;
+ }
+}
+
+/* sx and sy are 16.16 fixed point numbers */
+static void get_line_ram_info(running_machine *machine, tilemap *tmap, int sx, int sy, int pos, UINT32 *f3_pf_data_n)
+{
+ struct f3_playfield_line_inf *line_t=&pf_line_inf[pos];
+ const mame_bitmap *srcbitmap;
+ const mame_bitmap *flagsbitmap;
+
+ int y,y_start,y_end,y_inc;
+ int line_base,zoom_base,col_base,pri_base,inc;
+
+ int line_enable;
+ int colscroll=0,x_offset=0,line_zoom=0;
+ UINT32 _y_zoom[256];
+ UINT16 pri=0;
+ int bit_select0=0x10000<<pos;
+ int bit_select1=1<<pos;
+
+ int _colscroll[256];
+ UINT32 _x_offset[256];
+ int y_index_fx;
+
+ sx+=((46<<16));
+
+ if (flipscreen)
+ {
+ line_base=0xa1fe + (pos*0x200);
+ zoom_base=0x81fe;// + (pos*0x200);
+ col_base =0x41fe + (pos*0x200);
+ pri_base =0xb1fe + (pos*0x200);
+ inc=-2;
+ y_start=255;
+ y_end=-1;
+ y_inc=-1;
+
+ if (f3_game_config->extend) sx=-sx+((188-512)<<16); else sx=-sx+(188<<16); /* Adjust for flipped scroll position */
+ y_index_fx=-sy-(256<<16); /* Adjust for flipped scroll position */
+ }
+ else
+ {
+ line_base=0xa000 + (pos*0x200);
+ zoom_base=0x8000;// + (pos*0x200);
+ col_base =0x4000 + (pos*0x200);
+ pri_base =0xb000 + (pos*0x200);
+ inc=2;
+ y_start=0;
+ y_end=256;
+ y_inc=1;
+
+ y_index_fx=sy;
+ }
+
+ y=y_start;
+ while(y!=y_end)
+ {
+ /* The zoom, column and row values can latch according to control ram */
+ if (y&1)
+ {
+ if (f3_line_ram[0x300+(y>>1)]&bit_select1)
+ x_offset=(f3_line_ram[line_base/4]&0xffff)<<10;
+ if (f3_line_ram[0x380+(y>>1)]&bit_select1)
+ pri=f3_line_ram[pri_base/4]&0xffff;
+
+ // Zoom for playfields 1 & 3 is interleaved, as is the latch select
+ switch (pos)
+ {
+ case 0:
+ if (f3_line_ram[0x200+(y>>1)]&bit_select1)
+ line_zoom=f3_line_ram[(zoom_base+0x000)/4]&0xffff;
+ break;
+ case 1:
+ if (f3_line_ram[0x200+(y>>1)]&0x2)
+ line_zoom=((f3_line_ram[(zoom_base+0x200)/4]&0xffff)&0xff00) | (line_zoom&0x00ff);
+ if (f3_line_ram[0x200+(y>>1)]&0x8)
+ line_zoom=((f3_line_ram[(zoom_base+0x600)/4]&0xffff)&0x00ff) | (line_zoom&0xff00);
+ break;
+ case 2:
+ if (f3_line_ram[0x200+(y>>1)]&bit_select1)
+ line_zoom=f3_line_ram[(zoom_base+0x400)/4]&0xffff;
+ break;
+ case 3:
+ if (f3_line_ram[0x200+(y>>1)]&0x8)
+ line_zoom=((f3_line_ram[(zoom_base+0x600)/4]&0xffff)&0xff00) | (line_zoom&0x00ff);
+ if (f3_line_ram[0x200+(y>>1)]&0x2)
+ line_zoom=((f3_line_ram[(zoom_base+0x200)/4]&0xffff)&0x00ff) | (line_zoom&0xff00);
+ break;
+ default:
+ break;
+ }
+
+ // Column scroll only affects playfields 2 & 3
+ if (pos>=2 && f3_line_ram[0x000+(y>>1)]&bit_select1)
+ colscroll=(f3_line_ram[col_base/4]>> 0)&0x3ff;
+ }
+ else
+ {
+ if (f3_line_ram[0x300+(y>>1)]&bit_select0)
+ x_offset=(f3_line_ram[line_base/4]&0xffff0000)>>6;
+
+ if (f3_line_ram[0x380+(y>>1)]&bit_select0)
+ pri=(f3_line_ram[pri_base/4]>>16)&0xffff;
+
+ // Zoom for playfields 1 & 3 is interleaved, as is the latch select
+ switch (pos)
+ {
+ case 0:
+ if (f3_line_ram[0x200+(y>>1)]&bit_select0)
+ line_zoom=f3_line_ram[(zoom_base+0x000)/4]>>16;
+ break;
+ case 1:
+ if (f3_line_ram[0x200+(y>>1)]&0x20000)
+ line_zoom=((f3_line_ram[(zoom_base+0x200)/4]>>16)&0xff00) | (line_zoom&0x00ff);
+ if (f3_line_ram[0x200+(y>>1)]&0x80000)
+ line_zoom=((f3_line_ram[(zoom_base+0x600)/4]>>16)&0x00ff) | (line_zoom&0xff00);
+ break;
+ case 2:
+ if (f3_line_ram[0x200+(y>>1)]&bit_select0)
+ line_zoom=f3_line_ram[(zoom_base+0x400)/4]>>16;
+ break;
+ case 3:
+ if (f3_line_ram[0x200+(y>>1)]&0x80000)
+ line_zoom=((f3_line_ram[(zoom_base+0x600)/4]>>16)&0xff00) | (line_zoom&0x00ff);
+ if (f3_line_ram[0x200+(y>>1)]&0x20000)
+ line_zoom=((f3_line_ram[(zoom_base+0x200)/4]>>16)&0x00ff) | (line_zoom&0xff00);
+ break;
+ default:
+ break;
+ }
+
+ // Column scroll only affects playfields 2 & 3
+ if (pos>=2 && f3_line_ram[0x000+(y>>1)]&bit_select0)
+ colscroll=(f3_line_ram[col_base/4]>>16)&0x3ff;
+ }
+
+ if (!pri || (!flipscreen && y<24) || (flipscreen && y>231) ||
+ (pri&0xc000)==0xc000 || !(pri&0x2000)/**/)
+ line_enable=0;
+ else if(pri&0x4000) //alpha1
+ line_enable=2;
+ else if(pri&0x8000) //alpha2
+ line_enable=3;
+ else
+ line_enable=1;
+
+ _colscroll[y]=colscroll;
+ _x_offset[y]=(x_offset&0xffff0000) - (x_offset&0x0000ffff);
+ _y_zoom[y] = (line_zoom&0xff) << 9;
+
+ /* The football games use values in the range 0x200-0x3ff where the crowd should be drawn - !?
+
+ Until this is understood we disable those lines (which would usually wrap and show the grass
+ area.
+ */
+ if (colscroll&0x200)
+ pri|=0x0800;
+
+ /* Evaluate clipping */
+ if (pri&0x0800)
+ line_enable=0;
+ else if (pri&0x0330)
+ {
+ //fast path todo - remove line enable
+ calculate_clip(y, pri&0x0330, &line_t->clip0[y], &line_t->clip1[y], &line_enable);
+ }
+ else
+ {
+ /* No clipping */
+ line_t->clip0[y]=0x7fff0000;
+ line_t->clip1[y]=0;
+ }
+
+ line_t->x_zoom[y]=0x10000 - (line_zoom&0xff00);
+ line_t->alpha_mode[y]=line_enable;
+ line_t->pri[y]=pri;
+
+ zoom_base+=inc;
+ line_base+=inc;
+ col_base +=inc;
+ pri_base +=inc;
+ y +=y_inc;
+ }
+
+ /* set pixmap pointer */
+ srcbitmap = tilemap_get_pixmap(tmap);
+ flagsbitmap = tilemap_get_flagsmap(tmap);
+
+ y=y_start;
+ while(y!=y_end)
+ {
+ UINT32 x_index_fx;
+ UINT32 y_index;
+
+ if(line_t->alpha_mode[y]!=0)
+ {
+ UINT16 *src_s;
+ UINT8 *tsrc_s;
+
+ x_index_fx = (sx+_x_offset[y]-(10*0x10000)+(10*line_t->x_zoom[y]))&((width_mask<<16)|0xffff);
+ y_index = ((y_index_fx>>16)+_colscroll[y])&0x1ff;
+
+ /* check tile status */
+ visible_tile_check(machine, line_t,y,x_index_fx,y_index,f3_pf_data_n);
+
+ /* If clipping enabled for this line have to disable 'all opaque' optimisation */
+ if (line_t->clip0[y]!=0x7fff0000 || line_t->clip1[y]!=0)
+ line_t->alpha_mode[y]&=~0x80;
+
+ /* set pixmap index */
+ line_t->x_count[y]=x_index_fx & 0xffff; // Fractional part
+ line_t->src_s[y]=src_s=BITMAP_ADDR16(srcbitmap, y_index, 0);
+ line_t->src_e[y]=&src_s[width_mask+1];
+ line_t->src[y]=&src_s[x_index_fx>>16];
+
+ line_t->tsrc_s[y]=tsrc_s=BITMAP_ADDR8(flagsbitmap, y_index, 0);
+ line_t->tsrc[y]=&tsrc_s[x_index_fx>>16];
+ }
+
+ y_index_fx += _y_zoom[y];
+ y +=y_inc;
+ }
+}
+
+static void get_vram_info(tilemap *vram_tilemap, tilemap *pixel_tilemap, int sx, int sy)
+{
+ const struct f3_spritealpha_line_inf *sprite_alpha_line_t=&sa_line_inf[0];
+ struct f3_playfield_line_inf *line_t=&pf_line_inf[4];
+ const mame_bitmap *srcbitmap_pixel, *srcbitmap_vram;
+ const mame_bitmap *flagsbitmap_pixel, *flagsbitmap_vram;
+
+ int y,y_start,y_end,y_inc;
+ int pri_base,inc;
+
+ int line_enable;
+
+ UINT16 pri=0;
+
+ const int vram_width_mask=0x1ff;
+
+ if (flipscreen)
+ {
+ pri_base =0x73fe;
+ inc=-2;
+ y_start=255;
+ y_end=-1;
+ y_inc=-1;
+ }
+ else
+ {
+ pri_base =0x7200;
+ inc=2;
+ y_start=0;
+ y_end=256;
+ y_inc=1;
+
+ }
+
+ y=y_start;
+ while(y!=y_end)
+ {
+ /* The zoom, column and row values can latch according to control ram */
+ if (y&1)
+ {
+ if (f3_line_ram[(0x0600/4)+(y>>1)]&0x2)
+ pri=(f3_line_ram[pri_base/4]&0xffff);
+ }
+ else
+ {
+ if (f3_line_ram[(0x0600/4)+(y>>1)]&0x20000)
+ pri=(f3_line_ram[pri_base/4]&0xffff0000)>>16;
+ }
+
+ if (!pri || (!flipscreen && y<24) || (flipscreen && y>231) ||
+ (pri&0xc000)==0xc000 || !(pri&0x2000)/**/)
+ line_enable=0;
+ else if(pri&0x4000) //alpha1
+ line_enable=2;
+ else if(pri&0x8000) //alpha2
+ line_enable=3;
+ else
+ line_enable=1;
+
+ line_t->pri[y]=pri;
+
+ /* Evaluate clipping */
+ if (pri&0x0800)
+ line_enable=0;
+ else if (pri&0x0330)
+ {
+ //fast path todo - remove line enable
+ calculate_clip(y, pri&0x0330, &line_t->clip0[y], &line_t->clip1[y], &line_enable);
+ }
+ else
+ {
+ /* No clipping */
+ line_t->clip0[y]=0x7fff0000;
+ line_t->clip1[y]=0;
+ }
+
+ line_t->x_zoom[y]=0x10000;
+ line_t->alpha_mode[y]=line_enable;
+ if (line_t->alpha_mode[y]>1)
+ line_t->alpha_mode[y]|=0x10;
+
+ pri_base +=inc;
+ y +=y_inc;
+ }
+
+ sx&=0x1ff;
+
+ /* set pixmap pointer */
+ srcbitmap_pixel = tilemap_get_pixmap(pixel_tilemap);
+ flagsbitmap_pixel = tilemap_get_flagsmap(pixel_tilemap);
+ srcbitmap_vram = tilemap_get_pixmap(vram_tilemap);
+ flagsbitmap_vram = tilemap_get_flagsmap(vram_tilemap);
+
+ y=y_start;
+ while(y!=y_end)
+ {
+ if(line_t->alpha_mode[y]!=0)
+ {
+ UINT16 *src_s;
+ UINT8 *tsrc_s;
+
+ // These bits in control ram indicate whether the line is taken from
+ // the VRAM tilemap layer or pixel layer.
+ const int usePixelLayer=((sprite_alpha_line_t->sprite_alpha[y]&0xa000)==0xa000);
+
+ /* set pixmap index */
+ line_t->x_count[y]=0xffff;
+ if (usePixelLayer)
+ line_t->src_s[y]=src_s=BITMAP_ADDR16(srcbitmap_pixel, sy&0xff, 0);
+ else
+ line_t->src_s[y]=src_s=BITMAP_ADDR16(srcbitmap_vram, sy&0x1ff, 0);
+ line_t->src_e[y]=&src_s[vram_width_mask+1];
+ line_t->src[y]=&src_s[sx];
+
+ if (usePixelLayer)
+ line_t->tsrc_s[y]=tsrc_s=BITMAP_ADDR8(flagsbitmap_pixel, sy&0xff, 0);
+ else
+ line_t->tsrc_s[y]=tsrc_s=BITMAP_ADDR8(flagsbitmap_vram, sy&0x1ff, 0);
+ line_t->tsrc[y]=&tsrc_s[sx];
+ }
+
+ sy++;
+ y += y_inc;
+ }
+}
+
+/******************************************************************************/
+
+static void scanline_draw(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect)
+{
+ int i,j,y,ys,ye;
+ int y_start,y_end,y_start_next,y_end_next;
+ UINT8 draw_line[256];
+ INT16 draw_line_num[256];
+
+ UINT32 rot=0;
+
+ if (flipscreen)
+ {
+ rot=ORIENTATION_FLIP_Y;
+ ys=0;
+ ye=232;
+ }
+ else
+ {
+ ys=24;
+ ye=256;
+ }
+
+ y_start=ys;
+ y_end=ye;
+ memset(draw_line,0,256);
+
+ while(1)
+ {
+ static int alpha_level_last=-1;
+ int pos;
+ int pri[5],alpha_mode[5],alpha_mode_flag[5],alpha_level;
+ UINT16 sprite_alpha;
+ UINT8 sprite_alpha_check;
+ UINT8 sprite_alpha_all_2a;
+ int spri;
+ int alpha;
+ int layer_tmp[5];
+
+ int count_skip_layer=0;
+ int sprite[6]={0,0,0,0,0,0};
+ const struct f3_playfield_line_inf *line_t[5];
+
+
+ /* find same status of scanlines */
+ pri[0]=pf_line_inf[0].pri[y_start];
+ pri[1]=pf_line_inf[1].pri[y_start];
+ pri[2]=pf_line_inf[2].pri[y_start];
+ pri[3]=pf_line_inf[3].pri[y_start];
+ pri[4]=pf_line_inf[4].pri[y_start];
+ alpha_mode[0]=pf_line_inf[0].alpha_mode[y_start];
+ alpha_mode[1]=pf_line_inf[1].alpha_mode[y_start];
+ alpha_mode[2]=pf_line_inf[2].alpha_mode[y_start];
+ alpha_mode[3]=pf_line_inf[3].alpha_mode[y_start];
+ alpha_mode[4]=pf_line_inf[4].alpha_mode[y_start];
+ alpha_level=sa_line_inf[0].alpha_level[y_start];
+ spri=sa_line_inf[0].spri[y_start];
+ sprite_alpha=sa_line_inf[0].sprite_alpha[y_start];
+
+ draw_line[y_start]=1;
+ draw_line_num[i=0]=y_start;
+ y_start_next=-1;
+ y_end_next=-1;
+ for(y=y_start+1;y<y_end;y++)
+ {
+ if(!draw_line[y])
+ {
+ if(pri[0]!=pf_line_inf[0].pri[y]) y_end_next=y+1;
+ else if(pri[1]!=pf_line_inf[1].pri[y]) y_end_next=y+1;
+ else if(pri[2]!=pf_line_inf[2].pri[y]) y_end_next=y+1;
+ else if(pri[3]!=pf_line_inf[3].pri[y]) y_end_next=y+1;
+ else if(pri[4]!=pf_line_inf[4].pri[y]) y_end_next=y+1;
+ else if(alpha_mode[0]!=pf_line_inf[0].alpha_mode[y]) y_end_next=y+1;
+ else if(alpha_mode[1]!=pf_line_inf[1].alpha_mode[y]) y_end_next=y+1;
+ else if(alpha_mode[2]!=pf_line_inf[2].alpha_mode[y]) y_end_next=y+1;
+ else if(alpha_mode[3]!=pf_line_inf[3].alpha_mode[y]) y_end_next=y+1;
+ else if(alpha_mode[4]!=pf_line_inf[4].alpha_mode[y]) y_end_next=y+1;
+ else if(alpha_level!=sa_line_inf[0].alpha_level[y]) y_end_next=y+1;
+ else if(spri!=sa_line_inf[0].spri[y]) y_end_next=y+1;
+ else if(sprite_alpha!=sa_line_inf[0].sprite_alpha[y]) y_end_next=y+1;
+ else
+ {
+ draw_line[y]=1;
+ draw_line_num[++i]=y;
+ continue;
+ }
+
+ if(y_start_next<0) y_start_next=y;
+ }
+ }
+ y_end=y_end_next;
+ y_start=y_start_next;
+ draw_line_num[++i]=-1;
+
+ /* alpha blend */
+ alpha_mode_flag[0]=alpha_mode[0]&~3;
+ alpha_mode_flag[1]=alpha_mode[1]&~3;
+ alpha_mode_flag[2]=alpha_mode[2]&~3;
+ alpha_mode_flag[3]=alpha_mode[3]&~3;
+ alpha_mode_flag[4]=alpha_mode[4]&~3;
+ alpha_mode[0]&=3;
+ alpha_mode[1]&=3;
+ alpha_mode[2]&=3;
+ alpha_mode[3]&=3;
+ alpha_mode[4]&=3;
+ if( alpha_mode[0]>1 ||
+ alpha_mode[1]>1 ||
+ alpha_mode[2]>1 ||
+ alpha_mode[3]>1 ||
+ alpha_mode[4]>1 ||
+ (sprite_alpha&0xff) != 0xff )
+ {
+ /* set alpha level */
+ if(alpha_level!=alpha_level_last)
+ {
+ int al_s,al_d;
+ int a=alpha_level;
+ int b=(a>>8)&0xf;
+ int c=(a>>4)&0xf;
+ int d=(a>>0)&0xf;
+ a>>=12;
+
+ /* b000 7000 */
+ al_s = ( (15-d)*256) / 8;
+ al_d = ( (15-b)*256) / 8;
+ if(al_s>255) al_s = 255;
+ if(al_d>255) al_d = 255;
+ f3_alpha_level_3as = al_s;
+ f3_alpha_level_3ad = al_d;
+ f3_alpha_level_2as = al_d;
+ f3_alpha_level_2ad = al_s;
+
+ al_s = ( (15-c)*256) / 8;
+ al_d = ( (15-a)*256) / 8;
+ if(al_s>255) al_s = 255;
+ if(al_d>255) al_d = 255;
+ f3_alpha_level_3bs = al_s;
+ f3_alpha_level_3bd = al_d;
+ f3_alpha_level_2bs = al_d;
+ f3_alpha_level_2bd = al_s;
+
+ f3_alpha_set_level();
+ alpha_level_last=alpha_level;
+ }
+
+ /* set sprite alpha mode */
+ sprite_alpha_check=0;
+ sprite_alpha_all_2a=1;
+ dpix_sp[1]=0;
+ dpix_sp[2]=0;
+ dpix_sp[4]=0;
+ dpix_sp[8]=0;
+ for(i=0;i<4;i++) /* i = sprite priority offset */
+ {
+ UINT8 sprite_alpha_mode=(sprite_alpha>>(i*2))&3;
+ UINT8 sftbit=1<<i;
+ if(sprite_pri_usage&sftbit)
+ {
+ if(sprite_alpha_mode==1)
+ {
+ if(f3_alpha_level_2as==0 && f3_alpha_level_2ad==255)
+ sprite_pri_usage&=~sftbit; // Disable sprite priority block
+ else
+ {
+ dpix_sp[sftbit]=dpix_n[2];
+ sprite_alpha_check|=sftbit;
+ }
+ }
+ else if(sprite_alpha_mode==2)
+ {
+ if(sprite_alpha&0xff00)
+ {
+ if(f3_alpha_level_3as==0 && f3_alpha_level_3ad==255) sprite_pri_usage&=~sftbit;
+ else
+ {
+ dpix_sp[sftbit]=dpix_n[3];
+ sprite_alpha_check|=sftbit;
+ sprite_alpha_all_2a=0;
+ }
+ }
+ else
+ {
+ if(f3_alpha_level_3bs==0 && f3_alpha_level_3bd==255) sprite_pri_usage&=~sftbit;
+ else
+ {
+ dpix_sp[sftbit]=dpix_n[5];
+ sprite_alpha_check|=sftbit;
+ sprite_alpha_all_2a=0;
+ }
+ }
+ }
+ }
+ }
+
+
+ /* check alpha level */
+ for(i=0;i<5;i++) /* i = playfield num (pos) */
+ {
+ int alpha_type = (alpha_mode_flag[i]>>4)&3;
+
+ if(alpha_mode[i]==2)
+ {
+ if(alpha_type==1)
+ {
+ if (f3_alpha_level_2as==0 && f3_alpha_level_2ad==255) alpha_mode[i]=0;
+ else if(f3_alpha_level_2as==255 && f3_alpha_level_2ad==0 ) alpha_mode[i]=1;
+ }
+ else if(alpha_type==2)
+ {
+ if (f3_alpha_level_2bs==0 && f3_alpha_level_2bd==255) alpha_mode[i]=0;
+ else if(f3_alpha_level_2as==255 && f3_alpha_level_2ad==0 &&
+ f3_alpha_level_2bs==255 && f3_alpha_level_2bd==0 ) alpha_mode[i]=1;
+ }
+ else if(alpha_type==3)
+ {
+ if (f3_alpha_level_2as==0 && f3_alpha_level_2ad==255 &&
+ f3_alpha_level_2bs==0 && f3_alpha_level_2bd==255) alpha_mode[i]=0;
+ else if(f3_alpha_level_2as==255 && f3_alpha_level_2ad==0 &&
+ f3_alpha_level_2bs==255 && f3_alpha_level_2bd==0 ) alpha_mode[i]=1;
+ }
+ }
+ else if(alpha_mode[i]==3)
+ {
+ if(alpha_type==1)
+ {
+ if (f3_alpha_level_3as==0 && f3_alpha_level_3ad==255) alpha_mode[i]=0;
+ else if(f3_alpha_level_3as==255 && f3_alpha_level_3ad==0 ) alpha_mode[i]=1;
+ }
+ else if(alpha_type==2)
+ {
+ if (f3_alpha_level_3bs==0 && f3_alpha_level_3bd==255) alpha_mode[i]=0;
+ else if(f3_alpha_level_3as==255 && f3_alpha_level_3ad==0 &&
+ f3_alpha_level_3bs==255 && f3_alpha_level_3bd==0 ) alpha_mode[i]=1;
+ }
+ else if(alpha_type==3)
+ {
+ if (f3_alpha_level_3as==0 && f3_alpha_level_3ad==255 &&
+ f3_alpha_level_3bs==0 && f3_alpha_level_3bd==255) alpha_mode[i]=0;
+ else if(f3_alpha_level_3as==255 && f3_alpha_level_3ad==0 &&
+ f3_alpha_level_3bs==255 && f3_alpha_level_3bd==0 ) alpha_mode[i]=1;
+ }
+ }
+ }
+
+ if ( (alpha_mode[0]==1 || alpha_mode[0]==2 || !alpha_mode[0]) &&
+ (alpha_mode[1]==1 || alpha_mode[1]==2 || !alpha_mode[1]) &&
+ (alpha_mode[2]==1 || alpha_mode[2]==2 || !alpha_mode[2]) &&
+ (alpha_mode[3]==1 || alpha_mode[3]==2 || !alpha_mode[3]) &&
+ (alpha_mode[4]==1 || alpha_mode[4]==2 || !alpha_mode[4]) &&
+ sprite_alpha_all_2a )
+ {
+ int alpha_type = (alpha_mode_flag[0] | alpha_mode_flag[1] | alpha_mode_flag[2] | alpha_mode_flag[3])&0x30;
+ if( (alpha_type==0x10 && f3_alpha_level_2as==255) ||
+ (alpha_type==0x20 && f3_alpha_level_2as==255 && f3_alpha_level_2bs==255) ||
+ (alpha_type==0x30 && f3_alpha_level_2as==255 && f3_alpha_level_2bs==255) )
+ {
+ if(alpha_mode[0]>1) alpha_mode[0]=1;
+ if(alpha_mode[1]>1) alpha_mode[1]=1;
+ if(alpha_mode[2]>1) alpha_mode[2]=1;
+ if(alpha_mode[3]>1) alpha_mode[3]=1;
+ if(alpha_mode[4]>1) alpha_mode[4]=1;
+ sprite_alpha_check=0;
+ dpix_sp[1]=0;
+ dpix_sp[2]=0;
+ dpix_sp[4]=0;
+ dpix_sp[8]=0;
+ }
+ }
+ }
+ else
+ {
+ sprite_alpha_check=0;
+ dpix_sp[1]=0;
+ dpix_sp[2]=0;
+ dpix_sp[4]=0;
+ dpix_sp[8]=0;
+ }
+
+
+
+ /* set scanline priority */
+ {
+ int pri_max_opa=-1;
+ for(i=0;i<5;i++) /* i = playfield num (pos) */
+ {
+ int p0=pri[i];
+ int pri_sl1=p0&0x0f;
+
+ layer_tmp[i]=i + (pri_sl1<<3);
+
+ if(!alpha_mode[i])
+ {
+ layer_tmp[i]|=0x80;
+ count_skip_layer++;
+ }
+ else if(alpha_mode[i]==1 && (alpha_mode_flag[i]&0x80))
+ {
+ if(layer_tmp[i]>pri_max_opa) pri_max_opa=layer_tmp[i];
+ }
+ }
+
+ if(pri_max_opa!=-1)
+ {
+ if(pri_max_opa>layer_tmp[0]) {layer_tmp[0]|=0x80;count_skip_layer++;}
+ if(pri_max_opa>layer_tmp[1]) {layer_tmp[1]|=0x80;count_skip_layer++;}
+ if(pri_max_opa>layer_tmp[2]) {layer_tmp[2]|=0x80;count_skip_layer++;}
+ if(pri_max_opa>layer_tmp[3]) {layer_tmp[3]|=0x80;count_skip_layer++;}
+ if(pri_max_opa>layer_tmp[4]) {layer_tmp[4]|=0x80;count_skip_layer++;}
+ }
+ }
+
+
+ /* sort layer_tmp */
+ for(i=0;i<4;i++)
+ {
+ for(j=i+1;j<5;j++)
+ {
+ if(layer_tmp[i]<layer_tmp[j])
+ {
+ int temp = layer_tmp[i];
+ layer_tmp[i] = layer_tmp[j];
+ layer_tmp[j] = temp;
+ }
+ }
+ }
+
+
+ /* check sprite & layer priority */
+ {
+ int l0,l1,l2,l3,l4;
+ int pri_sp[5];
+
+ l0=layer_tmp[0]>>3;
+ l1=layer_tmp[1]>>3;
+ l2=layer_tmp[2]>>3;
+ l3=layer_tmp[3]>>3;
+ l4=layer_tmp[4]>>3;
+
+ pri_sp[0]=spri&0xf;
+ pri_sp[1]=(spri>>4)&0xf;
+ pri_sp[2]=(spri>>8)&0xf;
+ pri_sp[3]=spri>>12;
+
+ for(i=0;i<4;i++) /* i = sprite priority offset */
+ {
+ int sp,sflg=1<<i;
+ if(!(sprite_pri_usage & sflg)) continue;
+ sp=pri_sp[i];
+
+ /*
+ sprite priority==playfield priority
+ BUBSYMPH (title) ---> sprite
+ DARIUSG (ZONE V' BOSS) ---> playfield
+ */
+
+ if (f3_game == BUBSYMPH ) sp++; //BUBSYMPH (title)
+
+ if( sp>l0) sprite[0]|=sflg;
+ else if(sp<=l0 && sp>l1) sprite[1]|=sflg;
+ else if(sp<=l1 && sp>l2) sprite[2]|=sflg;
+ else if(sp<=l2 && sp>l3) sprite[3]|=sflg;
+ else if(sp<=l3 && sp>l4) sprite[4]|=sflg;
+ else if(sp<=l4 ) sprite[5]|=sflg;
+ }
+ }
+
+
+ /* draw scanlines */
+ alpha=0;
+ for(i=count_skip_layer;i<5;i++)
+ {
+ pos=layer_tmp[i]&7;
+ line_t[i]=&pf_line_inf[pos];
+
+ if(sprite[i]&sprite_alpha_check) alpha=1;
+ else if(!alpha) sprite[i]|=0x100;
+
+ if(alpha_mode[pos]>1)
+ {
+ int alpha_type=(((alpha_mode_flag[pos]>>4)&3)-1)*2;
+ dpix_lp[i]=dpix_n[alpha_mode[pos]+alpha_type];
+ alpha=1;
+ }
+ else
+ {
+ if(alpha) dpix_lp[i]=dpix_n[1];
+ else dpix_lp[i]=dpix_n[0];
+ }
+ }
+ if(sprite[5]&sprite_alpha_check) alpha=1;
+ else if(!alpha) sprite[5]|=0x100;
+
+ draw_scanlines(machine, bitmap,320,draw_line_num,line_t,sprite,rot,count_skip_layer);
+ if(y_start<0) break;
+ }
+}
+
+/******************************************************************************/
+
+#define PSET_T \
+ c = *source; \
+ if(c) \
+ { \
+ p=*pri; \
+ if(!p || p==0xff) \
+ { \
+ *dest = pal[c]; \
+ *pri = pri_dst; \
+ } \
+ }
+
+#define PSET_O \
+ p=*pri; \
+ if(!p || p==0xff) \
+ { \
+ *dest = pal[*source]; \
+ *pri = pri_dst; \
+ }
+
+#define NEXT_P \
+ source += dx; \
+ dest++; \
+ pri++;
+
+INLINE void f3_drawgfx( mame_bitmap *dest_bmp,const gfx_element *gfx,
+ UINT32 code,
+ UINT32 color,
+ int flipx,int flipy,
+ int sx,int sy,
+ const rectangle *clip,
+ UINT8 pri_dst)
+{
+ rectangle myclip;
+
+ pri_dst=1<<pri_dst;
+
+ /* KW 991012 -- Added code to force clip to bitmap boundary */
+ if(clip)
+ {
+ myclip.min_x = clip->min_x;
+ myclip.max_x = clip->max_x;
+ myclip.min_y = clip->min_y;
+ myclip.max_y = clip->max_y;
+
+ if (myclip.min_x < 0) myclip.min_x = 0;
+ if (myclip.max_x >= dest_bmp->width) myclip.max_x = dest_bmp->width-1;
+ if (myclip.min_y < 0) myclip.min_y = 0;
+ if (myclip.max_y >= dest_bmp->height) myclip.max_y = dest_bmp->height-1;
+
+ clip=&myclip;
+ }
+
+
+ if( gfx )
+ {
+ const pen_t *pal = &Machine->remapped_colortable[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ int source_base = (code % gfx->total_elements) * 16;
+
+ {
+ /* compute sprite increment per screen pixel */
+ int dx = 1;
+ int dy = 1;
+
+ int ex = sx+16;
+ int ey = sy+16;
+
+ int x_index_base;
+ int y_index;
+
+ if( flipx )
+ {
+ x_index_base = 15;
+ dx = -1;
+ }
+ else
+ {
+ x_index_base = 0;
+ }
+
+ if( flipy )
+ {
+ y_index = 15;
+ dy = -1;
+ }
+ else
+ {
+ y_index = 0;
+ }
+
+ if( clip )
+ {
+ if( sx < clip->min_x)
+ { /* clip left */
+ int pixels = clip->min_x-sx;
+ sx += pixels;
+ x_index_base += pixels*dx;
+ }
+ if( sy < clip->min_y )
+ { /* clip top */
+ int pixels = clip->min_y-sy;
+ sy += pixels;
+ y_index += pixels*dy;
+ }
+ /* NS 980211 - fixed incorrect clipping */
+ if( ex > clip->max_x+1 )
+ { /* clip right */
+ int pixels = ex-clip->max_x-1;
+ ex -= pixels;
+ }
+ if( ey > clip->max_y+1 )
+ { /* clip bottom */
+ int pixels = ey-clip->max_y-1;
+ ey -= pixels;
+ }
+ }
+
+ if( ex>sx && ey>sy)
+ { /* skip if inner loop doesn't draw anything */
+// if (dest_bmp->bpp == 32)
+ {
+ int y=ey-sy;
+ int x=(ex-sx-1)|(tile_opaque_sp[code % gfx->total_elements]<<4);
+ UINT8 *source0 = gfx->gfxdata + (source_base+y_index) * 16 + x_index_base;
+ UINT32 *dest0 = BITMAP_ADDR32(dest_bmp, sy, sx);
+ UINT8 *pri0 = BITMAP_ADDR8(pri_alp_bitmap, sy, sx);
+ int yadv = dest_bmp->rowpixels;
+ dy=dy*16;
+ while(1)
+ {
+ UINT8 *source = source0;
+ UINT32 *dest = dest0;
+ UINT8 *pri = pri0;
+
+ switch(x)
+ {
+ int c;
+ UINT8 p;
+ case 31: PSET_O NEXT_P
+ case 30: PSET_O NEXT_P
+ case 29: PSET_O NEXT_P
+ case 28: PSET_O NEXT_P
+ case 27: PSET_O NEXT_P
+ case 26: PSET_O NEXT_P
+ case 25: PSET_O NEXT_P
+ case 24: PSET_O NEXT_P
+ case 23: PSET_O NEXT_P
+ case 22: PSET_O NEXT_P
+ case 21: PSET_O NEXT_P
+ case 20: PSET_O NEXT_P
+ case 19: PSET_O NEXT_P
+ case 18: PSET_O NEXT_P
+ case 17: PSET_O NEXT_P
+ case 16: PSET_O break;
+
+ case 15: PSET_T NEXT_P
+ case 14: PSET_T NEXT_P
+ case 13: PSET_T NEXT_P
+ case 12: PSET_T NEXT_P
+ case 11: PSET_T NEXT_P
+ case 10: PSET_T NEXT_P
+ case 9: PSET_T NEXT_P
+ case 8: PSET_T NEXT_P
+ case 7: PSET_T NEXT_P
+ case 6: PSET_T NEXT_P
+ case 5: PSET_T NEXT_P
+ case 4: PSET_T NEXT_P
+ case 3: PSET_T NEXT_P
+ case 2: PSET_T NEXT_P
+ case 1: PSET_T NEXT_P
+ case 0: PSET_T
+ }
+
+ if(!(--y)) break;
+ source0 += dy;
+ dest0+=yadv;
+ pri0+=yadv;
+ }
+ }
+ }
+ }
+ }
+}
+#undef PSET_T
+#undef PSET_O
+#undef NEXT_P
+
+
+INLINE void f3_drawgfxzoom(mame_bitmap *dest_bmp,const gfx_element *gfx,
+ UINT32 code,
+ UINT32 color,
+ int flipx,int flipy,
+ int sx,int sy,
+ const rectangle *clip,
+ int scalex, int scaley,
+ UINT8 pri_dst)
+{
+ rectangle myclip;
+
+ pri_dst=1<<pri_dst;
+
+ /* KW 991012 -- Added code to force clip to bitmap boundary */
+ if(clip)
+ {
+ myclip.min_x = clip->min_x;
+ myclip.max_x = clip->max_x;
+ myclip.min_y = clip->min_y;
+ myclip.max_y = clip->max_y;
+
+ if (myclip.min_x < 0) myclip.min_x = 0;
+ if (myclip.max_x >= dest_bmp->width) myclip.max_x = dest_bmp->width-1;
+ if (myclip.min_y < 0) myclip.min_y = 0;
+ if (myclip.max_y >= dest_bmp->height) myclip.max_y = dest_bmp->height-1;
+
+ clip=&myclip;
+ }
+
+
+ if( gfx )
+ {
+ const pen_t *pal = &Machine->remapped_colortable[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ int source_base = (code % gfx->total_elements) * 16;
+
+ {
+ /* compute sprite increment per screen pixel */
+ int dx = (16<<16)/scalex;
+ int dy = (16<<16)/scaley;
+
+ int ex = sx+scalex;
+ int ey = sy+scaley;
+
+ int x_index_base;
+ int y_index;
+
+ if( flipx )
+ {
+ x_index_base = (scalex-1)*dx;
+ dx = -dx;
+ }
+ else
+ {
+ x_index_base = 0;
+ }
+
+ if( flipy )
+ {
+ y_index = (scaley-1)*dy;
+ dy = -dy;
+ }
+ else
+ {
+ y_index = 0;
+ }
+
+ if( clip )
+ {
+ if( sx < clip->min_x)
+ { /* clip left */
+ int pixels = clip->min_x-sx;
+ sx += pixels;
+ x_index_base += pixels*dx;
+ }
+ if( sy < clip->min_y )
+ { /* clip top */
+ int pixels = clip->min_y-sy;
+ sy += pixels;
+ y_index += pixels*dy;
+ }
+ /* NS 980211 - fixed incorrect clipping */
+ if( ex > clip->max_x+1 )
+ { /* clip right */
+ int pixels = ex-clip->max_x-1;
+ ex -= pixels;
+ }
+ if( ey > clip->max_y+1 )
+ { /* clip bottom */
+ int pixels = ey-clip->max_y-1;
+ ey -= pixels;
+ }
+ }
+
+ if( ex>sx )
+ { /* skip if inner loop doesn't draw anything */
+// if (dest_bmp->bpp == 32)
+ {
+ int y;
+ for( y=sy; y<ey; y++ )
+ {
+ UINT8 *source = gfx->gfxdata + (source_base+(y_index>>16)) * 16;
+ UINT32 *dest = BITMAP_ADDR32(dest_bmp, y, 0);
+ UINT8 *pri = BITMAP_ADDR8(pri_alp_bitmap, y, 0);
+
+ int x, x_index = x_index_base;
+ for( x=sx; x<ex; x++ )
+ {
+ int c = source[x_index>>16];
+ if(c)
+ {
+ UINT8 p=pri[x];
+ if (p == 0 || p == 0xff)
+ {
+ dest[x] = pal[c];
+ pri[x] = pri_dst;
+ }
+ }
+ x_index += dx;
+ }
+ y_index += dy;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+#define CALC_ZOOM(p) { \
+ p##_addition = 0x100 - block_zoom_##p + p##_addition_left; \
+ p##_addition_left = p##_addition & 0xf; \
+ p##_addition = p##_addition >> 4; \
+ /*zoom##p = p##_addition << 12;*/ \
+}
+
+static void get_sprite_info(running_machine *machine, const UINT32 *spriteram32_ptr)
+{
+ const int min_x=machine->screen[0].visarea.min_x,max_x=machine->screen[0].visarea.max_x;
+ const int min_y=machine->screen[0].visarea.min_y,max_y=machine->screen[0].visarea.max_y;
+ int offs,spritecont,flipx,flipy,old_x,old_y,color,x,y;
+ int sprite,global_x=0,global_y=0,subglobal_x=0,subglobal_y=0;
+ int block_x=0, block_y=0;
+ int last_color=0,last_x=0,last_y=0,block_zoom_x=0,block_zoom_y=0;
+ int this_x,this_y;
+ int y_addition=16, x_addition=16;
+ int multi=0;
+ int sprite_top;
+
+ int x_addition_left = 8, y_addition_left = 8;
+
+ struct tempsprite *sprite_ptr = spritelist;
+
+ int total_sprites=0;
+
+ color=0;
+ flipx=flipy=0;
+ old_y=old_x=0;
+ y=x=0;
+
+ sprite_top=0x1000;
+ for (offs = 0; offs < sprite_top && (total_sprites < 0x400); offs += 4)
+ {
+ const int current_offs=offs; /* Offs can change during loop, current_offs cannot */
+
+ /* Check if the sprite list jump command bit is set */
+ if ((spriteram32_ptr[current_offs+3]>>16) & 0x8000) {
+ UINT32 jump = (spriteram32_ptr[current_offs+3]>>16)&0x3ff;
+
+ UINT32 new_offs=((offs&0x2000)|((jump<<4)/4));
+ if (new_offs==offs)
+ break;
+ offs=new_offs - 4;
+ }
+
+ /* Check if special command bit is set */
+ if (spriteram32_ptr[current_offs+1] & 0x8000) {
+ UINT32 cntrl=(spriteram32_ptr[current_offs+2])&0xffff;
+ flipscreen=cntrl&0x2000;
+
+ /* cntrl&0x1000 = disabled? (From F2 driver, doesn't seem used anywhere)
+ cntrl&0x0010 = ???
+ cntrl&0x0020 = ???
+ */
+
+ /* Sprite bank select */
+ if (cntrl&1) {
+ offs=offs|0x2000;
+ sprite_top=sprite_top|0x2000;
+ }
+ }
+
+ /* Set global sprite scroll */
+ if (((spriteram32_ptr[current_offs+1]>>16) & 0xf000) == 0xa000) {
+ global_x = (spriteram32_ptr[current_offs+1]>>16) & 0xfff;
+ if (global_x >= 0x800) global_x -= 0x1000;
+ global_y = spriteram32_ptr[current_offs+1] & 0xfff;
+ if (global_y >= 0x800) global_y -= 0x1000;
+ }
+
+ /* And sub-global sprite scroll */
+ if (((spriteram32_ptr[current_offs+1]>>16) & 0xf000) == 0x5000) {
+ subglobal_x = (spriteram32_ptr[current_offs+1]>>16) & 0xfff;
+ if (subglobal_x >= 0x800) subglobal_x -= 0x1000;
+ subglobal_y = spriteram32_ptr[current_offs+1] & 0xfff;
+ if (subglobal_y >= 0x800) subglobal_y -= 0x1000;
+ }
+
+ if (((spriteram32_ptr[current_offs+1]>>16) & 0xf000) == 0xb000) {
+ subglobal_x = (spriteram32_ptr[current_offs+1]>>16) & 0xfff;
+ if (subglobal_x >= 0x800) subglobal_x -= 0x1000;
+ subglobal_y = spriteram32_ptr[current_offs+1] & 0xfff;
+ if (subglobal_y >= 0x800) subglobal_y -= 0x1000;
+ global_y=subglobal_y;
+ global_x=subglobal_x;
+ }
+
+ /* A real sprite to process! */
+ sprite = (spriteram32_ptr[current_offs]>>16) | ((spriteram32_ptr[current_offs+2]&1)<<16);
+ spritecont = spriteram32_ptr[current_offs+2]>>24;
+
+/* These games either don't set the XY control bits properly (68020 bug?), or
+ have some different mode from the others */
+#ifdef DARIUSG_KLUDGE
+ if (f3_game==DARIUSG || f3_game==GEKIRIDO || f3_game==CLEOPATR || f3_game==RECALH)
+ multi=spritecont&0xf0;
+#endif
+
+ /* Check if this sprite is part of a continued block */
+ if (multi) {
+ /* Bit 0x4 is 'use previous colour' for this block part */
+ if (spritecont&0x4) color=last_color;
+ else color=(spriteram32_ptr[current_offs+2]>>16)&0xff;
+
+#ifdef DARIUSG_KLUDGE
+ if (f3_game==DARIUSG || f3_game==GEKIRIDO || f3_game==CLEOPATR || f3_game==RECALH) {
+ /* Adjust X Position */
+ if ((spritecont & 0x40) == 0) {
+ if (spritecont & 0x4) {
+ x = block_x;
+ } else {
+ this_x = spriteram32_ptr[current_offs+1]>>16;
+ if (this_x&0x800) this_x= 0 - (0x800 - (this_x&0x7ff)); else this_x&=0x7ff;
+
+ if ((spriteram32_ptr[current_offs+1]>>16)&0x8000) {
+ this_x+=0;
+ } else if ((spriteram32_ptr[current_offs+1]>>16)&0x4000) {
+ /* Ignore subglobal (but apply global) */
+ this_x+=global_x;
+ } else { /* Apply both scroll offsets */
+ this_x+=global_x+subglobal_x;
+ }
+
+ x = block_x = this_x;
+ }
+ x_addition_left = 8;
+ CALC_ZOOM(x)
+ }
+ else if ((spritecont & 0x80) != 0) {
+ x = last_x+x_addition;
+ CALC_ZOOM(x)
+ }
+
+ /* Adjust Y Position */
+ if ((spritecont & 0x10) == 0) {
+ if (spritecont & 0x4) {
+ y = block_y;
+ } else {
+ this_y = spriteram32_ptr[current_offs+1]&0xffff;
+ if (this_y&0x800) this_y= 0 - (0x800 - (this_y&0x7ff)); else this_y&=0x7ff;
+
+ if ((spriteram32_ptr[current_offs+1]>>16)&0x8000) {
+ this_y+=0;
+ } else if ((spriteram32_ptr[current_offs+1]>>16)&0x4000) {
+ /* Ignore subglobal (but apply global) */
+ this_y+=global_y;
+ } else { /* Apply both scroll offsets */
+ this_y+=global_y+subglobal_y;
+ }
+
+ y = block_y = this_y;
+ }
+ y_addition_left = 8;
+ CALC_ZOOM(y)
+ }
+ else if ((spritecont & 0x20) != 0) {
+ y = last_y+y_addition;
+ CALC_ZOOM(y)
+ }
+ } else
+#endif
+ {
+ /* Adjust X Position */
+ if ((spritecont & 0x40) == 0) {
+ x = block_x;
+ x_addition_left = 8;
+ CALC_ZOOM(x)
+ }
+ else if ((spritecont & 0x80) != 0) {
+ x = last_x+x_addition;
+ CALC_ZOOM(x)
+ }
+ /* Adjust Y Position */
+ if ((spritecont & 0x10) == 0) {
+ y = block_y;
+ y_addition_left = 8;
+ CALC_ZOOM(y)
+ }
+ else if ((spritecont & 0x20) != 0) {
+ y = last_y+y_addition;
+ CALC_ZOOM(y)
+ }
+ /* Both zero = reread block latch? */
+ }
+ }
+ /* Else this sprite is the possible start of a block */
+ else {
+ color = (spriteram32_ptr[current_offs+2]>>16)&0xff;
+ last_color=color;
+
+ /* Sprite positioning */
+ this_y = spriteram32_ptr[current_offs+1]&0xffff;
+ this_x = spriteram32_ptr[current_offs+1]>>16;
+ if (this_y&0x800) this_y= 0 - (0x800 - (this_y&0x7ff)); else this_y&=0x7ff;
+ if (this_x&0x800) this_x= 0 - (0x800 - (this_x&0x7ff)); else this_x&=0x7ff;
+
+ /* Ignore both scroll offsets for this block */
+ if ((spriteram32_ptr[current_offs+1]>>16)&0x8000) {
+ this_x+=0;
+ this_y+=0;
+ } else if ((spriteram32_ptr[current_offs+1]>>16)&0x4000) {
+ /* Ignore subglobal (but apply global) */
+ this_x+=global_x;
+ this_y+=global_y;
+ } else { /* Apply both scroll offsets */
+ this_x+=global_x+subglobal_x;
+ this_y+=global_y+subglobal_y;
+ }
+
+ block_y = y = this_y;
+ block_x = x = this_x;
+
+ block_zoom_x=spriteram32_ptr[current_offs];
+ block_zoom_y=(block_zoom_x>>8)&0xff;
+ block_zoom_x&=0xff;
+
+ x_addition_left = 8;
+ CALC_ZOOM(x)
+
+ y_addition_left = 8;
+ CALC_ZOOM(y)
+ }
+
+ /* These features are common to sprite and block parts */
+ flipx = spritecont&0x1;
+ flipy = spritecont&0x2;
+ multi = spritecont&0x8;
+ last_x=x;
+ last_y=y;
+
+ if (!sprite) continue;
+ if (!x_addition || !y_addition) continue;
+
+ if (flipscreen)
+ {
+ int tx,ty;
+
+ tx = 512-x_addition-x;
+ ty = 256-y_addition-y;
+
+ if (tx+x_addition<=min_x || tx>max_x || ty+y_addition<=min_y || ty>max_y) continue;
+ sprite_ptr->x = tx;
+ sprite_ptr->y = ty;
+ sprite_ptr->flipx = !flipx;
+ sprite_ptr->flipy = !flipy;
+ }
+ else
+ {
+ if (x+x_addition<=min_x || x>max_x || y+y_addition<=min_y || y>max_y) continue;
+ sprite_ptr->x = x;
+ sprite_ptr->y = y;
+ sprite_ptr->flipx = flipx;
+ sprite_ptr->flipy = flipy;
+ }
+
+
+ sprite_ptr->code = sprite;
+ sprite_ptr->color = color;
+ sprite_ptr->zoomx = x_addition;
+ sprite_ptr->zoomy = y_addition;
+ sprite_ptr->pri = (color & 0xc0) >> 6;
+ sprite_ptr++;
+ total_sprites++;
+ }
+ sprite_end = sprite_ptr;
+}
+#undef CALC_ZOOM
+
+
+static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect)
+{
+ const struct tempsprite *sprite_ptr;
+ const gfx_element *sprite_gfx = machine->gfx[2];
+
+ sprite_ptr = sprite_end;
+ sprite_pri_usage=0;
+ while (sprite_ptr != spritelist)
+ {
+ int pri;
+ sprite_ptr--;
+
+ pri=sprite_ptr->pri;
+ sprite_pri_usage|=1<<pri;
+
+ if(sprite_ptr->zoomx==16 && sprite_ptr->zoomy==16)
+ f3_drawgfx(bitmap,sprite_gfx,
+ sprite_ptr->code,
+ sprite_ptr->color,
+ sprite_ptr->flipx,sprite_ptr->flipy,
+ sprite_ptr->x,sprite_ptr->y,
+ cliprect,
+ pri);
+ else
+ f3_drawgfxzoom(bitmap,sprite_gfx,
+ sprite_ptr->code,
+ sprite_ptr->color,
+ sprite_ptr->flipx,sprite_ptr->flipy,
+ sprite_ptr->x,sprite_ptr->y,
+ cliprect,
+ sprite_ptr->zoomx,sprite_ptr->zoomy,
+ pri);
+ }
+}
+
+/******************************************************************************/
+
+VIDEO_UPDATE( f3 )
+{
+ UINT32 sy_fix[5],sx_fix[5];
+ int tile;
+
+ f3_skip_this_frame=0;
+ tilemap_set_flip(ALL_TILEMAPS,flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
+
+ /* Dynamically decode VRAM chars if dirty */
+ if (vram_changed)
+ for (tile = 0;tile < 256;tile++)
+ if (vram_dirty[tile]) {
+ decodechar(machine->gfx[0],tile,(UINT8 *)f3_vram,machine->drv->gfxdecodeinfo[0].gfxlayout);
+ tilemap_mark_all_tiles_dirty(vram_layer); // TODO
+ //tilemap_mark_tile_dirty(vram_layer,tile);
+ vram_dirty[tile]=0;
+ }
+
+ /* Decode chars & mark tilemap dirty */
+ if (pivot_changed)
+ for (tile = 0;tile < 2048;tile++)
+ if (pivot_dirty[tile]) {
+ decodechar(machine->gfx[3],tile,(UINT8 *)f3_pivot_ram,machine->drv->gfxdecodeinfo[3].gfxlayout);
+ tilemap_mark_tile_dirty(pixel_layer,tile);
+ pivot_dirty[tile]=0;
+ }
+ pivot_changed=vram_changed=0;
+
+ /* Setup scroll */
+ sy_fix[0]=((f3_control_0[2]&0xffff0000)>> 7) + (1<<16);
+ sy_fix[1]=((f3_control_0[2]&0x0000ffff)<< 9) + (1<<16);
+ sy_fix[2]=((f3_control_0[3]&0xffff0000)>> 7) + (1<<16);
+ sy_fix[3]=((f3_control_0[3]&0x0000ffff)<< 9) + (1<<16);
+ sx_fix[0]=((f3_control_0[0]&0xffc00000)>> 6) - (6<<16);
+ sx_fix[1]=((f3_control_0[0]&0x0000ffc0)<<10) - (10<<16);
+ sx_fix[2]=((f3_control_0[1]&0xffc00000)>> 6) - (14<<16);
+ sx_fix[3]=((f3_control_0[1]&0x0000ffc0)<<10) - (18<<16);
+ sx_fix[4]=-(f3_control_1[2]>>16)+41;
+ sy_fix[4]=-(f3_control_1[2]&0x1ff);
+
+ sx_fix[0]-=((f3_control_0[0]&0x003f0000)>> 6)+0x0400-0x10000;
+ sx_fix[1]-=((f3_control_0[0]&0x0000003f)<<10)+0x0400-0x10000;
+ sx_fix[2]-=((f3_control_0[1]&0x003f0000)>> 6)+0x0400-0x10000;
+ sx_fix[3]-=((f3_control_0[1]&0x0000003f)<<10)+0x0400-0x10000;
+
+ if (flipscreen)
+ {
+ sy_fix[0]= 0x3000000-sy_fix[0];
+ sy_fix[1]= 0x3000000-sy_fix[1];
+ sy_fix[2]= 0x3000000-sy_fix[2];
+ sy_fix[3]= 0x3000000-sy_fix[3];
+ sx_fix[0]=-0x1a00000-sx_fix[0];
+ sx_fix[1]=-0x1a00000-sx_fix[1];
+ sx_fix[2]=-0x1a00000-sx_fix[2];
+ sx_fix[3]=-0x1a00000-sx_fix[3];
+ sx_fix[4]=-sx_fix[4] + 75;
+ sy_fix[4]=-sy_fix[4];
+ }
+
+ fillbitmap(pri_alp_bitmap,0,cliprect);
+
+ /* sprites */
+ if (sprite_lag==0)
+ get_sprite_info(machine, spriteram32);
+
+ /* Update sprite buffer */
+ draw_sprites(machine, bitmap,cliprect);
+
+ /* Parse sprite, alpha & clipping parts of lineram */
+ get_spritealphaclip_info();
+
+ /* Parse playfield effects */
+ get_line_ram_info(machine, pf1_tilemap,sx_fix[0],sy_fix[0],0,f3_pf_data_1);
+ get_line_ram_info(machine, pf2_tilemap,sx_fix[1],sy_fix[1],1,f3_pf_data_2);
+ get_line_ram_info(machine, pf3_tilemap,sx_fix[2],sy_fix[2],2,f3_pf_data_3);
+ get_line_ram_info(machine, pf4_tilemap,sx_fix[3],sy_fix[3],3,f3_pf_data_4);
+ get_vram_info(vram_layer,pixel_layer,sx_fix[4],sy_fix[4]);
+
+ /* Draw final framebuffer */
+ scanline_draw(machine, bitmap,cliprect);
+
+ if (VERBOSE)
+ print_debug_info(bitmap);
+ return 0;
+}