summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/fuukifg3.c
blob: e1552bb8d6580d46a8d7f7f285de0db01c9322c2 (plain) (tree)




























                                                                                            
                
                              


















                                                                            





                                                                                                                      

 








                                                                                                                      

 








                                                                                                      
 



                                                                                         











                                                                            
                                                                    

                                                                                                 
 

                                                                                        
 



                                                                                                          
 



                                                                         
 

                                                                                                                        






























                                                                               
                                                                                              
 
                                                                             
                 

                                                                     


                                                         
 
                                                                                                                            

                                               
                                                                              




                                                                 



                                                             



                                                 
                                                                                                            


                                               

                                 
 

                                    
 

                                              
 

                                                                


                                         


                                                                                                           






                                                                                                            
                                                      



                                                                            







                                                                              



                                                                                                  







                                                                       
                                                                              



                                                                                                 

                                                                                          
                                    
                                                                                  



                                                                                                                   

                                                                                                                                                                                                       




                         
                                                     
                                              
                     










































                                                                                          
                                                                                                                                 
 
                                                                    
                                                                      


                   

                                                                                                               
                                       
                                                                                       
                                       
                                                                                       



                                       
                        
 
                                                                              





                                              
                                                                                             

      







                                                                                      


                                                                          
 
                                                                                        


                              

                                                                                                                             
 



                                                                                       
 

                                                                        
 



                                                                    
 



                                                                    

                                                       
                                                       
                                                                  
 


                                                                                 
 
                                                


                 
                     
 
                                                                    
 
                                                     



                                                                                         
 
/***************************************************************************

                          -= Fuuki 32 Bit Games (FG-3) =-

                driver by Paul Priest and David Haywood
                based on fuukifg2 by Luca Elia


    [ 4 Scrolling Layers ]

                            [ Layer 0 ]     [ Layer 1 ]     [ Layers 2&3 (double-buffered) ]

    Tile Size:              16 x 16 x 8     16 x 16 x 8     8 x 8 x 4
    Layer Size (tiles):     64 x 32         64 x 32         64 x 32

    [ 1024? Zooming Sprites ]

    Sprites are made of 16 x 16 x 4 tiles. Size can vary from 1 to 16
    tiles both horizontally and vertically.
    There is zooming (from full size to half size) and 4 levels of
    priority (wrt layers)

    Per-line raster effects used on many stages
    Sprites buffered by two frames
    Tilebank buffered by 3 frames? Only 2 in attract
    Sprite pens needs to be buffered by 3 frames? Or lazy programming? Probably 2

***************************************************************************/

#include "emu.h"
#include "includes/fuukifg3.h"


/***************************************************************************


                                    Tilemaps

    Offset:     Bits:                   Value:

        0.w                             Code

        2.w     fedc ba98 ---- ----
                ---- ---- 7--- ----     Flip Y
                ---- ---- -6-- ----     Flip X
                ---- ---- --54 3210     Color


***************************************************************************/

INLINE void get_tile_info8bpp(running_machine &machine, tile_data *tileinfo, tilemap_memory_index tile_index, int _N_)
{
	fuuki32_state *state = machine.driver_data<fuuki32_state>();
	UINT16 code = (state->m_vram[_N_][tile_index] & 0xffff0000) >> 16;
	UINT16 attr = (state->m_vram[_N_][tile_index] & 0x0000ffff);
	SET_TILE_INFO(1 + _N_, code, (attr & 0x3f) >> 4, TILE_FLIPYX((attr >> 6) & 3));
}

static TILE_GET_INFO( get_tile_info_0 ) { get_tile_info8bpp(machine, tileinfo, tile_index, 0); }
static TILE_GET_INFO( get_tile_info_1 ) { get_tile_info8bpp(machine, tileinfo, tile_index, 1); }

