summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/m90.cpp
blob: 2bdeef80636252717dfeed65c7442dd526fd4e83 (plain) (tree)
1
2

                                  














                                                                              
                                                    




                                                                      
                                                    
                                                                 




                                                                              
                
                         
                   
 
                    
 
                                              
 
                                                        
                       
 

                                      
                               


                                                          
                                                                   

 
                                     
 



                                                                                                                                                                       





                                                               

 
                             
 
                              
 

                                                 
 

                         

 
                                      
 
                              
 



                                                 

 
                                      
 
                              
 

                                                 

 
                                                                                                   
 
                                                      

                 
                                                  


                                                      

                                                         
 

                                              



                            

                                                     
 
                                                                    


                                           
 
                                                           
                                                                                   



                                                                          
                                                          
                                                                         
                                                                
                                                                                   



                                                                          
                                                          
                                                                                 
                            
                                                                                   



                                                                          
                                                          
                                                


         
                                                                                                            
 
                                      

                                    
 
                                                                                
         





                                                      

                                                           
 

                                                        



                            

                                    

                                                       
 
                                                                   



                                       
                                                  
                                                                 


         
                                                                                                            
 
                                      
                                    
 
                                                                                
         





                                                      

                                                           
 

                                                        
 

                            
 

                                    

                                                       
 
                                                                   
                                       


                                       
                                                  
                                                                 

         
 
                                      
 
                                            
 




                                                                                       
 



                                                                                  

 
                                          
 
                                            
 




                                                                              

 
                                                                                                             
 
                                                                                       
 



                                                                                                           
 



                                          
 

                                                                       
                                               
         
                                                         

                                                                         
                 

                                                                                                 

                                                               
                                                   
                 
 
                                     
                                             


                                                                   
 
                                                     
                         

                                                                                                                                            





                                                                 

                                                                                                                                 
                 
         
 





                                                              
                                            
 
                         
         

                                                                       
                 




                                                                             
                         
                                                               
 
                                                        
                                 


                                                                                                                
                                 
                                    
                                 


                                                                                                                
                                 
                         
                 

                    











                                                                                           
                 




                                         
 



                                                                       
                 




                                                                             
                         
                                                               
 






                                                                                                                
                                 


                                                                                                                

                                 








                                                                                           

                            


                                                                                           
                         
                 
         
 

                                             

                 
 
                                                                                                                  
 
              
                                            
                                                      
 
                             
                                           





                                                                                            
                



                                                                            

         
                                             




                                                                             
                




                                                                             
         
 
                                             



                                                                             
                



                                                                             
         
 
                                                      


                 
 
                                                                                                                  
 
                                            
                                                      
 
                                                 





                                                                             
                





                                                                            
         
 
                                                 





                                                                             
                





                                                                            

         
                                                      


                 
// license:BSD-3-Clause
// copyright-holders:Bryan McPhail
/*****************************************************************************

    Irem M90 system.  There is 1 video chip - NANAO GA-25, it produces
    2 tilemaps and sprites.  16 control bytes:

    0:  Playfield 1 X scroll
    2:  Playfield 1 Y scroll
    4:  Playfield 2 X scroll
    6:  Playfield 2 Y scroll
    8:  Bit 0x01 - unknown (set by hasamu)
    10: Playfield 1 control
        Bits0x03 - Playfield 1 VRAM base
        Bit 0x04 - Playfield 1 width (0 is 64 tiles, 0x4 is 128 tiles)
        Bit 0x10 - Playfield 1 disable
        Bit 0x20 - Playfield 1 rowscroll enable
        Bit 0x40 - Playfield 1 y-offset table enable
    12: Playfield 2 control
        Bits0x03 - Playfield 2 VRAM base
        Bit 0x04 - Playfield 2 width (0 is 64 tiles, 0x4 is 128 tiles)
        Bit 0x10 - Playfield 2 disable
        Bit 0x20 - Playfield 2 rowscroll enable
        Bit 0x40 - Playfield 2 y-offset table enable
    14: Bits0x03 - Sprite/Tile Priority (related to sprite color)

    Emulation by Bryan McPhail, mish@tendril.co.uk, thanks to Chris Hardy!

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

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

#include <algorithm>

TILE_GET_INFO_MEMBER(m90_state::get_tile_info)
{
	uint16_t *vram = (uint16_t*)tilemap.user_data();
	int tile,color;

	tile=vram[tile_index<<1];
	color=vram[(tile_index<<1)|1];
	SET_TILE_INFO_MEMBER(0,
			tile,
			color&0xf,
			TILE_FLIPYX((color & 0xc0) >> 6));
			tileinfo.category = (color & 0x30) ? 1 : 0;
}

void m90_state::common_tilemap_init()
{
	m_pf_layer[0][0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(m90_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8,8,  64,64);
	m_pf_layer[0][1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(m90_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8,8, 128,64);
	m_pf_layer[1][0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(m90_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8,8,  64,64);
	m_pf_layer[1][1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(m90_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8,8, 128,64);

	// fix for bootlegs
	m_pf_layer[0][0]->set_user_data(&m_video_data[0x0000]);
	m_pf_layer[0][1]->set_user_data(&m_video_data[0x0000]);
	m_pf_layer[1][0]->set_user_data(&m_video_data[0x4000]);
	m_pf_layer[1][1]->set_user_data(&m_video_data[0x4000]);
}

void m90_state::video_start()
{
	common_tilemap_init();

	m_pf_layer[0][0]->set_transparent_pen(0);
	m_pf_layer[0][1]->set_transparent_pen(0);

	m_last_pf[0] = 0;
	m_last_pf[1] = 2;
}

VIDEO_START_MEMBER(m90_state,bomblord)
{
	common_tilemap_init();

	m_pf_layer[1][0]->set_transparent_pen(0);
	m_pf_layer[1][1]->set_transparent_pen(0);
	m_pf_layer[0][0]->set_transparent_pen(0);
	m_pf_layer[0][1]->set_transparent_pen(0);
}

VIDEO_START_MEMBER(m90_state,dynablsb)
{
	common_tilemap_init();

	m_pf_layer[1][0]->set_transparent_pen(0);
	m_pf_layer[1][1]->set_transparent_pen(0);
}

void m90_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap,const rectangle &cliprect)
{
	uint16_t *spriteram = m_video_data + 0xee00/2;
	int offs;

	for (offs = 0x1f2/2; offs >= 0; offs -= 3)
	{
		int x,y,sprite,colour,fx,fy,y_multi,i;

		sprite = spriteram[offs+1];
		colour = (spriteram[offs+0] >> 9) & 0x0f;

		y = spriteram[offs+0] & 0x1ff;
		x = spriteram[offs+2] & 0x1ff;

		x = x - 16;
		y = 512 - y;

		fx = (spriteram[offs+2] >> 8) & 0x02;
		fy = (spriteram[offs+0] >> 8) & 0x80;

		y_multi = 1 << ((spriteram[offs+0] & 0x6000) >> 13);
		y -= 16 * y_multi;

		for (i = 0;i < y_multi;i++)

			if (m_video_control_data[7] & 0x01)
				m_gfxdecode->gfx(1)->prio_transpen(bitmap,cliprect,
					sprite + (fy ? y_multi-1 - i : i),
					colour,
					fx,fy,
					x,y+i*16,
					screen.priority(),
					(colour & 0x08) ? 0x00 : 0x02,0);
			else if (m_video_control_data[7] & 0x02)
				m_gfxdecode->gfx(1)->prio_transpen(bitmap,cliprect,
					sprite + (fy ? y_multi-1 - i : i),
					colour,
					fx,fy,
					x,y+i*16,
					screen.priority(),
					((colour & 0x0c)==0x0c) ? 0x00 : 0x02,0);
			else
				m_gfxdecode->gfx(1)->prio_transpen(bitmap,cliprect,
					sprite + (fy ? y_multi-1 - i : i),
					colour,
					fx,fy,
					x,y+i*16,
					screen.priority(),
					0x02,0);
	}
}

void m90_state::bomblord_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap,const rectangle &cliprect)
{
	int offs = 0, last_sprite = 0;
	int x,y,sprite,colour,fx,fy;


	while ((offs < m_spriteram.bytes()/2) & (m_spriteram[offs+0] != 0x8000))
	{
		last_sprite = offs;
		offs += 4;
	}

	for (offs = last_sprite; offs >= 0; offs -= 4)
	{
		sprite = m_spriteram[offs+1];
		colour = (m_spriteram[offs+2] >> 9) & 0x0f;

		y = (m_spriteram[offs+0] & 0x1ff) + 152;
		x = (m_spriteram[offs+3] & 0x1ff) + 16;

		x = x - 16;
		y = 512 - y;

		if (y < 0) y += 512;

		fx = (m_spriteram[offs+3] >> 8) & 0x02;
		fy = (m_spriteram[offs+2] >> 8) & 0x80;

		m_gfxdecode->gfx(1)->prio_transpen(bitmap,cliprect,
				sprite,
				colour,
				fx,fy,
				x,y,
				screen.priority(),
				(colour & 0x08) ? 0x00 : 0x02,0);
	}
}

void m90_state::dynablsb_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap,const rectangle &cliprect)
{
	int offs = 0, last_sprite = 0;
	int x,y,sprite,colour,fx,fy;

	while ((offs < m_spriteram.bytes()/2) & (m_spriteram[offs+0] != 0xffff))
	{
		last_sprite = offs;
		offs += 4;
	}

	for (offs = last_sprite; offs >= 0; offs -= 4)
	{
		sprite = m_spriteram[offs+1];
		colour = (m_spriteram[offs+2] >> 9) & 0x0f;

		y = (m_spriteram[offs+0] & 0x1ff) + 288;
		x = (m_spriteram[offs+3] & 0x1ff) - 64;

		x = x - 16;
		y = 512 - y;

		if (y < 0) y += 512;

		fx = (m_spriteram[offs+3] >> 8) & 0x02;
		fy = (m_spriteram[offs+2] >> 8) & 0x80;

		m_gfxdecode->gfx(1)->prio_transpen(bitmap,cliprect,
				sprite,
				colour,
				fx,fy,
				x,y,
				screen.priority(),
				(colour & 0x08) ? 0x00 : 0x02,0);
	}
}

WRITE16_MEMBER(m90_state::m90_video_w)
{
	COMBINE_DATA(&m_video_data[offset]);

	int page[2] = { m_video_control_data[5] & 0x3, m_video_control_data[6] & 0x3 };
	for (int i = 0; i < 2; i++)
	{
		if ((offset >> 13) == page[i])
			m_pf_layer[i][0]->mark_tile_dirty((offset & 0x1fff) >> 1);

		page[i] >>= 1;
		if ((offset >> 14) == page[i])
			m_pf_layer[i][1]->mark_tile_dirty((offset & 0x3fff) >> 1);
	}
}

WRITE16_MEMBER(m90_state::bootleg_video_w)
{
	COMBINE_DATA(&m_video_data[offset]);

	int layer = offset >> 14;
	if (!(offset & 0x2000))
		m_pf_layer[layer][0]->mark_tile_dirty((offset & 0x1fff) >> 1);

	m_pf_layer[layer][1]->mark_tile_dirty((offset & 0x3fff) >> 1);
}

uint32_t m90_state::screen_update_m90(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	int const layer_ctrl[2] = { m_video_control_data[5], m_video_control_data[6] };

	bool const video_enable = !(m_video_control_data[7] & 0x04);
	bool const pf_enable[2] = { !(m_video_control_data[5] & 0x10), !(m_video_control_data[6] & 0x10) };
	int const clip_miny = std::min(cliprect.min_y, 511);
	int const clip_maxy = std::min(cliprect.max_y, 511);

// m_pf_layer[0][0]->enable(pf_enable[0]);
// m_pf_layer[1][0]->enable(pf_enable[1]);
// m_pf_layer[0][1]->enable(pf_enable[0]);
// m_pf_layer[1][1]->enable(pf_enable[1]);

	constexpr int rowscroll_offs[2] = { 0xf000 >> 1, 0xf400 >> 1 };
	constexpr int rowscroll_bias[2] = { 2, -2 };
	for (int layer = 0; layer < 2; layer++)
	{
		/* Dirty tilemaps if VRAM base changes */
		uint8_t const pf_base = uint8_t(layer_ctrl[layer] & 0x3);
		if (pf_base != m_last_pf[layer])
		{
			m_pf_layer[layer][0]->set_user_data(&m_video_data[pf_base << 13]);
			m_pf_layer[layer][1]->set_user_data(&m_video_data[(pf_base & ~1) << 13]);
			m_pf_layer[layer][0]->mark_all_dirty();
			m_pf_layer[layer][1]->mark_all_dirty();
			m_last_pf[layer] = pf_base;
		}

		/* Setup scrolling */
		if (layer_ctrl[layer] & 0x20)
		{
			m_pf_layer[layer][0]->set_scroll_rows(512);
			m_pf_layer[layer][1]->set_scroll_rows(512);

			for (int i = 0; i < 512; i++)
			{
				m_pf_layer[layer][0]->set_scrollx(i, m_video_data[rowscroll_offs[layer] + i] + rowscroll_bias[layer]);
				m_pf_layer[layer][1]->set_scrollx(i, m_video_data[rowscroll_offs[layer] + i] + rowscroll_bias[layer] + 256);
			}
		}
		else
		{
			m_pf_layer[layer][0]->set_scroll_rows(1);
			m_pf_layer[layer][1]->set_scroll_rows(1);
			m_pf_layer[layer][0]->set_scrollx(0, m_video_control_data[1 | (layer<<1)] + rowscroll_bias[layer]);
			m_pf_layer[layer][1]->set_scrollx(0, m_video_control_data[1 | (layer<<1)] + rowscroll_bias[layer] + 256);
		}
	}

	if (!video_enable)
	{
		bitmap.fill(m_palette->black_pen(), cliprect);
		return 0;
	}

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

	if (pf_enable[1])
	{
		// use the playfield 2 y-offset table for each scanline
		if (layer_ctrl[1] & 0x40)
		{
			rectangle clip;
			clip.min_x = cliprect.min_x;
			clip.max_x = cliprect.max_x;

			for (int line = clip_miny; line <= clip_maxy; line++)
			{
				clip.min_y = clip.max_y = line;

				if (layer_ctrl[1] & 0x4)
				{
					m_pf_layer[1][1]->set_scrolly(0, 0x200 + m_video_data[0xfc00/2 + line]);
					m_pf_layer[1][1]->draw(screen, bitmap, clip, 0,0);
					m_pf_layer[1][1]->draw(screen, bitmap, clip, 1,1);
				}
				else
				{
					m_pf_layer[1][0]->set_scrolly(0, 0x200 + m_video_data[0xfc00/2 + line]);
					m_pf_layer[1][0]->draw(screen, bitmap, clip, 0,0);
					m_pf_layer[1][0]->draw(screen, bitmap, clip, 1,1);
				}
			}
		}
		else
		{
			if (layer_ctrl[1] & 0x4)
			{
				m_pf_layer[1][1]->set_scrolly(0, m_video_control_data[2] );
				m_pf_layer[1][1]->draw(screen, bitmap, cliprect, 0,0);
				m_pf_layer[1][1]->draw(screen, bitmap, cliprect, 1,1);
			}
			else
			{
				m_pf_layer[1][0]->set_scrolly(0, m_video_control_data[2] );
				m_pf_layer[1][0]->draw(screen, bitmap, cliprect, 0,0);
				m_pf_layer[1][0]->draw(screen, bitmap, cliprect, 1,1);
			}
		}
	}
	else
	{
		bitmap.fill(0, cliprect);
	}

	if (pf_enable[0])
	{
		// use the playfield 1 y-offset table for each scanline
		if (layer_ctrl[0] & 0x40)
		{
			rectangle clip;
			clip.min_x = cliprect.min_x;
			clip.max_x = cliprect.max_x;

			for (int line = clip_miny; line <= clip_maxy; line++)
			{
				clip.min_y = clip.max_y = line;

				if (layer_ctrl[0] & 0x4)
				{
					m_pf_layer[0][1]->set_scrolly(0, 0x200 + m_video_data[0xf800/2 + line]);
					m_pf_layer[0][1]->draw(screen, bitmap, clip, 0,0);
					m_pf_layer[0][1]->draw(screen, bitmap, clip, 1,1);
				}
				else
				{
					m_pf_layer[0][0]->set_scrolly(0, 0x200 + m_video_data[0xf800/2 + line]);
					m_pf_layer[0][0]->draw(screen, bitmap, clip, 0,0);
					m_pf_layer[0][0]->draw(screen, bitmap, clip, 1,1);
				}
			}
		}
		else
		{
			if (layer_ctrl[0] & 0x4)
			{
				m_pf_layer[0][1]->set_scrolly(0, m_video_control_data[0] );
				m_pf_layer[0][1]->draw(screen, bitmap, cliprect, 0,0);
				m_pf_layer[0][1]->draw(screen, bitmap, cliprect, 1,1);
			}
			else
			{
				m_pf_layer[0][0]->set_scrolly(0, m_video_control_data[0] );
				m_pf_layer[0][0]->draw(screen, bitmap, cliprect, 0,0);
				m_pf_layer[0][0]->draw(screen, bitmap, cliprect, 1,1);
			}
		}
	}

	draw_sprites(screen,bitmap,cliprect);

	return 0;
}

