summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/atarist.cpp
blob: 11285b4872eefa5cd8d5805e786d34f059247804 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

                                                 











                     































                                                                            
















                                                                                                                                                   
                                     






















                                                                               
                                     



































                                                   
                                     








                                                   

                                 

















                                     
                                             







                                                   




                                                   
                                                              
                                                         




















                                                   





                                                         

                          

                                 



























                                                                            
                                                                 




                                               
                                                                 








                                                        

                                        
                                     

                                        
                                     

                                        
                                     

                                        



                                     
                                      
                                     
                                        
                                     
                                        
                                     
                                        
                                     
                                        
                                     
                                        
                                     
                                        
                                     
                                        






                                     
                                             





                                                   































                                                                
                         










































                                                                                   
                         

















































































                                                                 
                                                                                                


































                                                                            
                         


























































                                                                                 
                                                  























































                                                                            
                                                              
                                                         















                                                                           
                                
 

                                                                      

























                                                             
                                                                      
 
                                                              
 

                                                





                                                    
                                            






























































                                                                                                          
                       



                                                   
































































































































































































































































































































                                                                             
                                               

                                                                                                                
                                                                                                  














                                                                            

                            

                                                          
 

                                                                                                 
 
                                                   




































                                             








                                            




                                
                                                                                                        



                                                           
// license:BSD-3-Clause
// copyright-holders:Curt Coder, Olivier Galibert
/*

    TODO:

    - rewrite shifter
    - STe pixelofs
    - blitter hog
    - high resolution

*/

#include "emu.h"
#include "video/atarist.h"
#include "includes/atarist.h"



//**************************************************************************
//  CONSTANTS / MACROS
//**************************************************************************

#define LOG 0

static const int BLITTER_NOPS[16][4] =
{
	{ 1, 1, 1, 1 },
	{ 2, 2, 3, 3 },
	{ 2, 2, 3, 3 },
	{ 1, 1, 2, 2 },
	{ 2, 2, 3, 3 },
	{ 2, 2, 2, 2 },
	{ 2, 2, 3, 3 },
	{ 2, 2, 3, 3 },
	{ 2, 2, 3, 3 },
	{ 2, 2, 3, 3 },
	{ 2, 2, 2, 2 },
	{ 2, 2, 3, 3 },
	{ 1, 1, 2, 2 },
	{ 2, 2, 3, 3 },
	{ 2, 2, 3, 3 },
	{ 1, 1, 1, 1 }
};


//**************************************************************************
//  SHIFTER
//**************************************************************************

//-------------------------------------------------
//  shift_mode_0 -
//-------------------------------------------------

inline pen_t st_state::shift_mode_0()
{
	int color = (BIT(m_shifter_rr[3], 15) << 3) | (BIT(m_shifter_rr[2], 15) << 2) | (BIT(m_shifter_rr[1], 15) << 1) | BIT(m_shifter_rr[0], 15);

	m_shifter_rr[0] <<= 1;
	m_shifter_rr[1] <<= 1;
	m_shifter_rr[2] <<= 1;
	m_shifter_rr[3] <<= 1;

	return m_palette->pen(color);
}


//-------------------------------------------------
//  shift_mode_1 -
//-------------------------------------------------

inline pen_t st_state::shift_mode_1()
{
	int color = (BIT(m_shifter_rr[1], 15) << 1) | BIT(m_shifter_rr[0], 15);

	m_shifter_rr[0] <<= 1;
	m_shifter_rr[1] <<= 1;
	m_shifter_shift++;

	if (m_shifter_shift == 16)
	{
		m_shifter_rr[0] = m_shifter_rr[2];
		m_shifter_rr[1] = m_shifter_rr[3];
		m_shifter_rr[2] = m_shifter_rr[3] = 0;
		m_shifter_shift = 0;
	}

	return m_palette->pen(color);
}


//-------------------------------------------------
//  shift_mode_2 -
//-------------------------------------------------

