2 Skelton for retropc emulator
4 Origin : MAME Z80DMA / Xmillenium
5 Author : Takeda.Toshiya
17 #define CMD_RESET 0xc3
18 #define CMD_RESET_PORT_A_TIMING 0xc7
19 #define CMD_RESET_PORT_B_TIMING 0xcb
21 #define CMD_CONTINUE 0xd3
22 #define CMD_DISABLE_INTERRUPTS 0xaf
23 #define CMD_ENABLE_INTERRUPTS 0xab
24 #define CMD_RESET_AND_DISABLE_INTERRUPTS 0xa3
25 #define CMD_ENABLE_AFTER_RETI 0xb7
26 #define CMD_READ_STATUS_BYTE 0xbf
27 #define CMD_REINITIALIZE_STATUS_BYTE 0x8b
28 #define CMD_INITIATE_READ_SEQUENCE 0xa7
29 #define CMD_FORCE_READY 0xb3
30 #define CMD_ENABLE_DMA 0x87
31 #define CMD_DISABLE_DMA 0x83
32 #define CMD_READ_MASK_FOLLOWS 0xbb
36 #define TM_SEARCH_TRANSFER 3
39 #define OM_CONTINUOUS 1
44 #define INT_END_OF_BLOCK 2
46 #define GET_REGNUM(r) (int)(&(r) - &(WR0))
48 #define WR0 regs.m[0][0]
49 #define WR1 regs.m[1][0]
50 #define WR2 regs.m[2][0]
51 #define WR3 regs.m[3][0]
52 #define WR4 regs.m[4][0]
53 #define WR5 regs.m[5][0]
54 #define WR6 regs.m[6][0]
56 #define PORTA_ADDRESS_L regs.m[0][1]
57 #define PORTA_ADDRESS_H regs.m[0][2]
59 #define BLOCKLEN_L regs.m[0][3]
60 #define BLOCKLEN_H regs.m[0][4]
62 #define PORTA_TIMING regs.m[1][1]
63 #define PORTB_TIMING regs.m[2][1]
65 #define MASK_BYTE regs.m[3][1]
66 #define MATCH_BYTE regs.m[3][2]
68 #define PORTB_ADDRESS_L regs.m[4][1]
69 #define PORTB_ADDRESS_H regs.m[4][2]
70 #define INTERRUPT_CTRL regs.m[4][3]
71 #define INTERRUPT_VECTOR regs.m[4][4]
72 #define PULSE_CTRL regs.m[4][5]
74 #define READ_MASK regs.m[6][1]
76 #define PORTA_ADDRESS ((PORTA_ADDRESS_H << 8) | PORTA_ADDRESS_L)
77 #define PORTB_ADDRESS ((PORTB_ADDRESS_H << 8) | PORTB_ADDRESS_L)
78 #define BLOCKLEN ((BLOCKLEN_H << 8) | BLOCKLEN_L)
80 #define PORTA_INC (WR1 & 0x10)
81 #define PORTB_INC (WR2 & 0x10)
82 #define PORTA_FIXED (((WR1 >> 4) & 2) == 2)
83 #define PORTB_FIXED (((WR2 >> 4) & 2) == 2)
84 #define PORTA_MEMORY (((WR1 >> 3) & 1) == 0)
85 #define PORTB_MEMORY (((WR2 >> 3) & 1) == 0)
87 #define PORTA_CYCLE_LEN (((PORTA_TIMING & 3) != 3) ? (4 - (PORTA_TIMING & 3)) : PORTA_MEMORY ? 3 : 4)
88 #define PORTB_CYCLE_LEN (((PORTB_TIMING & 3) != 3) ? (4 - (PORTB_TIMING & 3)) : PORTB_MEMORY ? 3 : 4)
90 #define PORTA_IS_SOURCE ((WR0 >> 2) & 1)
91 #define PORTB_IS_SOURCE (!PORTA_IS_SOURCE)
92 #define TRANSFER_MODE (WR0 & 3)
94 #define MATCH_F_SET (status &= ~0x10)
95 #define MATCH_F_CLEAR (status |= 0x10)
96 #define EOB_F_SET (status &= ~0x20)
97 #define EOB_F_CLEAR (status |= 0x20)
99 #define STOP_ON_MATCH ((WR3 >> 2) & 1)
101 #define OPERATING_MODE ((WR4 >> 5) & 3)
103 #define READY_ACTIVE_HIGH ((WR5 >> 3) & 1)
104 #define CHECK_WAIT_SIGNAL ((WR5 >> 4) & 1)
105 #define AUTO_RESTART ((WR5 >> 5) & 1)
107 #define INTERRUPT_ENABLE (WR3 & 0x20)
108 #define INT_ON_MATCH (INTERRUPT_CTRL & 0x01)
109 #define INT_ON_END_OF_BLOCK (INTERRUPT_CTRL & 0x02)
110 #define INT_ON_READY (INTERRUPT_CTRL & 0x40)
111 #define STATUS_AFFECTS_VECTOR (INTERRUPT_CTRL & 0x20)
113 void Z80DMA::initialize()
115 DEVICE::initialize();
116 _SINGLE_MODE_DMA = osd->check_feature(_T("SINGLE_MODE_DMA"));
117 _DMA_DEBUG = osd->check_feature(_T("DMA_DEBUG"));
118 _X1TURBO_FEATURE = osd->check_feature(_T("_X1TURBO_FEATURE"));
119 // _DMA_DEBUG = true; // TMP
120 if(d_debugger != NULL) {
121 d_debugger->set_device_name(_T("Debugger (Z80DMA)"));
122 d_debugger->set_context_mem(this);
123 d_debugger->set_context_io(this);
129 WR3 &= ~0x20; // disable interrupt
143 req_intr = in_service = false;
152 void Z80DMA::write_io8(uint32_t addr, uint32_t data)
155 if((data & 0x87) == 0) {
157 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR2=%2x\n"), data);
161 wr_tmp[wr_num++] = GET_REGNUM(PORTB_TIMING);
163 } else if((data & 0x87) == 4) {
165 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR1=%2x\n"), data);
169 wr_tmp[wr_num++] = GET_REGNUM(PORTA_TIMING);
171 } else if((data & 0x80) == 0) {
173 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR0=%2x\n"), data);
177 wr_tmp[wr_num++] = GET_REGNUM(PORTA_ADDRESS_L);
180 wr_tmp[wr_num++] = GET_REGNUM(PORTA_ADDRESS_H);
183 wr_tmp[wr_num++] = GET_REGNUM(BLOCKLEN_L);
186 wr_tmp[wr_num++] = GET_REGNUM(BLOCKLEN_H);
188 } else if((data & 0x83) == 0x80) {
190 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR3=%2x\n"), data);
194 wr_tmp[wr_num++] = GET_REGNUM(MASK_BYTE);
197 wr_tmp[wr_num++] = GET_REGNUM(MATCH_BYTE);
199 enabled = ((data & 0x40) != 0);
200 } else if((data & 0x83) == 0x81) {
202 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR4=%2x\n"), data);
206 wr_tmp[wr_num++] = GET_REGNUM(PORTB_ADDRESS_L);
209 wr_tmp[wr_num++] = GET_REGNUM(PORTB_ADDRESS_H);
212 wr_tmp[wr_num++] = GET_REGNUM(INTERRUPT_CTRL);
214 } else if((data & 0xc7) == 0x82) {
216 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR5=%2x\n"), data);
219 // RDY signal sense is a LEVEL, not an EDDGE (thanks Mr.Sato)
220 if(now_ready() && INT_ON_READY) {
221 request_intr(INT_RDY);
223 } else if((data & 0x83) == 0x83) {
225 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR6=%2x\n"), data);
230 // check dma stop (from Xmil106RS)
233 case CMD_READ_STATUS_BYTE:
234 case CMD_INITIATE_READ_SEQUENCE:
236 case CMD_DISABLE_DMA:
237 case CMD_READ_MASK_FOLLOWS:
246 case CMD_ENABLE_AFTER_RETI:
248 case CMD_READ_STATUS_BYTE:
249 // force to read status (from Xmillenium)
251 update_read_buffer();
253 case CMD_RESET_AND_DISABLE_INTERRUPTS:
259 case CMD_INITIATE_READ_SEQUENCE:
260 update_read_buffer();
265 req_intr = in_service = false;
274 // reset auto repeat and wait functions
279 addr_a = PORTA_ADDRESS;
280 addr_b = PORTB_ADDRESS;
281 upcount = 0;//BLOCKLEN;
284 case CMD_DISABLE_DMA:
289 //#ifndef SINGLE_MODE_DMA
290 if(!_SINGLE_MODE_DMA) do_dma();
293 case CMD_READ_MASK_FOLLOWS:
294 wr_tmp[wr_num++] = GET_REGNUM(READ_MASK);
297 upcount = (dma_stop && upcount != blocklen) ? -1 : 0;
300 //#ifndef SINGLE_MODE_DMA
301 if(!_SINGLE_MODE_DMA) do_dma();
304 case CMD_RESET_PORT_A_TIMING:
307 case CMD_RESET_PORT_B_TIMING:
310 case CMD_FORCE_READY:
312 // RDY signal sense is a LEVEL, not an EDDGE (thanks Mr.Sato)
313 if(now_ready() && INT_ON_READY) {
314 request_intr(INT_RDY);
316 //#ifndef SINGLE_MODE_DMA
317 if(!_SINGLE_MODE_DMA) do_dma();
320 case CMD_ENABLE_INTERRUPTS:
322 // RDY signal sense is a LEVEL, not an EDDGE (thanks Mr.Sato)
323 if(now_ready() && INT_ON_READY) {
324 request_intr(INT_RDY);
327 case CMD_DISABLE_INTERRUPTS:
330 case CMD_REINITIALIZE_STATUS_BYTE:
339 int nreg = wr_tmp[wr_ptr];
341 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR[%d,%d]=%2x\n"), nreg >> 3, nreg & 7, data);
345 if(++wr_ptr >= wr_num) {
348 if(nreg == GET_REGNUM(INTERRUPT_CTRL)) {
351 wr_tmp[wr_num++] = GET_REGNUM(PULSE_CTRL);
354 wr_tmp[wr_num++] = GET_REGNUM(INTERRUPT_VECTOR);
357 // RDY signal sense is a LEVEL, not an EDDGE (thanks Mr.Sato)
358 if(now_ready() && INT_ON_READY) {
359 request_intr(INT_RDY);
361 } else if(wr_tmp[wr_num] == GET_REGNUM(READ_MASK)) {
364 update_read_buffer();
370 uint32_t Z80DMA::read_io8(uint32_t addr)
372 // return status if read buffer is empty (from Xmillenium)
374 return status | (now_ready() ? 0 : 2) | (req_intr ? 0 : 8);
376 uint32_t data = rr_tmp[rr_ptr];
379 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: RR[%d]=%2x\n"), rr_ptr, data);
381 if(++rr_ptr >= rr_num) {
387 void Z80DMA::write_signal(int id, uint32_t data, uint32_t mask)
389 // ready signal (wired-or)
390 bool prev_ready = now_ready();
397 if(!prev_ready && now_ready()) {
399 request_intr(INT_RDY);
401 //#ifndef SINGLE_MODE_DMA
402 if(!_SINGLE_MODE_DMA) do_dma();
407 bool Z80DMA::now_ready()
412 // FIXME: DRQ active is really L, but FDC class sends H
413 if(READY_ACTIVE_HIGH) {
420 void Z80DMA::update_read_buffer()
422 // note: return current count and address (from Xmillenium)
424 if(READ_MASK & 0x01) {
425 rr_tmp[rr_num++] = status | (now_ready() ? 0 : 2) | (req_intr ? 0 : 8);
427 if(READ_MASK & 0x02) {
428 rr_tmp[rr_num++] = upcount & 0xff;//BLOCKLEN_L;
430 if(READ_MASK & 0x04) {
431 rr_tmp[rr_num++] = upcount >> 8;//BLOCKLEN_H;
433 if(READ_MASK & 0x08) {
434 rr_tmp[rr_num++] = addr_a & 0xff;//PORTA_ADDRESS_L;
436 if(READ_MASK & 0x10) {
437 rr_tmp[rr_num++] = addr_a >> 8;//PORTA_ADDRESS_H;
439 if(READ_MASK & 0x20) {
440 rr_tmp[rr_num++] = addr_b & 0xff;//PORTB_ADDRESS_L;
442 if(READ_MASK & 0x40) {
443 rr_tmp[rr_num++] = addr_b >> 8;//PORTB_ADDRESS_H;
447 void Z80DMA::write_via_debugger_data8w(uint32_t addr, uint32_t data, int* wait)
449 d_mem->write_dma_data8w(addr, data, wait);
452 uint32_t Z80DMA::read_via_debugger_data8w(uint32_t addr, int* wait)
454 return d_mem->read_dma_data8w(addr, wait);
457 void Z80DMA::write_via_debugger_io8w(uint32_t addr, uint32_t data, int* wait)
459 d_io->write_dma_io8w(addr, data, wait);
462 uint32_t Z80DMA::read_via_debugger_io8w(uint32_t addr, int* wait)
464 return d_io->read_dma_io8w(addr, wait);
467 void Z80DMA::write_memory(uint32_t addr, uint32_t data, int* wait)
469 if(d_debugger != NULL && d_debugger->now_device_debugging) {
470 d_debugger->write_via_debugger_data8w(addr, data, wait);
472 this->write_via_debugger_data8w(addr, data, wait);
476 uint32_t Z80DMA::read_memory(uint32_t addr, int* wait)
478 if(d_debugger != NULL && d_debugger->now_device_debugging) {
479 return d_debugger->read_via_debugger_data8w(addr, wait);
481 return this->read_via_debugger_data8w(addr, wait);
485 void Z80DMA::write_ioport(uint32_t addr, uint32_t data, int* wait)
487 if(d_debugger != NULL && d_debugger->now_device_debugging) {
488 d_debugger->write_via_debugger_io8w(addr, data, wait);
490 this->write_via_debugger_io8w(addr, data, wait);
494 uint32_t Z80DMA::read_ioport(uint32_t addr, int* wait)
496 if(d_debugger != NULL && d_debugger->now_device_debugging) {
497 return d_debugger->read_via_debugger_io8w(addr, wait);
499 return this->read_via_debugger_io8w(addr, wait);
503 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
505 void Z80DMA::do_dma()
510 bool occured = false;
511 bool finished = false;
514 // from Xmillenium (thanks Y.S.)
517 } else if(BLOCKLEN == 0xffff) {
518 blocklen = (int)65536;
520 blocklen = BLOCKLEN + 1;
522 // Workaround of MinGW's (older) GCC.
523 // messages: crosses initialization of 'int wait_w' etc.
525 int wait_r = 0, wait_w = 0;
527 //#ifndef SINGLE_MODE_DMA
530 while(enabled && now_ready() && !(upcount == blocklen || found)) {
532 if(upcount < blocklen) {
546 if(PORTA_IS_SOURCE) {
548 data = read_memory(addr_a, &wait_r);
550 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: RAM[%4x]=%2x -> "), addr_a, data);
553 data = read_ioport(addr_a, &wait_r);
555 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: INP(%4x)=%2x -> "), addr_a, data);
559 if(CHECK_WAIT_SIGNAL) {
560 d_cpu->set_extra_clock(PORTA_CYCLE_LEN + wait_r);
562 d_cpu->set_extra_clock(PORTA_CYCLE_LEN);
567 data = read_memory(addr_b, &wait_r);
569 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: RAM[%4x]=%2x -> "), addr_b, data);
572 data = read_ioport(addr_b, &wait_r);
574 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: INP(%4x)=%2x -> "), addr_b, data);
578 if(CHECK_WAIT_SIGNAL) {
579 d_cpu->set_extra_clock(PORTB_CYCLE_LEN + wait_r);
581 d_cpu->set_extra_clock(PORTB_CYCLE_LEN);
587 if(TRANSFER_MODE == TM_TRANSFER || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
588 if(PORTA_IS_SOURCE) {
591 if(_DMA_DEBUG) this->out_debug_log(_T("RAM[%4x]\n"), addr_b);
593 write_signals(&outputs_wrote_mem, addr_b);
594 write_memory(addr_b, data, &wait_w);
597 if(_DMA_DEBUG) this->out_debug_log(_T("OUT(%4x)\n"), addr_b);
599 write_ioport(addr_b, data, &wait_w);
602 if(CHECK_WAIT_SIGNAL) {
603 d_cpu->set_extra_clock(PORTB_CYCLE_LEN + wait_w);
605 d_cpu->set_extra_clock(PORTB_CYCLE_LEN);
611 if(_DMA_DEBUG) this->out_debug_log(_T("RAM[%4x]\n"), addr_a);
613 write_signals(&outputs_wrote_mem, addr_a);
614 write_memory(addr_a, data, &wait_w);
617 if(_DMA_DEBUG) this->out_debug_log(_T("OUT(%4x)\n"), addr_a);
619 write_ioport(addr_a, data, &wait_w);
622 if(CHECK_WAIT_SIGNAL) {
623 d_cpu->set_extra_clock(PORTA_CYCLE_LEN + wait_w);
625 d_cpu->set_extra_clock(PORTA_CYCLE_LEN);
632 if(OPERATING_MODE == OM_BYTE) {
637 if(TRANSFER_MODE == TM_SEARCH || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
638 if((data & MASK_BYTE) == (MATCH_BYTE & MASK_BYTE)) {
645 if(found || (BLOCKLEN == 0 && !now_ready())) {
646 if(upcount < blocklen) {
653 if(PORTA_IS_SOURCE) {
654 addr_a += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
656 addr_b += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
658 if(TRANSFER_MODE == TM_TRANSFER || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
659 if(PORTA_IS_SOURCE) {
660 addr_b += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
662 addr_a += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
665 //#ifdef SINGLE_MODE_DMA
666 if(_SINGLE_MODE_DMA) {
667 if(OPERATING_MODE == OM_BYTE) {
677 this->out_debug_log(_T("Z80DMA: COUNT=%d BLOCKLEN=%d FOUND=%d\n"), upcount, blocklen, found ? 1 : 0);
681 if(occured && (upcount == blocklen || found)) {
683 if(AUTO_RESTART && upcount == blocklen && !force_ready) {
685 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: AUTO RESTART !!!\n"));
688 //#ifndef SINGLE_MODE_DMA
689 if(!_SINGLE_MODE_DMA) goto restart;
698 if(upcount != blocklen) {
705 if(upcount == blocklen) {
706 // transfer/search done
707 if(INT_ON_END_OF_BLOCK) {
708 level |= INT_END_OF_BLOCK;
727 if(finished || OPERATING_MODE == OM_BYTE || (OPERATING_MODE == OM_BURST && !now_ready())) {
732 void Z80DMA::request_bus()
736 //#ifdef SINGLE_MODE_DMA
737 if(_SINGLE_MODE_DMA) d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
739 d_cpu->set_extra_clock(3);
745 void Z80DMA::release_bus()
749 //#ifdef SINGLE_MODE_DMA
750 if(_SINGLE_MODE_DMA) d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
752 if(OPERATING_MODE == OM_BYTE) {
753 d_cpu->set_extra_clock(1);
755 d_cpu->set_extra_clock(2);
762 void Z80DMA::request_intr(int level)
764 if(!in_service && INTERRUPT_ENABLE) {
767 if(STATUS_AFFECTS_VECTOR) {
768 vector = (uint8_t)((INTERRUPT_VECTOR & 0xf9) | (level << 1));
770 vector = (uint8_t)INTERRUPT_VECTOR;
776 void Z80DMA::set_intr_iei(bool val)
784 #define set_intr_oei(val) { \
787 if(d_child != NULL) { \
788 d_child->set_intr_iei(oei); \
793 void Z80DMA::update_intr()
798 if((next = iei) == true) {
806 if((next = iei) == true) {
807 next = (!in_service && req_intr);
810 d_cpu->set_intr_line(next, true, intr_bit);
814 uint32_t Z80DMA::get_intr_ack()
818 // invalid interrupt status
820 } else if(req_intr) {
827 if(d_child != NULL) {
828 return d_child->get_intr_ack();
833 void Z80DMA::notify_intr_reti()
841 if(d_child != NULL) {
842 d_child->notify_intr_reti();
846 bool Z80DMA::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
849 PORT-A(MEM,FFFF)->PORT-B(I/O,FFFF) CNT=65536 BLK=65536 STAT=00 ENABLE=1 READY=1
851 my_stprintf_s(buffer, buffer_len,
852 _T("PORT-A(%s,%04X)%sPORT-B(%s,%04X) CNT=%d BLK=%d STAT=%02X ENABLE=%d READY=%d"),
853 PORTA_MEMORY ? "MEM" : "I/O", addr_a,
854 PORTA_IS_SOURCE ? "->" : "<-",
855 PORTB_MEMORY ? "MEM" : "I/O", addr_b,
857 status | (now_ready() ? 0 : 2) | (req_intr ? 0 : 8),
858 enabled, now_ready());
862 #define STATE_VERSION 2
864 bool Z80DMA::process_state(FILEIO* state_fio, bool loading)
866 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
869 if(!state_fio->StateCheckInt32(this_device_id)) {
872 state_fio->StateArray(®s.m[0][0], sizeof(regs.m), 1);
873 state_fio->StateArray(®s.t[0], sizeof(regs.t), 1);
874 state_fio->StateValue(status);
875 state_fio->StateArray(wr_tmp, sizeof(wr_tmp), 1);
876 state_fio->StateValue(wr_num);
877 state_fio->StateValue(wr_ptr);
878 state_fio->StateArray(rr_tmp, sizeof(rr_tmp), 1);
879 state_fio->StateValue(rr_num);
880 state_fio->StateValue(rr_ptr);
881 state_fio->StateValue(enabled);
882 state_fio->StateValue(ready);
883 state_fio->StateValue(force_ready);
884 state_fio->StateValue(addr_a);
885 state_fio->StateValue(addr_b);
886 state_fio->StateValue(upcount);
887 state_fio->StateValue(blocklen);
888 state_fio->StateValue(dma_stop);
889 state_fio->StateValue(bus_master);
890 state_fio->StateValue(req_intr);
891 state_fio->StateValue(in_service);
892 state_fio->StateValue(vector);
893 state_fio->StateValue(iei);
894 state_fio->StateValue(oei);
895 state_fio->StateValue(intr_bit);