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

                                    


                     





                                           
                                                                               
 
                                                                                                                   
                                                          
                       
                               



                              
                           


                           
                                                  



                                                   




                                                   


                                                    


                                                                                                                                                                              



                                             

                                                                                  
 

                                                                            






























































































                                                                                                              
                                                    




















                                                                                                          
                                          









































                                                                                          
                                     








                                                        
                                     







                                                        
                               

































                                                                                         
                                                                                                                                      



                             
                                                                                                          



































                                                                                                                
                                                                                         



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

#include "emu.h"
#include "tc0180vcu.h"

#define TC0180VCU_RAM_SIZE          0x10000
#define TC0180VCU_SCROLLRAM_SIZE    0x0800


DEFINE_DEVICE_TYPE(TC0180VCU, tc0180vcu_device, "tc0180vcu", "Taito TC0180VCU")

tc0180vcu_device::tc0180vcu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, TC0180VCU, tag, owner, clock),
	m_ram(nullptr),
	//m_scrollram(nullptr),
	//m_bg_rambank(0),
	//m_fg_rambank(0),
	//m_tx_rambank(0),
	m_framebuffer_page(0),
	m_video_control(0),
	m_bg_color_base(0),
	m_fg_color_base(0),
	m_tx_color_base(0),
	m_gfxdecode(*this, finder_base::DUMMY_TAG)
{
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

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

	m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(tc0180vcu_device::get_bg_tile_info),this), TILEMAP_SCAN_ROWS, 16, 16, 64, 64);
	m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(tc0180vcu_device::get_fg_tile_info),this), TILEMAP_SCAN_ROWS, 16, 16, 64, 64);
	m_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(tc0180vcu_device::get_tx_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);

	m_tilemap[1]->set_transparent_pen(0);
	m_tilemap[2]->set_transparent_pen(0);

	m_ram = make_unique_clear<uint16_t[]>(TC0180VCU_RAM_SIZE / 2);
	m_scrollram = make_unique_clear<uint16_t[]>(TC0180VCU_SCROLLRAM_SIZE / 2);

	save_pointer(NAME(m_ram.get()), TC0180VCU_RAM_SIZE / 2);
	save_pointer(NAME(m_scrollram.get()), TC0180VCU_SCROLLRAM_SIZE / 2);

	save_item(NAME(m_bg_rambank));
	save_item(NAME(m_fg_rambank));
	save_item(NAME(m_tx_rambank));

	save_item(NAME(m_framebuffer_page));

	save_item(NAME(m_video_control));
	save_item(NAME(m_ctrl));
}

//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void tc0180vcu_device::device_reset()
{
	int i;

	for (i = 0; i < 0x10; i++)
		m_ctrl[i] = 0;

	m_bg_rambank[0] = 0;
	m_bg_rambank[1] = 0;
	m_fg_rambank[0] = 0;
	m_fg_rambank[1] = 0;
	m_tx_rambank = 0;

	m_framebuffer_page = 0;
	m_video_control = 0;
}


/*****************************************************************************
    DEVICE HANDLERS
*****************************************************************************/

/* TC0180VCU control registers:
* offset:
* 0 - -----xxx bg ram page 0 (tile codes)
*     -xxx---- bg ram page 1 (attributes)
* 1 - -----xxx fg ram page 0 (tile codes)
*     -xxx---- fg ram page 1 (attributes)
* 2 - xxxxxxxx number of independent foreground scrolling blocks (see below)
* 3 - xxxxxxxx number of independent background scrolling blocks
* 4 - --xxxxxx text tile bank 0
* 5 - --xxxxxx text tile bank 1
* 6 - ----xxxx text ram page
* 7 - xxxxxxxx video control: pixelram page and enable, screen flip, sprite to foreground priority (see below)
* 8 to f - unused (always zero)
*
******************************************************************************************
*
* offset 6 - text video page register:
*            This location controls which page of video text ram to view
* hitice:
*     0x08 (00001000) - show game text: credits XX, player1 score
*     0x09 (00001001) - show FBI logo
* rambo3:
*     0x08 (00001000) - show game text
*     0x09 (00001001) - show taito logo
*     0x0a (00001010) - used in pair with 0x09 to smooth screen transitions (attract mode)
*
* Is bit 3 (0x08) video text enable/disable ?
*
******************************************************************************************
*
* offset 7 - video control register:
*            bit 0 (0x01) 1 = don't erase sprite frame buffer "after the beam"
*            bit 3 (0x08) sprite to foreground priority
*                         1 = bg, fg, obj, tx
*                         0 = bg, obj1, fg, obj0, tx (obj0/obj1 selected by bit 0 of color code)
*            bit 4 (0x10) screen flip (active HI) (this one is for sure)
*            bit 5 (0x20) could be global video enable switch (Hit the Ice clears this
*                         bit, clears videoram portions and sets this bit)
*            bit 6 (0x40) frame buffer page to show when bit 7 is set
*            bit 7 (0x80) don't flip frame buffer every vblank, use the page selected by bit 6
*
*/

READ8_MEMBER( tc0180vcu_device::get_fb_page )
{
	return m_framebuffer_page;
}

WRITE8_MEMBER( tc0180vcu_device::set_fb_page )
{
	m_framebuffer_page = data;
}

READ8_MEMBER( tc0180vcu_device::get_videoctrl )
{
	return m_video_control;
}

void tc0180vcu_device::video_control( uint8_t data )
{
#if 0
	if (data != m_video_control)
		popmessage("video control = %02x", data);
#endif

	m_video_control = data;

	if (m_video_control & 0x80)
		m_framebuffer_page = (~m_video_control & 0x40) >> 6;

	machine().tilemap().set_flip_all((m_video_control & 0x10) ? (TILEMAP_FLIPX | TILEMAP_FLIPY) : 0 );
}