inline pen_t st_state::shift_mode_2()
{
	int color = BIT(m_shifter_rr[0], 15);

	m_shifter_rr[0] <<= 1;
	m_shifter_shift++;

	switch (m_shifter_shift)
	{
	case 16:
		m_shifter_rr[0] = m_shifter_rr[1];
		m_shifter_rr[1] = m_shifter_rr[2];
		m_shifter_rr[2] = m_shifter_rr[3];
		m_shifter_rr[3] = 0;
		break;

	case 32:
		m_shifter_rr[0] = m_shifter_rr[1];
		m_shifter_rr[1] = m_shifter_rr[2];
		m_shifter_rr[2] = 0;
		break;

	case 48:
		m_shifter_rr[0] = m_shifter_rr[1];
		m_shifter_rr[1] = 0;
		m_shifter_shift = 0;
		break;
	}

	return m_palette->pen(color);
}


//-------------------------------------------------
//  shifter_tick -
//-------------------------------------------------

void st_state::shifter_tick()
{
	int y = m_screen->vpos();
	int x = m_screen->hpos();

	pen_t pen;

	switch (m_shifter_mode)
	{
	case 0:
		pen = shift_mode_0();
		break;

	case 1:
		pen = shift_mode_1();
		break;

	case 2:
		pen = shift_mode_2();
		break;

	default:
		pen = m_palette->black_pen();
		break;
	}

	m_bitmap.pix32(y, x) = pen;
}


//-------------------------------------------------
//  shifter_load -
//-------------------------------------------------

inline void st_state::shifter_load()
{
	address_space &program = m_maincpu->space(AS_PROGRAM);
	uint16_t data = program.read_word(m_shifter_ofs);

	m_shifter_ir[m_shifter_bitplane] = data;
	m_shifter_bitplane++;
	m_shifter_ofs += 2;

	if (m_shifter_bitplane == 4)
	{
		m_shifter_bitplane = 0;

		m_shifter_rr[0] = m_shifter_ir[0];
		m_shifter_rr[1] = m_shifter_ir[1];
		m_shifter_rr[2] = m_shifter_ir[2];
		m_shifter_rr[3] = m_shifter_ir[3];
	}
}


//-------------------------------------------------
//  glue_tick -
//-------------------------------------------------

void st_state::draw_pixel(int x, int y, u32 pen)
{
	if(x < m_bitmap.width() && y < m_bitmap.height())
		m_bitmap.pix32(y, x) = pen;
}

void st_state::glue_tick()
{
	int y = m_screen->vpos();
	int x = m_screen->hpos();

	int v = (y >= m_shifter_y_start) && (y < m_shifter_y_end);
	int h = (x >= m_shifter_x_start) && (x < m_shifter_x_end);

	if(m_shifter_mode == 1) {
		int dt = 8;
		h = (x >= m_shifter_x_start-dt) && (x < m_shifter_x_end-dt);
	}
	int de = h && v;

	if(!x) {
		m_shifter_bitplane = 0;
		m_shifter_shift = 0;
	}

	if (de != m_shifter_de)
	{
		m_mfp->tbi_w(de);
		m_shifter_de = de;
	}

	if (de)
	{
		shifter_load();
	}

	if ((y == m_shifter_vblank_start) && (x == 0))
	{
		m_maincpu->set_input_line(M68K_IRQ_4, HOLD_LINE);
		m_shifter_ofs = m_shifter_base;
	}

	if (x == m_shifter_hblank_start)
	{
		m_maincpu->set_input_line(M68K_IRQ_2, HOLD_LINE);
//      m_shifter_ofs += (m_shifter_lineofs * 2); // STe
	}

	pen_t pen;

	switch (m_shifter_mode)
	{
	case 0:
		pen = shift_mode_0();
		draw_pixel(x, y, pen);
		draw_pixel(x+1, y, pen);
		pen = shift_mode_0();
		draw_pixel(x+2, y, pen);
		draw_pixel(x+3, y, pen);
		pen = shift_mode_0();
		draw_pixel(x+4, y, pen);
		draw_pixel(x+5, y, pen);
		pen = shift_mode_0();
		draw_pixel(x+6, y, pen);
		draw_pixel(x+7, y, pen);
		break;

	case 1:
		pen = shift_mode_1();
		draw_pixel(x, y, pen);
		pen = shift_mode_1();
		draw_pixel(x+1, y, pen);
		pen = shift_mode_1();
		draw_pixel(x+2, y, pen);
		pen = shift_mode_1();
		draw_pixel(x+3, y, pen);
		pen = shift_mode_1();
		draw_pixel(x+4, y, pen);
		pen = shift_mode_1();
		draw_pixel(x+5, y, pen);
		pen = shift_mode_1();
		draw_pixel(x+6, y, pen);
		pen = shift_mode_1();
		draw_pixel(x+7, y, pen);
		break;

	case 2:
		pen = shift_mode_2();
		break;

	default:
		pen = m_palette->black_pen();
		break;
	}
}


