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

                                    





                                                                    
                
                              
                   

 























                                                                            
                                                              
 
                                                               
 

                                     
         


















                                                                                    


                             
                          
                                                                     
 

                                      
                                                                     
 

                                      
                                                                                  
 
                                                                                 
 
                                                                        










                                                                            
                                                                                                     



                                          
                                                                                                            
            
                                                                                                                                        
 
                                                 




                                                       
                                                    
 
                                                                           

 
                                                    
 
                                                                           

 
                                                    
 
                                                                           

 
                                                    
 
                                                                           
 







                                                                            
                                  
 



                                                                                                                                                                           
 

                                   
                                                                  




                                                                        
 
                                                    
 




                                        









                                                                            
                                          
 

                                                                         

 
                                          
 

                                                                           

 
                                                

                                 
                              
         


                                                  


         
                                                                                    



                       
                                                                             

                              
                                                                          

                              
                                                



                              
                                        
 
                                      
 
                                        
 
                                      
 
                                        
 
                                      
 
                                        
 
                                      

 
                                          
 
                           


 
                                          
 
                                            


                                                                                    
                                   




























                                                                            
                                                                                                         
 

                                                                                         
                                               
 

                                                                                  
 
                                                               


























                                                                   
                                  






                                         
                                                                              
 
                                                           
                                                   




                                                        
                                                                 





                               
                                          
 

                                       
                          



                                   

                                                     


 
                                                                                                              
 
                                                                     
                                                 



                      
 
                                            
 
                                                                                  
 
                                             
         
                                          
                 
                                                                    
                                                                                           


                 
                                             



                 
                                                
 
                      
                  
         
                                   
                 
                                                         
                         

                                                                                

                         
                                           
                 

         
// license:BSD-3-Clause
// copyright-holders:Nicola Salmoria
/*******************************************************************

Namco System 86 Video Hardware

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

#include "emu.h"
#include "includes/namcos86.h"
#include "screen.h"


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

  Convert the color PROMs into a more useable format.

  Rolling Thunder has two palette PROMs (512x8 and 512x4) and two 2048x8
  lookup table PROMs.
  The palette PROMs are connected to the RGB output this way:

  bit 3 -- 220 ohm resistor  -- BLUE
        -- 470 ohm resistor  -- BLUE
        -- 1  kohm resistor  -- BLUE
  bit 0 -- 2.2kohm resistor  -- BLUE

  bit 7 -- 220 ohm resistor  -- GREEN
        -- 470 ohm resistor  -- GREEN
        -- 1  kohm resistor  -- GREEN
        -- 2.2kohm resistor  -- GREEN
        -- 220 ohm resistor  -- RED
        -- 470 ohm resistor  -- RED
        -- 1  kohm resistor  -- RED
  bit 0 -- 2.2kohm resistor  -- RED

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

void namcos86_state::namcos86_palette(palette_device &palette)
{
	const uint8_t *color_prom = memregion("proms")->base();

	rgb_t palette_val[512];
	for (int i = 0; i < 512; i++)
	{
		int bit0, bit1, bit2, bit3;

		bit0 = BIT(color_prom[0], 0);
		bit1 = BIT(color_prom[0], 1);
		bit2 = BIT(color_prom[0], 2);
		bit3 = BIT(color_prom[0], 3);
		int const r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
		bit0 = BIT(color_prom[0], 4);
		bit1 = BIT(color_prom[0], 5);
		bit2 = BIT(color_prom[0], 6);
		bit3 = BIT(color_prom[0], 7);
		int const g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
		bit0 = BIT(color_prom[512], 0);
		bit1 = BIT(color_prom[512], 1);
		bit2 = BIT(color_prom[512], 2);
		bit3 = BIT(color_prom[512], 3);
		int const b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;

		palette_val[i] = rgb_t(r, g, b);
		color_prom++;
	}

	color_prom += 512;
	// color_prom now points to the beginning of the lookup table

	// tiles lookup table
	for (int i = 0; i < 2048; i++)
		palette.set_pen_color(i, palette_val[*color_prom++]);

	// sprites lookup table
	for (int i = 0; i < 2048; i++)
		palette.set_pen_color(2048 + i, palette_val[256 + *color_prom++]);

	// color_prom now points to the beginning of the tile address decode PROM

	m_tile_address_prom = color_prom; // we'll need this at run time
}




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

  Callbacks for the TileMap code

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

inline void namcos86_state::get_tile_info(tile_data &tileinfo,int tile_index,int layer,uint8_t *vram)
{
	int attr = vram[2*tile_index + 1];
	int tile_offs;
	if (layer & 2)
		tile_offs = ((m_tile_address_prom[((layer & 1) << 4) + (attr & 0x03)] & 0xe0) >> 5) * 0x100;
	else
		tile_offs = ((m_tile_address_prom[((layer & 1) << 4) + ((attr & 0x03) << 2)] & 0x0e) >> 1) * 0x100 + m_tilebank * 0x800;

	SET_TILE_INFO_MEMBER((layer & 2) ? 1 : 0,
			vram[2*tile_index] + tile_offs,
			attr,
			0);
}

TILE_GET_INFO_MEMBER(namcos86_state::get_tile_info0)
{
	get_tile_info(tileinfo,tile_index,0,&m_rthunder_videoram1[0x0000]);
}

TILE_GET_INFO_MEMBER(namcos86_state::get_tile_info1)
{
	get_tile_info(tileinfo,tile_index,1,&m_rthunder_videoram1[0x1000]);
}

TILE_GET_INFO_MEMBER(namcos86_state::get_tile_info2)
{
	get_tile_info(tileinfo,tile_index,2,&m_rthunder_videoram2[0x0000]);
}

TILE_GET_INFO_MEMBER(namcos86_state::get_tile_info3)
{
	get_tile_info(tileinfo,tile_index,3,&m_rthunder_videoram2[0x1000]);
}


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

  Start the video hardware emulation.

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

void namcos86_state::video_start()
{
	m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(namcos86_state::get_tile_info0)), TILEMAP_SCAN_ROWS, 8,8, 64,32);
	m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(namcos86_state::get_tile_info1)), TILEMAP_SCAN_ROWS, 8,8, 64,32);
	m_bg_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(namcos86_state::get_tile_info2)), TILEMAP_SCAN_ROWS, 8,8, 64,32);
	m_bg_tilemap[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(namcos86_state::get_tile_info3)), TILEMAP_SCAN_ROWS, 8,8, 64,32);

	for (int i = 0; i < 4; i++)
	{
		static constexpr int xdisp[] = { 47, 49, 46, 48 };

		m_bg_tilemap[i]->set_scrolldx(xdisp[i], 422 - xdisp[i]);
		m_bg_tilemap[i]->set_scrolldy(-9, 9);
		m_bg_tilemap[i]->set_transparent_pen(7);
	}

	m_spriteram = m_rthunder_spriteram + 0x1800;

	save_item(NAME(m_tilebank));
	save_item(NAME(m_xscroll));
	save_item(NAME(m_yscroll));
	save_item(NAME(m_backcolor));
	save_item(NAME(m_copy_sprites));
}



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

  Memory handlers

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

WRITE8_MEMBER(namcos86_state::videoram1_w)
{
	m_rthunder_videoram1[offset] = data;
	m_bg_tilemap[offset/0x1000]->mark_tile_dirty((offset & 0xfff)/2);
}

WRITE8_MEMBER(namcos86_state::videoram2_w)
{
	m_rthunder_videoram2[offset] = data;
	m_bg_tilemap[2+offset/0x1000]->mark_tile_dirty((offset & 0xfff)/2);
}

WRITE8_MEMBER(namcos86_state::tilebank_select_w)
{
	int bit = BIT(offset,10);
	if (m_tilebank != bit)
	{
		m_tilebank = bit;
		m_bg_tilemap[0]->mark_all_dirty();
		m_bg_tilemap[1]->mark_all_dirty();
	}
}

void namcos86_state::scroll_w(address_space &space, int offset, int data, int layer)
{
	switch (offset)
	{
		case 0:
			m_xscroll[layer] = (m_xscroll[layer]&0xff)|(data<<8);
			break;
		case 1:
			m_xscroll[layer] = (m_xscroll[layer]&0xff00)|data;
			break;
		case 2:
			m_yscroll[layer] = data;
			break;
	}
}

WRITE8_MEMBER(namcos86_state::scroll0_w)
{
	scroll_w(space,offset,data,0);
}
WRITE8_MEMBER(namcos86_state::scroll1_w)
{
	scroll_w(space,offset,data,1);
}
WRITE8_MEMBER(namcos86_state::scroll2_w)
{
	scroll_w(space,offset,data,2);
}
WRITE8_MEMBER(namcos86_state::scroll3_w)
{
	scroll_w(space,offset,data,3);
}

WRITE8_MEMBER(namcos86_state::backcolor_w)
{
	m_backcolor = data;
}


WRITE8_MEMBER(namcos86_state::spriteram_w)
{
	m_rthunder_spriteram[offset] = data;

	/* a write to this offset tells the sprite chip to buffer the sprite list */
	if (offset == 0x1ff2)
		m_copy_sprites = 1;
}


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

  Display refresh

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