uint32_t m90_state::screen_update_bomblord(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	int i;
	screen.priority().fill(0, cliprect);
	bitmap.fill(m_palette->black_pen(), cliprect);

	/* Setup scrolling */
	if (m_video_control_data[6]&0x20) {
		m_pf_layer[0][0]->set_scroll_rows(512);
		m_pf_layer[0][1]->set_scroll_rows(512);
		for (i=std::min(cliprect.min_y,511); i<=std::min(cliprect.max_y,511); i++) {
			m_pf_layer[0][0]->set_scrollx(i, m_video_data[0xf400/2+i]-12);
			m_pf_layer[0][1]->set_scrollx(i, m_video_data[0xf400/2+i]-12+256);
		}
	} else {
		m_pf_layer[0][0]->set_scroll_rows(1);
		m_pf_layer[0][1]->set_scroll_rows(1);
		m_pf_layer[0][0]->set_scrollx(0, m_video_data[0xf004/2]-12);
		m_pf_layer[0][1]->set_scrollx(0, m_video_data[0xf004/2]-12);
	}

	if (m_video_control_data[6] & 0x02) {
		m_pf_layer[1][1]->mark_all_dirty();
		m_pf_layer[1][1]->set_scrollx(0, m_video_data[0xf000/2]-16 );
		m_pf_layer[1][1]->set_scrolly(0, m_video_data[0xf008/2]+388);
		m_pf_layer[1][1]->draw(screen, bitmap, cliprect, 0,0);
		m_pf_layer[1][1]->draw(screen, bitmap, cliprect, 1,1);
	} else {
		m_pf_layer[1][0]->mark_all_dirty();
		m_pf_layer[1][0]->set_scrollx(0, m_video_data[0xf000/2]-16 );
		m_pf_layer[1][0]->set_scrolly(0, m_video_data[0xf008/2]-120);
		m_pf_layer[1][0]->draw(screen, bitmap, cliprect, 0,0);
		m_pf_layer[1][0]->draw(screen, bitmap, cliprect, 1,1);
	}

	if (m_video_control_data[6] & 0x04) {
		m_pf_layer[0][1]->mark_all_dirty();
		m_pf_layer[0][1]->set_scrolly(0, m_video_data[0xf00c/2]+392);
		m_pf_layer[0][1]->draw(screen, bitmap, cliprect, 0,0);
		m_pf_layer[0][1]->draw(screen, bitmap, cliprect, 1,1);
	} else {
		m_pf_layer[0][0]->mark_all_dirty();
		m_pf_layer[0][0]->set_scrolly(0, m_video_data[0xf00c/2]-116);
		m_pf_layer[0][0]->draw(screen, bitmap, cliprect, 0,0);
		m_pf_layer[0][0]->draw(screen, bitmap, cliprect, 1,1);
	}

	bomblord_draw_sprites(screen,bitmap,cliprect);

	return 0;
}