READ16_MEMBER( tc0180vcu_device::ctrl_r )
{
	return m_ctrl[offset];
}

WRITE16_MEMBER( tc0180vcu_device::ctrl_w )
{
	uint16_t oldword = m_ctrl[offset];

	COMBINE_DATA (&m_ctrl[offset]);

	if (oldword != m_ctrl[offset])
	{
		if (ACCESSING_BITS_8_15)
		{
			switch(offset)
			{
			case 0:
				m_tilemap[1]->mark_all_dirty();
				m_fg_rambank[0] = (((m_ctrl[offset] >> 8) & 0x0f) << 12);
				m_fg_rambank[1] = (((m_ctrl[offset] >> 12) & 0x0f) << 12);
				break;
			case 1:
				m_tilemap[0]->mark_all_dirty();
				m_bg_rambank[0] = (((m_ctrl[offset] >> 8) & 0x0f) << 12);
				m_bg_rambank[1] = (((m_ctrl[offset] >> 12) & 0x0f) << 12);
				break;
			case 4:
			case 5:
				m_tilemap[2]->mark_all_dirty();
				break;
			case 6:
				m_tilemap[2]->mark_all_dirty();
				m_tx_rambank = (((m_ctrl[offset] >> 8) & 0x0f) << 11);
				break;
			case 7:
				video_control((m_ctrl[offset] >> 8) & 0xff);
				break;
			default:
				break;
			}
		}
	}
}

TILE_GET_INFO_MEMBER(tc0180vcu_device::get_bg_tile_info)
{
	int tile  = m_ram[tile_index + m_bg_rambank[0]];
	int color = m_ram[tile_index + m_bg_rambank[1]];

	SET_TILE_INFO_MEMBER(1, tile,
		m_bg_color_base + (color & 0x3f),
		TILE_FLIPYX((color & 0x00c0) >> 6));
}

TILE_GET_INFO_MEMBER(tc0180vcu_device::get_fg_tile_info)
{
	int tile  = m_ram[tile_index + m_fg_rambank[0]];
	int color = m_ram[tile_index + m_fg_rambank[1]];

	SET_TILE_INFO_MEMBER(1, tile,
		m_fg_color_base + (color & 0x3f),
		TILE_FLIPYX((color & 0x00c0) >> 6));
}

TILE_GET_INFO_MEMBER(tc0180vcu_device::get_tx_tile_info)
{
	int tile = m_ram[tile_index + m_tx_rambank];

	SET_TILE_INFO_MEMBER(0,
		(tile & 0x07ff) | ((m_ctrl[4 + ((tile & 0x800) >> 11)]>>8) << 11),
		m_tx_color_base + ((tile >> 12) & 0x0f),
		0);
}

READ16_MEMBER( tc0180vcu_device::scroll_r )
{
	return m_scrollram[offset];
}

WRITE16_MEMBER( tc0180vcu_device::scroll_w )
{
	COMBINE_DATA(&m_scrollram[offset]);
}

READ16_MEMBER( tc0180vcu_device::word_r )
{
	return m_ram[offset];
}

WRITE16_MEMBER( tc0180vcu_device::word_w )
{
	COMBINE_DATA(&m_ram[offset]);

	if ((offset & 0x7000) == m_fg_rambank[0] || (offset & 0x7000) == m_fg_rambank[1])
		m_tilemap[1]->mark_tile_dirty(offset & 0x0fff);

	if ((offset & 0x7000) == m_bg_rambank[0] || (offset & 0x7000) == m_bg_rambank[1])
		m_tilemap[0]->mark_tile_dirty(offset & 0x0fff);

	if ((offset & 0x7800) == m_tx_rambank)
		m_tilemap[2]->mark_tile_dirty(offset & 0x7ff);
}

void tc0180vcu_device::tilemap_draw( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int tmap_num, int plane )
{
	assert(tmap_num < 3);

	if (tmap_num == 2)
		m_tilemap[2]->draw(screen, bitmap, cliprect, 0, 0);    /* not much to do for tx_tilemap */
	else
	{
		/*plane = 0 fg tilemap*/
		/*plane = 1 bg tilemap*/
		rectangle my_clip;
		int i;
		int scrollx, scrolly;
		int lines_per_block;    /* number of lines scrolled by the same amount (per one scroll value) */
		int number_of_blocks;   /* number of such blocks per _screen_ (256 lines) */

		lines_per_block = 256 - (m_ctrl[2 + plane] >> 8);
		number_of_blocks = 256 / lines_per_block;

		my_clip.min_x = cliprect.min_x;
		my_clip.max_x = cliprect.max_x;

		for (i = 0; i < number_of_blocks; i++)
		{
			scrollx = m_scrollram[plane * 0x200 + i * 2 * lines_per_block];
			scrolly = m_scrollram[plane * 0x200 + i * 2 * lines_per_block + 1];

			my_clip.min_y = i * lines_per_block;
			my_clip.max_y = (i + 1) * lines_per_block - 1;

			if (m_video_control & 0x10)   /*flip screen*/
			{
				my_clip.min_y = bitmap.height() - 1 - (i + 1) * lines_per_block - 1;
				my_clip.max_y = bitmap.height() - 1 - i * lines_per_block;
			}

			my_clip &= cliprect;

			if (my_clip.min_y <= my_clip.max_y)
			{
				m_tilemap[tmap_num]->set_scrollx(0, -scrollx);
				m_tilemap[tmap_num]->set_scrolly(0, -scrolly);
				m_tilemap[tmap_num]->draw(screen, bitmap, my_clip, 0, 0);
			}
		}
	}
}