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

                                                







                                                                            
                
                           
                   


































                                                                                           
                               
 

                            



                                                                         
                                                                                                                 
 



                                                
 
                                   
         
                                          






                                                                 
                                                          


                                                          
                                                      














                                                                                              
                                                                                 




                                                                                                                                      
                                                                                              





                                                                
                                                                                          



















                                                                                          
                                                                                                                   
 







                                                                                             
 
                       




                             
                                            
         
                                          






                                                                        
                                                          


                                                            
                                                                      
 
                                                                            

                                                   
                                                                                         












                                                           
                                                                  
















                                                                                               
                                                                                         



                                                                                        
                                                                         



















                                                                               
                                                                                                                   
 



                                                
 
                                   
         
                                          






                                                                 
                                                          


                                                          
                                                      














                                                                                              
                                                                                

                                                                                               
                                                                          






                                                                                          
                                                                          








                                                    
                                                                                                                 
 



                                                                                          

                                                                                           
                                   
         
                                             


                                                                 
                       




                       
                              
         
                                                 



                                                           
                                                                          


                                                                      
                                                                      
















                                                                                                               
                                                                                                        
















                                                                                                          
                                                     



                                                                    
                                                                          


                                                                  
                                                                              










                                                                                       
                                                                                                                    











                                                                                         
                                                     
                                                                                       
                                                                     



                                                                    
                                                                          


                                                                  
                                                                              













                                                                                       
                                                     
                                                                                      

                                                                                 



                                                                    
                                                                          


                                                                  

                                                                                                  



                                                                                       
                                                                                           






                                                                             

                                                                                                                    



                                                                                         
                                                                                         











                                                                              
                                                                                                                    
 



                                                
 
                                   
         
                                          






                                                                 
                                                          


                                                          
                                                      

                                                                                       
                                                                                       
















                                                                                  
                                                                                                                   

                                                                              



                                                
 
                                   
         
                                      






                                                                 
                                                          


                                                          
                                                      

                                                                                       
                                                                 























































                                                                                  







                                      

  
                                      
 
                                                                              
 
// license:BSD-3-Clause
// copyright-holders:Robbbert and unknown others
/***************************************************************************

  trs80.c

  Functions to emulate the video hardware of the TRS80.

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

#include "emu.h"
#include "includes/trs80.h"
#include "screen.h"

/* Bit assignment for "state->m_mode"
    d7 Page select
    d6 LNW80 switch to graphics ram
    d5 LNW80 colour or monochrome (1=colour)
    d4 LNW80 lores or hires (1=hires) also does 64 or 80 chars per line
    d3 LNW80 invert entire screen / Model III/4 Invert characters with bit 7 set (1=invert)
    d2 80/40 or 64/32 characters per line (1=80)
    d1 7 or 8 bit video (1=requires 7-bit, 0=don't care)
    d0 80/64 or 40/32 characters per line (1=32) */


WRITE8_MEMBER( trs80_state::trs80m4_88_w )
{
/* This is for the programming of the CRTC registers.
    However this CRTC is mask-programmed, and only the
    start address register can be used. The cursor and
    light-pen facilities are ignored. The character clock
    is changed depending on the screen size chosen.
    Therefore it is easier to use normal
    coding rather than the mc6845 device. */

	if (!offset) m_crtc_reg = data & 0x1f;

	if (offset) switch (m_crtc_reg)
	{
		case 12:
			m_start_address = (m_start_address & 0x00ff) | (data << 8);
			break;
		case 13:
			m_start_address = (m_start_address & 0xff00) | data;
	}
}


void trs80_state::video_start()
{
	m_size_store = 0xff;
	m_mode &= 2;
}