INLINE void get_tile_info4bpp(running_machine &machine, tile_data *tileinfo, tilemap_memory_index tile_index, int _N_)
{
	fuuki32_state *state = machine.driver_data<fuuki32_state>();
	UINT16 code = (state->m_vram[_N_][tile_index] & 0xffff0000) >> 16;
	UINT16 attr = (state->m_vram[_N_][tile_index] & 0x0000ffff);
	SET_TILE_INFO(1 + _N_, code, attr & 0x3f, TILE_FLIPYX((attr >> 6) & 3));
}

static TILE_GET_INFO( get_tile_info_2 ) { get_tile_info4bpp(machine, tileinfo, tile_index, 2); }
static TILE_GET_INFO( get_tile_info_3 ) { get_tile_info4bpp(machine, tileinfo, tile_index, 3); }

INLINE void fuuki32_vram_w(address_space *space, offs_t offset, UINT32 data, UINT32 mem_mask, int _N_)
{
	fuuki32_state *state = space->machine().driver_data<fuuki32_state>();
	COMBINE_DATA(&state->m_vram[_N_][offset]);
	tilemap_mark_tile_dirty(state->m_tilemap[_N_],offset);
}

WRITE32_HANDLER( fuuki32_vram_0_w ) { fuuki32_vram_w(space, offset, data, mem_mask, 0); }
WRITE32_HANDLER( fuuki32_vram_1_w ) { fuuki32_vram_w(space, offset, data, mem_mask, 1); }
WRITE32_HANDLER( fuuki32_vram_2_w ) { fuuki32_vram_w(space, offset, data, mem_mask, 2); }
WRITE32_HANDLER( fuuki32_vram_3_w ) { fuuki32_vram_w(space, offset, data, mem_mask, 3); }


/***************************************************************************


                            Video Hardware Init


***************************************************************************/

VIDEO_START( fuuki32 )
{
	fuuki32_state *state = machine.driver_data<fuuki32_state>();
	state->m_buf_spriteram = auto_alloc_array(machine, UINT32, state->m_spriteram_size / 4);
	state->m_buf_spriteram2 = auto_alloc_array(machine, UINT32, state->m_spriteram_size / 4);

	state->save_pointer(NAME(state->m_buf_spriteram), state->m_spriteram_size / 4);
	state->save_pointer(NAME(state->m_buf_spriteram2), state->m_spriteram_size / 4);

	state->m_tilemap[0] = tilemap_create(machine, get_tile_info_0, tilemap_scan_rows, 16, 16, 64, 32);
	state->m_tilemap[1] = tilemap_create(machine, get_tile_info_1, tilemap_scan_rows, 16, 16, 64, 32);
	state->m_tilemap[2] = tilemap_create(machine, get_tile_info_2, tilemap_scan_rows, 8, 8, 64, 32);
	state->m_tilemap[3] = tilemap_create(machine, get_tile_info_3, tilemap_scan_rows, 8, 8, 64, 32);

	tilemap_set_transparent_pen(state->m_tilemap[0], 0xff);	// 8 bits
	tilemap_set_transparent_pen(state->m_tilemap[1], 0xff);	// 8 bits
	tilemap_set_transparent_pen(state->m_tilemap[2], 0x0f);	// 4 bits
	tilemap_set_transparent_pen(state->m_tilemap[3], 0x0f);	// 4 bits

	//machine.gfx[1]->color_granularity = 16; /* 256 colour tiles with palette selectable on 16 colour boundaries */
	//machine.gfx[2]->color_granularity = 16;
}


