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







                                                                            
                
                            
 
































                                                                            

                                                     




                                                                                                    




                                                                                
                                                                            
 
                                                          
 


                                         
                            

                                              
                                            

  
                                                          
 
                                      
                                 




                                              

  
                                                    




                                                                                             
                                                                         


         





                                                                                             
                                                                         



                                                         




                                                                                             
                                                                         


         
                                                    




                                                                                              
                                                                         



         
                                                      
 
                                                         

                                      
                                                               


                                                                    
                                  
 
                         

 
                                                      
 
                                                                                     

                                     
                                                                 
                                                              

         
                                  
 
                         

 
                                 
 
                                                           
         
                                                                                         
 
                                       
 
                                                                                                
                                                  
         
 
                                                           
         
                                                                                              
 
                                

                                            


                                                                                                     


                                                                                   

         
                                                           
         
                                                                                      
 

                                       
                                                                                              
                                                   
         
 
                                              

 
                                       
 



                                          
                                                                                            


            
                                                                                           
         

 
                                       
 



                                                           
         
                                                                                            


            
                                                                                           


         
                                            
 


                                              
 
                                            


                                              

 
                                                  
 

                                                  
 
                                                

 
                              
 


                                        
                                                                   
 
                                                                                                                                                                          
                                             
 

                                     
 
                    
 
                                 

                                              
                                          

                                             

 
                                                                              
 
                                           
 
                                                              
         









                                         
                                                                         
                 
                                                                      





                                             
 



                                                 
                                                                                                              








                                                                    

                                                                                                  
                                             





                                                                                          

                         
 
                              
                                            
                 


                                                                    

                                                                                                                                       

                                                                                                            
 













                                                                                

                                                            
                                                               




                                                                    


                                                                                  



                                                                                
                 
         

                                                                            

 
                                                                            








                                                                          
                                                                                 
 





                                                              
                                                           


                                                                      
                                   
                                                                                                                                        


                                                                  
                                                                                                                         
                                                                
 
                                                                                                                              
                         

                 

 
                                                                                 
 





                                                              
                                                           


                                                                      
                                   
                                                                                                                                        


                                                                  
                                                                                 
                                                     
 













                                                                                                                              
                                                           



                                                                      
                                                                                                       


                                                                  
                                                                                 


                                                                                                                              
                         

                 
 
 

                                                                                                          

                                                                     
 
                         


















                                                                                  
                                                             







                                                                                  

                 
// license:BSD-3-Clause
// copyright-holders:smf, Nicola Salmoria, Couriersud
// thanks-to: Marc Lafontaine
/***************************************************************************

  video.c

  Functions to emulate the video hardware of the machine.

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

#include "emu.h"
#include "includes/popeye.h"

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

  Convert the color PROMs into a more useable format.

  Popeye has four color PROMS:
  - 32x8 char palette
  - 32x8 background palette
  - two 256x4 sprite palette

  The char and sprite PROMs are connected to the RGB output this way:

  bit 7 -- 220 ohm resistor  -- BLUE (inverted)
        -- 470 ohm resistor  -- BLUE (inverted)
        -- 220 ohm resistor  -- GREEN (inverted)
        -- 470 ohm resistor  -- GREEN (inverted)
        -- 1  kohm resistor  -- GREEN (inverted)
        -- 220 ohm resistor  -- RED (inverted)
        -- 470 ohm resistor  -- RED (inverted)
  bit 0 -- 1  kohm resistor  -- RED (inverted)

  The background PROM is connected to the RGB output this way:

  bit 7 -- 470 ohm resistor  -- BLUE (inverted)
        -- 680 ohm resistor  -- BLUE (inverted)  (1300 ohm in Sky Skipper)
        -- 470 ohm resistor  -- GREEN (inverted)
        -- 680 ohm resistor  -- GREEN (inverted)
        -- 1.2kohm resistor  -- GREEN (inverted)
        -- 470 ohm resistor  -- RED (inverted)
        -- 680 ohm resistor  -- RED (inverted)
  bit 0 -- 1.2kohm resistor  -- RED (inverted)

  The bootleg is the same, but the outputs are not inverted.

  system11 left the following comment on mametesters:

      Worth noting that there are at least 3 different types of picture output
      for this game - and it will be difficult to make it match 'everything' out there.
        1) Normal Nintendo board - inverted video output
        2) Normal Nintendo board with non-inverted video output - has potentiometers to adjust R/G/B
        3) Bootleg board, non inverted non adjustable output

  Additional note: Output for 1) is also adjusted by potentiometers which adjust
  RGB. With today's bgfx hlsl filters it is easy to individually adjust
  levels.

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

const res_net_decode_info tnx1_state::mb7051_decode_info =
{
	1,      /*  one prom 5 lines */
	0,      /*  start at 0 */
	15,     /*  end at 15 (banked) */
	/*  R,   G,   B,  */
	{   0,   0,   0 },      /*  offsets */
	{   0,   3,   6 },      /*  shifts */
	{0x07,0x07,0x03 }       /*  masks */
};