//-------------------------------------------------
//  set_screen_parameters -
//-------------------------------------------------

void st_state::set_screen_parameters()
{
	if (m_shifter_sync & 0x02)
	{
		m_shifter_x_start = ATARIST_HBDEND_PAL*2;
		m_shifter_x_end = ATARIST_HBDSTART_PAL*2;
		m_shifter_y_start = ATARIST_VBDEND_PAL;
		m_shifter_y_end = ATARIST_VBDSTART_PAL;
		m_shifter_hblank_start = ATARIST_HBSTART_PAL*2;
		m_shifter_vblank_start = ATARIST_VBSTART_PAL;
	}
	else
	{
		m_shifter_x_start = ATARIST_HBDEND_NTSC*2;
		m_shifter_x_end = ATARIST_HBDSTART_NTSC*2;
		m_shifter_y_start = ATARIST_VBDEND_NTSC;
		m_shifter_y_end = ATARIST_VBDSTART_NTSC;
		m_shifter_hblank_start = ATARIST_HBSTART_NTSC*2;
		m_shifter_vblank_start = ATARIST_VBSTART_NTSC;
	}
}


//-------------------------------------------------
//  shifter_base_r -
//-------------------------------------------------

READ8_MEMBER( st_state::shifter_base_r )
{
	uint8_t data = 0;

	switch (offset)
	{
	case 0x00:
		data = (m_shifter_base >> 16) & 0x3f;
		break;

	case 0x01:
		data = (m_shifter_base >> 8) & 0xff;
		break;
	}

	return data;
}


//-------------------------------------------------
//  shifter_base_w -
//-------------------------------------------------

WRITE8_MEMBER( st_state::shifter_base_w )
{
	switch (offset)
	{
	case 0x00:
		m_shifter_base = (m_shifter_base & 0x00ff00) | (data & 0x3f) << 16;
		logerror("SHIFTER Video Base Address %06x\n", m_shifter_base);
		break;

	case 0x01:
		m_shifter_base = (m_shifter_base & 0x3f0000) | (data << 8);
		logerror("SHIFTER Video Base Address %06x\n", m_shifter_base);
		break;
	}
}


//-------------------------------------------------
//  shifter_counter_r -
//-------------------------------------------------

READ8_MEMBER( st_state::shifter_counter_r )
{
	uint8_t data = 0;

	switch (offset)
	{
	case 0x00:
		data = (m_shifter_ofs >> 16) & 0x3f;
		break;

	case 0x01:
		data = (m_shifter_ofs >> 8) & 0xff;
		break;

	case 0x02:
		data = m_shifter_ofs & 0xff;
		break;
	}

	return data;
}


//-------------------------------------------------
//  shifter_sync_r -
//-------------------------------------------------

READ8_MEMBER( st_state::shifter_sync_r )
{
	return m_shifter_sync;
}


//-------------------------------------------------
//  shifter_sync_w -
//-------------------------------------------------

WRITE8_MEMBER( st_state::shifter_sync_w )
{
	m_shifter_sync = data;
	logerror("SHIFTER Sync %x\n", m_shifter_sync);
	set_screen_parameters();
}


//-------------------------------------------------
//  shifter_mode_r -
//-------------------------------------------------

