2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
13 void UPD71071::initialize()
16 _SINGLE_MODE_DMA = osd->check_feature(_T("SINGLE_MODE_DMA"));
17 for(int i = 0; i < 4; i++) {
18 dma[i].areg = dma[i].bareg = 0;
19 dma[i].creg = dma[i].bcreg = 0;
22 if(d_debugger != NULL) {
23 d_debugger->set_device_name(_T("Debugger (uPD71071 DMAC)"));
24 d_debugger->set_context_mem(this);
25 d_debugger->set_context_io(vm->dummy);
28 for(int i = 0; i < 4; i++) {
29 inputs_ube[i] = false; // This is input, maybe not initialize at reset().
33 void UPD71071::reset()
35 for(int i = 0; i < 4; i++) {
37 dma[i].is_16bit = false;
39 dma[i].endreq = false;
42 b16 = selch = base = 0;
51 void UPD71071::write_io16(uint32_t addr, uint32_t data)
58 dma[selch].creg = data & 0xffff;
60 dma[selch].bcreg = data & 0xffff;
65 _d.d = dma[selch].areg;
67 dma[selch].areg = _d.d;
69 _d.d = dma[selch].bareg;
71 dma[selch].bareg = _d.d;
75 _d.d = dma[selch].areg;
77 dma[selch].areg = _d.d;
79 _d.d = dma[selch].bareg;
81 dma[selch].bareg = _d.d;
87 write_io8(addr & 0x0e, data);
88 // write_io8(addr, data);
92 // write_io8(addr, data);
93 //// write_io8((addr & 0x0e) + 0, data & 0xff);
94 //// write_io8((addr & 0x0e) + 1, (data >> 8) & 0xff);
99 void UPD71071::write_io8(uint32_t addr, uint32_t data)
103 switch(addr & 0x0f) {
109 for(int i = 0; i < 4; i++) {
111 dma[i].is_16bit = false;
113 dma[i].endreq = false;
130 dma[selch].bcreg = manipulate_a_byte_from_word_le(dma[selch].bcreg, (addr & 0x0f) - 2, data);
132 dma[selch].creg = manipulate_a_byte_from_word_le(dma[selch].creg, (addr & 0x0f) - 2, data);
134 dma[selch].end = false; // OK?
135 dma[selch].endreq = false; // OK?
141 dma[selch].bareg = manipulate_a_byte_from_dword_le(dma[selch].bareg, (addr & 0x0f) - 4, data);
143 dma[selch].areg = manipulate_a_byte_from_dword_le(dma[selch].areg, (addr & 0x0f) - 4, data);
147 cmd = (cmd & 0xff00) | (data & 0x00ff);
150 cmd = (cmd & 0xff) | ((data & 0x00ff) << 8);
153 dma[selch].mode = data;
154 //dma[selch].is_16bit = ((data & 1) != 0) ? true : false;
155 if((data & 0x04) == 0) {
156 dma[selch].end = false;
157 dma[selch].endreq = false;
163 for(int _ch = 0; _ch < 4; _ch++) {
164 if((sreq & (1 << _ch)) != 0) {
165 //if((dma[_ch].mode & 0xc0) == 0x40) { // Single
166 do_dma_per_channel(_ch);
173 for(int _ch = 0; _ch < 4; _ch++) {
174 if(((sreq | req) & (1 << _ch)) != 0) {
175 if((mask & (1 << _ch)) == 0) {
176 do_dma_per_channel(_ch);
185 uint32_t UPD71071::read_io16(uint32_t addr)
188 switch(addr & 0x0e) {
191 return (dma[selch].creg & 0xffff);
193 return (dma[selch].bcreg & 0xffff);
198 return (dma[selch].areg & 0xffff);
200 return (dma[selch].bareg & 0xffff);
205 return ((dma[selch].areg >> 16) & 0xff);
207 return ((dma[selch].bareg >> 16) & 0xff);
211 return (uint32_t)(cmd & 0xffff);
214 // return read_io8(addr & 0x0e);
217 return read_io8(addr);
220 uint32_t UPD71071::read_io8(uint32_t addr)
226 switch(addr & 0x0f) {
230 // Q: Should be right BIT shift of BASE bit? 20200315 K.O
231 return ((base != 0) ? 0x10 : 0x00) | (1 << selch);
234 return dma[selch].bcreg & 0xff;
236 return dma[selch].creg & 0xff;
240 return (dma[selch].bcreg >> 8) & 0xff;
242 return (dma[selch].creg >> 8) & 0xff;
248 _d.d = dma[selch].areg;
250 _d.d = dma[selch].bareg;
252 switch(addr & 0x0f) {
268 return (cmd >> 8) & 0xff;
270 return dma[selch].mode;
272 val = (req << 4) | tc;
278 return (tmp >> 8) & 0xff;
287 void UPD71071::write_signal(int id, uint32_t data, uint32_t _mask)
290 uint8_t bit = 1 << ch;
291 if((id >= SIG_UPD71071_CH0) && (id <= SIG_UPD71071_CH3)) {
292 // out_debug_log(_T("DRQ#%d %s"), ch, ((data & _mask) != 0) ? _T("ON ") : _T("OFF"));
296 if(!(_SINGLE_MODE_DMA)) {
297 if((mask & (1 << ch)) == 0) { // MASK register MASKS DRQ.20200918 K.O
298 // Without #define SINGLE_MODE_DMA ,
299 // DMA trasfer is triggerd by SIGNAL or writing I/O 0Eh.
300 do_dma_per_channel(ch);
308 } else if((id >= SIG_UPD71071_UBE_CH0) && (id <= SIG_UPD71071_UBE_CH3)) {
309 inputs_ube[ch] = ((data & _mask) != 0) ? true : false;
310 } else if((id >= SIG_UPD71071_EOT_CH0) && (id <= SIG_UPD71071_EOT_CH3)) {
311 if((cmd & 0x04) == 0) {
312 switch(dma[ch].mode & 0xc0) {
314 dma[ch].endreq = true;
316 case 0x40: // Single -> Noop
319 dma[ch].endreq = true;
328 uint32_t UPD71071::read_signal(int ch)
330 if((ch >= (SIG_UPD71071_IS_TRANSFERING + 0)) && (ch < (SIG_UPD71071_IS_TRANSFERING + 4))) {
331 int _nch = ch - SIG_UPD71071_IS_TRANSFERING;
332 if((cmd & 0x04) != 0) return 0x00; // Not transfering
333 if(dma[_nch].creg == 0xffffffff) return 0x00; //
335 } else if((ch >= (SIG_UPD71071_IS_16BITS_TRANSFER + 0)) && (ch < (SIG_UPD71071_IS_16BITS_TRANSFER + 4))) {
336 int _nch = ch - SIG_UPD71071_IS_16BITS_TRANSFER;
337 bool stat = stats_ube[_nch];
338 return (stat) ? 0xffffffff : 0;
339 } else if((ch >= SIG_UPD71071_UBE_CH0) && (ch <= SIG_UPD71071_UBE_CH3)) {
340 return (inputs_ube[ch - SIG_UPD71071_UBE_CH0]) ? 0xffffffff : 0x00000000;
341 } else if((ch >= (SIG_UPD71071_CREG + 0)) && (ch < (SIG_UPD71071_CREG + 4))) {
342 return dma[ch - SIG_UPD71071_CREG].creg;
343 } else if((ch >= (SIG_UPD71071_BCREG + 0)) && (ch < (SIG_UPD71071_BCREG + 4))) {
344 return dma[ch - SIG_UPD71071_BCREG].creg;
345 } else if((ch >= (SIG_UPD71071_AREG + 0)) && (ch < (SIG_UPD71071_AREG + 4))) {
346 return dma[ch - SIG_UPD71071_AREG].creg;
347 } else if((ch >= (SIG_UPD71071_BAREG + 0)) && (ch < (SIG_UPD71071_BAREG + 4))) {
348 return dma[ch - SIG_UPD71071_BAREG].creg;
353 void UPD71071::write_via_debugger_data8w(uint32_t addr, uint32_t data, int *wait)
355 d_mem->write_dma_data8w(addr, data, wait);
358 uint32_t UPD71071::read_via_debugger_data8w(uint32_t addr, int *wait)
360 return d_mem->read_dma_data8w(addr, wait);
363 void UPD71071::write_via_debugger_data16w(uint32_t addr, uint32_t data, int *wait)
365 d_mem->write_dma_data16w(addr, data, wait);
368 uint32_t UPD71071::read_via_debugger_data16w(uint32_t addr, int *wait)
370 return d_mem->read_dma_data16w(addr, wait);
373 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
376 void UPD71071::do_dma_verify_8bit(int c, bool extended, bool compressed, int& wait)
378 bool __debugging = false;
379 int wait_1 = 0, wait_2 = 0;
380 __LIKELY_IF((__USE_DEBUGGER) && (d_debugger != NULL)) {
381 __debugging = d_debugger->now_device_debugging;
384 uint32_t val = dma[c].dev->read_dma_io8w(0, &wait_1);
388 __UNLIKELY_IF(__debugging) {
389 val2 = d_debugger->read_via_debugger_data8w(dma[c].areg, &wait_2);
391 val2 = read_via_debugger_data8w(dma[c].areg, &wait_2);
394 // ToDo: Compare val1 and val2.
395 // update temporary register
396 tmp = (tmp >> 8) | (val2 << 8);
398 wait += compressed ? 5 : 7;
400 wait += wait_1 + wait_2;
404 void UPD71071::do_dma_dev_to_mem_8bit(int c, bool extended, bool compressed, int& wait)
408 bool __debugging = false;
409 int wait_r = 0, wait_w = 0;
410 __LIKELY_IF((__USE_DEBUGGER) && (d_debugger != NULL)) {
411 __debugging = d_debugger->now_device_debugging;
415 val = dma[c].dev->read_dma_io8w(0, &wait_r);
416 // update temporary register
417 tmp = (tmp >> 8) | (val << 8);
419 __UNLIKELY_IF(__debugging) {
420 d_debugger->write_via_debugger_data8w(dma[c].areg, val, &wait_w);
422 write_via_debugger_data8w(dma[c].areg, val, &wait_w);
425 wait += compressed ? 5 : 7;
427 wait += wait_r + wait_w;
431 void UPD71071::do_dma_mem_to_dev_8bit(int c, bool extended, bool compressed, int& wait)
434 bool __debugging = false;
435 int wait_r = 0, wait_w = 0;
436 __LIKELY_IF((__USE_DEBUGGER) && (d_debugger != NULL)) {
437 __debugging = d_debugger->now_device_debugging;
441 __UNLIKELY_IF(__debugging) {
442 val = d_debugger->read_via_debugger_data8w(dma[c].areg, &wait_r);
444 val = read_via_debugger_data8w(dma[c].areg, &wait_r);
446 // update temporary register
447 tmp = (tmp >> 8) | (val << 8);
449 dma[c].dev->write_dma_io8w(0, val, &wait_w);
451 wait += compressed ? 5 : 7;
453 wait += wait_r + wait_w;
457 void UPD71071::do_dma_inc_dec_ptr_8bit(int c)
459 // Note: FM-Towns may extend to 32bit.
460 if(dma[c].mode & 0x20) {
461 dma[c].areg = (dma[c].areg - 1) & 0xffffff;
463 dma[c].areg = (dma[c].areg + 1) & 0xffffff;
467 void UPD71071::do_dma_verify_16bit(int c, bool extended, bool compressed, int& wait)
470 bool __debugging = false;
471 int wait_1 = 0, wait_2 = 0;
473 __LIKELY_IF((__USE_DEBUGGER) && (d_debugger != NULL)) {
474 __debugging = d_debugger->now_device_debugging;
477 uint32_t val = dma[c].dev->read_dma_io16w(0, &wait_1);
480 __UNLIKELY_IF(__debugging) {
481 val2 = d_debugger->read_via_debugger_data16w(dma[c].areg, &wait_2);
483 val2 = read_via_debugger_data16w(dma[c].areg, &wait_2);
486 // ToDo: Compare val1 and val2.
487 // update temporary register
490 wait += compressed ? 5 : 7;
492 wait += wait_1 + wait_2;
496 void UPD71071::do_dma_dev_to_mem_16bit(int c, bool extended, bool compressed, int& wait)
499 bool __debugging = false;
500 int wait_r = 0, wait_w = 0;
501 __LIKELY_IF((__USE_DEBUGGER) && (d_debugger != NULL)) {
502 __debugging = d_debugger->now_device_debugging;
504 // ToDo: For odd address.
507 val = dma[c].dev->read_dma_io16w(0, &wait_r);
508 // update temporary register
511 __UNLIKELY_IF(__debugging) {
512 d_debugger->write_via_debugger_data16w(dma[c].areg, val, &wait_w);
514 write_via_debugger_data16w(dma[c].areg, val, &wait_w);
517 wait += compressed ? 5 : 7;
519 wait += wait_r + wait_w;
523 void UPD71071::do_dma_mem_to_dev_16bit(int c, bool extended, bool compressed, int& wait)
526 bool __debugging = false;
527 int wait_r = 0, wait_w = 0;
528 __LIKELY_IF((__USE_DEBUGGER) && (d_debugger != NULL)) {
529 __debugging = d_debugger->now_device_debugging;
531 // ToDo: For odd address.
534 __UNLIKELY_IF(__debugging) {
535 val = d_debugger->read_via_debugger_data16w(dma[c].areg, &wait_r);
537 val = read_via_debugger_data16w(dma[c].areg, &wait_r);
539 // update temporary register
542 dma[c].dev->write_dma_io16w(0, val, &wait_w);
544 wait += compressed ? 5 : 7;
546 wait += wait_r + wait_w;
550 void UPD71071::do_dma_inc_dec_ptr_16bit(int c)
552 // Note: FM-Towns may extend to 32bit.
553 if(dma[c].mode & 0x20) {
554 dma[c].areg = (dma[c].areg - 2) & 0xffffff;
556 dma[c].areg = (dma[c].areg + 2) & 0xffffff;
560 bool UPD71071::do_dma_epilogue(int c)
563 uint8_t bit = 1 << c;
565 #if 0 /* SYNC TO UPSTREAM */
566 if(dma[c].creg-- == 0) {
567 //if(dma[c].endreq) dma[c].end = true;
568 if(dma[c].mode & 0x10) {
570 dma[c].areg = dma[c].bareg;
571 dma[c].creg = dma[c].bcreg;
579 //write_signals(&outputs_tc, 0xffffffff);
580 if((dma[c].mode & 0xc0) == 0x40) {
586 } else if((dma[c].mode & 0xc0) == 0x40) {
592 // Note: At FM-Towns, SCSI's DMAC will be set after
593 // SCSI bus phase become DATA IN/DATA OUT.
594 // Before bus phase became DATA IN/DATA OUT,
595 // DMAC mode and state was unstable (and ASSERTED
596 // DRQ came from SCSI before this state change).
597 // ToDo: Stop correctly before setting.
600 // if(dma[c].end) return true; // OK?
601 if((dma[c].creg == 0) || ((dma[c].endreq) && !(dma[c].end) && ((dma[c].mode & 0xc0) != 0x40))) { // OK?
602 if(dma[c].endreq) dma[c].end = true;
605 if(dma[c].end) is_tc = true;
607 if(dma[c].bcreg < dma[c].creg) {
610 if(dma[c].mode & 0x10) {
612 dma[c].areg = dma[c].bareg;
613 dma[c].creg = dma[c].bcreg;
623 if((dma[c].mode & 0xc0) == 0x40) {
631 // Note: At FM-Towns, SCSI's DMAC will be set after
632 // SCSI bus phase become DATA IN/DATA OUT.
633 // Before bus phase became DATA IN/DATA OUT,
634 // DMAC mode and state was unstable (and ASSERTED
635 // DRQ came from SCSI before this state change).
636 // ToDo: Stop correctly before setting.
638 if((dma[c].mode & 0xc0) == 0x40){
649 bool UPD71071::do_dma_per_channel(int c)
656 if((dma[c].mode & 0xc0) != 0x40) { // Without Single
660 uint8_t bit = 1 << c;
661 bool dmastat = false;
662 if(((req | sreq) & bit) /*&& !(mask & bit)*/) {
664 //while((req | sreq) & bit) { // Q: Will use burst transfer? 20230319 K.O
666 bool compressed = ((cmd & 0x08) != 0);
667 bool extended = ((cmd & 0x20) != 0);
674 // Will check WORD transfer mode for FM-Towns.(mode.bit0 = '1).
675 // Note: At FM-Towns, may set bit0 of mode register (B/W),
676 // but transferring per 8bit from/to SCSI HOST...
679 if((dma[c].is_16bit) && (inputs_ube[c]) /*&& (b16 != 0)*/) {
680 // This channel transferr makes 16bit.
681 if((dma[c].mode & 0x0c) == 0x00) {
682 do_dma_verify_16bit(c, extended, compressed, wait);
683 } else if((dma[c].mode & 0x0c) == 0x04) {
684 do_dma_dev_to_mem_16bit(c, extended, compressed, wait);
685 } else if((dma[c].mode & 0x0c) == 0x08) {
686 do_dma_mem_to_dev_16bit(c, extended, compressed, wait);
688 do_dma_inc_dec_ptr_16bit(c);
690 // 8bit transfer mode
691 if((dma[c].mode & 0x0c) == 0x00) {
692 do_dma_verify_8bit(c, extended, compressed, wait);
693 } else if((dma[c].mode & 0x0c) == 0x04) {
694 do_dma_dev_to_mem_8bit(c, extended, compressed, wait);
695 } else if((dma[c].mode & 0x0c) == 0x08) {
696 do_dma_mem_to_dev_8bit(c, extended, compressed, wait);
698 do_dma_inc_dec_ptr_8bit(c);
700 if(d_cpu != NULL) d_cpu->set_extra_clock(wait);
703 if(do_dma_epilogue(c)) {
705 // if(_SINGLE_MODE_DMA) {
715 void UPD71071::do_dma()
723 for(int c = 0; c < 4; c++) {
724 if((mask & (1 << c)) == 0) { // MASK
725 if((dma[c].mode & 0xc0) == 0x00) { // Demand
727 do_dma_per_channel(c);
729 } else if((dma[c].mode & 0xc0) == 0x40) { // Single
730 if(do_dma_per_channel(c)) break;
731 } else if((dma[c].mode & 0xc0) == 0xc0) { // Block (ToDo)
732 if(do_dma_per_channel(c)) break;
736 //#ifdef SINGLE_MODE_DMA
737 if(_SINGLE_MODE_DMA) {
745 bool UPD71071::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
748 CH0 AREG=FFFF CREG=FFFF BAREG=FFFF BCREG=FFFF REQ=1 MASK=1 MODE=FF MEM->I/O
749 CH1 AREG=FFFF CREG=FFFF BAREG=FFFF BCREG=FFFF REQ=1 MASK=1 MODE=FF I/O->MEM
750 CH2 AREG=FFFF CREG=FFFF BAREG=FFFF BCREG=FFFF REQ=1 MASK=1 MODE=FF VERIFY
751 CH3 AREG=FFFF CREG=FFFF BAREG=FFFF BCREG=FFFF REQ=1 MASK=1 MODE=FF INVALID
753 static const _TCHAR *dir[4] = {
754 _T("VERIFY"), _T("I/O->MEM"), _T("MEM->I/O"), _T("INVALID")
756 my_stprintf_s(buffer, buffer_len,
758 _T("SELECT CH=%d BASE=%02X REQ=%02X SREQ=%02X MASK=%02X TC=%02X ")
759 _T("CMD=%04X TMP=%04X\n")
760 _T("CH0 AREG=%04X CREG=%04X BAREG=%04X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s\n")
761 _T("CH1 AREG=%04X CREG=%04X BAREG=%04X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s\n")
762 _T("CH2 AREG=%04X CREG=%04X BAREG=%04X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s\n")
763 _T("CH3 AREG=%04X CREG=%04X BAREG=%04X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s"),
764 (b16 != 0) ? _T("YES") : _T("NO"),
765 selch, base, req, sreq, mask, tc,
767 dma[0].areg, dma[0].creg, dma[0].bareg, dma[0].bcreg, ((req | sreq) >> 0) & 1, (mask >> 0) & 1, dma[0].mode, dir[(dma[0].mode >> 2) & 3],
768 dma[1].areg, dma[1].creg, dma[1].bareg, dma[1].bcreg, ((req | sreq) >> 1) & 1, (mask >> 1) & 1, dma[1].mode, dir[(dma[1].mode >> 2) & 3],
769 dma[2].areg, dma[2].creg, dma[2].bareg, dma[2].bcreg, ((req | sreq) >> 2) & 1, (mask >> 2) & 1, dma[2].mode, dir[(dma[2].mode >> 2) & 3],
770 dma[3].areg, dma[3].creg, dma[3].bareg, dma[3].bcreg, ((req | sreq) >> 3) & 1, (mask >> 3) & 1, dma[3].mode, dir[(dma[3].mode >> 2) & 3]);
774 #define STATE_VERSION 6
776 bool UPD71071::process_state(FILEIO* state_fio, bool loading)
778 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
781 if(!state_fio->StateCheckInt32(this_device_id)) {
784 for(int i = 0; i < 4; i++) {
785 state_fio->StateValue(dma[i].areg);
786 state_fio->StateValue(dma[i].bareg);
787 state_fio->StateValue(dma[i].creg);
788 state_fio->StateValue(dma[i].bcreg);
789 state_fio->StateValue(dma[i].mode);
790 state_fio->StateValue(dma[i].is_16bit);
791 state_fio->StateValue(dma[i].endreq);
792 state_fio->StateValue(dma[i].end);
794 state_fio->StateValue(b16);
795 state_fio->StateValue(selch);
796 state_fio->StateValue(base);
797 state_fio->StateValue(cmd);
798 state_fio->StateValue(tmp);
799 state_fio->StateValue(req);
800 state_fio->StateValue(sreq);
801 state_fio->StateValue(mask);
802 state_fio->StateValue(tc);
803 state_fio->StateValue(running);
805 state_fio->StateArray(inputs_ube, sizeof(inputs_ube), 1);
806 state_fio->StateArray(stats_ube, sizeof(stats_ube), 1);