/* 7 or 8-bit video, 32/64 characters per line = trs80, trs80l2, sys80 */
uint32_t trs80_state::screen_update_trs80(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	uint8_t y,ra,chr,gfx,gfxbit;
	uint16_t sy=0,ma=0,x;
	uint8_t cols = BIT(m_mode, 0) ? 32 : 64;
	uint8_t skip = BIT(m_mode, 0) ? 2 : 1;

	if (m_mode != m_size_store)
	{
		m_size_store = m_mode & 1;
		screen.set_visible_area(0, cols*6-1, 0, 16*12-1);
	}

	for (y = 0; y < 16; y++)
	{
		for (ra = 0; ra < 12; ra++)
		{
			uint16_t *p = &bitmap.pix16(sy++);

			for (x = ma; x < ma + 64; x+=skip)
			{
				chr = m_p_videoram[x];

				if (chr & 0x80)
				{
					gfxbit = (ra & 0x0c)>>1;
					/* Display one line of a lores character (6 pixels) */
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					gfxbit++;
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
				}
				else
				{
					if (BIT(m_mode, 1) & (chr < 32)) chr+=64;

					// if g,j,p,q,y; lower the descender
					if ((chr==0x2c)||(chr==0x3b)||(chr==0x67)||(chr==0x6a)||(chr==0x70)||(chr==0x71)||(chr==0x79))
					{
						if ((ra < 10) && (ra > 1))
							gfx = m_p_chargen[(chr<<3) | (ra-2) ];
						else
							gfx = 0;
					}
					else
					{
						if (ra < 8)
							gfx = m_p_chargen[(chr<<3) | ra ];
						else
							gfx = 0;
					}

					/* Display a scanline of a character (6 pixels) */
					*p++ = BIT(gfx, 5);
					*p++ = BIT(gfx, 4);
					*p++ = BIT(gfx, 3);
					*p++ = BIT(gfx, 2);
					*p++ = BIT(gfx, 1);
					*p++ = BIT(gfx, 0);
				}
			}
		}
		ma+=64;
	}
	return 0;
}

/* 8-bit video, 32/64/40/80 characters per line = trs80m3, trs80m4. */
uint32_t trs80_state::screen_update_trs80m4(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	uint8_t y,ra,chr,gfx,gfxbit;
	uint16_t sy=0,ma=0,x;
	uint8_t skip=1;
	uint8_t cols = BIT(m_mode, 2) ? 80 : 64;
	uint8_t rows = BIT(m_mode, 2) ? 24 : 16;
	uint8_t lines = BIT(m_mode, 2) ? 10 : 12;
	uint8_t s_cols = cols;
	uint8_t mask = BIT(m_mode, 5) ? 0xff : 0xbf;  /* Select Japanese or extended chars */

	if (m_mode & 1)
	{
		s_cols >>= 1;
		skip = 2;
	}

	if ((m_mode & 0x7f) != m_size_store)
	{
		m_size_store = m_mode & 5;
		screen.set_visible_area(0, s_cols*8-1, 0, rows*lines-1);
	}

	for (y = 0; y < rows; y++)
	{
		for (ra = 0; ra < lines; ra++)
		{
			uint16_t *p = &bitmap.pix16(sy++);

			for (x = ma; x < ma + cols; x+=skip)
			{
				chr = m_p_videoram[x+m_start_address];

				if (((chr & 0xc0) == 0xc0) && (~m_mode & 8))
				{
					if (ra < 8)
						gfx = m_p_chargen[((chr&mask)<<3) | ra ];
					else
						gfx = 0;

					*p++ = BIT(gfx, 7);
					*p++ = BIT(gfx, 6);
					*p++ = BIT(gfx, 5);
					*p++ = BIT(gfx, 4);
					*p++ = BIT(gfx, 3);
					*p++ = BIT(gfx, 2);
					*p++ = BIT(gfx, 1);
					*p++ = BIT(gfx, 0);
				}
				else
				if ((chr & 0x80) && (~m_mode & 8))
				{
					gfxbit = (ra & 0x0c)>>1;
					/* Display one line of a lores character */
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					gfxbit++;
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
				}
				else
				{
					/* get pattern of pixels for that character scanline */
					if (ra < 8)
						gfx = m_p_chargen[((chr&0x7f)<<3) | ra ];
					else
						gfx = 0;

					/* if inverse mode, and bit 7 set, invert gfx */
					if (BIT(m_mode, 3) & BIT(chr, 7))
						gfx ^= 0xff;

					/* Display a scanline of a character */
					*p++ = BIT(gfx, 7);
					*p++ = BIT(gfx, 6);
					*p++ = BIT(gfx, 5);
					*p++ = BIT(gfx, 4);
					*p++ = BIT(gfx, 3);
					*p++ = BIT(gfx, 2);
					*p++ = BIT(gfx, 1);
					*p++ = BIT(gfx, 0);
				}
			}
		}
		ma+=cols;
	}
	return 0;
}