/*
sprite format:

0-3  scratchpad RAM
4-9  CPU writes here, hardware copies from here to 10-15
10   xx------  X size (16, 8, 32, 4)
10   --x-----  X flip
10   ---xx---  X offset inside 32x32 tile
10   -----xxx  tile bank
11   xxxxxxxx  tile number
12   xxxxxxx-  color
12   -------x  X position MSB
13   xxxxxxxx  X position
14   xxx-----  priority
14   ---xx---  Y offset inside 32x32 tile
14   -----xx-  Y size (16, 8, 32, 4)
14   -------x  Y flip
15   xxxxxxxx  Y position
*/

void namcos86_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	const uint8_t *source = &m_spriteram[0x0800-0x20]; /* the last is NOT a sprite */
	const uint8_t *finish = &m_spriteram[0];
	gfx_element *gfx = m_gfxdecode->gfx(2);

	int sprite_xoffs = m_spriteram[0x07f5] + ((m_spriteram[0x07f4] & 1) << 8);
	int sprite_yoffs = m_spriteram[0x07f7];

	int bank_sprites = m_gfxdecode->gfx(2)->elements() / 8;

	while (source >= finish)
	{
		static const int sprite_size[4] = { 16, 8, 32, 4 };
		int attr1 = source[10];
		int attr2 = source[14];
		int color = source[12];
		int flipx = (attr1 & 0x20) >> 5;
		int flipy = (attr2 & 0x01);
		int sizex = sprite_size[(attr1 & 0xc0) >> 6];
		int sizey = sprite_size[(attr2 & 0x06) >> 1];
		int tx = (attr1 & 0x18) & (~(sizex-1));
		int ty = (attr2 & 0x18) & (~(sizey-1));
		int sx = source[13] + ((color & 0x01) << 8);
		int sy = -source[15] - sizey;
		int sprite = source[11];
		int sprite_bank = attr1 & 7;
		int priority = (source[14] & 0xe0) >> 5;
		int pri_mask = (0xff << (priority + 1)) & 0xff;

		sprite &= bank_sprites-1;
		sprite += sprite_bank * bank_sprites;
		color = color >> 1;

		sx += sprite_xoffs;
		sy -= sprite_yoffs;

		if (flip_screen())
		{
			sx = -sx - sizex;
			sy = -sy - sizey;
			flipx ^= 1;
			flipy ^= 1;
		}

		sy++;   /* sprites are buffered and delayed by one scanline */

		gfx->set_source_clip(tx, sizex, ty, sizey);
		gfx->prio_transpen(bitmap,cliprect,
				sprite,
				color,
				flipx,flipy,
				sx & 0x1ff,
				((sy + 16) & 0xff) - 16,
				screen.priority(), pri_mask,0xf);

		source -= 0x10;
	}
}


