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




                                                                                                                 
 




                                       
                                                                                              
 
                                                                                                                           
                                                              





































                                                                                                                 
                                      





                                                                 
                                                              









                                                                              
                                                                         


                  


                                         


                                                    


                                                                                                                           
                                                                                                                                                                                                                                

                                                                             

                                                                                                                                                                                                                                
 
                                                                                                                                                                              
 

                                         































































                                                                                                         
                                                  

                                                          
                                                          












                                                                                                                                       
                                                                                                                                     


                                                              

                                                        

                                                                      

                                                    









                                                               
                                                                                                                            
 
                                               










                                                                   
                                       













































                                                                                                                                                                              
                                                         


                      
// license:BSD-3-Clause
// copyright-holders:Tomasz Slanina, Angelo Salese, hap, David Haywood

/* There are 2 versions of the Air Raid / Cross Shooter hardware, one has everything integrated on a single PCB
   the other is a Air Raid specific video PCB used with the Street Fight motherboard, there could be differences.

   This is very similar to Dark Mist */

#include "emu.h"
#include "airraid_dev.h"

DEFINE_DEVICE_TYPE(AIRRAID_VIDEO, airraid_video_device, "airraid_vid", "Seibu Air Raid Video")

airraid_video_device::airraid_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, AIRRAID_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_sprite_ram(*this, "^sprite_ram"),
		m_txram(*this,"^txram"),
		m_vregs(*this,"^vregs"),
		m_hw(0x09)
{
}

static const gfx_layout charlayout =
{
	8,8,        /* 8*8 characters */
	RGN_FRAC(1,1),      /* 512 characters */
	2,          /* 4 bits per pixel */
	{ 0,4 },
	{ 8,9,10,11,0,1,2,3 },
	{ 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
	128*1
};

static const gfx_layout char16layout =
{
	16,16,        /* 8*8 characters */
	RGN_FRAC(1,1),      /* 512 characters */
	4,          /* 4 bits per pixel */
	{ 0,4,8,12 },
	{ 0,1,2,3, 16,17,18,19, 512+0,512+1,512+2,512+3, 512+16,512+17,512+18,512+19},
	{ 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, 8*32, 9*32, 10*32, 11*32, 12*32, 13*32, 14*32, 15*32 },
	32*32
};

static GFXDECODE_START( gfx_cshooter )
	GFXDECODE_ENTRY( "tx_gfx", 0,     charlayout, 0, 16  )
	GFXDECODE_ENTRY( "spr_gfx", 0,     char16layout, 0, 16  )
	GFXDECODE_ENTRY( "bg_gfx", 0,     char16layout, 0, 16  )
	GFXDECODE_ENTRY( "fg_gfx", 0,     char16layout, 0, 16  )
GFXDECODE_END

MACHINE_CONFIG_START(airraid_video_device::device_add_mconfig)

	/* video hardware */
	MCFG_SCREEN_ADD("screen", RASTER)
	MCFG_SCREEN_REFRESH_RATE(60)
	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
	MCFG_SCREEN_SIZE(256, 256)
	MCFG_SCREEN_VISIBLE_AREA(0, 256-1, 16, 256-1-16)
	MCFG_SCREEN_UPDATE_DRIVER(airraid_video_device, screen_update_airraid)
	MCFG_SCREEN_PALETTE("^palette")

	MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "^palette", gfx_cshooter)

MACHINE_CONFIG_END


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

	save_item(NAME(m_hw));

	// there might actually be 4 banks of 2048 x 16 tilemaps in here as the upper scroll bits are with the rom banking.
	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(airraid_video_device::get_bg_tile_info),this),tilemap_mapper_delegate(FUNC(airraid_video_device::bg_scan),this),16,16,2048, 64);

	// which could in turn mean this is actually 256 x 128, not 256 x 512
//  m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(airraid_video_device::get_fg_tile_info),this),tilemap_mapper_delegate(FUNC(airraid_video_device::fg_scan),this),16,16,256, 512);
	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(airraid_video_device::get_fg_tile_info),this),tilemap_mapper_delegate(FUNC(airraid_video_device::fg_scan),this),16,16,256, 128);

	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(airraid_video_device::get_cstx_tile_info),this),TILEMAP_SCAN_ROWS, 8,8,32,32);

//  m_fg_tilemap->set_transparent_pen(0);
//  m_tx_tilemap->set_transparent_pen(0);

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

void airraid_video_device::device_reset()
{
}

TILEMAP_MAPPER_MEMBER(airraid_video_device::bg_scan)
{
	return ((row&0xf) * 0x10) + (col&0xf) + (((col&0x7f0) >> 4)*0x100) + ((row & 0x30)>>4) * 0x8000;
}

TILEMAP_MAPPER_MEMBER(airraid_video_device::fg_scan)
{
	return ((row&0xf) * 0x10) + (col&0xf) + (((col&0x0f0) >> 4)*0x100) + ((row & 0x1f0)>>4) * 0x1000;
}


