1 // license:BSD-3-Clause
2 // copyright-holders:Angelo Salese, Sandro Ronco
3 /***************************************************************************
4 
5     HD63484 ACRTC
6 
7     TODO:
8     - execution cycles;
9 
10 ***************************************************************************/
11 
12 #include "emu.h"
13 #include "hd63484.h"
14 
15 #include "screen.h"
16 
17 
18 #define LOG 0
19 #define FIFO_LOG 0
20 #define CMD_LOG 0
21 
22 
23 //-------------------------------------------------
24 //  hd63484_device - constructor
25 //-------------------------------------------------
26 
hd63484_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)27 hd63484_device::hd63484_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
28 	device_t(mconfig, HD63484, tag, owner, clock),
29 	device_memory_interface(mconfig, *this),
30 	device_video_interface(mconfig, *this),
31 	m_display_cb(*this),
32 	m_auto_configure_screen(true),
33 	m_external_skew(0),
34 	m_ar(0),
35 	m_sr(0),
36 	m_fifo_ptr(-1),
37 	m_fifo_r_ptr(-1),
38 	m_cr(0),
39 	m_param_ptr(0),
40 	m_rwp_dn(0),
41 	m_org_dpa(0),
42 	m_org_dn(0),
43 	m_org_dpd(0),
44 	m_cl0(0),
45 	m_cl1(0), m_ccmp(0), m_mask(0), m_cpx(0),
46 	m_dcr(0),
47 	m_space_config("videoram", ENDIANNESS_BIG, 16, 20, -1)
48 {
49 }
50 
51 enum
52 {
53 	FIFO_READ = 0,
54 	FIFO_WRITE
55 };
56 
57 enum
58 {
59 	FIFO_EMPTY = -1,
60 	FIFO_PARAMETER,
61 	FIFO_COMMAND
62 };
63 
64 #define HD63484_SR_CER 0x80 // Command Error
65 #define HD63484_SR_ARD 0x40 // Area Detect
66 #define HD63484_SR_CED 0x20 // Command End
67 #define HD63484_SR_LPD 0x10 // Light Pen Strobe Detect
68 #define HD63484_SR_RFF 0x08 // Read FIFO Full
69 #define HD63484_SR_RFR 0x04 // Read FIFO Ready
70 #define HD63484_SR_WFR 0x02 // Write FIFO Ready
71 #define HD63484_SR_WFE 0x01 // Write FIFO Empty
72 
73 
74 static const char *const acrtc_regnames[0x100/2] =
75 {
76 	"FIFO Entry", // 0x00
77 	"Command Control (CCR)", // 0x02
78 	"Operation Mode (OMR)", // 0x04
79 	"Display Control (DCR)", // 0x06
80 	"(Undefined)", // 0x08
81 	"(Undefined)", // 0x0a
82 	"(Undefined)", // 0x0c
83 	"(Undefined)", // 0x0e
84 	"(Undefined)", // 0x10
85 	"(Undefined)", // 0x12
86 	"(Undefined)", // 0x14
87 	"(Undefined)", // 0x16
88 	"(Undefined)", // 0x18
89 	"(Undefined)", // 0x1a
90 	"(Undefined)", // 0x1c
91 	"(Undefined)", // 0x1e
92 	"(Undefined)", // 0x20
93 	"(Undefined)", // 0x22
94 	"(Undefined)", // 0x24
95 	"(Undefined)", // 0x26
96 	"(Undefined)", // 0x28
97 	"(Undefined)", // 0x2a
98 	"(Undefined)", // 0x2c
99 	"(Undefined)", // 0x2e
100 	"(Undefined)", // 0x30
101 	"(Undefined)", // 0x32
102 	"(Undefined)", // 0x34
103 	"(Undefined)", // 0x36
104 	"(Undefined)", // 0x38
105 	"(Undefined)", // 0x3a
106 	"(Undefined)", // 0x3c
107 	"(Undefined)", // 0x3e
108 	"(Undefined)", // 0x40
109 	"(Undefined)", // 0x42
110 	"(Undefined)", // 0x44
111 	"(Undefined)", // 0x46
112 	"(Undefined)", // 0x48
113 	"(Undefined)", // 0x4a
114 	"(Undefined)", // 0x4c
115 	"(Undefined)", // 0x4e
116 	"(Undefined)", // 0x50
117 	"(Undefined)", // 0x52
118 	"(Undefined)", // 0x54
119 	"(Undefined)", // 0x56
120 	"(Undefined)", // 0x58
121 	"(Undefined)", // 0x5a
122 	"(Undefined)", // 0x5c
123 	"(Undefined)", // 0x5e
124 	"(Undefined)", // 0x60
125 	"(Undefined)", // 0x62
126 	"(Undefined)", // 0x64
127 	"(Undefined)", // 0x66
128 	"(Undefined)", // 0x68
129 	"(Undefined)", // 0x6a
130 	"(Undefined)", // 0x6c
131 	"(Undefined)", // 0x6e
132 	"(Undefined)", // 0x70
133 	"(Undefined)", // 0x72
134 	"(Undefined)", // 0x74
135 	"(Undefined)", // 0x76
136 	"(Undefined)", // 0x78
137 	"(Undefined)", // 0x7a
138 	"(Undefined)", // 0x7c
139 	"(Undefined)", // 0x7e
140 	"Raster Count (RCR)", // 0x80
141 	"Horizontal Sync (HSR)", // 0x82
142 	"Horizontal Display (HDR)", // 0x84
143 	"Vertical Sync (VSR)", // 0x86
144 	"Vertical Display (VDR)", // 0x88
145 	"Split Screen Width (SSW) 0x8a", // 0x8a
146 	"Split Screen Width (SSW) 0x8c", // 0x8c
147 	"Split Screen Width (SSW) 0x8e", // 0x8e
148 	"Blink Control (BCR)", // 0x90
149 	"Horizontal Window Display (HWR)", // 0x92
150 	"Vertical Window Display (VWR) 0x94", // 0x94
151 	"Vertical Window Display (VWR) 0x96", // 0x96
152 	"Graphic Cursor (GCR0)", // 0x98
153 	"Graphic Cursor (GCR1)", // 0x9a
154 	"Graphic Cursor (GCR2)", // 0x9c
155 	"(Undefined)", // 0x9e
156 	"(Undefined)", // 0xa0
157 	"(Undefined)", // 0xa2
158 	"(Undefined)", // 0xa4
159 	"(Undefined)", // 0xa6
160 	"(Undefined)", // 0xa8
161 	"(Undefined)", // 0xaa
162 	"(Undefined)", // 0xac
163 	"(Undefined)", // 0xae
164 	"(Undefined)", // 0xb0
165 	"(Undefined)", // 0xb2
166 	"(Undefined)", // 0xb4
167 	"(Undefined)", // 0xb6
168 	"(Undefined)", // 0xb8
169 	"(Undefined)", // 0xba
170 	"(Undefined)", // 0xbc
171 	"(Undefined)", // 0xbe
172 	// upper screen
173 	"Raster Address 0 (RAR0)", // 0xc0
174 	"Memory Width 0 (MWR0)", // 0xc2
175 	"Start Address 0 (SAR0) 0xc4", // 0xc4
176 	"Start Address 0 (SAR0) 0xc6", // 0xc6
177 	// base screen
178 	"Raster Address 1 (RAR1)", // 0xc8
179 	"Memory Width 1 (MWR1)", // 0xca
180 	"Start Address 1 (SAR1) 0xcc", // 0xcc
181 	"Start Address 1 (SAR1) 0xce", // 0xce
182 	// lower screen
183 	"Raster Address 2 (RAR2)", // 0xd0
184 	"Memory Width 2 (MWR2)", // 0xd2
185 	"Start Address 2 (SAR2) 0xd4", // 0xd4
186 	"Start Address 2 (SAR2) 0xd6", // 0xd6
187 	// window screen
188 	"Raster Address 3 (RAR3)", // 0xd8
189 	"Memory Width 3 (MWR3)", // 0xda
190 	"Start Address 3 (SAR3) 0xdc", // 0xdc
191 	"Start Address 3 (SAR3) 0xde", // 0xde
192 	// block cursor 1
193 	"Block Cursor 1 (BCUR1) 0xe0",
194 	"Block Cursor 1 (BCUR1) 0xe2",
195 	// block cursor 2
196 	"Block Cursor 2 (BCUR2) 0xe4",
197 	"Block Cursor 2 (BCUR2) 0xe6",
198 	"Cursor Definition (CDR)",
199 	"Zoom Factor (ZFR)",
200 	"Lightpen Address (LPAR) 0xec",
201 	"Lightpen Address (LPAR) 0xee",
202 	"(Undefined)", // 0xf0
203 	"(Undefined)", // 0xf2
204 	"(Undefined)", // 0xf4
205 	"(Undefined)", // 0xf6
206 	"(Undefined)", // 0xf8
207 	"(Undefined)", // 0xfa
208 	"(Undefined)", // 0xfc
209 	"(Undefined)"  // 0xfe
210 };
211 
212 static const char *const wpr_regnames[0x20] =
213 {
214 	"Color 0 (CL0)",
215 	"Color 1 (CL1)",
216 	"Color Comparison (COMP)",
217 	"Edge Color (EDG)",
218 	"Mask (MASK)",
219 	"Pattern RAM Control (PRC) 0x05",
220 	"Pattern RAM Control (PRC) 0x06",
221 	"Pattern RAM Control (PRC) 0x07",
222 	"Area Definition (ADR) 0x08",
223 	"Area Definition (ADR) 0x09",
224 	"Area Definition (ADR) 0x0a",
225 	"Area Definition (ADR) 0x0b",
226 	"Read Write Pointer (RWP) H",
227 	"Read Write Pointer (RWP) L",
228 	"(Undefined)",
229 	"(Undefined)",
230 	"Drawing Pointer (DP) H",
231 	"Drawing Pointer (DP) L",
232 	"Current Pointer (CP) H",
233 	"Current Pointer (CP) L",
234 	"(Undefined)", // 0x14
235 	"(Undefined)",
236 	"(Undefined)", // 0x16
237 	"(Undefined)",
238 	"(Undefined)", // 0x18
239 	"(Undefined)",
240 	"(Undefined)", // 0x1a
241 	"(Undefined)",
242 	"(Undefined)", // 0x1c
243 	"(Undefined)",
244 	"(Undefined)", // 0x1e
245 	"(Undefined)"
246 };
247 
248 enum
249 {
250 	COMMAND_INVALID = -1,
251 	COMMAND_ORG,
252 	COMMAND_WPR,
253 	COMMAND_RPR,
254 	COMMAND_WPTN,
255 	COMMAND_RPTN,
256 	COMMAND_DRD,
257 	COMMAND_DWT,
258 	COMMAND_DMOD,
259 	COMMAND_RD,
260 	COMMAND_WT,
261 	COMMAND_MOD,
262 	COMMAND_CLR,
263 	COMMAND_SCLR,
264 	COMMAND_CPY,
265 	COMMAND_SCPY,
266 	COMMAND_AMOVE,
267 	COMMAND_RMOVE,
268 	COMMAND_ALINE,
269 	COMMAND_RLINE,
270 	COMMAND_ARCT,
271 	COMMAND_RRCT,
272 	COMMAND_APLL,
273 	COMMAND_RPLL,
274 	COMMAND_APLG,
275 	COMMAND_RPLG,
276 	COMMAND_CRCL,
277 	COMMAND_ELPS,
278 	COMMAND_AARC,
279 	COMMAND_RARC,
280 	COMMAND_AEARC,
281 	COMMAND_REARC,
282 	COMMAND_AFRCT,
283 	COMMAND_RFRCT,
284 	COMMAND_PAINT,
285 	COMMAND_DOT,
286 	COMMAND_PTN,
287 	COMMAND_AGCPY,
288 	COMMAND_RGCPY
289 };
290 
291 #define HD63484_COMMAND_ORG      0x0400  //              p: 2
292 #define HD63484_COMMAND_WPR      0x0800  // & ~0x1f      p: 1
293 #define HD63484_COMMAND_RPR      0x0c00  // & ~0x1f      p: 0
294 #define HD63484_COMMAND_WPTN     0x1800  // & ~0xf       p: 1 + n
295 #define HD63484_COMMAND_RPTN     0x1c00  // & ~0xf       p: 1
296 #define HD63484_COMMAND_DRD      0x2400  //              p: 2
297 #define HD63484_COMMAND_DWT      0x2800  //              p: 2
298 #define HD63484_COMMAND_DMOD     0x2c00  // & ~3         p: 2
299 #define HD63484_COMMAND_RD       0x4400  //              p: 0
300 #define HD63484_COMMAND_WT       0x4800  //              p: 1
301 #define HD63484_COMMAND_MOD      0x4c00  // & ~3         p: 1
302 #define HD63484_COMMAND_CLR      0x5800  //              p: 3
303 #define HD63484_COMMAND_SCLR     0x5c00  // & ~3         p: 3
304 #define HD63484_COMMAND_CPY      0x6000  // & ~0x0f03    p: 4
305 #define HD63484_COMMAND_SCPY     0x7000  // & ~0x0f03    p: 4
306 #define HD63484_COMMAND_AMOVE    0x8000  //              p: 2
307 #define HD63484_COMMAND_RMOVE    0x8400  //              p: 2
308 #define HD63484_COMMAND_ALINE    0x8800  // & ~0x00ff    p: 2
309 #define HD63484_COMMAND_RLINE    0x8c00  // & ~0x00ff    p: 2
310 #define HD63484_COMMAND_ARCT     0x9000  // & ~0x00ff    p: 2
311 #define HD63484_COMMAND_RRCT     0x9400  // & ~0x00ff    p: 2
312 #define HD63484_COMMAND_APLL     0x9800  // & ~0x00ff    p: 1 + n
313 #define HD63484_COMMAND_RPLL     0x9c00  // & ~0x00ff    p: 1 + n
314 #define HD63484_COMMAND_APLG     0xa000  // & ~0x00ff    p: 1 + n
315 #define HD63484_COMMAND_RPLG     0xa400  // & ~0x00ff    p: 1 + n
316 #define HD63484_COMMAND_CRCL     0xa800  // & ~0x01ff    p: 1
317 #define HD63484_COMMAND_ELPS     0xac00  // & ~0x01ff    p: 3
318 #define HD63484_COMMAND_AARC     0xb000  // & ~0x01ff    p: 4
319 #define HD63484_COMMAND_RARC     0xb400  // & ~0x01ff    p: 4
320 #define HD63484_COMMAND_AEARC    0xb800  // & ~0x01ff    p: 6
321 #define HD63484_COMMAND_REARC    0xbc00  // & ~0x01ff    p: 6
322 #define HD63484_COMMAND_AFRCT    0xc000  // & ~0x00ff    p: 2
323 #define HD63484_COMMAND_RFRCT    0xc400  // & ~0x00ff    p: 2
324 #define HD63484_COMMAND_PAINT    0xc800  // & ~0x01ff    p: 0
325 #define HD63484_COMMAND_DOT      0xcc00  // & ~0x00ff    p: 0
326 #define HD63484_COMMAND_PTN      0xd000  // & ~0x0fff    p: 1
327 #define HD63484_COMMAND_AGCPY    0xe000  // & ~0x0fff    p: 4
328 #define HD63484_COMMAND_RGCPY    0xf000  // & ~0x0fff    p: 4
329 
330 
331 /*-------------------------------------------------
332     ROM( hd63484 )
333 -------------------------------------------------*/
334 
335 // devices
336 DEFINE_DEVICE_TYPE(HD63484, hd63484_device, "hd63484", "Hitachi HD63484 ACRTC")
337 
338 
ROM_START(hd63484)339 ROM_START( hd63484 )
340 	ROM_REGION( 0x100, "hd63484", 0 )
341 	ROM_LOAD( "hd63484.bin", 0x000, 0x100, NO_DUMP ) /* internal control ROM */
342 ROM_END
343 
344 //-------------------------------------------------
345 //  memory_space_config - return a description of
346 //  any address spaces owned by this device
347 //-------------------------------------------------
348 
349 device_memory_interface::space_config_vector hd63484_device::memory_space_config() const
350 {
351 	return space_config_vector {
352 		std::make_pair(0, &m_space_config)
353 	};
354 }
355 
356 
357 //-------------------------------------------------
358 //  rom_region - device-specific ROM region
359 //-------------------------------------------------
360 
device_rom_region() const361 const tiny_rom_entry *hd63484_device::device_rom_region() const
362 {
363 	return ROM_NAME( hd63484 );
364 }
365 
366 //-------------------------------------------------
367 //  readword - read a word at the given address
368 //-------------------------------------------------
369 
readword(offs_t address)370 inline uint16_t hd63484_device::readword(offs_t address)
371 {
372 	return space().read_word(address);
373 }
374 
375 
376 //-------------------------------------------------
377 //  writeword - write a word at the given address
378 //-------------------------------------------------
379 
writeword(offs_t address,uint16_t data)380 inline void hd63484_device::writeword(offs_t address, uint16_t data)
381 {
382 	space().write_word(address, data);
383 }
384 
385 
inc_ar(int value)386 inline void hd63484_device::inc_ar(int value)
387 {
388 	if(m_ar & 0x80)
389 	{
390 		if (m_ar + value > 0xff)    // TODO: what happens if it overflows?
391 			logerror("HD63484 '%s': Address Register overflows 0x%02x\n", tag(), m_ar + value);
392 
393 		m_ar = (m_ar + value) & 0xff;
394 	}
395 }
396 
fifo_w_clear()397 inline void hd63484_device::fifo_w_clear()
398 {
399 	int i;
400 
401 	for (i = 0; i < 16; i++)
402 		m_fifo[i] = 0;
403 
404 	m_fifo_ptr = -1;
405 
406 	m_sr |= HD63484_SR_WFR;
407 	m_sr |= HD63484_SR_WFE;
408 }
409 
queue_w(uint8_t data)410 inline void hd63484_device::queue_w(uint8_t data)
411 {
412 	if (m_fifo_ptr < 15)
413 	{
414 		m_fifo_ptr++;
415 
416 		m_fifo[m_fifo_ptr] = data;
417 
418 		if (m_fifo_ptr == 16)
419 			m_sr &= ~HD63484_SR_WFR;
420 
421 		m_sr &= ~HD63484_SR_WFE;
422 	}
423 	else
424 	{
425 		// TODO what happen? somebody set us up the bomb
426 		printf("FIFO?\n");
427 	}
428 }
429 
dequeue_w(uint8_t * data)430 inline void hd63484_device::dequeue_w(uint8_t *data)
431 {
432 	int i;
433 
434 	*data = m_fifo[0];
435 
436 	if (m_fifo_ptr > -1)
437 	{
438 		for (i = 0; i < 15; i++)
439 			m_fifo[i] = m_fifo[i + 1];
440 
441 		m_fifo[15] = 0;
442 
443 		m_fifo_ptr--;
444 
445 		m_sr |= HD63484_SR_WFR;
446 
447 		if (m_fifo_ptr == -1)
448 			m_sr |= HD63484_SR_WFE;
449 
450 	}
451 }
452 
fifo_r_clear()453 inline void hd63484_device::fifo_r_clear()
454 {
455 	int i;
456 
457 	for (i = 0; i < 16; i++)
458 		m_fifo_r[i] = 0;
459 
460 	m_fifo_r_ptr = -1;
461 
462 	m_sr &= ~HD63484_SR_RFR;
463 	m_sr &= ~HD63484_SR_RFF;
464 }
465 
queue_r(uint8_t data)466 inline void hd63484_device::queue_r(uint8_t data)
467 {
468 	if (m_fifo_r_ptr < 15)
469 	{
470 		m_fifo_r_ptr++;
471 
472 		m_fifo_r[m_fifo_r_ptr] = data;
473 
474 		if (m_fifo_r_ptr == 16)
475 			m_sr |= HD63484_SR_RFF;
476 
477 		m_sr |= HD63484_SR_RFR;
478 	}
479 	else
480 	{
481 		// TODO what happen? somebody set us up the bomb
482 		printf("FIFO?\n");
483 	}
484 }
485 
dequeue_r(uint8_t * data)486 inline void hd63484_device::dequeue_r(uint8_t *data)
487 {
488 	int i;
489 
490 	*data = m_fifo_r[0];
491 
492 	if (m_fifo_r_ptr > -1)
493 	{
494 		for (i = 0; i < 15; i++)
495 			m_fifo_r[i] = m_fifo_r[i + 1];
496 
497 		m_fifo_r[15] = 0;
498 
499 		m_fifo_r_ptr--;
500 
501 		m_sr &= ~HD63484_SR_RFF;
502 
503 		if (m_fifo_r_ptr == -1)
504 			m_sr &= ~HD63484_SR_RFR;
505 	}
506 }
507 
508 //-------------------------------------------------
509 //  recompute_parameters -
510 //-------------------------------------------------
511 
recompute_parameters()512 inline void hd63484_device::recompute_parameters()
513 {
514 	if(!m_auto_configure_screen || m_hdw < 3 || m_hc == 0 || m_vc == 0) //bail out if screen params aren't valid
515 		return;
516 
517 	if (LOG)
518 	{
519 		printf("HC %d HSW %d HDS %d HDW %d HWS %d HWW %d\n",m_hc,m_hsw,m_hds,m_hdw,m_hws,m_hww);
520 		printf("VC %d VDS %d VSW %d VWS %d VWW %d\n",m_vc,m_vds,m_vsw,m_vws,m_vww);
521 		printf("SP0 %d SP1 %d SP2 %d\n",m_sp[0],m_sp[1],m_sp[2]);
522 	}
523 
524 	int gai = (m_omr>>4) & 0x07;
525 	if (gai > 3)    printf("unsupported GAI=%d\n", gai);
526 	int acm = (m_omr & 0x08) ? 2 : 1;
527 	int ppw = 16 / get_bpp();
528 	int ppmc = ppw * (1 << gai) / acm;  // TODO: GAI > 3
529 	int vbstart = m_vds + m_sp[1];
530 	int hbend = (m_hsw + m_hds + m_external_skew) * ppmc;
531 	if (BIT(m_dcr, 13)) vbstart += m_sp[0];
532 	if (BIT(m_dcr, 11)) vbstart += m_sp[2];
533 
534 	rectangle visarea = screen().visible_area();
535 	visarea.set(hbend, hbend + (m_hdw * ppmc) - 1, m_vds, vbstart - 1);
536 	attoseconds_t frame_period = screen().frame_period().attoseconds(); // TODO: use clock() to calculate the frame_period
537 	screen().configure(m_hc * ppmc, m_vc, visarea, frame_period);
538 }
539 
540 
541 /*****************************************************************************
542     IMPLEMENTATION
543 *****************************************************************************/
544 
translate_command(uint16_t data)545 int hd63484_device::translate_command(uint16_t data)
546 {
547 	/* annoying switch-case sequence, but it's the only way to get invalid commands ... */
548 	switch (data)
549 	{
550 		case HD63484_COMMAND_ORG:    return COMMAND_ORG;
551 		case HD63484_COMMAND_DRD:    return COMMAND_DRD;
552 		case HD63484_COMMAND_DWT:    return COMMAND_DWT;
553 		case HD63484_COMMAND_RD:     return COMMAND_RD;
554 		case HD63484_COMMAND_WT:     return COMMAND_WT;
555 		case HD63484_COMMAND_CLR:    return COMMAND_CLR;
556 		case HD63484_COMMAND_AMOVE:  return COMMAND_AMOVE;
557 		case HD63484_COMMAND_RMOVE:  return COMMAND_RMOVE;
558 	}
559 
560 	switch(data & ~0x3)
561 	{
562 		case HD63484_COMMAND_DMOD:   return COMMAND_DMOD;
563 		case HD63484_COMMAND_MOD:    return COMMAND_MOD;
564 		case HD63484_COMMAND_SCLR:   return COMMAND_SCLR;
565 	}
566 
567 	switch(data & ~0xf)
568 	{
569 		case HD63484_COMMAND_WPTN:   return COMMAND_WPTN;
570 		case HD63484_COMMAND_RPTN:   return COMMAND_RPTN;
571 	}
572 
573 	switch(data & ~0x1f)
574 	{
575 		case HD63484_COMMAND_WPR:    return COMMAND_WPR;
576 		case HD63484_COMMAND_RPR:    return COMMAND_RPR;
577 	}
578 
579 	switch(data & ~0x0f03)
580 	{
581 		case HD63484_COMMAND_CPY:    return COMMAND_CPY;
582 		case HD63484_COMMAND_SCPY:   return COMMAND_SCPY;
583 	}
584 
585 	switch(data & ~0x00ff)
586 	{
587 		case HD63484_COMMAND_ALINE:  return COMMAND_ALINE;
588 		case HD63484_COMMAND_RLINE:  return COMMAND_RLINE;
589 		case HD63484_COMMAND_ARCT:   return COMMAND_ARCT;
590 		case HD63484_COMMAND_RRCT:   return COMMAND_RRCT;
591 		case HD63484_COMMAND_APLL:   return COMMAND_APLL;
592 		case HD63484_COMMAND_RPLL:   return COMMAND_RPLL;
593 		case HD63484_COMMAND_APLG:   return COMMAND_APLG;
594 		case HD63484_COMMAND_RPLG:   return COMMAND_RPLG;
595 		case HD63484_COMMAND_AFRCT:  return COMMAND_AFRCT;
596 		case HD63484_COMMAND_RFRCT:  return COMMAND_RFRCT;
597 		case HD63484_COMMAND_DOT:    return COMMAND_DOT;
598 	}
599 
600 	switch(data & ~0x01ff)
601 	{
602 		case HD63484_COMMAND_CRCL:   return COMMAND_CRCL;
603 		case HD63484_COMMAND_ELPS:   return COMMAND_ELPS;
604 		case HD63484_COMMAND_AARC:   return COMMAND_AARC;
605 		case HD63484_COMMAND_RARC:   return COMMAND_RARC;
606 		case HD63484_COMMAND_AEARC:  return COMMAND_AEARC;
607 		case HD63484_COMMAND_REARC:  return COMMAND_REARC;
608 		case HD63484_COMMAND_PAINT:  return COMMAND_PAINT;
609 	}
610 
611 	switch(data & ~0x0fff)
612 	{
613 		case HD63484_COMMAND_PTN:    return COMMAND_PTN;
614 		case HD63484_COMMAND_AGCPY:  return COMMAND_AGCPY;
615 		case HD63484_COMMAND_RGCPY:  return COMMAND_RGCPY;
616 	}
617 
618 	return COMMAND_INVALID;
619 }
620 
command_end_seq()621 inline void hd63484_device::command_end_seq()
622 {
623 	//hd63484->param_ptr = 0;
624 	m_sr |= HD63484_SR_CED;
625 
626 	/* TODO: we might need to be more aggressive and clear the params in there */
627 }
628 
get_bpp()629 int hd63484_device::get_bpp()
630 {
631 	int gbm = (m_ccr >> 8) & 0x07;
632 
633 	if (gbm <= 4)
634 		return 1 << gbm;
635 
636 	//logerror ("Invalid Graphic Bit Mode (%d)\n", gbm);
637 	return 1;
638 }
639 
calc_offset(int16_t x,int16_t y,uint32_t & offset,uint8_t & bit_pos)640 void hd63484_device::calc_offset(int16_t x, int16_t y, uint32_t &offset, uint8_t &bit_pos)
641 {
642 	int bpp = get_bpp();
643 	int ppw = 16 / bpp;
644 	int gbm = (m_ccr >> 8) & 0x07;
645 	x += (m_org_dpd >> gbm);
646 	if (x >= 0)
647 	{
648 		offset = x / ppw;
649 		bit_pos = x % ppw;
650 	}
651 	else
652 	{
653 		offset = x / ppw;
654 		bit_pos= (-x) % ppw;
655 		if (bit_pos != 0)
656 		{
657 			offset--;
658 			bit_pos = ppw - bit_pos;
659 		}
660 	}
661 
662 	offset += m_org_dpa - y * m_mwr[m_org_dn];
663 	bit_pos *= bpp;
664 }
665 
get_dot(int16_t x,int16_t y)666 uint16_t hd63484_device::get_dot(int16_t x, int16_t y)
667 {
668 	uint8_t bpp = get_bpp();
669 	uint32_t offset = 0;
670 	uint8_t bit_pos = 0;
671 
672 	calc_offset(x, y, offset, bit_pos);
673 
674 	return (readword(offset) >> bit_pos) & ((1 << bpp) - 1);
675 }
676 
set_dot(int16_t x,int16_t y,int16_t px,int16_t py)677 bool hd63484_device::set_dot(int16_t x, int16_t y, int16_t px, int16_t py)
678 {
679 	int xs = m_pex - m_psx + 1;
680 	int ys = m_pey - m_psy + 1;
681 	int zx = m_pzx + 1;
682 	int zy = m_pzy + 1;
683 	int xp = m_psx + ((px % (xs * zx)) / zx);
684 	int yp = m_psy + ((py % (ys * zy)) / zy);
685 
686 	if (xp < m_psx)
687 		xp = (m_pex + 1) - (m_psx - xp);
688 
689 	if (yp < m_psy)
690 		yp = (m_pey + 1) - (m_psy - yp);
691 
692 	int pix = (m_pram[yp & 0x0f] >> (xp & 0x0f)) & 0x01;
693 
694 	uint8_t col = (m_cr >> 3) & 0x03;
695 	uint8_t bpp = get_bpp();
696 	uint16_t mask = (1 << bpp) - 1;
697 	uint16_t xmask = (16 / bpp) - 1;
698 	uint16_t cl0 = (m_cl0 >> ((x & xmask) * bpp)) & mask;
699 	uint16_t cl1 = (m_cl1 >> ((x & xmask) * bpp)) & mask;
700 
701 	switch (col)
702 	{
703 		case 0x00:
704 			return set_dot(x, y, pix ? cl1 : cl0);
705 		case 0x01:
706 			if (pix)
707 				return set_dot(x, y, cl1);
708 			break;
709 		case 0x02:
710 			if (!pix)
711 				return set_dot(x, y, cl0);
712 			break;
713 		case 0x03:
714 			fatalerror("HD63484 color modes (Pattern RAM indirect)\n");
715 			// TODO
716 	}
717 
718 	return false;
719 }
720 
set_dot(int16_t x,int16_t y,uint16_t color)721 bool hd63484_device::set_dot(int16_t x, int16_t y, uint16_t color)
722 {
723 	uint8_t bpp = get_bpp();
724 	uint32_t offset = 0;
725 	uint8_t bit_pos = 0;
726 	uint8_t opm = m_cr & 0x07;
727 	uint8_t area = (m_cr >> 5) & 0x07;
728 
729 	calc_offset(x, y, offset, bit_pos);
730 
731 	uint16_t mask = ((1 << bpp) - 1) << bit_pos;
732 	uint16_t color_shifted = (color << bit_pos) & mask;
733 
734 	uint16_t data = readword(offset);
735 	uint16_t res = data;
736 
737 	switch (opm)
738 	{
739 		case 0:
740 			res = (data & ~mask) | color_shifted;
741 			break;
742 		case 1:
743 			res = (data & ~mask) | ((data & mask) | color_shifted);
744 			break;
745 		case 2:
746 			res = (data & ~mask) | ((data & mask) & color_shifted);
747 			break;
748 		case 3:
749 			res = (data & ~mask) | ((data & mask) ^ color_shifted);
750 			break;
751 		case 4:
752 			if (get_dot(x, y) == ((m_ccmp & mask) >> bit_pos))
753 				res = (data & ~mask) | color_shifted;
754 			break;
755 		case 5:
756 			if (get_dot(x, y) != ((m_ccmp & mask) >> bit_pos))
757 				res = (data & ~mask) | color_shifted;
758 			break;
759 		case 6:
760 			if (get_dot(x, y) < ((m_cl0 & mask) >> bit_pos))
761 				res = (data & ~mask) | color_shifted;
762 			break;
763 		case 7:
764 			if (get_dot(x, y) > ((m_cl1 & mask) >> bit_pos))
765 				res = (data & ~mask) | color_shifted;
766 			break;
767 	}
768 
769 	writeword(offset, res);
770 
771 	if (area)
772 		logerror("HD63484 '%s': unsupported area detection %x (%d %d)\n", tag(), area, x, y);
773 
774 	return false;   // TODO: return area detection status
775 }
776 
draw_line(int16_t sx,int16_t sy,int16_t ex,int16_t ey)777 void hd63484_device::draw_line(int16_t sx, int16_t sy, int16_t ex, int16_t ey)
778 {
779 	uint16_t delta_x = abs(ex - sx) * 2;
780 	uint16_t delta_y = abs(ey - sy) * 2;
781 	int dir_x = (ex < sx) ? -1 : ((ex > sx) ? +1 : 0);
782 	int dir_y = (ey < sy) ? -1 : ((ey > sy) ? +1 : 0);
783 	int pram_pos = 0;
784 
785 	if(delta_x > delta_y)
786 	{
787 		int delta = delta_y - delta_x / 2;
788 		while(sx != ex)
789 		{
790 			set_dot(sx, sy, pram_pos, 0);
791 
792 			if(delta >= 0)
793 			{
794 				sy += dir_y;
795 				delta -= delta_x;
796 			}
797 			pram_pos++;
798 			sx += dir_x;
799 			delta += delta_y;
800 		}
801 	}
802 	else
803 	{
804 		int delta = delta_x - delta_y / 2;
805 		while(sy != ey)
806 		{
807 			set_dot(sx, sy, pram_pos, 0);
808 
809 			if(delta >= 0)
810 			{
811 				sx += dir_x;
812 				delta -= delta_y;
813 			}
814 			pram_pos++;
815 			sy += dir_y;
816 			delta += delta_x;
817 		}
818 	}
819 }
820 
draw_ellipse(int16_t cx,int16_t cy,double dx,double dy,double s_angol,double e_angol,bool c)821 void hd63484_device::draw_ellipse(int16_t cx, int16_t cy, double dx, double dy, double s_angol, double e_angol, bool c)
822 {
823 	double inc = 1.0 / (std::max(dx, dy) * 100);
824 	for (double angol = s_angol; fabs(angol - e_angol) >= inc*2; angol += inc * (c ? -1 : +1))
825 	{
826 		if (angol > DEGREE_TO_RADIAN(360))    angol -= DEGREE_TO_RADIAN(360);
827 		if (angol < DEGREE_TO_RADIAN(0))      angol += DEGREE_TO_RADIAN(360);
828 
829 		double px = cos(angol) * dx;
830 		double py = sin(angol) * dy;
831 		set_dot(cx + round(px), cy + round(py), 0, 0);
832 	}
833 }
834 
paint(int16_t sx,int16_t sy)835 void hd63484_device::paint(int16_t sx, int16_t sy)
836 {
837 /*
838     This is not accurate since real hardware can only paint 4 'unpaintable' areas,
839     the other 'unpaintable' points are pushed into the read FIFO to be processed
840     later by the program, but currently is impossible suspend/resume the command
841     in case the read FIFO is full, so all 'unpaintable' areas are painted.
842     Also CP is not in the correct position after this command.
843 */
844 	uint8_t e = BIT(m_cr, 8);
845 	uint8_t bpp = get_bpp();
846 	uint16_t mask = (1 << bpp) - 1;
847 	uint16_t xmask = (16 / bpp) - 1;
848 
849 	for (int ydir=0; ydir<2; ydir++)
850 		for(uint16_t y=0;y<0x7fff; y++)
851 		{
852 			bool limit = true;
853 			bool unpaintable_up = false;
854 			bool unpaintable_dn = false;
855 
856 			for (int xdir=0; xdir<2; xdir++)
857 				for(uint16_t x=0; x<0x7fff; x++)
858 				{
859 					int16_t px = sx + (xdir ? -x : x);
860 					int16_t py = sy + (ydir ? -y : y);
861 
862 					uint16_t dot = get_dot(px, py);
863 					uint16_t edg = (m_edg >> (px & xmask) * bpp) & mask;
864 					uint16_t cl0 = (m_cl0 >> (px & xmask) * bpp) & mask;
865 					uint16_t cl1 = (m_cl1 >> (px & xmask) * bpp) & mask;
866 
867 					if ((e && dot != edg) || (!e && dot == edg) || dot == cl0 || dot == cl1)
868 						break;
869 
870 					if ((!ydir && !xdir && x && y) || (xdir && y) || (ydir && x) || (ydir && xdir))
871 						set_dot(px, py, px - m_cpx, py - m_cpy);
872 
873 					dot = get_dot(px, py + 1);
874 					if (unpaintable_up && !((e && dot == edg) && (!e && dot != edg) && dot != cl0 && dot != cl1))
875 						paint(px, py + 1);
876 					else if (!unpaintable_up && ((e && dot != edg) || (!e && dot == edg) || dot == cl0 || dot == cl1))
877 						unpaintable_up = true;
878 
879 					dot = get_dot(px, py - 1);
880 					if (unpaintable_dn && !((e && dot == edg) && (!e && dot != edg) && dot != cl0 && dot != cl1))
881 						paint(px, py - 1);
882 					else if (!unpaintable_dn && ((e && dot != edg) || (!e && dot == edg) || dot == cl0 || dot == cl1))
883 						unpaintable_dn = true;
884 
885 					limit = false;
886 				}
887 			if (limit)     break;
888 		}
889 }
890 
command_rpr_exec()891 uint16_t hd63484_device::command_rpr_exec()
892 {
893 	switch(m_cr & 0x1f)
894 	{
895 		case 0x00: // color 0
896 			return m_cl0;
897 		case 0x01: // color 1
898 			return m_cl1;
899 		case 0x02: // color comparison
900 			return m_ccmp;
901 		case 0x03: // edge color
902 			return m_edg;
903 		case 0x04: // mask
904 			return m_mask;
905 		case 0x05: // Pattern RAM Control 1
906 			return (m_ppy << 12) | (m_pzcy << 8) | (m_ppx << 4) | m_pzcx;
907 		case 0x06: // Pattern RAM Control 2
908 			return (m_psy << 12) | (m_psx << 4);
909 		case 0x07: // Pattern RAM Control 3
910 			return (m_pey << 12) | (m_pzy << 8) | (m_pex << 4) | m_pzx;
911 		case 0x08: // Area Definition XMIN
912 			return m_xmin;
913 		case 0x09: // Area Definition YMIN
914 			return m_ymin;
915 		case 0x0a: // Area Definition XMAX
916 			return m_xmax;
917 		case 0x0b: // Area Definition YMAX
918 			return m_ymax;
919 		case 0x0c: // Read Write Pointer H
920 			return (m_rwp_dn << 14) | ((m_rwp[m_rwp_dn] >> 12) & 0xff);
921 		case 0x0d: // Read Write Pointer L
922 			return (m_rwp[m_rwp_dn] & 0x0fff) << 4;
923 		default:
924 			if(LOG) printf("Read %sx\n", wpr_regnames[m_cr & 0x1f]);
925 			return 0;
926 	}
927 }
928 
command_wpr_exec()929 void hd63484_device::command_wpr_exec()
930 {
931 	switch(m_cr & 0x1f)
932 	{
933 		case 0x00: // color 0
934 			m_cl0 = m_pr[0];
935 			break;
936 		case 0x01: // color 1
937 			m_cl1 = m_pr[0];
938 			break;
939 		case 0x02: // color comparison
940 			m_ccmp = m_pr[0];
941 			break;
942 		case 0x03: // edge color
943 			m_edg = m_pr[0];
944 			break;
945 		case 0x04: // mask
946 			m_mask = m_pr[0];
947 			break;
948 		case 0x05: // Pattern RAM Control 1
949 			m_pzcx = (m_pr[0] >> 0) & 0x0f;
950 			m_ppx = (m_pr[0] >> 4) & 0x0f;
951 			m_pzcy = (m_pr[0] >> 8) & 0x0f;
952 			m_ppy = (m_pr[0] >> 12) & 0x0f;
953 			break;
954 		case 0x06: // Pattern RAM Control 2
955 			m_psx = (m_pr[0] >> 4) & 0x0f;
956 			m_psy = (m_pr[0] >> 12) & 0x0f;
957 			break;
958 		case 0x07: // Pattern RAM Control 3
959 			m_pzx = (m_pr[0] >> 0) & 0x0f;
960 			m_pex = (m_pr[0] >> 4) & 0x0f;
961 			m_pzy = (m_pr[0] >> 8) & 0x0f;
962 			m_pey = (m_pr[0] >> 12) & 0x0f;
963 			break;
964 		case 0x08: // Area Definition XMIN
965 			m_xmin = m_pr[0];
966 			break;
967 		case 0x09: // Area Definition YMIN
968 			m_ymin = m_pr[0];
969 			break;
970 		case 0x0a: // Area Definition XMAX
971 			m_xmax = m_pr[0];
972 			break;
973 		case 0x0b: // Area Definition YMAX
974 			m_ymax = m_pr[0];
975 			break;
976 		case 0x0c: // Read Write Pointer H
977 			m_rwp_dn = (m_pr[0] & 0xc000) >> 14;
978 			m_rwp[m_rwp_dn] = (m_rwp[m_rwp_dn] & 0x00fff) | ((m_pr[0] & 0x00ff) << 12);
979 			break;
980 		case 0x0d: // Read Write Pointer L
981 			m_rwp[m_rwp_dn] = (m_rwp[m_rwp_dn] & 0xff000) | ((m_pr[0] & 0xfff0) >> 4);
982 			break;
983 		default:
984 			if(LOG) printf("%s -> %02x\n",wpr_regnames[m_cr & 0x1f],m_pr[0]);
985 			break;
986 	}
987 }
988 
command_clr_exec()989 void hd63484_device::command_clr_exec()
990 {
991 	uint8_t mm = m_cr & 0x03;
992 	uint16_t d = m_pr[0];
993 	int16_t ax = (int16_t)m_pr[1];
994 	int16_t ay = (int16_t)m_pr[2];
995 
996 	int d0_inc = (ax < 0) ? -1 : 1;
997 	int d1_inc = (ay < 0) ? -1 : 1;
998 
999 	for(int16_t d1=0; d1!=ay+d1_inc; d1+=d1_inc)
1000 	{
1001 		for(int16_t d0=0; d0!=ax+d0_inc; d0+=d0_inc)
1002 		{
1003 			uint32_t offset = m_rwp[m_rwp_dn] - d1 * m_mwr[m_rwp_dn] + d0;
1004 			uint16_t data = readword(offset);
1005 			uint16_t res = 0;
1006 
1007 			if (BIT(m_cr, 10))
1008 			{
1009 				switch(mm)
1010 				{
1011 					case 0: // replace
1012 						res = (data & ~m_mask) | (d & m_mask);
1013 						break;
1014 					case 1: // OR
1015 						res = (data & ~m_mask) | ((data | d) & m_mask);
1016 						break;
1017 					case 2: // AND
1018 						res = (data & ~m_mask) | ((data & d) & m_mask);
1019 						break;
1020 					case 3: // EOR
1021 						res = (data & ~m_mask) | ((data ^ d) & m_mask);
1022 						break;
1023 				}
1024 			}
1025 			else
1026 				res = d;
1027 
1028 			writeword(offset, res);
1029 		}
1030 	}
1031 
1032 	m_rwp[m_rwp_dn] -= (ay + d1_inc) * m_mwr[m_rwp_dn];
1033 	m_rwp[m_rwp_dn] &= 0xfffff;
1034 }
1035 
command_cpy_exec()1036 void hd63484_device::command_cpy_exec()
1037 {
1038 	uint8_t mm = m_cr & 0x03;
1039 	uint8_t dsd = (m_cr >> 8) & 0x07;
1040 	uint8_t s = BIT(m_cr, 11);
1041 	uint32_t SA = ((m_pr[0] & 0xff) << 12) | ((m_pr[1]&0xfff0) >> 4);
1042 	int16_t DX = (int16_t)m_pr[s ? 3 : 2];
1043 	int16_t DY = (int16_t)m_pr[s ? 2 : 3];
1044 
1045 	int sd0_inc = (DX < 0) ? -1 : 1;
1046 	int sd1_inc = (DY < 0) ? -1 : 1;
1047 	int dd0_inc, dd1_inc;
1048 	if (dsd & 0x04)
1049 	{
1050 		dd0_inc = dsd & 0x01 ? -1 : +1;
1051 		dd1_inc = dsd & 0x02 ? -1 : +1;
1052 	}
1053 	else
1054 	{
1055 		dd0_inc = dsd & 0x02 ? -1 : +1;
1056 		dd1_inc = dsd & 0x01 ? -1 : +1;
1057 	}
1058 
1059 	for(int16_t sd1=0, dd1=0; sd1!=DY+sd1_inc; sd1+=sd1_inc, dd1+=dd1_inc)
1060 	{
1061 		for(int16_t sd0=0, dd0=0; sd0!=DX+sd0_inc; sd0+=sd0_inc, dd0+=dd0_inc)
1062 		{
1063 			uint32_t src_offset, dst_offset;
1064 
1065 			if (s)
1066 				src_offset = SA + sd1 - sd0 * m_mwr[m_rwp_dn];
1067 			else
1068 				src_offset = SA + sd0 - sd1 * m_mwr[m_rwp_dn];
1069 
1070 			if (BIT(dsd, 2))
1071 				dst_offset = m_rwp[m_rwp_dn] + dd1 - dd0 * m_mwr[m_rwp_dn];
1072 			else
1073 				dst_offset = m_rwp[m_rwp_dn] + dd0 - dd1 * m_mwr[m_rwp_dn];
1074 
1075 			uint16_t src_data = readword(src_offset);
1076 			uint16_t dst_data = readword(dst_offset);
1077 
1078 			if (BIT(m_cr, 12))
1079 			{
1080 				switch(mm)
1081 				{
1082 					case 0: // replace
1083 						dst_data = (dst_data & ~m_mask) | (src_data & m_mask);
1084 						break;
1085 					case 1: // OR
1086 						dst_data = (dst_data & ~m_mask) | ((dst_data | src_data) & m_mask);
1087 						break;
1088 					case 2: // AND
1089 						dst_data = (dst_data & ~m_mask) | ((dst_data & src_data) & m_mask);
1090 						break;
1091 					case 3: // EOR
1092 						dst_data = (dst_data & ~m_mask) | ((dst_data ^ src_data) & m_mask);
1093 						break;
1094 				}
1095 			}
1096 			else
1097 				dst_data = src_data;
1098 
1099 			writeword(dst_offset, dst_data);
1100 		}
1101 	}
1102 
1103 	m_rwp[m_rwp_dn] += dsd & 0x04 ? (DY + dd1_inc) : (-(DY + dd1_inc) * m_mwr[m_rwp_dn]);
1104 	m_rwp[m_rwp_dn] &= 0xfffff;
1105 }
1106 
command_line_exec()1107 void hd63484_device::command_line_exec()
1108 {
1109 	int16_t x = (int16_t)m_pr[0];
1110 	int16_t y = (int16_t)m_pr[1];
1111 
1112 	if (BIT(m_cr, 10))
1113 	{
1114 		x += m_cpx;
1115 		y += m_cpy;
1116 	}
1117 
1118 	draw_line(m_cpx, m_cpy, x, y);
1119 
1120 	m_cpx = x;
1121 	m_cpy = y;
1122 }
1123 
command_rct_exec()1124 void hd63484_device::command_rct_exec()
1125 {
1126 	int16_t dX = m_pr[0];
1127 	int16_t dY = m_pr[1];
1128 
1129 	if (BIT(m_cr, 10))  // relative (RRCT)
1130 	{
1131 		dX += m_cpx;
1132 		dY += m_cpy;
1133 	}
1134 
1135 	/*
1136 	3<-2
1137 	|  ^
1138 	v  |
1139 	0->1
1140 	*/
1141 
1142 	/* 0 -> 1 */
1143 	draw_line(m_cpx, m_cpy, dX, m_cpy);
1144 
1145 	/* 1 -> 2 */
1146 	draw_line(dX, m_cpy, dX, dY);
1147 
1148 	/* 2 -> 3 */
1149 	draw_line(dX, dY, m_cpx, dY);
1150 
1151 	/* 3 -> 4 */
1152 	draw_line(m_cpx, dY, m_cpx, m_cpy);
1153 }
1154 
command_gcpy_exec()1155 void hd63484_device::command_gcpy_exec()
1156 {
1157 	uint8_t dsd = (m_cr >> 8) & 0x07;
1158 	uint8_t s = BIT(m_cr, 11);
1159 	int16_t Xs = (int16_t)m_pr[0];
1160 	int16_t Ys = (int16_t)m_pr[1];
1161 	int16_t DX = (int16_t)m_pr[s ? 3 : 2];
1162 	int16_t DY = (int16_t)m_pr[s ? 2 : 3];
1163 
1164 	if (BIT(m_cr, 12))  // relative (RGCPY)
1165 	{
1166 		Xs += m_cpx;
1167 		Ys += m_cpy;
1168 	}
1169 
1170 	int sd0_inc = (DX < 0) ? -1 : 1;
1171 	int sd1_inc = (DY < 0) ? -1 : 1;
1172 	int dd0_inc, dd1_inc;
1173 	if (dsd & 0x04)
1174 	{
1175 		dd0_inc = dsd & 0x01 ? -1 : +1;
1176 		dd1_inc = dsd & 0x02 ? -1 : +1;
1177 	}
1178 	else
1179 	{
1180 		dd0_inc = dsd & 0x02 ? -1 : +1;
1181 		dd1_inc = dsd & 0x01 ? -1 : +1;
1182 	}
1183 
1184 	for(int16_t sd1=0, dd1=0; sd1!=DY+sd1_inc; sd1+=sd1_inc, dd1+=dd1_inc)
1185 	{
1186 		for(int16_t sd0=0, dd0=0; sd0!=DX+sd0_inc; sd0+=sd0_inc, dd0+=dd0_inc)
1187 		{
1188 			uint16_t color;
1189 			if (s)
1190 				color = get_dot(Xs + sd1, Ys + sd0);
1191 			else
1192 				color = get_dot(Xs + sd0, Ys + sd1);
1193 
1194 			if (BIT(dsd, 2))
1195 				set_dot(m_cpx + dd1, m_cpy + dd0, color);
1196 			else
1197 				set_dot(m_cpx + dd0, m_cpy + dd1, color);
1198 		}
1199 	}
1200 
1201 	if (dsd & 0x04)
1202 		m_cpx += DY + dd1_inc;
1203 	else
1204 		m_cpy += DY + dd1_inc;
1205 
1206 }
1207 
command_frct_exec()1208 void hd63484_device::command_frct_exec()
1209 {
1210 	int16_t X = (int16_t)m_pr[0];
1211 	int16_t Y = (int16_t)m_pr[1];
1212 
1213 	if (!BIT(m_cr, 10))
1214 	{
1215 		X -= m_cpx;
1216 		Y -= m_cpy;
1217 	}
1218 
1219 	int d0_inc = (X < 0) ? -1 : 1;
1220 	int d1_inc = (Y < 0) ? -1 : 1;
1221 
1222 	for(int16_t d1=0; d1!=Y+d1_inc; d1+=d1_inc)
1223 	{
1224 		for(int16_t d0=0; d0!=X+d0_inc; d0+=d0_inc)
1225 			set_dot(m_cpx + d0, m_cpy + d1, d0, d1);
1226 	}
1227 
1228 	m_cpy += (Y + d1_inc);
1229 }
1230 
command_ptn_exec()1231 void hd63484_device::command_ptn_exec()
1232 {
1233 	int16_t szx = ((m_pr[0] >> 0) & 0xff);
1234 	int16_t szy = ((m_pr[0] >> 8) & 0xff);
1235 	uint8_t sl_sd = (m_cr >> 8) & 0x0f;
1236 	int16_t px = 0;
1237 	int16_t py = 0;
1238 
1239 	for(int16_t d1=0; d1!=szy+1; d1++)
1240 	{
1241 		switch (sl_sd)
1242 		{
1243 			case 0x00: px = 0;    py = d1;   break;
1244 			case 0x01: px = -d1;  py = d1;   break;
1245 			case 0x02: py = 0;    px = -d1;  break;
1246 			case 0x03: px = -d1;  py = -d1;  break;
1247 			case 0x04: px = 0;    py = -d1;  break;
1248 			case 0x05: px = d1;   py = -d1;  break;
1249 			case 0x06: py = 0;    px = d1;   break;
1250 			case 0x07: px = d1;   py = d1;   break;
1251 			case 0x08: px = d1;   py = d1;   break;
1252 			case 0x09: px = 0;    py = d1;   break;
1253 			case 0x0a: px = -d1;  py = d1;   break;
1254 			case 0x0b: px = -d1;  py = 0;    break;
1255 			case 0x0c: px = -d1;  py = -d1;  break;
1256 			case 0x0d: px = 0;    py = -d1;  break;
1257 			case 0x0e: px = +d1;  py = -d1;  break;
1258 			case 0x0f: px = +d1;  py = 0;    break;
1259 		}
1260 
1261 		for(int16_t d0=0; d0!=szx+1; d0++)
1262 		{
1263 			set_dot(m_cpx + px, m_cpy + py, d0, d1);
1264 
1265 			switch (sl_sd)
1266 			{
1267 				case 0x00: px++;        break;
1268 				case 0x01: px++; py++;  break;
1269 				case 0x02: py++;        break;
1270 				case 0x03: px--; py++;  break;
1271 				case 0x04: px--;        break;
1272 				case 0x05: px--; py--;  break;
1273 				case 0x06: py--;        break;
1274 				case 0x07: px++; py--;  break;
1275 				case 0x08: px++;        break;
1276 				case 0x09: px++; py++;  break;
1277 				case 0x0a: py++;        break;
1278 				case 0x0b: px--; py++;  break;
1279 				case 0x0c: px--;        break;
1280 				case 0x0d: px--; py--;  break;
1281 				case 0x0e: py--;        break;
1282 				case 0x0f: px++; py--;  break;
1283 			}
1284 		}
1285 	}
1286 
1287 	switch (sl_sd)
1288 	{
1289 		case 0x00: m_cpy += (szy + 1); break;
1290 		case 0x01: m_cpx -= (szy + 1); m_cpy += (szy + 1); break;
1291 		case 0x02: m_cpx -= (szy + 1); break;
1292 		case 0x03: m_cpx -= (szy + 1); m_cpy -= (szy + 1); break;
1293 		case 0x04: m_cpy -= (szy + 1); break;
1294 		case 0x05: m_cpx += (szy + 1); m_cpy -= (szy + 1); break;
1295 		case 0x06: m_cpx += (szy + 1); break;
1296 		case 0x07: m_cpx += (szy + 1); m_cpy += (szy + 1); break;
1297 		case 0x08: m_cpx += (szy + 1); m_cpy += (szy + 1); break;
1298 		case 0x09: m_cpy += (szy + 1); break;
1299 		case 0x0a: m_cpx -= (szy + 1); m_cpy += (szy + 1); break;
1300 		case 0x0b: m_cpx -= (szy + 1); break;
1301 		case 0x0c: m_cpx -= (szy + 1); m_cpy -= (szy + 1); break;
1302 		case 0x0d: m_cpy -= (szy + 1); break;
1303 		case 0x0e: m_cpx += (szy + 1); m_cpy -= (szy + 1); break;
1304 		case 0x0f: m_cpx += (szy + 1); break;
1305 	}
1306 }
1307 
command_plg_exec()1308 void hd63484_device::command_plg_exec()
1309 {
1310 	int sx = m_cpx;
1311 	int sy = m_cpy;
1312 	int ex=0;
1313 	int ey=0;
1314 
1315 	for (int i = 0; i < m_dn; i++)
1316 	{
1317 		if (BIT(m_cr, 10))
1318 		{
1319 			ex = sx + (int16_t)m_pr[1 + i * 2];
1320 			ey = sy + (int16_t)m_pr[1 + i * 2 + 1];
1321 		}
1322 		else
1323 		{
1324 			ex = (int16_t)m_pr[1 + i * 2];
1325 			ey = (int16_t)m_pr[1 + i * 2 + 1];
1326 		}
1327 
1328 		draw_line(sx, sy, ex, ey);
1329 
1330 		sx = ex;
1331 		sy = ey;
1332 	}
1333 
1334 	if (m_cr & 0x2000)
1335 	{
1336 		// APLG/RPLG
1337 		draw_line(sx, sy, m_cpx, m_cpy);
1338 	}
1339 	else
1340 	{
1341 		// APLL/RPLL
1342 		m_cpx = ex;
1343 		m_cpy = ey;
1344 	}
1345 }
1346 
command_arc_exec()1347 void hd63484_device::command_arc_exec()
1348 {
1349 	int16_t xc = (int16_t)m_pr[0];
1350 	int16_t yc = (int16_t)m_pr[1];
1351 	int16_t xe = (int16_t)m_pr[2];
1352 	int16_t ye = (int16_t)m_pr[3];
1353 
1354 	if (BIT(m_cr, 10))
1355 	{
1356 		xc += m_cpx;
1357 		yc += m_cpy;
1358 		xe += m_cpx;
1359 		ye += m_cpy;
1360 	}
1361 
1362 	double r = sqrt(pow((double)(xc - m_cpx), 2) + pow((double)(yc - m_cpy), 2));
1363 	double s_angol = atan2((double)(m_cpy - yc), (double)(m_cpx - xc));
1364 	double e_angol = atan2((double)(ye - yc), (double)(xe - xc));
1365 	if (s_angol < 0)    s_angol += DEGREE_TO_RADIAN(360);
1366 	if (e_angol < 0)    e_angol += DEGREE_TO_RADIAN(360);
1367 
1368 	draw_ellipse(xc, yc, r, r, s_angol, e_angol, BIT(m_cr, 8));
1369 
1370 	m_cpx = xe;
1371 	m_cpy = ye;
1372 }
1373 
command_earc_exec()1374 void hd63484_device::command_earc_exec()
1375 {
1376 	uint16_t a = m_pr[0];
1377 	uint16_t b = m_pr[1];
1378 	int16_t xc = (int16_t)m_pr[2];
1379 	int16_t yc = (int16_t)m_pr[3];
1380 	int16_t xe = (int16_t)m_pr[4];
1381 	int16_t ye = (int16_t)m_pr[5];
1382 
1383 	if (BIT(m_cr, 10))
1384 	{
1385 		xc += m_cpx;
1386 		yc += m_cpy;
1387 		xe += m_cpx;
1388 		ye += m_cpy;
1389 	}
1390 
1391 	double r = sqrt(pow((double)(xc - m_cpx), 2) / a + pow((double)(yc - m_cpy), 2) / b);
1392 	double dx = sqrt((double)a);
1393 	double dy = sqrt((double)b);
1394 	double s_angol = atan2((double)(m_cpy - yc) / dy, (double)(m_cpx - xc) / dx);
1395 	double e_angol = atan2((double)(ye - yc) / dy, (double)(xe - xc) / dx);
1396 	if (s_angol < 0)    s_angol += DEGREE_TO_RADIAN(360);
1397 	if (e_angol < 0)    e_angol += DEGREE_TO_RADIAN(360);
1398 
1399 	draw_ellipse(xc, yc, r * dx, r * dy, s_angol, e_angol, BIT(m_cr, 8));
1400 
1401 	m_cpx = xe;
1402 	m_cpy = ye;
1403 }
1404 
process_fifo()1405 void hd63484_device::process_fifo()
1406 {
1407 	uint8_t data;
1408 
1409 	dequeue_w(&data);
1410 
1411 	if (m_sr & HD63484_SR_CED)
1412 	{
1413 		m_cr = (data & 0xff) << 8;
1414 		dequeue_w(&data);
1415 		m_cr |= data & 0xff;
1416 		m_param_ptr = 0;
1417 		m_sr &= ~HD63484_SR_CED;
1418 	}
1419 	else
1420 	{
1421 		m_pr[m_param_ptr] = (data & 0xff) << 8;
1422 		dequeue_w(&data);
1423 		m_pr[m_param_ptr] |= (data & 0xff);
1424 		m_param_ptr++;
1425 	}
1426 
1427 	switch (translate_command(m_cr))
1428 	{
1429 		case COMMAND_INVALID:
1430 			if (CMD_LOG)    logerror("HD63484 '%s': <invalid %04x>\n", tag(), m_cr);
1431 			printf("HD63484 '%s' Invalid Command Byte %02x\n", tag(), m_cr);
1432 			m_sr |= HD63484_SR_CER; // command error
1433 			command_end_seq();
1434 			break;
1435 
1436 		case COMMAND_ORG:
1437 			if (m_param_ptr == 2)
1438 			{
1439 				if (CMD_LOG)    logerror("HD63484 '%s': ORG 0x%04x, 0x%04x\n", tag(), m_pr[0], m_pr[1]);
1440 				m_org_dn = (m_pr[0] & 0xc000) >> 14;
1441 				m_org_dpa = ((m_pr[0] & 0xff) << 12) | ((m_pr[1] & 0xfff0) >> 4);
1442 				m_org_dpd = (m_pr[1] & 0xf);
1443 				m_cpx = m_cpy = 0;
1444 				command_end_seq();
1445 			}
1446 			break;
1447 
1448 		case COMMAND_WPR: // 0x0800 & ~0x1f
1449 			if (m_param_ptr == 1)
1450 			{
1451 				if (CMD_LOG)    logerror("HD63484 '%s': WPR (%d) 0x%04x\n", tag(), m_cr & 0x1f, m_pr[0]);
1452 				command_wpr_exec();
1453 				command_end_seq();
1454 			}
1455 			break;
1456 
1457 		case COMMAND_RPR:
1458 			if (m_param_ptr == 0)
1459 			{
1460 				if (CMD_LOG)    logerror("HD63484 '%s': RPR (%d)\n", tag(), m_cr & 0x1f);
1461 				uint16_t data = command_rpr_exec();
1462 				queue_r((data >> 8) & 0xff);
1463 				queue_r((data >> 0) & 0xff);
1464 				command_end_seq();
1465 			}
1466 			break;
1467 
1468 		case COMMAND_WPTN:
1469 			if(m_param_ptr == 1)
1470 			{
1471 				m_dn = m_pr[0]; // number of param words
1472 
1473 				//if(m_dn > 0x10 || m_dn == 0)
1474 				//  fatalerror("stop!\n");
1475 			}
1476 
1477 			if(m_param_ptr == (1 + m_dn))
1478 			{
1479 				if (CMD_LOG)    logerror("HD63484 '%s': WPTN (%d) %d", tag(), m_cr & 0x0f, m_pr[0]);
1480 
1481 				int pra = m_cr & 0xf;
1482 				for(int i=0; i<m_dn; i++)
1483 				{
1484 					if (CMD_LOG)    logerror(", 0x%04x", m_pr[1 + i]);
1485 					m_pram[(i + pra) & 0xf] = m_pr[1 + i];
1486 				}
1487 
1488 				if (CMD_LOG)    logerror("\n");
1489 				command_end_seq();
1490 			}
1491 			break;
1492 
1493 		case COMMAND_RPTN:
1494 			if(m_param_ptr == 1)
1495 			{
1496 				if (CMD_LOG)    logerror("HD63484 '%s': RPTN (%d) %d\n", tag(), m_cr & 0x0f, m_pr[0]);
1497 				command_end_seq();
1498 				fatalerror("HD63484 COMMAND_RPTN!\n");
1499 			}
1500 			break;
1501 
1502 		case COMMAND_DRD:
1503 			if (m_param_ptr == 2)
1504 			{
1505 				if (CMD_LOG)    logerror("HD63484 '%s': DRD %d, %d\n", tag(), m_pr[0], m_pr[1]);
1506 				command_end_seq();
1507 				fatalerror("HD63484 COMMAND_DRD!\n");
1508 			}
1509 			break;
1510 
1511 		case COMMAND_DWT:
1512 			if (m_param_ptr == 2)
1513 			{
1514 				if (CMD_LOG)    logerror("HD63484 '%s': DWT %d, %d\n", tag(), m_pr[0], m_pr[1]);
1515 				command_end_seq();
1516 				fatalerror("HD63484 COMMAND_DWT!\n");
1517 			}
1518 			break;
1519 
1520 		case COMMAND_DMOD:
1521 			if (m_param_ptr == 2)
1522 			{
1523 				if (CMD_LOG)    logerror("HD63484 '%s': DMOD (%d) %d, %d\n", tag(), m_cr & 0x03, m_pr[0], m_pr[1]);
1524 				command_end_seq();
1525 				fatalerror("HD63484 COMMAND_DMOD!\n");
1526 			}
1527 			break;
1528 
1529 		case COMMAND_RD:
1530 			if (m_param_ptr == 0)
1531 			{
1532 				if (CMD_LOG)    logerror("HD63484 '%s': RD\n", tag());
1533 				uint16_t data = readword(m_rwp[m_rwp_dn]);
1534 				queue_r((data >> 8) & 0xff);
1535 				queue_r((data >> 0) & 0xff);
1536 				m_rwp[m_rwp_dn]+=1;
1537 				m_rwp[m_rwp_dn]&=0xfffff;
1538 				command_end_seq();
1539 			}
1540 			break;
1541 
1542 		case COMMAND_WT:
1543 			if (m_param_ptr == 1)
1544 			{
1545 				if (CMD_LOG)    logerror("HD63484 '%s': WT 0x%04x\n", tag(), m_pr[0]);
1546 				writeword(m_rwp[m_rwp_dn], m_pr[0]);
1547 				m_rwp[m_rwp_dn]+=1;
1548 				m_rwp[m_rwp_dn]&=0xfffff;
1549 				command_end_seq();
1550 			}
1551 			break;
1552 
1553 		case COMMAND_MOD:
1554 			if(m_param_ptr == 1)
1555 			{
1556 				if (CMD_LOG)    logerror("HD63484 '%s': MOD (%d) 0x%04x\n", tag(), m_cr & 0x03, m_pr[0]);
1557 				uint16_t d = m_pr[0];
1558 				uint16_t data = readword(m_rwp[m_rwp_dn]);
1559 				uint16_t res = 0;
1560 
1561 				switch(m_cr & 0x03)
1562 				{
1563 					case 0: // replace
1564 						res = (data & ~m_mask) | (d & m_mask);
1565 						break;
1566 					case 1: // OR
1567 						res = (data & ~m_mask) | ((data | d) & m_mask);
1568 						break;
1569 					case 2: // AND
1570 						res = (data & ~m_mask) | ((data & d) & m_mask);
1571 						break;
1572 					case 3: // EOR
1573 						res = (data & ~m_mask) | ((data ^ d) & m_mask);
1574 						break;
1575 				}
1576 
1577 				writeword(m_rwp[m_rwp_dn], res);
1578 				command_end_seq();
1579 			}
1580 			break;
1581 
1582 		case COMMAND_CLR:
1583 		case COMMAND_SCLR:
1584 			if (m_param_ptr == 3)
1585 			{
1586 				if (CMD_LOG)
1587 				{
1588 					if (BIT(m_cr, 10))
1589 						logerror("HD63484 '%s': SCLR (%d) 0x%04x,  %d, %d\n", tag(), m_cr & 0x03, m_pr[0], (int16_t)m_pr[1], (int16_t)m_pr[2]);
1590 					else
1591 						logerror("HD63484 '%s': CLR 0x%04x, %d, %d\n", tag(), m_pr[0], (int16_t)m_pr[1], (int16_t)m_pr[2]);
1592 				}
1593 
1594 				command_clr_exec();
1595 				command_end_seq();
1596 			}
1597 			break;
1598 
1599 		case COMMAND_CPY:
1600 		case COMMAND_SCPY:
1601 			if (m_param_ptr == 4)
1602 			{
1603 				if (CMD_LOG)
1604 				{
1605 					if (BIT(m_cr, 12))
1606 						logerror("HD63484 '%s': SCPY (%d, %d, %d) 0x%x, 0x%x, %d, %d\n", tag(), BIT(m_cr, 11), (m_cr >> 8) & 0x07, m_cr & 0x07, m_pr[0] & 0xff, (m_pr[1]&0xfff0) >> 4, (int16_t)m_pr[2], (int16_t)m_pr[3]);
1607 					else
1608 						logerror("HD63484 '%s': CPY (%d, %d) 0x%x, 0x%x, %d, %d\n", tag(), BIT(m_cr, 11), (m_cr >> 8) & 0x07, m_pr[0] & 0xff, (m_pr[1]&0xfff0) >> 4, (int16_t)m_pr[2], (int16_t)m_pr[3]);
1609 				}
1610 
1611 				command_cpy_exec();
1612 				command_end_seq();
1613 			}
1614 			break;
1615 
1616 		case COMMAND_AMOVE:
1617 		case COMMAND_RMOVE:
1618 			if (m_param_ptr == 2)
1619 			{
1620 				if (CMD_LOG)    logerror("HD63484 '%s': %cMOVE %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', (int16_t)m_pr[0], (int16_t)m_pr[1]);
1621 				if (BIT(m_cr, 10))
1622 				{
1623 					m_cpx += (int16_t)m_pr[0];
1624 					m_cpy += (int16_t)m_pr[1];
1625 				}
1626 				else
1627 				{
1628 					m_cpx = (int16_t)m_pr[0];
1629 					m_cpy = (int16_t)m_pr[1];
1630 				}
1631 				command_end_seq();
1632 			}
1633 			break;
1634 
1635 		case COMMAND_RRCT:
1636 		case COMMAND_ARCT:
1637 			if (m_param_ptr == 2)
1638 			{
1639 				if (CMD_LOG)    logerror("HD63484 '%s': %cRTC (%d, %d, %d) %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (int16_t)m_pr[0], (int16_t)m_pr[1]);
1640 				command_rct_exec();
1641 				command_end_seq();
1642 			}
1643 			break;
1644 
1645 		case COMMAND_RLINE:
1646 		case COMMAND_ALINE:
1647 			if (m_param_ptr == 2)
1648 			{
1649 				if (CMD_LOG)    logerror("HD63484 '%s': %cLINE (%d, %d, %d) %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (int16_t)m_pr[0], (int16_t)m_pr[1]);
1650 				command_line_exec();
1651 				command_end_seq();
1652 			}
1653 			break;
1654 
1655 		case COMMAND_APLG:
1656 		case COMMAND_RPLG:
1657 		case COMMAND_APLL:
1658 		case COMMAND_RPLL:
1659 			if(m_param_ptr == 1)
1660 				m_dn = m_pr[0]; // number of param words
1661 
1662 			if(m_param_ptr == (1 + m_dn*2))
1663 			{
1664 				if (CMD_LOG)
1665 				{
1666 					logerror("HD63484 '%s': %cPL%c (%d, %d, %d) %d", tag(), BIT(m_cr, 10) ? 'R' : 'A', m_cr & 0x2000 ? 'G' : 'L', (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0]);
1667 					for (int i=0; i<m_dn; i++)
1668 						logerror(", %d, %d", (int16_t)m_pr[1 + i * 2], (int16_t)m_pr[1 + i * 2 + 1]);
1669 					logerror("\n");
1670 				}
1671 
1672 				command_plg_exec();
1673 				command_end_seq();
1674 			}
1675 			break;
1676 
1677 		case COMMAND_CRCL:
1678 			if(m_param_ptr == 1)
1679 			{
1680 				if (CMD_LOG)    logerror("HD63484 '%s': CRCL (%d, %d, %d, %d) %d\n", tag(), BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0]);
1681 				uint16_t r = m_pr[0] & 0x1fff;
1682 				draw_ellipse(m_cpx, m_cpy, r, r, DEGREE_TO_RADIAN(0), DEGREE_TO_RADIAN(360), BIT(m_cr, 8));
1683 				command_end_seq();
1684 			}
1685 			break;
1686 
1687 		case COMMAND_ELPS:
1688 			if(m_param_ptr == 3)
1689 			{
1690 				if (CMD_LOG)    logerror("HD63484 '%s': ELPS (%d, %d, %d, %d) %d, %d, %d\n", tag(), BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0], m_pr[1], m_pr[2]);
1691 				double dx = (double)m_pr[3];
1692 				double dy = sqrt(pow(dx, 2) / ((double)m_pr[0] / m_pr[1]));
1693 				draw_ellipse(m_cpx, m_cpy, dx, dy, DEGREE_TO_RADIAN(0), DEGREE_TO_RADIAN(360), BIT(m_cr, 8));
1694 				command_end_seq();
1695 			}
1696 			break;
1697 
1698 		case COMMAND_AARC:
1699 		case COMMAND_RARC:
1700 			if(m_param_ptr == 4)
1701 			{
1702 				if (CMD_LOG)    logerror("HD63484 '%s': %cARC (%d, %d, %d, %d) %d, %d, %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (int16_t)m_pr[0], (int16_t)m_pr[1], (int16_t)m_pr[2], (int16_t)m_pr[3]);
1703 				command_arc_exec();
1704 				command_end_seq();
1705 			}
1706 			break;
1707 
1708 		case COMMAND_AEARC:
1709 		case COMMAND_REARC:
1710 			if(m_param_ptr == 6)
1711 			{
1712 				if (CMD_LOG)    logerror("HD63484 '%s': %cEARC (%d, %d, %d, %d) %d, %d, %d, %d, %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0], m_pr[1], m_pr[2], m_pr[3], m_pr[4], m_pr[5]);
1713 				command_earc_exec();
1714 				command_end_seq();
1715 			}
1716 			break;
1717 
1718 		case COMMAND_AFRCT:
1719 		case COMMAND_RFRCT:
1720 			if (m_param_ptr == 2)
1721 			{
1722 				if (CMD_LOG)    logerror("HD63484 '%s': %cFRCT (%d, %d, %d) %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (int16_t)m_pr[0], (int16_t)m_pr[1]);
1723 
1724 				command_frct_exec();
1725 				command_end_seq();
1726 			}
1727 			break;
1728 
1729 		case COMMAND_PAINT:
1730 			if (m_param_ptr == 0)
1731 			{
1732 				if (CMD_LOG)    logerror("HD63484 '%s': PAINT (%d, %d, %d, %d)\n", tag(), BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07);
1733 				paint(m_cpx, m_cpy);
1734 				command_end_seq();
1735 			}
1736 			break;
1737 
1738 		case COMMAND_DOT:
1739 			if (m_param_ptr == 0)
1740 			{
1741 				if (CMD_LOG)    logerror("HD63484 '%s': DOT (%d, %d, %d)\n", tag(), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07);
1742 				set_dot(m_cpx, m_cpy, 0, 0);
1743 				command_end_seq();
1744 			}
1745 			break;
1746 
1747 		case COMMAND_PTN:
1748 			if (m_param_ptr == 1)
1749 			{
1750 				if (CMD_LOG)    logerror("HD63484 '%s': PTN (%d, %d, %d, %d, %d) 0x%04x\n", tag(), (m_cr >> 11) & 0x01, (m_cr >> 8) & 0x07, (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0]);
1751 				command_ptn_exec();
1752 				command_end_seq();
1753 			}
1754 			break;
1755 
1756 		case COMMAND_RGCPY:
1757 		case COMMAND_AGCPY:
1758 			if (m_param_ptr == 4)
1759 			{
1760 				if (CMD_LOG)    logerror("HD63484 '%s': %cGCPY (%d, %d, %d, %d, %d) %d, %d, %d, %d\n", tag(), BIT(m_cr, 12) ? 'R' : 'A', (m_cr >> 11) & 0x01, (m_cr >> 8) & 0x07, (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (int16_t)m_pr[0], (int16_t)m_pr[1], (int16_t)m_pr[2], (int16_t)m_pr[3]);
1761 
1762 				command_gcpy_exec();
1763 				command_end_seq();
1764 			}
1765 			break;
1766 
1767 		default:
1768 			printf("%04x\n",m_cr);
1769 			fatalerror("stop!\n");
1770 	}
1771 }
1772 
exec_abort_sequence()1773 void hd63484_device::exec_abort_sequence()
1774 {
1775 	fifo_w_clear();
1776 	fifo_r_clear();
1777 	m_sr = HD63484_SR_WFR | HD63484_SR_WFE | HD63484_SR_CED; // hard-set to 0x23
1778 }
1779 
video_registers_r(int offset)1780 uint16_t hd63484_device::video_registers_r(int offset)
1781 {
1782 	uint16_t res = (m_vreg[offset] << 8) | (m_vreg[offset+1] & 0xff);
1783 
1784 	switch(offset)
1785 	{
1786 		case 0x06:
1787 			res = m_dcr;
1788 			break;
1789 
1790 		case 0x80:
1791 			res = screen().vpos() & 0xfff; // Raster Count
1792 			break;
1793 
1794 		default:
1795 			if(LOG) printf("%s R\n",acrtc_regnames[m_ar/2]);
1796 			break;
1797 	}
1798 
1799 	return res;
1800 }
1801 
video_registers_w(int offset)1802 void hd63484_device::video_registers_w(int offset)
1803 {
1804 	uint16_t vreg_data;
1805 
1806 	vreg_data = (m_vreg[offset]<<8)|(m_vreg[offset+1]&0xff);
1807 
1808 	switch(offset)
1809 	{
1810 		case 0x00: // FIFO entry
1811 			queue_w((vreg_data & 0xff00) >> 8);
1812 			queue_w((vreg_data & 0x00ff) >> 0);
1813 			if(FIFO_LOG) printf("%s -> %04x\n",acrtc_regnames[m_ar/2],vreg_data);
1814 			process_fifo();
1815 			break;
1816 
1817 		case 0x02: // Command Entry
1818 
1819 			if(vreg_data & 0x8000) // abort sequence (ABT)
1820 				exec_abort_sequence();
1821 
1822 			/*
1823 			x--- ---- ---- ---- ABorT
1824 			-x-- ---- ---- ---- PauSE
1825 			...
1826 			---- -xxx ---- ---- Graphic Bit Mode (bpp)
1827 			---- ---- xxxx xxxx irq mask, directly correlated to sr
1828 			*/
1829 			m_ccr = vreg_data;
1830 			break;
1831 
1832 		case 0x04:
1833 			logerror("OMR: %04x\n", vreg_data);
1834 			m_omr = vreg_data;
1835 			break;
1836 
1837 		case 0x06:
1838 			m_dcr = vreg_data;
1839 			recompute_parameters();
1840 			break;
1841 
1842 		case 0x82: // Horizontal Sync Register
1843 			m_hc = ((vreg_data & 0xff00) >> 8) + 1;
1844 			m_hsw = vreg_data & 0x1f;
1845 			recompute_parameters();
1846 			break;
1847 		case 0x84: // Horizontal Display Register
1848 			m_hds = ((vreg_data & 0xff00) >> 8) + 1;
1849 			m_hdw = ((vreg_data & 0x00ff) >> 0) + 1;
1850 			recompute_parameters();
1851 			break;
1852 		case 0x92: // Horizontal Window Register
1853 			m_hws = ((vreg_data & 0xff00) >> 8) + 1;
1854 			m_hww = ((vreg_data & 0x00ff) >> 0) + 1;
1855 			recompute_parameters();
1856 			break;
1857 
1858 		case 0x86: // Vertical Sync Register
1859 			m_vc = (vreg_data & 0xfff);
1860 			recompute_parameters();
1861 			break;
1862 		case 0x88: // Vertical Display Register
1863 			m_vds = ((vreg_data & 0xff00) >> 8) + 1;
1864 			m_vsw = (vreg_data & 0x1f);
1865 			recompute_parameters();
1866 			break;
1867 		case 0x8a:  // Split Screen Width 1
1868 			m_sp[1] = vreg_data & 0x0fff;
1869 			recompute_parameters();
1870 			break;
1871 		case 0x8c:  // Split Screen Width 0
1872 			m_sp[0] = vreg_data & 0x0fff;
1873 			recompute_parameters();
1874 			break;
1875 		case 0x8e:  // Split Screen Width 2
1876 			m_sp[2] = vreg_data & 0x0fff;
1877 			recompute_parameters();
1878 			break;
1879 		case 0x94: // Vertical Window Register A
1880 			m_vws = (vreg_data & 0xfff) + 1;
1881 			recompute_parameters();
1882 			break;
1883 		case 0x96: // Vertical Window Register B
1884 			m_vww = (vreg_data & 0xfff);
1885 			recompute_parameters();
1886 			break;
1887 
1888 		case 0xc2: // Memory Width Register
1889 		case 0xca:
1890 		case 0xd2:
1891 		case 0xda:
1892 			m_mwr[(offset & 0x18) >> 3] = vreg_data & 0xfff; // pitch
1893 			m_mwr_chr[(offset & 0x18) >> 3] = (vreg_data & 0x8000) >> 15;
1894 			break;
1895 
1896 		case 0xc4: // Start Address Register
1897 		case 0xcc:
1898 		case 0xd4:
1899 		case 0xdc:
1900 			m_sar[(offset & 0x18) >> 3] = ((vreg_data & 0xf) << 16) | (m_sar[(offset & 0x18) >> 3] & 0xffff);
1901 			m_sda[(offset & 0x18) >> 3] = (vreg_data & 0x0f00) >> 8;
1902 			break;
1903 
1904 		case 0xc6: // Start Address Register
1905 		case 0xce:
1906 		case 0xd6:
1907 		case 0xde:
1908 			m_sar[(offset & 0x18) >> 3] = (vreg_data & 0xffff) | (m_sar[(offset & 0x18) >> 3] & 0xf0000);
1909 			break;
1910 
1911 		default:
1912 			if(LOG) printf("%s -> %04x\n",acrtc_regnames[m_ar/2],vreg_data);
1913 			break;
1914 	}
1915 }
1916 
read16(offs_t offset)1917 uint16_t hd63484_device::read16(offs_t offset)
1918 {
1919 	if (BIT(offset, 0))
1920 	{
1921 		// Read control register
1922 		uint16_t res;
1923 
1924 		if(m_ar == 0) // FIFO read
1925 		{
1926 			uint8_t data;
1927 
1928 			dequeue_r(&data);
1929 			res = (data & 0xff) << 8;
1930 			dequeue_r(&data);
1931 			res |= data & 0xff;
1932 		}
1933 		else
1934 			res = video_registers_r(m_ar);
1935 
1936 		inc_ar(2);
1937 
1938 		return res;
1939 	}
1940 	else
1941 	{
1942 		// Read status register
1943 		// kothello is coded so that upper byte of this should be 0xff (tests with jc opcode). Maybe it's just open bus?
1944 		return m_sr | 0xff00;
1945 	}
1946 }
1947 
write16(offs_t offset,uint16_t data)1948 void hd63484_device::write16(offs_t offset, uint16_t data)
1949 {
1950 	if (BIT(offset, 0))
1951 	{
1952 		// Write control register
1953 		m_vreg[m_ar] = (data & 0xff00) >> 8;
1954 		m_vreg[m_ar+1] = (data & 0xff);
1955 
1956 		video_registers_w(m_ar);
1957 
1958 		inc_ar(2);
1959 	}
1960 	else
1961 	{
1962 		// Write address register
1963 		m_ar = data & 0xfe;
1964 	}
1965 }
1966 
read8(offs_t offset)1967 uint8_t hd63484_device::read8(offs_t offset)
1968 {
1969 	if (BIT(offset, 0))
1970 	{
1971 		// Read control register
1972 		uint8_t res = 0xff;
1973 
1974 		if(m_ar < 2) // FIFO read
1975 			dequeue_r(&res);
1976 		else
1977 			res = video_registers_r(m_ar & 0xfe) >> (m_ar & 1 ? 0 : 8);
1978 
1979 		inc_ar(1);
1980 
1981 		return res;
1982 	}
1983 	else
1984 	{
1985 		// Read status register
1986 		return m_sr;
1987 	}
1988 }
1989 
write8(offs_t offset,uint8_t data)1990 void hd63484_device::write8(offs_t offset, uint8_t data)
1991 {
1992 	if (BIT(offset, 0))
1993 	{
1994 		// Write control register
1995 		m_vreg[m_ar] = data;
1996 
1997 		if(m_ar < 2) // FIFO write
1998 		{
1999 			queue_w(data);
2000 			if (m_ar & 1)
2001 				process_fifo();
2002 
2003 			m_ar ^= 1;
2004 		}
2005 		else
2006 			video_registers_w(m_ar & 0xfe);
2007 
2008 		inc_ar(1);
2009 	}
2010 	else
2011 	{
2012 		// Write address register
2013 		m_ar = data;
2014 	}
2015 }
2016 
device_start()2017 void hd63484_device::device_start()
2018 {
2019 	m_display_cb.resolve();
2020 
2021 	register_save_state();
2022 }
2023 
2024 //-------------------------------------------------
2025 //  device_reset - device-specific reset
2026 //-------------------------------------------------
2027 
device_reset()2028 void hd63484_device::device_reset()
2029 {
2030 	m_sr = HD63484_SR_CED | HD63484_SR_WFR | HD63484_SR_WFE;
2031 	m_ccr = m_omr = m_edg = m_dcr = m_hsw = 0;
2032 	m_hc = m_hds = m_hdw = m_hws = m_hww = 0;
2033 	m_vc = m_vws = m_vww = m_vds = m_vsw = 0;
2034 	m_sp[0] = m_sp[1] = m_sp[2] = 0;
2035 	m_cl0 = m_cl1 = 0;
2036 	m_xmin = m_ymin = m_xmax = m_ymax = 0;
2037 	m_ppx = m_pzcx = m_psx = m_pzx = m_pex = 0;
2038 	m_ppy = m_pzcy=  m_psy = m_pzy = m_pey = 0;
2039 	m_ar = m_cr = 0;
2040 	m_param_ptr = 0;
2041 	m_rwp_dn = 0;
2042 	m_org_dpa = 0;
2043 	m_org_dn = 0;
2044 	m_org_dpd = 0;
2045 	m_ccmp = 0;
2046 	m_mask = -1;
2047 	m_cpx = m_cpy = 0;
2048 	m_dn = 0;
2049 
2050 	memset(m_vreg, 0, sizeof(m_vreg));
2051 	memset(m_fifo, 0, sizeof(m_fifo));
2052 	memset(m_fifo_r, 0, sizeof(m_fifo_r));
2053 	memset(m_pr, 0, sizeof(m_pr));
2054 	memset(m_rwp, 0, sizeof(m_rwp));
2055 	memset(m_mwr, 0, sizeof(m_mwr));
2056 	memset(m_mwr_chr, 0, sizeof(m_mwr_chr));
2057 	memset(m_sar, 0, sizeof(m_sar));
2058 	memset(m_sda, 0, sizeof(m_sda));
2059 	memset(m_pram, 0, sizeof(m_pram));
2060 }
2061 
2062 //-------------------------------------------------
2063 //  draw_graphics_line -
2064 //-------------------------------------------------
2065 
draw_graphics_line(bitmap_ind16 & bitmap,const rectangle & cliprect,int vs,int y,int layer_n,bool active,bool ins_window)2066 void hd63484_device::draw_graphics_line(bitmap_ind16 &bitmap, const rectangle &cliprect, int vs, int y, int layer_n, bool active, bool ins_window)
2067 {
2068 	int bpp = get_bpp();
2069 	int ppw = 16 / bpp;
2070 	uint32_t mask = (1 << bpp) - 1;
2071 	uint32_t base_offs = m_sar[layer_n] + (y - vs) * m_mwr[layer_n] + m_external_skew;
2072 	uint32_t wind_offs = m_sar[3] + (y - m_vws) * m_mwr[3] + m_external_skew;
2073 	int step = (m_omr & 0x08) ? 2 : 1;
2074 	int gai = (m_omr>>4) & 0x07;
2075 	int ppmc = ppw * (1 << gai) / step;  // TODO: GAI > 3
2076 	int ws = m_hsw + m_hws + m_external_skew;
2077 
2078 	if (m_omr & 0x08)
2079 	{
2080 		/*
2081 		    According to the datasheet, in interleaved and superimposed modes:
2082 		    - HDW and HWW must be even
2083 		    - the relation between HDS and HWS must be even/even or odd/odd
2084 		*/
2085 
2086 		if (m_hww & 1)
2087 			ws += step;
2088 
2089 		if ((m_hws & 1) ^ (m_hds & 1))
2090 			wind_offs++;
2091 	}
2092 
2093 	for(int x=cliprect.min_x; x<=cliprect.max_x; x+=ppw)
2094 	{
2095 		uint16_t data = 0;
2096 		if (ins_window && x >= ws * ppmc && x < (ws + m_hww) * ppmc)
2097 		{
2098 			data = readword(wind_offs);
2099 			wind_offs++;
2100 		}
2101 		else if (active)
2102 			data = readword(base_offs);
2103 
2104 		for (int b=0; b<ppw; b++)
2105 		{
2106 			int px = x + b;
2107 			if (!m_display_cb.isnull())
2108 				m_display_cb(bitmap, cliprect, y, px, data & mask);
2109 			else if (cliprect.contains(px, y))
2110 				bitmap.pix(y, px) = data & mask;
2111 
2112 			data >>= bpp;
2113 		}
2114 
2115 		base_offs++;
2116 	}
2117 }
2118 
2119 //-------------------------------------------------
2120 //  update_screen -
2121 //-------------------------------------------------
2122 
update_screen(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)2123 uint32_t hd63484_device::update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
2124 {
2125 	int l0 = cliprect.min_y + (BIT(m_dcr, 13) ? m_sp[0] : 0);
2126 	int l1 = l0 + m_sp[1];
2127 	int l2 = l1 + (BIT(m_dcr, 11) ? m_sp[2] : 0);
2128 
2129 	if(m_omr & 0x4000)
2130 	{
2131 		for(int y=cliprect.min_y; y<=cliprect.max_y; y++)
2132 		{
2133 			bool ins_window = BIT(m_dcr, 9) && y >= m_vws && y < m_vws+m_vww;
2134 
2135 			if (BIT(m_dcr, 13) && y >= cliprect.min_y && y < l0)
2136 				draw_graphics_line(bitmap, cliprect, cliprect.min_y, y, 0, BIT(m_dcr, 12), ins_window);
2137 			else if (y >= l0 && y < l1)
2138 				draw_graphics_line(bitmap, cliprect, l0, y, 1, BIT(m_dcr, 14), ins_window);
2139 			else if (BIT(m_dcr, 11) && y >= l1 && y < l2)
2140 				draw_graphics_line(bitmap, cliprect, l1, y, 2, BIT(m_dcr, 10), ins_window);
2141 		}
2142 	}
2143 	return 0;
2144 }
2145 
register_save_state()2146 void hd63484_device::register_save_state()
2147 {
2148 	save_item(NAME(m_ar));
2149 	save_item(NAME(m_vreg));
2150 	save_item(NAME(m_sr));
2151 	save_item(NAME(m_fifo));
2152 	save_item(NAME(m_fifo_ptr));
2153 	save_item(NAME(m_fifo_r));
2154 	save_item(NAME(m_fifo_r_ptr));
2155 	save_item(NAME(m_cr));
2156 	save_item(NAME(m_pr));
2157 	save_item(NAME(m_param_ptr));
2158 	save_item(NAME(m_rwp));
2159 	save_item(NAME(m_rwp_dn));
2160 	save_item(NAME(m_org_dpa));
2161 	save_item(NAME(m_org_dn));
2162 	save_item(NAME(m_org_dpd));
2163 	save_item(NAME(m_cl0));
2164 	save_item(NAME(m_cl1));
2165 	save_item(NAME(m_ccmp));
2166 	save_item(NAME(m_mask));
2167 	save_item(NAME(m_cpx));
2168 	save_item(NAME(m_cpy));
2169 	save_item(NAME(m_mwr));
2170 	save_item(NAME(m_mwr_chr));
2171 	save_item(NAME(m_sar));
2172 	save_item(NAME(m_sda));
2173 	save_item(NAME(m_pram));
2174 	save_item(NAME(m_dn));
2175 	save_item(NAME(m_ccr));
2176 	save_item(NAME(m_omr));
2177 	save_item(NAME(m_edg));
2178 	save_item(NAME(m_dcr));
2179 	save_item(NAME(m_hc));
2180 	save_item(NAME(m_hds));
2181 	save_item(NAME(m_hdw));
2182 	save_item(NAME(m_hws));
2183 	save_item(NAME(m_hww));
2184 	save_item(NAME(m_sp));
2185 	save_item(NAME(m_hsw));
2186 	save_item(NAME(m_vc));
2187 	save_item(NAME(m_vws));
2188 	save_item(NAME(m_vww));
2189 	save_item(NAME(m_vds));
2190 	save_item(NAME(m_vsw));
2191 	save_item(NAME(m_ppy));
2192 	save_item(NAME(m_pzcy));
2193 	save_item(NAME(m_ppx));
2194 	save_item(NAME(m_pzcx));
2195 	save_item(NAME(m_psx));
2196 	save_item(NAME(m_pex));
2197 	save_item(NAME(m_pzx));
2198 	save_item(NAME(m_psy));
2199 	save_item(NAME(m_pzy));
2200 	save_item(NAME(m_pey));
2201 	save_item(NAME(m_xmin));
2202 	save_item(NAME(m_ymin));
2203 	save_item(NAME(m_xmax));
2204 	save_item(NAME(m_ymax));
2205 }
2206