summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/nick.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/nick.c')
-rw-r--r--src/mame/video/nick.c1055
1 files changed, 1055 insertions, 0 deletions
diff --git a/src/mame/video/nick.c b/src/mame/video/nick.c
new file mode 100644
index 00000000000..afb16ff815b
--- /dev/null
+++ b/src/mame/video/nick.c
@@ -0,0 +1,1055 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Intelligent Designs NICK emulation
+
+**********************************************************************/
+
+#include "nick.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+/* colour mode types */
+#define NICK_2_COLOUR_MODE 0
+#define NICK_4_COLOUR_MODE 1
+#define NICK_16_COLOUR_MODE 2
+#define NICK_256_COLOUR_MODE 3
+
+/* Display mode types */
+#define NICK_VSYNC_MODE 0
+#define NICK_PIXEL_MODE 1
+#define NICK_ATTR_MODE 2
+#define NICK_CH256_MODE 3
+#define NICK_CH128_MODE 4
+#define NICK_CH64_MODE 5
+#define NICK_UNUSED_MODE 6
+#define NICK_LPIXEL_MODE 7
+
+/* MODEBYTE defines */
+#define NICK_MB_VIRQ (1<<7)
+#define NICK_MB_VRES (1<<4)
+#define NICK_MB_LPT_RELOAD (1<<0)
+
+/* Left margin defines */
+#define NICK_LM_MSBALT (1<<7)
+#define NICK_LM_LSBALT (1<<6)
+
+/* Right margin defines */
+#define NICK_RM_ALTIND1 (1<<7)
+#define NICK_RM_ALTIND0 (1<<6)
+
+/* useful macros */
+#define NICK_GET_LEFT_MARGIN(x) (x & 0x03f)
+#define NICK_GET_RIGHT_MARGIN(x) (x & 0x03f)
+#define NICK_GET_DISPLAY_MODE(x) ((x>>1) & 0x07)
+#define NICK_GET_COLOUR_MODE(x) ((x>>5) & 0x03)
+
+#define NICK_RELOAD_LPT(x) (x & 0x080)
+#define NICK_CLOCK_LPT(x) (x & 0x040)
+
+/* Macros to generate memory address is CHx modes */
+/* x = LD2, y = buf1 */
+#define ADDR_CH256(x,y) (((x & 0x0ff)<<8) | (y & 0x0ff))
+#define ADDR_CH128(x,y) (((x & 0x01ff)<<7) | (y & 0x07f))
+#define ADDR_CH64(x,y) (((x & 0x03ff)<<6) | (y & 0x03f))
+
+/* No of highest resolution pixels per "clock" */
+#define NICK_PIXELS_PER_CLOCK 16
+
+/* "clocks" per line */
+#define NICK_TOTAL_CLOCKS_PER_LINE 64
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NICK = &device_creator<nick_device>;
+
+
+DEVICE_ADDRESS_MAP_START( vram_map, 8, nick_device )
+ AM_RANGE(0x0000, 0xffff) AM_READWRITE(vram_r, vram_w)
+ADDRESS_MAP_END
+
+DEVICE_ADDRESS_MAP_START( vio_map, 8, nick_device )
+ AM_RANGE(0x00, 0x00) AM_WRITE(fixbias_w)
+ AM_RANGE(0x01, 0x01) AM_WRITE(border_w)
+ AM_RANGE(0x02, 0x02) AM_WRITE(lpl_w)
+ AM_RANGE(0x03, 0x03) AM_WRITE(lph_w)
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START( nick_map, AS_0, 8, nick_device )
+ AM_RANGE(0x0000, 0xffff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nick_device - constructor
+//-------------------------------------------------
+
+nick_device::nick_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, NICK, "NICK", tag, owner, clock, "nick", __FILE__),
+ device_memory_interface(mconfig, *this),
+ device_video_interface(mconfig, *this),
+ m_space_config("vram", ENDIANNESS_LITTLE, 8, 16, 0, *ADDRESS_MAP_NAME(nick_map)),
+ m_write_virq(*this),
+ horizontal_clock(0),
+ m_scanline_count(0),
+ m_FIXBIAS(0),
+ m_BORDER(0),
+ m_LPL(0),
+ m_LPH(0),
+ m_LD1(0),
+ m_LD2(0),
+ m_virq(CLEAR_LINE)
+{
+ memset(&m_LPT, 0x00, sizeof(m_LPT));
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void nick_device::device_start()
+{
+ m_screen->register_screen_bitmap(m_bitmap);
+ calc_visible_clocks(ENTERPRISE_SCREEN_WIDTH);
+
+ // initialize palette
+ initialize_palette();
+
+ // resolve callbacks
+ m_write_virq.resolve_safe();
+
+ // allocate timers
+ m_timer_scanline = timer_alloc();
+ m_timer_scanline->adjust(m_screen->time_until_pos(0, 0), 0, m_screen->scan_period());
+
+ // state saving
+ save_item(NAME(m_scanline_count));
+ save_item(NAME(m_FIXBIAS));
+ save_item(NAME(m_BORDER));
+ save_item(NAME(m_LPL));
+ save_item(NAME(m_LPH));
+ save_item(NAME(m_LD1));
+ save_item(NAME(m_LD2));
+ save_item(NAME(m_LPT.SC));
+ save_item(NAME(m_LPT.MB));
+ save_item(NAME(m_LPT.LM));
+ save_item(NAME(m_LPT.RM));
+ save_item(NAME(m_LPT.LD1L));
+ save_item(NAME(m_LPT.LD1H));
+ save_item(NAME(m_LPT.LD2L));
+ save_item(NAME(m_LPT.LD2H));
+ save_item(NAME(m_LPT.COL));
+ save_item(NAME(m_dest_pos));
+ save_item(NAME(m_dest_max_pos));
+ save_item(NAME(m_reg));
+ save_item(NAME(m_first_visible_clock));
+ save_item(NAME(m_last_visible_clock));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void nick_device::device_reset()
+{
+ m_write_virq(CLEAR_LINE);
+ m_virq = 0;
+
+ m_scanline_count = 0;
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void nick_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ int scanline = m_screen->vpos();
+
+ if (scanline < ENTERPRISE_SCREEN_HEIGHT)
+ {
+ /* set write address for line */
+ m_dest = &m_bitmap.pix32(scanline);
+ m_dest_pos = 0;
+ m_dest_max_pos = m_bitmap.width();
+
+ /* write line */
+ do_line();
+ }
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *nick_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == 0) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// update_screen - update screen
+//-------------------------------------------------
+
+UINT32 nick_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// vram_r - video RAM read
+//-------------------------------------------------
+
+READ8_MEMBER( nick_device::vram_r )
+{
+ return this->space().read_byte(offset);
+}
+
+
+//-------------------------------------------------
+// vram_w - video RAM write
+//-------------------------------------------------
+
+WRITE8_MEMBER( nick_device::vram_w )
+{
+ this->space().write_byte(offset, data);
+}
+
+
+//-------------------------------------------------
+// fixbias_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( nick_device::fixbias_w )
+{
+ m_FIXBIAS = data;
+}
+
+
+//-------------------------------------------------
+// border_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( nick_device::border_w )
+{
+ m_BORDER = data;
+}
+
+
+//-------------------------------------------------
+// lpl_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( nick_device::lpl_w )
+{
+ m_LPL = m_reg[2] = data;
+
+ update_lpt();
+}
+
+
+//-------------------------------------------------
+// lph_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( nick_device::lph_w )
+{
+ m_LPH = m_reg[3] = data;
+
+ update_lpt();
+}
+
+
+//-------------------------------------------------
+// initialize_palette -
+//-------------------------------------------------
+
+void nick_device::initialize_palette()
+{
+ const int resistances_rg[] = { (int) RES_R(470), (int) RES_R(220), (int) RES_R(100) };
+ const int resistances_b[] = { (int) RES_R(220), (int) RES_R(82) };
+
+ double color_weights_rg[3], color_weights_b[2];
+
+ compute_resistor_weights(0, 0xff, -1.0,
+ 3, resistances_rg, color_weights_rg, 0, 0,
+ 2, resistances_b, color_weights_b, 0, 0,
+ 0, 0, 0, 0, 0);
+
+ for (int i = 0; i < 256; i++)
+ {
+ /*
+
+ bit description
+
+ PC0 100R -- RED
+ PC1 100R -- GREEN
+ PC2 82R -- BLUE
+ PC3 220R -- RED
+ PC4 220R -- GREEN
+ PC5 220R -- BLUE
+ PC6 470R -- RED
+ PC7 470R -- GREEN
+
+ */
+
+ int ra = BIT(i, 0);
+ int rb = BIT(i, 3);
+ int rc = BIT(i, 6);
+
+ int ga = BIT(i, 1);
+ int gb = BIT(i, 4);
+ int gc = BIT(i, 7);
+
+ int ba = BIT(i, 2);
+ int bb = BIT(i, 5);
+
+ UINT8 r = combine_3_weights(color_weights_rg, rc, rb, ra);
+ UINT8 g = combine_3_weights(color_weights_rg, gc, gb, ga);
+ UINT8 b = combine_2_weights(color_weights_b, bb, ba);
+
+ m_palette[i] = rgb_t(r, g, b);
+ }
+
+ for (int i = 0; i < 256; i++)
+ {
+ int pen_index;
+
+ pen_index = (BIT(i, 7) << 0) | (BIT(i, 3) << 1);
+ m_pen_idx_4col[i] = pen_index;
+
+ pen_index = (BIT(i, 7) << 0) | (BIT(i, 3) << 1) | (BIT(i, 5) << 2) | (BIT(i, 1) << 3);
+ m_pen_idx_16col[i] = pen_index;
+ }
+}
+
+// MESS specific
+/* 8-bit pixel write! */
+void nick_device::write_pixel(int ci)
+{
+ if (m_dest_pos < m_dest_max_pos)
+ {
+ m_dest[m_dest_pos++] = m_palette[ci];
+ }
+}
+
+/* we align based on the clocks */
+void nick_device::calc_visible_clocks(int width)
+{
+ /* number of clocks we can see */
+ int no_visible_clocks = width / NICK_PIXELS_PER_CLOCK;
+ m_first_visible_clock = (NICK_TOTAL_CLOCKS_PER_LINE - no_visible_clocks) >> 1;
+ m_last_visible_clock = m_first_visible_clock + no_visible_clocks;
+}
+
+
+/* write border colour */
+void nick_device::write_border(int clocks)
+{
+ int col_index = m_BORDER;
+
+ for (int i = 0; i < (clocks << 4); i++)
+ write_pixel(col_index);
+}
+
+
+void nick_device::do_left_margin()
+{
+ UINT8 left = NICK_GET_LEFT_MARGIN(m_LPT.LM);
+
+ if (left > m_first_visible_clock)
+ {
+ /* some of the left margin is visible */
+ UINT8 left_visible = left - m_first_visible_clock;
+
+ /* render the border */
+ write_border(left_visible);
+ }
+}
+
+void nick_device::do_right_margin()
+{
+ UINT8 right = NICK_GET_RIGHT_MARGIN(m_LPT.RM);
+
+ if (right < m_last_visible_clock)
+ {
+ /* some of the right margin is visible */
+ UINT8 right_visible = m_last_visible_clock - right;
+
+ /* render the border */
+ write_border(right_visible);
+ }
+}
+
+int nick_device::get_color_index(int pen_index)
+{
+ if (pen_index & 0x08)
+ return ((m_FIXBIAS & 0x01f) << 3) | (pen_index & 0x07);
+ else
+ return m_LPT.COL[pen_index];
+}
+
+void nick_device::write_pixels2color(UINT8 pen0, UINT8 pen1, UINT8 data_byte)
+{
+ int col_index[2];
+ int pen_index;
+ UINT8 data = data_byte;
+
+ col_index[0] = get_color_index(pen0);
+ col_index[1] = get_color_index(pen1);
+
+ for (int i = 0; i < 8; i++)
+ {
+ pen_index = col_index[BIT(data, 7)];
+ write_pixel(pen_index);
+ data <<= 1;
+ }
+}
+
+void nick_device::write_pixels2color_lpixel(UINT8 pen0, UINT8 pen1, UINT8 data_byte)
+{
+ int col_index[2];
+ int pen_index;
+ UINT8 data = data_byte;
+
+ col_index[0] = get_color_index(pen0);
+ col_index[1] = get_color_index(pen1);
+
+ for (int i = 0; i < 8; i++)
+ {
+ pen_index = col_index[BIT(data, 7)];
+ write_pixel(pen_index);
+ write_pixel(pen_index);
+ data <<= 1;
+ }
+}
+
+
+void nick_device::write_pixels(UINT8 data_byte, UINT8 char_idx)
+{
+ /* pen index colour 2-C (0,1), 4-C (0..3) 16-C (0..16) */
+ int pen_idx;
+ /* Col index = EP colour value */
+ int pal_idx;
+ UINT8 color_mode = NICK_GET_COLOUR_MODE(m_LPT.MB);
+ UINT8 data = data_byte;
+
+ switch (color_mode)
+ {
+ case NICK_2_COLOUR_MODE:
+ {
+ int pen_offs = 0;
+
+ /* do before displaying byte */
+
+ /* left margin attributes */
+ if (m_LPT.LM & NICK_LM_MSBALT)
+ {
+ if (data & 0x080)
+ {
+ pen_offs |= 2;
+ }
+
+ data &=~0x080;
+ }
+
+ if (m_LPT.LM & NICK_LM_LSBALT)
+ {
+ if (data & 0x001)
+ {
+ pen_offs |= 4;
+ }
+
+ data &=~0x01;
+ }
+
+ if (m_LPT.RM & NICK_RM_ALTIND1)
+ {
+ if (char_idx & 0x080)
+ {
+ pen_offs |= 0x02;
+ }
+ }
+
+#if 0
+ if (m_LPT.RM & NICK_RM_ALTIND0)
+ {
+ if (data & 0x040)
+ {
+ pen_offs |= 0x04;
+ }
+ }
+#endif
+
+
+ write_pixels2color(pen_offs, (pen_offs | 0x01), data);
+ }
+ break;
+
+ case NICK_4_COLOUR_MODE:
+ {
+ //osd_printf_info("4 colour\r\n");
+
+ /* left margin attributes */
+ if (m_LPT.LM & NICK_LM_MSBALT)
+ {
+ data &= ~0x080;
+ }
+
+ if (m_LPT.LM & NICK_LM_LSBALT)
+ {
+ data &= ~0x01;
+ }
+
+
+ for (int i = 0; i < 4; i++)
+ {
+ pen_idx = m_pen_idx_4col[data];
+ pal_idx = m_LPT.COL[pen_idx & 0x03];
+
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+
+ data <<= 1;
+ }
+ }
+ break;
+
+ case NICK_16_COLOUR_MODE:
+ {
+ //osd_printf_info("16 colour\r\n");
+
+ /* left margin attributes */
+ if (m_LPT.LM & NICK_LM_MSBALT)
+ {
+ data &= ~0x080;
+ }
+
+ if (m_LPT.LM & NICK_LM_LSBALT)
+ {
+ data &= ~0x01;
+ }
+
+
+ for (int i = 0; i < 2; i++)
+ {
+ pen_idx = m_pen_idx_16col[data];
+
+ pal_idx = get_color_index(pen_idx);
+
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+
+ data <<= 1;
+ }
+ }
+ break;
+
+ case NICK_256_COLOUR_MODE:
+ {
+ /* left margin attributes */
+ if (m_LPT.LM & NICK_LM_MSBALT)
+ {
+ data &= ~0x080;
+ }
+
+ if (m_LPT.LM & NICK_LM_LSBALT)
+ {
+ data &= ~0x01;
+ }
+
+
+ pal_idx = data;
+
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+
+
+ }
+ break;
+ }
+}
+
+void nick_device::write_pixels_lpixel(UINT8 data_byte, UINT8 char_idx)
+{
+ /* pen index colour 2-C (0,1), 4-C (0..3) 16-C (0..16) */
+ int pen_idx;
+ /* Col index = EP colour value */
+ int pal_idx;
+ UINT8 color_mode = NICK_GET_COLOUR_MODE(m_LPT.MB);
+ UINT8 data = data_byte;
+
+ switch (color_mode)
+ {
+ case NICK_2_COLOUR_MODE:
+ {
+ int pen_offs = 0;
+
+ /* do before displaying byte */
+
+ /* left margin attributes */
+ if (m_LPT.LM & NICK_LM_MSBALT)
+ {
+ if (data & 0x080)
+ {
+ pen_offs |= 2;
+ }
+
+ data &=~0x080;
+ }
+
+ if (m_LPT.LM & NICK_LM_LSBALT)
+ {
+ if (data & 0x001)
+ {
+ pen_offs |= 4;
+ }
+
+ data &=~0x01;
+ }
+
+ if (m_LPT.RM & NICK_RM_ALTIND1)
+ {
+ if (char_idx & 0x080)
+ {
+ pen_offs |= 0x02;
+ }
+ }
+
+#if 0
+ if (m_LPT.RM & NICK_RM_ALTIND0)
+ {
+ if (data & 0x040)
+ {
+ pen_offs |= 0x04;
+ }
+ }
+#endif
+
+
+ write_pixels2color_lpixel(pen_offs, (pen_offs | 0x01), data);
+ }
+ break;
+
+ case NICK_4_COLOUR_MODE:
+ {
+ //osd_printf_info("4 colour\r\n");
+
+ /* left margin attributes */
+ if (m_LPT.LM & NICK_LM_MSBALT)
+ {
+ data &= ~0x080;
+ }
+
+ if (m_LPT.LM & NICK_LM_LSBALT)
+ {
+ data &= ~0x01;
+ }
+
+
+ for (int i = 0; i < 4; i++)
+ {
+ pen_idx = m_pen_idx_4col[data];
+ pal_idx = m_LPT.COL[pen_idx & 0x03];
+
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+
+ data <<= 1;
+ }
+ }
+ break;
+
+ case NICK_16_COLOUR_MODE:
+ {
+ //osd_printf_info("16 colour\r\n");
+
+ /* left margin attributes */
+ if (m_LPT.LM & NICK_LM_MSBALT)
+ {
+ data &= ~0x080;
+ }
+
+ if (m_LPT.LM & NICK_LM_LSBALT)
+ {
+ data &= ~0x01;
+ }
+
+
+ for (int i = 0; i < 2; i++)
+ {
+ pen_idx = m_pen_idx_16col[data];
+ pal_idx = get_color_index(pen_idx);
+
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+
+ data <<= 1;
+ }
+ }
+ break;
+
+ case NICK_256_COLOUR_MODE:
+ {
+ /* left margin attributes */
+ if (m_LPT.LM & NICK_LM_MSBALT)
+ {
+ data &= ~0x080;
+ }
+
+ if (m_LPT.LM & NICK_LM_LSBALT)
+ {
+ data &= ~0x01;
+ }
+
+
+ pal_idx = data;
+
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+ write_pixel(pal_idx);
+
+
+ }
+ break;
+ }
+}
+
+
+void nick_device::do_pixel(int clocks_visible)
+{
+ UINT8 buf1, buf2;
+
+ for (int i = 0; i < clocks_visible; i++)
+ {
+ buf1 = space().read_byte(m_LD1);
+ m_LD1++;
+
+ buf2 = space().read_byte(m_LD1);
+ m_LD1++;
+
+ write_pixels(buf1, buf1);
+ write_pixels(buf2, buf1);
+ }
+}
+
+
+void nick_device::do_lpixel(int clocks_visible)
+{
+ UINT8 buf1;
+
+ for (int i = 0; i < clocks_visible; i++)
+ {
+ buf1 = space().read_byte(m_LD1);
+ m_LD1++;
+
+ write_pixels_lpixel(buf1, buf1);
+ }
+}
+
+void nick_device::do_attr(int clocks_visible)
+{
+ UINT8 buf1, buf2;
+
+ for (int i = 0; i < clocks_visible; i++)
+ {
+ buf1 = space().read_byte(m_LD1);
+ m_LD1++;
+
+ buf2 = space().read_byte(m_LD2);
+ m_LD2++;
+
+ {
+ UINT8 bg_color = ((buf1 >> 4) & 0x0f);
+ UINT8 fg_color = (buf1 & 0x0f);
+
+ write_pixels2color_lpixel(bg_color, fg_color, buf2);
+ }
+ }
+}
+
+void nick_device::do_ch256(int clocks_visible)
+{
+ UINT8 buf1, buf2;
+
+ for (int i = 0; i < clocks_visible; i++)
+ {
+ buf1 = space().read_byte(m_LD1);
+ m_LD1++;
+ buf2 = space().read_byte(ADDR_CH256(m_LD2, buf1));
+
+ write_pixels_lpixel(buf2, buf1);
+ }
+}
+
+void nick_device::do_ch128(int clocks_visible)
+{
+ UINT8 buf1, buf2;
+
+ for (int i = 0; i < clocks_visible; i++)
+ {
+ buf1 = space().read_byte(m_LD1);
+ m_LD1++;
+ buf2 = space().read_byte(ADDR_CH128(m_LD2, buf1));
+
+ write_pixels_lpixel(buf2, buf1);
+ }
+}
+
+void nick_device::do_ch64(int clocks_visible)
+{
+ UINT8 buf1, buf2;
+
+ for (int i = 0; i < clocks_visible; i++)
+ {
+ buf1 = space().read_byte(m_LD1);
+ m_LD1++;
+ buf2 = space().read_byte(ADDR_CH64(m_LD2, buf1));
+
+ write_pixels_lpixel(buf2, buf1);
+ }
+}
+
+
+void nick_device::do_display()
+{
+ LPT_ENTRY *pLPT = &m_LPT;
+ UINT8 clocks_visible;
+ UINT8 right_margin = NICK_GET_RIGHT_MARGIN(pLPT->RM);
+ UINT8 left_margin = NICK_GET_LEFT_MARGIN(pLPT->LM);
+
+ clocks_visible = right_margin - left_margin;
+
+ if (clocks_visible)
+ {
+ /* get display mode */
+ UINT8 display_mode = NICK_GET_DISPLAY_MODE(pLPT->MB);
+
+ if (m_scanline_count == 0) // ||
+ //((pLPT->MB & NICK_MB_VRES)==0))
+ {
+ /* doing first line */
+ /* reload LD1, and LD2 (if necessary) regardless of display mode */
+ m_LD1 = (pLPT->LD1L & 0xff) | ((pLPT->LD1H & 0xff) << 8);
+
+ if ((display_mode != NICK_LPIXEL_MODE) && (display_mode != NICK_PIXEL_MODE))
+ {
+ /* lpixel and pixel modes don't use LD2 */
+ m_LD2 = (pLPT->LD2L & 0xff) | ((pLPT->LD2H & 0xff) << 8);
+ }
+ }
+ else
+ {
+ /* not first line */
+ switch (display_mode)
+ {
+ case NICK_ATTR_MODE:
+ {
+ /* reload LD1 */
+ m_LD1 = (pLPT->LD1L & 0xff) | ((pLPT->LD1H & 0xff) << 8);
+ }
+ break;
+
+ case NICK_CH256_MODE:
+ case NICK_CH128_MODE:
+ case NICK_CH64_MODE:
+ {
+ /* reload LD1 */
+ m_LD1 = (pLPT->LD1L & 0xff) | ((pLPT->LD1H & 0xff) << 8);
+ m_LD2++;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ switch (display_mode)
+ {
+ case NICK_PIXEL_MODE:
+ {
+ do_pixel(clocks_visible);
+ }
+ break;
+
+ case NICK_ATTR_MODE:
+ {
+ //osd_printf_info("attr mode\r\n");
+ do_attr(clocks_visible);
+ }
+ break;
+
+ case NICK_CH256_MODE:
+ {
+ //osd_printf_info("ch256 mode\r\n");
+ do_ch256(clocks_visible);
+ }
+ break;
+
+ case NICK_CH128_MODE:
+ {
+ do_ch128(clocks_visible);
+ }
+ break;
+
+ case NICK_CH64_MODE:
+ {
+ //osd_printf_info("ch64 mode\r\n");
+ do_ch64(clocks_visible);
+ }
+ break;
+
+ case NICK_LPIXEL_MODE:
+ {
+ do_lpixel(clocks_visible);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void nick_device::update_lpt()
+{
+ UINT16 CurLPT = (m_LPL & 0x0ff) | ((m_LPH & 0x0f) << 8);
+ CurLPT++;
+ m_LPL = CurLPT & 0x0ff;
+ m_LPH = (m_LPH & 0x0f0) | ((CurLPT >> 8) & 0x0f);
+}
+
+
+void nick_device::reload_lpt()
+{
+ /* get addr of LPT */
+ UINT32 LPT_Addr = ((m_LPL & 0x0ff) << 4) | ((m_LPH & 0x0f) << (8+4));
+
+ /* update internal LPT state */
+ m_LPT.SC = space().read_byte(LPT_Addr);
+ m_LPT.MB = space().read_byte(LPT_Addr + 1);
+ m_LPT.LM = space().read_byte(LPT_Addr + 2);
+ m_LPT.RM = space().read_byte(LPT_Addr + 3);
+ m_LPT.LD1L = space().read_byte(LPT_Addr + 4);
+ m_LPT.LD1H = space().read_byte(LPT_Addr + 5);
+ m_LPT.LD2L = space().read_byte(LPT_Addr + 6);
+ m_LPT.LD2H = space().read_byte(LPT_Addr + 7);
+ m_LPT.COL[0] = space().read_byte(LPT_Addr + 8);
+ m_LPT.COL[1] = space().read_byte(LPT_Addr + 9);
+ m_LPT.COL[2] = space().read_byte(LPT_Addr + 10);
+ m_LPT.COL[3] = space().read_byte(LPT_Addr + 11);
+ m_LPT.COL[4] = space().read_byte(LPT_Addr + 12);
+ m_LPT.COL[5] = space().read_byte(LPT_Addr + 13);
+ m_LPT.COL[6] = space().read_byte(LPT_Addr + 14);
+ m_LPT.COL[7] = space().read_byte(LPT_Addr + 15);
+}
+
+/* call here to render a line of graphics */
+void nick_device::do_line()
+{
+ UINT8 scanline;
+
+ m_write_virq((m_LPT.MB & NICK_MB_VIRQ) ? ASSERT_LINE : CLEAR_LINE);
+
+ if (m_virq && !(m_LPT.MB & NICK_MB_VIRQ))
+ {
+ m_timer_scanline->adjust(m_screen->time_until_pos(0, 0), 0, m_screen->scan_period());
+ }
+
+ m_virq = (m_LPT.MB & NICK_MB_VIRQ) ? 1 : 0;
+
+ if ((m_LPT.MB & NICK_MB_LPT_RELOAD)!=0)
+ {
+ /* reload LPT */
+
+ m_LPL = m_reg[2];
+ m_LPH = m_reg[3];
+
+ reload_lpt();
+ }
+
+ /* left border */
+ do_left_margin();
+
+ /* do visible part */
+ do_display();
+
+ /* right border */
+ do_right_margin();
+
+ // 0x0f7 is first!
+ /* scan line count for this LPT */
+ scanline = ((~m_LPT.SC) + 1) & 0x0ff;
+
+ //printf("scanline %02x\r\n", scanline);
+
+ /* update count of scanlines done so far */
+ m_scanline_count++;
+
+ if (m_scanline_count == scanline)
+ {
+ /* done all scanlines of this Line Parameter Table, get next */
+
+ m_scanline_count = 0;
+
+ update_lpt();
+ reload_lpt();
+ }
+}