READ8_MEMBER( st_state::shifter_mode_r )
{
	return m_shifter_mode;
}


//-------------------------------------------------
//  shifter_mode_w -
//-------------------------------------------------

WRITE8_MEMBER( st_state::shifter_mode_w )
{
	m_shifter_mode = data;
	logerror("SHIFTER Mode %x\n", m_shifter_mode);
}


//-------------------------------------------------
//  shifter_palette_r -
//-------------------------------------------------

READ16_MEMBER( st_state::shifter_palette_r )
{
	return m_shifter_palette[offset] | 0xf888;
}


//-------------------------------------------------
//  shifter_palette_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::shifter_palette_w )
{
	m_shifter_palette[offset] = data;
	//  logerror("SHIFTER Palette[%x] = %x\n", offset, data);

	m_palette->set_pen_color(offset, pal3bit(data >> 8), pal3bit(data >> 4), pal3bit(data));
}



//**************************************************************************
//  STE SHIFTER
//**************************************************************************

//-------------------------------------------------
//  shifter_base_low_r -
//-------------------------------------------------

READ8_MEMBER( ste_state::shifter_base_low_r )
{
	return m_shifter_base & 0xfe;
}


//-------------------------------------------------
//  shifter_base_low_w -
//-------------------------------------------------

WRITE8_MEMBER( ste_state::shifter_base_low_w )
{
	m_shifter_base = (m_shifter_base & 0x3fff00) | (data & 0xfe);
	logerror("SHIFTER Video Base Address %06x\n", m_shifter_base);
}


//-------------------------------------------------
//  shifter_counter_r -
//-------------------------------------------------

READ8_MEMBER( ste_state::shifter_counter_r )
{
	uint8_t data = 0;

	switch (offset)
	{
	case 0x00:
		data = (m_shifter_ofs >> 16) & 0x3f;
		break;

	case 0x01:
		data = (m_shifter_ofs >> 8) & 0xff;
		break;

	case 0x02:
		data = m_shifter_ofs & 0xfe;
		break;
	}

	return data;
}


//-------------------------------------------------
//  shifter_counter_w -
//-------------------------------------------------

WRITE8_MEMBER( ste_state::shifter_counter_w )
{
	switch (offset)
	{
	case 0x00:
		m_shifter_ofs = (m_shifter_ofs & 0x00fffe) | (data & 0x3f) << 16;
		logerror("SHIFTER Video Address Counter %06x\n", m_shifter_ofs);
		break;

	case 0x01:
		m_shifter_ofs = (m_shifter_ofs & 0x3f00fe) | (data << 8);
		logerror("SHIFTER Video Address Counter %06x\n", m_shifter_ofs);
		break;

	case 0x02:
		m_shifter_ofs = (m_shifter_ofs & 0x3fff00) | (data & 0xfe);
		logerror("SHIFTER Video Address Counter %06x\n", m_shifter_ofs);
		break;
	}
}


//-------------------------------------------------
//  shifter_palette_w -
//-------------------------------------------------

WRITE16_MEMBER( ste_state::shifter_palette_w )
{
	int r = ((data >> 7) & 0x0e) | BIT(data, 11);
	int g = ((data >> 3) & 0x0e) | BIT(data, 7);
	int b = ((data << 1) & 0x0e) | BIT(data, 3);

	m_shifter_palette[offset] = data;
	logerror("SHIFTER palette %x = %x\n", offset, data);

	m_palette->set_pen_color(offset, r, g, b);
}


//-------------------------------------------------
//  shifter_lineofs_r -
//-------------------------------------------------

READ8_MEMBER( ste_state::shifter_lineofs_r )
{
	return m_shifter_lineofs;
}


//-------------------------------------------------
//  shifter_lineofs_w -
//-------------------------------------------------

WRITE8_MEMBER( ste_state::shifter_lineofs_w )
{
	m_shifter_lineofs = data;
	logerror("SHIFTER Line Offset %x\n", m_shifter_lineofs);
}


