summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/stfight_dev.cpp
blob: 7c5d26f04b54583543d05e50badf588c5c9de00a (plain) (tree)
1
2
3
4
5
6
7
8
9







                                                                                                                                              
                   

 
                                                                                                  

 

                                                                                                                             






















































































                                                                   




                                                                 


                                                                 

                                                                     
                            









                                                                                       
 






























































                                                                                              
                                                 






































                                                                                                               


                                           















                                                                       
                                                                                                                            

























                                                                                                                                                              
                                                                                                                                                                                                       


                                                              

                                                  






                                                                      

                                                            























                                                                                                              


                                                                                                                                                                                                                                      


































































                                                                                 
// license:BSD-3-Clause
// copyright-holders:Mark McDougall, David Haywood

// The Street Fight video appears to be 4 layers, very similar to Dark Mist and Air Raid, but at least without the CLUT transparency handling?
// which are presumably handled by the SEI0100BU chips on the other games (with the GFX inside the modules on Air Raid)

#include "emu.h"
#include "stfight_dev.h"
#include "screen.h"


DEFINE_DEVICE_TYPE(STFIGHT_VIDEO, stfight_video_device, "stfight_vid", "Seibu Street Fight Video")


stfight_video_device::stfight_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, STFIGHT_VIDEO, tag, owner, clock),
	m_gfxdecode(*this, "gfxdecode"),
	m_palette(*this,"^palette"),
	m_screen(*this, "screen"),
	m_tx_clut(*this, "tx_clut"),
	m_fg_clut(*this, "fg_clut"),
	m_bg_clut(*this, "bg_clut"),
	m_spr_clut(*this, "spr_clut"),
	m_fgmap(*this,"fg_map"),
	m_bgmap(*this,"bg_map"),
	m_vregs(*this,"^vregs"),
	m_sprite_ram(*this, "^sprite_ram"),
	m_txram(*this, "^txram")
{
}

/* text-layer characters */
static const gfx_layout charlayout =
{
	8,8,        /* 8*8 pixels */
	512,        /* 512 characters */
	2,          /* 2 bits per pixel */
	{ 4, 0 },
	{ 0, 1, 2, 3, 8+0, 8+1, 8+2, 8+3 },
	{ 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
	8*16        /* every char takes 16 consecutive bytes */
};

/* foreground tiles */
static const gfx_layout fglayout =
{
	16,16,      /* 16*16 pixels */
	1024,       /* 1024 tiles */
	4,          /* 4 bits per pixel */
	{ 64*1024*8+0, 64*1024*8+4, 0, 4 },
	{      0,      1,       2,       3,
			8,      9,      10,      11,
		32*8+0, 32*8+1, 32*8+ 2, 32*8+ 3,
		32*8+8, 32*8+9, 32*8+10, 32*8+11 },
	{  0*8,  2*8,  4*8,  6*8,
		8*8, 10*8, 12*8, 14*8,
		16*8, 18*8, 20*8, 22*8,
		24*8, 26*8, 28*8, 30*8 },
	64*8        /* every char takes 64 consecutive bytes */
};

/*
 *      The background tiles are interleaved in banks of 2
 *      - so we need to create two separate layout structs
 *        to handle them properly with tilemaps
 */

/* background tiles */
static const gfx_layout bglayout =
{
	16,16,      /* 16*16 pixels */
	512,        /* 512 tiles */
	4,          /* 4 bits per pixel */
	{ 64*1024*8+4, 64*1024*8+0, 4, 0 },
	{      0,      1,       2,       3,
			8,      9,      10,      11,
		64*8+0, 64*8+1, 64*8+ 2, 64*8+ 3,
		64*8+8, 64*8+9, 64*8+10, 64*8+11 },
	{  0*8,  2*8,  4*8,  6*8,
		8*8, 10*8, 12*8, 14*8,
		16*8, 18*8, 20*8, 22*8,
		24*8, 26*8, 28*8, 30*8 },
	128*8       /* every tile takes 64/128 consecutive bytes */
};

/* sprites */
static const gfx_layout spritelayout =
{
	16,16,      /* 16*16 pixels */
	1024,       /* 1024 sprites */
	4,          /* 4 bits per pixel */
	{ 64*1024*8+0, 64*1024*8+4, 0, 4 },
	{      0,      1,       2,       3,
			8,      9,      10,      11,
		32*8+0, 32*8+1, 32*8+ 2, 32*8+ 3,
		32*8+8, 32*8+9, 32*8+10, 32*8+11 },
	{  0*8,  2*8,  4*8,  6*8,
		8*8, 10*8, 12*8, 14*8,
		16*8, 18*8, 20*8, 22*8,
		24*8, 26*8, 28*8, 30*8 },
	64*8        /* every sprite takes 64 consecutive bytes */
};

static GFXDECODE_START( gfx_stfight )
	GFXDECODE_ENTRY( "tx_gfx", 0x0000,  charlayout,   0, 16 )
	GFXDECODE_ENTRY( "fg_gfx", 0x0000,  fglayout,     0, 16 )
	GFXDECODE_ENTRY( "bg_gfx", 0x0000,  bglayout,     0, 16 )
	GFXDECODE_ENTRY( "bg_gfx", 0x0020,  bglayout,     0, 16 )
	GFXDECODE_ENTRY( "spr_gfx", 0x0000, spritelayout, 0, 32 )
GFXDECODE_END

void stfight_video_device::device_add_mconfig(machine_config &config)
{
	/* video hardware */
	SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
	m_screen->set_refresh_hz(60);
	m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0));
	m_screen->set_size(32*8, 32*8);
	m_screen->set_visarea(0*8, 32*8-1, 2*8, 30*8-1);
	m_screen->set_screen_update(FUNC(stfight_video_device::screen_update_stfight));
	m_screen->set_palette(m_palette);

	GFXDECODE(config, m_gfxdecode, m_palette, gfx_stfight);
}

