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