/* 7 or 8-bit video, 64/32 characters per line = ht1080z, ht1080z2, ht108064 */
uint32_t trs80_state::screen_update_ht1080z(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	uint8_t y,ra,chr,gfx,gfxbit;
	uint16_t sy=0,ma=0,x;
	uint8_t cols = BIT(m_mode, 0) ? 32 : 64;
	uint8_t skip = BIT(m_mode, 0) ? 2 : 1;

	if (m_mode != m_size_store)
	{
		m_size_store = m_mode & 1;
		screen.set_visible_area(0, cols*6-1, 0, 16*12-1);
	}

	for (y = 0; y < 16; y++)
	{
		for (ra = 0; ra < 12; ra++)
		{
			uint16_t *p = &bitmap.pix16(sy++);

			for (x = ma; x < ma + 64; x+=skip)
			{
				chr = m_p_videoram[x];

				if (chr & 0x80)
				{
					gfxbit = (ra & 0x0c)>>1;
					/* Display one line of a lores character (6 pixels) */
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					gfxbit++;
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
					*p++ = BIT(chr, gfxbit);
				}
				else
				{
					if ((m_mode & 2) && (chr < 32)) chr+=64;

					/* get pattern of pixels for that character scanline */
					gfx = m_p_chargen[(chr<<4) | ra ];

					/* Display a scanline of a character (6 pixels) */
					*p++ = BIT(gfx, 7);
					*p++ = BIT(gfx, 6);
					*p++ = BIT(gfx, 5);
					*p++ = BIT(gfx, 4);
					*p++ = BIT(gfx, 3);
					*p++ = 0;   /* fix for ht108064 */
				}
			}
		}
		ma+=64;
	}
	return 0;
}