/*
        Graphics ROM Format
        ===================

        Each tile is 8x8 pixels
        Each composite tile is 2x2 tiles, 16x16 pixels
        Each screen is 32x32 composite tiles, 64x64 tiles, 256x256 pixels
        Each layer is a 4-plane bitmap 8x16 screens, 2048x4096 pixels

        There are 4x256=1024 composite tiles defined for each layer

        Each layer is mapped using 2 bytes/composite tile
        - one byte for the tile
        - one byte for the tile bank, attribute
            - b7,b5     tile bank (0-3)

        Each pixel is 4 bits = 16 colours.

 */

TILEMAP_MAPPER_MEMBER(stfight_video_device::fg_scan)
{
	/* logical (col,row) -> memory offset */
	return (col & 0x0f) + ((row & 0x0f) << 4) + ((col & 0x70) << 4) + ((row & 0xf0) << 7);
}

TILE_GET_INFO_MEMBER(stfight_video_device::get_fg_tile_info)
{
	int attr,tile_base;

	attr = m_fgmap[0x8000+tile_index];
	tile_base = ((attr & 0x80) << 2) | ((attr & 0x20) << 3);

	SET_TILE_INFO_MEMBER(1,
			tile_base + m_fgmap[tile_index],
			attr & 0x07,
			0);
}

TILEMAP_MAPPER_MEMBER(stfight_video_device::bg_scan)
{
	/* logical (col,row) -> memory offset */
	return ((col & 0x0e) >> 1) + ((row & 0x0f) << 3) + ((col & 0x70) << 3) +
			((row & 0x80) << 3) + ((row & 0x10) << 7) + ((col & 0x01) << 12) +
			((row & 0x60) << 8);
}

TILE_GET_INFO_MEMBER(stfight_video_device::get_bg_tile_info)
{
	int attr,tile_bank,tile_base;

	attr = m_bgmap[0x8000+tile_index];
	tile_bank = (attr & 0x20) >> 5;
	tile_base = (attr & 0x80) << 1;

	SET_TILE_INFO_MEMBER(2+tile_bank,
			tile_base + m_bgmap[tile_index],
			attr & 0x07,
			0);
}

TILE_GET_INFO_MEMBER(stfight_video_device::get_tx_tile_info)
{
	uint8_t attr = m_txram[tile_index+0x400];
	int color = attr & 0x0f;

	tileinfo.group = color;

	SET_TILE_INFO_MEMBER(0,
			m_txram[tile_index] + ((attr & 0x80) << 1),
			attr & 0x0f,
			TILE_FLIPYX((attr & 0x60) >> 5));
}

void stfight_video_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	int offs, sx, sy;

	for (offs = 4096 - 32;offs >= 0;offs -= 32)
	{
		int code;
		int attr = m_sprite_ram[offs + 1];
		int flipx = attr & 0x10;
		int color = attr & 0x0f;
		color |= (attr & 0x20) >> 1; // mix in priority bit

		sy = m_sprite_ram[offs + 2];
		sx = m_sprite_ram[offs + 3];

		// non-active sprites have zero y coordinate value
		if (sy > 0)
		{
			// sprites which wrap onto/off the screen have
			// a sign extension bit in the sprite attribute
			if (sx >= 0xf0)
			{
				if (attr & 0x80)
					sx -= 0x100;
			}

			/*
			if (flip_screen())
			{
			    sx = 240 - sx;
			    sy = 240 - sy;
			    flipx = !flipx;
			}
			*/

			code = m_sprite_base + m_sprite_ram[offs];

			m_gfxdecode->gfx(4)->transpen(bitmap, cliprect,
				code,
				color,
				flipx, 0/*flip_screen()*/,
				sx, sy,
				0x0f);
		}
	}
}