const res_net_decode_info tnx1_state::mb7052_decode_info =
{
	1,      /*  two 4 bit proms */
	0,      /*  start at 0 */
	31,     /*  end at 31 (banked) */
	/*  R,   G,   B */
	{   0,   0,   0},       /*  offsets */
	{   0,   3,   6},       /*  shifts */
	{0x07,0x07,0x03}        /*  masks */
};

const res_net_info tnx1_state::txt_mb7051_net_info =
{
	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_MB7051 | RES_NET_MONITOR_SANYO_EZV20,
	{
		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1000, 470, 220 } },
		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1000, 470, 220 } },
		{ RES_NET_AMP_DARLINGTON, 680, 0, 2, {  470, 220,   0 } }
	}
};

const res_net_info tnx1_state::tnx1_bak_mb7051_net_info =
{
	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_MB7051 | RES_NET_MONITOR_SANYO_EZV20,
	{
		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1200, 680, 470 } },
		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1200, 680, 470 } },
		{ RES_NET_AMP_DARLINGTON, 680, 0, 2, {  680, 470,   0 } }
	}
};

const res_net_info tpp1_state::tpp1_bak_mb7051_net_info =
{
	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_MB7051 | RES_NET_MONITOR_SANYO_EZV20,
	{
		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1200, 680, 470 } },
		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1200, 680, 470 } },
		{ RES_NET_AMP_DARLINGTON, 680, 0, 2, {  680, 470,   0 } }
	}
};

const res_net_info tnx1_state::obj_mb7052_net_info =
{
	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_MB7052 |  RES_NET_MONITOR_SANYO_EZV20,
	{
		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1000, 470, 220 } },
		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1000, 470, 220 } },
		{ RES_NET_AMP_DARLINGTON, 680, 0, 2, {  470, 220,   0 } }
	}
};


void tpp1_state::tnx1_palette(palette_device &palette)
{
	// Two of the PROM address pins are tied together
	for (int i = 0; i < 0x20; i++)
	{
		int const color = (i & 0xf) | ((i & 0x8) << 1);
		m_color_prom[i + 0x20] = m_color_prom[color + 0x20];
	}

	m_palette_bank_cache = -1;

	update_palette();
}

void tnx1_state::tnx1_palette(palette_device &palette)
{
	// Two of the PROM address pins are tied together and one is not connected...
	for (int i = 0;i < 0x100;i++)
	{
		int const color = (i & 0x3f) | ((i & 0x20) << 1);
		m_color_prom_spr[i] = m_color_prom_spr[color];
	}

	m_palette_bank_cache = -1;

	update_palette();
}

void tnx1_state::update_palette()
{
	if ((m_palette_bank ^ m_palette_bank_cache) & 0x08)
	{
		uint8_t *color_prom = m_color_prom + 16 * ((m_palette_bank & 0x08) >> 3);

		std::vector<rgb_t> rgb;

		compute_res_net_all(rgb, color_prom, mb7051_decode_info, bak_mb7051_net_info());
		m_palette->set_pen_colors(0, rgb);
	}

	if ((m_palette_bank ^ m_palette_bank_cache) & 0x08)
	{
		uint8_t *color_prom = m_color_prom + 32 + 16 * ((m_palette_bank & 0x08) >> 3);

		/* characters */
		for (int i = 0; i < 16; i++)
		{
			int r = compute_res_net((color_prom[i] >> 0) & 0x07, 0, txt_mb7051_net_info);
			int g = compute_res_net((color_prom[i] >> 3) & 0x07, 1, txt_mb7051_net_info);
			int b = compute_res_net((color_prom[i] >> 6) & 0x03, 2, txt_mb7051_net_info);
			m_palette->set_pen_color(16 + (2 * i) + 0, rgb_t(0, 0, 0));
			m_palette->set_pen_color(16 + (2 * i) + 1, rgb_t(r, g, b));
		}
	}

	if ((m_palette_bank ^ m_palette_bank_cache) & 0x07)
	{
		uint8_t *color_prom = m_color_prom_spr + 32 * (m_palette_bank & 0x07);

		/* sprites */
		std::vector<rgb_t> rgb;
		compute_res_net_all(rgb, color_prom, mb7052_decode_info, obj_mb7052_net_info);
		m_palette->set_pen_colors(48, rgb);
	}

	m_palette_bank_cache = m_palette_bank;
}