/* 8-bit video, 64/80 characters per line = lnw80 */
uint32_t trs80_state::screen_update_lnw80(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	static const uint16_t rows[] = { 0, 0x200, 0x100, 0x300, 1, 0x201, 0x101, 0x301 };
	uint8_t chr,gfx,gfxbit,bg=7,fg=0;
	uint16_t sy=0,ma=0,x,y,ra;
	uint8_t cols = BIT(m_mode, 4) ? 80 : 64;

	/* Although the OS can select 32-character mode, it is not supported by hardware */
	if (m_mode != m_size_store)
	{
		m_size_store = m_mode & 0x10;
		screen.set_visible_area(0, cols*6-1, 0, 16*12-1);
	}

	if (m_mode & 8)
	{
		bg = 0;
		fg = 7;
	}

	switch (m_mode & 0x30)
	{
		case 0:                 // MODE 0
			for (y = 0; y < 16; y++)
			{
				for (ra = 0; ra < 12; ra++)
				{
					uint16_t *p = &bitmap.pix16(sy++);

					for (x = ma; x < ma + 64; x++)
					{
						chr = m_p_videoram[x];

						if (chr & 0x80)
						{
							gfxbit = (ra & 0x0c)>>1;
							/* Display one line of a lores character (6 pixels) */
							*p++ = BIT(chr, gfxbit) ? fg : bg;
							*p++ = BIT(chr, gfxbit) ? fg : bg;
							*p++ = BIT(chr, gfxbit) ? fg : bg;
							gfxbit++;
							*p++ = BIT(chr, gfxbit) ? fg : bg;
							*p++ = BIT(chr, gfxbit) ? fg : bg;
							*p++ = BIT(chr, gfxbit) ? fg : bg;
						}
						else
						{
							/* get pattern of pixels for that character scanline */
							if (ra < 8)
								gfx = m_p_chargen[(chr<<1) | rows[ra] ];
							else
								gfx = 0;

							/* Display a scanline of a character (6 pixels) */
							*p++ = BIT(gfx, 2) ? fg : bg;
							*p++ = BIT(gfx, 1) ? fg : bg;
							*p++ = BIT(gfx, 6) ? fg : bg;
							*p++ = BIT(gfx, 7) ? fg : bg;
							*p++ = BIT(gfx, 5) ? fg : bg;
							*p++ = BIT(gfx, 3) ? fg : bg;
						}
					}
				}
				ma+=64;
			}
			break;

		case 0x10:                  // MODE 1
			for (y = 0; y < 0x400; y+=0x40)
			{
				for (ra = 0; ra < 0x3000; ra+=0x400)
				{
					uint16_t *p = &bitmap.pix16(sy++);

					for (x = 0; x < 0x40; x++)
					{
						gfx = m_p_gfxram[ y | x | ra];
						/* Display 6 pixels in normal region */
						*p++ = BIT(gfx, 0) ? fg : bg;
						*p++ = BIT(gfx, 1) ? fg : bg;
						*p++ = BIT(gfx, 2) ? fg : bg;
						*p++ = BIT(gfx, 3) ? fg : bg;
						*p++ = BIT(gfx, 4) ? fg : bg;
						*p++ = BIT(gfx, 5) ? fg : bg;
					}

					for (x = 0; x < 0x10; x++)
					{
						gfx = m_p_gfxram[ 0x3000 | x | (ra & 0xc00) | ((ra & 0x3000) >> 8)];
						/* Display 6 pixels in extended region */
						*p++ = BIT(gfx, 0) ? fg : bg;
						*p++ = BIT(gfx, 1) ? fg : bg;
						*p++ = BIT(gfx, 2) ? fg : bg;
						*p++ = BIT(gfx, 3) ? fg : bg;
						*p++ = BIT(gfx, 4) ? fg : bg;
						*p++ = BIT(gfx, 5) ? fg : bg;
					}
				}
			}
			break;

		case 0x20:                  // MODE 2
			/* it seems the text video ram can have an effect in this mode,
			    not explained clearly, so not emulated */
			for (y = 0; y < 0x400; y+=0x40)
			{
				for (ra = 0; ra < 0x3000; ra+=0x400)
				{
					uint16_t *p = &bitmap.pix16(sy++);

					for (x = 0; x < 0x40; x++)
					{
						gfx = m_p_gfxram[ y | x | ra];
						/* Display 6 pixels in normal region */
						fg = (gfx & 0x38) >> 3;
						*p++ = fg;
						*p++ = fg;
						*p++ = fg;
						fg = gfx & 0x07;
						*p++ = fg;
						*p++ = fg;
						*p++ = fg;
					}
				}
			}
			break;

		case 0x30:                  // MODE 3
			/* the manual does not explain at all how colour is determined
			    for the extended area. Further, the background colour
			    is not mentioned anywhere. Black is assumed. */
			for (y = 0; y < 0x400; y+=0x40)
			{
				for (ra = 0; ra < 0x3000; ra+=0x400)
				{
					uint16_t *p = &bitmap.pix16(sy++);

					for (x = 0; x < 0x40; x++)
					{
						gfx = m_p_gfxram[ y | x | ra];
						fg = (m_p_videoram[ 0x3c00 | x | y ] & 0x38) >> 3;
						/* Display 6 pixels in normal region */
						*p++ = BIT(gfx, 0) ? fg : bg;
						*p++ = BIT(gfx, 1) ? fg : bg;
						*p++ = BIT(gfx, 2) ? fg : bg;
						fg = m_p_videoram[ 0x3c00 | x | y ] & 0x07;
						*p++ = BIT(gfx, 3) ? fg : bg;
						*p++ = BIT(gfx, 4) ? fg : bg;
						*p++ = BIT(gfx, 5) ? fg : bg;
					}

					for (x = 0; x < 0x10; x++)
					{
						gfx = m_p_gfxram[ 0x3000 | x | (ra & 0xc00) | ((ra & 0x3000) >> 8)];
						fg = (m_p_gfxram[ 0x3c00 | x | y ] & 0x38) >> 3;
						/* Display 6 pixels in extended region */
						*p++ = BIT(gfx, 0) ? fg : bg;
						*p++ = BIT(gfx, 1) ? fg : bg;
						*p++ = BIT(gfx, 2) ? fg : bg;
						fg = m_p_gfxram[ 0x3c00 | x | y ] & 0x07;
						*p++ = BIT(gfx, 3) ? fg : bg;
						*p++ = BIT(gfx, 4) ? fg : bg;
						*p++ = BIT(gfx, 5) ? fg : bg;
					}
				}
			}
			break;
	}
	return 0;
}

