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