/***************************************************************************


                                Sprites Drawing

    Offset:     Bits:                   Value:

        0.w     fedc ---- ---- ----     Number Of Tiles Along X - 1
                ---- b--- ---- ----     Flip X
                ---- -a-- ---- ----     1 = Don't Draw This Sprite
                ---- --98 7654 3210     X (Signed)

        2.w     fedc ---- ---- ----     Number Of Tiles Along Y - 1
                ---- b--- ---- ----     Flip Y
                ---- -a-- ---- ----
                ---- --98 7654 3210     Y (Signed)

        4.w     fedc ---- ---- ----     Zoom X ($0 = Full Size, $F = Half Size)
                ---- ba98 ---- ----     Zoom Y ""
                ---- ---- 76-- ----     Priority
                ---- ---- --54 3210     Color

        6.w     fe-- ---- ---- ----     Tile Bank
                --dc ba98 7654 3210     Tile Code


***************************************************************************/

static void draw_sprites( screen_device &screen, bitmap_t *bitmap, const rectangle *cliprect )
{
	fuuki32_state *state = screen.machine().driver_data<fuuki32_state>();
	int offs;
	const gfx_element *gfx = screen.machine().gfx[0];
	bitmap_t *priority_bitmap = screen.machine().priority_bitmap;
	const rectangle &visarea = screen.visible_area();
	int max_x =	visarea.max_x + 1;
	int max_y =	visarea.max_y + 1;

	UINT32 *src = state->m_buf_spriteram2; /* Use spriteram buffered by 2 frames, need palette buffered by one frame? */

	/* Draw them backwards, for pdrawgfx */
	for (offs = (state->m_spriteram_size - 8) / 4; offs >= 0; offs -= 8/4)
	{
		int x, y, xstart, ystart, xend, yend, xinc, yinc;
		int xnum, ynum, xzoom, yzoom, flipx, flipy;
		int pri_mask;

		int sx = (src[offs + 0]& 0xffff0000) >> 16;
		int sy = (src[offs + 0]& 0x0000ffff);
		int attr = (src[offs + 1]& 0xffff0000) >> 16;
		int code = (src[offs + 1]& 0x0000ffff);

		int bank = (code & 0xc000) >> 14;
		int bank_lookedup;

		bank_lookedup = ((state->m_spr_buffered_tilebank[1] & 0xffff0000) >> (16 + bank * 4)) & 0xf;
		code &= 0x3fff;
		code += bank_lookedup * 0x4000;

		if (sx & 0x400)
			continue;

		flipx = sx & 0x0800;
		flipy = sy & 0x0800;

		xnum = ((sx >> 12) & 0xf) + 1;
		ynum = ((sy >> 12) & 0xf) + 1;

		xzoom = 16 * 8 - (8 * ((attr >> 12) & 0xf)) / 2;
		yzoom = 16 * 8 - (8 * ((attr >>  8) & 0xf)) / 2;

		switch( (attr >> 6) & 3 )
		{
			case 3:	pri_mask = 0xf0 | 0xcc | 0xaa;	break;	// behind all layers
			case 2:	pri_mask = 0xf0 | 0xcc;			break;	// behind fg + middle layer
			case 1:	pri_mask = 0xf0;				break;	// behind fg layer
			case 0:
			default:	pri_mask = 0;						// above all
		}

		sx = (sx & 0x1ff) - (sx & 0x200);
		sy = (sy & 0x1ff) - (sy & 0x200);

		if (flip_screen_get(screen.machine()))
		{
			flipx = !flipx;		sx = max_x - sx - xnum * 16;
			flipy = !flipy;		sy = max_y - sy - ynum * 16;
		}

		if (flipx)	{ xstart = xnum-1;  xend = -1;    xinc = -1; }
		else		{ xstart = 0;       xend = xnum;  xinc = +1; }

		if (flipy)	{ ystart = ynum-1;  yend = -1;    yinc = -1; }
		else		{ ystart = 0;       yend = ynum;  yinc = +1; }

#if 0
		if(!( (screen.machine().input().code_pressed(KEYCODE_V) && (((attr >> 6)&3) == 0))
		   || (screen.machine().input().code_pressed(KEYCODE_B) && (((attr >> 6)&3) == 1))
		   || (screen.machine().input().code_pressed(KEYCODE_N) && (((attr >> 6)&3) == 2))
		   || (screen.machine().input().code_pressed(KEYCODE_M) && (((attr >> 6)&3) == 3))
		   ))
#endif

		for (y = ystart; y != yend; y += yinc)
		{
			for (x = xstart; x != xend; x += xinc)
			{
				if (xzoom == (16*8) && yzoom == (16*8))
					pdrawgfx_transpen(bitmap,cliprect,gfx,
									code++,
									attr & 0x3f,
									flipx, flipy,
									sx + x * 16, sy + y * 16,
									priority_bitmap,
									pri_mask,15	);
				else
					pdrawgfxzoom_transpen(bitmap,cliprect,gfx,
									code++,
									attr & 0x3f,
									flipx, flipy,
									sx + (x * xzoom) / 8, sy + (y * yzoom) / 8,
									(0x10000/0x10/8) * (xzoom + 8),(0x10000/0x10/8) * (yzoom + 8),	priority_bitmap,// nearest greater integer value to avoid holes
									pri_mask,15	);
			}
		}

#ifdef MAME_DEBUG
#if 0
if (screen.machine().input().code_pressed(KEYCODE_X))
{	/* Display some info on each sprite */
	char buf[40];
	sprintf(buf, "%Xx%X %X",xnum,ynum,(attr>>6)&3);
	ui_draw_text(buf, sx, sy);
}
#endif
#endif
	}
}


