1 // license:GPL-2.0+
2 // copyright-holders:Curt Coder,Christian Bauer
3 /***************************************************************************
4
5 MOS 6566/6567/6569 Video Interface Chip (VIC-II) emulation
6
7 A part of the code (cycle routine and drawing routines) is a modified version of the vic ii emulation used in
8 commodore 64 emulator "frodo" by Christian Bauer
9
10 ***************************************************************************/
11
12 /*
13
14 TODO:
15
16 - cleanup
17 - http://hitmen.c02.at/temp/palstuff/
18
19 */
20
21 #include "emu.h"
22 #include "mos6566.h"
23
24 #include "screen.h"
25
26
27
28 //**************************************************************************
29 // MACROS / CONSTANTS
30 //**************************************************************************
31
32 #define LOG 0
33
34
35 enum
36 {
37 REGISTER_M0X = 0,
38 REGISTER_M0Y,
39 REGISTER_M1X,
40 REGISTER_M1Y,
41 REGISTER_M2X,
42 REGISTER_M2Y,
43 REGISTER_M3X,
44 REGISTER_M3Y,
45 REGISTER_M4X,
46 REGISTER_M4Y,
47 REGISTER_M5X,
48 REGISTER_M5Y,
49 REGISTER_M6X,
50 REGISTER_M6Y,
51 REGISTER_M7X,
52 REGISTER_M7Y,
53 REGISTER_MX_MSB,
54 REGISTER_CR1,
55 REGISTER_RASTER,
56 REGISTER_LPX,
57 REGISTER_LPY,
58 REGISTER_ME,
59 REGISTER_CR2,
60 REGISTER_MYE,
61 REGISTER_MP,
62 REGISTER_IRQ,
63 REGISTER_IE,
64 REGISTER_MDP,
65 REGISTER_MMC,
66 REGISTER_MXE,
67 REGISTER_MM,
68 REGISTER_MD,
69 REGISTER_EC,
70 REGISTER_B0C,
71 REGISTER_B1C,
72 REGISTER_B2C,
73 REGISTER_B3C,
74 REGISTER_MM0,
75 REGISTER_MM1,
76 REGISTER_M0C,
77 REGISTER_M1C,
78 REGISTER_M2C,
79 REGISTER_M3C,
80 REGISTER_M4C,
81 REGISTER_M5C,
82 REGISTER_M6C,
83 REGISTER_M7C,
84 REGISTER_KCR,
85 REGISTER_FAST
86 };
87
88 static int UNUSED_BITS[0x40] =
89 {
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x01, 0x70, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff,
93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
94 };
95
96 // VICE palette
97 static const rgb_t PALETTE_MOS[] =
98 {
99 rgb_t(0x00, 0x00, 0x00),
100 rgb_t(0xfd, 0xfe, 0xfc),
101 rgb_t(0xbe, 0x1a, 0x24),
102 rgb_t(0x30, 0xe6, 0xc6),
103 rgb_t(0xb4, 0x1a, 0xe2),
104 rgb_t(0x1f, 0xd2, 0x1e),
105 rgb_t(0x21, 0x1b, 0xae),
106 rgb_t(0xdf, 0xf6, 0x0a),
107 rgb_t(0xb8, 0x41, 0x04),
108 rgb_t(0x6a, 0x33, 0x04),
109 rgb_t(0xfe, 0x4a, 0x57),
110 rgb_t(0x42, 0x45, 0x40),
111 rgb_t(0x70, 0x74, 0x6f),
112 rgb_t(0x59, 0xfe, 0x59),
113 rgb_t(0x5f, 0x53, 0xfe),
114 rgb_t(0xa4, 0xa7, 0xa2)
115 };
116
117
118 #define VERBOSE_LEVEL 0
119 #define DBG_LOG(N,M,A) \
120 do { \
121 if(VERBOSE_LEVEL >= N) \
122 { \
123 if( M ) \
124 logerror("%11.6f: %-24s", machine().time().as_double(), (char*) M ); \
125 logerror A; \
126 } \
127 } while (0)
128
129 #define IS_PAL ((m_variant == TYPE_6569) || (m_variant == TYPE_6572) || (m_variant == TYPE_6573) || (m_variant == TYPE_8565) || (m_variant == TYPE_8569))
130 #define IS_VICIIE ((m_variant == TYPE_8564) || (m_variant == TYPE_8566) || (m_variant == TYPE_8569))
131
132 #define ROW25_YSTART 0x33
133 #define ROW25_YSTOP 0xfb
134 #define ROW24_YSTART 0x37
135 #define ROW24_YSTOP 0xf7
136
137 #define RASTERLINE_2_C64(a) (a)
138 #define C64_2_RASTERLINE(a) (a)
139 #define XPOS (VIC2_STARTVISIBLECOLUMNS + (VIC2_VISIBLECOLUMNS - VIC2_HSIZE) / 2)
140 #define YPOS (VIC2_STARTVISIBLELINES /* + (VIC2_VISIBLELINES - VIC2_VSIZE) / 2 */)
141 #define FIRSTCOLUMN 50
142
143 /* 2008-05 FP: lightpen code needs to read input port from c64.c and cbmb.c */
144
145 #define LIGHTPEN_BUTTON (m_in_lightpen_button_func(0))
146 #define LIGHTPEN_X_VALUE (m_in_lightpen_x_func(0))
147 #define LIGHTPEN_Y_VALUE (m_in_lightpen_y_func(0))
148
149 /* lightpen delivers values from internal counters; they do not start with the visual area or frame area */
150 #define VIC2_MAME_XPOS 0
151 #define VIC2_MAME_YPOS 0
152 #define VIC6567_X_BEGIN 38
153 #define VIC6567_Y_BEGIN -6 /* first 6 lines after retrace not for lightpen! */
154 #define VIC6569_X_BEGIN 38
155 #define VIC6569_Y_BEGIN -6
156 #define VIC2_X_BEGIN (IS_PAL ? VIC6569_X_BEGIN : VIC6567_X_BEGIN)
157 #define VIC2_Y_BEGIN (IS_PAL ? VIC6569_Y_BEGIN : VIC6567_Y_BEGIN)
158 #define VIC2_X_VALUE ((LIGHTPEN_X_VALUE / 1.3) + 12)
159 #define VIC2_Y_VALUE ((LIGHTPEN_Y_VALUE ) + 10)
160
161 /* sprites 0 .. 7 */
162 #define SPRITEON(nr) (m_reg[0x15] & (1 << nr))
163 #define SPRITE_Y_EXPAND(nr) (m_reg[0x17] & (1 << nr))
164 #define SPRITE_Y_SIZE(nr) (SPRITE_Y_EXPAND(nr) ? 2 * 21 : 21)
165 #define SPRITE_X_EXPAND(nr) (m_reg[0x1d] & (1 << nr))
166 #define SPRITE_X_SIZE(nr) (SPRITE_X_EXPAND(nr) ? 2 * 24 : 24)
167 #define SPRITE_X_POS(nr) (m_reg[(nr) * 2] | (m_reg[0x10] & (1 << (nr)) ? 0x100 : 0))
168 #define SPRITE_Y_POS(nr) (m_reg[1 + 2 * (nr)])
169 #define SPRITE_MULTICOLOR(nr) (m_reg[0x1c] & (1 << nr))
170 #define SPRITE_PRIORITY(nr) (m_reg[0x1b] & (1 << nr))
171 #define SPRITE_MULTICOLOR1 (m_reg[0x25] & 0x0f)
172 #define SPRITE_MULTICOLOR2 (m_reg[0x26] & 0x0f)
173 #define SPRITE_COLOR(nr) (m_reg[0x27+nr] & 0x0f)
174 #define SPRITE_ADDR(nr) (m_videoaddr | 0x3f8 | nr)
175 #define SPRITE_COLL (m_reg[0x1e])
176 #define SPRITE_BG_COLL (m_reg[0x1f])
177
178 #define GFXMODE ((m_reg[0x11] & 0x60) | (m_reg[0x16] & 0x10)) >> 4
179 #define SCREENON (m_reg[0x11] & 0x10)
180 #define YSCROLL (m_reg[0x11] & 0x07)
181 #define XSCROLL (m_reg[0x16] & 0x07)
182 #define ECMON (m_reg[0x11] & 0x40)
183 #define HIRESON (m_reg[0x11] & 0x20)
184 #define COLUMNS40 (m_reg[0x16] & 0x08) /* else 38 Columns */
185
186 #define VIDEOADDR ((m_reg[0x18] & 0xf0) << (10 - 4))
187 #define CHARGENADDR ((m_reg[0x18] & 0x0e) << 10)
188 #define BITMAPADDR ((data & 0x08) << 10)
189
190 #define RASTERLINE (((m_reg[0x11] & 0x80) << 1) | m_reg[0x12])
191
192 #define FRAMECOLOR (m_reg[0x20] & 0x0f)
193 #define BACKGROUNDCOLOR (m_reg[0x21] & 0x0f)
194 #define MULTICOLOR1 (m_reg[0x22] & 0x0f)
195 #define MULTICOLOR2 (m_reg[0x23] & 0x0f)
196 #define FOREGROUNDCOLOR (m_reg[0x24] & 0x0f)
197
198 #define VIC2_LINES (IS_PAL ? VIC6569_LINES : VIC6567_LINES)
199 #define VIC2_FIRST_DMA_LINE (IS_PAL ? VIC6569_FIRST_DMA_LINE : VIC6567_FIRST_DMA_LINE)
200 #define VIC2_LAST_DMA_LINE (IS_PAL ? VIC6569_LAST_DMA_LINE : VIC6567_LAST_DMA_LINE)
201 #define VIC2_FIRST_DISP_LINE (IS_PAL ? VIC6569_FIRST_DISP_LINE : VIC6567_FIRST_DISP_LINE)
202 #define VIC2_LAST_DISP_LINE (IS_PAL ? VIC6569_LAST_DISP_LINE : VIC6567_LAST_DISP_LINE)
203 #define VIC2_RASTER_2_EMU(a) (IS_PAL ? VIC6569_RASTER_2_EMU(a) : VIC6567_RASTER_2_EMU(a))
204 #define VIC2_FIRSTCOLUMN (IS_PAL ? VIC6569_FIRSTCOLUMN : VIC6567_FIRSTCOLUMN)
205 #define VIC2_X_2_EMU(a) (IS_PAL ? VIC6569_X_2_EMU(a) : VIC6567_X_2_EMU(a))
206
207 #define IRQ_RST 0x01
208 #define IRQ_MBC 0x02
209 #define IRQ_MMC 0x04
210 #define IRQ_LP 0x08
211
212
213
214 //**************************************************************************
215 // DEVICE DEFINITIONS
216 //**************************************************************************
217
218 DEFINE_DEVICE_TYPE(MOS6566, mos6566_device, "mos6566", "MOS 6566 VIC-II")
219 DEFINE_DEVICE_TYPE(MOS6567, mos6567_device, "mos6567", "MOS 6567 VIC-II")
220 DEFINE_DEVICE_TYPE(MOS8562, mos8562_device, "mos8562", "MOS 8562 VIC-II")
221 DEFINE_DEVICE_TYPE(MOS8564, mos8564_device, "mos8564", "MOS 8564 VIC-II")
222 DEFINE_DEVICE_TYPE(MOS6569, mos6569_device, "mos6569", "MOS 6569 VIC-II")
223 DEFINE_DEVICE_TYPE(MOS8565, mos8565_device, "mos8565", "MOS 8565 VIC-II")
224 DEFINE_DEVICE_TYPE(MOS8566, mos8566_device, "mos8566", "MOS 8566 VIC-II")
225
226
227 // default address maps
mos6566_videoram_map(address_map & map)228 void mos6566_device::mos6566_videoram_map(address_map &map)
229 {
230 if (!has_configured_map(0))
231 map(0x0000, 0x3fff).ram();
232 }
233
mos6566_colorram_map(address_map & map)234 void mos6566_device::mos6566_colorram_map(address_map &map)
235 {
236 if (!has_configured_map(1))
237 map(0x000, 0x3ff).ram();
238 }
239
240
241 //-------------------------------------------------
242 // memory_space_config - return a description of
243 // any address spaces owned by this device
244 //-------------------------------------------------
245
memory_space_config() const246 device_memory_interface::space_config_vector mos6566_device::memory_space_config() const
247 {
248 return space_config_vector {
249 std::make_pair(0, &m_videoram_space_config),
250 std::make_pair(1, &m_colorram_space_config)
251 };
252 }
253
254
255
256 //**************************************************************************
257 // INLINE HELPERS
258 //**************************************************************************
259
set_interrupt(int mask)260 inline void mos6566_device::set_interrupt( int mask )
261 {
262 if (((m_reg[0x19] ^ mask) & m_reg[0x1a] & 0xf))
263 {
264 if (!(m_reg[0x19] & 0x80))
265 {
266 DBG_LOG(2, "vic2", ("irq start %.2x\n", mask));
267 m_reg[0x19] |= 0x80;
268 m_write_irq(ASSERT_LINE);
269 }
270 }
271 m_reg[0x19] |= mask;
272 }
273
clear_interrupt(int mask)274 inline void mos6566_device::clear_interrupt( int mask )
275 {
276 m_reg[0x19] &= ~mask;
277 if ((m_reg[0x19] & 0x80) && !(m_reg[0x19] & m_reg[0x1a] & 0xf))
278 {
279 DBG_LOG(2, "vic2", ("irq end %.2x\n", mask));
280 m_reg[0x19] &= ~0x80;
281 m_write_irq(CLEAR_LINE);
282 }
283 }
284
read_videoram(offs_t offset)285 inline uint8_t mos6566_device::read_videoram(offs_t offset)
286 {
287 //logerror("cycle %u VRAM %04x BA %u AEC %u\n", m_cycle, offset & 0x3fff, m_ba, m_aec);
288 m_last_data = space(0).read_byte(offset & 0x3fff);
289
290 return m_last_data;
291 }
292
read_colorram(offs_t offset)293 inline uint8_t mos6566_device::read_colorram(offs_t offset)
294 {
295 return space(1).read_byte(offset & 0x3ff);
296 }
297
298 // Idle access
idle_access()299 inline void mos6566_device::idle_access()
300 {
301 read_videoram(0x3fff);
302 }
303
304 // Fetch sprite data pointer
spr_ptr_access(int num)305 inline void mos6566_device::spr_ptr_access( int num )
306 {
307 m_spr_ptr[num] = read_videoram(SPRITE_ADDR(num)) << 6;
308 }
309
spr_ba(int num)310 inline void mos6566_device::spr_ba(int num)
311 {
312 if (BIT(m_spr_dma_on, num))
313 {
314 set_ba(CLEAR_LINE);
315 m_rdy_cycles += 2;
316 }
317 else if (num > 1 && !BIT(m_spr_dma_on, num - 1))
318 {
319 set_ba(ASSERT_LINE);
320 }
321 }
322
323 // Fetch sprite data, increment data counter
spr_data_access(int num,int bytenum)324 inline void mos6566_device::spr_data_access( int num, int bytenum )
325 {
326 if (m_spr_dma_on & (1 << num))
327 {
328 m_spr_data[num][bytenum] = read_videoram((m_mc[num] & 0x3f) | m_spr_ptr[num]);
329 m_mc[num]++;
330 }
331 else
332 if (bytenum == 1)
333 idle_access();
334 }
335
336 // Turn on display if Bad Line
display_if_bad_line()337 inline void mos6566_device::display_if_bad_line()
338 {
339 if (m_is_bad_line)
340 m_display_state = 1;
341 }
342
set_ba(int state)343 inline void mos6566_device::set_ba(int state)
344 {
345 if (m_ba != state)
346 {
347 m_ba = state;
348
349 if (m_ba)
350 {
351 m_aec_delay = 0xff;
352 }
353 }
354 }
355
set_aec(int state)356 inline void mos6566_device::set_aec(int state)
357 {
358 if (m_aec != state)
359 {
360 m_aec = state;
361 }
362 }
363
bad_line_ba()364 inline void mos6566_device::bad_line_ba()
365 {
366 if (m_is_bad_line)
367 {
368 if (m_ba)
369 {
370 set_ba(CLEAR_LINE);
371 m_rdy_cycles += 55 - m_cycle;
372 }
373 }
374 else
375 {
376 set_ba(ASSERT_LINE);
377 }
378 }
379
380 // Refresh access
refresh_access()381 inline void mos6566_device::refresh_access()
382 {
383 read_videoram(0x3f00 | m_ref_cnt--);
384 }
385
386
fetch_if_bad_line()387 inline void mos6566_device::fetch_if_bad_line()
388 {
389 if (m_is_bad_line)
390 m_display_state = 1;
391 }
392
393
394 // Turn on display and matrix access and reset RC if Bad Line
rc_if_bad_line()395 inline void mos6566_device::rc_if_bad_line()
396 {
397 if (m_is_bad_line)
398 {
399 m_display_state = 1;
400 m_rc = 0;
401 }
402 }
403
404 // Sample border color and increment m_graphic_x
sample_border()405 inline void mos6566_device::sample_border()
406 {
407 if (m_draw_this_line)
408 {
409 if (m_border_on)
410 m_border_color_sample[m_cycle - 13] = FRAMECOLOR;
411 m_graphic_x += 8;
412 }
413 }
414
415
416 // Turn on sprite DMA if necessary
check_sprite_dma()417 inline void mos6566_device::check_sprite_dma()
418 {
419 int i;
420 uint8_t mask = 1;
421
422 for (i = 0; i < 8; i++, mask <<= 1)
423 if (SPRITEON(i) && ((m_rasterline & 0xff) == SPRITE_Y_POS(i)))
424 {
425 m_spr_dma_on |= mask;
426 m_mc_base[i] = 0;
427 if (SPRITE_Y_EXPAND(i))
428 m_spr_exp_y &= ~mask;
429 }
430 }
431
432 // Video matrix access
matrix_access()433 inline void mos6566_device::matrix_access()
434 {
435 if (!m_is_bad_line) return;
436
437 uint16_t adr = (m_vc & 0x03ff) | VIDEOADDR;
438
439 // we're in the second clock phase
440 m_phi0 = 1;
441 set_aec(BIT(m_aec_delay, 2));
442
443 if (!m_ba && m_aec)
444 {
445 m_matrix_line[m_ml_index] = 0xff;
446 }
447 else
448 {
449 m_matrix_line[m_ml_index] = read_videoram(adr);
450 }
451
452 m_color_line[m_ml_index] = read_colorram(adr & 0x03ff);
453 }
454
455 // Graphics data access
graphics_access()456 inline void mos6566_device::graphics_access()
457 {
458 if (m_display_state == 1)
459 {
460 uint16_t adr;
461 if (HIRESON)
462 adr = ((m_vc & 0x03ff) << 3) | m_bitmapaddr | m_rc;
463 else
464 adr = (m_matrix_line[m_ml_index] << 3) | m_chargenaddr | m_rc;
465 if (ECMON)
466 adr &= 0xf9ff;
467 m_gfx_data = read_videoram(adr);
468 m_char_data = m_matrix_line[m_ml_index];
469 m_color_data = m_color_line[m_ml_index];
470 m_ml_index++;
471 m_vc++;
472 }
473 else
474 {
475 m_gfx_data = read_videoram((ECMON ? 0x39ff : 0x3fff));
476 m_char_data = 0;
477 }
478 }
479
draw_background()480 inline void mos6566_device::draw_background()
481 {
482 if (m_draw_this_line)
483 {
484 uint8_t c;
485
486 switch (GFXMODE)
487 {
488 case 0:
489 case 1:
490 case 3:
491 c = m_colors[0];
492 break;
493 case 2:
494 c = m_last_char_data & 0x0f;
495 break;
496 case 4:
497 if (m_last_char_data & 0x80)
498 if (m_last_char_data & 0x40)
499 c = m_colors[3];
500 else
501 c = m_colors[2];
502 else
503 if (m_last_char_data & 0x40)
504 c = m_colors[1];
505 else
506 c = m_colors[0];
507 break;
508 default:
509 c = 0;
510 break;
511 }
512 m_bitmap.plot_box(m_graphic_x, VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[c]);
513 }
514 }
515
draw_mono(uint16_t p,uint8_t c0,uint8_t c1)516 inline void mos6566_device::draw_mono( uint16_t p, uint8_t c0, uint8_t c1 )
517 {
518 uint8_t const c[2] = { c0, c1 };
519 uint8_t data = m_gfx_data;
520
521 for (unsigned i = 0; i < 8; i++)
522 {
523 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 7 - i) = PALETTE_MOS[c[data & 1]];
524 m_fore_coll_buf[p + 7 - i] = data & 1;
525 data >>= 1;
526 }
527 }
528
draw_multi(uint16_t p,uint8_t c0,uint8_t c1,uint8_t c2,uint8_t c3)529 inline void mos6566_device::draw_multi( uint16_t p, uint8_t c0, uint8_t c1, uint8_t c2, uint8_t c3 )
530 {
531 uint8_t const c[4] = { c0, c1, c2, c3 };
532 uint8_t data = m_gfx_data;
533
534 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 7) = PALETTE_MOS[c[data & 3]];
535 m_fore_coll_buf[p + 7] = data & 2;
536 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 6) = PALETTE_MOS[c[data & 3]];
537 m_fore_coll_buf[p + 6] = data & 2; data >>= 2;
538 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 5) = PALETTE_MOS[c[data & 3]];
539 m_fore_coll_buf[p + 5] = data & 2;
540 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 4) = PALETTE_MOS[c[data & 3]];
541 m_fore_coll_buf[p + 4] = data & 2; data >>= 2;
542 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 3) = PALETTE_MOS[c[data & 3]];
543 m_fore_coll_buf[p + 3] = data & 2;
544 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 2) = PALETTE_MOS[c[data & 3]];
545 m_fore_coll_buf[p + 2] = data & 2; data >>= 2;
546 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 1) = PALETTE_MOS[c[data]];
547 m_fore_coll_buf[p + 1] = data & 2;
548 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 0) = PALETTE_MOS[c[data]];
549 m_fore_coll_buf[p + 0] = data & 2;
550 }
551
552
553
554 //**************************************************************************
555 // LIVE DEVICE
556 //**************************************************************************
557
558 //-------------------------------------------------
559 // mos6566_device - constructor
560 //-------------------------------------------------
561
mos6566_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)562 mos6566_device::mos6566_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
563 : mos6566_device(mconfig, MOS6566, tag, owner, clock, TYPE_6566)
564 {
565 }
566
mos6566_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,uint32_t variant)567 mos6566_device::mos6566_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t variant)
568 : device_t(mconfig, type, tag, owner, clock),
569 device_memory_interface(mconfig, *this),
570 device_video_interface(mconfig, *this),
571 device_execute_interface(mconfig, *this),
572 m_icount(0),
573 m_variant(variant),
574 m_videoram_space_config("videoram", ENDIANNESS_LITTLE, 8, 14, 0, address_map_constructor(FUNC(mos6566_device::mos6566_videoram_map), this)),
575 m_colorram_space_config("colorram", ENDIANNESS_LITTLE, 8, 10, 0, address_map_constructor(FUNC(mos6566_device::mos6566_colorram_map), this)),
576 m_write_irq(*this),
577 m_write_ba(*this),
578 m_write_aec(*this),
579 m_write_k(*this),
580 m_cpu(*this, finder_base::DUMMY_TAG),
581 m_phi0(1),
582 m_ba(ASSERT_LINE),
583 m_aec(ASSERT_LINE)
584 {
585 }
586
mos6567_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)587 mos6567_device::mos6567_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
588 : mos6567_device(mconfig, MOS6567, tag, owner, clock, TYPE_6567)
589 {
590 }
591
mos6567_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,uint32_t variant)592 mos6567_device::mos6567_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t variant)
593 : mos6566_device(mconfig, type, tag, owner, clock, variant)
594 {
595 }
596
mos8562_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)597 mos8562_device::mos8562_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
598 : mos6567_device(mconfig, MOS8562, tag, owner, clock, TYPE_8562)
599 {
600 }
601
mos8564_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)602 mos8564_device::mos8564_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
603 : mos6567_device(mconfig, MOS8564, tag, owner, clock, TYPE_8564)
604 {
605 }
606
mos6569_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)607 mos6569_device::mos6569_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
608 : mos6569_device(mconfig, MOS6569, tag, owner, clock, TYPE_6569)
609 {
610 }
611
mos6569_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,uint32_t variant)612 mos6569_device::mos6569_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t variant)
613 : mos6566_device(mconfig, type, tag, owner, clock, variant)
614 {
615 }
616
mos8565_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)617 mos8565_device::mos8565_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
618 : mos6569_device(mconfig, MOS8565, tag, owner, clock, TYPE_8565)
619 {
620 }
621
mos8566_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)622 mos8566_device::mos8566_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
623 : mos6569_device(mconfig, MOS8566, tag, owner, clock, TYPE_8566)
624 {
625 }
626
627
628 //-------------------------------------------------
629 // device_start - device-specific startup
630 //-------------------------------------------------
631
device_start()632 void mos6566_device::device_start()
633 {
634 // set our instruction counter
635 set_icountptr(m_icount);
636
637 // resolve callbacks
638 m_write_irq.resolve_safe();
639 m_write_ba.resolve_safe();
640 m_write_aec.resolve_safe();
641 m_write_k.resolve_safe();
642
643 screen().register_screen_bitmap(m_bitmap);
644
645 for (int i = 0; i < 256; i++)
646 {
647 m_expandx[i] = 0;
648 if (i & 1)
649 m_expandx[i] |= 3;
650 if (i & 2)
651 m_expandx[i] |= 0xc;
652 if (i & 4)
653 m_expandx[i] |= 0x30;
654 if (i & 8)
655 m_expandx[i] |= 0xc0;
656 if (i & 0x10)
657 m_expandx[i] |= 0x300;
658 if (i & 0x20)
659 m_expandx[i] |= 0xc00;
660 if (i & 0x40)
661 m_expandx[i] |= 0x3000;
662 if (i & 0x80)
663 m_expandx[i] |= 0xc000;
664 }
665
666 for (int i = 0; i < 256; i++)
667 {
668 m_expandx_multi[i] = 0;
669 if (i & 1)
670 m_expandx_multi[i] |= 5;
671 if (i & 2)
672 m_expandx_multi[i] |= 0xa;
673 if (i & 4)
674 m_expandx_multi[i] |= 0x50;
675 if (i & 8)
676 m_expandx_multi[i] |= 0xa0;
677 if (i & 0x10)
678 m_expandx_multi[i] |= 0x500;
679 if (i & 0x20)
680 m_expandx_multi[i] |= 0xa00;
681 if (i & 0x40)
682 m_expandx_multi[i] |= 0x5000;
683 if (i & 0x80)
684 m_expandx_multi[i] |= 0xa000;
685 }
686
687 // state saving
688 save_item(NAME(m_reg));
689
690 save_item(NAME(m_on));
691
692 //save_item(NAME(m_bitmap));
693
694 save_item(NAME(m_chargenaddr));
695 save_item(NAME(m_videoaddr));
696 save_item(NAME(m_bitmapaddr));
697
698 save_item(NAME(m_colors));
699 save_item(NAME(m_spritemulti));
700
701 save_item(NAME(m_rasterline));
702 save_item(NAME(m_cycle));
703 save_item(NAME(m_raster_x));
704 save_item(NAME(m_graphic_x));
705 save_item(NAME(m_last_data));
706
707 save_item(NAME(m_dy_start));
708 save_item(NAME(m_dy_stop));
709
710 save_item(NAME(m_draw_this_line));
711 save_item(NAME(m_is_bad_line));
712 save_item(NAME(m_bad_lines_enabled));
713 save_item(NAME(m_display_state));
714 save_item(NAME(m_char_data));
715 save_item(NAME(m_gfx_data));
716 save_item(NAME(m_color_data));
717 save_item(NAME(m_last_char_data));
718 save_item(NAME(m_matrix_line));
719 save_item(NAME(m_color_line));
720 save_item(NAME(m_vblanking));
721 save_item(NAME(m_ml_index));
722 save_item(NAME(m_rc));
723 save_item(NAME(m_vc));
724 save_item(NAME(m_vc_base));
725 save_item(NAME(m_ref_cnt));
726
727 save_item(NAME(m_spr_coll_buf));
728 save_item(NAME(m_fore_coll_buf));
729 save_item(NAME(m_spr_exp_y));
730 save_item(NAME(m_spr_dma_on));
731 save_item(NAME(m_spr_draw));
732 save_item(NAME(m_spr_disp_on));
733 save_item(NAME(m_spr_ptr));
734 save_item(NAME(m_mc_base));
735 save_item(NAME(m_mc));
736
737 for (int i = 0; i < 8; i++)
738 {
739 save_item(NAME(m_spr_data[i]), i);
740 save_item(NAME(m_spr_draw_data[i]), i);
741 }
742
743 save_item(NAME(m_border_on));
744 save_item(NAME(m_ud_border_on));
745 save_item(NAME(m_border_on_sample));
746 save_item(NAME(m_border_color_sample));
747
748 save_item(NAME(m_first_ba_cycle));
749 save_item(NAME(m_device_suspended));
750 }
751
752
753 //-------------------------------------------------
754 // device_reset - device-specific reset
755 //-------------------------------------------------
756
device_reset()757 void mos6566_device::device_reset()
758 {
759 memset(m_reg, 0, sizeof(m_reg));
760
761 for (auto & elem : m_mc)
762 elem = 63;
763
764 // from 0 to 311 (0 first, PAL) or from 0 to 261 (? first, NTSC 6567R56A) or from 0 to 262 (? first, NTSC 6567R8)
765 m_rasterline = 0; // VIC2_LINES - 1;
766
767 m_cycle = 14;
768 m_raster_x = 0x004;
769 m_graphic_x = 0;
770 m_last_data = 0;
771
772 m_on = 1;
773
774 m_chargenaddr = m_videoaddr = m_bitmapaddr = 0;
775
776 m_dy_start = ROW24_YSTART;
777 m_dy_stop = ROW24_YSTOP;
778
779 m_draw_this_line = 0;
780 m_is_bad_line = 0;
781 m_bad_lines_enabled = 0;
782 m_display_state = 0;
783 m_char_data = 0;
784 m_gfx_data = 0;
785 m_color_data = 0;
786 m_last_char_data = 0;
787 m_vblanking = 0;
788 m_ml_index = 0;
789 m_rc = 0;
790 m_vc = 0;
791 m_vc_base = 0;
792 m_ref_cnt = 0;
793
794 m_spr_exp_y = 0;
795 m_spr_dma_on = 0;
796 m_spr_draw = 0;
797 m_spr_disp_on = 0;
798
799
800 m_border_on = 0;
801 m_ud_border_on = 0;
802
803 m_first_ba_cycle = 0;
804 m_device_suspended = 0;
805
806 memset(m_matrix_line, 0, sizeof(m_matrix_line));
807 memset(m_color_line, 0, sizeof(m_color_line));
808
809 memset(m_spr_coll_buf, 0, sizeof(m_spr_coll_buf));
810 memset(m_fore_coll_buf, 0, sizeof(m_fore_coll_buf));
811 memset(m_border_on_sample, 0, sizeof(m_border_on_sample));
812 memset(m_border_color_sample, 0, sizeof(m_border_color_sample));
813
814 for (int i = 0; i < 8; i++)
815 {
816 m_spr_ptr[i] = 0;
817 m_mc_base[i] = 0;
818 m_mc[i] = 0;
819
820 for (int j = 0; j < 4; j++)
821 {
822 m_spr_draw_data[i][j] = 0;
823 m_spr_data[i][j] = 0;
824 }
825 }
826
827 for (int i = 0; i < 4; i++)
828 {
829 m_colors[i] = 0;
830 m_spritemulti[i] = 0;
831 }
832
833 m_phi0 = 1;
834 m_ba = CLEAR_LINE;
835 m_aec = CLEAR_LINE;
836 m_aec_delay = 0xff;
837 m_rdy_cycles = 0;
838
839 set_ba(ASSERT_LINE);
840 set_aec(ASSERT_LINE);
841 }
842
843
844 //-------------------------------------------------
845 // execute_run -
846 //-------------------------------------------------
847
execute_run()848 void mos6566_device::execute_run()
849 {
850 do
851 {
852 uint8_t cpu_cycles = m_cpu->total_cycles() & 0xff;
853 uint8_t vic_cycles = total_cycles() & 0xff;
854
855 m_phi0 = 0;
856
857 m_aec_delay <<= 1;
858 m_aec_delay |= m_ba;
859
860 set_aec(CLEAR_LINE);
861
862 int i;
863 uint8_t mask;
864
865 if (m_rasterline == VIC2_FIRST_DMA_LINE)
866 m_bad_lines_enabled = SCREENON;
867
868 m_is_bad_line = ((m_rasterline >= VIC2_FIRST_DMA_LINE) && (m_rasterline <= VIC2_LAST_DMA_LINE) &&
869 ((m_rasterline & 0x07) == YSCROLL) && m_bad_lines_enabled);
870
871 switch (m_cycle)
872 {
873 // Sprite 3, raster counter, raster IRQ, bad line
874 case 1:
875 if (m_rasterline == (VIC2_LINES - 1))
876 {
877 m_vblanking = 1;
878 }
879 else
880 {
881 m_rasterline++;
882
883 m_draw_this_line = ((VIC2_RASTER_2_EMU(m_rasterline) >= VIC2_RASTER_2_EMU(VIC2_FIRST_DISP_LINE)) &&
884 (VIC2_RASTER_2_EMU(m_rasterline ) <= VIC2_RASTER_2_EMU(VIC2_LAST_DISP_LINE)));
885 }
886
887 m_border_on_sample[0] = m_border_on;
888 spr_ptr_access(3);
889 spr_data_access(3, 0);
890 display_if_bad_line();
891
892 m_cycle++;
893 break;
894
895 // Sprite 3
896 case 2:
897 if (m_vblanking)
898 {
899 // Vertical blank, reset counters
900 m_rasterline = m_vc_base = 0;
901 m_ref_cnt = 0xff;
902 m_vblanking = 0;
903
904 // Trigger raster IRQ if IRQ in line 0
905 if (RASTERLINE == 0)
906 {
907 set_interrupt(IRQ_RST);
908 }
909 }
910
911 if (m_rasterline == RASTERLINE)
912 {
913 set_interrupt(IRQ_RST);
914 }
915
916 m_graphic_x = VIC2_X_2_EMU(0);
917
918 spr_data_access(3, 1);
919 spr_data_access(3, 2);
920 display_if_bad_line();
921
922 spr_ba(5);
923
924 m_cycle++;
925 break;
926
927 // Sprite 4
928 case 3:
929 spr_ptr_access(4);
930 spr_data_access(4, 0);
931 display_if_bad_line();
932
933 m_cycle++;
934 break;
935
936 // Sprite 4
937 case 4:
938 spr_data_access(4, 1);
939 spr_data_access(4, 2);
940 display_if_bad_line();
941
942 spr_ba(6);
943
944 m_cycle++;
945 break;
946
947 // Sprite 5
948 case 5:
949 spr_ptr_access(5);
950 spr_data_access(5, 0);
951 display_if_bad_line();
952
953 m_cycle++;
954 break;
955
956 // Sprite 5
957 case 6:
958 spr_data_access(5, 1);
959 spr_data_access(5, 2);
960 display_if_bad_line();
961
962 spr_ba(7);
963
964 m_cycle++;
965 break;
966
967 // Sprite 6
968 case 7:
969 spr_ptr_access(6);
970 spr_data_access(6, 0);
971 display_if_bad_line();
972
973 m_cycle++;
974 break;
975
976 // Sprite 6
977 case 8:
978 spr_data_access(6, 1);
979 spr_data_access(6, 2);
980 display_if_bad_line();
981
982 m_cycle++;
983 break;
984
985 // Sprite 7
986 case 9:
987 spr_ptr_access(7);
988 spr_data_access(7, 0);
989 display_if_bad_line();
990
991 m_cycle++;
992 break;
993
994 // Sprite 7
995 case 10:
996 spr_data_access(7, 1);
997 spr_data_access(7, 2);
998 display_if_bad_line();
999
1000 set_ba(ASSERT_LINE);
1001
1002 m_cycle++;
1003 break;
1004
1005 // Refresh
1006 case 11:
1007 refresh_access();
1008 display_if_bad_line();
1009
1010 m_cycle++;
1011 break;
1012
1013 // Refresh, fetch if bad line
1014 case 12:
1015 bad_line_ba();
1016
1017 refresh_access();
1018 fetch_if_bad_line();
1019
1020 m_cycle++;
1021 break;
1022
1023 // Refresh, fetch if bad line, raster_x
1024 case 13:
1025 bad_line_ba();
1026
1027 draw_background();
1028 sample_border();
1029 refresh_access();
1030 fetch_if_bad_line();
1031
1032 m_cycle++;
1033 break;
1034
1035 // Refresh, fetch if bad line, RC, VC
1036 case 14:
1037 bad_line_ba();
1038
1039 draw_background();
1040 sample_border();
1041 refresh_access();
1042 rc_if_bad_line();
1043
1044 m_vc = m_vc_base;
1045
1046 m_cycle++;
1047 break;
1048
1049 // Refresh, fetch if bad line, sprite y expansion
1050 case 15:
1051 bad_line_ba();
1052
1053 draw_background();
1054 sample_border();
1055 refresh_access();
1056 fetch_if_bad_line();
1057
1058 for (i = 0; i < 8; i++)
1059 if (m_spr_exp_y & (1 << i))
1060 m_mc_base[i] += 2;
1061
1062 m_ml_index = 0;
1063 matrix_access();
1064
1065 m_cycle++;
1066 break;
1067
1068 // Graphics, sprite y expansion, sprite DMA
1069 case 16:
1070 bad_line_ba();
1071
1072 draw_background();
1073 sample_border();
1074 graphics_access();
1075 fetch_if_bad_line();
1076
1077 mask = 1;
1078 for (i = 0; i < 8; i++, mask <<= 1)
1079 {
1080 if (m_spr_exp_y & mask)
1081 m_mc_base[i]++;
1082 if ((m_mc_base[i] & 0x3f) == 0x3f)
1083 m_spr_dma_on &= ~mask;
1084 }
1085
1086 matrix_access();
1087
1088 m_cycle++;
1089 break;
1090
1091 // Graphics, check border
1092 case 17:
1093 bad_line_ba();
1094
1095 if (COLUMNS40)
1096 {
1097 if (m_rasterline == m_dy_stop)
1098 m_ud_border_on = 1;
1099 else
1100 {
1101 if (SCREENON)
1102 {
1103 if (m_rasterline == m_dy_start)
1104 m_border_on = m_ud_border_on = 0;
1105 else
1106 if (m_ud_border_on == 0)
1107 m_border_on = 0;
1108 }
1109 else
1110 if (m_ud_border_on == 0)
1111 m_border_on = 0;
1112 }
1113 }
1114
1115 // Second sample of border state
1116 m_border_on_sample[1] = m_border_on;
1117
1118 draw_background();
1119 draw_graphics();
1120 sample_border();
1121 graphics_access();
1122 fetch_if_bad_line();
1123 matrix_access();
1124
1125 m_cycle++;
1126 break;
1127
1128 // Check border
1129 case 18:
1130 bad_line_ba();
1131
1132 if (!COLUMNS40)
1133 {
1134 if (m_rasterline == m_dy_stop)
1135 m_ud_border_on = 1;
1136 else
1137 {
1138 if (SCREENON)
1139 {
1140 if (m_rasterline == m_dy_start)
1141 m_border_on = m_ud_border_on = 0;
1142 else
1143 if (m_ud_border_on == 0)
1144 m_border_on = 0;
1145 }
1146 else
1147 if (m_ud_border_on == 0)
1148 m_border_on = 0;
1149 }
1150 }
1151
1152 // Third sample of border state
1153 m_border_on_sample[2] = m_border_on;
1154
1155 // Graphics
1156
1157 case 19:
1158 case 20:
1159 case 21:
1160 case 22:
1161 case 23:
1162 case 24:
1163 case 25:
1164 case 26:
1165 case 27:
1166 case 28:
1167 case 29:
1168 case 30:
1169 case 31:
1170 case 32:
1171 case 33:
1172 case 34:
1173 case 35:
1174 case 36:
1175 case 37:
1176 case 38:
1177 case 39:
1178 case 40:
1179 case 41:
1180 case 42:
1181 case 43:
1182 case 44:
1183 case 45:
1184 case 46:
1185 case 47:
1186 case 48:
1187 case 49:
1188 case 50:
1189 case 51:
1190 case 52:
1191 case 53:
1192 case 54:
1193 draw_graphics();
1194 sample_border();
1195 graphics_access();
1196 fetch_if_bad_line();
1197 matrix_access();
1198 m_last_char_data = m_char_data;
1199
1200 m_cycle++;
1201 break;
1202
1203 // Graphics, sprite y expansion, sprite DMA
1204 case 55:
1205 if (m_is_bad_line)
1206 set_ba(ASSERT_LINE);
1207
1208 draw_graphics();
1209 sample_border();
1210 graphics_access();
1211 display_if_bad_line();
1212
1213 // sprite y expansion
1214 mask = 1;
1215 for (i = 0; i < 8; i++, mask <<= 1)
1216 if (SPRITE_Y_EXPAND (i))
1217 m_spr_exp_y ^= mask;
1218
1219 check_sprite_dma();
1220
1221 m_cycle++;
1222 break;
1223
1224 // Check border, sprite DMA
1225 case 56:
1226 if (!COLUMNS40)
1227 m_border_on = 1;
1228
1229 // Fourth sample of border state
1230 m_border_on_sample[3] = m_border_on;
1231
1232 draw_graphics();
1233 sample_border();
1234 idle_access();
1235 display_if_bad_line();
1236 check_sprite_dma();
1237
1238 m_cycle++;
1239 break;
1240
1241 // Check border, sprites
1242 case 57:
1243 if (COLUMNS40)
1244 m_border_on = 1;
1245
1246 // Fifth sample of border state
1247 m_border_on_sample[4] = m_border_on;
1248
1249 // Sample spr_disp_on and spr_data for sprite drawing
1250 m_spr_draw = m_spr_disp_on;
1251 if (m_spr_draw)
1252 memcpy(m_spr_draw_data, m_spr_data, 8 * 4);
1253
1254 mask = 1;
1255 for (i = 0; i < 8; i++, mask <<= 1)
1256 if ((m_spr_disp_on & mask) && !(m_spr_dma_on & mask))
1257 m_spr_disp_on &= ~mask;
1258
1259 draw_background();
1260 sample_border();
1261 idle_access();
1262 display_if_bad_line();
1263
1264 spr_ba(0);
1265
1266 m_cycle++;
1267 break;
1268
1269 // for NTSC 6567R8
1270 case 58:
1271 draw_background();
1272 sample_border();
1273 idle_access();
1274 display_if_bad_line();
1275
1276 m_cycle++;
1277 break;
1278
1279 // for NTSC 6567R8
1280 case 59:
1281 draw_background();
1282 sample_border();
1283 idle_access();
1284 display_if_bad_line();
1285
1286 spr_ba(1);
1287
1288 m_cycle++;
1289 break;
1290
1291 // Sprite 0, sprite DMA, MC, RC
1292 case 60:
1293 draw_background();
1294 sample_border();
1295
1296 mask = 1;
1297 for (i = 0; i < 8; i++, mask <<= 1)
1298 {
1299 m_mc[i] = m_mc_base[i];
1300 if ((m_spr_dma_on & mask) && ((m_rasterline & 0xff) == SPRITE_Y_POS(i)))
1301 m_spr_disp_on |= mask;
1302 }
1303
1304 spr_ptr_access(0);
1305 spr_data_access(0, 0);
1306
1307 if (m_rc == 7)
1308 {
1309 m_vc_base = m_vc;
1310 m_display_state = 0;
1311 }
1312
1313 if (m_is_bad_line || m_display_state)
1314 {
1315 m_display_state = 1;
1316 m_rc = (m_rc + 1) & 7;
1317 }
1318
1319 m_cycle++;
1320 break;
1321
1322 // Sprite 0
1323 case 61:
1324 draw_background();
1325 sample_border();
1326 spr_data_access(0, 1);
1327 spr_data_access(0, 2);
1328 display_if_bad_line();
1329
1330 spr_ba(2);
1331
1332 m_cycle++;
1333 break;
1334
1335 // Sprite 1, draw
1336 case 62:
1337 draw_background();
1338 sample_border();
1339
1340 if (m_draw_this_line)
1341 {
1342 draw_sprites();
1343
1344 if (m_border_on_sample[0])
1345 for (i = 0; i < 4; i++)
1346 m_bitmap.plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[i]]);
1347
1348 if (m_border_on_sample[1])
1349 m_bitmap.plot_box(VIC2_X_2_EMU(4 * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[4]]);
1350
1351 if (m_border_on_sample[2])
1352 for (i = 5; i < 43; i++)
1353 m_bitmap.plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[i]]);
1354
1355 if (m_border_on_sample[3])
1356 m_bitmap.plot_box(VIC2_X_2_EMU(43 * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[43]]);
1357
1358 if (m_border_on_sample[4])
1359 {
1360 for (i = 44; i < 48; i++)
1361 m_bitmap.plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[i]]);
1362 for (i = 48; i < 53; i++)
1363 m_bitmap.plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[47]]);
1364 }
1365 }
1366
1367 spr_ptr_access(1);
1368 spr_data_access(1, 0);
1369 display_if_bad_line();
1370
1371 m_cycle++;
1372 break;
1373
1374 // Sprite 1
1375 case 63:
1376 spr_data_access(1, 1);
1377 spr_data_access(1, 2);
1378 display_if_bad_line();
1379
1380 spr_ba(3);
1381
1382 m_cycle++;
1383 break;
1384
1385 // Sprite 2
1386 case 64:
1387 spr_ptr_access(2);
1388 spr_data_access(2, 0);
1389 display_if_bad_line();
1390
1391 m_cycle++;
1392 break;
1393
1394 // Sprite 2
1395 case 65:
1396 spr_data_access(2, 1);
1397 spr_data_access(2, 2);
1398 display_if_bad_line();
1399
1400 if (m_rasterline == m_dy_stop)
1401 m_ud_border_on = 1;
1402 else
1403 if (SCREENON && (m_rasterline == m_dy_start))
1404 m_ud_border_on = 0;
1405
1406 spr_ba(4);
1407
1408 // Last cycle
1409 m_cycle = 1;
1410 }
1411
1412 m_phi0 = 1;
1413 set_aec(BIT(m_aec_delay, 2));
1414
1415 m_write_ba(m_ba);
1416 m_write_aec(m_aec);
1417
1418 m_raster_x += 8;
1419 if (m_raster_x == 0x1fc) m_raster_x = 0x004;
1420
1421 if ((cpu_cycles == vic_cycles) && (m_rdy_cycles > 0))
1422 {
1423 m_cpu->spin_until_time(m_cpu->cycles_to_attotime(m_rdy_cycles));
1424 m_rdy_cycles = 0;
1425 }
1426
1427 m_icount--;
1428 } while (m_icount > 0);
1429 }
1430
1431
1432 //-------------------------------------------------
1433 // execute_run -
1434 //-------------------------------------------------
1435
execute_run()1436 void mos6569_device::execute_run()
1437 {
1438 do
1439 {
1440 uint8_t cpu_cycles = m_cpu->total_cycles() & 0xff;
1441 uint8_t vic_cycles = total_cycles() & 0xff;
1442
1443 m_phi0 = 0;
1444
1445 m_aec_delay <<= 1;
1446 m_aec_delay |= m_ba;
1447
1448 set_aec(CLEAR_LINE);
1449
1450 int i;
1451 uint8_t mask;
1452
1453 if ((m_rasterline == VIC2_FIRST_DMA_LINE) && !m_bad_lines_enabled)
1454 m_bad_lines_enabled = SCREENON;
1455
1456 m_is_bad_line = ((m_rasterline >= VIC2_FIRST_DMA_LINE) && (m_rasterline <= VIC2_LAST_DMA_LINE) &&
1457 ((m_rasterline & 0x07) == YSCROLL) && m_bad_lines_enabled);
1458
1459 switch (m_cycle)
1460 {
1461 // Sprite 3, raster counter, raster IRQ, bad line
1462 case 1:
1463 if (m_rasterline == (VIC2_LINES - 1))
1464 {
1465 m_vblanking = 1;
1466 }
1467 else
1468 {
1469 m_rasterline++;
1470
1471 m_draw_this_line = ((VIC2_RASTER_2_EMU(m_rasterline) >= VIC2_RASTER_2_EMU(VIC2_FIRST_DISP_LINE)) &&
1472 (VIC2_RASTER_2_EMU(m_rasterline ) <= VIC2_RASTER_2_EMU(VIC2_LAST_DISP_LINE)));
1473 }
1474
1475 m_border_on_sample[0] = m_border_on;
1476 spr_ptr_access(3);
1477 spr_data_access(3, 0);
1478 display_if_bad_line();
1479
1480 m_cycle++;
1481 break;
1482
1483 // Sprite 3
1484 case 2:
1485 spr_ba(5);
1486
1487 if (m_vblanking)
1488 {
1489 // Vertical blank, reset counters
1490 m_rasterline = m_vc_base = 0;
1491 m_ref_cnt = 0xff;
1492 m_vblanking = 0;
1493
1494 // Trigger raster IRQ if IRQ in line 0
1495 if (RASTERLINE == 0)
1496 {
1497 set_interrupt(IRQ_RST);
1498 }
1499 }
1500
1501 if (m_rasterline == RASTERLINE)
1502 {
1503 set_interrupt(IRQ_RST);
1504 }
1505
1506 m_graphic_x = VIC2_X_2_EMU(0);
1507
1508 spr_data_access(3, 1);
1509 spr_data_access(3, 2);
1510 display_if_bad_line();
1511
1512 m_cycle++;
1513 break;
1514
1515 // Sprite 4
1516 case 3:
1517 spr_ptr_access(4);
1518 spr_data_access(4, 0);
1519 display_if_bad_line();
1520
1521 m_cycle++;
1522 break;
1523
1524 // Sprite 4
1525 case 4:
1526 spr_ba(6);
1527
1528 spr_data_access(4, 1);
1529 spr_data_access(4, 2);
1530 display_if_bad_line();
1531
1532 m_cycle++;
1533 break;
1534
1535 // Sprite 5
1536 case 5:
1537 spr_ptr_access(5);
1538 spr_data_access(5, 0);
1539 display_if_bad_line();
1540
1541 m_cycle++;
1542 break;
1543
1544 // Sprite 5
1545 case 6:
1546 spr_ba(7);
1547
1548 spr_data_access(5, 1);
1549 spr_data_access(5, 2);
1550 display_if_bad_line();
1551
1552 m_cycle++;
1553 break;
1554
1555 // Sprite 6
1556 case 7:
1557 spr_ptr_access(6);
1558 spr_data_access(6, 0);
1559 display_if_bad_line();
1560
1561 m_cycle++;
1562 break;
1563
1564 // Sprite 6
1565 case 8:
1566 spr_data_access(6, 1);
1567 spr_data_access(6, 2);
1568 display_if_bad_line();
1569
1570 m_cycle++;
1571 break;
1572
1573 // Sprite 7
1574 case 9:
1575 spr_ptr_access(7);
1576 spr_data_access(7, 0);
1577 display_if_bad_line();
1578
1579 m_cycle++;
1580 break;
1581
1582 // Sprite 7
1583 case 10:
1584 spr_data_access(7, 1);
1585 spr_data_access(7, 2);
1586 display_if_bad_line();
1587
1588 set_ba(ASSERT_LINE);
1589
1590 m_cycle++;
1591 break;
1592
1593 // Refresh
1594 case 11:
1595 refresh_access();
1596 display_if_bad_line();
1597
1598 m_cycle++;
1599 break;
1600
1601 // Refresh, fetch if bad line
1602 case 12:
1603 bad_line_ba();
1604
1605 refresh_access();
1606 fetch_if_bad_line();
1607
1608 m_cycle++;
1609 break;
1610
1611 // Refresh, fetch if bad line, raster_x
1612 case 13:
1613 bad_line_ba();
1614
1615 draw_background();
1616 sample_border();
1617 refresh_access();
1618 fetch_if_bad_line();
1619
1620 m_cycle++;
1621 break;
1622
1623 // Refresh, fetch if bad line, RC, VC
1624 case 14:
1625 bad_line_ba();
1626
1627 draw_background();
1628 sample_border();
1629 refresh_access();
1630 rc_if_bad_line();
1631
1632 m_vc = m_vc_base;
1633
1634 m_cycle++;
1635 break;
1636
1637 // Refresh, fetch if bad line, sprite y expansion
1638 case 15:
1639 bad_line_ba();
1640
1641 draw_background();
1642 sample_border();
1643 refresh_access();
1644 fetch_if_bad_line();
1645
1646 for (i = 0; i < 8; i++)
1647 if (m_spr_exp_y & (1 << i))
1648 m_mc_base[i] += 2;
1649
1650 m_ml_index = 0;
1651
1652 matrix_access();
1653
1654 m_cycle++;
1655 break;
1656
1657 // Graphics, sprite y expansion, sprite DMA
1658 case 16:
1659 bad_line_ba();
1660
1661 draw_background();
1662 sample_border();
1663 graphics_access();
1664 fetch_if_bad_line();
1665
1666 mask = 1;
1667 for (i = 0; i < 8; i++, mask <<= 1)
1668 {
1669 if (m_spr_exp_y & (1 << i))
1670 m_mc_base[i]++;
1671 if ((m_mc_base[i] & 0x3f) == 0x3f)
1672 m_spr_dma_on &= ~mask;
1673 }
1674
1675 matrix_access();
1676
1677 m_cycle++;
1678 break;
1679
1680 // Graphics, check border
1681 case 17:
1682 bad_line_ba();
1683
1684 if (COLUMNS40)
1685 {
1686 if (m_rasterline == m_dy_stop)
1687 m_ud_border_on = 1;
1688 else
1689 {
1690 if (SCREENON)
1691 {
1692 if (m_rasterline == m_dy_start)
1693 m_border_on = m_ud_border_on = 0;
1694 else
1695 if (m_ud_border_on == 0)
1696 m_border_on = 0;
1697 } else
1698 if (m_ud_border_on == 0)
1699 m_border_on = 0;
1700 }
1701 }
1702
1703 // Second sample of border state
1704 m_border_on_sample[1] = m_border_on;
1705
1706 draw_background();
1707 draw_graphics();
1708 sample_border();
1709 graphics_access();
1710 fetch_if_bad_line();
1711 matrix_access();
1712
1713 m_cycle++;
1714 break;
1715
1716 // Check border
1717 case 18:
1718 bad_line_ba();
1719
1720 if (!COLUMNS40)
1721 {
1722 if (m_rasterline == m_dy_stop)
1723 m_ud_border_on = 1;
1724 else
1725 {
1726 if (SCREENON)
1727 {
1728 if (m_rasterline == m_dy_start)
1729 m_border_on = m_ud_border_on = 0;
1730 else
1731 if (m_ud_border_on == 0)
1732 m_border_on = 0;
1733 } else
1734 if (m_ud_border_on == 0)
1735 m_border_on = 0;
1736 }
1737 }
1738
1739 // Third sample of border state
1740 m_border_on_sample[2] = m_border_on;
1741
1742 // Graphics
1743
1744 case 19:
1745 case 20:
1746 case 21:
1747 case 22:
1748 case 23:
1749 case 24:
1750 case 25:
1751 case 26:
1752 case 27:
1753 case 28:
1754 case 29:
1755 case 30:
1756 case 31:
1757 case 32:
1758 case 33:
1759 case 34:
1760 case 35:
1761 case 36:
1762 case 37:
1763 case 38:
1764 case 39:
1765 case 40:
1766 case 41:
1767 case 42:
1768 case 43:
1769 case 44:
1770 case 45:
1771 case 46:
1772 case 47:
1773 case 48:
1774 case 49:
1775 case 50:
1776 case 51:
1777 case 52:
1778 case 53:
1779 case 54:
1780 bad_line_ba();
1781
1782 draw_graphics();
1783 sample_border();
1784 graphics_access();
1785 fetch_if_bad_line();
1786 matrix_access();
1787 m_last_char_data = m_char_data;
1788
1789 m_cycle++;
1790 break;
1791
1792 // Graphics, sprite y expansion, sprite DMA
1793 case 55:
1794 if (m_is_bad_line)
1795 set_ba(ASSERT_LINE);
1796
1797 draw_graphics();
1798 sample_border();
1799 graphics_access();
1800 display_if_bad_line();
1801
1802 // sprite y expansion
1803 mask = 1;
1804 for (i = 0; i < 8; i++, mask <<= 1)
1805 if (SPRITE_Y_EXPAND (i))
1806 m_spr_exp_y ^= mask;
1807
1808 check_sprite_dma();
1809
1810 spr_ba(0);
1811
1812 m_cycle++;
1813 break;
1814
1815 // Check border, sprite DMA
1816 case 56:
1817 if (!COLUMNS40)
1818 m_border_on = 1;
1819
1820 // Fourth sample of border state
1821 m_border_on_sample[3] = m_border_on;
1822
1823 draw_graphics();
1824 sample_border();
1825 idle_access();
1826 display_if_bad_line();
1827 check_sprite_dma();
1828
1829 m_cycle++;
1830 break;
1831
1832 // Check border, sprites
1833 case 57:
1834 spr_ba(1);
1835
1836 if (COLUMNS40)
1837 m_border_on = 1;
1838
1839 // Fifth sample of border state
1840 m_border_on_sample[4] = m_border_on;
1841
1842 // Sample spr_disp_on and spr_data for sprite drawing
1843 m_spr_draw = m_spr_disp_on;
1844 if (m_spr_draw)
1845 memcpy(m_spr_draw_data, m_spr_data, 8 * 4);
1846
1847 mask = 1;
1848 for (i = 0; i < 8; i++, mask <<= 1)
1849 if ((m_spr_disp_on & mask) && !(m_spr_dma_on & mask))
1850 m_spr_disp_on &= ~mask;
1851
1852 draw_background();
1853 sample_border();
1854 idle_access();
1855 display_if_bad_line();
1856
1857 m_cycle++;
1858 break;
1859
1860 // Sprite 0, sprite DMA, MC, RC
1861 case 58:
1862 draw_background();
1863 sample_border();
1864
1865 mask = 1;
1866 for (i = 0; i < 8; i++, mask <<= 1)
1867 {
1868 m_mc[i] = m_mc_base[i];
1869 if ((m_spr_dma_on & mask) && ((m_rasterline & 0xff) == SPRITE_Y_POS(i)))
1870 m_spr_disp_on |= mask;
1871 }
1872
1873 spr_ptr_access(0);
1874 spr_data_access(0, 0);
1875
1876 if (m_rc == 7)
1877 {
1878 m_vc_base = m_vc;
1879 m_display_state = 0;
1880 }
1881
1882 if (m_is_bad_line || m_display_state)
1883 {
1884 m_display_state = 1;
1885 m_rc = (m_rc + 1) & 7;
1886 }
1887
1888 m_cycle++;
1889 break;
1890
1891 // Sprite 0
1892 case 59:
1893 spr_ba(2);
1894
1895 draw_background();
1896 sample_border();
1897 spr_data_access(0, 1);
1898 spr_data_access(0, 2);
1899 display_if_bad_line();
1900
1901 m_cycle++;
1902 break;
1903
1904 // Sprite 1, draw
1905 case 60:
1906 draw_background();
1907 sample_border();
1908
1909 if (m_draw_this_line)
1910 {
1911 draw_sprites();
1912
1913 if (m_border_on_sample[0])
1914 for (i = 0; i < 4; i++)
1915 m_bitmap.plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[i]]);
1916
1917 if (m_border_on_sample[1])
1918 m_bitmap.plot_box(VIC2_X_2_EMU(4 * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[4]]);
1919
1920 if (m_border_on_sample[2])
1921 for (i = 5; i < 43; i++)
1922 m_bitmap.plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[i]]);
1923
1924 if (m_border_on_sample[3])
1925 m_bitmap.plot_box(VIC2_X_2_EMU(43 * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[43]]);
1926
1927 if (m_border_on_sample[4])
1928 {
1929 for (i = 44; i < 48; i++)
1930 m_bitmap.plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[i]]);
1931 for (i = 48; i < 51; i++)
1932 m_bitmap.plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(m_rasterline), 8, 1, PALETTE_MOS[m_border_color_sample[47]]);
1933 }
1934 }
1935
1936 spr_ptr_access(1);
1937 spr_data_access(1, 0);
1938 display_if_bad_line();
1939
1940 m_cycle++;
1941 break;
1942
1943 // Sprite 1
1944 case 61:
1945 spr_ba(3);
1946
1947 spr_data_access(1, 1);
1948 spr_data_access(1, 2);
1949 display_if_bad_line();
1950
1951 m_cycle++;
1952 break;
1953
1954 // Sprite 2
1955 case 62:
1956 spr_ptr_access(2);
1957 spr_data_access(2, 0);
1958 display_if_bad_line();
1959
1960 m_cycle++;
1961 break;
1962
1963 // Sprite 2
1964 case 63:
1965 spr_ba(4);
1966
1967 spr_data_access(2, 1);
1968 spr_data_access(2, 2);
1969 display_if_bad_line();
1970
1971 if (m_rasterline == m_dy_stop)
1972 m_ud_border_on = 1;
1973 else
1974 if (SCREENON && (m_rasterline == m_dy_start))
1975 m_ud_border_on = 0;
1976
1977 // Last cycle
1978 m_cycle = 1;
1979 }
1980
1981 m_phi0 = 1;
1982 set_aec(BIT(m_aec_delay, 2));
1983
1984 m_write_ba(m_ba);
1985 m_write_aec(m_aec);
1986
1987 m_raster_x += 8;
1988 if (m_raster_x == 0x1fc) m_raster_x = 0x004;
1989
1990 if ((cpu_cycles == vic_cycles) && (m_rdy_cycles > 0))
1991 {
1992 m_cpu->spin_until_time(m_cpu->cycles_to_attotime(m_rdy_cycles));
1993 m_rdy_cycles = 0;
1994 }
1995
1996 m_icount--;
1997 } while (m_icount > 0);
1998 }
1999
2000 // Graphics display (8 pixels)
draw_graphics()2001 void mos6566_device::draw_graphics()
2002 {
2003 if (m_draw_this_line == 0)
2004 {
2005 uint16_t p = m_graphic_x + XSCROLL;
2006 m_fore_coll_buf[p + 7] = 0;
2007 m_fore_coll_buf[p + 6] = 0;
2008 m_fore_coll_buf[p + 5] = 0;
2009 m_fore_coll_buf[p + 4] = 0;
2010 m_fore_coll_buf[p + 3] = 0;
2011 m_fore_coll_buf[p + 2] = 0;
2012 m_fore_coll_buf[p + 1] = 0;
2013 m_fore_coll_buf[p + 0] = 0;
2014 }
2015 else if (m_ud_border_on)
2016 {
2017 uint16_t p = m_graphic_x + XSCROLL;
2018 m_fore_coll_buf[p + 7] = 0;
2019 m_fore_coll_buf[p + 6] = 0;
2020 m_fore_coll_buf[p + 5] = 0;
2021 m_fore_coll_buf[p + 4] = 0;
2022 m_fore_coll_buf[p + 3] = 0;
2023 m_fore_coll_buf[p + 2] = 0;
2024 m_fore_coll_buf[p + 1] = 0;
2025 m_fore_coll_buf[p + 0] = 0;
2026 draw_background();
2027 }
2028 else
2029 {
2030 uint8_t tmp_col;
2031 uint16_t p = m_graphic_x + XSCROLL;
2032 switch (GFXMODE)
2033 {
2034 case 0:
2035 draw_mono(p, m_colors[0], m_color_data & 0x0f);
2036 break;
2037 case 1:
2038 if (m_color_data & 0x08)
2039 draw_multi(p, m_colors[0], m_colors[1], m_colors[2], m_color_data & 0x07);
2040 else
2041 draw_mono(p, m_colors[0], m_color_data & 0x0f);
2042 break;
2043 case 2:
2044 draw_mono(p, m_char_data & 0x0f, m_char_data >> 4);
2045 break;
2046 case 3:
2047 draw_multi(p, m_colors[0], m_char_data >> 4, m_char_data & 0x0f, m_color_data & 0x0f);
2048 break;
2049 case 4:
2050 if (m_char_data & 0x80)
2051 if (m_char_data & 0x40)
2052 tmp_col = m_colors[3];
2053 else
2054 tmp_col = m_colors[2];
2055 else
2056 if (m_char_data & 0x40)
2057 tmp_col = m_colors[1];
2058 else
2059 tmp_col = m_colors[0];
2060 draw_mono(p, tmp_col, m_color_data & 0x0f);
2061 break;
2062 case 5:
2063 case 6:
2064 case 7:
2065 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 7) = PALETTE_MOS[0];
2066 m_fore_coll_buf[p + 7] = 0;
2067 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 6) = PALETTE_MOS[0];
2068 m_fore_coll_buf[p + 6] = 0;
2069 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 5) = PALETTE_MOS[0];
2070 m_fore_coll_buf[p + 5] = 0;
2071 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 4) = PALETTE_MOS[0];
2072 m_fore_coll_buf[p + 4] = 0;
2073 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 3) = PALETTE_MOS[0];
2074 m_fore_coll_buf[p + 3] = 0;
2075 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 2) = PALETTE_MOS[0];
2076 m_fore_coll_buf[p + 2] = 0;
2077 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 1) = PALETTE_MOS[0];
2078 m_fore_coll_buf[p + 1] = 0;
2079 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + 0) = PALETTE_MOS[0];
2080 m_fore_coll_buf[p + 0] = 0;
2081 break;
2082 }
2083 }
2084 }
2085
draw_sprites()2086 void mos6566_device::draw_sprites()
2087 {
2088 int i;
2089 uint8_t snum, sbit;
2090 uint8_t spr_coll = 0, gfx_coll = 0;
2091 uint32_t plane0_l, plane0_r, plane1_l, plane1_r;
2092 uint32_t sdata_l, sdata_r;
2093
2094 for (i = 0; i < 0x400; i++)
2095 m_spr_coll_buf[i] = 0;
2096
2097 for (snum = 0, sbit = 1; snum < 8; snum++, sbit <<= 1)
2098 {
2099 if ((m_spr_draw & sbit) && (SPRITE_X_POS(snum) <= (403 - (VIC2_FIRSTCOLUMN + 1))))
2100 {
2101 uint16_t p = SPRITE_X_POS(snum) + VIC2_X_2_EMU(0) + 8;
2102 uint8_t color = SPRITE_COLOR(snum);
2103 uint32_t sdata = (m_spr_draw_data[snum][0] << 24) | (m_spr_draw_data[snum][1] << 16) | (m_spr_draw_data[snum][2] << 8);
2104
2105 if (SPRITE_X_EXPAND(snum))
2106 {
2107 if (SPRITE_X_POS(snum) > (403 - 24 - (VIC2_FIRSTCOLUMN + 1)))
2108 continue;
2109
2110 if (SPRITE_MULTICOLOR(snum))
2111 {
2112 sdata_l = (m_expandx_multi[(sdata >> 24) & 0xff] << 16) | m_expandx_multi[(sdata >> 16) & 0xff];
2113 sdata_r = m_expandx_multi[(sdata >> 8) & 0xff] << 16;
2114 plane0_l = (sdata_l & 0x55555555) | (sdata_l & 0x55555555) << 1;
2115 plane1_l = (sdata_l & 0xaaaaaaaa) | (sdata_l & 0xaaaaaaaa) >> 1;
2116 plane0_r = (sdata_r & 0x55555555) | (sdata_r & 0x55555555) << 1;
2117 plane1_r = (sdata_r & 0xaaaaaaaa) | (sdata_r & 0xaaaaaaaa) >> 1;
2118 for (i = 0; i < 32; i++, plane0_l <<= 1, plane1_l <<= 1)
2119 {
2120 uint8_t col;
2121
2122 if (plane1_l & 0x80000000)
2123 {
2124 if (m_fore_coll_buf[p + i])
2125 {
2126 gfx_coll |= sbit;
2127 }
2128 if (plane0_l & 0x80000000)
2129 col = m_spritemulti[3];
2130 else
2131 col = color;
2132 }
2133 else
2134 {
2135 if (plane0_l & 0x80000000)
2136 {
2137 if (m_fore_coll_buf[p + i])
2138 {
2139 gfx_coll |= sbit;
2140 }
2141 col = m_spritemulti[1];
2142 }
2143 else
2144 continue;
2145 }
2146
2147 if (m_spr_coll_buf[p + i])
2148 spr_coll |= m_spr_coll_buf[p + i] | sbit;
2149 else
2150 {
2151 if (SPRITE_PRIORITY(snum))
2152 {
2153 if (m_fore_coll_buf[p + i] == 0)
2154 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[col];
2155 m_spr_coll_buf[p + i] = sbit;
2156 }
2157 else
2158 {
2159 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[col];
2160 m_spr_coll_buf[p + i] = sbit;
2161 }
2162 }
2163 }
2164
2165 for (; i < 48; i++, plane0_r <<= 1, plane1_r <<= 1)
2166 {
2167 uint8_t col;
2168
2169 if(plane1_r & 0x80000000)
2170 {
2171 if (m_fore_coll_buf[p + i])
2172 {
2173 gfx_coll |= sbit;
2174 }
2175
2176 if (plane0_r & 0x80000000)
2177 col = m_spritemulti[3];
2178 else
2179 col = color;
2180 }
2181 else
2182 {
2183 if (plane0_r & 0x80000000)
2184 {
2185 if (m_fore_coll_buf[p + i])
2186 {
2187 gfx_coll |= sbit;
2188 }
2189 col = m_spritemulti[1];
2190 }
2191 else
2192 continue;
2193 }
2194
2195 if (m_spr_coll_buf[p + i])
2196 spr_coll |= m_spr_coll_buf[p + i] | sbit;
2197 else
2198 {
2199 if (SPRITE_PRIORITY(snum))
2200 {
2201 if (m_fore_coll_buf[p + i] == 0)
2202 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[col];
2203 m_spr_coll_buf[p + i] = sbit;
2204 }
2205 else
2206 {
2207 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[col];
2208 m_spr_coll_buf[p + i] = sbit;
2209 }
2210 }
2211 }
2212 }
2213 else
2214 {
2215 sdata_l = (m_expandx[(sdata >> 24) & 0xff] << 16) | m_expandx[(sdata >> 16) & 0xff];
2216 sdata_r = m_expandx[(sdata >> 8) & 0xff] << 16;
2217
2218 for (i = 0; i < 32; i++, sdata_l <<= 1)
2219 if (sdata_l & 0x80000000)
2220 {
2221 if (m_fore_coll_buf[p + i])
2222 {
2223 gfx_coll |= sbit;
2224 }
2225
2226 if (m_spr_coll_buf[p + i])
2227 spr_coll |= m_spr_coll_buf[p + i] | sbit;
2228 else
2229 {
2230 if (SPRITE_PRIORITY(snum))
2231 {
2232 if (m_fore_coll_buf[p + i] == 0)
2233 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[color];
2234 m_spr_coll_buf[p + i] = sbit;
2235 }
2236 else
2237 {
2238 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[color];
2239 m_spr_coll_buf[p + i] = sbit;
2240 }
2241 }
2242 }
2243
2244 for (; i < 48; i++, sdata_r <<= 1)
2245 if (sdata_r & 0x80000000)
2246 {
2247 if (m_fore_coll_buf[p + i])
2248 {
2249 gfx_coll |= sbit;
2250 }
2251
2252 if (m_spr_coll_buf[p + i])
2253 spr_coll |= m_spr_coll_buf[p + i] | sbit;
2254 else
2255 {
2256 if (SPRITE_PRIORITY(snum))
2257 {
2258 if (m_fore_coll_buf[p + i] == 0)
2259 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[color];
2260 m_spr_coll_buf[p + i] = sbit;
2261 }
2262 else
2263 {
2264 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[color];
2265 m_spr_coll_buf[p + i] = sbit;
2266 }
2267 }
2268 }
2269 }
2270 }
2271 else
2272 {
2273 if (SPRITE_MULTICOLOR(snum))
2274 {
2275 uint32_t plane0 = (sdata & 0x55555555) | (sdata & 0x55555555) << 1;
2276 uint32_t plane1 = (sdata & 0xaaaaaaaa) | (sdata & 0xaaaaaaaa) >> 1;
2277
2278 for (i = 0; i < 24; i++, plane0 <<= 1, plane1 <<= 1)
2279 {
2280 uint8_t col;
2281
2282 if (plane1 & 0x80000000)
2283 {
2284 if (m_fore_coll_buf[p + i])
2285 {
2286 gfx_coll |= sbit;
2287 }
2288
2289 if (plane0 & 0x80000000)
2290 col = m_spritemulti[3];
2291 else
2292 col = color;
2293 }
2294 else
2295 {
2296 if (m_fore_coll_buf[p + i])
2297 {
2298 gfx_coll |= sbit;
2299 }
2300
2301 if (plane0 & 0x80000000)
2302 col = m_spritemulti[1];
2303 else
2304 continue;
2305 }
2306
2307 if (m_spr_coll_buf[p + i])
2308 spr_coll |= m_spr_coll_buf[p + i] | sbit;
2309 else
2310 {
2311 if (SPRITE_PRIORITY(snum))
2312 {
2313 if (m_fore_coll_buf[p + i] == 0)
2314 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[col];
2315 m_spr_coll_buf[p + i] = sbit;
2316 }
2317 else
2318 {
2319 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[col];
2320 m_spr_coll_buf[p + i] = sbit;
2321 }
2322 }
2323 }
2324 }
2325 else
2326 {
2327 for (i = 0; i < 24; i++, sdata <<= 1)
2328 {
2329 if (sdata & 0x80000000)
2330 {
2331 if (m_fore_coll_buf[p + i])
2332 {
2333 gfx_coll |= sbit;
2334 }
2335 if (m_spr_coll_buf[p + i])
2336 {
2337 spr_coll |= m_spr_coll_buf[p + i] | sbit;
2338 }
2339 else
2340 {
2341 if (SPRITE_PRIORITY(snum))
2342 {
2343 if (m_fore_coll_buf[p + i] == 0)
2344 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[color];
2345 m_spr_coll_buf[p + i] = sbit;
2346 }
2347 else
2348 {
2349 m_bitmap.pix(VIC2_RASTER_2_EMU(m_rasterline), p + i) = PALETTE_MOS[color];
2350 m_spr_coll_buf[p + i] = sbit;
2351 }
2352 }
2353 }
2354 }
2355 }
2356 }
2357 }
2358 }
2359
2360 if (SPRITE_COLL)
2361 SPRITE_COLL |= spr_coll;
2362 else
2363 {
2364 SPRITE_COLL = spr_coll;
2365 if (SPRITE_COLL)
2366 set_interrupt(IRQ_MMC);
2367 }
2368
2369 if (SPRITE_BG_COLL)
2370 SPRITE_BG_COLL |= gfx_coll;
2371 else
2372 {
2373 SPRITE_BG_COLL = gfx_coll;
2374 if (SPRITE_BG_COLL)
2375 set_interrupt(IRQ_MBC);
2376 }
2377 }
2378
2379
2380 //-------------------------------------------------
2381 // screen_update -
2382 //-------------------------------------------------
2383
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)2384 uint32_t mos6566_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
2385 {
2386 bitmap.fill(PALETTE_MOS[0], cliprect);
2387
2388 if (m_on)
2389 copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
2390
2391 return 0;
2392 }
2393
2394
2395 //-------------------------------------------------
2396 // read -
2397 //-------------------------------------------------
2398
read(offs_t offset)2399 uint8_t mos6566_device::read(offs_t offset)
2400 {
2401 uint8_t val = 0;
2402
2403 offset &= 0x3f;
2404
2405 switch (offset)
2406 {
2407 case 0x11:
2408 val = (m_reg[offset] & ~0x80) | ((m_rasterline & 0x100) >> 1);
2409 val |= UNUSED_BITS[offset];
2410 break;
2411
2412 case 0x12:
2413 val = m_rasterline & 0xff;
2414 val |= UNUSED_BITS[offset];
2415 break;
2416
2417 case 0x16:
2418 val = m_reg[offset] | 0xc0;
2419 val |= UNUSED_BITS[offset];
2420 break;
2421
2422 case 0x18:
2423 val = m_reg[offset] | 0x01;
2424 val |= UNUSED_BITS[offset];
2425 break;
2426
2427 case 0x19: /* interrupt flag register */
2428 /* clear_interrupt(0xf); */
2429 val = m_reg[offset] | 0x70;
2430 val |= UNUSED_BITS[offset];
2431 break;
2432
2433 case 0x1a:
2434 val = m_reg[offset] | 0xf0;
2435 val |= UNUSED_BITS[offset];
2436 break;
2437
2438 case 0x1e: /* sprite to sprite collision detect */
2439 val = m_reg[offset];
2440 m_reg[offset] = 0;
2441 clear_interrupt(4);
2442 val |= UNUSED_BITS[offset];
2443 break;
2444
2445 case 0x1f: /* sprite to background collision detect */
2446 val = m_reg[offset];
2447 m_reg[offset] = 0;
2448 clear_interrupt(2);
2449 val |= UNUSED_BITS[offset];
2450 break;
2451
2452 case 0x20:
2453 case 0x21:
2454 case 0x22:
2455 case 0x23:
2456 case 0x24:
2457 val = m_reg[offset];
2458 val |= UNUSED_BITS[offset];
2459 break;
2460
2461 case 0x00:
2462 case 0x01:
2463 case 0x02:
2464 case 0x03:
2465 case 0x04:
2466 case 0x05:
2467 case 0x06:
2468 case 0x07:
2469 case 0x08:
2470 case 0x09:
2471 case 0x0a:
2472 case 0x0b:
2473 case 0x0c:
2474 case 0x0d:
2475 case 0x0e:
2476 case 0x0f:
2477 case 0x10:
2478 case 0x17:
2479 case 0x1b:
2480 case 0x1c:
2481 case 0x1d:
2482 case 0x25:
2483 case 0x26:
2484 case 0x27:
2485 case 0x28:
2486 case 0x29:
2487 case 0x2a:
2488 case 0x2b:
2489 case 0x2c:
2490 case 0x2d:
2491 case 0x2e:
2492 val = m_reg[offset];
2493 val |= UNUSED_BITS[offset];
2494 break;
2495
2496 case REGISTER_KCR:
2497 case REGISTER_FAST:
2498 if (IS_VICIIE)
2499 {
2500 val = m_reg[offset];
2501 DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
2502 }
2503 else
2504 {
2505 val |= UNUSED_BITS[offset];
2506 }
2507 break;
2508
2509 case 0x31:
2510 case 0x32:
2511 case 0x33:
2512 case 0x34:
2513 case 0x35:
2514 case 0x36:
2515 case 0x37:
2516 case 0x38:
2517 case 0x39:
2518 case 0x3a:
2519 case 0x3b:
2520 case 0x3c:
2521 case 0x3d:
2522 case 0x3e:
2523 case 0x3f: /* not used */
2524 DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
2525 val |= UNUSED_BITS[offset];
2526 break;
2527
2528 default:
2529 val = m_reg[offset];
2530 val |= UNUSED_BITS[offset];
2531 }
2532
2533 if ((offset != 0x11) && (offset != 0x12))
2534 DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
2535
2536 return val;
2537 }
2538
2539
2540 //-------------------------------------------------
2541 // write -
2542 //-------------------------------------------------
2543
write(offs_t offset,uint8_t data)2544 void mos6566_device::write(offs_t offset, uint8_t data)
2545 {
2546 DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
2547 offset &= 0x3f;
2548
2549 switch (offset)
2550 {
2551 case 0x01:
2552 case 0x03:
2553 case 0x05:
2554 case 0x07:
2555 case 0x09:
2556 case 0x0b:
2557 case 0x0d:
2558 case 0x0f:
2559 m_reg[offset] = data; /* sprite y positions */
2560 break;
2561
2562 case 0x00:
2563 case 0x02:
2564 case 0x04:
2565 case 0x06:
2566 case 0x08:
2567 case 0x0a:
2568 case 0x0c:
2569 case 0x0e:
2570 m_reg[offset] = data; /* sprite x positions */
2571 break;
2572
2573 case 0x10:
2574 m_reg[offset] = data; /* sprite x positions */
2575 break;
2576
2577 case 0x17: /* sprite y size */
2578 m_spr_exp_y |= ~data;
2579 if (m_reg[offset] != data)
2580 {
2581 m_reg[offset] = data;
2582 }
2583 break;
2584
2585 case 0x1d: /* sprite x size */
2586 if (m_reg[offset] != data)
2587 {
2588 m_reg[offset] = data;
2589 }
2590 break;
2591
2592 case 0x1b: /* sprite background priority */
2593 if (m_reg[offset] != data)
2594 {
2595 m_reg[offset] = data;
2596 }
2597 break;
2598
2599 case 0x1c: /* sprite multicolor mode select */
2600 if (m_reg[offset] != data)
2601 {
2602 m_reg[offset] = data;
2603 }
2604 break;
2605
2606 case 0x27:
2607 case 0x28:
2608 case 0x29:
2609 case 0x2a:
2610 case 0x2b:
2611 case 0x2c:
2612 case 0x2d:
2613 case 0x2e:
2614 /* sprite colors */
2615 if (m_reg[offset] != data)
2616 {
2617 m_reg[offset] = data;
2618 }
2619 break;
2620
2621 case 0x25: /* sprite multicolor */
2622 if (m_reg[offset] != data)
2623 {
2624 m_reg[offset] = data;
2625 m_spritemulti[1] = SPRITE_MULTICOLOR1;
2626 }
2627 break;
2628
2629 case 0x26: /* sprite multicolor */
2630 if (m_reg[offset] != data)
2631 {
2632 m_reg[offset] = data;
2633 m_spritemulti[3] = SPRITE_MULTICOLOR2;
2634 }
2635 break;
2636
2637 case 0x19:
2638 clear_interrupt(data & 0x0f);
2639 break;
2640
2641 case 0x1a: /* irq mask */
2642 m_reg[offset] = data;
2643 set_interrupt(0); // beamrider needs this
2644 break;
2645
2646 case 0x11:
2647 if (m_reg[offset] != data)
2648 {
2649 m_reg[offset] = data;
2650 if (data & 8)
2651 {
2652 m_dy_start = ROW25_YSTART;
2653 m_dy_stop = ROW25_YSTOP;
2654 }
2655 else
2656 {
2657 m_dy_start = ROW24_YSTART;
2658 m_dy_stop = ROW24_YSTOP;
2659 }
2660 }
2661 break;
2662
2663 case 0x12:
2664 if (data != m_reg[offset])
2665 {
2666 m_reg[offset] = data;
2667 }
2668 break;
2669
2670 case 0x16:
2671 if (m_reg[offset] != data)
2672 {
2673 m_reg[offset] = data;
2674 }
2675 break;
2676
2677 case 0x18:
2678 if (m_reg[offset] != data)
2679 {
2680 m_reg[offset] = data;
2681 m_videoaddr = VIDEOADDR;
2682 m_chargenaddr = CHARGENADDR;
2683 m_bitmapaddr = BITMAPADDR;
2684 }
2685 break;
2686
2687 case 0x21: /* background color */
2688 if (m_reg[offset] != data)
2689 {
2690 m_reg[offset] = data;
2691 m_colors[0] = BACKGROUNDCOLOR;
2692 }
2693 break;
2694
2695 case 0x22: /* background color 1 */
2696 if (m_reg[offset] != data)
2697 {
2698 m_reg[offset] = data;
2699 m_colors[1] = MULTICOLOR1;
2700 }
2701 break;
2702
2703 case 0x23: /* background color 2 */
2704 if (m_reg[offset] != data)
2705 {
2706 m_reg[offset] = data;
2707 m_colors[2] = MULTICOLOR2;
2708 }
2709 break;
2710
2711 case 0x24: /* background color 3 */
2712 if (m_reg[offset] != data)
2713 {
2714 m_reg[offset] = data;
2715 m_colors[3] = FOREGROUNDCOLOR;
2716 }
2717 break;
2718
2719 case 0x20: /* framecolor */
2720 if (m_reg[offset] != data)
2721 {
2722 m_reg[offset] = data;
2723 }
2724 break;
2725
2726 case REGISTER_KCR:
2727 if (IS_VICIIE)
2728 {
2729 m_reg[offset] = data | 0xf8;
2730
2731 m_write_k((offs_t)0, data & 0x07);
2732 }
2733 break;
2734
2735 case REGISTER_FAST:
2736 if (IS_VICIIE)
2737 {
2738 if (BIT(m_reg[offset], 0) != BIT(data, 0))
2739 {
2740 m_cpu->set_unscaled_clock(clock() << BIT(data, 0));
2741 }
2742
2743 m_reg[offset] = data | 0xfc;
2744
2745 m_on = !BIT(data, 0);
2746 }
2747 break;
2748
2749 case 0x31:
2750 case 0x32:
2751 case 0x33:
2752 case 0x34:
2753 case 0x35:
2754 case 0x36:
2755 case 0x37:
2756 case 0x38:
2757 case 0x39:
2758 case 0x3a:
2759 case 0x3b:
2760 case 0x3c:
2761 case 0x3d:
2762 case 0x3e:
2763 case 0x3f:
2764 m_reg[offset] = data;
2765 DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
2766 break;
2767
2768 default:
2769 m_reg[offset] = data;
2770 break;
2771 }
2772 }
2773
2774
2775 //-------------------------------------------------
2776 // lp_w - light pen strobe
2777 //-------------------------------------------------
2778
WRITE_LINE_MEMBER(mos6566_device::lp_w)2779 WRITE_LINE_MEMBER( mos6566_device::lp_w )
2780 {
2781 if (m_lp && !state && !(m_reg[REGISTER_IRQ] & IRQ_LP))
2782 {
2783 m_reg[REGISTER_LPX] = m_raster_x >> 1;
2784 m_reg[REGISTER_LPY] = m_rasterline;
2785
2786 set_interrupt(IRQ_LP);
2787 }
2788
2789 m_lp = state;
2790 }
2791