WRITE8_MEMBER(tnx1_state::background_w)
{
	// TODO: confirm the memory layout
	bool lsn = (data & 0x80) == 0;
	if (lsn)
	{
		m_background_ram[offset] = (m_background_ram[offset] & 0xf0) | (data & 0xf);
	}
	else
	{
		m_background_ram[offset] = (m_background_ram[offset] & 0x0f) | (data << 4);
	}
}

WRITE8_MEMBER(tpp2_state::background_w)
{
	// TODO: confirm the memory layout
	bool lsn = (offset & 0x40) == 0;
	offset = (offset & 0x3f) | ((offset & ~0x7f) >> 1);
	if (lsn)
	{
		m_background_ram[offset] = (m_background_ram[offset] & 0xf0) | (data & 0xf);
	}
	else
	{
		m_background_ram[offset] = (m_background_ram[offset] & 0x0f) | (data << 4);
	}
}

WRITE8_MEMBER(tnx1_state::popeye_videoram_w)
{
	m_videoram[offset] = data;
	m_fg_tilemap->mark_tile_dirty(offset);
}

WRITE8_MEMBER(tnx1_state::popeye_colorram_w)
{
	m_colorram[offset] = data;
	m_fg_tilemap->mark_tile_dirty(offset);
}

TILE_GET_INFO_MEMBER(tnx1_state::get_fg_tile_info)
{
	int code = m_videoram[tile_index];
	int color = m_colorram[tile_index] & 0x0f;

	SET_TILE_INFO_MEMBER(0, code, color, 0);
}

void tnx1_state::video_start()
{
	m_background_ram.resize(0x1000);
	m_sprite_ram.resize(0x400);

	m_sprite_bitmap = std::make_unique<bitmap_ind16>(512, 512);

	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tnx1_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32);
	m_fg_tilemap->set_transparent_pen(0);

	m_bitmap[0].resize(512, 512);
	m_bitmap[1].resize(512, 512);

	m_field = 0;

	save_item(NAME(m_field));
	save_item(NAME(m_palette_bank));
	save_item(NAME(m_palette_bank_cache));
	save_item(NAME(m_background_ram));
	save_item(NAME(m_background_scroll));
	save_item(NAME(m_sprite_ram));
}

void tnx1_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	m_sprite_bitmap->fill(0, cliprect);

	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
	{
		struct attribute_memory
		{
			int row;
			int sx;
			uint8_t color;
			uint16_t code;
			int flipx;
			int flipy;
		} attributes[64] = { 0 };

		for (int offs = 4; offs < m_dmasource.bytes(); offs += 4)
		{
			int sy = 0x200 - (m_sprite_ram[offs + 1] * 2);
			int row = y - sy;
			if (flip_screen())
			{
				sy ^= 0x1ff;
				row = sy - y;
			}

			if (row >= 0 && row < 16)
			{
				/*
				* offs+3:
				* bit 7 ? TODO: figure out why olive oil and wimpy have some of these bits set
				* bit 6 ?
				* bit 5 ?
				* bit 4 MSB of sprite code
				* bit 3 vertical flip
				* bit 2 sprite bank
				* bit 1 \ color (with bit 2 as well)
				* bit 0 /
				*/

				struct attribute_memory *a = &attributes[m_sprite_ram[offs] >> 2];
				a->sx = m_sprite_ram[offs] * 2;
				a->row = row;
				a->code = ((m_sprite_ram[offs + 2] & 0x7f)
					+ ((m_sprite_ram[offs + 3] & 0x10) << 3)
					+ ((m_sprite_ram[offs + 3] & 0x04) << 6)) ^ 0x1ff;
				a->color = (m_sprite_ram[offs + 3] & 0x07);
				a->flipx = (m_sprite_ram[offs + 2] & 0x80) ? 0xf : 0;
				a->flipy = (m_sprite_ram[offs + 3] & 0x08) ? 0xf : 0;
			}
		}

		int flipx = 0;
		for (int i = 0; i < 64; i++)
		{
			struct attribute_memory *a = &attributes[i];
			if (a->color != 0)
			{
				gfx_element *gfx = m_gfxdecode->gfx(1);
				const pen_t *pal = &m_palette->pen(gfx->colorbase() + gfx->granularity() * (a->color % gfx->colors()));
				const uint8_t *source_base = gfx->get_data(a->code % gfx->elements());
				const uint8_t *source = source_base + (a->row ^ a->flipy) * gfx->rowbytes();

				if (bootleg_sprites() && flipx != a->flipx)
				{
					int px = a->sx - 7;
					if (px >= 0 && px < 512)
					{
						if (flip_screen())
							px ^= 0x1ff;

						m_sprite_bitmap->pix(y, px) = 0;
					}

					flipx = a->flipx;
				}

				for (int x = 0; x < 16; x++)
				{
					int px = a->sx + x - 6;
					if (px >= 0 && px < 512)
					{
						if (flip_screen())
							px ^= 0x1ff;

						uint16_t p = source[x ^ a->flipx];
						if (p) p = pal[p];

						m_sprite_bitmap->pix(y, px) = p;
					}
				}
			}
		}
	}

	copybitmap_trans(bitmap, *m_sprite_bitmap, 0, 0, 0, 0, cliprect, 0);
}

