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

                                







                                                                            
                
                            
                         


               

                                         


               
                     
 





                                       
                                                      

                             
 
                             
                                    
                                                                            
 
                                    
                                                                            
 
                                   

                                      
 
                                                        
                                                                               
 



                                      
























                                                                                               
                                              




                                                                        
                                                      







                                                                                                     



                                       
                                
 


                                                                                                                                                                                                                       
                             
                                                              
 
                            
                                                                                                                                 
                                                              

                                       
                                                   




                                         
         


                                                            

 
                               
 
                                                                                                                                         
                     
                                                                                                                                                                                                                   
 
                                         
                                                              

                             
                                                               
 

                                                    


                                       
         


                                                            


 





                                       
                                            
 
                                        
                         
                                                       
 
                                            

                       
                       
                                                                           


                              
                                                                                  


                              
                                                                           


                              
                                                                                  


                              
                                                                     



         
                                              
 



                                                       




                                            


 





                                       
                                                                                           
 
                                                          

                    
                                                                                
            
                                                                                


 





                                       
                                                                               
 
                                                           
                                 
                                    



                           
                                                      
                                                



                                                  
                                     
                                                    


                                    
                                     
                                                     



                                    
                                                                                              
                                                                                            


                                
                             

                                       
                                                                                                                             
 
                   
 

 





                                       
                                                                                          
 
                                               
                                                           
                                 


                                        
                                                                
                                         
                                        
                         
                                                       

                                       
                                                                                                                               

                                                                           

                           
                                                         
                                                                 
                                                    


                                    
                                                         
                                                    
                                                                 


                                    
                                                              

                                  

                                                                                   
                         
                                               



                                                  
                                             
                                                 

                                  

                                                                                       
                         
                                                   


                                    
                                             
                                                 

                                  

                                                                                        
                         
                                                    



                                    
                                                                                                    
                                                                                            



                                          
                             


 





                                       
                                                       
 
                                                    


 
                                                           
 
                                                           
 


                                         
                                                     


 
                                                
 
                                                                                                                                                   


 
                                               
 
                                                    


 





                                       
                                                      
 
                                                    


 
                                                
 
                                                   


 
                                               
 
                                                    


 





                                       
                                              

                                                                                   
                                                                                                                                                  


 
                                              

                                                                                   
                                                   


 





                                       
                                             

                                                                                   
                                                    


 
                                             

                                                                                   
                                                    


 

                                      
                   


                                       
                                                                                                            
 


                                                     

                                                     
                                                              
         

                                                                   

                                                    
                                                                      
                 
                                                                
                                                  


                                                 
                                                                           
                            
                                                                           
 
                                     


                 



                 

                                      
                   


                                       
                                       
 


























                                                                                                     
 
                                                
                                                                      

                                         
 
                                         
                                                         


                                                          
                                                              
                                      
                  
 
                                              
                             
 
                                                                         

                                             
                  
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    Cinemat/Leland driver

    Leland video hardware

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

#include "emu.h"
#include "includes/leland.h"
#include "audio/leland.h"


/* constants */
static constexpr int VRAM_SIZE = 0x10000;
static constexpr int QRAM_SIZE = 0x10000;


/* debugging */
#define LOG_COMM    0

/*************************************
 *
 *  Scanline callback
 *
 *************************************/

TIMER_CALLBACK_MEMBER(leland_state::scanline_callback)
{
	int scanline = param;

	/* update the DACs */
	if (!(m_dac_control & 0x01))
		m_dac[0]->write(m_video_ram[(m_last_scanline) * 256 + 160]);

	if (!(m_dac_control & 0x02))
		m_dac[1]->write(m_video_ram[(m_last_scanline) * 256 + 161]);

	m_last_scanline = scanline;

	scanline = (scanline+1) % 256;

	/* come back at the next appropriate scanline */
	m_scanline_timer->adjust(m_screen->time_until_pos(scanline), scanline);
}


/*************************************
 *
 *  ROM-based tilemap
 *
 *************************************/

TILEMAP_MAPPER_MEMBER(leland_state::leland_scan)
{
	/* logical (col,row) -> memory offset */
	return (col & 0xff) | ((row & 0x1f) << 8) | ((row & 0xe0) << 9);
}

TILE_GET_INFO_MEMBER(leland_state::leland_get_tile_info)
{
	int char_bank = ((m_gfxbank >> 4) & 0x03) << 10;
	int prom_bank = ((m_gfxbank >> 3) & 0x01) << 13;
	int tile = m_bg_prom[prom_bank | tile_index] | ((tile_index >> 7) & 0x300) | char_bank;
	SET_TILE_INFO_MEMBER(0, tile, m_bg_prom[prom_bank | tile_index] >> 5, 0);
}


