summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/vic4567.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/vic4567.cpp')
-rw-r--r--src/devices/video/vic4567.cpp2055
1 files changed, 2055 insertions, 0 deletions
diff --git a/src/devices/video/vic4567.cpp b/src/devices/video/vic4567.cpp
new file mode 100644
index 00000000000..ca98279365b
--- /dev/null
+++ b/src/devices/video/vic4567.cpp
@@ -0,0 +1,2055 @@
+// license:BSD-3-Clause
+// copyright-holders:Peter Trauner
+/***************************************************************************
+
+ Video Interface Chip (4567)
+
+ original emulation by PeT (mess@utanet.at)
+
+ 2010-02: converted to be a device and split from vic II
+
+ TODO:
+ - plenty of cleanups
+ - emulate variants of the vic chip
+ - update vic III to use the new vic6567.c code for the vic II comaptibility
+
+***************************************************************************/
+
+#include "emu.h"
+#include "video/vic4567.h"
+
+/*****************************************************************************
+ CONSTANTS
+*****************************************************************************/
+
+#define VERBOSE_LEVEL 0
+#define DBG_LOG(N,M,A) \
+ do { \
+ if(VERBOSE_LEVEL >= N) \
+ { \
+ if( M ) \
+ logerror("%11.6f: %-24s", machine().time().as_double(), (char*) M ); \
+ logerror A; \
+ } \
+ } while (0)
+
+#define VREFRESHINLINES 28
+
+#define VIC2_YPOS 50
+#define RASTERLINE_2_C64(a) (a)
+#define C64_2_RASTERLINE(a) (a)
+#define XPOS (VIC2_STARTVISIBLECOLUMNS + (VIC2_VISIBLECOLUMNS - VIC2_HSIZE) / 2)
+#define YPOS (VIC2_STARTVISIBLELINES /* + (VIC2_VISIBLELINES - VIC2_VSIZE) / 2 */)
+#define FIRSTLINE 10 /* 36 ((VIC2_VISIBLELINES - VIC2_VSIZE)/2) */
+#define FIRSTCOLUMN 50
+
+/* 2008-05 FP: lightpen code needs to read input port from c64.c and cbmb.c */
+
+#define LIGHTPEN_BUTTON (m_lightpen_button_cb(0))
+#define LIGHTPEN_X_VALUE (m_lightpen_x_cb(0))
+#define LIGHTPEN_Y_VALUE (m_lightpen_y_cb(0))
+
+/* lightpen delivers values from internal counters; they do not start with the visual area or frame area */
+#define VIC2_MAME_XPOS 0
+#define VIC2_MAME_YPOS 0
+#define VIC6567_X_BEGIN 38
+#define VIC6567_Y_BEGIN -6 /* first 6 lines after retrace not for lightpen! */
+#define VIC6569_X_BEGIN 38
+#define VIC6569_Y_BEGIN -6
+#define VIC2_X_BEGIN ((m_type == VIC4567_PAL) ? VIC6569_X_BEGIN : VIC6567_X_BEGIN)
+#define VIC2_Y_BEGIN ((m_type == VIC4567_PAL) ? VIC6569_Y_BEGIN : VIC6567_Y_BEGIN)
+#define VIC2_X_VALUE ((LIGHTPEN_X_VALUE + VIC2_X_BEGIN + VIC2_MAME_XPOS) / 2)
+#define VIC2_Y_VALUE ((LIGHTPEN_Y_VALUE + VIC2_Y_BEGIN + VIC2_MAME_YPOS))
+
+#define VIC2E_K0_LEVEL (m_reg[0x2f] & 0x01)
+#define VIC2E_K1_LEVEL (m_reg[0x2f] & 0x02)
+#define VIC2E_K2_LEVEL (m_reg[0x2f] & 0x04)
+
+/*#define VIC3_P5_LEVEL (m_reg[0x30] & 0x20) */
+#define VIC3_BITPLANES (m_reg[0x31] & 0x10)
+#define VIC3_80COLUMNS (m_reg[0x31] & 0x80)
+#define VIC3_LINES ((m_reg[0x31] & 0x19) == 0x19 ? 400 : 200)
+#define VIC3_BITPLANES_WIDTH (m_reg[0x31] & 0x80 ? 640 : 320)
+
+/*#define VIC2E_TEST (vic2[0x30] & 2) */
+#define DOUBLE_CLOCK (m_reg[0x30] & 0x01)
+
+/* sprites 0 .. 7 */
+#define SPRITEON(nr) (m_reg[0x15] & (1 << nr))
+#define SPRITE_Y_EXPAND(nr) (m_reg[0x17] & (1 << nr))
+#define SPRITE_Y_SIZE(nr) (SPRITE_Y_EXPAND(nr) ? 2 * 21 : 21)
+#define SPRITE_X_EXPAND(nr) (m_reg[0x1d] & (1 << nr))
+#define SPRITE_X_SIZE(nr) (SPRITE_X_EXPAND(nr) ? 2 * 24 : 24)
+#define SPRITE_X_POS(nr) ((m_reg[(nr) * 2] | (m_reg[0x10] & (1 <<(nr)) ? 0x100 : 0)) - 24 + XPOS)
+#define SPRITE_X_POS2(nr) (m_reg[(nr) * 2] | (m_reg[0x10] & (1 <<(nr)) ? 0x100 : 0))
+#define SPRITE_Y_POS(nr) (m_reg[1+2*(nr)] - 50 + YPOS)
+#define SPRITE_Y_POS2(nr) (m_reg[1 + 2 *(nr)])
+#define SPRITE_MULTICOLOR(nr) (m_reg[0x1c] & (1 << nr))
+#define SPRITE_PRIORITY(nr) (m_reg[0x1b] & (1 << nr))
+#define SPRITE_MULTICOLOR1 (m_reg[0x25] & 0x0f)
+#define SPRITE_MULTICOLOR2 (m_reg[0x26] & 0x0f)
+#define SPRITE_COLOR(nr) (m_reg[0x27+nr] & 0x0f)
+#define SPRITE_ADDR(nr) (m_videoaddr | 0x3f8 | nr)
+#define SPRITE_BG_COLLISION(nr) (m_reg[0x1f] & (1 << nr))
+#define SPRITE_COLLISION(nr) (m_reg[0x1e] & (1 << nr))
+#define SPRITE_SET_BG_COLLISION(nr) (m_reg[0x1f] |= (1 << nr))
+#define SPRITE_SET_COLLISION(nr) (m_reg[0x1e] |= (1 << nr))
+#define SPRITE_COLL (m_reg[0x1e])
+#define SPRITE_BG_COLL (m_reg[0x1f])
+
+#define GFXMODE ((m_reg[0x11] & 0x60) | (m_reg[0x16] & 0x10)) >> 4
+#define SCREENON (m_reg[0x11] & 0x10)
+#define VERTICALPOS (m_reg[0x11] & 0x07)
+#define HORIZONTALPOS (m_reg[0x16] & 0x07)
+#define ECMON (m_reg[0x11] & 0x40)
+#define HIRESON (m_reg[0x11] & 0x20)
+#define MULTICOLORON (m_reg[0x16] & 0x10)
+#define LINES25 (m_reg[0x11] & 0x08) /* else 24 Lines */
+#define LINES (LINES25 ? 25 : 24)
+#define YSIZE (LINES * 8)
+#define COLUMNS40 (m_reg[0x16] & 0x08) /* else 38 Columns */
+#define COLUMNS (COLUMNS40 ? 40 : 38)
+#define XSIZE (COLUMNS * 8)
+
+#define VIDEOADDR ((m_reg[0x18] & 0xf0) << (10 - 4))
+#define CHARGENADDR ((m_reg[0x18] & 0x0e) << 10)
+#define BITMAPADDR ((data & 0x08) << 10)
+
+#define RASTERLINE (((m_reg[0x11] & 0x80) << 1) | m_reg[0x12])
+
+#define FRAMECOLOR (m_reg[0x20] & 0x0f)
+#define BACKGROUNDCOLOR (m_reg[0x21] & 0x0f)
+#define MULTICOLOR1 (m_reg[0x22] & 0x0f)
+#define MULTICOLOR2 (m_reg[0x23] & 0x0f)
+#define FOREGROUNDCOLOR (m_reg[0x24] & 0x0f)
+
+
+#define VIC2_LINES (m_type == VIC4567_PAL ? VIC6569_LINES : VIC6567_LINES)
+#define VIC2_VISIBLELINES (m_type == VIC4567_PAL ? VIC6569_VISIBLELINES : VIC6567_VISIBLELINES)
+#define VIC2_VISIBLECOLUMNS (m_type == VIC4567_PAL ? VIC6569_VISIBLECOLUMNS : VIC6567_VISIBLECOLUMNS)
+#define VIC2_STARTVISIBLELINES ((VIC2_LINES - VIC2_VISIBLELINES)/2)
+#define VIC2_FIRSTRASTERLINE (m_type == VIC4567_PAL ? VIC6569_FIRSTRASTERLINE : VIC6567_FIRSTRASTERLINE)
+#define VIC2_COLUMNS (m_type == VIC4567_PAL ? VIC6569_COLUMNS : VIC6567_COLUMNS)
+#define VIC2_STARTVISIBLECOLUMNS ((VIC2_COLUMNS - VIC2_VISIBLECOLUMNS)/2)
+
+#define VIC3_BITPLANES_MASK (m_reg[0x32])
+/* bit 0, 4 not used !?*/
+/* I think hinibbles contains the banknumbers for interlaced modes */
+/* if hinibble set then x&1==0 should be in bank1 (0x10000), x&1==1 in bank 0 */
+#define VIC3_BITPLANE_ADDR_HELPER(x) ((m_reg[0x33 + x] & 0x0f) << 12)
+#define VIC3_BITPLANE_ADDR(x) (x & 1 ? VIC3_BITPLANE_ADDR_HELPER(x) + 0x10000 : VIC3_BITPLANE_ADDR_HELPER(x) )
+#define VIC3_BITPLANE_IADDR_HELPER(x) ((m_reg[0x33 + x] & 0xf0) << 8)
+#define VIC3_BITPLANE_IADDR(x) (x & 1 ? VIC3_BITPLANE_IADDR_HELPER(x) + 0x10000 : VIC3_BITPLANE_IADDR_HELPER(x))
+
+
+const device_type VIC3 = &device_creator<vic3_device>;
+
+vic3_device::vic3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, VIC3, "4567 VIC III", tag, owner, clock, "vic3", __FILE__),
+ device_video_interface(mconfig, *this),
+ m_type(VIC4567_NTSC),
+ m_cpu(*this),
+ m_dma_read_cb(*this),
+ m_dma_read_color_cb(*this),
+ m_interrupt_cb(*this),
+ m_port_changed_cb(*this),
+ m_lightpen_button_cb(*this),
+ m_lightpen_x_cb(*this),
+ m_lightpen_y_cb(*this),
+ m_c64_mem_r_cb(*this),
+ m_palette(*this, "palette")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void vic3_device::device_start()
+{
+ int width, height;
+
+ width = m_screen->width();
+ height = m_screen->height();
+
+ m_bitmap = auto_bitmap_ind16_alloc(machine(), width, height);
+
+ m_dma_read_cb.resolve_safe(0);
+ m_dma_read_color_cb.resolve_safe(0);
+ m_interrupt_cb.resolve_safe();
+
+ m_port_changed_cb.resolve();
+
+ m_c64_mem_r_cb.resolve_safe(0);
+
+ m_lightpen_button_cb.resolve_safe(0);
+ m_lightpen_x_cb.resolve_safe(0);
+ m_lightpen_y_cb.resolve_safe(0);
+
+ m_screenptr[0] = auto_alloc_array(machine(), UINT8, 216 * 656 / 8);
+
+ for (int i = 1; i < 216; i++)
+ m_screenptr[i] = m_screenptr[i - 1] + 656 / 8;
+
+ for (int i = 0; i < 256; i++)
+ {
+ m_foreground[i] = 0;
+ if ((i & 3) > 1)
+ m_foreground[i] |= 0x3;
+ if ((i & 0xc) > 0x4)
+ m_foreground[i] |= 0xc;
+ if ((i & 0x30) > 0x10)
+ m_foreground[i] |= 0x30;
+ if ((i & 0xc0) > 0x40)
+ m_foreground[i] |= 0xc0;
+ }
+
+ for (int i = 0; i < 256; i++)
+ {
+ m_expandx[i] = 0;
+ if (i & 1)
+ m_expandx[i] |= 3;
+ if (i & 2)
+ m_expandx[i] |= 0xc;
+ if (i & 4)
+ m_expandx[i] |= 0x30;
+ if (i & 8)
+ m_expandx[i] |= 0xc0;
+ if (i & 0x10)
+ m_expandx[i] |= 0x300;
+ if (i & 0x20)
+ m_expandx[i] |= 0xc00;
+ if (i & 0x40)
+ m_expandx[i] |= 0x3000;
+ if (i & 0x80)
+ m_expandx[i] |= 0xc000;
+ }
+
+ for (int i = 0; i < 256; i++)
+ {
+ m_expandx_multi[i] = 0;
+ if (i & 1)
+ m_expandx_multi[i] |= 5;
+ if (i & 2)
+ m_expandx_multi[i] |= 0xa;
+ if (i & 4)
+ m_expandx_multi[i] |= 0x50;
+ if (i & 8)
+ m_expandx_multi[i] |= 0xa0;
+ if (i & 0x10)
+ m_expandx_multi[i] |= 0x500;
+ if (i & 0x20)
+ m_expandx_multi[i] |= 0xa00;
+ if (i & 0x40)
+ m_expandx_multi[i] |= 0x5000;
+ if (i & 0x80)
+ m_expandx_multi[i] |= 0xa000;
+ }
+
+ save_item(NAME(m_reg));
+
+ save_item(NAME(m_on));
+
+ //save_item(NAME(m_bitmap));
+
+ save_item(NAME(m_lines));
+
+ save_item(NAME(m_chargenaddr));
+ save_item(NAME(m_videoaddr));
+ save_item(NAME(m_bitmapaddr));
+
+ save_item(NAME(m_x_begin));
+ save_item(NAME(m_x_end));
+ save_item(NAME(m_y_begin));
+ save_item(NAME(m_y_end));
+
+ save_item(NAME(m_c64_bitmap));
+ save_item(NAME(m_bitmapmulti));
+ save_item(NAME(m_mono));
+ save_item(NAME(m_multi));
+ save_item(NAME(m_ecmcolor));
+ save_item(NAME(m_colors));
+ save_item(NAME(m_spritemulti));
+
+ save_item(NAME(m_lastline));
+ save_item(NAME(m_rasterline));
+ save_item(NAME(m_interlace));
+
+ save_item(NAME(m_columns));
+ save_item(NAME(m_rows));
+
+ save_item(NAME(m_shift));
+ save_item(NAME(m_foreground));
+ save_item(NAME(m_multi_collision));
+
+ save_item(NAME(m_palette_red));
+ save_item(NAME(m_palette_green));
+ save_item(NAME(m_palette_blue));
+ save_item(NAME(m_palette_dirty));
+
+ for (int i = 0; i < 8; i++)
+ {
+ save_item(NAME(m_sprites[i].x), i);
+ save_item(NAME(m_sprites[i].y), i);
+ save_item(NAME(m_sprites[i].repeat), i);
+ save_item(NAME(m_sprites[i].line), i);
+ save_item(NAME(m_sprites[i].paintedline), i);
+ save_item(NAME(m_sprites[i].bitmap[0]), i);
+ save_item(NAME(m_sprites[i].bitmap[1]), i);
+ save_item(NAME(m_sprites[i].bitmap[2]), i);
+ save_item(NAME(m_sprites[i].bitmap[3]), i);
+ save_item(NAME(m_sprites[i].bitmap[4]), i);
+ save_item(NAME(m_sprites[i].bitmap[5]), i);
+ save_item(NAME(m_sprites[i].bitmap[6]), i);
+ save_item(NAME(m_sprites[i].bitmap[7]), i);
+ }
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void vic3_device::device_reset()
+{
+ memset(m_reg, 0, ARRAY_LENGTH(m_reg));
+
+ m_on = 1;
+
+ m_interlace = 0;
+ m_columns = 640;
+ m_rows = 200;
+ m_lines = VIC2_LINES;
+
+ memset(&m_sprites, 0, sizeof(m_sprites));
+
+ m_chargenaddr = 0;
+ m_videoaddr = 0;
+ m_bitmapaddr = 0;
+
+ m_x_begin = 0;
+ m_x_end = 0;
+ m_y_begin = 0;
+ m_y_end = 0;
+
+ for (int i = 0; i < 2; i++)
+ {
+ m_c64_bitmap[i] = 0;
+ m_mono[i] = 0;
+ m_ecmcolor[i] = 0;
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ m_bitmapmulti[i] = 0;
+ m_multi[i] = 0;
+ m_colors[i] = 0;
+ m_spritemulti[i] = 0;
+ }
+
+ m_lastline = 0;
+ m_rasterline = 0;
+
+ memset(m_shift, 0, ARRAY_LENGTH(m_shift));
+ memset(m_multi_collision, 0, ARRAY_LENGTH(m_multi_collision));
+ memset(m_palette_red, 0, ARRAY_LENGTH(m_palette_red));
+ memset(m_palette_green, 0, ARRAY_LENGTH(m_palette_green));
+ memset(m_palette_blue, 0, ARRAY_LENGTH(m_palette_blue));
+
+ m_palette_dirty = 0;
+}
+
+
+/*****************************************************************************
+ IMPLEMENTATION
+*****************************************************************************/
+
+inline int vic3_device::getforeground( int y, int x )
+{
+ return ((m_screenptr[y][x >> 3] << 8) | (m_screenptr[y][(x >> 3) + 1])) >> (8 - (x & 7));
+}
+
+inline int vic3_device::getforeground16( int y, int x )
+{
+ return ((m_screenptr[y][x >> 3] << 16) | (m_screenptr[y][(x >> 3) + 1] << 8) | (m_screenptr[y][(x >> 3) + 2])) >> (8 - (x & 7));
+}
+
+void vic3_device::set_interrupt( int mask )
+{
+ if (((m_reg[0x19] ^ mask) & m_reg[0x1a] & 0xf))
+ {
+ if (!(m_reg[0x19] & 0x80))
+ {
+ //DBG_LOG(2, "vic2", ("irq start %.2x\n", mask));
+ m_reg[0x19] |= 0x80;
+ m_interrupt_cb(1);
+ }
+ }
+ m_reg[0x19] |= mask;
+}
+
+void vic3_device::clear_interrupt( int mask )
+{
+ m_reg[0x19] &= ~mask;
+ if ((m_reg[0x19] & 0x80) && !(m_reg[0x19] & m_reg[0x1a] & 0xf))
+ {
+ //DBG_LOG(2, "vic2", ("irq end %.2x\n", mask));
+ m_reg[0x19] &= ~0x80;
+ m_interrupt_cb(0);
+ }
+}
+
+TIMER_CALLBACK_MEMBER( vic3_device::timer_timeout )
+{
+ int which = param;
+ //DBG_LOG(3, "vic3 ", ("timer %d timeout\n", which));
+ switch (which)
+ {
+ case 1: /* light pen */
+ /* and diode must recognize light */
+ if (1)
+ {
+ m_reg[0x13] = VIC2_X_VALUE;
+ m_reg[0x14] = VIC2_Y_VALUE;
+ }
+ set_interrupt(8);
+ break;
+ }
+}
+
+void vic3_device::draw_character( int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color, int start_x, int end_x )
+{
+ int code;
+
+ for (int y = ybegin; y <= yend; y++)
+ {
+ code = m_dma_read_cb(m_chargenaddr + ch * 8 + y);
+ m_screenptr[y + yoff][xoff >> 3] = code;
+ if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 0) = color[code >> 7];
+ if ((xoff + 1 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 1) = color[(code >> 6) & 1];
+ if ((xoff + 2 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 2) = color[(code >> 5) & 1];
+ if ((xoff + 3 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 3) = color[(code >> 4) & 1];
+ if ((xoff + 4 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 4) = color[(code >> 3) & 1];
+ if ((xoff + 5 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 5) = color[(code >> 2) & 1];
+ if ((xoff + 6 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 6) = color[(code >> 1) & 1];
+ if ((xoff + 7 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 7) = color[code & 1];
+ }
+}
+
+void vic3_device::draw_character_multi( int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x )
+{
+ int code;
+
+ for (int y = ybegin; y <= yend; y++)
+ {
+ code = m_dma_read_cb(m_chargenaddr + ch * 8 + y);
+ m_screenptr[y + yoff][xoff >> 3] = m_foreground[code];
+ if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 0) = m_multi[code >> 6];
+ if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 1) = m_multi[code >> 6];
+ if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 2) = m_multi[(code >> 4) & 3];
+ if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 3) = m_multi[(code >> 4) & 3];
+ if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 4) = m_multi[(code >> 2) & 3];
+ if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 5) = m_multi[(code >> 2) & 3];
+ if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 6) = m_multi[code & 3];
+ if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 7) = m_multi[code & 3];
+ }
+}
+
+void vic3_device::draw_bitmap( int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x )
+{
+ int code;
+
+ for (int y = ybegin; y <= yend; y++)
+ {
+ code = m_dma_read_cb((m_chargenaddr & 0x2000) + ch * 8 + y);
+ m_screenptr[y + yoff][xoff >> 3] = code;
+ if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 0) = m_c64_bitmap[code >> 7];
+ if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 1) = m_c64_bitmap[(code >> 6) & 1];
+ if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 2) = m_c64_bitmap[(code >> 5) & 1];
+ if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 3) = m_c64_bitmap[(code >> 4) & 1];
+ if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 4) = m_c64_bitmap[(code >> 3) & 1];
+ if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 5) = m_c64_bitmap[(code >> 2) & 1];
+ if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 6) = m_c64_bitmap[(code >> 1) & 1];
+ if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 7) = m_c64_bitmap[code & 1];
+ }
+}
+
+void vic3_device::draw_bitmap_multi( int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x )
+{
+ int code;
+
+ for (int y = ybegin; y <= yend; y++)
+ {
+ code = m_dma_read_cb((m_chargenaddr & 0x2000) + ch * 8 + y);
+ m_screenptr[y + yoff][xoff >> 3] = m_foreground[code];
+ if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 0) = m_bitmapmulti[code >> 6];
+ if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 1) = m_bitmapmulti[code >> 6];
+ if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 2) = m_bitmapmulti[(code >> 4) & 3];
+ if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 3) = m_bitmapmulti[(code >> 4) & 3];
+ if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 4) = m_bitmapmulti[(code >> 2) & 3];
+ if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 5) = m_bitmapmulti[(code >> 2) & 3];
+ if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 6) = m_bitmapmulti[code & 3];
+ if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) m_bitmap->pix16(y + yoff + FIRSTLINE, xoff + 7) = m_bitmapmulti[code & 3];
+ }
+}
+
+void vic3_device::draw_sprite_code( int y, int xbegin, int code, int color, int start_x, int end_x )
+{
+ register int mask, x;
+
+ if ((y < YPOS) || (y >= (VIC2_STARTVISIBLELINES + VIC2_VISIBLELINES)) || (xbegin <= 1) || (xbegin >= (VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS)))
+ return;
+
+ for (x = 0, mask = 0x80; x < 8; x++, mask >>= 1)
+ {
+ if (code & mask)
+ {
+ if ((xbegin + x > start_x) && (xbegin + x < end_x))
+ m_bitmap->pix16(y + FIRSTLINE, xbegin + x) = color;
+ }
+ }
+}
+
+void vic3_device::draw_sprite_code_multi( int y, int xbegin, int code, int prior, int start_x, int end_x )
+{
+ register int x, mask, shift;
+
+ if ((y < YPOS) || (y >= (VIC2_STARTVISIBLELINES + VIC2_VISIBLELINES)) || (xbegin <= 1) || (xbegin >= (VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS)))
+ return;
+
+ for (x = 0, mask = 0xc0, shift = 6; x < 8; x += 2, mask >>= 2, shift -= 2)
+ {
+ if (code & mask)
+ {
+ switch ((prior & mask) >> shift)
+ {
+ case 1:
+ if ((xbegin + x + 1 > start_x) && (xbegin + x + 1 < end_x))
+ m_bitmap->pix16(y + FIRSTLINE, xbegin + x + 1) = m_spritemulti[(code >> shift) & 3];
+ break;
+ case 2:
+ if ((xbegin + x > start_x) && (xbegin + x < end_x))
+ m_bitmap->pix16(y + FIRSTLINE, xbegin + x) = m_spritemulti[(code >> shift) & 3];
+ break;
+ case 3:
+ if ((xbegin + x > start_x) && (xbegin + x < end_x))
+ m_bitmap->pix16(y + FIRSTLINE, xbegin + x) = m_spritemulti[(code >> shift) & 3];
+ if ((xbegin + x + 1> start_x) && (xbegin + x + 1< end_x))
+ m_bitmap->pix16(y + FIRSTLINE, xbegin + x + 1) = m_spritemulti[(code >> shift) & 3];
+ break;
+ }
+ }
+ }
+}
+
+void vic3_device::sprite_collision( int nr, int y, int x, int mask )
+{
+ int value, xdiff;
+
+ for (int i = 7; i > nr; i--)
+ {
+ if (!SPRITEON(i) || !m_sprites[i].paintedline[y] || (SPRITE_COLLISION(i) && SPRITE_COLLISION(nr)))
+ continue;
+
+ if ((x + 7 < SPRITE_X_POS(i)) || (x >= SPRITE_X_POS(i) + SPRITE_X_SIZE(i)))
+ continue;
+
+ xdiff = x - SPRITE_X_POS(i);
+
+ if ((x & 7) == (SPRITE_X_POS(i) & 7))
+ value = m_sprites[i].bitmap[y][xdiff >> 3];
+ else if (xdiff < 0)
+ value = m_sprites[i].bitmap[y][0] >> (-xdiff);
+ else {
+ UINT8 *vp = m_sprites[i].bitmap[y]+(xdiff >> 3);
+ value = ((vp[1] | (*vp << 8)) >> (8 - (xdiff & 7) )) & 0xff;
+ }
+
+ if (value & mask)
+ {
+ SPRITE_SET_COLLISION(i);
+ SPRITE_SET_COLLISION(nr);
+ set_interrupt(4);
+ }
+ }
+}
+
+void vic3_device::draw_sprite( int nr, int yoff, int ybegin, int yend, int start_x, int end_x )
+{
+ int y, i, addr, xbegin, color, prior, collision;
+ int value, value3 = 0;
+
+ xbegin = SPRITE_X_POS(nr);
+ addr = m_dma_read_cb(SPRITE_ADDR(nr)) << 6;
+ color = SPRITE_COLOR(nr);
+ prior = SPRITE_PRIORITY(nr);
+ collision = SPRITE_BG_COLLISION(nr);
+
+ if (SPRITE_X_EXPAND(nr))
+ {
+ for (y = ybegin; y <= yend; y++)
+ {
+ m_sprites[nr].paintedline[y] = 1;
+ for (i = 0; i < 3; i++)
+ {
+ value = m_expandx[m_dma_read_cb(addr + m_sprites[nr].line * 3 + i)];
+ m_sprites[nr].bitmap[y][i * 2] = value >> 8;
+ m_sprites[nr].bitmap[y][i * 2 + 1] = value & 0xff;
+ sprite_collision(nr, y, xbegin + i * 16, value >> 8);
+ sprite_collision(nr, y, xbegin + i * 16 + 8, value & 0xff);
+ if (prior || !collision)
+ value3 = getforeground16(yoff + y, xbegin + i * 16 - 7);
+ if (!collision && (value & value3))
+ {
+ collision = 1;
+ SPRITE_SET_BG_COLLISION(nr);
+ set_interrupt(2);
+ }
+ if (prior)
+ value &= ~value3;
+ draw_sprite_code(yoff + y, xbegin + i * 16, value >> 8, color, start_x, end_x);
+ draw_sprite_code(yoff + y, xbegin + i * 16 + 8, value & 0xff, color, start_x, end_x);
+ }
+ m_sprites[nr].bitmap[y][i * 2]=0; //easier sprite collision detection
+ if (SPRITE_Y_EXPAND(nr))
+ {
+ if (m_sprites[nr].repeat)
+ {
+ m_sprites[nr].line++;
+ m_sprites[nr].repeat = 0;
+ }
+ else
+ m_sprites[nr].repeat = 1;
+ }
+ else
+ {
+ m_sprites[nr].line++;
+ }
+ }
+ }
+ else
+ {
+ for (y = ybegin; y <= yend; y++)
+ {
+ m_sprites[nr].paintedline[y] = 1;
+ for (i = 0; i < 3; i++)
+ {
+ value = m_dma_read_cb(addr + m_sprites[nr].line * 3 + i);
+ m_sprites[nr].bitmap[y][i] = value;
+ sprite_collision(nr, y, xbegin + i * 8, value);
+ if (prior || !collision)
+ value3 = getforeground(yoff + y, xbegin + i * 8 - 7);
+ if (!collision && (value & value3))
+ {
+ collision = 1;
+ SPRITE_SET_BG_COLLISION(nr);
+ set_interrupt(2);
+ }
+ if (prior)
+ value &= ~value3;
+ draw_sprite_code(yoff + y, xbegin + i * 8, value, color, start_x, end_x);
+ }
+ m_sprites[nr].bitmap[y][i]=0; //easier sprite collision detection
+ if (SPRITE_Y_EXPAND(nr))
+ {
+ if (m_sprites[nr].repeat)
+ {
+ m_sprites[nr].line++;
+ m_sprites[nr].repeat = 0;
+ }
+ else
+ m_sprites[nr].repeat = 1;
+ }
+ else
+ {
+ m_sprites[nr].line++;
+ }
+ }
+ }
+}
+
+void vic3_device::draw_sprite_multi( int nr, int yoff, int ybegin, int yend, int start_x, int end_x )
+{
+ int y, i, prior, addr, xbegin, collision;
+ int value, value2, value3 = 0, bg/*, color[2]*/;
+
+ xbegin = SPRITE_X_POS(nr);
+ addr = m_dma_read_cb(SPRITE_ADDR(nr)) << 6;
+ m_spritemulti[2] = SPRITE_COLOR(nr);
+ prior = SPRITE_PRIORITY(nr);
+ collision = SPRITE_BG_COLLISION(nr);
+ //color[0] = 0;
+ //color[1] = 1;
+
+ if (SPRITE_X_EXPAND(nr))
+ {
+ for (y = ybegin; y <= yend; y++)
+ {
+ m_sprites[nr].paintedline[y] = 1;
+ for (i = 0; i < 3; i++)
+ {
+ value = m_expandx_multi[bg = m_dma_read_cb(addr + m_sprites[nr].line * 3 + i)];
+ value2 = m_expandx[m_multi_collision[bg]];
+ m_sprites[nr].bitmap[y][i * 2] = value2 >> 8;
+ m_sprites[nr].bitmap[y][i * 2 + 1] = value2 & 0xff;
+ sprite_collision(nr, y, xbegin + i * 16, value2 >> 8);
+ sprite_collision(nr, y, xbegin + i * 16 + 8, value2 & 0xff);
+ if (prior || !collision)
+ {
+ value3 = getforeground16(yoff + y, xbegin + i * 16 - 7);
+ }
+ if (!collision && (value2 & value3))
+ {
+ collision = 1;
+ SPRITE_SET_BG_COLLISION(nr);
+ set_interrupt(2);
+ }
+ if (prior)
+ {
+ draw_sprite_code_multi(yoff + y, xbegin + i * 16, value >> 8, (value3 >> 8) ^ 0xff, start_x, end_x);
+ draw_sprite_code_multi(yoff + y, xbegin + i * 16 + 8, value & 0xff, (value3 & 0xff) ^ 0xff, start_x, end_x);
+ }
+ else
+ {
+ draw_sprite_code_multi(yoff + y, xbegin + i * 16, value >> 8, 0xff, start_x, end_x);
+ draw_sprite_code_multi(yoff + y, xbegin + i * 16 + 8, value & 0xff, 0xff, start_x, end_x);
+ }
+ }
+ m_sprites[nr].bitmap[y][i * 2]=0; //easier sprite collision detection
+ if (SPRITE_Y_EXPAND(nr))
+ {
+ if (m_sprites[nr].repeat)
+ {
+ m_sprites[nr].line++;
+ m_sprites[nr].repeat = 0;
+ }
+ else
+ m_sprites[nr].repeat = 1;
+ }
+ else
+ {
+ m_sprites[nr].line++;
+ }
+ }
+ }
+ else
+ {
+ for (y = ybegin; y <= yend; y++)
+ {
+ m_sprites[nr].paintedline[y] = 1;
+ for (i = 0; i < 3; i++)
+ {
+ value = m_dma_read_cb(addr + m_sprites[nr].line * 3 + i);
+ m_sprites[nr].bitmap[y][i] = value2 = m_multi_collision[value];
+ sprite_collision(nr, y, xbegin + i * 8, value2);
+ if (prior || !collision)
+ {
+ value3 = getforeground(yoff + y, xbegin + i * 8 - 7);
+ }
+ if (!collision && (value2 & value3))
+ {
+ collision = 1;
+ SPRITE_SET_BG_COLLISION(nr);
+ set_interrupt(2);
+ }
+ if (prior)
+ {
+ draw_sprite_code_multi(yoff + y, xbegin + i * 8, value, value3 ^ 0xff, start_x, end_x);
+ }
+ else
+ {
+ draw_sprite_code_multi(yoff + y, xbegin + i * 8, value, 0xff, start_x, end_x);
+ }
+ }
+ m_sprites[nr].bitmap[y][i] = 0; //easier sprite collision detection
+ if (SPRITE_Y_EXPAND(nr))
+ {
+ if (m_sprites[nr].repeat)
+ {
+ m_sprites[nr].line++;
+ m_sprites[nr].repeat = 0;
+ }
+ else
+ m_sprites[nr].repeat = 1;
+ }
+ else
+ {
+ m_sprites[nr].line++;
+ }
+ }
+ }
+}
+
+#ifndef memset16
+static void *memset16(void *dest, int value, size_t size)
+{
+ register int i;
+
+ for (i = 0; i < size; i++)
+ ((short *) dest)[i] = value;
+ return dest;
+}
+#endif
+
+void vic3_device::drawlines( int first, int last, int start_x, int end_x )
+{
+ int line, vline, end;
+ int attr, ch, ecm;
+ int syend;
+ int offs, yoff, xoff, ybegin, yend, xbegin, xend;
+ int x_end2;
+ int i, j;
+
+ if (first == last)
+ return;
+ m_lastline = last;
+
+ /* top part of display not rastered */
+ first -= VIC2_YPOS - YPOS;
+ last -= VIC2_YPOS - YPOS;
+ if ((first >= last) || (last <= 0))
+ {
+ for (i = 0; i < 8; i++)
+ m_sprites[i].repeat = m_sprites[i].line = 0;
+ return;
+ }
+ if (first < 0)
+ first = 0;
+
+ if (!SCREENON)
+ {
+ for (line = first; (line < last) && (line < m_bitmap->height()); line++)
+ {
+ memset16(&m_bitmap->pix16(line + FIRSTLINE), 0, m_bitmap->width());
+ }
+ return;
+ }
+ if (COLUMNS40)
+ xbegin = XPOS, xend = xbegin + 640;
+ else
+ xbegin = XPOS + 7, xend = xbegin + 624;
+
+ if (last < m_y_begin)
+ end = last;
+ else
+ end = m_y_begin + YPOS;
+
+ for (line = first; line < end; line++)
+ {
+ memset16(&m_bitmap->pix16(line + FIRSTLINE), FRAMECOLOR, m_bitmap->width());
+ }
+
+ if (LINES25)
+ {
+ vline = line - m_y_begin - YPOS;
+ }
+ else
+ {
+ vline = line - m_y_begin - YPOS + 8 - VERTICALPOS;
+ }
+ if (last < m_y_end + YPOS)
+ end = last;
+ else
+ end = m_y_end + YPOS;
+ x_end2 = m_x_end * 2;
+ for (; line < end; vline = (vline + 8) & ~7, line = line + 1 + yend - ybegin)
+ {
+ offs = (vline >> 3) * 80;
+ ybegin = vline & 7;
+ yoff = line - ybegin;
+ yend = (yoff + 7 < end) ? 7 : (end - yoff - 1);
+ /* rendering 39 characters */
+ /* left and right borders are overwritten later */
+ m_shift[line] = HORIZONTALPOS;
+
+ for (xoff = m_x_begin + XPOS; xoff < x_end2 + XPOS; xoff += 8, offs++)
+ {
+ ch = m_dma_read_cb(m_videoaddr + offs);
+ attr = m_dma_read_color_cb(m_videoaddr + offs);
+ if (HIRESON)
+ {
+ m_bitmapmulti[1] = m_c64_bitmap[1] = ch >> 4;
+ m_bitmapmulti[2] = m_c64_bitmap[0] = ch & 0xf;
+ if (MULTICOLORON)
+ {
+ m_bitmapmulti[3] = attr;
+ draw_bitmap_multi(ybegin, yend, offs, yoff, xoff, start_x, end_x);
+ }
+ else
+ {
+ draw_bitmap(ybegin, yend, offs, yoff, xoff, start_x, end_x);
+ }
+ }
+ else if (ECMON)
+ {
+ ecm = ch >> 6;
+ m_ecmcolor[0] = m_colors[ecm];
+ m_ecmcolor[1] = attr;
+ draw_character(ybegin, yend, ch & ~0xC0, yoff, xoff, m_ecmcolor, start_x, end_x);
+ }
+ else if (MULTICOLORON && (attr & 8))
+ {
+ m_multi[3] = attr & 7;
+ draw_character_multi(ybegin, yend, ch, yoff, xoff, start_x, end_x);
+ }
+ else
+ {
+ m_mono[1] = attr;
+ draw_character(ybegin, yend, ch, yoff, xoff, m_mono, start_x, end_x);
+ }
+ }
+ /* sprite priority, sprite overwrites lowerprior pixels */
+ for (i = 7; i >= 0; i--)
+ {
+ if (m_sprites[i].line || m_sprites[i].repeat)
+ {
+ syend = yend;
+ if (SPRITE_Y_EXPAND(i))
+ {
+ if ((21 - m_sprites[i].line) * 2 - m_sprites[i].repeat < yend - ybegin + 1)
+ syend = ybegin + (21 - m_sprites[i].line) * 2 - m_sprites[i].repeat - 1;
+ }
+ else
+ {
+ if (m_sprites[i].line + yend - ybegin + 1 > 20)
+ syend = ybegin + 20 - m_sprites[i].line;
+ }
+ if (yoff + syend > YPOS + 200)
+ syend = YPOS + 200 - yoff - 1;
+ if (SPRITE_MULTICOLOR(i))
+ draw_sprite_multi(i, yoff, ybegin, syend, start_x, end_x);
+ else
+ draw_sprite(i, yoff, ybegin, syend, start_x, end_x);
+ if ((syend != yend) || (m_sprites[i].line > 20))
+ {
+ m_sprites[i].line = m_sprites[i].repeat = 0;
+ for (j = syend; j <= yend; j++)
+ m_sprites[i].paintedline[j] = 0;
+ }
+ }
+ // sprite wrap y at the top of the screen
+ else if (SPRITEON(i) && (yoff == 1 + yend - ybegin) && (SPRITE_Y_POS(i) < 1 + yend - ybegin))
+ {
+ int wrapped = 1 + yend - ybegin - SPRITE_Y_POS(i);
+ syend = yend;
+
+ if (SPRITE_Y_EXPAND(i))
+ {
+ if (wrapped & 1) m_sprites[i].repeat = 1;
+ wrapped >>= 1;
+ syend = 21 * 2 - 1 - wrapped * 2;
+ if (syend > (yend - ybegin)) syend = yend - ybegin;
+ }
+ else
+ {
+ syend = 21 - 1 - wrapped;
+ if (syend > (yend - ybegin)) syend = yend - ybegin;
+ }
+
+ m_sprites[i].line = wrapped;
+
+ if (SPRITE_MULTICOLOR(i))
+ draw_sprite_multi(i, yoff, 0 , syend, start_x, end_x);
+ else
+ draw_sprite(i, yoff, 0 , syend, start_x, end_x);
+
+ if ((syend != yend) || (m_sprites[i].line > 20))
+ {
+ for (j = syend; j <= yend; j++)
+ m_sprites[i].paintedline[j] = 0;
+ m_sprites[i].line = m_sprites[i].repeat = 0;
+ }
+ }
+ else if (SPRITEON(i) && (yoff + ybegin <= SPRITE_Y_POS(i))
+ && (yoff + yend >= SPRITE_Y_POS(i)))
+ {
+ syend = yend;
+ if (SPRITE_Y_EXPAND(i))
+ {
+ if (21 * 2 < yend - ybegin + 1)
+ syend = ybegin + 21 * 2 - 1;
+ }
+ else
+ {
+ if (yend - ybegin + 1 > 21)
+ syend = ybegin + 21 - 1;
+ }
+ if (yoff + syend >= YPOS + 200)
+ syend = YPOS + 200 - yoff - 1;
+ for (j = 0; j < SPRITE_Y_POS(i) - yoff; j++)
+ m_sprites[i].paintedline[j] = 0;
+ if (SPRITE_MULTICOLOR(i))
+ draw_sprite_multi(i, yoff, SPRITE_Y_POS(i) - yoff, syend, start_x, end_x);
+ else
+ draw_sprite(i, yoff, SPRITE_Y_POS(i) - yoff, syend, start_x, end_x);
+ if ((syend != yend) || (m_sprites[i].line > 20))
+ {
+ for (j = syend; j <= yend; j++)
+ m_sprites[i].paintedline[j] = 0;
+ m_sprites[i].line = m_sprites[i].repeat = 0;
+ }
+ }
+ else
+ {
+ memset (m_sprites[i].paintedline, 0, sizeof (m_sprites[i].paintedline));
+ }
+ }
+
+ for (i = ybegin; i <= yend; i++)
+ {
+ m_bitmap->plot_box(0, yoff + ybegin + FIRSTLINE, xbegin, yend - ybegin + 1, FRAMECOLOR);
+ m_bitmap->plot_box(xend, yoff + ybegin + FIRSTLINE, m_bitmap->width() - xend, yend - ybegin + 1, FRAMECOLOR);
+ }
+ }
+ if (last < m_bitmap->height())
+ end = last;
+ else
+ end = m_bitmap->height();
+
+ for (; line < end; line++)
+ {
+ memset16(&m_bitmap->pix16(line + FIRSTLINE), FRAMECOLOR, m_bitmap->width());
+ }
+}
+
+void vic3_device::vic2_drawlines( int first, int last, int start_x, int end_x )
+{
+ int line, vline, end;
+ int attr, ch, ecm;
+ int syend;
+ int offs, yoff, xoff, ybegin, yend, xbegin, xend;
+ int i;
+
+ if (VIC3_BITPLANES)
+ return ;
+
+ /* temporary allowing vic3 displaying 80 columns */
+ if (m_reg[0x31] & 0x80)
+ {
+ drawlines(first, first + 1, start_x, end_x);
+ return;
+ }
+
+ /* otherwise, draw VIC II output (currently using the old code, not the new one from vic6567.c) */
+
+ /* top part of display not rastered */
+ first -= VIC2_YPOS - YPOS;
+
+ xbegin = VIC2_STARTVISIBLECOLUMNS;
+ xend = xbegin + VIC2_VISIBLECOLUMNS;
+ if (!SCREENON)
+ {
+ xbegin = VIC2_STARTVISIBLECOLUMNS;
+ xend = xbegin + VIC2_VISIBLECOLUMNS;
+ if ((start_x <= xbegin) && (end_x >= xend))
+ m_bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR);
+ if ((start_x > xbegin) && (end_x >= xend))
+ m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR);
+ if ((start_x <= xbegin) && (end_x < xend))
+ m_bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR);
+ if ((start_x > xbegin) && (end_x < xend))
+ m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
+ return;
+ }
+
+ if (COLUMNS40)
+ {
+ xbegin = XPOS;
+ xend = xbegin + 320;
+ }
+ else
+ {
+ xbegin = XPOS + 7;
+ xend = xbegin + 304;
+ }
+
+ if (first + 1 < m_y_begin)
+ end = first + 1;
+ else
+ end = m_y_begin + YPOS;
+
+ line = first;
+ // top border
+ if (line < end)
+ {
+ if ((start_x <= xbegin) && (end_x >= xend))
+ m_bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR);
+ if ((start_x > xbegin) && (end_x >= xend))
+ m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR);
+ if ((start_x <= xbegin) && (end_x < xend))
+ m_bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR);
+ if ((start_x > xbegin) && (end_x < xend))
+ m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
+ line = end;
+ }
+
+ vline = line - YPOS + 3 - VERTICALPOS;
+
+ if (first + 1 < m_y_end + YPOS)
+ end = first + 1;
+ else
+ end = m_y_end + YPOS;
+
+ if (line < end)
+ {
+ offs = (vline >> 3) * 40;
+ ybegin = vline & 7;
+ yoff = line - ybegin;
+ yend = (yoff + 7 < end) ? 7 : (end - yoff - 1);
+
+ /* rendering 39 characters */
+ /* left and right borders are overwritten later */
+
+ m_shift[line] = HORIZONTALPOS;
+ for (xoff = m_x_begin + XPOS; xoff < m_x_end + XPOS; xoff += 8, offs++)
+ {
+ ch = m_dma_read_cb(m_videoaddr + offs);
+#if 0
+ attr = m_dma_read_color_cb(m_videoaddr + offs);
+#else
+ /* temporary until vic3 finished */
+ attr = m_dma_read_color_cb((m_videoaddr + offs)&0x3ff)&0x0f;
+#endif
+ if (HIRESON)
+ {
+ m_bitmapmulti[1] = m_c64_bitmap[1] = ch >> 4;
+ m_bitmapmulti[2] = m_c64_bitmap[0] = ch & 0xf;
+ if (MULTICOLORON)
+ {
+ m_bitmapmulti[3] = attr;
+ draw_bitmap_multi(ybegin, yend, offs, yoff, xoff, start_x, end_x);
+ }
+ else
+ {
+ draw_bitmap(ybegin, yend, offs, yoff, xoff, start_x, end_x);
+ }
+ }
+ else if (ECMON)
+ {
+ ecm = ch >> 6;
+ m_ecmcolor[0] = m_colors[ecm];
+ m_ecmcolor[1] = attr;
+ draw_character(ybegin, yend, ch & ~0xC0, yoff, xoff, m_ecmcolor, start_x, end_x);
+ }
+ else if (MULTICOLORON && (attr & 8))
+ {
+ m_multi[3] = attr & 7;
+ draw_character_multi(ybegin, yend, ch, yoff, xoff, start_x, end_x);
+ }
+ else
+ {
+ m_mono[1] = attr;
+ draw_character(ybegin, yend, ch, yoff, xoff, m_mono, start_x, end_x);
+ }
+ }
+
+ /* sprite priority, sprite overwrites lowerprior pixels */
+ for (i = 7; i >= 0; i--)
+ {
+ if (SPRITEON (i) &&
+ (yoff + ybegin >= SPRITE_Y_POS (i)) &&
+ (yoff + ybegin - SPRITE_Y_POS (i) < (SPRITE_Y_EXPAND (i)? 21 * 2 : 21 )) &&
+ (SPRITE_Y_POS (i) < 0))
+ {
+ int wrapped = - SPRITE_Y_POS (i) + 6;
+
+ syend = yend;
+
+ if (SPRITE_Y_EXPAND (i))
+ {
+ if (wrapped & 1) m_sprites[i].repeat = 1;
+ wrapped >>= 1;
+ syend = 21 * 2 - 1 - wrapped * 2;
+ if (syend > (yend - ybegin)) syend = yend - ybegin;
+ }
+ else
+ {
+ syend = 21 - 1 - wrapped;
+ if (syend > (yend - ybegin)) syend = yend - ybegin;
+ }
+
+ m_sprites[i].line = wrapped;
+
+ if (SPRITE_MULTICOLOR (i))
+ draw_sprite_multi(i, 0, 0 , syend, start_x, end_x);
+ else
+ draw_sprite(i, 0, 0 , syend, start_x, end_x);
+ }
+ else if (SPRITEON (i) &&
+ (yoff + ybegin >= SPRITE_Y_POS (i)) &&
+ (yoff + ybegin - SPRITE_Y_POS (i) < (SPRITE_Y_EXPAND (i)? 21 * 2 : 21 )) &&
+ (SPRITE_Y_POS (i) >= 0))
+ {
+ int wrapped = yoff + ybegin - SPRITE_Y_POS (i);
+
+ syend = yend;
+
+ if (SPRITE_Y_EXPAND (i))
+ {
+ if (wrapped & 1) m_sprites[i].repeat = 1;
+ wrapped >>= 1;
+ syend = 21 * 2 - 1 - wrapped * 2;
+ if (syend > (yend - ybegin)) syend = yend - ybegin;
+ }
+ else
+ {
+ syend = 21 - 1 - wrapped;
+ if (syend > (yend - ybegin)) syend = yend - ybegin;
+ }
+
+ m_sprites[i].line = wrapped;
+
+ if (SPRITE_MULTICOLOR (i))
+ draw_sprite_multi(i, yoff + ybegin, 0, 0, start_x, end_x);
+ else
+ draw_sprite(i, yoff + ybegin, 0, 0, start_x, end_x);
+ }
+ else
+ {
+ memset(m_sprites[i].paintedline, 0, sizeof (m_sprites[i].paintedline));
+ }
+ }
+ line += 1 + yend - ybegin;
+ }
+
+ // left border
+ if ((start_x <= VIC2_STARTVISIBLECOLUMNS) && (end_x >= xbegin))
+ m_bitmap->plot_box(VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xbegin - VIC2_STARTVISIBLECOLUMNS, 1, FRAMECOLOR);
+ else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x >= xbegin))
+ m_bitmap->plot_box(start_x, first + FIRSTLINE, xbegin - start_x, 1, FRAMECOLOR);
+ else if ((start_x <= VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin))
+ m_bitmap->plot_box(VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x, 1, FRAMECOLOR);
+ else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin))
+ m_bitmap->plot_box(start_x, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
+
+ // right border
+ if ((start_x <= xend) && (end_x >= VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS))
+ m_bitmap->plot_box(xend, first + FIRSTLINE, VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS - xend, 1, FRAMECOLOR);
+ else if ((start_x > xend) && (end_x >= VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS))
+ m_bitmap->plot_box(start_x, first + FIRSTLINE, VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS - start_x, 1, FRAMECOLOR);
+ else if ((start_x <= xend) && (end_x < VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS))
+ m_bitmap->plot_box(xend, first + FIRSTLINE, end_x - xend, 1, FRAMECOLOR);
+ else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin))
+ m_bitmap->plot_box(start_x, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
+
+ if (first + 1 < m_bitmap->height())
+ end = first + 1;
+ else
+ end = m_bitmap->height();
+
+ // bottom border
+ if (line < end)
+ {
+ if ((start_x <= xbegin) && (end_x >= xend))
+ m_bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR);
+ if ((start_x > xbegin) && (end_x >= xend))
+ m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR);
+ if ((start_x <= xbegin) && (end_x < xend))
+ m_bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR);
+ if ((start_x > xbegin) && (end_x < xend))
+ m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
+ line = end;
+ }
+}
+
+/*****************************************************************************
+ I/O HANDLERS
+*****************************************************************************/
+
+WRITE8_MEMBER( vic3_device::palette_w )
+{
+ if (offset < 0x100)
+ m_palette_red[offset] = data;
+ else if (offset < 0x200)
+ m_palette_green[offset & 0xff] = data;
+ else
+ m_palette_blue[offset & 0xff] = data;
+
+ m_palette_dirty = 1;
+}
+
+
+WRITE8_MEMBER( vic3_device::port_w )
+{
+ DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
+ offset &= 0x7f;
+
+ /* offsets 0x00 -> 0x2e coincide with VICII */
+ switch (offset)
+ {
+ case 0x01:
+ case 0x03:
+ case 0x05:
+ case 0x07:
+ case 0x09:
+ case 0x0b:
+ case 0x0d:
+ case 0x0f:
+ /* sprite y positions */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_sprites[offset / 2].y = SPRITE_Y_POS(offset / 2);
+ }
+ break;
+
+ case 0x00:
+ case 0x02:
+ case 0x04:
+ case 0x06:
+ case 0x08:
+ case 0x0a:
+ case 0x0c:
+ case 0x0e:
+ /* sprite x positions */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_sprites[offset / 2].x = SPRITE_X_POS(offset / 2);
+ }
+ break;
+
+ case 0x10: /* sprite x positions */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_sprites[0].x = SPRITE_X_POS(0);
+ m_sprites[1].x = SPRITE_X_POS(1);
+ m_sprites[2].x = SPRITE_X_POS(2);
+ m_sprites[3].x = SPRITE_X_POS(3);
+ m_sprites[4].x = SPRITE_X_POS(4);
+ m_sprites[5].x = SPRITE_X_POS(5);
+ m_sprites[6].x = SPRITE_X_POS(6);
+ m_sprites[7].x = SPRITE_X_POS(7);
+ }
+ break;
+
+ case 0x17: /* sprite y size */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ }
+ break;
+
+ case 0x1d: /* sprite x size */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ }
+ break;
+
+ case 0x1b: /* sprite background priority */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ }
+ break;
+
+ case 0x1c: /* sprite multicolor mode select */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ }
+ break;
+
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ /* sprite colors */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ }
+ break;
+
+ case 0x25: /* sprite multicolor */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_spritemulti[1] = SPRITE_MULTICOLOR1;
+ }
+ break;
+
+ case 0x26: /* sprite multicolor */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_spritemulti[3] = SPRITE_MULTICOLOR2;
+ }
+ break;
+
+ case 0x19:
+ clear_interrupt(data & 0x0f);
+ break;
+
+ case 0x1a: /* irq mask */
+ m_reg[offset] = data;
+ set_interrupt(0); // beamrider needs this
+ break;
+
+ case 0x11:
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ if (LINES25)
+ {
+ m_y_begin = 0;
+ m_y_end = m_y_begin + 200;
+ }
+ else
+ {
+ m_y_begin = 4;
+ m_y_end = m_y_begin + 192;
+ }
+ }
+ break;
+
+ case 0x12:
+ if (data != m_reg[offset])
+ {
+ m_reg[offset] = data;
+ }
+ break;
+
+ case 0x16:
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_x_begin = HORIZONTALPOS;
+ m_x_end = m_x_begin + 320;
+ }
+ break;
+
+ case 0x18:
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_videoaddr = VIDEOADDR;
+ m_chargenaddr = CHARGENADDR;
+ m_bitmapaddr = BITMAPADDR;
+ }
+ break;
+
+ case 0x21: /* background color */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_mono[0] = m_bitmapmulti[0] = m_multi[0] = m_colors[0] = BACKGROUNDCOLOR;
+ }
+ break;
+
+ case 0x22: /* background color 1 */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_multi[1] = m_colors[1] = MULTICOLOR1;
+ }
+ break;
+
+ case 0x23: /* background color 2 */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_multi[2] = m_colors[2] = MULTICOLOR2;
+ }
+ break;
+
+ case 0x24: /* background color 3 */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ m_colors[3] = FOREGROUNDCOLOR;
+ }
+ break;
+
+ case 0x20: /* framecolor */
+ if (m_reg[offset] != data)
+ {
+ m_reg[offset] = data;
+ }
+ break;
+
+ case 0x2f:
+ DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
+ m_reg[offset] = data;
+ break;
+ case 0x30:
+ m_reg[offset] = data;
+ if (!m_port_changed_cb.isnull())
+ {
+ DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
+ m_reg[offset] = data;
+ m_port_changed_cb((offs_t)0,data);
+ }
+ break;
+ case 0x31:
+ m_reg[offset] = data;
+ if (data & 0x40)
+ m_cpu->set_clock_scale(1.0);
+ else
+ m_cpu->set_clock_scale(1.0/3.5);
+ break;
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b:
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f:
+ m_reg[offset] = data;
+ DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
+ break;
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ DBG_LOG(2, "vic plane write", ("%.2x:%.2x\n", offset, data));
+ break;
+ default:
+ m_reg[offset] = data;
+ break;
+ }
+}
+
+READ8_MEMBER( vic3_device::port_r )
+{
+ int val = 0;
+ offset &= 0x7f;
+
+ /* offsets 0x00 -> 0x2e coincide with VICII */
+ switch (offset)
+ {
+ case 0x11:
+ val = (m_reg[offset] & ~0x80) | ((m_rasterline & 0x100) >> 1);
+ break;
+
+ case 0x12:
+ val = m_rasterline & 0xff;
+ break;
+
+ case 0x16:
+ val = m_reg[offset] | 0xc0;
+ break;
+
+ case 0x18:
+ val = m_reg[offset] | 0x01;
+ break;
+
+ case 0x19: /* interrupt flag register */
+ /* vic2_clear_interrupt(0xf); */
+ val = m_reg[offset] | 0x70;
+ break;
+
+ case 0x1a:
+ val = m_reg[offset] | 0xf0;
+ break;
+
+ case 0x1e: /* sprite to sprite collision detect */
+ val = m_reg[offset];
+ m_reg[offset] = 0;
+ clear_interrupt(4);
+ break;
+
+ case 0x1f: /* sprite to background collision detect */
+ val = m_reg[offset];
+ m_reg[offset] = 0;
+ clear_interrupt(2);
+ break;
+
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ val = m_reg[offset];
+ break;
+
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ case 0x10:
+ case 0x17:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ val = m_reg[offset];
+ break;
+
+ case 0x2f:
+ case 0x30:
+ val = m_reg[offset];
+ DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
+ break;
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b:
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f: /* not used */
+ val = m_reg[offset];
+ DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
+ break;
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ DBG_LOG(2, "vic3 plane read", ("%.2x:%.2x\n", offset, val));
+ break;
+ default:
+ val = m_reg[offset];
+ }
+ return val;
+}
+
+
+#define VIC3_MASK(M) \
+ if (M) \
+ { \
+ if (M & 0x01) \
+ colors[0] = m_c64_mem_r_cb(VIC3_ADDR(0) + offset); \
+ if (M & 0x02) \
+ colors[1] = m_c64_mem_r_cb(VIC3_ADDR(1) + offset) << 1; \
+ if (M & 0x04) \
+ colors[2] = m_c64_mem_r_cb(VIC3_ADDR(2) + offset) << 2; \
+ if (M & 0x08) \
+ colors[3] = m_c64_mem_r_cb(VIC3_ADDR(3) + offset) << 3; \
+ if (M & 0x10) \
+ colors[4] = m_c64_mem_r_cb(VIC3_ADDR(4) + offset) << 4; \
+ if (M & 0x20) \
+ colors[5] = m_c64_mem_r_cb(VIC3_ADDR(5) + offset) << 5; \
+ if (M & 0x40) \
+ colors[6] = m_c64_mem_r_cb(VIC3_ADDR(6) + offset) << 6; \
+ if (M & 0x80) \
+ colors[7] = m_c64_mem_r_cb(VIC3_ADDR(7) + offset) << 7; \
+ for (i = 7; i >= 0; i--) \
+ { \
+ p = 0; \
+ if (M & 0x01) \
+ { \
+ p = colors[0] & 0x01; \
+ colors[0] >>= 1; \
+ } \
+ if (M & 0x02) \
+ { \
+ p |= colors[1] & 0x02; \
+ colors[1] >>= 1; \
+ } \
+ if (M & 0x04) \
+ { \
+ p |= colors[2] & 0x04; \
+ colors[2] >>= 1; \
+ } \
+ if (M & 0x08) \
+ { \
+ p |= colors[3] & 0x08; \
+ colors[3] >>= 1; \
+ } \
+ if (M & 0x10) \
+ { \
+ p |= colors[4] & 0x10; \
+ colors[4] >>= 1; \
+ } \
+ if (M & 0x20) \
+ { \
+ p |= colors[5] & 0x20; \
+ colors[5] >>= 1; \
+ } \
+ if (M & 0x40) \
+ { \
+ p |= colors[6] & 0x40; \
+ colors[6] >>= 1; \
+ } \
+ if (M & 0x80) \
+ { \
+ p |= colors[7] & 0x80; \
+ colors[7] >>= 1; \
+ } \
+ m_bitmap->pix16(YPOS + y, XPOS + x + i) = p; \
+ } \
+ }
+
+#define VIC3_ADDR(a) VIC3_BITPLANE_IADDR(a)
+void vic3_device::interlace_draw_block( int x, int y, int offset )
+{
+ int colors[8] = {0};
+ int i, p;
+
+ switch (VIC3_BITPLANES_MASK)
+ {
+ case 0x05:
+ VIC3_MASK(0x05)
+ break;
+ case 0x07:
+ VIC3_MASK(0x07)
+ break;
+ case 0x0f:
+ VIC3_MASK(0x0f)
+ break;
+ case 0x1f:
+ VIC3_MASK(0x1f)
+ break;
+ case 0x7f:
+ VIC3_MASK(0x7f)
+ break;
+ case 0xff:
+ VIC3_MASK(0xff)
+ break;
+ default:
+ if (VIC3_BITPLANES_MASK & 0x01)
+ colors[0] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(0) + offset);
+
+ if (VIC3_BITPLANES_MASK & 0x02)
+ colors[1] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(1) + offset) << 1;
+
+ if (VIC3_BITPLANES_MASK & 0x04)
+ colors[2] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(2) + offset) << 2;
+
+ if (VIC3_BITPLANES_MASK & 0x08)
+ colors[3] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(3) + offset) << 3;
+
+ if (VIC3_BITPLANES_MASK & 0x10)
+ colors[4] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(4) + offset) << 4;
+
+ if (VIC3_BITPLANES_MASK & 0x20)
+ colors[5] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(5) + offset) << 5;
+
+ if (VIC3_BITPLANES_MASK & 0x40)
+ colors[6] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(6) + offset) << 6;
+
+ if (VIC3_BITPLANES_MASK & 0x80)
+ colors[7] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(7) + offset) << 7;
+
+ for (i = 7; i >= 0; i--)
+ {
+ m_bitmap->pix16(YPOS + y, XPOS + x + i) =
+ (colors[0] & 0x01) | (colors[1] & 0x02)
+ | (colors[2] & 0x04) | (colors[3] & 0x08)
+ | (colors[4] & 0x10) | (colors[5] & 0x20)
+ | (colors[6] & 0x40) | (colors[7] & 0x80);
+ colors[0] >>= 1;
+ colors[1] >>= 1;
+ colors[2] >>= 1;
+ colors[3] >>= 1;
+ colors[4] >>= 1;
+ colors[5] >>= 1;
+ colors[6] >>= 1;
+ colors[7] >>= 1;
+ }
+ }
+}
+
+#undef VIC3_ADDR
+#define VIC3_ADDR(a) VIC3_BITPLANE_ADDR(a)
+void vic3_device::draw_block( int x, int y, int offset )
+{
+ int colors[8] = {0};
+ int i, p;
+
+ switch (VIC3_BITPLANES_MASK)
+ {
+ case 5:
+ VIC3_MASK(0x05)
+ break;
+ case 7:
+ VIC3_MASK(0x07)
+ break;
+ case 0xf:
+ VIC3_MASK(0x0f)
+ break;
+ case 0x1f:
+ VIC3_MASK(0x1f)
+ break;
+ case 0x7f:
+ VIC3_MASK(0x7f)
+ break;
+ case 0xff:
+ VIC3_MASK(0xff)
+ break;
+ default:
+ if (VIC3_BITPLANES_MASK & 0x01)
+ colors[0] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(0) + offset);
+
+ if (VIC3_BITPLANES_MASK & 0x02)
+ colors[1] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(1) + offset) << 1;
+
+ if (VIC3_BITPLANES_MASK & 0x04)
+ colors[2] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(2) + offset) << 2;
+
+ if (VIC3_BITPLANES_MASK & 0x08)
+ colors[3] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(3) + offset) << 3;
+
+ if (VIC3_BITPLANES_MASK & 0x10)
+ colors[4] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(4) + offset) << 4;
+
+ if (VIC3_BITPLANES_MASK & 0x20)
+ colors[5] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(5) + offset) << 5;
+
+ if (VIC3_BITPLANES_MASK & 0x40)
+ colors[6] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(6) + offset) << 6;
+
+ if (VIC3_BITPLANES_MASK & 0x80)
+ colors[7] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(7) + offset) << 7;
+
+ for (i = 7; i >= 0; i--)
+ {
+ m_bitmap->pix16(YPOS + y, XPOS + x + i) =
+ (colors[0] & 0x01) | (colors[1] & 0x02)
+ | (colors[2] & 0x04) | (colors[3] & 0x08)
+ | (colors[4] & 0x10) | (colors[5] & 0x20)
+ | (colors[6] & 0x40) | (colors[7] & 0x80);
+ colors[0] >>= 1;
+ colors[1] >>= 1;
+ colors[2] >>= 1;
+ colors[3] >>= 1;
+ colors[4] >>= 1;
+ colors[5] >>= 1;
+ colors[6] >>= 1;
+ colors[7] >>= 1;
+ }
+ }
+}
+
+
+void vic3_device::draw_bitplanes()
+{
+ int x, y, y1s, offset;
+ rectangle vis;
+ const rectangle &visarea = m_screen->visible_area();
+
+ if (VIC3_LINES == 400)
+ { /* interlaced! */
+ for (y1s = 0, offset = 0; y1s < 400; y1s += 16)
+ {
+ for (x = 0; x < VIC3_BITPLANES_WIDTH; x += 8)
+ {
+ for (y = y1s; y < y1s + 16; y += 2, offset++)
+ {
+ if (m_interlace)
+ draw_block(x, y, offset);
+ else
+ interlace_draw_block(x, y + 1, offset);
+ }
+ }
+ }
+ m_interlace ^= 1;
+ }
+ else
+ {
+ for (y1s = 0, offset = 0; y1s < 200; y1s += 8)
+ {
+ for (x = 0; x < VIC3_BITPLANES_WIDTH; x += 8)
+ {
+ for (y = y1s; y < y1s + 8; y++, offset++)
+ {
+ draw_block(x, y, offset);
+ }
+ }
+ }
+ }
+
+ if (XPOS > 0)
+ {
+ vis.set(0, XPOS - 1, 0, visarea.max_y);
+ m_bitmap->fill(FRAMECOLOR, vis);
+ }
+
+ if (XPOS + VIC3_BITPLANES_WIDTH < visarea.max_x)
+ {
+ vis.set(XPOS + VIC3_BITPLANES_WIDTH, visarea.max_x, 0, visarea.max_y);
+ m_bitmap->fill(FRAMECOLOR, vis);
+ }
+
+ if (YPOS > 0)
+ {
+ vis.set(0, visarea.max_x, 0, YPOS - 1);
+ m_bitmap->fill(FRAMECOLOR, vis);
+ }
+
+ if (YPOS + VIC3_LINES < visarea.max_y)
+ {
+ vis.set(0, visarea.max_x, YPOS + VIC3_LINES, visarea.max_y);
+ m_bitmap->fill(FRAMECOLOR, vis);
+ }
+}
+
+void vic3_device::raster_interrupt_gen()
+{
+ int new_columns, new_rows;
+ int i;
+
+ m_rasterline++;
+ if (m_rasterline >= m_lines)
+ {
+ m_rasterline = 0;
+ if (m_palette_dirty)
+ for (i = 0; i < 256; i++)
+ m_palette->set_pen_color(i, m_palette_red[i] << 4, m_palette_green[i] << 4, m_palette_blue[i] << 4);
+
+ if (m_palette_dirty)
+ {
+ m_spritemulti[1] = SPRITE_MULTICOLOR1;
+ m_spritemulti[3] = SPRITE_MULTICOLOR2;
+ m_mono[0] = m_bitmapmulti[0] = m_multi[0] = m_colors[0] = BACKGROUNDCOLOR;
+ m_multi[1] = m_colors[1] = MULTICOLOR1;
+ m_multi[2] = m_colors[2] = MULTICOLOR2;
+ m_colors[3] = FOREGROUNDCOLOR;
+ m_palette_dirty = 0;
+ }
+
+ new_rows = 200;
+
+ if (VIC3_BITPLANES)
+ {
+ new_columns = VIC3_BITPLANES_WIDTH;
+ if (new_columns < 320)
+ new_columns = 320; /*sprites resolution about 320x200 */
+ new_rows = VIC3_LINES;
+ }
+ else if (VIC3_80COLUMNS)
+ {
+ new_columns = 640;
+ }
+ else
+ {
+ new_columns = 320;
+ }
+ if ((new_columns != m_columns) || (new_rows != m_rows))
+ {
+ m_rows = new_rows;
+ m_columns = new_columns;
+ if (m_type == VIC4567_PAL)
+ m_screen->set_visible_area(
+ VIC2_STARTVISIBLECOLUMNS + 32,
+ VIC2_STARTVISIBLECOLUMNS + 32 + m_columns + 16 - 1,
+ VIC2_STARTVISIBLELINES + 34,
+ VIC2_STARTVISIBLELINES + 34 + m_rows + 16 - 1);
+ else
+ m_screen->set_visible_area(
+ VIC2_STARTVISIBLECOLUMNS + 34,
+ VIC2_STARTVISIBLECOLUMNS + 34 + m_columns + 16 - 1,
+ VIC2_STARTVISIBLELINES + 10,
+ VIC2_STARTVISIBLELINES + 10 + m_rows + 16 - 1);
+ }
+ if (VIC3_BITPLANES)
+ {
+ draw_bitplanes();
+ }
+ else
+ {
+ if (m_type == VIC4567_PAL)
+ {
+ if (m_on)
+ vic2_drawlines(m_lastline, m_lines, VIC2_STARTVISIBLECOLUMNS + 32, VIC2_STARTVISIBLECOLUMNS + 32 + m_columns + 16 - 1);
+ }
+ else
+ {
+ if (m_on)
+ vic2_drawlines(m_lastline, m_lines, VIC2_STARTVISIBLECOLUMNS + 34, VIC2_STARTVISIBLECOLUMNS + 34 + m_columns + 16 - 1);
+ }
+ }
+
+ for (i = 0; i < 8; i++)
+ m_sprites[i].repeat = m_sprites[i].line = 0;
+
+ m_lastline = 0;
+
+ if (LIGHTPEN_BUTTON)
+ {
+ /* lightpen timer start */
+ machine().scheduler().timer_set(attotime(0, 0), timer_expired_delegate(FUNC(vic3_device::timer_timeout),this), 1);
+ }
+
+ }
+
+ if (m_rasterline == C64_2_RASTERLINE(RASTERLINE))
+ {
+ set_interrupt(1);
+ }
+
+ if (m_on)
+ if ((m_rasterline >= VIC2_FIRSTRASTERLINE) && (m_rasterline < (VIC2_FIRSTRASTERLINE + VIC2_VISIBLELINES)))
+ {
+ if (m_type == VIC4567_PAL)
+ {
+ if (m_on)
+ vic2_drawlines(m_rasterline - 1, m_rasterline, VIC2_STARTVISIBLECOLUMNS + 32, VIC2_STARTVISIBLECOLUMNS + 32 + m_columns + 16 - 1);
+ }
+ else
+ {
+ if (m_on)
+ vic2_drawlines(m_rasterline - 1, m_rasterline, VIC2_STARTVISIBLECOLUMNS + 34, VIC2_STARTVISIBLECOLUMNS + 34 + m_columns + 16 - 1);
+ }
+ }
+}
+
+UINT32 vic3_device::video_update( bitmap_ind16 &bitmap, const rectangle &cliprect )
+{
+ copybitmap(bitmap, *m_bitmap, 0, 0, 0, 0, cliprect);
+ return 0;
+}
+
+
+static MACHINE_CONFIG_FRAGMENT( vic3 )
+ MCFG_PALETTE_ADD_INIT_BLACK("palette", 0x100)
+MACHINE_CONFIG_END
+
+//-------------------------------------------------
+// machine_config_additions - return a pointer to
+// the device's machine fragment
+//-------------------------------------------------
+
+machine_config_constructor vic3_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( vic3 );
+}