TILE_GET_INFO_MEMBER(airraid_video_device::get_bg_tile_info)
{
	int tile = m_bgmap[(tile_index*2)+1] & 0xff;
	int attr = m_bgmap[(tile_index*2)+0] & 0xff;

	tile |= (attr & 0x70) << 4;

	SET_TILE_INFO_MEMBER(2,
			tile,
			attr&0xf,
			0);
}

TILE_GET_INFO_MEMBER(airraid_video_device::get_fg_tile_info)
{
	int tile = m_fgmap[(tile_index*2)+1] & 0xff;
	int attr = m_fgmap[(tile_index*2)+0] & 0xff;

	tile |= (attr & 0x70) << 4;

	SET_TILE_INFO_MEMBER(3,
			tile,
			attr&0xf,
			0);
}

TILE_GET_INFO_MEMBER(airraid_video_device::get_cstx_tile_info)
{
	int code = (m_txram[tile_index*2]);
	int attr = (m_txram[tile_index*2+1]);
	int color = attr & 0xf;

	SET_TILE_INFO_MEMBER(0, (code << 1) | ((attr & 0x20) >> 5), color, 0);
}



void airraid_video_device::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	for (int i = 0x200 - 4; i >= 0 ; i -= 4)
	{
		if (m_sprite_ram[i+1]&0x80)
			continue;

		uint16_t tile = (m_sprite_ram[i]);
		tile |= (m_sprite_ram[i + 1] & 0x70) << 4;

		uint16_t col = (m_sprite_ram[i+1] & 0x0f);
		//col |= (m_sprite_ram[i+1] & 0x80)<<3;

		m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, tile,col, 0, 0, m_sprite_ram[i+3],m_sprite_ram[i+2],0);
	}
}


#define DISPLAY_SPR     1
#define DISPLAY_FG      2
#define DISPLAY_BG      4
#define DISPLAY_TXT     8
#define DM_GETSCROLL(n) (((m_vregs[(n)]<<1)&0xff) + ((m_vregs[(n)]&0x80)?1:0) +( ((m_vregs[(n)-1]<<4) | (m_vregs[(n)-1]<<12) )&0xff00))

void airraid_video_device::mix_layer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t* clut, int base)
{
	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
	{
		uint16_t *dest = &bitmap.pix16(y);
		uint16_t *src = &m_temp_bitmap.pix16(y);
		for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
		{
			uint8_t pix = src[x] & 0xff;
			uint8_t real = clut[pix];

			if (!(real & 0x40))
			{
				dest[x] = (real & 0x3f) + base;
			}
		}
	}
}


uint32_t airraid_video_device::screen_update_airraid(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	uint16_t bgscrolly = DM_GETSCROLL(0x6);
	// this is more likely to be 'bank' than scroll, like NMK16
	bgscrolly += ((m_hw & 0xc0) >> 6) * 256;

	m_bg_tilemap->set_scrollx(0, DM_GETSCROLL(0x2));
	m_bg_tilemap->set_scrolly(0, bgscrolly);
	m_fg_tilemap->set_scrollx(0, DM_GETSCROLL(0xa));
	m_fg_tilemap->set_scrolly(0, DM_GETSCROLL(0xe));

	// draw screen
	bitmap.fill(0x80, cliprect); // temp

//  m_temp_bitmap.fill(0x00, cliprect);

	if ((m_hw & DISPLAY_BG) == 0x00)
	{
		m_bg_tilemap->draw(screen, m_temp_bitmap, cliprect, 0, 0);
		mix_layer(screen, bitmap, cliprect, m_bg_clut, 0x80);
	}

	if ((m_hw & DISPLAY_FG) == 0x00)
	{
		m_fg_tilemap->draw(screen, m_temp_bitmap, cliprect, 0, 0);
		mix_layer(screen, bitmap, cliprect, m_fg_clut, 0x00);
	}

	if (m_hw & DISPLAY_SPR)
	{
		m_temp_bitmap.fill(0x00, cliprect);
		draw_sprites(m_temp_bitmap, cliprect); // technically this should draw manually because 0x40 in the prom is transparency and our code just assumes it to be 0.
		mix_layer(screen, bitmap, cliprect, m_spr_clut, 0x40);
	}

	if (m_hw & DISPLAY_TXT)
	{
		m_tx_tilemap->draw(screen, m_temp_bitmap, cliprect, 0, 0);
		mix_layer(screen, bitmap, cliprect, m_tx_clut, 0xc0);
	}


	return 0;
}

// public functions

WRITE8_MEMBER(airraid_video_device::txram_w)
{
	m_txram[offset] = data;
	m_tx_tilemap->mark_tile_dirty(offset/2);
}

WRITE8_MEMBER(airraid_video_device::vregs_w)
{
	m_vregs[offset] = data;

	if ((offset != 0x2) && (offset != 0x01) && (offset != 0xa) && (offset != 0x09)   && (offset != 0xe) && (offset != 0x0d)  )
		printf("vregs_w %02x: %02x\n", offset, data);
}

void airraid_video_device::layer_enable_w(uint8_t enable)
{
	m_hw = enable;
}