void tnx1_state::draw_field(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	int x;
	int y;

	for (y=(cliprect.min_y & ~1) + m_field; y<=cliprect.max_y; y += 2)
		for (x=cliprect.min_x; x<=cliprect.max_x; x++)
			bitmap.pix(y, x) = 0;
}

void tnx1_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
	{
		int sy = y;
		if (flip_screen())
			sy ^= 0x1ff;

		sy -= 0x200 - (2 * m_background_scroll[1]);

		for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
		{
			if (sy < 0)
				bitmap.pix16(y, x) = m_background_ram[0] & 0xf; // TODO: find out exactly where the data is fetched from
			else
			{
				// TODO: confirm the memory layout
				int sx = x + (2 * (m_background_scroll[0] | ((m_background_scroll[2] & 1) << 8))) + 0x70;
				int shift = (sx & 0x200) / 0x80;

				bitmap.pix16(y, x) = (m_background_ram[((sx / 8) & 0x3f) + ((sy / 8) * 0x40)] >> shift) & 0xf;
			}
		}
	}
}

void tpp1_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
	{
		int sy = y;
		if (flip_screen())
			sy ^= 0x1ff;

		sy -= 0x200 - (2 * m_background_scroll[1]);

		for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
		{
			if (sy < 0)
				bitmap.pix16(y, x) = m_background_ram[0] & 0xf; // TODO: find out exactly where the data is fetched from
			else
			{
				// TODO: confirm the memory layout
				int sx = x + (2 * m_background_scroll[0]) + 0x70;
				int shift = (sy & 4);

				bitmap.pix16(y, x) = (m_background_ram[((sx / 8) & 0x3f) + ((sy / 8) * 0x40)] >> shift) & 0xf;
			}
		}
	}
}

void tpp2_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
	{
		int sy = y;
		if (flip_screen())
			sy ^= 0x1ff;

		sy -= 0x200 - (2 * m_background_scroll[1]);

		for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
		{
			if (sy < 0)
				bitmap.pix16(y, x) = m_background_ram[((sy & 0x100) / 8) * 0x40] & 0xf;
			else
			{
				// TODO: confirm the memory layout
				int sx = x + (2 * m_background_scroll[0]) + 0x70;
				int shift = (sy & 4);

				bitmap.pix16(y, x) = (m_background_ram[((sx / 8) & 0x3f) + ((sy / 8) * 0x40)] >> shift) & 0xf;
			}
		}
	}
}

uint32_t tnx1_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	const auto ilmode(m_io_mconf->read());
	bitmap_ind16 &bm((ilmode == 0) ? bitmap : m_bitmap[m_field]);

	update_palette();
	draw_background(bm, cliprect);
	draw_sprites(bm, cliprect);
	m_fg_tilemap->draw(screen, bm, cliprect, 0, 0);
	if (ilmode == 1)
	{
		for (int y=(cliprect.min_y); y<=cliprect.max_y; y ++)
		{
			if ((y & 1) == m_field)
				for (int x=cliprect.min_x; x<=cliprect.max_x; x++)
					bitmap.pix(y, x) = 0;
			else
				for (int x=cliprect.min_x; x<=cliprect.max_x; x++)
					bitmap.pix(y, x) = bm.pix(y, x);
		}
	}
	else if (ilmode == 2)
	{
		for (int y=(cliprect.min_y); y<=cliprect.max_y; y ++)
		{
			auto &bm_last(m_bitmap[m_field ^ 1]);
			if ((y & 1) == m_field)
				for (int x=cliprect.min_x; x<=cliprect.max_x; x++)
					bitmap.pix(y, x) = bm_last.pix(y, x);
			else
				for (int x=cliprect.min_x; x<=cliprect.max_x; x++)
					bitmap.pix(y, x) = bm.pix(y, x);
		}
	}
	return 0;
}