/*************************************
 *
 *  RAM-based tilemap
 *
 *************************************/

TILEMAP_MAPPER_MEMBER(ataxx_state::ataxx_scan)
{
	/* logical (col,row) -> memory offset */
	return (col & 0xff) | ((row & 0x3f) << 8) | ((row & 0x40) << 9);
}

TILE_GET_INFO_MEMBER(ataxx_state::ataxx_get_tile_info)
{
	uint16_t tile = m_ataxx_qram[tile_index] | ((m_ataxx_qram[0x4000 | tile_index] & 0x7f) << 8);
	SET_TILE_INFO_MEMBER(0, tile, 0, 0);
}


/*************************************
 *
 *  Start video hardware
 *
 *************************************/

void leland_state::video_start()
{
	/* tilemap */
	m_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(leland_state::leland_get_tile_info),this), tilemap_mapper_delegate(FUNC(leland_state::leland_scan),this), 8, 8, 256, 256);

	/* allocate memory */
	m_video_ram = make_unique_clear<uint8_t[]>(VRAM_SIZE);

	/* scanline timer */
	m_scanline_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(leland_state::scanline_callback),this));
	m_scanline_timer->adjust(m_screen->time_until_pos(0));

	save_item(NAME(m_gfx_control));
	save_pointer(NAME(m_video_ram), VRAM_SIZE);
	save_item(NAME(m_xscroll));
	save_item(NAME(m_yscroll));
	save_item(NAME(m_gfxbank));
	save_item(NAME(m_last_scanline));
	for (uint8_t i = 0; i < 2; i++)
	{
		save_item(NAME(m_vram_state[i].m_addr), i);
		save_item(NAME(m_vram_state[i].m_latch), i);
	}
}

void ataxx_state::video_start()
{
	// TODO: further untangle driver so the base class doesn't have stuff that isn't common and this can call the base implementation
	/* tilemap */
	m_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(ataxx_state::ataxx_get_tile_info),this), tilemap_mapper_delegate(FUNC(ataxx_state::ataxx_scan),this), 8, 8, 256, 128);

	/* first do the standard stuff */
	m_video_ram = make_unique_clear<uint8_t[]>(VRAM_SIZE);

	/* allocate memory */
	m_ataxx_qram = make_unique_clear<uint8_t[]>(QRAM_SIZE);

	save_pointer(NAME(m_video_ram), VRAM_SIZE);
	save_pointer(NAME(m_ataxx_qram), QRAM_SIZE);
	save_item(NAME(m_xscroll));
	save_item(NAME(m_yscroll));
	for (uint8_t i = 0; i < 2; i++)
	{
		save_item(NAME(m_vram_state[i].m_addr), i);
		save_item(NAME(m_vram_state[i].m_latch), i);
	}
}


/*************************************
 *
 *  Scrolling and banking
 *
 *************************************/

WRITE8_MEMBER(leland_state::leland_scroll_w)
{
	int scanline = m_screen->vpos();
	if (scanline > 0)
		m_screen->update_partial(scanline - 1);

	/* adjust the proper scroll value */
	switch (offset)
	{
		case 0:
			m_xscroll = (m_xscroll & 0xff00) | (data & 0x00ff);
			break;

		case 1:
			m_xscroll = (m_xscroll & 0x00ff) | ((data << 8) & 0xff00);
			break;

		case 2:
			m_yscroll = (m_yscroll & 0xff00) | (data & 0x00ff);
			break;

		case 3:
			m_yscroll = (m_yscroll & 0x00ff) | ((data << 8) & 0xff00);
			break;

		default:
			fatalerror("Unexpected leland_gfx_port_w\n");
	}
}


WRITE8_MEMBER(leland_state::leland_gfx_port_w)
{
	int scanline = m_screen->vpos();
	if (scanline > 0)
		m_screen->update_partial(scanline - 1);

	if (m_gfxbank != data)
	{
		m_gfxbank = data;
		m_tilemap->mark_all_dirty();
	}
}


/*************************************
 *
 *  Video address setting
 *
 *************************************/

void leland_state::leland_video_addr_w(address_space &space, int offset, int data, int num)
{
	struct vram_state_data &state = m_vram_state[num];

	if (!offset)
		state.m_addr = (state.m_addr & 0xfe00) | ((data << 1) & 0x01fe);
	else
		state.m_addr = ((data << 9) & 0xfe00) | (state.m_addr & 0x01fe);
}


/*************************************
 *
 *  Common video RAM read
 *
 *************************************/

