2 Skelton for retropc emulator
4 Origin : MAME Z80DMA / Xmillenium
5 Author : Takeda.Toshiya
16 #define CMD_RESET 0xc3
17 #define CMD_RESET_PORT_A_TIMING 0xc7
18 #define CMD_RESET_PORT_B_TIMING 0xcb
20 #define CMD_CONTINUE 0xd3
21 #define CMD_DISABLE_INTERRUPTS 0xaf
22 #define CMD_ENABLE_INTERRUPTS 0xab
23 #define CMD_RESET_AND_DISABLE_INTERRUPTS 0xa3
24 #define CMD_ENABLE_AFTER_RETI 0xb7
25 #define CMD_READ_STATUS_BYTE 0xbf
26 #define CMD_REINITIALIZE_STATUS_BYTE 0x8b
27 #define CMD_INITIATE_READ_SEQUENCE 0xa7
28 #define CMD_FORCE_READY 0xb3
29 #define CMD_ENABLE_DMA 0x87
30 #define CMD_DISABLE_DMA 0x83
31 #define CMD_READ_MASK_FOLLOWS 0xbb
35 #define TM_SEARCH_TRANSFER 3
38 #define OM_CONTINUOUS 1
43 #define INT_END_OF_BLOCK 2
45 #define GET_REGNUM(r) (&(r) - &(WR0))
47 #define WR0 regs.m[0][0]
48 #define WR1 regs.m[1][0]
49 #define WR2 regs.m[2][0]
50 #define WR3 regs.m[3][0]
51 #define WR4 regs.m[4][0]
52 #define WR5 regs.m[5][0]
53 #define WR6 regs.m[6][0]
55 #define PORTA_ADDRESS_L regs.m[0][1]
56 #define PORTA_ADDRESS_H regs.m[0][2]
58 #define BLOCKLEN_L regs.m[0][3]
59 #define BLOCKLEN_H regs.m[0][4]
61 #define PORTA_TIMING regs.m[1][1]
62 #define PORTB_TIMING regs.m[2][1]
64 #define MASK_BYTE regs.m[3][1]
65 #define MATCH_BYTE regs.m[3][2]
67 #define PORTB_ADDRESS_L regs.m[4][1]
68 #define PORTB_ADDRESS_H regs.m[4][2]
69 #define INTERRUPT_CTRL regs.m[4][3]
70 #define INTERRUPT_VECTOR regs.m[4][4]
71 #define PULSE_CTRL regs.m[4][5]
73 #define READ_MASK regs.m[6][1]
75 #define PORTA_ADDRESS ((PORTA_ADDRESS_H << 8) | PORTA_ADDRESS_L)
76 #define PORTB_ADDRESS ((PORTB_ADDRESS_H << 8) | PORTB_ADDRESS_L)
77 #define BLOCKLEN ((BLOCKLEN_H << 8) | BLOCKLEN_L)
79 #define PORTA_INC (WR1 & 0x10)
80 #define PORTB_INC (WR2 & 0x10)
81 #define PORTA_FIXED (((WR1 >> 4) & 2) == 2)
82 #define PORTB_FIXED (((WR2 >> 4) & 2) == 2)
83 #define PORTA_MEMORY (((WR1 >> 3) & 1) == 0)
84 #define PORTB_MEMORY (((WR2 >> 3) & 1) == 0)
86 #define PORTA_CYCLE_LEN (((PORTA_TIMING & 3) != 3) ? (4 - (PORTA_TIMING & 3)) : PORTA_MEMORY ? 3 : 4)
87 #define PORTB_CYCLE_LEN (((PORTB_TIMING & 3) != 3) ? (4 - (PORTB_TIMING & 3)) : PORTB_MEMORY ? 3 : 4)
89 #define PORTA_IS_SOURCE ((WR0 >> 2) & 1)
90 #define PORTB_IS_SOURCE (!PORTA_IS_SOURCE)
91 #define TRANSFER_MODE (WR0 & 3)
93 #define MATCH_F_SET (status &= ~0x10)
94 #define MATCH_F_CLEAR (status |= 0x10)
95 #define EOB_F_SET (status &= ~0x20)
96 #define EOB_F_CLEAR (status |= 0x20)
98 #define STOP_ON_MATCH ((WR3 >> 2) & 1)
100 #define OPERATING_MODE ((WR4 >> 5) & 3)
102 #define READY_ACTIVE_HIGH ((WR5 >> 3) & 1)
103 #define CHECK_WAIT_SIGNAL ((WR5 >> 4) & 1)
104 #define AUTO_RESTART ((WR5 >> 5) & 1)
106 #define INTERRUPT_ENABLE (WR3 & 0x20)
107 #define INT_ON_MATCH (INTERRUPT_CTRL & 0x01)
108 #define INT_ON_END_OF_BLOCK (INTERRUPT_CTRL & 0x02)
109 #define INT_ON_READY (INTERRUPT_CTRL & 0x40)
110 #define STATUS_AFFECTS_VECTOR (INTERRUPT_CTRL & 0x20)
112 void Z80DMA::initialize()
114 DEVICE::initialize();
115 _SINGLE_MODE_DMA = osd->check_feature(_T("SINGLE_MODE_DMA"));
116 _DMA_DEBUG = osd->check_feature(_T("DMA_DEBUG"));
121 WR3 &= ~0x20; // disable interrupt
135 req_intr = in_service = false;
144 void Z80DMA::write_io8(uint32_t addr, uint32_t data)
147 if((data & 0x87) == 0) {
149 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR2=%2x\n"), data);
153 wr_tmp[wr_num++] = GET_REGNUM(PORTB_TIMING);
155 } else if((data & 0x87) == 4) {
157 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR1=%2x\n"), data);
161 wr_tmp[wr_num++] = GET_REGNUM(PORTA_TIMING);
163 } else if((data & 0x80) == 0) {
165 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR0=%2x\n"), data);
169 wr_tmp[wr_num++] = GET_REGNUM(PORTA_ADDRESS_L);
172 wr_tmp[wr_num++] = GET_REGNUM(PORTA_ADDRESS_H);
175 wr_tmp[wr_num++] = GET_REGNUM(BLOCKLEN_L);
178 wr_tmp[wr_num++] = GET_REGNUM(BLOCKLEN_H);
180 } else if((data & 0x83) == 0x80) {
182 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR3=%2x\n"), data);
186 wr_tmp[wr_num++] = GET_REGNUM(MASK_BYTE);
189 wr_tmp[wr_num++] = GET_REGNUM(MATCH_BYTE);
191 enabled = ((data & 0x40) != 0);
192 } else if((data & 0x83) == 0x81) {
194 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR4=%2x\n"), data);
198 wr_tmp[wr_num++] = GET_REGNUM(PORTB_ADDRESS_L);
201 wr_tmp[wr_num++] = GET_REGNUM(PORTB_ADDRESS_H);
204 wr_tmp[wr_num++] = GET_REGNUM(INTERRUPT_CTRL);
206 } else if((data & 0xc7) == 0x82) {
208 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR5=%2x\n"), data);
211 } else if((data & 0x83) == 0x83) {
213 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR6=%2x\n"), data);
218 // check dma stop (from Xmil106RS)
221 case CMD_READ_STATUS_BYTE:
222 case CMD_INITIATE_READ_SEQUENCE:
224 case CMD_DISABLE_DMA:
225 case CMD_READ_MASK_FOLLOWS:
234 case CMD_ENABLE_AFTER_RETI:
236 case CMD_READ_STATUS_BYTE:
237 // force to read status (from Xmillenium)
239 update_read_buffer();
241 case CMD_RESET_AND_DISABLE_INTERRUPTS:
247 case CMD_INITIATE_READ_SEQUENCE:
248 update_read_buffer();
262 // reset auto repeat and wait functions
267 addr_a = PORTA_ADDRESS;
268 addr_b = PORTB_ADDRESS;
269 upcount = 0;//BLOCKLEN;
272 case CMD_DISABLE_DMA:
277 //#ifndef SINGLE_MODE_DMA
278 if(!_SINGLE_MODE_DMA) do_dma();
281 case CMD_READ_MASK_FOLLOWS:
282 wr_tmp[wr_num++] = GET_REGNUM(READ_MASK);
285 upcount = (dma_stop && upcount != blocklen) ? -1 : 0;
288 //#ifndef SINGLE_MODE_DMA
289 if(!_SINGLE_MODE_DMA) do_dma();
292 case CMD_RESET_PORT_A_TIMING:
295 case CMD_RESET_PORT_B_TIMING:
298 case CMD_FORCE_READY:
300 //#ifndef SINGLE_MODE_DMA
301 if(!_SINGLE_MODE_DMA) do_dma();
304 case CMD_ENABLE_INTERRUPTS:
307 case CMD_DISABLE_INTERRUPTS:
310 case CMD_REINITIALIZE_STATUS_BYTE:
319 int nreg = wr_tmp[wr_ptr];
321 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR[%d,%d]=%2x\n"), nreg >> 3, nreg & 7, data);
325 if(++wr_ptr >= wr_num) {
328 if(nreg == GET_REGNUM(INTERRUPT_CTRL)) {
331 wr_tmp[wr_num++] = GET_REGNUM(PULSE_CTRL);
334 wr_tmp[wr_num++] = GET_REGNUM(INTERRUPT_VECTOR);
337 } else if(wr_tmp[wr_num] == GET_REGNUM(READ_MASK)) {
339 update_read_buffer();
344 uint32_t Z80DMA::read_io8(uint32_t addr)
346 // return status if read buffer is empty (from Xmillenium)
348 return status | (now_ready() ? 0 : 2) | (req_intr ? 0 : 8);
350 uint32_t data = rr_tmp[rr_ptr];
353 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: RR[%d]=%2x\n"), rr_ptr, data);
355 if(++rr_ptr >= rr_num) {
361 void Z80DMA::write_signal(int id, uint32_t data, uint32_t mask)
363 // ready signal (wired-or)
364 bool prev_ready = now_ready();
371 if(!prev_ready && now_ready()) {
373 request_intr(INT_RDY);
375 //#ifndef SINGLE_MODE_DMA
376 if(!_SINGLE_MODE_DMA) do_dma();
381 bool Z80DMA::now_ready()
386 // FIXME: DRQ active is really L, but FDC class sends H
387 if(READY_ACTIVE_HIGH) {
394 void Z80DMA::update_read_buffer()
396 // note: return current count and address (from Xmillenium)
398 if(READ_MASK & 0x01) {
399 rr_tmp[rr_num++] = status | (now_ready() ? 0 : 2) | (req_intr ? 0 : 8);
401 if(READ_MASK & 0x02) {
402 rr_tmp[rr_num++] = upcount & 0xff;//BLOCKLEN_L;
404 if(READ_MASK & 0x04) {
405 rr_tmp[rr_num++] = upcount >> 8;//BLOCKLEN_H;
407 if(READ_MASK & 0x08) {
408 rr_tmp[rr_num++] = addr_a & 0xff;//PORTA_ADDRESS_L;
410 if(READ_MASK & 0x10) {
411 rr_tmp[rr_num++] = addr_a >> 8;//PORTA_ADDRESS_H;
413 if(READ_MASK & 0x20) {
414 rr_tmp[rr_num++] = addr_b & 0xff;//PORTB_ADDRESS_L;
416 if(READ_MASK & 0x40) {
417 rr_tmp[rr_num++] = addr_b >> 8;//PORTB_ADDRESS_H;
421 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
423 void Z80DMA::do_dma()
428 bool occured = false;
429 bool finished = false;
432 // from Xmillenium (thanks Y.S.)
435 } else if(BLOCKLEN == 0xffff) {
436 blocklen = (int)65536;
438 blocklen = BLOCKLEN + 1;
441 // Workaround of MinGW's (older) GCC.
442 // messages: crosses initialization of 'int wait_w' etc.
444 int wait_r = 0, wait_w = 0;
446 //#ifndef SINGLE_MODE_DMA
449 while(enabled && now_ready() && !(upcount == blocklen || found)) {
451 if(upcount < blocklen) {
465 if(PORTA_IS_SOURCE) {
467 data = d_mem->read_dma_data8w(addr_a, &wait_r);
469 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: RAM[%4x]=%2x -> "), addr_a, data);
472 data = d_io->read_dma_io8w(addr_a, &wait_r);
474 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: INP(%4x)=%2x -> "), addr_a, data);
478 if(CHECK_WAIT_SIGNAL) {
479 d_cpu->set_extra_clock(PORTA_CYCLE_LEN + wait_r);
481 d_cpu->set_extra_clock(PORTA_CYCLE_LEN);
486 data = d_mem->read_dma_data8w(addr_b, &wait_r);
488 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: RAM[%4x]=%2x -> "), addr_b, data);
491 data = d_io->read_dma_io8w(addr_b, &wait_r);
493 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: INP(%4x)=%2x -> "), addr_b, data);
497 if(CHECK_WAIT_SIGNAL) {
498 d_cpu->set_extra_clock(PORTB_CYCLE_LEN + wait_r);
500 d_cpu->set_extra_clock(PORTB_CYCLE_LEN);
506 if(TRANSFER_MODE == TM_TRANSFER || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
507 if(PORTA_IS_SOURCE) {
510 if(_DMA_DEBUG) this->out_debug_log(_T("RAM[%4x]\n"), addr_b);
512 d_mem->write_dma_data8w(addr_b, data, &wait_w);
515 if(_DMA_DEBUG) this->out_debug_log(_T("OUT(%4x)\n"), addr_b);
517 d_io->write_dma_io8w(addr_b, data, &wait_w);
520 if(CHECK_WAIT_SIGNAL) {
521 d_cpu->set_extra_clock(PORTB_CYCLE_LEN + wait_w);
523 d_cpu->set_extra_clock(PORTB_CYCLE_LEN);
529 if(_DMA_DEBUG) this->out_debug_log(_T("RAM[%4x]\n"), addr_a);
531 d_mem->write_dma_data8w(addr_a, data, &wait_w);
534 if(_DMA_DEBUG) this->out_debug_log(_T("OUT(%4x)\n"), addr_a);
536 d_io->write_dma_io8w(addr_a, data, &wait_w);
539 if(CHECK_WAIT_SIGNAL) {
540 d_cpu->set_extra_clock(PORTA_CYCLE_LEN + wait_w);
542 d_cpu->set_extra_clock(PORTA_CYCLE_LEN);
549 if(OPERATING_MODE == OM_BYTE) {
554 if(TRANSFER_MODE == TM_SEARCH || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
555 if((data & MASK_BYTE) == (MATCH_BYTE & MASK_BYTE)) {
562 if(found || (BLOCKLEN == 0 && !now_ready())) {
563 if(upcount < blocklen) {
570 if(PORTA_IS_SOURCE) {
571 addr_a += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
573 addr_b += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
575 if(TRANSFER_MODE == TM_TRANSFER || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
576 if(PORTA_IS_SOURCE) {
577 addr_b += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
579 addr_a += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
582 //#ifdef SINGLE_MODE_DMA
583 if(_SINGLE_MODE_DMA) {
584 if(OPERATING_MODE == OM_BYTE) {
594 this->out_debug_log(_T("Z80DMA: COUNT=%d BLOCKLEN=%d FOUND=%d\n"), upcount, blocklen, found ? 1 : 0);
598 if(occured && (upcount == blocklen || found)) {
600 if(AUTO_RESTART && upcount == blocklen && !force_ready) {
602 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: AUTO RESTART !!!\n"));
605 //#ifndef SINGLE_MODE_DMA
606 if(!_SINGLE_MODE_DMA) goto restart;
615 if(upcount != blocklen) {
622 if(upcount == blocklen) {
623 // transfer/search done
624 if(INT_ON_END_OF_BLOCK) {
625 level |= INT_END_OF_BLOCK;
644 if(finished || OPERATING_MODE == OM_BYTE || (OPERATING_MODE == OM_BURST && !now_ready())) {
649 void Z80DMA::request_bus()
653 //#ifdef SINGLE_MODE_DMA
654 if(_SINGLE_MODE_DMA) d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
656 d_cpu->set_extra_clock(2);
662 void Z80DMA::release_bus()
666 //#ifdef SINGLE_MODE_DMA
667 if(_SINGLE_MODE_DMA) d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
669 if(OPERATING_MODE == OM_BYTE) {
670 d_cpu->set_extra_clock(1);
672 d_cpu->set_extra_clock(2);
679 void Z80DMA::request_intr(int level)
681 if(!in_service && INTERRUPT_ENABLE) {
684 if(STATUS_AFFECTS_VECTOR) {
685 vector = (uint8_t)((INTERRUPT_VECTOR & 0xf9) | (level << 1));
687 vector = (uint8_t)INTERRUPT_VECTOR;
693 void Z80DMA::set_intr_iei(bool val)
701 #define set_intr_oei(val) { \
704 if(d_child != NULL) { \
705 d_child->set_intr_iei(oei); \
710 void Z80DMA::update_intr()
715 if((next = iei) == true) {
723 if((next = iei) == true) {
724 next = (!in_service && req_intr);
727 d_cpu->set_intr_line(next, true, intr_bit);
731 uint32_t Z80DMA::get_intr_ack()
735 // invalid interrupt status
737 } else if(req_intr) {
744 if(d_child != NULL) {
745 return d_child->get_intr_ack();
750 void Z80DMA::notify_intr_reti()
758 if(d_child != NULL) {
759 d_child->notify_intr_reti();
763 #define STATE_VERSION 2
765 bool Z80DMA::process_state(FILEIO* state_fio, bool loading)
767 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
770 if(!state_fio->StateCheckInt32(this_device_id)) {
773 //state_fio->StateBuffer(®s, sizeof(regs), 1);
775 for(int i = 0; i < 7; i++) {
776 for(int j = 0; j < 8; j++) {
777 state_fio->StateUint16(regs.m[i][j]);
780 for(int i = 0; i < (6 * 8 + 1 + 1); i++) {
781 state_fio->StateUint16(regs.t[i]);
784 state_fio->StateUint8(status);
785 //state_fio->StateBuffer(wr_tmp, sizeof(wr_tmp), 1);
786 for(int i = 0; i < (sizeof(wr_tmp) / sizeof(uint16_t)); i++) {
787 state_fio->StateUint16(wr_tmp[i]);
789 state_fio->StateInt32(wr_num);
790 state_fio->StateInt32(wr_ptr);
791 //state_fio->StateBuffer(rr_tmp, sizeof(rr_tmp), 1);
792 for(int i = 0; i < (sizeof(rr_tmp) / sizeof(uint16_t)); i++) {
793 state_fio->StateUint16(rr_tmp[i]);
795 state_fio->StateInt32(rr_num);
796 state_fio->StateInt32(rr_ptr);
797 state_fio->StateBool(enabled);
798 state_fio->StateUint32(ready);
799 state_fio->StateBool(force_ready);
800 state_fio->StateUint16(addr_a);
801 state_fio->StateUint16(addr_b);
802 state_fio->StateInt32(upcount);
803 state_fio->StateInt32(blocklen);
804 state_fio->StateBool(dma_stop);
805 state_fio->StateBool(bus_master);
806 state_fio->StateBool(req_intr);
807 state_fio->StateBool(in_service);
808 state_fio->StateUint8(vector);
809 state_fio->StateBool(iei);
810 state_fio->StateBool(oei);
811 state_fio->StateUint32(intr_bit);