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


                                                                                                               





                                                                             
                
                              

 
                                                                                                                       
 


                                                      


                 
                                         
                                                                                  
                                                                             
 
                             





                                             

                                                            
                         
                                                                                            
                                                                                                   



                                                             
                                                                                                         

                                  
                                         





                                                                                   
                                                                        
                                                      













                                       













                                                                                                     

                                                                                   








                                                                        

 
                                                                                                              
 







                                                      
                                       
                                    
                                         


                                 



                                                          
            
                                 
 

                 
                                         
                                                
                                                                  
 
                                                                                                                  



                                                
                                                                                                                           
                 
                                                                                                  

                                 
                                                                                                                               
                 
                                                         



                                                      
                                                                                                                                   

                 

                                                                              
 
                                                                             




                                                                       
                             


                                             
                                           
                 

                                                            
                         
                                                      
                                                             

                                                                                              
                                    
                                                             
 
                                                                                                   




                                                                         

                                                                        














                                                                 
                                                                                  
                                        
                                                                                  
 
                                                                                         
                                       
                                                                                                     
 
                                                                                                         

                                  
                                         


                                      
                                                                                                             
                 
                                                                        
                                                      
























                                                                                             


                                                                                                     
 
                                                                 

 
                                                                                                                       
 



                                                      
 
                                                          
 
                                                           



                                   
                                               


                                            
                                                




                                                                      
                                                                    
 
                                                                             

                                                                          
                                                            




























                                                                                     
                                                                                            
                                                                                                   










                                                                               
                                                                 









                                                                                   
                                                      






                 
                                                         
 
                       
                   
         
                                                            
 

                                                                                                                                          
         


 






                                       
                                                                        
 
                                                                                                                       
 


                                                      


                 
                                         
                                                                                  
 
                                  
                                                                                                                                       
                    
                                                                                     
 
                             


                                             
                               

                           

                                                            
                         
                                                                                            
 
                                                  
                                                                                                                                                               
                                    
                                                                                                           



                                                             
                                                                                                         

                                  
                                         


                                      
                                                                                                             
                 
                                                                        
                                                      




                 
// license:BSD-3-Clause
// copyright-holders:Nicola Salmoria, Tormod Tjaberg, Mirko Buffoni,Lee Taylor, Valerio Verrando, Zsolt Vasvari
// thanks-to:Michael Strutts, Marco Cassili
/***************************************************************************

    Midway 8080-based black and white hardware

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

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


uint32_t mw8080bw_state::screen_update_mw8080bw(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	uint8_t x = 0;
	uint8_t y = MW8080BW_VCOUNTER_START_NO_VBLANK;
	uint8_t video_data = 0;

	while (1)
	{
		// plot the current pixel
		pen_t pen = (video_data & 0x01) ? rgb_t::white() : rgb_t::black();
		bitmap.pix32(y - MW8080BW_VCOUNTER_START_NO_VBLANK, x) = pen;

		// next pixel
		video_data = video_data >> 1;
		x = x + 1;

		/* end of line? */
		if (x == 0)
		{
			// yes, flush out the shift register
			for (int i = 0; i < 4; i++)
			{
				pen = (video_data & 0x01) ? rgb_t::white() : rgb_t::black();
				bitmap.pix32(y - MW8080BW_VCOUNTER_START_NO_VBLANK, 256 + i) = pen;

				video_data = video_data >> 1;
			}

			// next row, video_data is now 0, so the next line will start with 4 blank pixels
			y = y + 1;

			// end of screen?
			if (y == 0)
				break;
		}
		/* the video RAM is read at every 8 pixels starting with pixel 4 */
		else if ((x & 0x07) == 0x04)
		{
			offs_t const offs = ((offs_t)y << 5) | (x >> 3);
			video_data = m_main_ram[offs];
		}
	}

	return 0;
}



/*************************************
 *
 *  Space Encounters
 *
 *************************************/