int leland_state::leland_vram_port_r(address_space &space, int offset, int num)
{
	struct vram_state_data *state = m_vram_state + num;
	int addr = state->m_addr;
	int inc = (offset >> 2) & 2;
	int ret;

	switch (offset & 7)
	{
		case 3: /* read hi/lo (alternating) */
			ret = m_video_ram[addr];
			addr += inc & (addr << 1);
			addr ^= 1;
			break;

		case 5: /* read hi */
			ret = m_video_ram[addr | 1];
			addr += inc;
			break;

		case 6: /* read lo */
			ret = m_video_ram[addr & ~1];
			addr += inc;
			break;

		default:
			logerror("%s: Warning: Unknown video port %02x read (address=%04x)\n",
						machine().describe_context(), offset, addr);
			ret = 0;
			break;
	}
	state->m_addr = addr;

	if (LOG_COMM && addr >= 0xf000)
		logerror("%s:%s comm read %04X = %02X\n", machine().describe_context(), num ? "slave" : "master", addr, ret);

	return ret;
}


/*************************************
 *
 *  Common video RAM write
 *
 *************************************/

void leland_state::leland_vram_port_w(address_space &space, int offset, int data, int num)
{
	uint8_t *video_ram = m_video_ram.get();
	struct vram_state_data *state = m_vram_state + num;
	int addr = state->m_addr;
	int inc = (offset >> 2) & 2;
	int trans = (offset >> 4) & num;

	/* don't fully understand why this is needed.  Isn't the
	   video RAM just one big RAM? */
	int scanline = m_screen->vpos();
	if (scanline > 0)
		m_screen->update_partial(scanline - 1);

	if (LOG_COMM && addr >= 0xf000)
		logerror("%s:%s comm write %04X = %02X\n", machine().describe_context(), num ? "slave" : "master", addr, data);

	/* based on the low 3 bits of the offset, update the destination */
	switch (offset & 7)
	{
		case 1: /* write hi = data, lo = latch */
			video_ram[addr & ~1] = state->m_latch[0];
			video_ram[addr |  1] = data;
			addr += inc;
			break;

		case 2: /* write hi = latch, lo = data */
			video_ram[addr & ~1] = data;
			video_ram[addr |  1] = state->m_latch[1];
			addr += inc;
			break;

		case 3: /* write hi/lo = data (alternating) */
			if (trans)
			{
				if (!(data & 0xf0)) data |= video_ram[addr] & 0xf0;
				if (!(data & 0x0f)) data |= video_ram[addr] & 0x0f;
			}
			video_ram[addr] = data;
			addr += inc & (addr << 1);
			addr ^= 1;
			break;

		case 5: /* write hi = data */
			state->m_latch[1] = data;
			if (trans)
			{
				if (!(data & 0xf0)) data |= video_ram[addr | 1] & 0xf0;
				if (!(data & 0x0f)) data |= video_ram[addr | 1] & 0x0f;
			}
			video_ram[addr | 1] = data;
			addr += inc;
			break;

		case 6: /* write lo = data */
			state->m_latch[0] = data;
			if (trans)
			{
				if (!(data & 0xf0)) data |= video_ram[addr & ~1] & 0xf0;
				if (!(data & 0x0f)) data |= video_ram[addr & ~1] & 0x0f;
			}
			video_ram[addr & ~1] = data;
			addr += inc;
			break;

		default:
			logerror("%s:Warning: Unknown video port write (address=%04x value=%02x)\n",
						machine().describe_context(), offset, addr);
			break;
	}

	/* update the address and plane */
	state->m_addr = addr;
}


/*************************************
 *
 *  Master video RAM read/write
 *
 *************************************/

WRITE8_MEMBER(leland_state::leland_master_video_addr_w)
{
	leland_video_addr_w(space, offset, data, 0);
}


TIMER_CALLBACK_MEMBER(leland_state::leland_delayed_mvram_w)
{
	address_space &space = m_master->space(AS_PROGRAM);

	int num = (param >> 16) & 1;
	int offset = (param >> 8) & 0xff;
	int data = param & 0xff;
	leland_vram_port_w(space, offset, data, num);
}


WRITE8_MEMBER(leland_state::leland_mvram_port_w)
{
	machine().scheduler().synchronize(timer_expired_delegate(FUNC(leland_state::leland_delayed_mvram_w),this), 0x00000 | (offset << 8) | data);
}


READ8_MEMBER(leland_state::leland_mvram_port_r)
{
	return leland_vram_port_r(space, offset, 0);
}


/*************************************
 *
 *  Slave video RAM read/write
 *
 *************************************/

WRITE8_MEMBER(leland_state::leland_slave_video_addr_w)
{
	leland_video_addr_w(space, offset, data, 1);
}


WRITE8_MEMBER(leland_state::leland_svram_port_w)
{
	leland_vram_port_w(space, offset, data, 1);
}