//-------------------------------------------------
//  shifter_pixelofs_r -
//-------------------------------------------------

READ8_MEMBER( ste_state::shifter_pixelofs_r )
{
	return m_shifter_pixelofs;
}


//-------------------------------------------------
//  shifter_pixelofs_w -
//-------------------------------------------------

WRITE8_MEMBER( ste_state::shifter_pixelofs_w )
{
	m_shifter_pixelofs = data & 0x0f;
	logerror("SHIFTER Pixel Offset %x\n", m_shifter_pixelofs);
}



//**************************************************************************
//  BLITTER
//**************************************************************************

//-------------------------------------------------
//  blitter_source -
//-------------------------------------------------

void st_state::blitter_source()
{
	address_space &program = m_maincpu->space(AS_PROGRAM);
	uint16_t data = program.read_word(m_blitter_src);

	if (m_blitter_src_inc_x < 0)
	{
		m_blitter_srcbuf = (data << 16) | (m_blitter_srcbuf >> 16);
	}
	else
	{
		m_blitter_srcbuf = (m_blitter_srcbuf << 16) | data;
	}
}


//-------------------------------------------------
//  blitter_hop -
//-------------------------------------------------

uint16_t st_state::blitter_hop()
{
	uint16_t source = m_blitter_srcbuf >> (m_blitter_skew & 0x0f);
	uint16_t halftone = m_blitter_halftone[m_blitter_ctrl & 0x0f];

	if (m_blitter_ctrl & ATARIST_BLITTER_CTRL_SMUDGE)
	{
		halftone = m_blitter_halftone[source & 0x0f];
	}

	switch (m_blitter_hop)
	{
	case 0:
		return 0xffff;
	case 1:
		return halftone;
	case 2:
		return source;
	case 3:
		return source & halftone;
	}

	return 0;
}


//-------------------------------------------------
//  blitter_op -
//-------------------------------------------------

void st_state::blitter_op(uint16_t s, uint32_t dstaddr, uint16_t mask)
{
	address_space &program = m_maincpu->space(AS_PROGRAM);

	uint16_t d = program.read_word(dstaddr);
	uint16_t result = 0;

	if (m_blitter_op & 0x08) result = (~s & ~d);
	if (m_blitter_op & 0x04) result |= (~s & d);
	if (m_blitter_op & 0x02) result |= (s & ~d);
	if (m_blitter_op & 0x01) result |= (s & d);

	program.write_word(dstaddr, result);
}


//-------------------------------------------------
//  blitter_tick -
//-------------------------------------------------

void st_state::blitter_tick()
{
	do
	{
		if (m_blitter_skew & ATARIST_BLITTER_SKEW_FXSR)
		{
			blitter_source();
			m_blitter_src += m_blitter_src_inc_x;
		}

		blitter_source();
		blitter_op(blitter_hop(), m_blitter_dst, m_blitter_endmask1);
		m_blitter_xcount--;

		while (m_blitter_xcount > 0)
		{
			m_blitter_src += m_blitter_src_inc_x;
			m_blitter_dst += m_blitter_dst_inc_x;

			if (m_blitter_xcount == 1)
			{
				if (!(m_blitter_skew & ATARIST_BLITTER_SKEW_NFSR))
				{
					blitter_source();
				}

				blitter_op(blitter_hop(), m_blitter_dst, m_blitter_endmask3);
			}
			else
			{
				blitter_source();
				blitter_op(blitter_hop(), m_blitter_dst, m_blitter_endmask2);
			}

			m_blitter_xcount--;
		}

		m_blitter_src += m_blitter_src_inc_y;
		m_blitter_dst += m_blitter_dst_inc_y;

		if (m_blitter_dst_inc_y < 0)
		{
			m_blitter_ctrl = (m_blitter_ctrl & 0xf0) | (((m_blitter_ctrl & 0x0f) - 1) & 0x0f);
		}
		else
		{
			m_blitter_ctrl = (m_blitter_ctrl & 0xf0) | (((m_blitter_ctrl & 0x0f) + 1) & 0x0f);
		}

		m_blitter_xcount = m_blitter_xcountl;
		m_blitter_ycount--;
	}
	while (m_blitter_ycount > 0);

	m_blitter_ctrl &= 0x7f;

	m_mfp->i3_w(0);
}


