1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /******************************************************************************
4 *
5 * Sony PlayStation 2 VU1 interface device skeleton
6 *
7 * To Do:
8 * Everything
9 *
10 * Note: STAT mode bit twiddling is a total guess
11 *
12 */
13
14 #include <cmath>
15 #include "emu.h"
16 #include "ps2vif1.h"
17 #include <cmath>
18
19 #include "video/ps2gif.h"
20
21 DEFINE_DEVICE_TYPE(SONYPS2_VIF1, ps2_vif1_device, "ps2vif1", "PlayStation 2 VIF1")
22
23 /*static*/ const size_t ps2_vif1_device::BUFFER_SIZE = 0x40;
24 /*static*/ const uint32_t ps2_vif1_device::FORMAT_SIZE[] = {
25 1, 1, 1, 1,
26 2, 1, 1, 1,
27 3, 2, 1, 1,
28 4, 2, 1, 2
29 };
30
ps2_vif1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)31 ps2_vif1_device::ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
32 : device_t(mconfig, SONYPS2_VIF1, tag, owner, clock)
33 , device_execute_interface(mconfig, *this)
34 , m_gs(*this, finder_base::DUMMY_TAG)
35 , m_vu1(*this, finder_base::DUMMY_TAG)
36 {
37 }
38
~ps2_vif1_device()39 ps2_vif1_device::~ps2_vif1_device()
40 {
41 }
42
device_start()43 void ps2_vif1_device::device_start()
44 {
45 set_icountptr(m_icount);
46
47 save_item(NAME(m_icount));
48
49 save_item(NAME(m_buffer));
50 save_item(NAME(m_curr));
51 save_item(NAME(m_end));
52
53 save_item(NAME(m_status));
54 save_item(NAME(m_control));
55 save_item(NAME(m_err));
56 save_item(NAME(m_mark));
57 save_item(NAME(m_cycle));
58 save_item(NAME(m_mode));
59 save_item(NAME(m_num));
60 save_item(NAME(m_mask));
61 save_item(NAME(m_code));
62 save_item(NAME(m_itops));
63 save_item(NAME(m_base));
64 save_item(NAME(m_offset));
65 save_item(NAME(m_tops));
66 save_item(NAME(m_itop));
67 save_item(NAME(m_top));
68
69 save_item(NAME(m_row_fill));
70 save_item(NAME(m_col_fill));
71
72 save_item(NAME(m_data_needed));
73 save_item(NAME(m_data_index));
74 save_item(NAME(m_command));
75 save_item(NAME(m_alignment));
76
77 save_item(NAME(m_mpg_count));
78 save_item(NAME(m_mpg_addr));
79 save_item(NAME(m_mpg_insn));
80
81 save_item(NAME(m_unpack_count));
82 save_item(NAME(m_unpack_addr));
83 save_item(NAME(m_unpack_last));
84 save_item(NAME(m_unpack_bits_remaining));
85 save_item(NAME(m_unpack_signed));
86 save_item(NAME(m_unpack_add_tops));
87 save_item(NAME(m_unpack_format));
88 }
89
device_reset()90 void ps2_vif1_device::device_reset()
91 {
92 m_icount = 0;
93
94 memset(m_buffer, 0, sizeof(uint32_t) * BUFFER_SIZE);
95 m_curr = 0;
96 m_end = 0;
97
98 m_status = 0;
99 m_control = 0;
100 m_err = 0;
101 m_mark = 0;
102 m_cycle = 0;
103 m_mode = 0;
104 m_num = 0;
105 m_mask = 0;
106 m_code = 0;
107 m_itops = 0;
108 m_base = 0;
109 m_offset = 0;
110 m_tops = 0;
111 m_itop = 0;
112 m_top = 0;
113
114 memset(m_row_fill, 0, sizeof(uint32_t) * 4);
115 memset(m_col_fill, 0, sizeof(uint32_t) * 4);
116
117 m_data_needed = 0;
118 m_data_index = 0;
119 m_command = 0;
120 m_alignment = 0;
121
122 m_mpg_count = 0;
123 m_mpg_addr = 0;
124 m_mpg_insn = 0;
125
126 m_unpack_count = 0;
127 m_unpack_addr = 0;
128 m_unpack_last = 0;
129 m_unpack_bits_remaining = 0;
130 m_unpack_signed = false;
131 m_unpack_add_tops = false;
132 m_unpack_format = FMT_S32;
133 }
134
regs_r(offs_t offset)135 uint32_t ps2_vif1_device::regs_r(offs_t offset)
136 {
137 uint32_t ret = 0;
138 switch (offset)
139 {
140 case 0x00/4:
141 ret = m_status;
142 logerror("%s: Read: VIF1_STAT (%08x)\n", machine().describe_context(), ret);
143 break;
144 case 0x10/4:
145 ret = m_control;
146 logerror("%s: Read: VIF1_FBRST (%08x)\n", machine().describe_context(), ret);
147 break;
148 case 0x20/4:
149 ret = m_err;
150 logerror("%s: Read: VIF1_ERR (%08x)\n", machine().describe_context(), ret);
151 break;
152 case 0x30/4:
153 ret = m_mark;
154 logerror("%s: Read: VIF1_MARK (%08x)\n", machine().describe_context(), ret);
155 break;
156 case 0x40/4:
157 ret = m_cycle;
158 logerror("%s: Read: VIF1_CYCLE (%08x)\n", machine().describe_context(), ret);
159 break;
160 case 0x50/4:
161 ret = m_mode;
162 logerror("%s: Read: VIF1_MODE (%08x)\n", machine().describe_context(), ret);
163 break;
164 case 0x60/4:
165 ret = m_num;
166 logerror("%s: Read: VIF1_NUM (%08x)\n", machine().describe_context(), ret);
167 break;
168 case 0x70/4:
169 ret = m_mask;
170 logerror("%s: Read: VIF1_MASK (%08x)\n", machine().describe_context(), ret);
171 break;
172 case 0x80/4:
173 ret = m_code;
174 logerror("%s: Read: VIF1_CODE (%08x)\n", machine().describe_context(), ret);
175 break;
176 case 0x90/4:
177 ret = m_itops;
178 logerror("%s: Read: VIF1_ITOPS (%08x)\n", machine().describe_context(), ret);
179 break;
180 case 0xa0/4:
181 ret = m_base;
182 logerror("%s: Read: VIF1_BASE (%08x)\n", machine().describe_context(), ret);
183 break;
184 case 0xb0/4:
185 ret = m_offset;
186 logerror("%s: Read: VIF1_OFST (%08x)\n", machine().describe_context(), ret);
187 break;
188 case 0xc0/4:
189 ret = m_tops;
190 logerror("%s: Read: VIF1_TOPS (%08x)\n", machine().describe_context(), ret);
191 break;
192 case 0xd0/4:
193 ret = m_itop;
194 logerror("%s: Read: VIF1_ITOP (%08x)\n", machine().describe_context(), ret);
195 break;
196 case 0xe0/4:
197 ret = m_top;
198 logerror("%s: Read: VIF1_TOP (%08x)\n", machine().describe_context(), ret);
199 break;
200 case 0x100/4:
201 ret = m_row_fill[0];
202 logerror("%s: Read: VIF1_R0 (%08x)\n", machine().describe_context(), ret);
203 break;
204 case 0x110/4:
205 ret = m_row_fill[1];
206 logerror("%s: Read: VIF1_R1 (%08x)\n", machine().describe_context(), ret);
207 break;
208 case 0x120/4:
209 ret = m_row_fill[2];
210 logerror("%s: Read: VIF1_R2 (%08x)\n", machine().describe_context(), ret);
211 break;
212 case 0x130/4:
213 ret = m_row_fill[3];
214 logerror("%s: Read: VIF1_R3 (%08x)\n", machine().describe_context(), ret);
215 break;
216 case 0x140/4:
217 ret = m_col_fill[0];
218 logerror("%s: Read: VIF1_C0 (%08x)\n", machine().describe_context(), ret);
219 break;
220 case 0x150/4:
221 ret = m_col_fill[1];
222 logerror("%s: Read: VIF1_C1 (%08x)\n", machine().describe_context(), ret);
223 break;
224 case 0x160/4:
225 ret = m_col_fill[2];
226 logerror("%s: Read: VIF1_C2 (%08x)\n", machine().describe_context(), ret);
227 break;
228 case 0x170/4:
229 ret = m_col_fill[3];
230 logerror("%s: Read: VIF1_C3 (%08x)\n", machine().describe_context(), ret);
231 break;
232 default:
233 logerror("%s: Read: Unknown (%08x)\n", machine().describe_context(), 0x10003c00 + (offset << 2));
234 break;
235 }
236 return ret;
237 }
238
regs_w(offs_t offset,uint32_t data)239 void ps2_vif1_device::regs_w(offs_t offset, uint32_t data)
240 {
241 logerror("%s: Write: Unknown %08x = %08x\n", machine().describe_context(), 0x10003c00 + (offset << 2), data);
242 }
243
mmio_r(offs_t offset)244 uint64_t ps2_vif1_device::mmio_r(offs_t offset)
245 {
246 uint64_t ret = 0ULL;
247 if (offset)
248 {
249 logerror("%s: mmio_r [127..64]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
250 }
251 else
252 {
253 logerror("%s: mmio_r [63..0]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
254 }
255 return ret;
256 }
257
mmio_w(offs_t offset,uint64_t data)258 void ps2_vif1_device::mmio_w(offs_t offset, uint64_t data)
259 {
260 if (offset)
261 {
262 logerror("%s: mmio_w [127..64]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
263 fifo_push((uint32_t)data);
264 fifo_push((uint32_t)(data >> 32));
265 }
266 else
267 {
268 logerror("%s: mmio_w [63..0]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
269 fifo_push((uint32_t)data);
270 fifo_push((uint32_t)(data >> 32));
271 }
272 }
273
274
dma_write(const uint64_t hi,const uint64_t lo)275 void ps2_vif1_device::dma_write(const uint64_t hi, const uint64_t lo)
276 {
277 //logerror("%s: dma_write: %08x%08x%08x%08x\n", machine().describe_context(), (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
278 fifo_push((uint32_t)(lo >> 32));
279 fifo_push((uint32_t)lo);
280 fifo_push((uint32_t)(hi >> 32));
281 fifo_push((uint32_t)hi);
282 }
283
tag_write(uint32_t * data)284 void ps2_vif1_device::tag_write(uint32_t *data)
285 {
286 logerror("%s: tag_write: %08x%08x\n", machine().describe_context(), data[2], data[3]);
287 fifo_push(data[2]);
288 fifo_push(data[3]);
289 }
290
fifo_push(uint32_t data)291 void ps2_vif1_device::fifo_push(uint32_t data)
292 {
293 if (m_end >= BUFFER_SIZE)
294 {
295 printf("FIFO overflow :(\n");
296 return;
297 }
298
299 m_buffer[m_end++] = data;
300
301 m_status &= ~0x1f000000;
302 m_status |= ((m_end - m_curr) >> 2) << 24;
303 logerror("%s: Pushing %08x onto FIFO, depth is now %d, status is now %08x\n", machine().describe_context(), data, m_end - m_curr, m_status);
304 }
305
fifo_pop()306 uint32_t ps2_vif1_device::fifo_pop()
307 {
308 m_alignment = (m_alignment + 1) & 3;
309
310 if (m_curr >= m_end)
311 {
312 return 0;
313 }
314
315 const uint32_t ret = m_buffer[m_curr++];
316 if (m_curr >= m_end)
317 {
318 m_curr = 0;
319 m_end = 0;
320 }
321
322 m_status &= ~0x1f000000;
323 m_status |= ((m_end - m_curr) >> 2) << 24;
324 logerror("%s: Popping %08x from FIFO, depth is now %d, status is now %08x\n", machine().describe_context(), ret, m_end - m_curr, m_status);
325
326 return ret;
327 }
328
execute_run()329 void ps2_vif1_device::execute_run()
330 {
331 while (m_icount > 0)
332 {
333 if (m_status & (STAT_E_WAIT | STAT_GS_WAIT | STAT_STALL_STOP | STAT_STALL_FBRK | STAT_STALL_INT))
334 {
335 m_icount = 0;
336 break;
337 }
338
339 switch (m_status & STAT_MODE_MASK)
340 {
341 case STAT_MODE_IDLE:
342 if (fifo_depth())
343 {
344 m_code = fifo_pop();
345 logerror("%s: New VIFcode: %08x\n", machine().describe_context(), m_code);
346 }
347 else
348 {
349 //logerror("%s: Nothing in FIFO, idle\n", machine().describe_context());
350 m_icount = 0;
351 break;
352 }
353 // Intentional fall-through
354 case STAT_MODE_DECODE:
355 decode_vifcode();
356 break;
357 case STAT_MODE_WAIT:
358 if (fifo_depth() < m_data_needed)
359 {
360 m_icount = 0;
361 break;
362 }
363 // Intentional fall-through
364 case STAT_MODE_DATA:
365 transfer_vifcode_data();
366 break;
367 }
368 }
369 }
370
transfer_vifcode_data()371 void ps2_vif1_device::transfer_vifcode_data()
372 {
373 m_status &= ~STAT_MODE_MASK;
374 if (fifo_depth() < m_data_needed)
375 {
376 //logerror("%s: transfer: We need %d but only have %d, waiting\n", machine().describe_context(), m_data_needed, fifo_depth());
377 m_status |= STAT_MODE_WAIT;
378 m_icount = 0;
379 return;
380 }
381
382 switch (m_command)
383 {
384 case 0x20: /* STMASK */
385 m_mask = fifo_pop();
386 logerror("%s: STMASK: %08x\n", machine().describe_context(), m_mask);
387 m_data_needed = 0;
388 break;
389 case 0x30: /* STROW */
390 m_row_fill[m_data_index] = fifo_pop();
391 logerror("%s: STMASK: %08x\n", machine().describe_context(), m_row_fill[m_data_index]);
392 m_data_needed--;
393 break;
394 case 0x31: /* STCOL */
395 m_col_fill[m_data_index] = fifo_pop();
396 logerror("%s: STMASK: %08x\n", machine().describe_context(), m_col_fill[m_data_index]);
397 m_data_needed--;
398 break;
399 case 0x4a: /* MPG */
400 transfer_mpg();
401 break;
402 default:
403 if ((m_command & 0x60) == 0x60)
404 {
405 logerror("%s: Unpack: %02x\n", machine().describe_context(), m_command);
406 transfer_unpack();
407 }
408 else
409 {
410 logerror("%s: Unknown command: %02x\n", machine().describe_context(), m_command);
411 }
412 break;
413 }
414
415 if (m_data_needed)
416 {
417 if (fifo_depth() == 0)
418 {
419 m_status |= STAT_MODE_WAIT;
420 m_icount = 0;
421 }
422 else
423 {
424 m_status |= STAT_MODE_DATA;
425 m_icount--;
426 }
427 }
428 else if (fifo_depth() > 0)
429 {
430 m_code = fifo_pop();
431 logerror("%s: New VIFcode: %08x\n", machine().describe_context(), m_code);
432 m_status |= STAT_MODE_DECODE;
433 m_icount--;
434 }
435 else
436 {
437 m_status |= STAT_MODE_IDLE;
438 m_icount = 0;
439 }
440 }
441
transfer_unpack()442 void ps2_vif1_device::transfer_unpack()
443 {
444 switch (m_unpack_format)
445 {
446 case FMT_V4_32:
447 //logerror("%s: Unpacking V4-32.\n", machine().describe_context());
448 for (int element = 0; element < 4; element++)
449 {
450 const uint32_t data = fifo_pop();
451 m_vu1->write_vu_mem(m_unpack_addr, data);
452 m_unpack_addr += 4;
453 m_unpack_count--;
454 }
455 break;
456 default:
457 logerror("%s: Unsupported unpack format: %02x\n", machine().describe_context(), m_unpack_format);
458 break;
459 }
460
461 if (m_unpack_count > 0)
462 {
463 m_data_needed = FORMAT_SIZE[m_unpack_format] - (m_unpack_bits_remaining ? 1 : 0);
464 }
465 else
466 {
467 m_data_needed = 0;
468 }
469 }
470
transfer_mpg()471 void ps2_vif1_device::transfer_mpg()
472 {
473 while (m_data_needed > 2)
474 {
475 fifo_pop();
476 m_data_needed--;
477 }
478
479 m_mpg_insn = (uint64_t)fifo_pop() << 32;
480 m_mpg_insn |= fifo_pop();
481 m_mpg_count--;
482
483 m_vu1->write_micro_mem(m_mpg_addr, m_mpg_insn);
484 logerror("%s: MPG, VU insn: %08x = %08x%08x, %d remaining\n", machine().describe_context(), m_mpg_addr, (uint32_t)(m_mpg_insn >> 32), (uint32_t)m_mpg_insn, m_mpg_count);
485
486 m_mpg_addr += 8;
487 m_data_needed = m_mpg_count ? 2 : 0;
488 }
489
decode_vifcode()490 void ps2_vif1_device::decode_vifcode()
491 {
492 bool trigger_interrupt = BIT(m_code, 31);
493 m_command = (m_code >> 24) & 0x7f;
494 m_status &= ~STAT_MODE_MASK;
495
496 switch (m_command)
497 {
498 case 0x00: /* NOP */
499 logerror("%s: NOP\n", machine().describe_context());
500 break;
501 case 0x01: /* STCYCL */
502 m_cycle = (uint16_t)m_code;
503 logerror("%s: STCYCL: %04x\n", machine().describe_context(), (uint16_t)m_cycle);
504 break;
505 case 0x02: /* OFFSET */
506 m_offset = m_code & 0x3ff;
507 logerror("%s: OFFSET: %03x\n", machine().describe_context(), m_offset);
508 break;
509 case 0x03: /* BASE */
510 m_base = m_code & 0x3ff;
511 logerror("%s: BASE: %03x\n", machine().describe_context(), m_base);
512 break;
513 case 0x04: /* ITOP */
514 m_itops = m_code & 0x3ff;
515 logerror("%s: ITOP: %03x\n", machine().describe_context(), m_itops);
516 break;
517 case 0x05: /* STMOD */
518 m_mode = m_code & 3;
519 logerror("%s: MODE: %03x\n", machine().describe_context(), m_mode);
520 break;
521 case 0x06: /* MSKPATH3 */
522 m_gs->interface()->set_path3_mask(BIT(m_code, 15));
523 logerror("%s: MSKPATH3: %d\n", machine().describe_context(), BIT(m_code, 15));
524 break;
525 case 0x07: /* Oh hi, MARK */
526 m_mark = (uint16_t)m_code;
527 logerror("%s: MARK: %04x\n", machine().describe_context(), (uint16_t)m_mark);
528 break;
529 case 0x14: /* MSCAL */
530 logerror("%s: MSCAL %04x\n", machine().describe_context(), (uint16_t)m_code);
531 if (m_vu1->running())
532 {
533 m_icount--;
534 return;
535 }
536 else
537 {
538 m_vu1->start((uint16_t)m_code);
539 }
540 break;
541 case 0x20: /* STMASK */
542 m_data_needed = 1;
543 m_data_index = 0;
544 logerror("%s: STMASK\n", machine().describe_context());
545 break;
546 case 0x30: /* STROW */
547 m_data_needed = 4;
548 m_data_index = 0;
549 logerror("%s: STROW\n", machine().describe_context());
550 break;
551 case 0x31: /* STCOL */
552 m_data_needed = 4;
553 m_data_index = 0;
554 logerror("%s: STCOL\n", machine().describe_context());
555 break;
556 case 0x4a: /* MPG */
557 m_data_needed = 2 + (m_alignment & 1);
558 m_data_index = 0;
559 m_mpg_count = (m_code >> 16) & 0xff;
560 if (!m_mpg_count)
561 m_mpg_count = 0x100;
562 m_mpg_addr = m_code & 0xffff;
563 logerror("%s: MPG\n", machine().describe_context());
564 break;
565 default:
566 if ((m_command & 0x60) == 0x60)
567 { /* UNPACK */
568 m_unpack_count = calculate_unpack_count();
569 m_unpack_signed = BIT(m_code, 14);
570 m_unpack_add_tops = BIT(m_code, 15);
571 m_unpack_format = (uint8_t)(m_command & 0xf);
572 m_data_needed = FORMAT_SIZE[m_unpack_format];
573 logerror("%s: UNPACK (%08x), count %d\n", machine().describe_context(), m_code, m_unpack_count);
574 }
575 else
576 { /* unknown */
577 logerror("%s: decode_vifcode: Unknown command %02x\n", machine().describe_context(), m_command);
578 }
579 break;
580 }
581
582 if (m_data_needed > 0)
583 {
584 if (fifo_depth())
585 {
586 m_status |= STAT_MODE_DATA;
587 m_icount--;
588 }
589 else
590 {
591 m_status |= STAT_MODE_WAIT;
592 m_icount = 0;
593 }
594 }
595 else if (fifo_depth())
596 {
597 m_code = fifo_pop();
598 m_status |= STAT_MODE_DECODE;
599 m_icount--;
600 }
601 else
602 {
603 m_status |= STAT_MODE_IDLE;
604 m_icount = 0;
605 }
606
607 if (trigger_interrupt)
608 {
609 //printf("******************\n");
610 }
611 }
612
calculate_unpack_count()613 uint32_t ps2_vif1_device::calculate_unpack_count()
614 {
615 const uint32_t wl = (m_cycle >> 8) & 0xff;
616 const uint32_t cl = m_cycle & 0xff;
617 const uint32_t vl = m_command & 3;
618 const uint32_t vn = (m_command >> 2) & 3;
619
620 uint32_t num = (m_code >> 16) & 0xff;
621 if (wl > cl)
622 {
623 const uint32_t mod = num % wl;
624 num = cl * (num / wl) + ((mod > cl) ? cl : mod);
625 }
626
627 return (uint32_t)std::ceil(((32 >> vl) * (vn + 1) * num) / 32.0f);
628 }
629