uint32_t stfight_video_device::screen_update_stfight(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	bitmap.fill(0, cliprect);   /* in case m_bg_tilemap is disabled */

	m_temp_sprite_bitmap.fill(-1, cliprect);
	draw_sprites(screen, m_temp_sprite_bitmap, cliprect);

	m_temp_bitmap.fill(-1, cliprect);
	m_bg_tilemap->draw(screen, m_temp_bitmap, cliprect, 0, 0);
	mix_txlayer(screen, bitmap, m_temp_bitmap, cliprect, m_bg_clut, 0x00, 0x00, 0x00, false);

	if (m_vregs[0x07] & 0x40) mix_txlayer(screen, bitmap, m_temp_sprite_bitmap, cliprect, m_spr_clut, 0x80, 0x100, 0x100, false); // low priority sprites

	m_temp_bitmap.fill(-1, cliprect);
	m_fg_tilemap->draw(screen, m_temp_bitmap, cliprect, 0, 0);
	mix_txlayer(screen, bitmap, m_temp_bitmap, cliprect, m_fg_clut, 0x40, 0x00, 0x00, false);

	if (m_vregs[0x07] & 0x40) mix_txlayer(screen, bitmap, m_temp_sprite_bitmap, cliprect, m_spr_clut, 0x80, 0x100, 0x000, false); // high priority sprites

	m_temp_bitmap.fill(-1, cliprect);
	m_tx_tilemap->draw(screen, m_temp_bitmap, cliprect, 0, 0);
	mix_txlayer(screen, bitmap, m_temp_bitmap, cliprect, m_tx_clut, 0xc0, 0x00, 0x00, true);
	//
	return 0;
}


void stfight_video_device::mix_txlayer(screen_device &screen, bitmap_ind16 &bitmap, bitmap_ind16 &bitmap2, const rectangle &cliprect, uint8_t* clut, int base, int mask, int condition, bool realcheck)
{
	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
	{
		uint16_t *dest = &bitmap.pix16(y);
		uint16_t *src = &bitmap2.pix16(y);
		for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
		{
			if (src[x] == -1)
				continue;

			if ((src[x] & mask) == condition)
			{
				uint8_t pix = src[x] & 0xff;
				uint8_t real = clut[pix];

				if (realcheck) // the text layer transparency appears to be 0xf *after* lookup
				{
					if ((real & 0x0f) != 0x0f)
					{
						dest[x] = (real & 0x3f) + base;
					}
				}
				else if ((src[x] & 0xf) != 0xf) // other layers it's pre-lookup
				{
					dest[x] = (real & 0x3f) + base;
				}
			}
		}
	}
}

void stfight_video_device::device_start()
{
	if(!m_gfxdecode->started())
		throw device_missing_dependencies();

	save_item(NAME(m_sprite_base));

	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(stfight_video_device::get_bg_tile_info)), tilemap_mapper_delegate(*this, FUNC(stfight_video_device::bg_scan)), 16,16, 128,256);
	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(stfight_video_device::get_fg_tile_info)), tilemap_mapper_delegate(*this, FUNC(stfight_video_device::fg_scan)), 16,16, 128,256);
	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(stfight_video_device::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8,8, 32,32);

	// we do manual mixing using a temp bitmap
	m_screen->register_screen_bitmap(m_temp_sprite_bitmap);
	m_screen->register_screen_bitmap(m_temp_bitmap);
}

void stfight_video_device::device_reset()
{
}

// public functions

WRITE8_MEMBER(stfight_video_device::stfight_text_char_w)
{
	m_txram[offset] = data;
	m_tx_tilemap->mark_tile_dirty(offset&0x3ff);
}


WRITE8_MEMBER(stfight_video_device::stfight_sprite_bank_w)
{
	m_sprite_base = ( ( data & 0x04 ) << 7 ) |
							( ( data & 0x01 ) << 8 );
}

WRITE8_MEMBER(stfight_video_device::stfight_vh_latch_w)
{
	int scroll;


	m_vregs[offset] = data;

	switch( offset )
	{
		case 0x00:
		case 0x01:
			scroll = (m_vregs[1] << 8) | m_vregs[0];
			m_fg_tilemap->set_scrollx(0,scroll);
			break;

		case 0x02:
		case 0x03:
			scroll = (m_vregs[3] << 8) | m_vregs[2];
			m_fg_tilemap->set_scrolly(0,scroll);
			break;

		case 0x04:
		case 0x05:
			scroll = (m_vregs[5] << 8) | m_vregs[4];
			m_bg_tilemap->set_scrollx(0,scroll);
			break;

		case 0x06:
		case 0x08:
			scroll = (m_vregs[8] << 8) | m_vregs[6];
			m_bg_tilemap->set_scrolly(0,scroll);
			break;

		case 0x07:
			m_tx_tilemap->enable(data & 0x80);
			/* 0x40 = sprites */
			m_bg_tilemap->enable(data & 0x20);
			m_fg_tilemap->enable(data & 0x10);
			//flip_screen_set(data & 0x01);
			break;
	}
}