//-------------------------------------------------
//  blitter_halftone_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_halftone_r )
{
	return m_blitter_halftone[offset];
}


//-------------------------------------------------
//  blitter_src_inc_x_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_src_inc_x_r )
{
	return m_blitter_src_inc_x;
}


//-------------------------------------------------
//  blitter_src_inc_y_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_src_inc_y_r )
{
	return m_blitter_src_inc_y;
}


//-------------------------------------------------
//  blitter_src_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_src_r )
{
	switch (offset)
	{
	case 0:
		return (m_blitter_src >> 16) & 0xff;
	case 1:
		return m_blitter_src & 0xfffe;
	}

	return 0;
}


//-------------------------------------------------
//  blitter_end_mask_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_end_mask_r )
{
	switch (offset)
	{
	case 0:
		return m_blitter_endmask1;
	case 1:
		return m_blitter_endmask2;
	case 2:
		return m_blitter_endmask3;
	}

	return 0;
}


//-------------------------------------------------
//  blitter_dst_inc_x_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_dst_inc_x_r )
{
	return m_blitter_dst_inc_x;
}


//-------------------------------------------------
//  blitter_dst_inc_y_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_dst_inc_y_r )
{
	return m_blitter_dst_inc_y;
}


//-------------------------------------------------
//  blitter_dst_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_dst_r )
{
	switch (offset)
	{
	case 0:
		return (m_blitter_dst >> 16) & 0xff;
	case 1:
		return m_blitter_dst & 0xfffe;
	}

	return 0;
}


//-------------------------------------------------
//  blitter_count_x_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_count_x_r )
{
	return m_blitter_xcount;
}


//-------------------------------------------------
//  blitter_count_y_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_count_y_r )
{
	return m_blitter_ycount;
}


//-------------------------------------------------
//  blitter_op_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_op_r )
{
	if (ACCESSING_BITS_0_7)
	{
		return m_blitter_hop;
	}
	else
	{
		return m_blitter_op;
	}
}


//-------------------------------------------------
//  blitter_ctrl_r -
//-------------------------------------------------

READ16_MEMBER( st_state::blitter_ctrl_r )
{
	if (ACCESSING_BITS_0_7)
	{
		return m_blitter_ctrl;
	}
	else
	{
		return m_blitter_skew;
	}
}


//-------------------------------------------------
//  blitter_halftone_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_halftone_w )
{
	m_blitter_halftone[offset] = data;
}


//-------------------------------------------------
//  blitter_src_inc_x_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_src_inc_x_w )
{
	m_blitter_src_inc_x = data & 0xfffe;
}


//-------------------------------------------------
//  blitter_src_inc_y_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_src_inc_y_w )
{
	m_blitter_src_inc_y = data & 0xfffe;
}


//-------------------------------------------------
//  blitter_src_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_src_w )
{
	switch (offset)
	{
	case 0:
		m_blitter_src = (data & 0xff) | (m_blitter_src & 0xfffe);
		break;

	case 1:
		m_blitter_src = (m_blitter_src & 0xff0000) | (data & 0xfffe);
		break;
	}
}


//-------------------------------------------------
//  blitter_end_mask_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_end_mask_w )
{
	switch (offset)
	{
	case 0:
		m_blitter_endmask1 = data;
		break;

	case 1:
		m_blitter_endmask2 = data;
		break;

	case 2:
		m_blitter_endmask3 = data;
		break;
	}
}


//-------------------------------------------------
//  blitter_dst_inc_x_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_dst_inc_x_w )
{
	m_blitter_dst_inc_x = data & 0xfffe;
}


//-------------------------------------------------
//  blitter_dst_inc_y_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_dst_inc_y_w )
{
	m_blitter_dst_inc_y = data & 0xfffe;
}