READ8_MEMBER(leland_state::leland_svram_port_r)
{
	return leland_vram_port_r(space, offset, 1);
}


/*************************************
 *
 *  Ataxx master video RAM read/write
 *
 *************************************/

WRITE8_MEMBER(ataxx_state::ataxx_mvram_port_w)
{
	offset = ((offset >> 1) & 0x07) | ((offset << 3) & 0x08) | (offset & 0x10);
	machine().scheduler().synchronize(timer_expired_delegate(FUNC(ataxx_state::leland_delayed_mvram_w),this), 0x00000 | (offset << 8) | data);
}


WRITE8_MEMBER(ataxx_state::ataxx_svram_port_w)
{
	offset = ((offset >> 1) & 0x07) | ((offset << 3) & 0x08) | (offset & 0x10);
	leland_vram_port_w(space, offset, data, 1);
}


/*************************************
 *
 *  Ataxx slave video RAM read/write
 *
 *************************************/

READ8_MEMBER(ataxx_state::ataxx_mvram_port_r)
{
	offset = ((offset >> 1) & 0x07) | ((offset << 3) & 0x08) | (offset & 0x10);
	return leland_vram_port_r(space, offset, 0);
}


READ8_MEMBER(ataxx_state::ataxx_svram_port_r)
{
	offset = ((offset >> 1) & 0x07) | ((offset << 3) & 0x08) | (offset & 0x10);
	return leland_vram_port_r(space, offset, 1);
}


/*************************************
 *
 *  Refresh routine
 *
 *************************************/

uint32_t leland_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	m_tilemap->set_scrollx(0, m_xscroll);
	m_tilemap->set_scrolly(0, m_yscroll);
	m_tilemap->draw(screen, bitmap, cliprect, 0);

	/* for each scanline in the visible region */
	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
	{
		uint16_t *const dst = &bitmap.pix16(y);
		uint8_t const *const fg_src = &m_video_ram[y << 8];

		/* for each pixel on the scanline */
		for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
		{
			/* build the pen, background is d0-d5 */
			pen_t pen = dst[x] & 0x3f;

			/* foreground is d6-d9 */
			if (x & 0x01)
				pen = pen | ((fg_src[x >> 1] & 0x0f) << 6);
			else
				pen = pen | ((fg_src[x >> 1] & 0xf0) << 2);

			dst[x] = pen;
		}
	}

	return 0;
}


/*************************************
 *
 *  Machine drivers
 *
 *************************************/

static const gfx_layout leland_layout =
{
	8,8,
	RGN_FRAC(1,3),
	3,
	{ RGN_FRAC(0,3), RGN_FRAC(1,3), RGN_FRAC(2,3) },
	{ STEP8(0,1) },
	{ STEP8(0,8) },
	8*8
};

static const gfx_layout ataxx_layout =
{
	8,8,
	RGN_FRAC(1,6),
	6,
	{ RGN_FRAC(5,6), RGN_FRAC(4,6), RGN_FRAC(3,6), RGN_FRAC(2,6), RGN_FRAC(1,6), RGN_FRAC(0,6) },
	{ STEP8(0,1) },
	{ STEP8(0,8) },
	8*8
};

static GFXDECODE_START( gfx_leland )
	GFXDECODE_ENTRY( "bg_gfx", 0, leland_layout, 0, 8*16) // *16 is foreground
GFXDECODE_END

static GFXDECODE_START( gfx_ataxx )
	GFXDECODE_ENTRY( "bg_gfx", 0, ataxx_layout, 0, 16) // 16 is foreground
GFXDECODE_END

MACHINE_CONFIG_START(leland_state::leland_video)
	MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_leland)
	MCFG_PALETTE_ADD("palette", 1024)
	MCFG_PALETTE_FORMAT(BBGGGRRR)

	MCFG_SCREEN_ADD("screen", RASTER)
	MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_ALWAYS_UPDATE)
	MCFG_SCREEN_SIZE(40*8, 32*8)
	MCFG_SCREEN_VISIBLE_AREA(0*8, 40*8-1, 0*8, 30*8-1)
	MCFG_SCREEN_REFRESH_RATE(60)
	MCFG_SCREEN_UPDATE_DRIVER(leland_state, screen_update)
	MCFG_SCREEN_PALETTE("palette")
MACHINE_CONFIG_END

MACHINE_CONFIG_START(ataxx_state::ataxx_video)
	leland_video(config);

	MCFG_DEVICE_REPLACE("gfxdecode", GFXDECODE, "palette", gfx_ataxx)
	MCFG_PALETTE_MODIFY("palette")
	MCFG_PALETTE_FORMAT(xxxxRRRRGGGGBBBB)
MACHINE_CONFIG_END