summaryrefslogtreecommitdiffstatshomepage
path: root/scripts/src/cpu.lua
diff options
context:
space:
mode:
author fulivi <fulivi@users.noreply.github.com>2016-11-03 14:51:40 +0100
committer fulivi <fulivi@users.noreply.github.com>2016-11-03 14:52:42 +0100
commitf60621bbd443493b0e24aad355482ec77f781a9c (patch)
treef00802ff07148fe56e42e2813ce3c554c07d22e3 /scripts/src/cpu.lua
parent18d72a5cec6472e3bf303959b264f224968c305f (diff)
hp9845: minor fix to graphic video subsystem
Diffstat (limited to 'scripts/src/cpu.lua')
0 files changed, 0 insertions, 0 deletions
1 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
/*
    video/crt.c

    CRT video emulation for TX-0 and PDP-1.


Theory of operation:

    What makes such CRT devices so odd is that there is no video processor, no
    scan logic, no refresh logic.  The beam position and intensity is
    controlled by the program completely: in order to draw an object, the
    program must direct the beam to each point of the object, and in order to
    refresh it, the program must redraw the object periodically.

    Since the refresh rates are highly variable (completely controlled by the
    program), I need to simulate CRT remanence: the intensity of each pixel on
    display decreases regularly.  In order to keep this efficient, I keep a
    list of non-black pixels, and only process these pixels on each refresh.
    In order to improve efficiency further, I keep a distinct list for each
    line of the display: I have found that it improves drawing speed slightly
    (probably because it improves the cache hit rate).


    Raphael Nabet 2002-2004
    Based on earlier work by Chris Salomon
*/

#include <math.h>
#include "emu.h"
#include "video/crt.h"


// special value that tells that the node is not in list
enum
{
	intensity_pixel_not_in_list = -1
};


// device type definition
const device_type CRT = &device_creator<crt_device>;

//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  crt_device - constructor
//-------------------------------------------------

crt_device::crt_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
	: device_t(mconfig, CRT, "CRT Video", tag, owner, clock),
	  m_list(NULL),
	  m_list_head(NULL),
	  m_decay_counter(0),
	  m_num_intensity_levels(0),
	  m_window_offset_x(0),
      m_window_offset_y(0),
	  m_window_width(0),
      m_window_height(0)
{
}


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

void crt_device::device_start()
{
	const crt_interface *intf = (const crt_interface *)static_config();
	int width = intf->width;
	int height = intf->height;
	int i;

	m_num_intensity_levels = intf->num_levels;
	m_window_offset_x = intf->offset_x;
	m_window_offset_y = intf->offset_y;
	m_window_width = width;
	m_window_height = height;

	/* alloc the arrays */
	m_list = auto_alloc_array(machine(), crt_point, width * height);

	m_list_head = auto_alloc_array(machine(), int, height);

	/* fill with black and set up list as empty */
	for (i=0; i<(width * height); i++)
	{
		m_list[i].intensity = intensity_pixel_not_in_list;
	}

	for (i=0; i<height; i++)
		m_list_head[i] = -1;

	m_decay_counter = 0;
}


//
//    crt_plot
//
//    schedule a pixel to be plotted
//
void crt_device::plot(int x, int y)
{
	crt_point *node;
	int list_index;

	/* compute pixel coordinates */
	if (x<0) x=0;
	if (y<0) y=0;
	if ((x>(m_window_width-1)) || ((y>m_window_height-1)))
		return;
	y = (m_window_height-1) - y;

	/* find entry in list */
	list_index = x + y*m_window_width;

	node = &m_list[list_index];

	if (node->intensity == intensity_pixel_not_in_list)
	{   /* insert node in list if it is not in it */
		node->next = m_list_head[y];
		m_list_head[y] = list_index;
	}
	/* set intensity */
	node->intensity = m_num_intensity_levels;
}


//
//  crt_eof
//
//  keep track of time
//
void crt_device::eof()
{
	m_decay_counter++;
}


//
//  crt_update
//
//  update the bitmap
//
void crt_device::update(bitmap_ind16 &bitmap)
{
	int i, p_i;
	int y;

	//if (m_decay_counter)
	{
		/* some time has elapsed: let's update the screen */
		for (y=0; y<m_window_height; y++)
		{
			UINT16 *line = &bitmap.pix16(y+m_window_offset_y);

			p_i = -1;

			for (i=m_list_head[y]; (i != -1); i=m_list[i].next)
			{
				crt_point *node = &m_list[i];
				int x = (i % m_window_width) + m_window_offset_x;

				if (node->intensity == m_num_intensity_levels)
					/* new pixel: set to max intensity */
					node->intensity = m_num_intensity_levels-1;
				else
				{
					/* otherwise, apply intensity decay */
					node->intensity -= m_decay_counter;
					if (node->intensity < 0)
						node->intensity = 0;
				}

				/* draw pixel on screen */
				//plot_pixel(bitmap, x, y+m_window_offset_y, node->intensity);
				line[x] = node->intensity;

				if (node->intensity != 0)
					p_i = i;    /* current node will be next iteration's previous node */
				else
				{   /* delete current node */
					node->intensity = intensity_pixel_not_in_list;
					if (p_i != -1)
						m_list[p_i].next = node->next;
					else
						m_list_head[y] = node->next;
				}
			}
		}

		m_decay_counter = 0;
	}
}