//-------------------------------------------------
//  blitter_dst_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_dst_w )
{
	switch (offset)
	{
	case 0:
		m_blitter_dst = (data & 0xff) | (m_blitter_dst & 0xfffe);
		break;

	case 1:
		m_blitter_dst = (m_blitter_dst & 0xff0000) | (data & 0xfffe);
		break;
	}
}


//-------------------------------------------------
//  blitter_count_x_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_count_x_w )
{
	m_blitter_xcount = data;
}


//-------------------------------------------------
//  blitter_count_y_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_count_y_w )
{
	m_blitter_ycount = data;
}


//-------------------------------------------------
//  blitter_op_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_op_w )
{
	if (ACCESSING_BITS_0_7)
	{
		m_blitter_hop = (data >> 8) & 0x03;
	}
	else
	{
		m_blitter_op = data & 0x0f;
	}
}


//-------------------------------------------------
//  blitter_ctrl_w -
//-------------------------------------------------

WRITE16_MEMBER( st_state::blitter_ctrl_w )
{
	if (ACCESSING_BITS_0_7)
	{
		m_blitter_ctrl = (data >> 8) & 0xef;

		if (!(m_blitter_ctrl & ATARIST_BLITTER_CTRL_BUSY))
		{
			if ((data >> 8) & ATARIST_BLITTER_CTRL_BUSY)
			{
				m_mfp->i3_w(1);

				int nops = BLITTER_NOPS[m_blitter_op][m_blitter_hop]; // each NOP takes 4 cycles
				timer_set(attotime::from_hz((Y2/4)/(4*nops)), TIMER_BLITTER_TICK);
			}
		}
	}
	else
	{
		m_blitter_skew = data & 0xcf;
	}
}



//**************************************************************************
//  VIDEO
//**************************************************************************

void st_state::video_start()
{
	m_shifter_timer = timer_alloc(TIMER_SHIFTER_TICK);
	m_glue_timer = timer_alloc(TIMER_GLUE_TICK);

//  m_shifter_timer->adjust(m_screen->time_until_pos(0), 0, attotime::from_hz(Y2/4)); // 125 ns
	m_glue_timer->adjust(m_screen->time_until_pos(0), 0, attotime::from_hz(Y2/16)); // 500 ns

	m_screen->register_screen_bitmap(m_bitmap);

	/* register for state saving */
	save_item(NAME(m_shifter_base));
	save_item(NAME(m_shifter_ofs));
	save_item(NAME(m_shifter_sync));
	save_item(NAME(m_shifter_mode));
	save_item(NAME(m_shifter_palette));
	save_item(NAME(m_shifter_rr));
	save_item(NAME(m_shifter_ir));
	save_item(NAME(m_shifter_bitplane));
	save_item(NAME(m_shifter_shift));
	save_item(NAME(m_shifter_h));
	save_item(NAME(m_shifter_v));
	save_item(NAME(m_shifter_de));

	save_item(NAME(m_blitter_halftone));
	save_item(NAME(m_blitter_src_inc_x));
	save_item(NAME(m_blitter_src_inc_y));
	save_item(NAME(m_blitter_dst_inc_x));
	save_item(NAME(m_blitter_dst_inc_y));
	save_item(NAME(m_blitter_src));
	save_item(NAME(m_blitter_dst));
	save_item(NAME(m_blitter_endmask1));
	save_item(NAME(m_blitter_endmask2));
	save_item(NAME(m_blitter_endmask3));
	save_item(NAME(m_blitter_xcount));
	save_item(NAME(m_blitter_ycount));
	save_item(NAME(m_blitter_xcountl));
	save_item(NAME(m_blitter_hop));
	save_item(NAME(m_blitter_op));
	save_item(NAME(m_blitter_ctrl));
	save_item(NAME(m_blitter_skew));

	set_screen_parameters();
}


void ste_state::video_start()
{
	st_state::video_start();

	// register for state saving
	save_item(NAME(m_shifter_lineofs));
	save_item(NAME(m_shifter_pixelofs));
}

void stbook_state::video_start()
{
}


uint32_t st_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
	return 0;
}