uint32_t m90_state::screen_update_dynablsb(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	screen.priority().fill(0, cliprect);
	bitmap.fill(m_palette->black_pen(), cliprect);

	if (!(m_video_data[0xf008/2] & 0x4000)) {
		m_pf_layer[0][1]->mark_all_dirty();
		m_pf_layer[0][1]->set_scroll_rows(1);
		m_pf_layer[0][1]->set_scrollx(0, m_video_data[0xf004/2]+64);
		m_pf_layer[0][1]->set_scrolly(0, m_video_data[0xf006/2]+512);
		m_pf_layer[0][1]->draw(screen, bitmap, cliprect, 0,0);
		m_pf_layer[0][1]->draw(screen, bitmap, cliprect, 1,1);
	} else {
		m_pf_layer[0][0]->mark_all_dirty();
		m_pf_layer[0][0]->set_scroll_rows(1);
		m_pf_layer[0][0]->set_scrollx(0, m_video_data[0xf004/2]+64);
		m_pf_layer[0][0]->set_scrolly(0, m_video_data[0xf006/2]+4);
		m_pf_layer[0][0]->draw(screen, bitmap, cliprect, 0,0);
		m_pf_layer[0][0]->draw(screen, bitmap, cliprect, 1,1);
	}

	if (!(m_video_data[0xf008/2] & 0x8000)) {
		m_pf_layer[1][1]->mark_all_dirty();
		m_pf_layer[1][1]->set_scroll_rows(1);
		m_pf_layer[1][1]->set_scrollx(0, m_video_data[0xf000/2]+68);
		m_pf_layer[1][1]->set_scrolly(0, m_video_data[0xf002/2]+512);
		m_pf_layer[1][1]->draw(screen, bitmap, cliprect, 0,0);
		m_pf_layer[1][1]->draw(screen, bitmap, cliprect, 1,1);
	} else {
		m_pf_layer[1][0]->mark_all_dirty();
		m_pf_layer[1][0]->set_scroll_rows(1);
		m_pf_layer[1][0]->set_scrollx(0, m_video_data[0xf000/2]+68);
		m_pf_layer[1][0]->set_scrolly(0, m_video_data[0xf002/2]+4);
		m_pf_layer[1][0]->draw(screen, bitmap, cliprect, 0,0);
		m_pf_layer[1][0]->draw(screen, bitmap, cliprect, 1,1);
	}

	dynablsb_draw_sprites(screen,bitmap,cliprect);

	return 0;
}