void namcos86_state::set_scroll(int layer)
{
	int scrollx = m_xscroll[layer];
	int scrolly = m_yscroll[layer];
	if (flip_screen())
	{
		scrollx = -scrollx;
		scrolly = -scrolly;
	}
	m_bg_tilemap[layer]->set_scrollx(0, scrollx);
	m_bg_tilemap[layer]->set_scrolly(0, scrolly);
}


uint32_t namcos86_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	/* flip screen is embedded in the sprite control registers */
	flip_screen_set(m_spriteram[0x07f6] & 1);
	set_scroll(0);
	set_scroll(1);
	set_scroll(2);
	set_scroll(3);

	screen.priority().fill(0, cliprect);

	bitmap.fill(m_gfxdecode->gfx(0)->colorbase() + 8*m_backcolor+7, cliprect);

	for (int layer = 0;layer < 8;layer++)
	{
		for (int i = 3;i >= 0;i--)
		{
			if (((m_xscroll[i] & 0x0e00) >> 9) == layer)
				m_bg_tilemap[i]->draw(screen, bitmap, cliprect, 0,layer,0);
		}
	}

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


WRITE_LINE_MEMBER(namcos86_state::screen_vblank)
{
	// rising edge
	if (state)
	{
		if (m_copy_sprites)
		{
			for (int i = 0;i < 0x800;i += 16)
			{
				for (int j = 10;j < 16;j++)
					m_spriteram[i+j] = m_spriteram[i+j - 6];
			}

			m_copy_sprites = 0;
		}
	}
}