/* video signals mixed via R2 open collector nand gates and 'brite' RC circuit

    * when /BRITE lo, cap C23 discharge rapidly, disabling Q2, overpowering all other video signals
    * when /BRITE hi, cap C23 charge through 10k res, brite voltage decrease to 0 over approx 0.4 sec

    * inverted video data is fed into R2 nand gates:
        * when /VIDEO lo, all gates open for max brightness
            * max V = (5 - 0.7) * 470 / (470 + 100) = 3.5 V
        * when /video hi, pin 5 always gnd, max = 3 V, min = 1 V
        * (guess) pin 11 state controls trench color
        * (guess) pin 3 low for trench side
        * (guess) pin 8 low for trench floor
        * thus, trench side: 1.4 or 2.2 V
        * trench floor: 1.3 or 2.0 V
        * trech top: 1.8 or 3 V
        * scaled to 3.2 V = 255, 1.2 V = 0 (arbitrary values chosen to match video)
*/

#define SPCENCTR_TOP_TRENCH_DARK_RGB32_PEN       rgb_t(0x4d, 0x4d, 0x4d)
#define SPCENCTR_TOP_TRENCH_LIGHT_RGB32_PEN      rgb_t(0xe6, 0xe6, 0xe6)
#define SPCENCTR_SIDE_TRENCH_DARK_RGB32_PEN      rgb_t(0x1a, 0x1a, 0x1a)
#define SPCENCTR_SIDE_TRENCH_LIGHT_RGB32_PEN     rgb_t(0x80, 0x80, 0x80)
#define SPCENCTR_BOTTOM_TRENCH_DARK_RGB32_PEN    rgb_t(0x0d, 0x0d, 0x0d)
#define SPCENCTR_BOTTOM_TRENCH_LIGHT_RGB32_PEN   rgb_t(0x66, 0x66, 0x66)
#define SPCENCTR_BRIGHTNESS_DECAY                10


uint32_t spcenctr_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	uint8_t line_buf[256]; /* 256x1 bit RAM */

	uint8_t x = 0;
	uint8_t y = MW8080BW_VCOUNTER_START_NO_VBLANK;
	uint8_t video_data = 0;
	uint8_t draw_line = 0;
	uint8_t draw_trench = 0;
	uint8_t draw_floor = 0;
	uint8_t width = m_trench_width;
	uint8_t floor_width = width;
	uint8_t center = m_trench_center;

	memset(line_buf, 0, 256);

	if (m_bright_control)
		m_brightness = 255;
	else if (m_brightness > SPCENCTR_BRIGHTNESS_DECAY)
		m_brightness -= SPCENCTR_BRIGHTNESS_DECAY;
	else
		m_brightness = 0;

	while (1)
	{
		// plot the current pixel
		uint8_t bit = video_data & 0x01;
		pen_t pen = bit ? rgb_t::white() : rgb_t::black();

		if (!(width & 0x80) && draw_trench) // possibly draw trench in the background, top of trench first
		{
			line_buf[x] = draw_line;

			if (!bit)
				pen = draw_line ? SPCENCTR_TOP_TRENCH_LIGHT_RGB32_PEN : SPCENCTR_TOP_TRENCH_DARK_RGB32_PEN;
		}
		else if (!(floor_width & 0x80) && (draw_trench || draw_floor)) // sides of trench?
		{
			if (!bit)
				pen = line_buf[x] ? SPCENCTR_SIDE_TRENCH_LIGHT_RGB32_PEN : SPCENCTR_SIDE_TRENCH_DARK_RGB32_PEN;
		}
		else if (draw_floor) // bottom of trench?
		{
			line_buf[x] = line_buf[x - 1];

			if (!bit)
				pen = line_buf[x] ? SPCENCTR_BOTTOM_TRENCH_LIGHT_RGB32_PEN : SPCENCTR_BOTTOM_TRENCH_DARK_RGB32_PEN;
		}

		if (m_brightness > (pen & 0xff))
			pen = rgb_t(m_brightness, m_brightness, m_brightness);

		bitmap.pix32(y - MW8080BW_VCOUNTER_START_NO_VBLANK, x) = pen;

		center = center + 1;
		width = width + ((center & 0x80) ? -1 : 1);
		floor_width = floor_width + ((center & 0x80) ? -1 : 1);

		// next pixel
		video_data = video_data >> 1;
		x = x + 1;

		if (x == 0) // end of line?
		{
			// yes, flush out the shift register
			for (int i = 0; i < 4; i++)
			{
				if (video_data & 0x01)
					pen = rgb_t::white();
				else if(m_brightness)
					pen = rgb_t(m_brightness, m_brightness, m_brightness);
				else
					pen = rgb_t::black();

				bitmap.pix32(y - MW8080BW_VCOUNTER_START_NO_VBLANK, 256 + i) = pen;

				video_data = video_data >> 1;
			}

			/* update the trench control for the next line */
			offs_t const offs = ((offs_t)y << 5) | 0x1f;
			uint8_t const trench_control = m_main_ram[offs];

			if (trench_control & 0x40)
				draw_trench = 1;

			if (trench_control & 0x20)
				draw_trench = 0;

			if (trench_control & 0x10)
				draw_floor = 1;

			if (trench_control & 0x08)
				draw_floor = 0;

			draw_line = (trench_control & 0x80) >> 7;

			// add the lower 2 bits stored in the slope array to width
			if (draw_trench)
				width = width + (m_trench_slope[y & 0x0f] & 0x03);

			// add the higher 2 bits stored in the slope array to floor width
			if (draw_floor)
				floor_width = floor_width + ((m_trench_slope[y & 0x0f] & 0x0c) >> 2);

			// next row, video_data is now 0, so the next line will start with 4 blank pixels
			y = y + 1;

			// end of screen?
			if (y == 0)
				break;
		}
		else if ((x & 0x07) == 0x04) // the video RAM is read at every 8 pixels starting with pixel 4
		{
			offs_t const offs = ((offs_t)y << 5) | (x >> 3);
			video_data = m_main_ram[offs];
		}
	}

	return 0;
}



