1 // license:BSD-3-Clause
2 // copyright-holders:Peter Trauner
3 /***************************************************************************
4
5 Video Interface Chip (4567)
6
7 original emulation by PeT (mess@utanet.at)
8
9 2010-02: converted to be a device and split from vic II
10
11 TODO:
12 - plenty of cleanups
13 - emulate variants of the vic chip
14 - update vic III to use the new vic6567.c code for the vic II comaptibility
15
16 ***************************************************************************/
17
18 #include "emu.h"
19 #include "video/vic4567.h"
20
21 #include "screen.h"
22
23 #include <algorithm>
24
25
26 /*****************************************************************************
27 CONSTANTS
28 *****************************************************************************/
29
30 #define VERBOSE_LEVEL 0
31 #define DBG_LOG(N,M,A) \
32 do { \
33 if(VERBOSE_LEVEL >= N) \
34 { \
35 if( M ) \
36 logerror("%11.6f: %-24s", machine().time().as_double(), (char*) M ); \
37 logerror A; \
38 } \
39 } while (0)
40
41 #define VREFRESHINLINES 28
42
43 #define VIC2_YPOS 50
44 #define RASTERLINE_2_C64(a) (a)
45 #define C64_2_RASTERLINE(a) (a)
46 #define XPOS (VIC2_STARTVISIBLECOLUMNS + (VIC2_VISIBLECOLUMNS - VIC2_HSIZE) / 2)
47 #define YPOS (VIC2_STARTVISIBLELINES /* + (VIC2_VISIBLELINES - VIC2_VSIZE) / 2 */)
48 #define FIRSTLINE 10 /* 36 ((VIC2_VISIBLELINES - VIC2_VSIZE)/2) */
49 #define FIRSTCOLUMN 50
50
51 /* 2008-05 FP: lightpen code needs to read input port from c64.c and cbmb.c */
52
53 #define LIGHTPEN_BUTTON (m_lightpen_button_cb(0))
54 #define LIGHTPEN_X_VALUE (m_lightpen_x_cb(0))
55 #define LIGHTPEN_Y_VALUE (m_lightpen_y_cb(0))
56
57 /* lightpen delivers values from internal counters; they do not start with the visual area or frame area */
58 #define VIC2_MAME_XPOS 0
59 #define VIC2_MAME_YPOS 0
60 #define VIC6567_X_BEGIN 38
61 #define VIC6567_Y_BEGIN -6 /* first 6 lines after retrace not for lightpen! */
62 #define VIC6569_X_BEGIN 38
63 #define VIC6569_Y_BEGIN -6
64 #define VIC2_X_BEGIN ((m_type == vic3_type::PAL) ? VIC6569_X_BEGIN : VIC6567_X_BEGIN)
65 #define VIC2_Y_BEGIN ((m_type == vic3_type::PAL) ? VIC6569_Y_BEGIN : VIC6567_Y_BEGIN)
66 #define VIC2_X_VALUE ((LIGHTPEN_X_VALUE + VIC2_X_BEGIN + VIC2_MAME_XPOS) / 2)
67 #define VIC2_Y_VALUE ((LIGHTPEN_Y_VALUE + VIC2_Y_BEGIN + VIC2_MAME_YPOS))
68
69 #define VIC2E_K0_LEVEL (m_reg[0x2f] & 0x01)
70 #define VIC2E_K1_LEVEL (m_reg[0x2f] & 0x02)
71 #define VIC2E_K2_LEVEL (m_reg[0x2f] & 0x04)
72
73 /*#define VIC3_P5_LEVEL (m_reg[0x30] & 0x20) */
74 #define VIC3_BITPLANES (m_reg[0x31] & 0x10)
75 #define VIC3_80COLUMNS (m_reg[0x31] & 0x80)
76 #define VIC3_LINES ((m_reg[0x31] & 0x19) == 0x19 ? 400 : 200)
77 #define VIC3_BITPLANES_WIDTH (m_reg[0x31] & 0x80 ? 640 : 320)
78
79 /*#define VIC2E_TEST (vic2[0x30] & 2) */
80 #define DOUBLE_CLOCK (m_reg[0x30] & 0x01)
81
82 /* sprites 0 .. 7 */
83 #define SPRITEON(nr) (m_reg[0x15] & (1 << nr))
84 #define SPRITE_Y_EXPAND(nr) (m_reg[0x17] & (1 << nr))
85 #define SPRITE_Y_SIZE(nr) (SPRITE_Y_EXPAND(nr) ? 2 * 21 : 21)
86 #define SPRITE_X_EXPAND(nr) (m_reg[0x1d] & (1 << nr))
87 #define SPRITE_X_SIZE(nr) (SPRITE_X_EXPAND(nr) ? 2 * 24 : 24)
88 #define SPRITE_X_POS(nr) ((m_reg[(nr) * 2] | (m_reg[0x10] & (1 <<(nr)) ? 0x100 : 0)) - 24 + XPOS)
89 #define SPRITE_X_POS2(nr) (m_reg[(nr) * 2] | (m_reg[0x10] & (1 <<(nr)) ? 0x100 : 0))
90 #define SPRITE_Y_POS(nr) (m_reg[1+2*(nr)] - 50 + YPOS)
91 #define SPRITE_Y_POS2(nr) (m_reg[1 + 2 *(nr)])
92 #define SPRITE_MULTICOLOR(nr) (m_reg[0x1c] & (1 << nr))
93 #define SPRITE_PRIORITY(nr) (m_reg[0x1b] & (1 << nr))
94 #define SPRITE_MULTICOLOR1 (m_reg[0x25] & 0x0f)
95 #define SPRITE_MULTICOLOR2 (m_reg[0x26] & 0x0f)
96 #define SPRITE_COLOR(nr) (m_reg[0x27+nr] & 0x0f)
97 #define SPRITE_ADDR(nr) (m_videoaddr | 0x3f8 | nr)
98 #define SPRITE_BG_COLLISION(nr) (m_reg[0x1f] & (1 << nr))
99 #define SPRITE_COLLISION(nr) (m_reg[0x1e] & (1 << nr))
100 #define SPRITE_SET_BG_COLLISION(nr) (m_reg[0x1f] |= (1 << nr))
101 #define SPRITE_SET_COLLISION(nr) (m_reg[0x1e] |= (1 << nr))
102 #define SPRITE_COLL (m_reg[0x1e])
103 #define SPRITE_BG_COLL (m_reg[0x1f])
104
105 #define GFXMODE ((m_reg[0x11] & 0x60) | (m_reg[0x16] & 0x10)) >> 4
106 #define SCREENON (m_reg[0x11] & 0x10)
107 #define VERTICALPOS (m_reg[0x11] & 0x07)
108 #define HORIZONTALPOS (m_reg[0x16] & 0x07)
109 #define ECMON (m_reg[0x11] & 0x40)
110 #define HIRESON (m_reg[0x11] & 0x20)
111 #define MULTICOLORON (m_reg[0x16] & 0x10)
112 #define LINES25 (m_reg[0x11] & 0x08) /* else 24 Lines */
113 #define LINES (LINES25 ? 25 : 24)
114 #define YSIZE (LINES * 8)
115 #define COLUMNS40 (m_reg[0x16] & 0x08) /* else 38 Columns */
116 #define COLUMNS (COLUMNS40 ? 40 : 38)
117 #define XSIZE (COLUMNS * 8)
118
119 #define VIDEOADDR ((m_reg[0x18] & 0xf0) << (10 - 4))
120 #define CHARGENADDR ((m_reg[0x18] & 0x0e) << 10)
121 #define BITMAPADDR ((data & 0x08) << 10)
122
123 #define RASTERLINE (((m_reg[0x11] & 0x80) << 1) | m_reg[0x12])
124
125 #define FRAMECOLOR (m_reg[0x20] & 0x0f)
126 #define BACKGROUNDCOLOR (m_reg[0x21] & 0x0f)
127 #define MULTICOLOR1 (m_reg[0x22] & 0x0f)
128 #define MULTICOLOR2 (m_reg[0x23] & 0x0f)
129 #define FOREGROUNDCOLOR (m_reg[0x24] & 0x0f)
130
131
132 #define VIC2_LINES (m_type == vic3_type::PAL ? VIC6569_LINES : VIC6567_LINES)
133 #define VIC2_VISIBLELINES (m_type == vic3_type::PAL ? VIC6569_VISIBLELINES : VIC6567_VISIBLELINES)
134 #define VIC2_VISIBLECOLUMNS (m_type == vic3_type::PAL ? VIC6569_VISIBLECOLUMNS : VIC6567_VISIBLECOLUMNS)
135 #define VIC2_STARTVISIBLELINES ((VIC2_LINES - VIC2_VISIBLELINES)/2)
136 #define VIC2_FIRSTRASTERLINE (m_type == vic3_type::PAL ? VIC6569_FIRSTRASTERLINE : VIC6567_FIRSTRASTERLINE)
137 #define VIC2_COLUMNS (m_type == vic3_type::PAL ? VIC6569_COLUMNS : VIC6567_COLUMNS)
138 #define VIC2_STARTVISIBLECOLUMNS ((VIC2_COLUMNS - VIC2_VISIBLECOLUMNS)/2)
139
140 #define VIC3_BITPLANES_MASK (m_reg[0x32])
141 /* bit 0, 4 not used !?*/
142 /* I think hinibbles contains the banknumbers for interlaced modes */
143 /* if hinibble set then x&1==0 should be in bank1 (0x10000), x&1==1 in bank 0 */
144 #define VIC3_BITPLANE_ADDR_HELPER(x) ((m_reg[0x33 + x] & 0x0f) << 12)
145 #define VIC3_BITPLANE_ADDR(x) (x & 1 ? VIC3_BITPLANE_ADDR_HELPER(x) + 0x10000 : VIC3_BITPLANE_ADDR_HELPER(x) )
146 #define VIC3_BITPLANE_IADDR_HELPER(x) ((m_reg[0x33 + x] & 0xf0) << 8)
147 #define VIC3_BITPLANE_IADDR(x) (x & 1 ? VIC3_BITPLANE_IADDR_HELPER(x) + 0x10000 : VIC3_BITPLANE_IADDR_HELPER(x))
148
149
150 DEFINE_DEVICE_TYPE(VIC3, vic3_device, "vic3", "CSG 4567 VIC-III")
151
vic3_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)152 vic3_device::vic3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
153 : device_t(mconfig, VIC3, tag, owner, clock)
154 , device_palette_interface(mconfig, *this)
155 , device_video_interface(mconfig, *this)
156 , m_type(vic3_type::NTSC)
157 , m_cpu(*this, finder_base::DUMMY_TAG)
158 , m_dma_read_cb(*this)
159 , m_dma_read_color_cb(*this)
160 , m_interrupt_cb(*this)
161 , m_port_changed_cb(*this)
162 , m_lightpen_button_cb(*this)
163 , m_lightpen_x_cb(*this)
164 , m_lightpen_y_cb(*this)
165 , m_c64_mem_r_cb(*this)
166 {
167 }
168
169 //-------------------------------------------------
170 // device_start - device-specific startup
171 //-------------------------------------------------
172
device_start()173 void vic3_device::device_start()
174 {
175 int width, height;
176
177 width = screen().width();
178 height = screen().height();
179
180 m_bitmap = std::make_unique<bitmap_ind16>(width, height);
181
182 m_dma_read_cb.resolve_safe(0);
183 m_dma_read_color_cb.resolve_safe(0);
184 m_interrupt_cb.resolve_safe();
185
186 m_port_changed_cb.resolve();
187
188 m_c64_mem_r_cb.resolve_safe(0);
189
190 m_lightpen_button_cb.resolve_safe(0);
191 m_lightpen_x_cb.resolve_safe(0);
192 m_lightpen_y_cb.resolve_safe(0);
193
194 m_screenptr[0] = auto_alloc_array(machine(), uint8_t, 216 * 656 / 8);
195
196 for (int i = 1; i < 216; i++)
197 m_screenptr[i] = m_screenptr[i - 1] + 656 / 8;
198
199 for (int i = 0; i < 256; i++)
200 {
201 m_foreground[i] = 0;
202 if ((i & 3) > 1)
203 m_foreground[i] |= 0x3;
204 if ((i & 0xc) > 0x4)
205 m_foreground[i] |= 0xc;
206 if ((i & 0x30) > 0x10)
207 m_foreground[i] |= 0x30;
208 if ((i & 0xc0) > 0x40)
209 m_foreground[i] |= 0xc0;
210 }
211
212 for (int i = 0; i < 256; i++)
213 {
214 m_expandx[i] = 0;
215 if (i & 1)
216 m_expandx[i] |= 3;
217 if (i & 2)
218 m_expandx[i] |= 0xc;
219 if (i & 4)
220 m_expandx[i] |= 0x30;
221 if (i & 8)
222 m_expandx[i] |= 0xc0;
223 if (i & 0x10)
224 m_expandx[i] |= 0x300;
225 if (i & 0x20)
226 m_expandx[i] |= 0xc00;
227 if (i & 0x40)
228 m_expandx[i] |= 0x3000;
229 if (i & 0x80)
230 m_expandx[i] |= 0xc000;
231 }
232
233 for (int i = 0; i < 256; i++)
234 {
235 m_expandx_multi[i] = 0;
236 if (i & 1)
237 m_expandx_multi[i] |= 5;
238 if (i & 2)
239 m_expandx_multi[i] |= 0xa;
240 if (i & 4)
241 m_expandx_multi[i] |= 0x50;
242 if (i & 8)
243 m_expandx_multi[i] |= 0xa0;
244 if (i & 0x10)
245 m_expandx_multi[i] |= 0x500;
246 if (i & 0x20)
247 m_expandx_multi[i] |= 0xa00;
248 if (i & 0x40)
249 m_expandx_multi[i] |= 0x5000;
250 if (i & 0x80)
251 m_expandx_multi[i] |= 0xa000;
252 }
253
254 save_item(NAME(m_reg));
255
256 save_item(NAME(m_on));
257
258 //save_item(NAME(m_bitmap));
259
260 save_item(NAME(m_lines));
261
262 save_item(NAME(m_chargenaddr));
263 save_item(NAME(m_videoaddr));
264 save_item(NAME(m_bitmapaddr));
265
266 save_item(NAME(m_x_begin));
267 save_item(NAME(m_x_end));
268 save_item(NAME(m_y_begin));
269 save_item(NAME(m_y_end));
270
271 save_item(NAME(m_c64_bitmap));
272 save_item(NAME(m_bitmapmulti));
273 save_item(NAME(m_mono));
274 save_item(NAME(m_multi));
275 save_item(NAME(m_ecmcolor));
276 save_item(NAME(m_colors));
277 save_item(NAME(m_spritemulti));
278
279 save_item(NAME(m_lastline));
280 save_item(NAME(m_rasterline));
281 save_item(NAME(m_interlace));
282
283 save_item(NAME(m_columns));
284 save_item(NAME(m_rows));
285
286 save_item(NAME(m_shift));
287 save_item(NAME(m_foreground));
288 save_item(NAME(m_multi_collision));
289
290 save_item(NAME(m_palette_red));
291 save_item(NAME(m_palette_green));
292 save_item(NAME(m_palette_blue));
293 save_item(NAME(m_palette_dirty));
294
295 for (int i = 0; i < 8; i++)
296 {
297 save_item(NAME(m_sprites[i].x), i);
298 save_item(NAME(m_sprites[i].y), i);
299 save_item(NAME(m_sprites[i].repeat), i);
300 save_item(NAME(m_sprites[i].line), i);
301 save_item(NAME(m_sprites[i].paintedline), i);
302 save_item(NAME(m_sprites[i].bitmap[0]), i);
303 save_item(NAME(m_sprites[i].bitmap[1]), i);
304 save_item(NAME(m_sprites[i].bitmap[2]), i);
305 save_item(NAME(m_sprites[i].bitmap[3]), i);
306 save_item(NAME(m_sprites[i].bitmap[4]), i);
307 save_item(NAME(m_sprites[i].bitmap[5]), i);
308 save_item(NAME(m_sprites[i].bitmap[6]), i);
309 save_item(NAME(m_sprites[i].bitmap[7]), i);
310 }
311 }
312
313 //-------------------------------------------------
314 // device_reset - device-specific reset
315 //-------------------------------------------------
316
device_reset()317 void vic3_device::device_reset()
318 {
319 memset(m_reg, 0, ARRAY_LENGTH(m_reg));
320
321 m_on = 1;
322
323 m_interlace = 0;
324 m_columns = 640;
325 m_rows = 200;
326 m_lines = VIC2_LINES;
327
328 memset(&m_sprites, 0, sizeof(m_sprites));
329
330 m_chargenaddr = 0;
331 m_videoaddr = 0;
332 m_bitmapaddr = 0;
333
334 m_x_begin = 0;
335 m_x_end = 0;
336 m_y_begin = 0;
337 m_y_end = 0;
338
339 for (int i = 0; i < 2; i++)
340 {
341 m_c64_bitmap[i] = 0;
342 m_mono[i] = 0;
343 m_ecmcolor[i] = 0;
344 }
345
346 for (int i = 0; i < 4; i++)
347 {
348 m_bitmapmulti[i] = 0;
349 m_multi[i] = 0;
350 m_colors[i] = 0;
351 m_spritemulti[i] = 0;
352 }
353
354 m_lastline = 0;
355 m_rasterline = 0;
356
357 memset(m_shift, 0, ARRAY_LENGTH(m_shift));
358 memset(m_multi_collision, 0, ARRAY_LENGTH(m_multi_collision));
359
360 for (int i = 0; i < 256; i++)
361 {
362 m_palette_red[i] = m_palette_green[i] = m_palette_blue[i] = 0;
363 set_pen_color(i, rgb_t::black());
364 }
365
366 m_palette_dirty = 0;
367 }
368
369
370 /*****************************************************************************
371 IMPLEMENTATION
372 *****************************************************************************/
373
getforeground(int y,int x)374 inline int vic3_device::getforeground( int y, int x )
375 {
376 return ((m_screenptr[y][x >> 3] << 8) | (m_screenptr[y][(x >> 3) + 1])) >> (8 - (x & 7));
377 }
378
getforeground16(int y,int x)379 inline int vic3_device::getforeground16( int y, int x )
380 {
381 return ((m_screenptr[y][x >> 3] << 16) | (m_screenptr[y][(x >> 3) + 1] << 8) | (m_screenptr[y][(x >> 3) + 2])) >> (8 - (x & 7));
382 }
383
set_interrupt(int mask)384 void vic3_device::set_interrupt( int mask )
385 {
386 if (((m_reg[0x19] ^ mask) & m_reg[0x1a] & 0xf))
387 {
388 if (!(m_reg[0x19] & 0x80))
389 {
390 //DBG_LOG(2, "vic2", ("irq start %.2x\n", mask));
391 m_reg[0x19] |= 0x80;
392 m_interrupt_cb(1);
393 }
394 }
395 m_reg[0x19] |= mask;
396 }
397
clear_interrupt(int mask)398 void vic3_device::clear_interrupt( int mask )
399 {
400 m_reg[0x19] &= ~mask;
401 if ((m_reg[0x19] & 0x80) && !(m_reg[0x19] & m_reg[0x1a] & 0xf))
402 {
403 //DBG_LOG(2, "vic2", ("irq end %.2x\n", mask));
404 m_reg[0x19] &= ~0x80;
405 m_interrupt_cb(0);
406 }
407 }
408
TIMER_CALLBACK_MEMBER(vic3_device::timer_timeout)409 TIMER_CALLBACK_MEMBER( vic3_device::timer_timeout )
410 {
411 int which = param;
412 //DBG_LOG(3, "vic3 ", ("timer %d timeout\n", which));
413 switch (which)
414 {
415 case 1: /* light pen */
416 /* and diode must recognize light */
417 if (1)
418 {
419 m_reg[0x13] = VIC2_X_VALUE;
420 m_reg[0x14] = VIC2_Y_VALUE;
421 }
422 set_interrupt(8);
423 break;
424 }
425 }
426
draw_character(int ybegin,int yend,int ch,int yoff,int xoff,uint16_t * color,int start_x,int end_x)427 void vic3_device::draw_character( int ybegin, int yend, int ch, int yoff, int xoff, uint16_t *color, int start_x, int end_x )
428 {
429 for (int y = ybegin; y <= yend; y++)
430 {
431 int code = m_dma_read_cb(m_chargenaddr + ch * 8 + y);
432 m_screenptr[y + yoff][xoff >> 3] = code;
433 if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 0) = color[code >> 7];
434 if ((xoff + 1 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 1) = color[(code >> 6) & 1];
435 if ((xoff + 2 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 2) = color[(code >> 5) & 1];
436 if ((xoff + 3 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 3) = color[(code >> 4) & 1];
437 if ((xoff + 4 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 4) = color[(code >> 3) & 1];
438 if ((xoff + 5 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 5) = color[(code >> 2) & 1];
439 if ((xoff + 6 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 6) = color[(code >> 1) & 1];
440 if ((xoff + 7 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 7) = color[code & 1];
441 }
442 }
443
draw_character_multi(int ybegin,int yend,int ch,int yoff,int xoff,int start_x,int end_x)444 void vic3_device::draw_character_multi( int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x )
445 {
446 for (int y = ybegin; y <= yend; y++)
447 {
448 int code = m_dma_read_cb(m_chargenaddr + ch * 8 + y);
449 m_screenptr[y + yoff][xoff >> 3] = m_foreground[code];
450 if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 0) = m_multi[code >> 6];
451 if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 1) = m_multi[code >> 6];
452 if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 2) = m_multi[(code >> 4) & 3];
453 if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 3) = m_multi[(code >> 4) & 3];
454 if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 4) = m_multi[(code >> 2) & 3];
455 if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 5) = m_multi[(code >> 2) & 3];
456 if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 6) = m_multi[code & 3];
457 if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 7) = m_multi[code & 3];
458 }
459 }
460
draw_bitmap(int ybegin,int yend,int ch,int yoff,int xoff,int start_x,int end_x)461 void vic3_device::draw_bitmap( int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x )
462 {
463 for (int y = ybegin; y <= yend; y++)
464 {
465 int code = m_dma_read_cb((m_chargenaddr & 0x2000) + ch * 8 + y);
466 m_screenptr[y + yoff][xoff >> 3] = code;
467 if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 0) = m_c64_bitmap[code >> 7];
468 if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 1) = m_c64_bitmap[(code >> 6) & 1];
469 if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 2) = m_c64_bitmap[(code >> 5) & 1];
470 if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 3) = m_c64_bitmap[(code >> 4) & 1];
471 if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 4) = m_c64_bitmap[(code >> 3) & 1];
472 if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 5) = m_c64_bitmap[(code >> 2) & 1];
473 if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 6) = m_c64_bitmap[(code >> 1) & 1];
474 if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 7) = m_c64_bitmap[code & 1];
475 }
476 }
477
draw_bitmap_multi(int ybegin,int yend,int ch,int yoff,int xoff,int start_x,int end_x)478 void vic3_device::draw_bitmap_multi( int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x )
479 {
480 for (int y = ybegin; y <= yend; y++)
481 {
482 int code = m_dma_read_cb((m_chargenaddr & 0x2000) + ch * 8 + y);
483 m_screenptr[y + yoff][xoff >> 3] = m_foreground[code];
484 if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 0) = m_bitmapmulti[code >> 6];
485 if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 1) = m_bitmapmulti[code >> 6];
486 if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 2) = m_bitmapmulti[(code >> 4) & 3];
487 if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 3) = m_bitmapmulti[(code >> 4) & 3];
488 if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 4) = m_bitmapmulti[(code >> 2) & 3];
489 if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 5) = m_bitmapmulti[(code >> 2) & 3];
490 if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 6) = m_bitmapmulti[code & 3];
491 if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 7) = m_bitmapmulti[code & 3];
492 }
493 }
494
draw_sprite_code(int y,int xbegin,int code,int color,int start_x,int end_x)495 void vic3_device::draw_sprite_code( int y, int xbegin, int code, int color, int start_x, int end_x )
496 {
497 if ((y < YPOS) || (y >= (VIC2_STARTVISIBLELINES + VIC2_VISIBLELINES)) || (xbegin <= 1) || (xbegin >= (VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS)))
498 return;
499
500 for (int x = 0, mask = 0x80; x < 8; x++, mask >>= 1)
501 {
502 if (code & mask)
503 {
504 if ((xbegin + x > start_x) && (xbegin + x < end_x))
505 m_bitmap->pix(y + FIRSTLINE, xbegin + x) = color;
506 }
507 }
508 }
509
draw_sprite_code_multi(int y,int xbegin,int code,int prior,int start_x,int end_x)510 void vic3_device::draw_sprite_code_multi( int y, int xbegin, int code, int prior, int start_x, int end_x )
511 {
512 if ((y < YPOS) || (y >= (VIC2_STARTVISIBLELINES + VIC2_VISIBLELINES)) || (xbegin <= 1) || (xbegin >= (VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS)))
513 return;
514
515 for (int x = 0, mask = 0xc0, shift = 6; x < 8; x += 2, mask >>= 2, shift -= 2)
516 {
517 if (code & mask)
518 {
519 switch ((prior & mask) >> shift)
520 {
521 case 1:
522 if ((xbegin + x + 1 > start_x) && (xbegin + x + 1 < end_x))
523 m_bitmap->pix(y + FIRSTLINE, xbegin + x + 1) = m_spritemulti[(code >> shift) & 3];
524 break;
525 case 2:
526 if ((xbegin + x > start_x) && (xbegin + x < end_x))
527 m_bitmap->pix(y + FIRSTLINE, xbegin + x) = m_spritemulti[(code >> shift) & 3];
528 break;
529 case 3:
530 if ((xbegin + x > start_x) && (xbegin + x < end_x))
531 m_bitmap->pix(y + FIRSTLINE, xbegin + x) = m_spritemulti[(code >> shift) & 3];
532 if ((xbegin + x + 1> start_x) && (xbegin + x + 1< end_x))
533 m_bitmap->pix(y + FIRSTLINE, xbegin + x + 1) = m_spritemulti[(code >> shift) & 3];
534 break;
535 }
536 }
537 }
538 }
539
sprite_collision(int nr,int y,int x,int mask)540 void vic3_device::sprite_collision( int nr, int y, int x, int mask )
541 {
542 for (int i = 7; i > nr; i--)
543 {
544 if (!SPRITEON(i) || !m_sprites[i].paintedline[y] || (SPRITE_COLLISION(i) && SPRITE_COLLISION(nr)))
545 continue;
546
547 if ((x + 7 < SPRITE_X_POS(i)) || (x >= SPRITE_X_POS(i) + SPRITE_X_SIZE(i)))
548 continue;
549
550 int xdiff = x - SPRITE_X_POS(i);
551
552 int value;
553 if ((x & 7) == (SPRITE_X_POS(i) & 7))
554 value = m_sprites[i].bitmap[y][xdiff >> 3];
555 else if (xdiff < 0)
556 value = m_sprites[i].bitmap[y][0] >> (-xdiff);
557 else {
558 uint8_t *vp = m_sprites[i].bitmap[y]+(xdiff >> 3);
559 value = ((vp[1] | (*vp << 8)) >> (8 - (xdiff & 7) )) & 0xff;
560 }
561
562 if (value & mask)
563 {
564 SPRITE_SET_COLLISION(i);
565 SPRITE_SET_COLLISION(nr);
566 set_interrupt(4);
567 }
568 }
569 }
570
draw_sprite(int nr,int yoff,int ybegin,int yend,int start_x,int end_x)571 void vic3_device::draw_sprite( int nr, int yoff, int ybegin, int yend, int start_x, int end_x )
572 {
573 int y, i, addr, xbegin, color, prior, collision;
574 int value, value3 = 0;
575
576 xbegin = SPRITE_X_POS(nr);
577 addr = m_dma_read_cb(SPRITE_ADDR(nr)) << 6;
578 color = SPRITE_COLOR(nr);
579 prior = SPRITE_PRIORITY(nr);
580 collision = SPRITE_BG_COLLISION(nr);
581
582 if (SPRITE_X_EXPAND(nr))
583 {
584 for (y = ybegin; y <= yend; y++)
585 {
586 m_sprites[nr].paintedline[y] = 1;
587 for (i = 0; i < 3; i++)
588 {
589 value = m_expandx[m_dma_read_cb(addr + m_sprites[nr].line * 3 + i)];
590 m_sprites[nr].bitmap[y][i * 2] = value >> 8;
591 m_sprites[nr].bitmap[y][i * 2 + 1] = value & 0xff;
592 sprite_collision(nr, y, xbegin + i * 16, value >> 8);
593 sprite_collision(nr, y, xbegin + i * 16 + 8, value & 0xff);
594 if (prior || !collision)
595 value3 = getforeground16(yoff + y, xbegin + i * 16 - 7);
596 if (!collision && (value & value3))
597 {
598 collision = 1;
599 SPRITE_SET_BG_COLLISION(nr);
600 set_interrupt(2);
601 }
602 if (prior)
603 value &= ~value3;
604 draw_sprite_code(yoff + y, xbegin + i * 16, value >> 8, color, start_x, end_x);
605 draw_sprite_code(yoff + y, xbegin + i * 16 + 8, value & 0xff, color, start_x, end_x);
606 }
607 m_sprites[nr].bitmap[y][i * 2]=0; //easier sprite collision detection
608 if (SPRITE_Y_EXPAND(nr))
609 {
610 if (m_sprites[nr].repeat)
611 {
612 m_sprites[nr].line++;
613 m_sprites[nr].repeat = 0;
614 }
615 else
616 m_sprites[nr].repeat = 1;
617 }
618 else
619 {
620 m_sprites[nr].line++;
621 }
622 }
623 }
624 else
625 {
626 for (y = ybegin; y <= yend; y++)
627 {
628 m_sprites[nr].paintedline[y] = 1;
629 for (i = 0; i < 3; i++)
630 {
631 value = m_dma_read_cb(addr + m_sprites[nr].line * 3 + i);
632 m_sprites[nr].bitmap[y][i] = value;
633 sprite_collision(nr, y, xbegin + i * 8, value);
634 if (prior || !collision)
635 value3 = getforeground(yoff + y, xbegin + i * 8 - 7);
636 if (!collision && (value & value3))
637 {
638 collision = 1;
639 SPRITE_SET_BG_COLLISION(nr);
640 set_interrupt(2);
641 }
642 if (prior)
643 value &= ~value3;
644 draw_sprite_code(yoff + y, xbegin + i * 8, value, color, start_x, end_x);
645 }
646 m_sprites[nr].bitmap[y][i]=0; //easier sprite collision detection
647 if (SPRITE_Y_EXPAND(nr))
648 {
649 if (m_sprites[nr].repeat)
650 {
651 m_sprites[nr].line++;
652 m_sprites[nr].repeat = 0;
653 }
654 else
655 m_sprites[nr].repeat = 1;
656 }
657 else
658 {
659 m_sprites[nr].line++;
660 }
661 }
662 }
663 }
664
draw_sprite_multi(int nr,int yoff,int ybegin,int yend,int start_x,int end_x)665 void vic3_device::draw_sprite_multi( int nr, int yoff, int ybegin, int yend, int start_x, int end_x )
666 {
667 int y, i, prior, addr, xbegin, collision;
668 int value, value2, value3 = 0, bg/*, color[2]*/;
669
670 xbegin = SPRITE_X_POS(nr);
671 addr = m_dma_read_cb(SPRITE_ADDR(nr)) << 6;
672 m_spritemulti[2] = SPRITE_COLOR(nr);
673 prior = SPRITE_PRIORITY(nr);
674 collision = SPRITE_BG_COLLISION(nr);
675 //color[0] = 0;
676 //color[1] = 1;
677
678 if (SPRITE_X_EXPAND(nr))
679 {
680 for (y = ybegin; y <= yend; y++)
681 {
682 m_sprites[nr].paintedline[y] = 1;
683 for (i = 0; i < 3; i++)
684 {
685 value = m_expandx_multi[bg = m_dma_read_cb(addr + m_sprites[nr].line * 3 + i)];
686 value2 = m_expandx[m_multi_collision[bg]];
687 m_sprites[nr].bitmap[y][i * 2] = value2 >> 8;
688 m_sprites[nr].bitmap[y][i * 2 + 1] = value2 & 0xff;
689 sprite_collision(nr, y, xbegin + i * 16, value2 >> 8);
690 sprite_collision(nr, y, xbegin + i * 16 + 8, value2 & 0xff);
691 if (prior || !collision)
692 {
693 value3 = getforeground16(yoff + y, xbegin + i * 16 - 7);
694 }
695 if (!collision && (value2 & value3))
696 {
697 collision = 1;
698 SPRITE_SET_BG_COLLISION(nr);
699 set_interrupt(2);
700 }
701 if (prior)
702 {
703 draw_sprite_code_multi(yoff + y, xbegin + i * 16, value >> 8, (value3 >> 8) ^ 0xff, start_x, end_x);
704 draw_sprite_code_multi(yoff + y, xbegin + i * 16 + 8, value & 0xff, (value3 & 0xff) ^ 0xff, start_x, end_x);
705 }
706 else
707 {
708 draw_sprite_code_multi(yoff + y, xbegin + i * 16, value >> 8, 0xff, start_x, end_x);
709 draw_sprite_code_multi(yoff + y, xbegin + i * 16 + 8, value & 0xff, 0xff, start_x, end_x);
710 }
711 }
712 m_sprites[nr].bitmap[y][i * 2]=0; //easier sprite collision detection
713 if (SPRITE_Y_EXPAND(nr))
714 {
715 if (m_sprites[nr].repeat)
716 {
717 m_sprites[nr].line++;
718 m_sprites[nr].repeat = 0;
719 }
720 else
721 m_sprites[nr].repeat = 1;
722 }
723 else
724 {
725 m_sprites[nr].line++;
726 }
727 }
728 }
729 else
730 {
731 for (y = ybegin; y <= yend; y++)
732 {
733 m_sprites[nr].paintedline[y] = 1;
734 for (i = 0; i < 3; i++)
735 {
736 value = m_dma_read_cb(addr + m_sprites[nr].line * 3 + i);
737 m_sprites[nr].bitmap[y][i] = value2 = m_multi_collision[value];
738 sprite_collision(nr, y, xbegin + i * 8, value2);
739 if (prior || !collision)
740 {
741 value3 = getforeground(yoff + y, xbegin + i * 8 - 7);
742 }
743 if (!collision && (value2 & value3))
744 {
745 collision = 1;
746 SPRITE_SET_BG_COLLISION(nr);
747 set_interrupt(2);
748 }
749 if (prior)
750 {
751 draw_sprite_code_multi(yoff + y, xbegin + i * 8, value, value3 ^ 0xff, start_x, end_x);
752 }
753 else
754 {
755 draw_sprite_code_multi(yoff + y, xbegin + i * 8, value, 0xff, start_x, end_x);
756 }
757 }
758 m_sprites[nr].bitmap[y][i] = 0; //easier sprite collision detection
759 if (SPRITE_Y_EXPAND(nr))
760 {
761 if (m_sprites[nr].repeat)
762 {
763 m_sprites[nr].line++;
764 m_sprites[nr].repeat = 0;
765 }
766 else
767 m_sprites[nr].repeat = 1;
768 }
769 else
770 {
771 m_sprites[nr].line++;
772 }
773 }
774 }
775 }
776
drawlines(int first,int last,int start_x,int end_x)777 void vic3_device::drawlines( int first, int last, int start_x, int end_x )
778 {
779 int line, vline, end;
780 int attr, ch, ecm;
781 int syend;
782 int offs, yoff, xoff, ybegin, yend, xbegin, xend;
783 int x_end2;
784 int i, j;
785
786 if (first == last)
787 return;
788 m_lastline = last;
789
790 /* top part of display not rastered */
791 first -= VIC2_YPOS - YPOS;
792 last -= VIC2_YPOS - YPOS;
793 if ((first >= last) || (last <= 0))
794 {
795 for (i = 0; i < 8; i++)
796 m_sprites[i].repeat = m_sprites[i].line = 0;
797 return;
798 }
799 if (first < 0)
800 first = 0;
801
802 if (!SCREENON)
803 {
804 for (line = first; (line < last) && (line < m_bitmap->height()); line++)
805 {
806 std::fill_n(&m_bitmap->pix(line + FIRSTLINE), m_bitmap->width(), 0);
807 }
808 return;
809 }
810 if (COLUMNS40)
811 xbegin = XPOS, xend = xbegin + 640;
812 else
813 xbegin = XPOS + 7, xend = xbegin + 624;
814
815 if (last < m_y_begin)
816 end = last;
817 else
818 end = m_y_begin + YPOS;
819
820 for (line = first; line < end; line++)
821 {
822 std::fill_n(&m_bitmap->pix(line + FIRSTLINE), m_bitmap->width(), FRAMECOLOR);
823 }
824
825 if (LINES25)
826 {
827 vline = line - m_y_begin - YPOS;
828 }
829 else
830 {
831 vline = line - m_y_begin - YPOS + 8 - VERTICALPOS;
832 }
833 if (last < m_y_end + YPOS)
834 end = last;
835 else
836 end = m_y_end + YPOS;
837 x_end2 = m_x_end * 2;
838 for (; line < end; vline = (vline + 8) & ~7, line = line + 1 + yend - ybegin)
839 {
840 offs = (vline >> 3) * 80;
841 ybegin = vline & 7;
842 yoff = line - ybegin;
843 yend = (yoff + 7 < end) ? 7 : (end - yoff - 1);
844 /* rendering 39 characters */
845 /* left and right borders are overwritten later */
846 m_shift[line] = HORIZONTALPOS;
847
848 for (xoff = m_x_begin + XPOS; xoff < x_end2 + XPOS; xoff += 8, offs++)
849 {
850 ch = m_dma_read_cb(m_videoaddr + offs);
851 attr = m_dma_read_color_cb(m_videoaddr + offs);
852 if (HIRESON)
853 {
854 m_bitmapmulti[1] = m_c64_bitmap[1] = ch >> 4;
855 m_bitmapmulti[2] = m_c64_bitmap[0] = ch & 0xf;
856 if (MULTICOLORON)
857 {
858 m_bitmapmulti[3] = attr;
859 draw_bitmap_multi(ybegin, yend, offs, yoff, xoff, start_x, end_x);
860 }
861 else
862 {
863 draw_bitmap(ybegin, yend, offs, yoff, xoff, start_x, end_x);
864 }
865 }
866 else if (ECMON)
867 {
868 ecm = ch >> 6;
869 m_ecmcolor[0] = m_colors[ecm];
870 m_ecmcolor[1] = attr;
871 draw_character(ybegin, yend, ch & ~0xC0, yoff, xoff, m_ecmcolor, start_x, end_x);
872 }
873 else if (MULTICOLORON && (attr & 8))
874 {
875 m_multi[3] = attr & 7;
876 draw_character_multi(ybegin, yend, ch, yoff, xoff, start_x, end_x);
877 }
878 else
879 {
880 m_mono[1] = attr;
881 draw_character(ybegin, yend, ch, yoff, xoff, m_mono, start_x, end_x);
882 }
883 }
884 /* sprite priority, sprite overwrites lowerprior pixels */
885 for (i = 7; i >= 0; i--)
886 {
887 if (m_sprites[i].line || m_sprites[i].repeat)
888 {
889 syend = yend;
890 if (SPRITE_Y_EXPAND(i))
891 {
892 if ((21 - m_sprites[i].line) * 2 - m_sprites[i].repeat < yend - ybegin + 1)
893 syend = ybegin + (21 - m_sprites[i].line) * 2 - m_sprites[i].repeat - 1;
894 }
895 else
896 {
897 if (m_sprites[i].line + yend - ybegin + 1 > 20)
898 syend = ybegin + 20 - m_sprites[i].line;
899 }
900 if (yoff + syend > YPOS + 200)
901 syend = YPOS + 200 - yoff - 1;
902 if (SPRITE_MULTICOLOR(i))
903 draw_sprite_multi(i, yoff, ybegin, syend, start_x, end_x);
904 else
905 draw_sprite(i, yoff, ybegin, syend, start_x, end_x);
906 if ((syend != yend) || (m_sprites[i].line > 20))
907 {
908 m_sprites[i].line = m_sprites[i].repeat = 0;
909 for (j = syend; j <= yend; j++)
910 m_sprites[i].paintedline[j] = 0;
911 }
912 }
913 // sprite wrap y at the top of the screen
914 else if (SPRITEON(i) && (yoff == 1 + yend - ybegin) && (SPRITE_Y_POS(i) < 1 + yend - ybegin))
915 {
916 int wrapped = 1 + yend - ybegin - SPRITE_Y_POS(i);
917 syend = yend;
918
919 if (SPRITE_Y_EXPAND(i))
920 {
921 if (wrapped & 1) m_sprites[i].repeat = 1;
922 wrapped >>= 1;
923 syend = 21 * 2 - 1 - wrapped * 2;
924 if (syend > (yend - ybegin)) syend = yend - ybegin;
925 }
926 else
927 {
928 syend = 21 - 1 - wrapped;
929 if (syend > (yend - ybegin)) syend = yend - ybegin;
930 }
931
932 m_sprites[i].line = wrapped;
933
934 if (SPRITE_MULTICOLOR(i))
935 draw_sprite_multi(i, yoff, 0 , syend, start_x, end_x);
936 else
937 draw_sprite(i, yoff, 0 , syend, start_x, end_x);
938
939 if ((syend != yend) || (m_sprites[i].line > 20))
940 {
941 for (j = syend; j <= yend; j++)
942 m_sprites[i].paintedline[j] = 0;
943 m_sprites[i].line = m_sprites[i].repeat = 0;
944 }
945 }
946 else if (SPRITEON(i) && (yoff + ybegin <= SPRITE_Y_POS(i))
947 && (yoff + yend >= SPRITE_Y_POS(i)))
948 {
949 syend = yend;
950 if (SPRITE_Y_EXPAND(i))
951 {
952 if (21 * 2 < yend - ybegin + 1)
953 syend = ybegin + 21 * 2 - 1;
954 }
955 else
956 {
957 if (yend - ybegin + 1 > 21)
958 syend = ybegin + 21 - 1;
959 }
960 if (yoff + syend >= YPOS + 200)
961 syend = YPOS + 200 - yoff - 1;
962 for (j = 0; j < SPRITE_Y_POS(i) - yoff; j++)
963 m_sprites[i].paintedline[j] = 0;
964 if (SPRITE_MULTICOLOR(i))
965 draw_sprite_multi(i, yoff, SPRITE_Y_POS(i) - yoff, syend, start_x, end_x);
966 else
967 draw_sprite(i, yoff, SPRITE_Y_POS(i) - yoff, syend, start_x, end_x);
968 if ((syend != yend) || (m_sprites[i].line > 20))
969 {
970 for (j = syend; j <= yend; j++)
971 m_sprites[i].paintedline[j] = 0;
972 m_sprites[i].line = m_sprites[i].repeat = 0;
973 }
974 }
975 else
976 {
977 memset (m_sprites[i].paintedline, 0, sizeof (m_sprites[i].paintedline));
978 }
979 }
980
981 for (i = ybegin; i <= yend; i++)
982 {
983 m_bitmap->plot_box(0, yoff + ybegin + FIRSTLINE, xbegin, yend - ybegin + 1, FRAMECOLOR);
984 m_bitmap->plot_box(xend, yoff + ybegin + FIRSTLINE, m_bitmap->width() - xend, yend - ybegin + 1, FRAMECOLOR);
985 }
986 }
987 if (last < m_bitmap->height())
988 end = last;
989 else
990 end = m_bitmap->height();
991
992 for (; line < end; line++)
993 {
994 std::fill_n(&m_bitmap->pix(line + FIRSTLINE), m_bitmap->width(), FRAMECOLOR);
995 }
996 }
997
vic2_drawlines(int first,int last,int start_x,int end_x)998 void vic3_device::vic2_drawlines( int first, int last, int start_x, int end_x )
999 {
1000 if (VIC3_BITPLANES)
1001 return;
1002
1003 /* temporary allowing vic3 displaying 80 columns */
1004 if (m_reg[0x31] & 0x80)
1005 {
1006 drawlines(first, first + 1, start_x, end_x);
1007 return;
1008 }
1009
1010 /* otherwise, draw VIC II output (currently using the old code, not the new one from vic6567.c) */
1011
1012 /* top part of display not rastered */
1013 first -= VIC2_YPOS - YPOS;
1014
1015 int xbegin = VIC2_STARTVISIBLECOLUMNS;
1016 int xend = xbegin + VIC2_VISIBLECOLUMNS;
1017 if (!SCREENON)
1018 {
1019 xbegin = VIC2_STARTVISIBLECOLUMNS;
1020 xend = xbegin + VIC2_VISIBLECOLUMNS;
1021 if ((start_x <= xbegin) && (end_x >= xend))
1022 m_bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR);
1023 if ((start_x > xbegin) && (end_x >= xend))
1024 m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR);
1025 if ((start_x <= xbegin) && (end_x < xend))
1026 m_bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR);
1027 if ((start_x > xbegin) && (end_x < xend))
1028 m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
1029 return;
1030 }
1031
1032 if (COLUMNS40)
1033 {
1034 xbegin = XPOS;
1035 xend = xbegin + 320;
1036 }
1037 else
1038 {
1039 xbegin = XPOS + 7;
1040 xend = xbegin + 304;
1041 }
1042
1043 int end;
1044 if (first + 1 < m_y_begin)
1045 end = first + 1;
1046 else
1047 end = m_y_begin + YPOS;
1048
1049 int line = first;
1050 // top border
1051 if (line < end)
1052 {
1053 if ((start_x <= xbegin) && (end_x >= xend))
1054 m_bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR);
1055 if ((start_x > xbegin) && (end_x >= xend))
1056 m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR);
1057 if ((start_x <= xbegin) && (end_x < xend))
1058 m_bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR);
1059 if ((start_x > xbegin) && (end_x < xend))
1060 m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
1061 line = end;
1062 }
1063
1064 int vline = line - YPOS + 3 - VERTICALPOS;
1065
1066 if (first + 1 < m_y_end + YPOS)
1067 end = first + 1;
1068 else
1069 end = m_y_end + YPOS;
1070
1071 if (line < end)
1072 {
1073 int offs = (vline >> 3) * 40;
1074 int ybegin = vline & 7;
1075 int yoff = line - ybegin;
1076 int yend = (yoff + 7 < end) ? 7 : (end - yoff - 1);
1077
1078 /* rendering 39 characters */
1079 /* left and right borders are overwritten later */
1080
1081 m_shift[line] = HORIZONTALPOS;
1082 for (int xoff = m_x_begin + XPOS; xoff < m_x_end + XPOS; xoff += 8, offs++)
1083 {
1084 int ch = m_dma_read_cb(m_videoaddr + offs);
1085 #if 0
1086 int attr = m_dma_read_color_cb(m_videoaddr + offs);
1087 #else
1088 /* temporary until vic3 finished */
1089 int attr = m_dma_read_color_cb((m_videoaddr + offs)&0x3ff)&0x0f;
1090 #endif
1091 if (HIRESON)
1092 {
1093 m_bitmapmulti[1] = m_c64_bitmap[1] = ch >> 4;
1094 m_bitmapmulti[2] = m_c64_bitmap[0] = ch & 0xf;
1095 if (MULTICOLORON)
1096 {
1097 m_bitmapmulti[3] = attr;
1098 draw_bitmap_multi(ybegin, yend, offs, yoff, xoff, start_x, end_x);
1099 }
1100 else
1101 {
1102 draw_bitmap(ybegin, yend, offs, yoff, xoff, start_x, end_x);
1103 }
1104 }
1105 else if (ECMON)
1106 {
1107 int ecm = ch >> 6;
1108 m_ecmcolor[0] = m_colors[ecm];
1109 m_ecmcolor[1] = attr;
1110 draw_character(ybegin, yend, ch & ~0xC0, yoff, xoff, m_ecmcolor, start_x, end_x);
1111 }
1112 else if (MULTICOLORON && (attr & 8))
1113 {
1114 m_multi[3] = attr & 7;
1115 draw_character_multi(ybegin, yend, ch, yoff, xoff, start_x, end_x);
1116 }
1117 else
1118 {
1119 m_mono[1] = attr;
1120 draw_character(ybegin, yend, ch, yoff, xoff, m_mono, start_x, end_x);
1121 }
1122 }
1123
1124 /* sprite priority, sprite overwrites lowerprior pixels */
1125 for (int i = 7; i >= 0; i--)
1126 {
1127 if (SPRITEON (i) &&
1128 (yoff + ybegin >= SPRITE_Y_POS (i)) &&
1129 (yoff + ybegin - SPRITE_Y_POS (i) < (SPRITE_Y_EXPAND (i)? 21 * 2 : 21 )) &&
1130 (SPRITE_Y_POS (i) < 0))
1131 {
1132 int wrapped = - SPRITE_Y_POS (i) + 6;
1133
1134 int syend = yend;
1135
1136 if (SPRITE_Y_EXPAND (i))
1137 {
1138 if (wrapped & 1) m_sprites[i].repeat = 1;
1139 wrapped >>= 1;
1140 syend = 21 * 2 - 1 - wrapped * 2;
1141 if (syend > (yend - ybegin)) syend = yend - ybegin;
1142 }
1143 else
1144 {
1145 syend = 21 - 1 - wrapped;
1146 if (syend > (yend - ybegin)) syend = yend - ybegin;
1147 }
1148
1149 m_sprites[i].line = wrapped;
1150
1151 if (SPRITE_MULTICOLOR (i))
1152 draw_sprite_multi(i, 0, 0 , syend, start_x, end_x);
1153 else
1154 draw_sprite(i, 0, 0 , syend, start_x, end_x);
1155 }
1156 else if (SPRITEON (i) &&
1157 (yoff + ybegin >= SPRITE_Y_POS (i)) &&
1158 (yoff + ybegin - SPRITE_Y_POS (i) < (SPRITE_Y_EXPAND (i)? 21 * 2 : 21 )) &&
1159 (SPRITE_Y_POS (i) >= 0))
1160 {
1161 int wrapped = yoff + ybegin - SPRITE_Y_POS (i);
1162
1163 int syend = yend;
1164
1165 if (SPRITE_Y_EXPAND (i))
1166 {
1167 if (wrapped & 1) m_sprites[i].repeat = 1;
1168 wrapped >>= 1;
1169 syend = 21 * 2 - 1 - wrapped * 2;
1170 if (syend > (yend - ybegin)) syend = yend - ybegin;
1171 }
1172 else
1173 {
1174 syend = 21 - 1 - wrapped;
1175 if (syend > (yend - ybegin)) syend = yend - ybegin;
1176 }
1177
1178 m_sprites[i].line = wrapped;
1179
1180 if (SPRITE_MULTICOLOR (i))
1181 draw_sprite_multi(i, yoff + ybegin, 0, 0, start_x, end_x);
1182 else
1183 draw_sprite(i, yoff + ybegin, 0, 0, start_x, end_x);
1184 }
1185 else
1186 {
1187 memset(m_sprites[i].paintedline, 0, sizeof (m_sprites[i].paintedline));
1188 }
1189 }
1190 line += 1 + yend - ybegin;
1191 }
1192
1193 // left border
1194 if ((start_x <= VIC2_STARTVISIBLECOLUMNS) && (end_x >= xbegin))
1195 m_bitmap->plot_box(VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xbegin - VIC2_STARTVISIBLECOLUMNS, 1, FRAMECOLOR);
1196 else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x >= xbegin))
1197 m_bitmap->plot_box(start_x, first + FIRSTLINE, xbegin - start_x, 1, FRAMECOLOR);
1198 else if ((start_x <= VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin))
1199 m_bitmap->plot_box(VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x, 1, FRAMECOLOR);
1200 else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin))
1201 m_bitmap->plot_box(start_x, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
1202
1203 // right border
1204 if ((start_x <= xend) && (end_x >= VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS))
1205 m_bitmap->plot_box(xend, first + FIRSTLINE, VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS - xend, 1, FRAMECOLOR);
1206 else if ((start_x > xend) && (end_x >= VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS))
1207 m_bitmap->plot_box(start_x, first + FIRSTLINE, VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS - start_x, 1, FRAMECOLOR);
1208 else if ((start_x <= xend) && (end_x < VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS))
1209 m_bitmap->plot_box(xend, first + FIRSTLINE, end_x - xend, 1, FRAMECOLOR);
1210 else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin))
1211 m_bitmap->plot_box(start_x, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
1212
1213 if (first + 1 < m_bitmap->height())
1214 end = first + 1;
1215 else
1216 end = m_bitmap->height();
1217
1218 // bottom border
1219 if (line < end)
1220 {
1221 if ((start_x <= xbegin) && (end_x >= xend))
1222 m_bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR);
1223 if ((start_x > xbegin) && (end_x >= xend))
1224 m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR);
1225 if ((start_x <= xbegin) && (end_x < xend))
1226 m_bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR);
1227 if ((start_x > xbegin) && (end_x < xend))
1228 m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
1229 line = end;
1230 }
1231 }
1232
1233 /*****************************************************************************
1234 I/O HANDLERS
1235 *****************************************************************************/
1236
palette_w(offs_t offset,uint8_t data)1237 void vic3_device::palette_w(offs_t offset, uint8_t data)
1238 {
1239 if (offset < 0x100)
1240 m_palette_red[offset] = data;
1241 else if (offset < 0x200)
1242 m_palette_green[offset & 0xff] = data;
1243 else
1244 m_palette_blue[offset & 0xff] = data;
1245
1246 m_palette_dirty = 1;
1247 }
1248
1249
port_w(offs_t offset,uint8_t data)1250 void vic3_device::port_w(offs_t offset, uint8_t data)
1251 {
1252 DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
1253 offset &= 0x7f;
1254
1255 /* offsets 0x00 -> 0x2e coincide with VICII */
1256 switch (offset)
1257 {
1258 case 0x01:
1259 case 0x03:
1260 case 0x05:
1261 case 0x07:
1262 case 0x09:
1263 case 0x0b:
1264 case 0x0d:
1265 case 0x0f:
1266 /* sprite y positions */
1267 if (m_reg[offset] != data)
1268 {
1269 m_reg[offset] = data;
1270 m_sprites[offset / 2].y = SPRITE_Y_POS(offset / 2);
1271 }
1272 break;
1273
1274 case 0x00:
1275 case 0x02:
1276 case 0x04:
1277 case 0x06:
1278 case 0x08:
1279 case 0x0a:
1280 case 0x0c:
1281 case 0x0e:
1282 /* sprite x positions */
1283 if (m_reg[offset] != data)
1284 {
1285 m_reg[offset] = data;
1286 m_sprites[offset / 2].x = SPRITE_X_POS(offset / 2);
1287 }
1288 break;
1289
1290 case 0x10: /* sprite x positions */
1291 if (m_reg[offset] != data)
1292 {
1293 m_reg[offset] = data;
1294 m_sprites[0].x = SPRITE_X_POS(0);
1295 m_sprites[1].x = SPRITE_X_POS(1);
1296 m_sprites[2].x = SPRITE_X_POS(2);
1297 m_sprites[3].x = SPRITE_X_POS(3);
1298 m_sprites[4].x = SPRITE_X_POS(4);
1299 m_sprites[5].x = SPRITE_X_POS(5);
1300 m_sprites[6].x = SPRITE_X_POS(6);
1301 m_sprites[7].x = SPRITE_X_POS(7);
1302 }
1303 break;
1304
1305 case 0x17: /* sprite y size */
1306 if (m_reg[offset] != data)
1307 {
1308 m_reg[offset] = data;
1309 }
1310 break;
1311
1312 case 0x1d: /* sprite x size */
1313 if (m_reg[offset] != data)
1314 {
1315 m_reg[offset] = data;
1316 }
1317 break;
1318
1319 case 0x1b: /* sprite background priority */
1320 if (m_reg[offset] != data)
1321 {
1322 m_reg[offset] = data;
1323 }
1324 break;
1325
1326 case 0x1c: /* sprite multicolor mode select */
1327 if (m_reg[offset] != data)
1328 {
1329 m_reg[offset] = data;
1330 }
1331 break;
1332
1333 case 0x27:
1334 case 0x28:
1335 case 0x29:
1336 case 0x2a:
1337 case 0x2b:
1338 case 0x2c:
1339 case 0x2d:
1340 case 0x2e:
1341 /* sprite colors */
1342 if (m_reg[offset] != data)
1343 {
1344 m_reg[offset] = data;
1345 }
1346 break;
1347
1348 case 0x25: /* sprite multicolor */
1349 if (m_reg[offset] != data)
1350 {
1351 m_reg[offset] = data;
1352 m_spritemulti[1] = SPRITE_MULTICOLOR1;
1353 }
1354 break;
1355
1356 case 0x26: /* sprite multicolor */
1357 if (m_reg[offset] != data)
1358 {
1359 m_reg[offset] = data;
1360 m_spritemulti[3] = SPRITE_MULTICOLOR2;
1361 }
1362 break;
1363
1364 case 0x19:
1365 clear_interrupt(data & 0x0f);
1366 break;
1367
1368 case 0x1a: /* irq mask */
1369 m_reg[offset] = data;
1370 set_interrupt(0); // beamrider needs this
1371 break;
1372
1373 case 0x11:
1374 if (m_reg[offset] != data)
1375 {
1376 m_reg[offset] = data;
1377 if (LINES25)
1378 {
1379 m_y_begin = 0;
1380 m_y_end = m_y_begin + 200;
1381 }
1382 else
1383 {
1384 m_y_begin = 4;
1385 m_y_end = m_y_begin + 192;
1386 }
1387 }
1388 break;
1389
1390 case 0x12:
1391 if (data != m_reg[offset])
1392 {
1393 m_reg[offset] = data;
1394 }
1395 break;
1396
1397 case 0x16:
1398 if (m_reg[offset] != data)
1399 {
1400 m_reg[offset] = data;
1401 m_x_begin = HORIZONTALPOS;
1402 m_x_end = m_x_begin + 320;
1403 }
1404 break;
1405
1406 case 0x18:
1407 if (m_reg[offset] != data)
1408 {
1409 m_reg[offset] = data;
1410 m_videoaddr = VIDEOADDR;
1411 m_chargenaddr = CHARGENADDR;
1412 m_bitmapaddr = BITMAPADDR;
1413 }
1414 break;
1415
1416 case 0x21: /* background color */
1417 if (m_reg[offset] != data)
1418 {
1419 m_reg[offset] = data;
1420 m_mono[0] = m_bitmapmulti[0] = m_multi[0] = m_colors[0] = BACKGROUNDCOLOR;
1421 }
1422 break;
1423
1424 case 0x22: /* background color 1 */
1425 if (m_reg[offset] != data)
1426 {
1427 m_reg[offset] = data;
1428 m_multi[1] = m_colors[1] = MULTICOLOR1;
1429 }
1430 break;
1431
1432 case 0x23: /* background color 2 */
1433 if (m_reg[offset] != data)
1434 {
1435 m_reg[offset] = data;
1436 m_multi[2] = m_colors[2] = MULTICOLOR2;
1437 }
1438 break;
1439
1440 case 0x24: /* background color 3 */
1441 if (m_reg[offset] != data)
1442 {
1443 m_reg[offset] = data;
1444 m_colors[3] = FOREGROUNDCOLOR;
1445 }
1446 break;
1447
1448 case 0x20: /* framecolor */
1449 if (m_reg[offset] != data)
1450 {
1451 m_reg[offset] = data;
1452 }
1453 break;
1454
1455 case 0x2f:
1456 DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
1457 m_reg[offset] = data;
1458 break;
1459 case 0x30:
1460 m_reg[offset] = data;
1461 if (!m_port_changed_cb.isnull())
1462 {
1463 DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
1464 m_reg[offset] = data;
1465 m_port_changed_cb((offs_t)0,data);
1466 }
1467 break;
1468 case 0x31:
1469 m_reg[offset] = data;
1470 if (data & 0x40)
1471 m_cpu->set_clock_scale(1.0);
1472 else
1473 m_cpu->set_clock_scale(1.0/3.5);
1474 break;
1475 case 0x32:
1476 case 0x33:
1477 case 0x34:
1478 case 0x35:
1479 case 0x36:
1480 case 0x37:
1481 case 0x38:
1482 case 0x39:
1483 case 0x3a:
1484 case 0x3b:
1485 case 0x3c:
1486 case 0x3d:
1487 case 0x3e:
1488 case 0x3f:
1489 m_reg[offset] = data;
1490 DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
1491 break;
1492 case 0x40:
1493 case 0x41:
1494 case 0x42:
1495 case 0x43:
1496 case 0x44:
1497 case 0x45:
1498 case 0x46:
1499 case 0x47:
1500 DBG_LOG(2, "vic plane write", ("%.2x:%.2x\n", offset, data));
1501 break;
1502 default:
1503 m_reg[offset] = data;
1504 break;
1505 }
1506 }
1507
port_r(offs_t offset)1508 uint8_t vic3_device::port_r(offs_t offset)
1509 {
1510 int val = 0;
1511 offset &= 0x7f;
1512
1513 /* offsets 0x00 -> 0x2e coincide with VICII */
1514 switch (offset)
1515 {
1516 case 0x11:
1517 val = (m_reg[offset] & ~0x80) | ((m_rasterline & 0x100) >> 1);
1518 break;
1519
1520 case 0x12:
1521 val = m_rasterline & 0xff;
1522 break;
1523
1524 case 0x16:
1525 val = m_reg[offset] | 0xc0;
1526 break;
1527
1528 case 0x18:
1529 val = m_reg[offset] | 0x01;
1530 break;
1531
1532 case 0x19: /* interrupt flag register */
1533 /* vic2_clear_interrupt(0xf); */
1534 val = m_reg[offset] | 0x70;
1535 break;
1536
1537 case 0x1a:
1538 val = m_reg[offset] | 0xf0;
1539 break;
1540
1541 case 0x1e: /* sprite to sprite collision detect */
1542 val = m_reg[offset];
1543 m_reg[offset] = 0;
1544 clear_interrupt(4);
1545 break;
1546
1547 case 0x1f: /* sprite to background collision detect */
1548 val = m_reg[offset];
1549 m_reg[offset] = 0;
1550 clear_interrupt(2);
1551 break;
1552
1553 case 0x20:
1554 case 0x21:
1555 case 0x22:
1556 case 0x23:
1557 case 0x24:
1558 val = m_reg[offset];
1559 break;
1560
1561 case 0x00:
1562 case 0x01:
1563 case 0x02:
1564 case 0x03:
1565 case 0x04:
1566 case 0x05:
1567 case 0x06:
1568 case 0x07:
1569 case 0x08:
1570 case 0x09:
1571 case 0x0a:
1572 case 0x0b:
1573 case 0x0c:
1574 case 0x0d:
1575 case 0x0e:
1576 case 0x0f:
1577 case 0x10:
1578 case 0x17:
1579 case 0x1b:
1580 case 0x1c:
1581 case 0x1d:
1582 case 0x25:
1583 case 0x26:
1584 case 0x27:
1585 case 0x28:
1586 case 0x29:
1587 case 0x2a:
1588 case 0x2b:
1589 case 0x2c:
1590 case 0x2d:
1591 case 0x2e:
1592 val = m_reg[offset];
1593 break;
1594
1595 case 0x2f:
1596 case 0x30:
1597 val = m_reg[offset];
1598 DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
1599 break;
1600 case 0x31:
1601 case 0x32:
1602 case 0x33:
1603 case 0x34:
1604 case 0x35:
1605 case 0x36:
1606 case 0x37:
1607 case 0x38:
1608 case 0x39:
1609 case 0x3a:
1610 case 0x3b:
1611 case 0x3c:
1612 case 0x3d:
1613 case 0x3e:
1614 case 0x3f: /* not used */
1615 val = m_reg[offset];
1616 DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
1617 break;
1618 case 0x40:
1619 case 0x41:
1620 case 0x42:
1621 case 0x43:
1622 case 0x44:
1623 case 0x45:
1624 case 0x46:
1625 case 0x47:
1626 DBG_LOG(2, "vic3 plane read", ("%.2x:%.2x\n", offset, val));
1627 break;
1628 default:
1629 val = m_reg[offset];
1630 }
1631 return val;
1632 }
1633
1634
1635 #define VIC3_MASK(M) \
1636 if (M) \
1637 { \
1638 if (M & 0x01) \
1639 colors[0] = m_c64_mem_r_cb(VIC3_ADDR(0) + offset); \
1640 if (M & 0x02) \
1641 colors[1] = m_c64_mem_r_cb(VIC3_ADDR(1) + offset) << 1; \
1642 if (M & 0x04) \
1643 colors[2] = m_c64_mem_r_cb(VIC3_ADDR(2) + offset) << 2; \
1644 if (M & 0x08) \
1645 colors[3] = m_c64_mem_r_cb(VIC3_ADDR(3) + offset) << 3; \
1646 if (M & 0x10) \
1647 colors[4] = m_c64_mem_r_cb(VIC3_ADDR(4) + offset) << 4; \
1648 if (M & 0x20) \
1649 colors[5] = m_c64_mem_r_cb(VIC3_ADDR(5) + offset) << 5; \
1650 if (M & 0x40) \
1651 colors[6] = m_c64_mem_r_cb(VIC3_ADDR(6) + offset) << 6; \
1652 if (M & 0x80) \
1653 colors[7] = m_c64_mem_r_cb(VIC3_ADDR(7) + offset) << 7; \
1654 for (int i = 7; i >= 0; i--) \
1655 { \
1656 int p = 0; \
1657 if (M & 0x01) \
1658 { \
1659 p = colors[0] & 0x01; \
1660 colors[0] >>= 1; \
1661 } \
1662 if (M & 0x02) \
1663 { \
1664 p |= colors[1] & 0x02; \
1665 colors[1] >>= 1; \
1666 } \
1667 if (M & 0x04) \
1668 { \
1669 p |= colors[2] & 0x04; \
1670 colors[2] >>= 1; \
1671 } \
1672 if (M & 0x08) \
1673 { \
1674 p |= colors[3] & 0x08; \
1675 colors[3] >>= 1; \
1676 } \
1677 if (M & 0x10) \
1678 { \
1679 p |= colors[4] & 0x10; \
1680 colors[4] >>= 1; \
1681 } \
1682 if (M & 0x20) \
1683 { \
1684 p |= colors[5] & 0x20; \
1685 colors[5] >>= 1; \
1686 } \
1687 if (M & 0x40) \
1688 { \
1689 p |= colors[6] & 0x40; \
1690 colors[6] >>= 1; \
1691 } \
1692 if (M & 0x80) \
1693 { \
1694 p |= colors[7] & 0x80; \
1695 colors[7] >>= 1; \
1696 } \
1697 m_bitmap->pix(YPOS + y, XPOS + x + i) = p; \
1698 } \
1699 }
1700
1701 #define VIC3_ADDR(a) VIC3_BITPLANE_IADDR(a)
interlace_draw_block(int x,int y,int offset)1702 void vic3_device::interlace_draw_block( int x, int y, int offset )
1703 {
1704 int colors[8] = {0};
1705
1706 switch (VIC3_BITPLANES_MASK)
1707 {
1708 case 0x05:
1709 VIC3_MASK(0x05)
1710 break;
1711 case 0x07:
1712 VIC3_MASK(0x07)
1713 break;
1714 case 0x0f:
1715 VIC3_MASK(0x0f)
1716 break;
1717 case 0x1f:
1718 VIC3_MASK(0x1f)
1719 break;
1720 case 0x7f:
1721 VIC3_MASK(0x7f)
1722 break;
1723 case 0xff:
1724 VIC3_MASK(0xff)
1725 break;
1726 default:
1727 if (VIC3_BITPLANES_MASK & 0x01)
1728 colors[0] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(0) + offset);
1729
1730 if (VIC3_BITPLANES_MASK & 0x02)
1731 colors[1] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(1) + offset) << 1;
1732
1733 if (VIC3_BITPLANES_MASK & 0x04)
1734 colors[2] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(2) + offset) << 2;
1735
1736 if (VIC3_BITPLANES_MASK & 0x08)
1737 colors[3] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(3) + offset) << 3;
1738
1739 if (VIC3_BITPLANES_MASK & 0x10)
1740 colors[4] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(4) + offset) << 4;
1741
1742 if (VIC3_BITPLANES_MASK & 0x20)
1743 colors[5] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(5) + offset) << 5;
1744
1745 if (VIC3_BITPLANES_MASK & 0x40)
1746 colors[6] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(6) + offset) << 6;
1747
1748 if (VIC3_BITPLANES_MASK & 0x80)
1749 colors[7] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(7) + offset) << 7;
1750
1751 for (int i = 7; i >= 0; i--)
1752 {
1753 m_bitmap->pix(YPOS + y, XPOS + x + i) =
1754 (colors[0] & 0x01) | (colors[1] & 0x02) |
1755 (colors[2] & 0x04) | (colors[3] & 0x08) |
1756 (colors[4] & 0x10) | (colors[5] & 0x20) |
1757 (colors[6] & 0x40) | (colors[7] & 0x80);
1758 colors[0] >>= 1;
1759 colors[1] >>= 1;
1760 colors[2] >>= 1;
1761 colors[3] >>= 1;
1762 colors[4] >>= 1;
1763 colors[5] >>= 1;
1764 colors[6] >>= 1;
1765 colors[7] >>= 1;
1766 }
1767 }
1768 }
1769
1770 #undef VIC3_ADDR
1771 #define VIC3_ADDR(a) VIC3_BITPLANE_ADDR(a)
draw_block(int x,int y,int offset)1772 void vic3_device::draw_block( int x, int y, int offset )
1773 {
1774 int colors[8] = {0};
1775
1776 switch (VIC3_BITPLANES_MASK)
1777 {
1778 case 5:
1779 VIC3_MASK(0x05)
1780 break;
1781 case 7:
1782 VIC3_MASK(0x07)
1783 break;
1784 case 0xf:
1785 VIC3_MASK(0x0f)
1786 break;
1787 case 0x1f:
1788 VIC3_MASK(0x1f)
1789 break;
1790 case 0x7f:
1791 VIC3_MASK(0x7f)
1792 break;
1793 case 0xff:
1794 VIC3_MASK(0xff)
1795 break;
1796 default:
1797 if (VIC3_BITPLANES_MASK & 0x01)
1798 colors[0] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(0) + offset);
1799
1800 if (VIC3_BITPLANES_MASK & 0x02)
1801 colors[1] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(1) + offset) << 1;
1802
1803 if (VIC3_BITPLANES_MASK & 0x04)
1804 colors[2] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(2) + offset) << 2;
1805
1806 if (VIC3_BITPLANES_MASK & 0x08)
1807 colors[3] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(3) + offset) << 3;
1808
1809 if (VIC3_BITPLANES_MASK & 0x10)
1810 colors[4] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(4) + offset) << 4;
1811
1812 if (VIC3_BITPLANES_MASK & 0x20)
1813 colors[5] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(5) + offset) << 5;
1814
1815 if (VIC3_BITPLANES_MASK & 0x40)
1816 colors[6] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(6) + offset) << 6;
1817
1818 if (VIC3_BITPLANES_MASK & 0x80)
1819 colors[7] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(7) + offset) << 7;
1820
1821 for (int i = 7; i >= 0; i--)
1822 {
1823 m_bitmap->pix(YPOS + y, XPOS + x + i) =
1824 (colors[0] & 0x01) | (colors[1] & 0x02) |
1825 (colors[2] & 0x04) | (colors[3] & 0x08) |
1826 (colors[4] & 0x10) | (colors[5] & 0x20) |
1827 (colors[6] & 0x40) | (colors[7] & 0x80);
1828 colors[0] >>= 1;
1829 colors[1] >>= 1;
1830 colors[2] >>= 1;
1831 colors[3] >>= 1;
1832 colors[4] >>= 1;
1833 colors[5] >>= 1;
1834 colors[6] >>= 1;
1835 colors[7] >>= 1;
1836 }
1837 }
1838 }
1839
1840
draw_bitplanes()1841 void vic3_device::draw_bitplanes()
1842 {
1843 const rectangle &visarea = screen().visible_area();
1844
1845 if (VIC3_LINES == 400)
1846 { /* interlaced! */
1847 for (int y1s = 0, offset = 0; y1s < 400; y1s += 16)
1848 {
1849 for (int x = 0; x < VIC3_BITPLANES_WIDTH; x += 8)
1850 {
1851 for (int y = y1s; y < y1s + 16; y += 2, offset++)
1852 {
1853 if (m_interlace)
1854 draw_block(x, y, offset);
1855 else
1856 interlace_draw_block(x, y + 1, offset);
1857 }
1858 }
1859 }
1860 m_interlace ^= 1;
1861 }
1862 else
1863 {
1864 for (int y1s = 0, offset = 0; y1s < 200; y1s += 8)
1865 {
1866 for (int x = 0; x < VIC3_BITPLANES_WIDTH; x += 8)
1867 {
1868 for (int y = y1s; y < y1s + 8; y++, offset++)
1869 {
1870 draw_block(x, y, offset);
1871 }
1872 }
1873 }
1874 }
1875
1876 if (XPOS > 0)
1877 {
1878 rectangle vis(0, XPOS - 1, 0, visarea.bottom());
1879 m_bitmap->fill(FRAMECOLOR, vis);
1880 }
1881
1882 if (XPOS + VIC3_BITPLANES_WIDTH < visarea.right())
1883 {
1884 rectangle vis(XPOS + VIC3_BITPLANES_WIDTH, visarea.right(), 0, visarea.bottom());
1885 m_bitmap->fill(FRAMECOLOR, vis);
1886 }
1887
1888 if (YPOS > 0)
1889 {
1890 rectangle vis(0, visarea.right(), 0, YPOS - 1);
1891 m_bitmap->fill(FRAMECOLOR, vis);
1892 }
1893
1894 if (YPOS + VIC3_LINES < visarea.bottom())
1895 {
1896 rectangle vis(0, visarea.right(), YPOS + VIC3_LINES, visarea.bottom());
1897 m_bitmap->fill(FRAMECOLOR, vis);
1898 }
1899 }
1900
raster_interrupt_gen()1901 void vic3_device::raster_interrupt_gen()
1902 {
1903 int new_columns, new_rows;
1904 int i;
1905
1906 m_rasterline++;
1907 if (m_rasterline >= m_lines)
1908 {
1909 m_rasterline = 0;
1910 if (m_palette_dirty)
1911 for (i = 0; i < 256; i++)
1912 set_pen_color(i, m_palette_red[i] << 4, m_palette_green[i] << 4, m_palette_blue[i] << 4);
1913
1914 if (m_palette_dirty)
1915 {
1916 m_spritemulti[1] = SPRITE_MULTICOLOR1;
1917 m_spritemulti[3] = SPRITE_MULTICOLOR2;
1918 m_mono[0] = m_bitmapmulti[0] = m_multi[0] = m_colors[0] = BACKGROUNDCOLOR;
1919 m_multi[1] = m_colors[1] = MULTICOLOR1;
1920 m_multi[2] = m_colors[2] = MULTICOLOR2;
1921 m_colors[3] = FOREGROUNDCOLOR;
1922 m_palette_dirty = 0;
1923 }
1924
1925 new_rows = 200;
1926
1927 if (VIC3_BITPLANES)
1928 {
1929 new_columns = VIC3_BITPLANES_WIDTH;
1930 if (new_columns < 320)
1931 new_columns = 320; /*sprites resolution about 320x200 */
1932 new_rows = VIC3_LINES;
1933 }
1934 else if (VIC3_80COLUMNS)
1935 {
1936 new_columns = 640;
1937 }
1938 else
1939 {
1940 new_columns = 320;
1941 }
1942 if ((new_columns != m_columns) || (new_rows != m_rows))
1943 {
1944 m_rows = new_rows;
1945 m_columns = new_columns;
1946 if (m_type == vic3_type::PAL)
1947 screen().set_visible_area(
1948 VIC2_STARTVISIBLECOLUMNS + 32,
1949 VIC2_STARTVISIBLECOLUMNS + 32 + m_columns + 16 - 1,
1950 VIC2_STARTVISIBLELINES + 34,
1951 VIC2_STARTVISIBLELINES + 34 + m_rows + 16 - 1);
1952 else
1953 screen().set_visible_area(
1954 VIC2_STARTVISIBLECOLUMNS + 34,
1955 VIC2_STARTVISIBLECOLUMNS + 34 + m_columns + 16 - 1,
1956 VIC2_STARTVISIBLELINES + 10,
1957 VIC2_STARTVISIBLELINES + 10 + m_rows + 16 - 1);
1958 }
1959 if (VIC3_BITPLANES)
1960 {
1961 draw_bitplanes();
1962 }
1963 else
1964 {
1965 if (m_type == vic3_type::PAL)
1966 {
1967 if (m_on)
1968 vic2_drawlines(m_lastline, m_lines, VIC2_STARTVISIBLECOLUMNS + 32, VIC2_STARTVISIBLECOLUMNS + 32 + m_columns + 16 - 1);
1969 }
1970 else
1971 {
1972 if (m_on)
1973 vic2_drawlines(m_lastline, m_lines, VIC2_STARTVISIBLECOLUMNS + 34, VIC2_STARTVISIBLECOLUMNS + 34 + m_columns + 16 - 1);
1974 }
1975 }
1976
1977 for (i = 0; i < 8; i++)
1978 m_sprites[i].repeat = m_sprites[i].line = 0;
1979
1980 m_lastline = 0;
1981
1982 if (LIGHTPEN_BUTTON)
1983 {
1984 /* lightpen timer start */
1985 machine().scheduler().timer_set(attotime(0, 0), timer_expired_delegate(FUNC(vic3_device::timer_timeout),this), 1);
1986 }
1987
1988 }
1989
1990 if (m_rasterline == C64_2_RASTERLINE(RASTERLINE))
1991 {
1992 set_interrupt(1);
1993 }
1994
1995 if (m_on)
1996 if ((m_rasterline >= VIC2_FIRSTRASTERLINE) && (m_rasterline < (VIC2_FIRSTRASTERLINE + VIC2_VISIBLELINES)))
1997 {
1998 if (m_type == vic3_type::PAL)
1999 {
2000 if (m_on)
2001 vic2_drawlines(m_rasterline - 1, m_rasterline, VIC2_STARTVISIBLECOLUMNS + 32, VIC2_STARTVISIBLECOLUMNS + 32 + m_columns + 16 - 1);
2002 }
2003 else
2004 {
2005 if (m_on)
2006 vic2_drawlines(m_rasterline - 1, m_rasterline, VIC2_STARTVISIBLECOLUMNS + 34, VIC2_STARTVISIBLECOLUMNS + 34 + m_columns + 16 - 1);
2007 }
2008 }
2009 }
2010
video_update(bitmap_ind16 & bitmap,const rectangle & cliprect)2011 uint32_t vic3_device::video_update( bitmap_ind16 &bitmap, const rectangle &cliprect )
2012 {
2013 copybitmap(bitmap, *m_bitmap, 0, 0, 0, 0, cliprect);
2014 return 0;
2015 }
2016