/***************************************************************************


                                Screen Drawing

    Video Registers (fuuki32_vregs):

        00.w        Layer 0 Scroll Y
        02.w        Layer 0 Scroll X
        04.w        Layer 1 Scroll Y
        06.w        Layer 1 Scroll X
        08.w        Layer 2 Scroll Y
        0a.w        Layer 2 Scroll X
        0c.w        Layers Y Offset
        0e.w        Layers X Offset

        10-1a.w     ? 0
        1c.w        Trigger a level 5 irq on this raster line
        1e.w        ? $3390/$3393 (Flip Screen Off/On), $0040 is buffer for tilemap 2 or 3

    Priority Register (fuuki32_priority):

        fedc ba98 7654 3---
        ---- ---- ---- -210     Layer Order


    Unknown Registers ($de0000.l):

        00.w        ? $0200/$0201   (Flip Screen Off/On)
        02.w        ? $f300/$0330

***************************************************************************/

/* Wrapper to handle bg and bg2 ttogether */
static void fuuki32_draw_layer( running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect, int i, int flag, int pri )
{
	fuuki32_state *state = machine.driver_data<fuuki32_state>();
	int buffer = ((state->m_vregs[0x1e / 4] & 0x0000ffff) & 0x40);

	switch( i )
	{
		case 2:	if (buffer)	tilemap_draw(bitmap, cliprect, state->m_tilemap[3], flag, pri);
				else		tilemap_draw(bitmap, cliprect, state->m_tilemap[2], flag, pri);
				return;
		case 1:	tilemap_draw(bitmap, cliprect, state->m_tilemap[1], flag, pri);
				return;
		case 0:	tilemap_draw(bitmap, cliprect, state->m_tilemap[0], flag, pri);
				return;
	}
}