/* lores characters are in the character generator. Each character is 8x16. */
uint32_t trs80_state::screen_update_radionic(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	uint8_t y,ra,chr,gfx;
	uint16_t sy=0,ma=0,x;
	uint8_t cols = BIT(m_mode, 0) ? 32 : 64;
	uint8_t skip = BIT(m_mode, 0) ? 2 : 1;

	if (m_mode != m_size_store)
	{
		m_size_store = m_mode & 1;
		screen.set_visible_area(0, cols*8-1, 0, 16*16-1);
	}

	for (y = 0; y < 16; y++)
	{
		for (ra = 0; ra < 16; ra++)
		{
			uint16_t *p = &bitmap.pix16(sy++);

			for (x = ma; x < ma + 64; x+=skip)
			{
				chr = m_p_videoram[x];

				/* get pattern of pixels for that character scanline */
				gfx = m_p_chargen[(chr<<3) | (ra & 7) | (ra & 8) << 8];

				/* Display a scanline of a character (8 pixels) */
				*p++ = BIT(gfx, 0);
				*p++ = BIT(gfx, 1);
				*p++ = BIT(gfx, 2);
				*p++ = BIT(gfx, 3);
				*p++ = BIT(gfx, 4);
				*p++ = BIT(gfx, 5);
				*p++ = BIT(gfx, 6);
				*p++ = BIT(gfx, 7);
			}
		}
		ma+=64;
	}
	return 0;
}

uint32_t trs80_state::screen_update_meritum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
/* lores characters are in the character generator. Each character is 6x11. */
{
	uint8_t y,ra,chr,gfx;
	uint16_t sy=0,ma=0,x;
	uint8_t cols = BIT(m_mode, 0) ? 32 : 64;
	uint8_t skip = BIT(m_mode, 0) ? 2 : 1;

	if (m_mode != m_size_store)
	{
		m_size_store = m_mode;
		screen.set_visible_area(0, cols*6-1, 0, 16*11-1);
	}

	for (y = 0; y < 16; y++)
	{
		for (ra = 0; ra < 11; ra++)
		{
			uint16_t *p = &bitmap.pix16(sy++);

			for (x = ma; x < ma + 64; x+=skip)
			{
				chr = m_p_videoram[x];

				/* get pattern of pixels for that character scanline */
				gfx = m_p_chargen[(chr<<4) | ra];

				/* Display a scanline of a character (6 pixels) */
				*p++ = BIT(gfx, 5);
				*p++ = BIT(gfx, 4);
				*p++ = BIT(gfx, 3);
				*p++ = BIT(gfx, 2);
				*p++ = BIT(gfx, 1);
				*p++ = BIT(gfx, 0);
			}
		}
		ma+=64;
	}
	return 0;
}



/***************************************************************************
  Write to video ram
***************************************************************************/

READ8_MEMBER( trs80_state::trs80_videoram_r )
{
	if ((m_mode & 0x80) && (~m_model4 & 1)) offset |= 0x400;
	return m_p_videoram[offset];
}

WRITE8_MEMBER( trs80_state::trs80_videoram_w )
{
	if ((m_mode & 0x80) && (~m_model4 & 1)) offset |= 0x400;
	m_p_videoram[offset] = data;
}


/***************************************************************************
  Write to graphics ram
***************************************************************************/

READ8_MEMBER( trs80_state::trs80_gfxram_r )
{
	return m_p_gfxram[offset];
}

WRITE8_MEMBER( trs80_state::trs80_gfxram_w )
{
	m_p_gfxram[offset] = data;
}


/***************************************************************************
  Palettes
***************************************************************************/

/* Levels are unknown - guessing */
static const rgb_t lnw80_palette[] =
{
	rgb_t(220, 220, 220), // white
	rgb_t(0, 175, 0), // green
	rgb_t(200, 200, 0), // yellow
	rgb_t(255, 0, 0), // red
	rgb_t(255, 0, 255), // magenta
	rgb_t(0, 0, 175), // blue
	rgb_t(0, 255, 255), // cyan
	rgb_t(0, 0, 0), // black
};

PALETTE_INIT_MEMBER(trs80_state,lnw80)
{
	palette.set_pen_colors(0, lnw80_palette, ARRAY_LENGTH(lnw80_palette));
}