/*************************************
 *
 *  Phantom II
 *
 *************************************/


/* the cloud generator comprises of 2 counters and a shift register:

   * counter 1 is 8 bits and and clocked every pixel. It gets cleared at the end of HBLANK .
     Bit 0 is used to clock the shift register, thus repeating every pixel twice.
     Bits 4-7 go to address line A0-A3 of the cloud gfx prom.
   * counter 2 is 12 bits starting from 0xe0b and counts up to 0xfff.  It gets clocked at the
     beginning of HBLANK and is never cleared.
     Bits 1-7 go to address line A4-A10 of the cloud gfx prom.
*/

#define PHANTOM2_CLOUD_COUNTER_START      (0x0e0b)
#define PHANTOM2_CLOUD_COUNTER_END        (0x1000)
#define PHANTOM2_CLOUD_COUNTER_PERIOD     (PHANTOM2_CLOUD_COUNTER_END - PHANTOM2_CLOUD_COUNTER_START)

#define PHANTOM2_RGB32_CLOUD_PEN          rgb_t(0xc0, 0xc0, 0xc0)


uint32_t mw8080bw_state::screen_update_phantom2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	uint8_t x = 0;
	uint8_t y = MW8080BW_VCOUNTER_START_NO_VBLANK;
	uint8_t video_data = 0;
	uint8_t cloud_data = 0;

	uint16_t cloud_counter = m_phantom2_cloud_counter;

	uint8_t *cloud_region = memregion("proms")->base();

	while (1)
	{
		int load_shift_reg;
		uint8_t cloud_data_to_load = 0;
		pen_t pen;

		/* plot the current pixel */
		uint8_t bit = video_data & 0x01;

		/* if background color, cloud gfx in the background */
		if ((bit == 0) && (cloud_data & 0x01))
			pen = PHANTOM2_RGB32_CLOUD_PEN;
		else
			pen = bit ? rgb_t::white() : rgb_t::black();

		bitmap.pix32(y - MW8080BW_VCOUNTER_START_NO_VBLANK, x) = pen;

		/* move to next pixel -- if ripple carry is currently set,
		   prepare for loading the shift register */
		load_shift_reg = ((x & 0x0f) == 0x0f);

		if (load_shift_reg)
		{
			offs_t cloud_offs = ((cloud_counter & 0xfe) << 3) | (x >> 4);
			cloud_data_to_load = cloud_region[cloud_offs];
		}

		video_data = video_data >> 1;
		x = x + 1;

		/* the sift register is clocked on the falling edge of bit 0 */
		if (!(x & 0x01))
		{
			/* load or shift? */
			if (load_shift_reg)
				cloud_data = cloud_data_to_load;
			else
				cloud_data = cloud_data >> 1;
		}

		/* end of line? */
		if (x == 0)
		{
			/* yes, flush out the shift register */
			int i;

			for (i = 0; i < 4; i++)
			{
				pen = (video_data & 0x01) ? rgb_t::white() : rgb_t::black();
				bitmap.pix32(y - MW8080BW_VCOUNTER_START_NO_VBLANK, 256 + i) = pen;

				video_data = video_data >> 1;
			}

			/* next row of clouds */
			cloud_counter = cloud_counter + 1;

			if (cloud_counter == PHANTOM2_CLOUD_COUNTER_END)
				cloud_counter = PHANTOM2_CLOUD_COUNTER_START;

			/* next row of pixels, video_data is now 0, so the next
			   line will start with 4 blank pixels */
			y = y + 1;

			/* end of screen? */
			if (y == 0)
				break;
		}
		/* the video RAM is read at every 8 pixels starting with pixel 4 */
		else if ((x & 0x07) == 0x04)
		{
			offs_t offs = ((offs_t)y << 5) | (x >> 3);
			video_data = m_main_ram[offs];
		}
	}

	return 0;
}


