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)
114 WR3 &= ~0x20; // disable interrupt
128 req_intr = in_service = false;
137 void Z80DMA::write_io8(uint32 addr, uint32 data)
140 if((data & 0x87) == 0) {
142 emu->out_debug_log(_T("Z80DMA: WR2=%2x\n"), data);
146 wr_tmp[wr_num++] = GET_REGNUM(PORTB_TIMING);
148 } else if((data & 0x87) == 4) {
150 emu->out_debug_log(_T("Z80DMA: WR1=%2x\n"), data);
154 wr_tmp[wr_num++] = GET_REGNUM(PORTA_TIMING);
156 } else if((data & 0x80) == 0) {
158 emu->out_debug_log(_T("Z80DMA: WR0=%2x\n"), data);
162 wr_tmp[wr_num++] = GET_REGNUM(PORTA_ADDRESS_L);
165 wr_tmp[wr_num++] = GET_REGNUM(PORTA_ADDRESS_H);
168 wr_tmp[wr_num++] = GET_REGNUM(BLOCKLEN_L);
171 wr_tmp[wr_num++] = GET_REGNUM(BLOCKLEN_H);
173 } else if((data & 0x83) == 0x80) {
175 emu->out_debug_log(_T("Z80DMA: WR3=%2x\n"), data);
179 wr_tmp[wr_num++] = GET_REGNUM(MASK_BYTE);
182 wr_tmp[wr_num++] = GET_REGNUM(MATCH_BYTE);
184 enabled = ((data & 0x40) != 0);
185 } else if((data & 0x83) == 0x81) {
187 emu->out_debug_log(_T("Z80DMA: WR4=%2x\n"), data);
191 wr_tmp[wr_num++] = GET_REGNUM(PORTB_ADDRESS_L);
194 wr_tmp[wr_num++] = GET_REGNUM(PORTB_ADDRESS_H);
197 wr_tmp[wr_num++] = GET_REGNUM(INTERRUPT_CTRL);
199 } else if((data & 0xc7) == 0x82) {
201 emu->out_debug_log(_T("Z80DMA: WR5=%2x\n"), data);
204 } else if((data & 0x83) == 0x83) {
206 emu->out_debug_log(_T("Z80DMA: WR6=%2x\n"), data);
211 // check dma stop (from Xmil106RS)
214 case CMD_READ_STATUS_BYTE:
215 case CMD_INITIATE_READ_SEQUENCE:
217 case CMD_DISABLE_DMA:
218 case CMD_READ_MASK_FOLLOWS:
227 case CMD_ENABLE_AFTER_RETI:
229 case CMD_READ_STATUS_BYTE:
230 // force to read status (from Xmillenium)
232 update_read_buffer();
234 case CMD_RESET_AND_DISABLE_INTERRUPTS:
240 case CMD_INITIATE_READ_SEQUENCE:
241 update_read_buffer();
255 // reset auto repeat and wait functions
260 addr_a = PORTA_ADDRESS;
261 addr_b = PORTB_ADDRESS;
262 upcount = 0;//BLOCKLEN;
265 case CMD_DISABLE_DMA:
270 #ifndef SINGLE_MODE_DMA
274 case CMD_READ_MASK_FOLLOWS:
275 wr_tmp[wr_num++] = GET_REGNUM(READ_MASK);
278 upcount = (dma_stop && upcount != blocklen) ? -1 : 0;
281 #ifndef SINGLE_MODE_DMA
285 case CMD_RESET_PORT_A_TIMING:
288 case CMD_RESET_PORT_B_TIMING:
291 case CMD_FORCE_READY:
293 #ifndef SINGLE_MODE_DMA
297 case CMD_ENABLE_INTERRUPTS:
300 case CMD_DISABLE_INTERRUPTS:
303 case CMD_REINITIALIZE_STATUS_BYTE:
312 int nreg = wr_tmp[wr_ptr];
314 emu->out_debug_log(_T("Z80DMA: WR[%d,%d]=%2x\n"), nreg >> 3, nreg & 7, data);
318 if(++wr_ptr >= wr_num) {
321 if(nreg == GET_REGNUM(INTERRUPT_CTRL)) {
324 wr_tmp[wr_num++] = GET_REGNUM(PULSE_CTRL);
327 wr_tmp[wr_num++] = GET_REGNUM(INTERRUPT_VECTOR);
330 } else if(wr_tmp[wr_num] == GET_REGNUM(READ_MASK)) {
332 update_read_buffer();
337 uint32 Z80DMA::read_io8(uint32 addr)
339 // return status if read buffer is empty (from Xmillenium)
341 return status | (now_ready() ? 0 : 2) | (req_intr ? 0 : 8);
343 uint32 data = rr_tmp[rr_ptr];
346 emu->out_debug_log(_T("Z80DMA: RR[%d]=%2x\n"), rr_ptr, data);
348 if(++rr_ptr >= rr_num) {
354 void Z80DMA::write_signal(int id, uint32 data, uint32 mask)
356 // ready signal (wired-or)
357 bool prev_ready = now_ready();
364 if(!prev_ready && now_ready()) {
366 request_intr(INT_RDY);
368 #ifndef SINGLE_MODE_DMA
374 bool Z80DMA::now_ready()
379 // FIXME: DRQ active is really L, but FDC class sends H
380 if(READY_ACTIVE_HIGH) {
387 void Z80DMA::update_read_buffer()
389 // note: return current count and address (from Xmillenium)
391 if(READ_MASK & 0x01) {
392 rr_tmp[rr_num++] = status | (now_ready() ? 0 : 2) | (req_intr ? 0 : 8);
394 if(READ_MASK & 0x02) {
395 rr_tmp[rr_num++] = upcount & 0xff;//BLOCKLEN_L;
397 if(READ_MASK & 0x04) {
398 rr_tmp[rr_num++] = upcount >> 8;//BLOCKLEN_H;
400 if(READ_MASK & 0x08) {
401 rr_tmp[rr_num++] = addr_a & 0xff;//PORTA_ADDRESS_L;
403 if(READ_MASK & 0x10) {
404 rr_tmp[rr_num++] = addr_a >> 8;//PORTA_ADDRESS_H;
406 if(READ_MASK & 0x20) {
407 rr_tmp[rr_num++] = addr_b & 0xff;//PORTB_ADDRESS_L;
409 if(READ_MASK & 0x40) {
410 rr_tmp[rr_num++] = addr_b >> 8;//PORTB_ADDRESS_H;
414 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
416 void Z80DMA::do_dma()
421 bool occured = false;
422 bool finished = false;
425 // from Xmillenium (thanks Y.S.)
428 } else if(BLOCKLEN == 0xffff) {
429 blocklen = (int)65536;
431 blocklen = BLOCKLEN + 1;
434 #ifndef SINGLE_MODE_DMA
437 while(enabled && now_ready() && !(upcount == blocklen || found)) {
439 if(upcount < blocklen) {
451 int wait_r = 0, wait_w = 0;
453 if(PORTA_IS_SOURCE) {
455 data = d_mem->read_dma_data8w(addr_a, &wait_r);
457 emu->out_debug_log(_T("Z80DMA: RAM[%4x]=%2x -> "), addr_a, data);
460 data = d_io->read_dma_io8w(addr_a, &wait_r);
462 emu->out_debug_log(_T("Z80DMA: INP(%4x)=%2x -> "), addr_a, data);
466 if(CHECK_WAIT_SIGNAL) {
467 d_cpu->set_extra_clock(PORTA_CYCLE_LEN + wait_r);
469 d_cpu->set_extra_clock(PORTA_CYCLE_LEN);
474 data = d_mem->read_dma_data8w(addr_b, &wait_r);
476 emu->out_debug_log(_T("Z80DMA: RAM[%4x]=%2x -> "), addr_b, data);
479 data = d_io->read_dma_io8w(addr_b, &wait_r);
481 emu->out_debug_log(_T("Z80DMA: INP(%4x)=%2x -> "), addr_b, data);
485 if(CHECK_WAIT_SIGNAL) {
486 d_cpu->set_extra_clock(PORTB_CYCLE_LEN + wait_r);
488 d_cpu->set_extra_clock(PORTB_CYCLE_LEN);
494 if(TRANSFER_MODE == TM_TRANSFER || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
495 if(PORTA_IS_SOURCE) {
498 emu->out_debug_log(_T("RAM[%4x]\n"), addr_b);
500 d_mem->write_dma_data8w(addr_b, data, &wait_w);
503 emu->out_debug_log(_T("OUT(%4x)\n"), addr_b);
505 d_io->write_dma_io8w(addr_b, data, &wait_w);
508 if(CHECK_WAIT_SIGNAL) {
509 d_cpu->set_extra_clock(PORTB_CYCLE_LEN + wait_w);
511 d_cpu->set_extra_clock(PORTB_CYCLE_LEN);
517 emu->out_debug_log(_T("RAM[%4x]\n"), addr_a);
519 d_mem->write_dma_data8w(addr_a, data, &wait_w);
522 emu->out_debug_log(_T("OUT(%4x)\n"), addr_a);
524 d_io->write_dma_io8w(addr_a, data, &wait_w);
527 if(CHECK_WAIT_SIGNAL) {
528 d_cpu->set_extra_clock(PORTA_CYCLE_LEN + wait_w);
530 d_cpu->set_extra_clock(PORTA_CYCLE_LEN);
537 if(OPERATING_MODE == OM_BYTE) {
542 if(TRANSFER_MODE == TM_SEARCH || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
543 if((data & MASK_BYTE) == (MATCH_BYTE & MASK_BYTE)) {
550 if(found || (BLOCKLEN == 0 && !now_ready())) {
551 if(upcount < blocklen) {
558 if(PORTA_IS_SOURCE) {
559 addr_a += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
561 addr_b += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
563 if(TRANSFER_MODE == TM_TRANSFER || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
564 if(PORTA_IS_SOURCE) {
565 addr_b += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
567 addr_a += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
570 #ifdef SINGLE_MODE_DMA
571 if(OPERATING_MODE == OM_BYTE) {
579 emu->out_debug_log(_T("Z80DMA: COUNT=%d BLOCKLEN=%d FOUND=%d\n"), upcount, blocklen, found ? 1 : 0);
582 if(occured && (upcount == blocklen || found)) {
584 if(AUTO_RESTART && upcount == blocklen && !force_ready) {
586 emu->out_debug_log(_T("Z80DMA: AUTO RESTART !!!\n"));
589 #ifndef SINGLE_MODE_DMA
599 if(upcount != blocklen) {
606 if(upcount == blocklen) {
607 // transfer/search done
608 if(INT_ON_END_OF_BLOCK) {
609 level |= INT_END_OF_BLOCK;
628 if(finished || OPERATING_MODE == OM_BYTE || (OPERATING_MODE == OM_BURST && !now_ready())) {
633 void Z80DMA::request_bus()
637 #ifdef SINGLE_MODE_DMA
638 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
640 d_cpu->set_extra_clock(2);
646 void Z80DMA::release_bus()
650 #ifdef SINGLE_MODE_DMA
651 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
653 if(OPERATING_MODE == OM_BYTE) {
654 d_cpu->set_extra_clock(1);
656 d_cpu->set_extra_clock(2);
663 void Z80DMA::request_intr(int level)
665 if(!in_service && INTERRUPT_ENABLE) {
668 if(STATUS_AFFECTS_VECTOR) {
669 vector = (uint8)((INTERRUPT_VECTOR & 0xf9) | (level << 1));
671 vector = (uint8)INTERRUPT_VECTOR;
677 void Z80DMA::set_intr_iei(bool val)
685 #define set_intr_oei(val) { \
688 if(d_child != NULL) { \
689 d_child->set_intr_iei(oei); \
694 void Z80DMA::update_intr()
699 if((next = iei) == true) {
707 if((next = iei) == true) {
708 next = (!in_service && req_intr);
711 d_cpu->set_intr_line(next, true, intr_bit);
715 uint32 Z80DMA::get_intr_ack()
719 // invalid interrupt status
721 } else if(req_intr) {
728 if(d_child != NULL) {
729 return d_child->get_intr_ack();
734 void Z80DMA::notify_intr_reti()
742 if(d_child != NULL) {
743 d_child->notify_intr_reti();
747 #define STATE_VERSION 1
749 void Z80DMA::save_state(FILEIO* state_fio)
751 state_fio->FputUint32(STATE_VERSION);
752 state_fio->FputInt32(this_device_id);
754 state_fio->Fwrite(®s, sizeof(regs), 1);
755 state_fio->FputUint8(status);
756 state_fio->Fwrite(wr_tmp, sizeof(wr_tmp), 1);
757 state_fio->FputInt32(wr_num);
758 state_fio->FputInt32(wr_ptr);
759 state_fio->Fwrite(rr_tmp, sizeof(rr_tmp), 1);
760 state_fio->FputInt32(rr_num);
761 state_fio->FputInt32(rr_ptr);
762 state_fio->FputBool(enabled);
763 state_fio->FputUint32(ready);
764 state_fio->FputBool(force_ready);
765 state_fio->FputUint16(addr_a);
766 state_fio->FputUint16(addr_b);
767 state_fio->FputInt32(upcount);
768 state_fio->FputInt32(blocklen);
769 state_fio->FputBool(dma_stop);
770 state_fio->FputBool(bus_master);
771 state_fio->FputBool(req_intr);
772 state_fio->FputBool(in_service);
773 state_fio->FputUint8(vector);
774 state_fio->FputBool(iei);
775 state_fio->FputBool(oei);
776 state_fio->FputUint32(intr_bit);
779 bool Z80DMA::load_state(FILEIO* state_fio)
781 if(state_fio->FgetUint32() != STATE_VERSION) {
784 if(state_fio->FgetInt32() != this_device_id) {
787 state_fio->Fread(®s, sizeof(regs), 1);
788 status = state_fio->FgetUint8();
789 state_fio->Fread(wr_tmp, sizeof(wr_tmp), 1);
790 wr_num = state_fio->FgetInt32();
791 wr_ptr = state_fio->FgetInt32();
792 state_fio->Fread(rr_tmp, sizeof(rr_tmp), 1);
793 rr_num = state_fio->FgetInt32();
794 rr_ptr = state_fio->FgetInt32();
795 enabled = state_fio->FgetBool();
796 ready = state_fio->FgetUint32();
797 force_ready = state_fio->FgetBool();
798 addr_a = state_fio->FgetUint16();
799 addr_b = state_fio->FgetUint16();
800 upcount = state_fio->FgetInt32();
801 blocklen = state_fio->FgetInt32();
802 dma_stop = state_fio->FgetBool();
803 bus_master = state_fio->FgetBool();
804 req_intr = state_fio->FgetBool();
805 in_service = state_fio->FgetBool();
806 vector = state_fio->FgetUint8();
807 iei = state_fio->FgetBool();
808 oei = state_fio->FgetBool();
809 intr_bit = state_fio->FgetUint32();