diff options
Diffstat (limited to 'src/mess/video/vic4567.c')
-rw-r--r-- | src/mess/video/vic4567.c | 2165 |
1 files changed, 2165 insertions, 0 deletions
diff --git a/src/mess/video/vic4567.c b/src/mess/video/vic4567.c new file mode 100644 index 00000000000..5284cf721c3 --- /dev/null +++ b/src/mess/video/vic4567.c @@ -0,0 +1,2165 @@ +/*************************************************************************** + + 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" + +#define SPRITE_BASE_X_SIZE 24 +#define SPRITE_BASE_Y_SIZE 21 + +struct vic3_sprite +{ + int x, y; + + int repeat; /* expand, line once drawn */ + int line; /* 0 not painting, else painting */ + + /* buffer for currently painted line */ + int paintedline[8]; + UINT8 bitmap[8][SPRITE_BASE_X_SIZE * 2 / 8 + 1 /*for simplier sprite collision detection*/]; +}; + +typedef struct _vic3_state vic3_state; +struct _vic3_state +{ + vic3_type type; + + screen_device *main_screen; // screen which sets bitmap properties + + device_t *cpu; + + UINT8 reg[0x80]; + int on; /* rastering of the screen */ + + int lines; + + UINT16 chargenaddr, videoaddr, bitmapaddr; + + bitmap_ind16 *bitmap; + int x_begin, x_end; + int y_begin, y_end; + + UINT16 c64_bitmap[2], bitmapmulti[4], mono[2], multi[4], ecmcolor[2], colors[4], spritemulti[4]; + + int lastline, rasterline; + + int interlace; + int columns, rows; + + /* background/foreground for sprite collision */ + UINT8 *screen[216], shift[216]; + + /* convert multicolor byte to background/foreground for sprite collision */ + UINT8 foreground[256]; + UINT16 expandx[256]; + UINT16 expandx_multi[256]; + + /* converts sprite multicolor info to info for background collision checking */ + UINT8 multi_collision[256]; + + vic3_sprite sprites[8]; + + /* DMA */ + vic3_dma_read dma_read; + vic3_dma_read_color dma_read_color; + + /* IRQ */ + vic3_irq interrupt; + + /* Port Changed */ + vic3_port_changed_callback port_changed; + + /* lightpen */ + vic3_lightpen_button_callback lightpen_button_cb; + vic3_lightpen_x_callback lightpen_x_cb; + vic3_lightpen_y_callback lightpen_y_cb; + + /* C64 memory access */ + vic3_c64mem_callback c64_mem_r; + + /* palette - vic3 specific items (the ones above are used for VIC II as well) */ + UINT8 palette_red[0x100]; + UINT8 palette_green[0x100]; + UINT8 palette_blue[0x100]; + int palette_dirty; +}; + +/***************************************************************************** + CONSTANTS +*****************************************************************************/ + +#define VERBOSE_LEVEL 0 +#define DBG_LOG(N,M,A) \ + do { \ + if(VERBOSE_LEVEL >= N) \ + { \ + if( M ) \ + logerror("%11.6f: %-24s", device->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 (vic3->lightpen_button_cb(machine)) +#define LIGHTPEN_X_VALUE (vic3->lightpen_x_cb(machine)) +#define LIGHTPEN_Y_VALUE (vic3->lightpen_y_cb(machine)) + +/* 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 ((vic3->type == VIC4567_PAL) ? VIC6569_X_BEGIN : VIC6567_X_BEGIN) +#define VIC2_Y_BEGIN ((vic3->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 (vic3->reg[0x2f] & 0x01) +#define VIC2E_K1_LEVEL (vic3->reg[0x2f] & 0x02) +#define VIC2E_K2_LEVEL (vic3->reg[0x2f] & 0x04) + +/*#define VIC3_P5_LEVEL (vic3->reg[0x30] & 0x20) */ +#define VIC3_BITPLANES (vic3->reg[0x31] & 0x10) +#define VIC3_80COLUMNS (vic3->reg[0x31] & 0x80) +#define VIC3_LINES ((vic3->reg[0x31] & 0x19) == 0x19 ? 400 : 200) +#define VIC3_BITPLANES_WIDTH (vic3->reg[0x31] & 0x80 ? 640 : 320) + +/*#define VIC2E_TEST (vic2[0x30] & 2) */ +#define DOUBLE_CLOCK (vic3->reg[0x30] & 0x01) + +/* sprites 0 .. 7 */ +#define SPRITEON(nr) (vic3->reg[0x15] & (1 << nr)) +#define SPRITE_Y_EXPAND(nr) (vic3->reg[0x17] & (1 << nr)) +#define SPRITE_Y_SIZE(nr) (SPRITE_Y_EXPAND(nr) ? 2 * 21 : 21) +#define SPRITE_X_EXPAND(nr) (vic3->reg[0x1d] & (1 << nr)) +#define SPRITE_X_SIZE(nr) (SPRITE_X_EXPAND(nr) ? 2 * 24 : 24) +#define SPRITE_X_POS(nr) ((vic3->reg[(nr) * 2] | (vic3->reg[0x10] & (1 <<(nr)) ? 0x100 : 0)) - 24 + XPOS) +#define SPRITE_X_POS2(nr) (vic3->reg[(nr) * 2] | (vic3->reg[0x10] & (1 <<(nr)) ? 0x100 : 0)) +#define SPRITE_Y_POS(nr) (vic3->reg[1+2*(nr)] - 50 + YPOS) +#define SPRITE_Y_POS2(nr) (vic3->reg[1 + 2 *(nr)]) +#define SPRITE_MULTICOLOR(nr) (vic3->reg[0x1c] & (1 << nr)) +#define SPRITE_PRIORITY(nr) (vic3->reg[0x1b] & (1 << nr)) +#define SPRITE_MULTICOLOR1 (vic3->reg[0x25] & 0x0f) +#define SPRITE_MULTICOLOR2 (vic3->reg[0x26] & 0x0f) +#define SPRITE_COLOR(nr) (vic3->reg[0x27+nr] & 0x0f) +#define SPRITE_ADDR(nr) (vic3->videoaddr | 0x3f8 | nr) +#define SPRITE_BG_COLLISION(nr) (vic3->reg[0x1f] & (1 << nr)) +#define SPRITE_COLLISION(nr) (vic3->reg[0x1e] & (1 << nr)) +#define SPRITE_SET_BG_COLLISION(nr) (vic3->reg[0x1f] |= (1 << nr)) +#define SPRITE_SET_COLLISION(nr) (vic3->reg[0x1e] |= (1 << nr)) +#define SPRITE_COLL (vic3->reg[0x1e]) +#define SPRITE_BG_COLL (vic3->reg[0x1f]) + +#define GFXMODE ((vic3->reg[0x11] & 0x60) | (vic3->reg[0x16] & 0x10)) >> 4 +#define SCREENON (vic3->reg[0x11] & 0x10) +#define VERTICALPOS (vic3->reg[0x11] & 0x07) +#define HORIZONTALPOS (vic3->reg[0x16] & 0x07) +#define ECMON (vic3->reg[0x11] & 0x40) +#define HIRESON (vic3->reg[0x11] & 0x20) +#define MULTICOLORON (vic3->reg[0x16] & 0x10) +#define LINES25 (vic3->reg[0x11] & 0x08) /* else 24 Lines */ +#define LINES (LINES25 ? 25 : 24) +#define YSIZE (LINES * 8) +#define COLUMNS40 (vic3->reg[0x16] & 0x08) /* else 38 Columns */ +#define COLUMNS (COLUMNS40 ? 40 : 38) +#define XSIZE (COLUMNS * 8) + +#define VIDEOADDR ((vic3->reg[0x18] & 0xf0) << (10 - 4)) +#define CHARGENADDR ((vic3->reg[0x18] & 0x0e) << 10) +#define BITMAPADDR ((data & 0x08) << 10) + +#define RASTERLINE (((vic3->reg[0x11] & 0x80) << 1) | vic3->reg[0x12]) + +#define FRAMECOLOR (vic3->reg[0x20] & 0x0f) +#define BACKGROUNDCOLOR (vic3->reg[0x21] & 0x0f) +#define MULTICOLOR1 (vic3->reg[0x22] & 0x0f) +#define MULTICOLOR2 (vic3->reg[0x23] & 0x0f) +#define FOREGROUNDCOLOR (vic3->reg[0x24] & 0x0f) + + +#define VIC2_LINES (vic3->type == VIC4567_PAL ? VIC6569_LINES : VIC6567_LINES) +#define VIC2_VISIBLELINES (vic3->type == VIC4567_PAL ? VIC6569_VISIBLELINES : VIC6567_VISIBLELINES) +#define VIC2_VISIBLECOLUMNS (vic3->type == VIC4567_PAL ? VIC6569_VISIBLECOLUMNS : VIC6567_VISIBLECOLUMNS) +#define VIC2_STARTVISIBLELINES ((VIC2_LINES - VIC2_VISIBLELINES)/2) +#define VIC2_FIRSTRASTERLINE (vic3->type == VIC4567_PAL ? VIC6569_FIRSTRASTERLINE : VIC6567_FIRSTRASTERLINE) +#define VIC2_COLUMNS (vic3->type == VIC4567_PAL ? VIC6569_COLUMNS : VIC6567_COLUMNS) +#define VIC2_STARTVISIBLECOLUMNS ((VIC2_COLUMNS - VIC2_VISIBLECOLUMNS)/2) + +#define VIC3_BITPLANES_MASK (vic3->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) ((vic3->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) ((vic3->reg[0x33 + x] & 0xf0) << 8) +#define VIC3_BITPLANE_IADDR(x) (x & 1 ? VIC3_BITPLANE_IADDR_HELPER(x) + 0x10000 : VIC3_BITPLANE_IADDR_HELPER(x)) + + +/***************************************************************************** + INLINE FUNCTIONS +*****************************************************************************/ + +INLINE vic3_state *get_safe_token( device_t *device ) +{ + assert(device != NULL); + assert(device->type() == VIC3); + + return (vic3_state *)downcast<legacy_device_base *>(device)->token(); +} + +INLINE const vic3_interface *get_interface( device_t *device ) +{ + assert(device != NULL); + assert((device->type() == VIC3)); + return (const vic3_interface *) device->static_config(); +} + +/***************************************************************************** + IMPLEMENTATION +*****************************************************************************/ + +INLINE int vic3_getforeground( device_t *device, int y, int x ) +{ + vic3_state *vic3 = get_safe_token(device); + return ((vic3->screen[y][x >> 3] << 8) | (vic3->screen[y][(x >> 3) + 1])) >> (8 - (x & 7)); +} + +INLINE int vic3_getforeground16(device_t *device, int y, int x ) +{ + vic3_state *vic3 = get_safe_token(device); + return ((vic3->screen[y][x >> 3] << 16) | (vic3->screen[y][(x >> 3) + 1] << 8) | (vic3->screen[y][(x >> 3) + 2])) >> (8 - (x & 7)); +} + +static void vic3_set_interrupt( running_machine &machine, int mask, vic3_state *vic3 ) +{ + if (((vic3->reg[0x19] ^ mask) & vic3->reg[0x1a] & 0xf)) + { + if (!(vic3->reg[0x19] & 0x80)) + { + //DBG_LOG(2, "vic2", ("irq start %.2x\n", mask)); + vic3->reg[0x19] |= 0x80; + vic3->interrupt(machine, 1); + } + } + vic3->reg[0x19] |= mask; +} + +static void vic3_clear_interrupt( running_machine &machine, int mask, vic3_state *vic3 ) +{ + vic3->reg[0x19] &= ~mask; + if ((vic3->reg[0x19] & 0x80) && !(vic3->reg[0x19] & vic3->reg[0x1a] & 0xf)) + { + //DBG_LOG(2, "vic2", ("irq end %.2x\n", mask)); + vic3->reg[0x19] &= ~0x80; + vic3->interrupt(machine, 0); + } +} + +static TIMER_CALLBACK(vic3_timer_timeout) +{ + vic3_state *vic3 = (vic3_state *)ptr; + 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) + { + vic3->reg[0x13] = VIC2_X_VALUE; + vic3->reg[0x14] = VIC2_Y_VALUE; + } + vic3_set_interrupt(machine, 8, vic3); + break; + } +} +static void vic3_draw_character( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + int y, code; + + for (y = ybegin; y <= yend; y++) + { + code = vic3->dma_read(device->machine(), vic3->chargenaddr + ch * 8 + y); + vic3->screen[y + yoff][xoff >> 3] = code; + if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 0) = color[code >> 7]; + if ((xoff + 1 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 1) = color[(code >> 6) & 1]; + if ((xoff + 2 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 2) = color[(code >> 5) & 1]; + if ((xoff + 3 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 3) = color[(code >> 4) & 1]; + if ((xoff + 4 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 4) = color[(code >> 3) & 1]; + if ((xoff + 5 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 5) = color[(code >> 2) & 1]; + if ((xoff + 6 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 6) = color[(code >> 1) & 1]; + if ((xoff + 7 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 7) = color[code & 1]; + } +} + +static void vic3_draw_character_multi( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + int y, code; + + for (y = ybegin; y <= yend; y++) + { + code = vic3->dma_read(device->machine(), vic3->chargenaddr + ch * 8 + y); + vic3->screen[y + yoff][xoff >> 3] = vic3->foreground[code]; + if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 0) = vic3->multi[code >> 6]; + if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 1) = vic3->multi[code >> 6]; + if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 2) = vic3->multi[(code >> 4) & 3]; + if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 3) = vic3->multi[(code >> 4) & 3]; + if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 4) = vic3->multi[(code >> 2) & 3]; + if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 5) = vic3->multi[(code >> 2) & 3]; + if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 6) = vic3->multi[code & 3]; + if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 7) = vic3->multi[code & 3]; + } +} + +static void vic3_draw_bitmap( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + int y, code; + + for (y = ybegin; y <= yend; y++) + { + code = vic3->dma_read(device->machine(), (vic3->chargenaddr & 0x2000) + ch * 8 + y); + vic3->screen[y + yoff][xoff >> 3] = code; + if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 0) = vic3->c64_bitmap[code >> 7]; + if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 1) = vic3->c64_bitmap[(code >> 6) & 1]; + if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 2) = vic3->c64_bitmap[(code >> 5) & 1]; + if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 3) = vic3->c64_bitmap[(code >> 4) & 1]; + if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 4) = vic3->c64_bitmap[(code >> 3) & 1]; + if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 5) = vic3->c64_bitmap[(code >> 2) & 1]; + if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 6) = vic3->c64_bitmap[(code >> 1) & 1]; + if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 7) = vic3->c64_bitmap[code & 1]; + } +} + +static void vic3_draw_bitmap_multi( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + int y, code; + + for (y = ybegin; y <= yend; y++) + { + code = vic3->dma_read(device->machine(), (vic3->chargenaddr & 0x2000) + ch * 8 + y); + vic3->screen[y + yoff][xoff >> 3] = vic3->foreground[code]; + if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 0) = vic3->bitmapmulti[code >> 6]; + if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 1) = vic3->bitmapmulti[code >> 6]; + if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 2) = vic3->bitmapmulti[(code >> 4) & 3]; + if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 3) = vic3->bitmapmulti[(code >> 4) & 3]; + if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 4) = vic3->bitmapmulti[(code >> 2) & 3]; + if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 5) = vic3->bitmapmulti[(code >> 2) & 3]; + if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 6) = vic3->bitmapmulti[code & 3]; + if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) vic3->bitmap->pix16(y + yoff + FIRSTLINE, xoff + 7) = vic3->bitmapmulti[code & 3]; + } +} + +static void vic3_draw_sprite_code( device_t *device, int y, int xbegin, int code, int color, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + 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)) + vic3->bitmap->pix16(y + FIRSTLINE, xbegin + x) = color; + } + } +} + +static void vic3_draw_sprite_code_multi( device_t *device, int y, int xbegin, int code, int prior, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + 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)) + vic3->bitmap->pix16(y + FIRSTLINE, xbegin + x + 1) = vic3->spritemulti[(code >> shift) & 3]; + break; + case 2: + if ((xbegin + x > start_x) && (xbegin + x < end_x)) + vic3->bitmap->pix16(y + FIRSTLINE, xbegin + x) = vic3->spritemulti[(code >> shift) & 3]; + break; + case 3: + if ((xbegin + x > start_x) && (xbegin + x < end_x)) + vic3->bitmap->pix16(y + FIRSTLINE, xbegin + x) = vic3->spritemulti[(code >> shift) & 3]; + if ((xbegin + x + 1> start_x) && (xbegin + x + 1< end_x)) + vic3->bitmap->pix16(y + FIRSTLINE, xbegin + x + 1) = vic3->spritemulti[(code >> shift) & 3]; + break; + } + } + } +} + +static void vic3_sprite_collision( device_t *device, int nr, int y, int x, int mask ) +{ + vic3_state *vic3 = get_safe_token(device); + int i, value, xdiff; + + for (i = 7; i > nr; i--) + { + if (!SPRITEON(i) || !vic3->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 = vic3->sprites[i].bitmap[y][xdiff >> 3]; + else if (xdiff < 0) + value = vic3->sprites[i].bitmap[y][0] >> (-xdiff); + else { + UINT8 *vp = vic3->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); + vic3_set_interrupt(device->machine(), 4, vic3); + } + } +} + +static void vic3_draw_sprite( device_t *device, int nr, int yoff, int ybegin, int yend, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + int y, i, addr, xbegin, color, prior, collision; + int value, value3 = 0; + + xbegin = SPRITE_X_POS(nr); + addr = vic3->dma_read(device->machine(), 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++) + { + vic3->sprites[nr].paintedline[y] = 1; + for (i = 0; i < 3; i++) + { + value = vic3->expandx[vic3->dma_read(device->machine(), addr + vic3->sprites[nr].line * 3 + i)]; + vic3->sprites[nr].bitmap[y][i * 2] = value >> 8; + vic3->sprites[nr].bitmap[y][i * 2 + 1] = value & 0xff; + vic3_sprite_collision(device, nr, y, xbegin + i * 16, value >> 8); + vic3_sprite_collision(device, nr, y, xbegin + i * 16 + 8, value & 0xff); + if (prior || !collision) + value3 = vic3_getforeground16(device, yoff + y, xbegin + i * 16 - 7); + if (!collision && (value & value3)) + { + collision = 1; + SPRITE_SET_BG_COLLISION(nr); + vic3_set_interrupt(device->machine(), 2, vic3); + } + if (prior) + value &= ~value3; + vic3_draw_sprite_code(device, yoff + y, xbegin + i * 16, value >> 8, color, start_x, end_x); + vic3_draw_sprite_code(device, yoff + y, xbegin + i * 16 + 8, value & 0xff, color, start_x, end_x); + } + vic3->sprites[nr].bitmap[y][i * 2]=0; //easier sprite collision detection + if (SPRITE_Y_EXPAND(nr)) + { + if (vic3->sprites[nr].repeat) + { + vic3->sprites[nr].line++; + vic3->sprites[nr].repeat = 0; + } + else + vic3->sprites[nr].repeat = 1; + } + else + { + vic3->sprites[nr].line++; + } + } + } + else + { + for (y = ybegin; y <= yend; y++) + { + vic3->sprites[nr].paintedline[y] = 1; + for (i = 0; i < 3; i++) + { + value = vic3->dma_read(device->machine(), addr + vic3->sprites[nr].line * 3 + i); + vic3->sprites[nr].bitmap[y][i] = value; + vic3_sprite_collision(device, nr, y, xbegin + i * 8, value); + if (prior || !collision) + value3 = vic3_getforeground(device, yoff + y, xbegin + i * 8 - 7); + if (!collision && (value & value3)) + { + collision = 1; + SPRITE_SET_BG_COLLISION(nr); + vic3_set_interrupt(device->machine(), 2, vic3); + } + if (prior) + value &= ~value3; + vic3_draw_sprite_code(device, yoff + y, xbegin + i * 8, value, color, start_x, end_x); + } + vic3->sprites[nr].bitmap[y][i]=0; //easier sprite collision detection + if (SPRITE_Y_EXPAND(nr)) + { + if (vic3->sprites[nr].repeat) + { + vic3->sprites[nr].line++; + vic3->sprites[nr].repeat = 0; + } + else + vic3->sprites[nr].repeat = 1; + } + else + { + vic3->sprites[nr].line++; + } + } + } +} + +static void vic3_draw_sprite_multi( device_t *device, int nr, int yoff, int ybegin, int yend, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + int y, i, prior, addr, xbegin, collision; + int value, value2, value3 = 0, bg/*, color[2]*/; + + xbegin = SPRITE_X_POS(nr); + addr = vic3->dma_read(device->machine(), SPRITE_ADDR(nr)) << 6; + vic3->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++) + { + vic3->sprites[nr].paintedline[y] = 1; + for (i = 0; i < 3; i++) + { + value = vic3->expandx_multi[bg = vic3->dma_read(device->machine(), addr + vic3->sprites[nr].line * 3 + i)]; + value2 = vic3->expandx[vic3->multi_collision[bg]]; + vic3->sprites[nr].bitmap[y][i * 2] = value2 >> 8; + vic3->sprites[nr].bitmap[y][i * 2 + 1] = value2 & 0xff; + vic3_sprite_collision(device, nr, y, xbegin + i * 16, value2 >> 8); + vic3_sprite_collision(device, nr, y, xbegin + i * 16 + 8, value2 & 0xff); + if (prior || !collision) + { + value3 = vic3_getforeground16(device, yoff + y, xbegin + i * 16 - 7); + } + if (!collision && (value2 & value3)) + { + collision = 1; + SPRITE_SET_BG_COLLISION(nr); + vic3_set_interrupt(device->machine(), 2, vic3); + } + if (prior) + { + vic3_draw_sprite_code_multi(device, yoff + y, xbegin + i * 16, value >> 8, (value3 >> 8) ^ 0xff, start_x, end_x); + vic3_draw_sprite_code_multi(device, yoff + y, xbegin + i * 16 + 8, value & 0xff, (value3 & 0xff) ^ 0xff, start_x, end_x); + } + else + { + vic3_draw_sprite_code_multi(device, yoff + y, xbegin + i * 16, value >> 8, 0xff, start_x, end_x); + vic3_draw_sprite_code_multi(device, yoff + y, xbegin + i * 16 + 8, value & 0xff, 0xff, start_x, end_x); + } + } + vic3->sprites[nr].bitmap[y][i * 2]=0; //easier sprite collision detection + if (SPRITE_Y_EXPAND(nr)) + { + if (vic3->sprites[nr].repeat) + { + vic3->sprites[nr].line++; + vic3->sprites[nr].repeat = 0; + } + else + vic3->sprites[nr].repeat = 1; + } + else + { + vic3->sprites[nr].line++; + } + } + } + else + { + for (y = ybegin; y <= yend; y++) + { + vic3->sprites[nr].paintedline[y] = 1; + for (i = 0; i < 3; i++) + { + value = vic3->dma_read(device->machine(), addr + vic3->sprites[nr].line * 3 + i); + vic3->sprites[nr].bitmap[y][i] = value2 = vic3->multi_collision[value]; + vic3_sprite_collision(device, nr, y, xbegin + i * 8, value2); + if (prior || !collision) + { + value3 = vic3_getforeground(device, yoff + y, xbegin + i * 8 - 7); + } + if (!collision && (value2 & value3)) + { + collision = 1; + SPRITE_SET_BG_COLLISION(nr); + vic3_set_interrupt(device->machine(), 2, vic3); + } + if (prior) + { + vic3_draw_sprite_code_multi(device, yoff + y, xbegin + i * 8, value, value3 ^ 0xff, start_x, end_x); + } + else + { + vic3_draw_sprite_code_multi(device, yoff + y, xbegin + i * 8, value, 0xff, start_x, end_x); + } + } + vic3->sprites[nr].bitmap[y][i] = 0; //easier sprite collision detection + if (SPRITE_Y_EXPAND(nr)) + { + if (vic3->sprites[nr].repeat) + { + vic3->sprites[nr].line++; + vic3->sprites[nr].repeat = 0; + } + else + vic3->sprites[nr].repeat = 1; + } + else + { + vic3->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 + +static void vic3_drawlines( device_t *device, int first, int last, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + 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; + vic3->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++) + vic3->sprites[i].repeat = vic3->sprites[i].line = 0; + return; + } + if (first < 0) + first = 0; + + if (!SCREENON) + { + for (line = first; (line < last) && (line < vic3->bitmap->height()); line++) + { + memset16(&vic3->bitmap->pix16(line + FIRSTLINE), 0, vic3->bitmap->width()); + } + return; + } + if (COLUMNS40) + xbegin = XPOS, xend = xbegin + 640; + else + xbegin = XPOS + 7, xend = xbegin + 624; + + if (last < vic3->y_begin) + end = last; + else + end = vic3->y_begin + YPOS; + + for (line = first; line < end; line++) + { + memset16(&vic3->bitmap->pix16(line + FIRSTLINE), FRAMECOLOR, vic3->bitmap->width()); + } + + if (LINES25) + { + vline = line - vic3->y_begin - YPOS; + } + else + { + vline = line - vic3->y_begin - YPOS + 8 - VERTICALPOS; + } + if (last < vic3->y_end + YPOS) + end = last; + else + end = vic3->y_end + YPOS; + x_end2 = vic3->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 */ + vic3->shift[line] = HORIZONTALPOS; + + for (xoff = vic3->x_begin + XPOS; xoff < x_end2 + XPOS; xoff += 8, offs++) + { + ch = vic3->dma_read(device->machine(), vic3->videoaddr + offs); + attr = vic3->dma_read_color(device->machine(), vic3->videoaddr + offs); + if (HIRESON) + { + vic3->bitmapmulti[1] = vic3->c64_bitmap[1] = ch >> 4; + vic3->bitmapmulti[2] = vic3->c64_bitmap[0] = ch & 0xf; + if (MULTICOLORON) + { + vic3->bitmapmulti[3] = attr; + vic3_draw_bitmap_multi(device, ybegin, yend, offs, yoff, xoff, start_x, end_x); + } + else + { + vic3_draw_bitmap(device, ybegin, yend, offs, yoff, xoff, start_x, end_x); + } + } + else if (ECMON) + { + ecm = ch >> 6; + vic3->ecmcolor[0] = vic3->colors[ecm]; + vic3->ecmcolor[1] = attr; + vic3_draw_character(device, ybegin, yend, ch & ~0xC0, yoff, xoff, vic3->ecmcolor, start_x, end_x); + } + else if (MULTICOLORON && (attr & 8)) + { + vic3->multi[3] = attr & 7; + vic3_draw_character_multi(device, ybegin, yend, ch, yoff, xoff, start_x, end_x); + } + else + { + vic3->mono[1] = attr; + vic3_draw_character(device, ybegin, yend, ch, yoff, xoff, vic3->mono, start_x, end_x); + } + } + /* sprite priority, sprite overwrites lowerprior pixels */ + for (i = 7; i >= 0; i--) + { + if (vic3->sprites[i].line || vic3->sprites[i].repeat) + { + syend = yend; + if (SPRITE_Y_EXPAND(i)) + { + if ((21 - vic3->sprites[i].line) * 2 - vic3->sprites[i].repeat < yend - ybegin + 1) + syend = ybegin + (21 - vic3->sprites[i].line) * 2 - vic3->sprites[i].repeat - 1; + } + else + { + if (vic3->sprites[i].line + yend - ybegin + 1 > 20) + syend = ybegin + 20 - vic3->sprites[i].line; + } + if (yoff + syend > YPOS + 200) + syend = YPOS + 200 - yoff - 1; + if (SPRITE_MULTICOLOR(i)) + vic3_draw_sprite_multi(device, i, yoff, ybegin, syend, start_x, end_x); + else + vic3_draw_sprite(device, i, yoff, ybegin, syend, start_x, end_x); + if ((syend != yend) || (vic3->sprites[i].line > 20)) + { + vic3->sprites[i].line = vic3->sprites[i].repeat = 0; + for (j = syend; j <= yend; j++) + vic3->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) vic3->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; + } + + vic3->sprites[i].line = wrapped; + + if (SPRITE_MULTICOLOR(i)) + vic3_draw_sprite_multi(device, i, yoff, 0 , syend, start_x, end_x); + else + vic3_draw_sprite(device, i, yoff, 0 , syend, start_x, end_x); + + if ((syend != yend) || (vic3->sprites[i].line > 20)) + { + for (j = syend; j <= yend; j++) + vic3->sprites[i].paintedline[j] = 0; + vic3->sprites[i].line = vic3->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++) + vic3->sprites[i].paintedline[j] = 0; + if (SPRITE_MULTICOLOR(i)) + vic3_draw_sprite_multi(device, i, yoff, SPRITE_Y_POS(i) - yoff, syend, start_x, end_x); + else + vic3_draw_sprite(device, i, yoff, SPRITE_Y_POS(i) - yoff, syend, start_x, end_x); + if ((syend != yend) || (vic3->sprites[i].line > 20)) + { + for (j = syend; j <= yend; j++) + vic3->sprites[i].paintedline[j] = 0; + vic3->sprites[i].line = vic3->sprites[i].repeat = 0; + } + } + else + { + memset (vic3->sprites[i].paintedline, 0, sizeof (vic3->sprites[i].paintedline)); + } + } + + for (i = ybegin; i <= yend; i++) + { + vic3->bitmap->plot_box(0, yoff + ybegin + FIRSTLINE, xbegin, yend-ybegin+1, FRAMECOLOR); + vic3->bitmap->plot_box(xend, yoff + ybegin + FIRSTLINE, vic3->bitmap->width() - xend, yend-ybegin+1, FRAMECOLOR); + } + } + if (last < vic3->bitmap->height()) + end = last; + else + end = vic3->bitmap->height(); + + for (; line < end; line++) + { + memset16 (&vic3->bitmap->pix16(line + FIRSTLINE), FRAMECOLOR, vic3->bitmap->width()); + } +} + +static void vic2_drawlines( device_t *device, int first, int last, int start_x, int end_x ) +{ + vic3_state *vic3 = get_safe_token(device); + 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 (vic3->reg[0x31] & 0x80) + { + vic3_drawlines(device, 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)) + vic3->bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR); + if ((start_x > xbegin) && (end_x >= xend)) + vic3->bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR); + if ((start_x <= xbegin) && (end_x < xend)) + vic3->bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR); + if ((start_x > xbegin) && (end_x < xend)) + vic3->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 < vic3->y_begin) + end = first + 1; + else + end = vic3->y_begin + YPOS; + + line = first; + // top border + if (line < end) + { + if ((start_x <= xbegin) && (end_x >= xend)) + vic3->bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR); + if ((start_x > xbegin) && (end_x >= xend)) + vic3->bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR); + if ((start_x <= xbegin) && (end_x < xend)) + vic3->bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR); + if ((start_x > xbegin) && (end_x < xend)) + vic3->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 < vic3->y_end + YPOS) + end = first + 1; + else + end = vic3->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 */ + + vic3->shift[line] = HORIZONTALPOS; + for (xoff = vic3->x_begin + XPOS; xoff < vic3->x_end + XPOS; xoff += 8, offs++) + { + ch = vic3->dma_read(device->machine(), vic3->videoaddr + offs); +#if 0 + attr = vic3->dma_read_color(device->machine(), vic3->videoaddr + offs); +#else + /* temporaery until vic3 finished */ + attr = vic3->dma_read_color(device->machine(), (vic3->videoaddr + offs)&0x3ff)&0x0f; +#endif + if (HIRESON) + { + vic3->bitmapmulti[1] = vic3->c64_bitmap[1] = ch >> 4; + vic3->bitmapmulti[2] = vic3->c64_bitmap[0] = ch & 0xf; + if (MULTICOLORON) + { + vic3->bitmapmulti[3] = attr; + vic3_draw_bitmap_multi(device, ybegin, yend, offs, yoff, xoff, start_x, end_x); + } + else + { + vic3_draw_bitmap(device, ybegin, yend, offs, yoff, xoff, start_x, end_x); + } + } + else if (ECMON) + { + ecm = ch >> 6; + vic3->ecmcolor[0] = vic3->colors[ecm]; + vic3->ecmcolor[1] = attr; + vic3_draw_character(device, ybegin, yend, ch & ~0xC0, yoff, xoff, vic3->ecmcolor, start_x, end_x); + } + else if (MULTICOLORON && (attr & 8)) + { + vic3->multi[3] = attr & 7; + vic3_draw_character_multi(device, ybegin, yend, ch, yoff, xoff, start_x, end_x); + } + else + { + vic3->mono[1] = attr; + vic3_draw_character(device, ybegin, yend, ch, yoff, xoff, vic3->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) vic3->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; + } + + vic3->sprites[i].line = wrapped; + + if (SPRITE_MULTICOLOR (i)) + vic3_draw_sprite_multi(device, i, 0, 0 , syend, start_x, end_x); + else + vic3_draw_sprite(device, 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) vic3->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; + } + + vic3->sprites[i].line = wrapped; + + if (SPRITE_MULTICOLOR (i)) + vic3_draw_sprite_multi(device, i, yoff + ybegin, 0, 0, start_x, end_x); + else + vic3_draw_sprite(device, i, yoff + ybegin, 0, 0, start_x, end_x); + } + else + { + memset (vic3->sprites[i].paintedline, 0, sizeof (vic3->sprites[i].paintedline)); + } + } + line += 1 + yend - ybegin; + } + + // left border + if ((start_x <= VIC2_STARTVISIBLECOLUMNS) && (end_x >= xbegin)) + vic3->bitmap->plot_box(VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xbegin - VIC2_STARTVISIBLECOLUMNS, 1, FRAMECOLOR); + else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x >= xbegin)) + vic3->bitmap->plot_box(start_x, first + FIRSTLINE, xbegin - start_x, 1, FRAMECOLOR); + else if ((start_x <= VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin)) + vic3->bitmap->plot_box(VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x, 1, FRAMECOLOR); + else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin)) + vic3->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)) + vic3->bitmap->plot_box(xend, first + FIRSTLINE, VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS - xend, 1, FRAMECOLOR); + else if ((start_x > xend) && (end_x >= VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS)) + vic3->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)) + vic3->bitmap->plot_box(xend, first + FIRSTLINE, end_x - xend, 1, FRAMECOLOR); + else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin)) + vic3->bitmap->plot_box(start_x, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR); + + if (first + 1 < vic3->bitmap->height()) + end = first + 1; + else + end = vic3->bitmap->height(); + + // bottom border + if (line < end) + { + if ((start_x <= xbegin) && (end_x >= xend)) + vic3->bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR); + if ((start_x > xbegin) && (end_x >= xend)) + vic3->bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR); + if ((start_x <= xbegin) && (end_x < xend)) + vic3->bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR); + if ((start_x > xbegin) && (end_x < xend)) + vic3->bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR); + line = end; + } +} + +/***************************************************************************** + I/O HANDLERS +*****************************************************************************/ + +WRITE8_DEVICE_HANDLER( vic3_palette_w ) +{ + vic3_state *vic3 = get_safe_token(device); + + if (offset < 0x100) + vic3->palette_red[offset] = data; + else if (offset < 0x200) + vic3->palette_green[offset & 0xff] = data; + else + vic3->palette_blue[offset & 0xff] = data; + + vic3->palette_dirty = 1; +} + + +WRITE8_DEVICE_HANDLER( vic3_port_w ) +{ + vic3_state *vic3 = get_safe_token(device); + + 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 (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->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 (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->sprites[offset / 2].x = SPRITE_X_POS(offset / 2); + } + break; + + case 0x10: /* sprite x positions */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->sprites[0].x = SPRITE_X_POS(0); + vic3->sprites[1].x = SPRITE_X_POS(1); + vic3->sprites[2].x = SPRITE_X_POS(2); + vic3->sprites[3].x = SPRITE_X_POS(3); + vic3->sprites[4].x = SPRITE_X_POS(4); + vic3->sprites[5].x = SPRITE_X_POS(5); + vic3->sprites[6].x = SPRITE_X_POS(6); + vic3->sprites[7].x = SPRITE_X_POS(7); + } + break; + + case 0x17: /* sprite y size */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + } + break; + + case 0x1d: /* sprite x size */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + } + break; + + case 0x1b: /* sprite background priority */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + } + break; + + case 0x1c: /* sprite multicolor mode select */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + } + break; + + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + /* sprite colors */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + } + break; + + case 0x25: /* sprite multicolor */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->spritemulti[1] = SPRITE_MULTICOLOR1; + } + break; + + case 0x26: /* sprite multicolor */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->spritemulti[3] = SPRITE_MULTICOLOR2; + } + break; + + case 0x19: + vic3_clear_interrupt(device->machine(), data & 0x0f, vic3); + break; + + case 0x1a: /* irq mask */ + vic3->reg[offset] = data; + vic3_set_interrupt(device->machine(), 0, vic3); // beamrider needs this + break; + + case 0x11: + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + if (LINES25) + { + vic3->y_begin = 0; + vic3->y_end = vic3->y_begin + 200; + } + else + { + vic3->y_begin = 4; + vic3->y_end = vic3->y_begin + 192; + } + } + break; + + case 0x12: + if (data != vic3->reg[offset]) + { + vic3->reg[offset] = data; + } + break; + + case 0x16: + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->x_begin = HORIZONTALPOS; + vic3->x_end = vic3->x_begin + 320; + } + break; + + case 0x18: + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->videoaddr = VIDEOADDR; + vic3->chargenaddr = CHARGENADDR; + vic3->bitmapaddr = BITMAPADDR; + } + break; + + case 0x21: /* background color */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->mono[0] = vic3->bitmapmulti[0] = vic3->multi[0] = vic3->colors[0] = BACKGROUNDCOLOR; + } + break; + + case 0x22: /* background color 1 */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->multi[1] = vic3->colors[1] = MULTICOLOR1; + } + break; + + case 0x23: /* background color 2 */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->multi[2] = vic3->colors[2] = MULTICOLOR2; + } + break; + + case 0x24: /* background color 3 */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + vic3->colors[3] = FOREGROUNDCOLOR; + } + break; + + case 0x20: /* framecolor */ + if (vic3->reg[offset] != data) + { + vic3->reg[offset] = data; + } + break; + + case 0x2f: + DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data)); + vic3->reg[offset] = data; + break; + case 0x30: + vic3->reg[offset] = data; + if (vic3->port_changed!=NULL) { + DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data)); + vic3->reg[offset] = data; + vic3->port_changed(device->machine(), data); + } + break; + case 0x31: + vic3->reg[offset] = data; + if (data & 0x40) + vic3->cpu->set_clock_scale(1.0); + else + vic3->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: + vic3->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: + vic3->reg[offset] = data; + break; + } +} + +READ8_DEVICE_HANDLER( vic3_port_r ) +{ + vic3_state *vic3 = get_safe_token(device); + int val = 0; + offset &= 0x7f; + + /* offsets 0x00 -> 0x2e coincide with VICII */ + switch (offset) + { + case 0x11: + val = (vic3->reg[offset] & ~0x80) | ((vic3->rasterline & 0x100) >> 1); + break; + + case 0x12: + val = vic3->rasterline & 0xff; + break; + + case 0x16: + val = vic3->reg[offset] | 0xc0; + break; + + case 0x18: + val = vic3->reg[offset] | 0x01; + break; + + case 0x19: /* interrupt flag register */ + /* vic2_clear_interrupt(0xf); */ + val = vic3->reg[offset] | 0x70; + break; + + case 0x1a: + val = vic3->reg[offset] | 0xf0; + break; + + case 0x1e: /* sprite to sprite collision detect */ + val = vic3->reg[offset]; + vic3->reg[offset] = 0; + vic3_clear_interrupt(device->machine(), 4, vic3); + break; + + case 0x1f: /* sprite to background collision detect */ + val = vic3->reg[offset]; + vic3->reg[offset] = 0; + vic3_clear_interrupt(device->machine(), 2, vic3); + break; + + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + val = vic3->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 = vic3->reg[offset]; + break; + + case 0x2f: + case 0x30: + val = vic3->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 = vic3->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 = vic3->reg[offset]; + } + return val; +} + + +#define VIC3_MASK(M) \ + if (M) \ + { \ + if (M & 0x01) \ + colors[0] = vic3->c64_mem_r(device->machine(), VIC3_ADDR(0) + offset); \ + if (M & 0x02) \ + colors[1] = vic3->c64_mem_r(device->machine(), VIC3_ADDR(1) + offset) << 1; \ + if (M & 0x04) \ + colors[2] = vic3->c64_mem_r(device->machine(), VIC3_ADDR(2) + offset) << 2; \ + if (M & 0x08) \ + colors[3] = vic3->c64_mem_r(device->machine(), VIC3_ADDR(3) + offset) << 3; \ + if (M & 0x10) \ + colors[4] = vic3->c64_mem_r(device->machine(), VIC3_ADDR(4) + offset) << 4; \ + if (M & 0x20) \ + colors[5] = vic3->c64_mem_r(device->machine(), VIC3_ADDR(5) + offset) << 5; \ + if (M & 0x40) \ + colors[6] = vic3->c64_mem_r(device->machine(), VIC3_ADDR(6) + offset) << 6; \ + if (M & 0x80) \ + colors[7] = vic3->c64_mem_r(device->machine(), 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; \ + } \ + vic3->bitmap->pix16(YPOS + y, XPOS + x + i) = p; \ + } \ + } + +#define VIC3_ADDR(a) VIC3_BITPLANE_IADDR(a) +static void vic3_interlace_draw_block( device_t *device, int x, int y, int offset ) +{ + vic3_state *vic3 = get_safe_token(device); + 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] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_IADDR(0) + offset); + + if (VIC3_BITPLANES_MASK & 0x02) + colors[1] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_IADDR(1) + offset) << 1; + + if (VIC3_BITPLANES_MASK & 0x04) + colors[2] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_IADDR(2) + offset) << 2; + + if (VIC3_BITPLANES_MASK & 0x08) + colors[3] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_IADDR(3) + offset) << 3; + + if (VIC3_BITPLANES_MASK & 0x10) + colors[4] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_IADDR(4) + offset) << 4; + + if (VIC3_BITPLANES_MASK & 0x20) + colors[5] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_IADDR(5) + offset) << 5; + + if (VIC3_BITPLANES_MASK & 0x40) + colors[6] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_IADDR(6) + offset) << 6; + + if (VIC3_BITPLANES_MASK & 0x80) + colors[7] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_IADDR(7) + offset) << 7; + + for (i = 7; i >= 0; i--) + { + vic3->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) +static void vic3_draw_block( device_t *device, int x, int y, int offset ) +{ + vic3_state *vic3 = get_safe_token(device); + 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] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_ADDR(0) + offset); + + if (VIC3_BITPLANES_MASK & 0x02) + colors[1] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_ADDR(1) + offset) << 1; + + if (VIC3_BITPLANES_MASK & 0x04) + colors[2] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_ADDR(2) + offset) << 2; + + if (VIC3_BITPLANES_MASK & 0x08) + colors[3] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_ADDR(3) + offset) << 3; + + if (VIC3_BITPLANES_MASK & 0x10) + colors[4] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_ADDR(4) + offset) << 4; + + if (VIC3_BITPLANES_MASK & 0x20) + colors[5] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_ADDR(5) + offset) << 5; + + if (VIC3_BITPLANES_MASK & 0x40) + colors[6] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_ADDR(6) + offset) << 6; + + if (VIC3_BITPLANES_MASK & 0x80) + colors[7] = vic3->c64_mem_r(device->machine(), VIC3_BITPLANE_ADDR(7) + offset) << 7; + + for (i = 7; i >= 0; i--) + { + vic3->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; + } + } +} + + +static void vic3_draw_bitplanes( device_t *device ) +{ + vic3_state *vic3 = get_safe_token(device); + int x, y, y1s, offset; + rectangle vis; + const rectangle &visarea = vic3->main_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 (vic3->interlace) + vic3_draw_block(device, x, y, offset); + else + vic3_interlace_draw_block(device, x, y + 1, offset); + } + } + } + vic3->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++) + { + vic3_draw_block(device, x, y, offset); + } + } + } + } + + if (XPOS > 0) + { + vis.set(0, XPOS - 1, 0, visarea.max_y); + vic3->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); + vic3->bitmap->fill(FRAMECOLOR, vis); + } + + if (YPOS > 0) + { + vis.set(0, visarea.max_x, 0, YPOS - 1); + vic3->bitmap->fill(FRAMECOLOR, vis); + } + + if (YPOS + VIC3_LINES < visarea.max_y) + { + vis.set(0, visarea.max_x, YPOS + VIC3_LINES, visarea.max_y); + vic3->bitmap->fill(FRAMECOLOR, vis); + } +} + +void vic3_raster_interrupt_gen( device_t *device ) +{ + vic3_state *vic3 = get_safe_token(device); + running_machine &machine = device->machine(); + int new_columns, new_rows; + int i; + + vic3->rasterline++; + if (vic3->rasterline >= vic3->lines) + { + vic3->rasterline = 0; + if (vic3->palette_dirty) + for (i = 0; i < 256; i++) + palette_set_color_rgb(machine, i, vic3->palette_red[i] << 4, vic3->palette_green[i] << 4, vic3->palette_blue[i] << 4); + + if (vic3->palette_dirty) + { + vic3->spritemulti[1] = SPRITE_MULTICOLOR1; + vic3->spritemulti[3] = SPRITE_MULTICOLOR2; + vic3->mono[0] = vic3->bitmapmulti[0] = vic3->multi[0] = vic3->colors[0] = BACKGROUNDCOLOR; + vic3->multi[1] = vic3->colors[1] = MULTICOLOR1; + vic3->multi[2] = vic3->colors[2] = MULTICOLOR2; + vic3->colors[3] = FOREGROUNDCOLOR; + vic3->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 != vic3->columns) || (new_rows != vic3->rows)) + { + vic3->rows = new_rows; + vic3->columns = new_columns; + if (vic3->type == VIC4567_PAL) + vic3->main_screen->set_visible_area( + VIC2_STARTVISIBLECOLUMNS + 32, + VIC2_STARTVISIBLECOLUMNS + 32 + vic3->columns + 16 - 1, + VIC2_STARTVISIBLELINES + 34, + VIC2_STARTVISIBLELINES + 34 + vic3->rows + 16 - 1); + else + vic3->main_screen->set_visible_area( + VIC2_STARTVISIBLECOLUMNS + 34, + VIC2_STARTVISIBLECOLUMNS + 34 + vic3->columns + 16 - 1, + VIC2_STARTVISIBLELINES + 10, + VIC2_STARTVISIBLELINES + 10 + vic3->rows + 16 - 1); + } + if (VIC3_BITPLANES) + { + vic3_draw_bitplanes(device); + } + else + { + if (vic3->type == VIC4567_PAL) + { + if (vic3->on) + vic2_drawlines(device, vic3->lastline, vic3->lines, VIC2_STARTVISIBLECOLUMNS + 32, VIC2_STARTVISIBLECOLUMNS + 32 + vic3->columns + 16 - 1); + } + else + { + if (vic3->on) + vic2_drawlines(device, vic3->lastline, vic3->lines, VIC2_STARTVISIBLECOLUMNS + 34, VIC2_STARTVISIBLECOLUMNS + 34 + vic3->columns + 16 - 1); + } + } + + for (i = 0; i < 8; i++) + vic3->sprites[i].repeat = vic3->sprites[i].line = 0; + + vic3->lastline = 0; + + if (LIGHTPEN_BUTTON) + { + /* lightpen timer start */ + machine.scheduler().timer_set(attotime(0, 0), FUNC(vic3_timer_timeout), 1, vic3); + } + + } + + if (vic3->rasterline == C64_2_RASTERLINE(RASTERLINE)) + { + vic3_set_interrupt(machine, 1, vic3); + } + + if (vic3->on) + if ((vic3->rasterline >= VIC2_FIRSTRASTERLINE) && (vic3->rasterline < (VIC2_FIRSTRASTERLINE + VIC2_VISIBLELINES))) + { + if (vic3->type == VIC4567_PAL) + { + if (vic3->on) + vic2_drawlines(device, vic3->rasterline - 1, vic3->rasterline, VIC2_STARTVISIBLECOLUMNS + 32, VIC2_STARTVISIBLECOLUMNS + 32 + vic3->columns + 16 - 1); + } + else + { + if (vic3->on) + vic2_drawlines(device, vic3->rasterline - 1, vic3->rasterline, VIC2_STARTVISIBLECOLUMNS + 34, VIC2_STARTVISIBLECOLUMNS + 34 + vic3->columns + 16 - 1); + } + } +} + +UINT32 vic3_video_update( device_t *device, bitmap_ind16 &bitmap, const rectangle &cliprect ) +{ + vic3_state *vic3 = get_safe_token(device); + + copybitmap(bitmap, *vic3->bitmap, 0, 0, 0, 0, cliprect); + return 0; +} + +/***************************************************************************** + DEVICE INTERFACE +*****************************************************************************/ + +static DEVICE_START( vic3 ) +{ + vic3_state *vic3 = get_safe_token(device); + const vic3_interface *intf = (vic3_interface *)device->static_config(); + int width, height; + int i; + + vic3->cpu = device->machine().device(intf->cpu); + + vic3->main_screen = device->machine().device<screen_device>(intf->screen); + width = vic3->main_screen->width(); + height = vic3->main_screen->height(); + + vic3->bitmap = auto_bitmap_ind16_alloc(device->machine(), width, height); + + vic3->type = intf->type; + + vic3->dma_read = intf->dma_read; + vic3->dma_read_color = intf->dma_read_color; + vic3->interrupt = intf->irq; + + vic3->port_changed = intf->port_changed; + + vic3->c64_mem_r = intf->c64_mem_r; + + vic3->lightpen_button_cb = intf->button_cb; + vic3->lightpen_x_cb = intf->x_cb; + vic3->lightpen_y_cb = intf->y_cb; + + vic3->screen[0] = auto_alloc_array(device->machine(), UINT8, 216 * 656 / 8); + + for (i = 1; i < 216; i++) + vic3->screen[i] = vic3->screen[i - 1] + 656 / 8; + + for (i = 0; i < 256; i++) + { + vic3->foreground[i] = 0; + if ((i & 3) > 1) + vic3->foreground[i] |= 0x3; + if ((i & 0xc) > 0x4) + vic3->foreground[i] |= 0xc; + if ((i & 0x30) > 0x10) + vic3->foreground[i] |= 0x30; + if ((i & 0xc0) > 0x40) + vic3->foreground[i] |= 0xc0; + } + + for (i = 0; i < 256; i++) + { + vic3->expandx[i] = 0; + if (i & 1) + vic3->expandx[i] |= 3; + if (i & 2) + vic3->expandx[i] |= 0xc; + if (i & 4) + vic3->expandx[i] |= 0x30; + if (i & 8) + vic3->expandx[i] |= 0xc0; + if (i & 0x10) + vic3->expandx[i] |= 0x300; + if (i & 0x20) + vic3->expandx[i] |= 0xc00; + if (i & 0x40) + vic3->expandx[i] |= 0x3000; + if (i & 0x80) + vic3->expandx[i] |= 0xc000; + } + + for (i = 0; i < 256; i++) + { + vic3->expandx_multi[i] = 0; + if (i & 1) + vic3->expandx_multi[i] |= 5; + if (i & 2) + vic3->expandx_multi[i] |= 0xa; + if (i & 4) + vic3->expandx_multi[i] |= 0x50; + if (i & 8) + vic3->expandx_multi[i] |= 0xa0; + if (i & 0x10) + vic3->expandx_multi[i] |= 0x500; + if (i & 0x20) + vic3->expandx_multi[i] |= 0xa00; + if (i & 0x40) + vic3->expandx_multi[i] |= 0x5000; + if (i & 0x80) + vic3->expandx_multi[i] |= 0xa000; + } + + device->save_item(NAME(vic3->reg)); + + device->save_item(NAME(vic3->on)); + + //device->save_item(NAME(vic3->bitmap)); + + device->save_item(NAME(vic3->lines)); + + device->save_item(NAME(vic3->chargenaddr)); + device->save_item(NAME(vic3->videoaddr)); + device->save_item(NAME(vic3->bitmapaddr)); + + device->save_item(NAME(vic3->x_begin)); + device->save_item(NAME(vic3->x_end)); + device->save_item(NAME(vic3->y_begin)); + device->save_item(NAME(vic3->y_end)); + + device->save_item(NAME(vic3->c64_bitmap)); + device->save_item(NAME(vic3->bitmapmulti)); + device->save_item(NAME(vic3->mono)); + device->save_item(NAME(vic3->multi)); + device->save_item(NAME(vic3->ecmcolor)); + device->save_item(NAME(vic3->colors)); + device->save_item(NAME(vic3->spritemulti)); + + device->save_item(NAME(vic3->lastline)); + device->save_item(NAME(vic3->rasterline)); + device->save_item(NAME(vic3->interlace)); + + device->save_item(NAME(vic3->columns)); + device->save_item(NAME(vic3->rows)); + + device->save_item(NAME(vic3->shift)); + device->save_item(NAME(vic3->foreground)); + device->save_item(NAME(vic3->multi_collision)); + + device->save_item(NAME(vic3->palette_red)); + device->save_item(NAME(vic3->palette_green)); + device->save_item(NAME(vic3->palette_blue)); + device->save_item(NAME(vic3->palette_dirty)); + + for (i = 0; i < 8; i++) + { + device->save_item(NAME(vic3->sprites[i].x), i); + device->save_item(NAME(vic3->sprites[i].y), i); + device->save_item(NAME(vic3->sprites[i].repeat), i); + device->save_item(NAME(vic3->sprites[i].line), i); + device->save_item(NAME(vic3->sprites[i].paintedline), i); + device->save_item(NAME(vic3->sprites[i].bitmap[0]), i); + device->save_item(NAME(vic3->sprites[i].bitmap[1]), i); + device->save_item(NAME(vic3->sprites[i].bitmap[2]), i); + device->save_item(NAME(vic3->sprites[i].bitmap[3]), i); + device->save_item(NAME(vic3->sprites[i].bitmap[4]), i); + device->save_item(NAME(vic3->sprites[i].bitmap[5]), i); + device->save_item(NAME(vic3->sprites[i].bitmap[6]), i); + device->save_item(NAME(vic3->sprites[i].bitmap[7]), i); + } +} + +static DEVICE_RESET( vic3 ) +{ + vic3_state *vic3 = get_safe_token(device); + int i; + + memset(vic3->reg, 0, ARRAY_LENGTH(vic3->reg)); + + vic3->on = 1; + + vic3->interlace = 0; + vic3->columns = 640; + vic3->rows = 200; + vic3->lines = VIC2_LINES; + + memset(&vic3->sprites, 0, sizeof(vic3->sprites)); + + vic3->chargenaddr = 0; + vic3->videoaddr = 0; + vic3->bitmapaddr = 0; + + vic3->x_begin = 0; + vic3->x_end = 0; + vic3->y_begin = 0; + vic3->y_end = 0; + + for (i = 0; i < 2; i++) + { + vic3->c64_bitmap[i] = 0; + vic3->mono[i] = 0; + vic3->ecmcolor[i] = 0; + } + + for (i = 0; i < 4; i++) + { + vic3->bitmapmulti[i] = 0; + vic3->multi[i] = 0; + vic3->colors[i] = 0; + vic3->spritemulti[i] = 0; + } + + vic3->lastline = 0; + vic3->rasterline = 0; + + memset(vic3->shift, 0, ARRAY_LENGTH(vic3->shift)); + memset(vic3->multi_collision, 0, ARRAY_LENGTH(vic3->multi_collision)); + memset(vic3->palette_red, 0, ARRAY_LENGTH(vic3->palette_red)); + memset(vic3->palette_green, 0, ARRAY_LENGTH(vic3->palette_green)); + memset(vic3->palette_blue, 0, ARRAY_LENGTH(vic3->palette_blue)); + + vic3->palette_dirty = 0; +} + + +/*------------------------------------------------- + device definition +-------------------------------------------------*/ + +static const char DEVTEMPLATE_SOURCE[] = __FILE__; + +#define DEVTEMPLATE_ID(p,s) p##vic3##s +#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET +#define DEVTEMPLATE_NAME "4567 VIC III" +#define DEVTEMPLATE_FAMILY "4567 VIC III" +#include "devtempl.h" + +DEFINE_LEGACY_DEVICE(VIC3, vic3); |