WRITE_LINE_MEMBER(mw8080bw_state::screen_vblank_phantom2)
{
	// falling edge
	if (!state)
	{
		m_phantom2_cloud_counter += MW8080BW_VTOTAL;

		if (m_phantom2_cloud_counter >= PHANTOM2_CLOUD_COUNTER_END)
			m_phantom2_cloud_counter = PHANTOM2_CLOUD_COUNTER_START + (m_phantom2_cloud_counter - PHANTOM2_CLOUD_COUNTER_END);
	}
}


/*************************************
 *
 *  Space Invaders
 *
 *************************************/


// the flip screen circuit is just a couple of relays on the monitor PCB

uint32_t mw8080bw_state::screen_update_invaders(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	uint8_t x = 0;
	uint8_t y = MW8080BW_VCOUNTER_START_NO_VBLANK;
	uint8_t video_data = 0;

	while (1)
	{
		// plot the current pixel
		pen_t pen = (video_data & 0x01) ? rgb_t::white() : rgb_t::black();

		if (m_flip_screen)
			bitmap.pix32(MW8080BW_VBSTART - 1 - (y - MW8080BW_VCOUNTER_START_NO_VBLANK), MW8080BW_HPIXCOUNT - 1 - x) = pen;
		else
			bitmap.pix32(y - MW8080BW_VCOUNTER_START_NO_VBLANK, x) = pen;

		// next pixel
		video_data = video_data >> 1;
		x = x + 1;

		// end of line?
		if (x == 0)
		{
			// yes, flush out the shift register
			for (int i = 0; i < 4; i++)
			{
				pen = (video_data & 0x01) ? rgb_t::white() : rgb_t::black();

				if (m_flip_screen)
					bitmap.pix32(MW8080BW_VBSTART - 1 - (y - MW8080BW_VCOUNTER_START_NO_VBLANK), MW8080BW_HPIXCOUNT - 1 - (256 + i)) = pen;
				else
					bitmap.pix32(y - MW8080BW_VCOUNTER_START_NO_VBLANK, 256 + i) = pen;

				video_data = video_data >> 1;
			}

			// next row, video_data is now 0, so the next line will start with 4 blank pixels
			y = y + 1;

			// end of screen?
			if (y == 0)
				break;
		}
		else if ((x & 0x07) == 0x04) // the video RAM is read at every 8 pixels starting with pixel 4
		{
			offs_t const offs = (offs_t(y) << 5) | (x >> 3);
			video_data = m_main_ram[offs];
		}
	}

	return 0;
}