SCREEN_UPDATE( fuuki32 )
{
	fuuki32_state *state = screen->machine().driver_data<fuuki32_state>();
	UINT16 layer0_scrollx, layer0_scrolly;
	UINT16 layer1_scrollx, layer1_scrolly;
	UINT16 layer2_scrollx, layer2_scrolly;
	UINT16 scrollx_offs,   scrolly_offs;

	/*
    It's not independent bits causing layers to switch, that wouldn't make sense with 3 bits.
    */

	static const int pri_table[6][3] = {
		{ 0, 1, 2 }, // Special moves 0>1, 0>2 (0,1,2 or 0,2,1)
		{ 0, 2, 1 }, // Two Levels - 0>1 (0,1,2 or 0,2,1 or 2,0,1)
		{ 1, 0, 2 }, // Most Levels - 2>1 1>0 2>0 (1,0,2)
		{ 1, 2, 0 }, // Not used?
		{ 2, 0, 1 }, // Title etc. - 0>1 (0,1,2 or 0,2,1 or 2,0,1)
		{ 2, 1, 0 }}; // Char Select, prison stage 1>0 (leaves 1,2,0 or 2,1,0)

	int tm_front  = pri_table[(state->m_priority[0] >> 16) & 0x0f][0];
	int tm_middle = pri_table[(state->m_priority[0] >> 16) & 0x0f][1];
	int tm_back   = pri_table[(state->m_priority[0] >> 16) & 0x0f][2];

	flip_screen_set(screen->machine(), (state->m_vregs[0x1e / 4] & 0x0000ffff) & 1);

	/* Layers scrolling */

	scrolly_offs = ((state->m_vregs[0xc / 4] & 0xffff0000) >> 16) - (flip_screen_get(screen->machine()) ? 0x103 : 0x1f3);
	scrollx_offs =  (state->m_vregs[0xc / 4] & 0x0000ffff) - (flip_screen_get(screen->machine()) ? 0x2c7 : 0x3f6);

	layer0_scrolly = ((state->m_vregs[0x0 / 4] & 0xffff0000) >> 16) + scrolly_offs;
	layer0_scrollx = ((state->m_vregs[0x0 / 4] & 0x0000ffff)) + scrollx_offs;
	layer1_scrolly = ((state->m_vregs[0x4 / 4] & 0xffff0000) >> 16) + scrolly_offs;
	layer1_scrollx = ((state->m_vregs[0x4 / 4] & 0x0000ffff)) + scrollx_offs;

	layer2_scrolly = ((state->m_vregs[0x8 / 4] & 0xffff0000) >> 16);
	layer2_scrollx = ((state->m_vregs[0x8 / 4] & 0x0000ffff));

	tilemap_set_scrollx(state->m_tilemap[0], 0, layer0_scrollx);
	tilemap_set_scrolly(state->m_tilemap[0], 0, layer0_scrolly);
	tilemap_set_scrollx(state->m_tilemap[1], 0, layer1_scrollx);
	tilemap_set_scrolly(state->m_tilemap[1], 0, layer1_scrolly);

	tilemap_set_scrollx(state->m_tilemap[2], 0, layer2_scrollx);
	tilemap_set_scrolly(state->m_tilemap[2], 0, layer2_scrolly);
	tilemap_set_scrollx(state->m_tilemap[3], 0, layer2_scrollx);
	tilemap_set_scrolly(state->m_tilemap[3], 0, layer2_scrolly);

	/* The bg colour is the last pen i.e. 0x1fff */
	bitmap_fill(bitmap, cliprect, (0x800 * 4) - 1);
	bitmap_fill(screen->machine().priority_bitmap,cliprect,0);

	fuuki32_draw_layer(screen->machine(), bitmap, cliprect, tm_back,   0, 1);
	fuuki32_draw_layer(screen->machine(), bitmap, cliprect, tm_middle, 0, 2);
	fuuki32_draw_layer(screen->machine(), bitmap, cliprect, tm_front,  0, 4);

	draw_sprites(*screen, bitmap, cliprect);
	return 0;
}

SCREEN_EOF( fuuki32 )
{
	fuuki32_state *state = machine.driver_data<fuuki32_state>();

	/* Buffer sprites and tilebank by 2 frames */
	state->m_spr_buffered_tilebank[1] = state->m_spr_buffered_tilebank[0];
	state->m_spr_buffered_tilebank[0] = state->m_tilebank[0];
	memcpy(state->m_buf_spriteram2, state->m_buf_spriteram, state->m_spriteram_size);
	memcpy(state->m_buf_spriteram, state->m_spriteram, state->m_spriteram_size);
}