OSDN Git Service

92c58cb45598bc72fe344b47f62725c05a2e7864
[csp-qt/common_source_project-fm7.git] / source / src / vm / z80dma.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : MAME Z80DMA / Xmillenium
5         Author : Takeda.Toshiya
6                  Y.S. (Xmil106RS)
7         Date   : 2011.04.96-
8
9         [ Z80DMA ]
10 */
11
12 #include "z80dma.h"
13
14 //#define DMA_DEBUG
15
16 #define CMD_RESET                               0xc3
17 #define CMD_RESET_PORT_A_TIMING                 0xc7
18 #define CMD_RESET_PORT_B_TIMING                 0xcb
19 #define CMD_LOAD                                0xcf
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
32
33 #define TM_TRANSFER             1
34 #define TM_SEARCH               2
35 #define TM_SEARCH_TRANSFER      3
36
37 #define OM_BYTE                 0
38 #define OM_CONTINUOUS           1
39 #define OM_BURST                2
40
41 #define INT_RDY                 0
42 #define INT_MATCH               1
43 #define INT_END_OF_BLOCK        2
44
45 #define GET_REGNUM(r)           (&(r) - &(WR0))
46
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]
54
55 #define PORTA_ADDRESS_L         regs.m[0][1]
56 #define PORTA_ADDRESS_H         regs.m[0][2]
57
58 #define BLOCKLEN_L              regs.m[0][3]
59 #define BLOCKLEN_H              regs.m[0][4]
60
61 #define PORTA_TIMING            regs.m[1][1]
62 #define PORTB_TIMING            regs.m[2][1]
63
64 #define MASK_BYTE               regs.m[3][1]
65 #define MATCH_BYTE              regs.m[3][2]
66
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]
72
73 #define READ_MASK               regs.m[6][1]
74
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)
78
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)
85
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)
88
89 #define PORTA_IS_SOURCE         ((WR0 >> 2) & 1)
90 #define PORTB_IS_SOURCE         (!PORTA_IS_SOURCE)
91 #define TRANSFER_MODE           (WR0 & 3)
92
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)
97
98 #define STOP_ON_MATCH           ((WR3 >> 2) & 1)
99
100 #define OPERATING_MODE          ((WR4 >> 5) & 3)
101
102 #define READY_ACTIVE_HIGH       ((WR5 >> 3) & 1)
103 #define CHECK_WAIT_SIGNAL       ((WR5 >> 4) & 1)
104 #define AUTO_RESTART            ((WR5 >> 5) & 1)
105
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)
111
112 void Z80DMA::initialize()
113 {
114         DEVICE::initialize();
115         _SINGLE_MODE_DMA = osd->check_feature(_T("SINGLE_MODE_DMA"));
116         _DMA_DEBUG = osd->check_feature(_T("DMA_DEBUG"));
117 }
118
119 void Z80DMA::reset()
120 {
121         WR3 &= ~0x20; // disable interrupt
122         status = 0x30;
123         
124         PORTA_TIMING |= 3;
125         PORTB_TIMING |= 3;
126         
127         wr_num = wr_ptr = 0;
128         rr_num = rr_ptr = 0;
129         
130         enabled = false;
131         ready = 0;
132         force_ready = false;
133         
134         iei = oei = true;
135         req_intr = in_service = false;
136         vector = 0;
137         
138         upcount = 0;
139         blocklen = 0;
140         dma_stop = false;
141         bus_master = false;
142 }
143
144 void Z80DMA::write_io8(uint32_t addr, uint32_t data)
145 {
146         if(wr_num == 0) {
147                 if((data & 0x87) == 0) {
148 //#ifdef DMA_DEBUG
149                         if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR2=%2x\n"), data);
150 //#endif
151                         WR2 = data;
152                         if(data & 0x40) {
153                                 wr_tmp[wr_num++] = GET_REGNUM(PORTB_TIMING);
154                         }
155                 } else if((data & 0x87) == 4) {
156 //#ifdef DMA_DEBUG
157                         if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR1=%2x\n"), data);
158 //#endif
159                         WR1 = data;
160                         if(data & 0x40) {
161                                 wr_tmp[wr_num++] = GET_REGNUM(PORTA_TIMING);
162                         }
163                 } else if((data & 0x80) == 0) {
164 //#ifdef DMA_DEBUG
165                         if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR0=%2x\n"), data);
166 //#endif
167                         WR0 = data;
168                         if(data & 0x08) {
169                                 wr_tmp[wr_num++] = GET_REGNUM(PORTA_ADDRESS_L);
170                         }
171                         if(data & 0x10) {
172                                 wr_tmp[wr_num++] = GET_REGNUM(PORTA_ADDRESS_H);
173                         }
174                         if(data & 0x20) {
175                                 wr_tmp[wr_num++] = GET_REGNUM(BLOCKLEN_L);
176                         }
177                         if(data & 0x40) {
178                                 wr_tmp[wr_num++] = GET_REGNUM(BLOCKLEN_H);
179                         }
180                 } else if((data & 0x83) == 0x80) {
181 //#ifdef DMA_DEBUG
182                         if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR3=%2x\n"), data);
183 //#endif
184                         WR3 = data;
185                         if(data & 0x08) {
186                                 wr_tmp[wr_num++] = GET_REGNUM(MASK_BYTE);
187                         }
188                         if(data & 0x10) {
189                                 wr_tmp[wr_num++] = GET_REGNUM(MATCH_BYTE);
190                         }
191                         enabled = ((data & 0x40) != 0);
192                 } else if((data & 0x83) == 0x81) {
193 //#ifdef DMA_DEBUG
194                         if(_DMA_DEBUG)  this->out_debug_log(_T("Z80DMA: WR4=%2x\n"), data);
195 //#endif
196                         WR4 = data;
197                         if(data & 0x04) {
198                                 wr_tmp[wr_num++] = GET_REGNUM(PORTB_ADDRESS_L);
199                         }
200                         if(data & 0x08) {
201                                 wr_tmp[wr_num++] = GET_REGNUM(PORTB_ADDRESS_H);
202                         }
203                         if(data & 0x10) {
204                                 wr_tmp[wr_num++] = GET_REGNUM(INTERRUPT_CTRL);
205                         }
206                 } else if((data & 0xc7) == 0x82) {
207 //#ifdef DMA_DEBUG
208                         if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR5=%2x\n"), data);
209 //#endif
210                         WR5 = data;
211                 } else if((data & 0x83) == 0x83) {
212 //#ifdef DMA_DEBUG
213                         if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR6=%2x\n"), data);
214 //#endif
215                         WR6 = data;
216                         enabled = false;
217                         
218                         // check dma stop (from Xmil106RS)
219                         switch (data) {
220                         case CMD_CONTINUE:
221                         case CMD_READ_STATUS_BYTE:
222                         case CMD_INITIATE_READ_SEQUENCE:
223                         case CMD_ENABLE_DMA:
224                         case CMD_DISABLE_DMA:
225                         case CMD_READ_MASK_FOLLOWS:
226                                 break;
227                         default:
228                                 dma_stop = false;
229                                 break;
230                         }
231                         
232                         // run command
233                         switch (data) {
234                         case CMD_ENABLE_AFTER_RETI:
235                                 break;
236                         case CMD_READ_STATUS_BYTE:
237                                 // force to read status (from Xmillenium)
238                                 READ_MASK = 1;
239                                 update_read_buffer();
240                                 break;
241                         case CMD_RESET_AND_DISABLE_INTERRUPTS:
242                                 WR3 &= ~0x20;
243                                 req_intr = false;
244                                 update_intr();
245                                 force_ready = false;
246                                 break;
247                         case CMD_INITIATE_READ_SEQUENCE:
248                                 update_read_buffer();
249                                 break;
250                         case CMD_RESET:
251                                 enabled = false;
252                                 force_ready = false;
253                                 req_intr = false;
254                                 update_intr();
255                                 status = 0x30;
256                                 // reset timing
257                                 PORTA_TIMING |= 3;
258                                 PORTB_TIMING |= 3;
259                                 // reset upcount
260                                 WR3 &= ~0x20;
261                                 upcount = 0;
262                                 // reset auto repeat and wait functions
263                                 WR5 &= ~0x30;
264                                 break;
265                         case CMD_LOAD:
266                                 force_ready = false;
267                                 addr_a = PORTA_ADDRESS;
268                                 addr_b = PORTB_ADDRESS;
269                                 upcount = 0;//BLOCKLEN;
270                                 status |= 0x30;
271                                 break;
272                         case CMD_DISABLE_DMA:
273                                 enabled = false;
274                                 break;
275                         case CMD_ENABLE_DMA:
276                                 enabled = true;
277 //#ifndef SINGLE_MODE_DMA
278                                 if(!_SINGLE_MODE_DMA) do_dma();
279 //#endif
280                                 break;
281                         case CMD_READ_MASK_FOLLOWS:
282                                 wr_tmp[wr_num++] = GET_REGNUM(READ_MASK);
283                                 break;
284                         case CMD_CONTINUE:
285                                 upcount = (dma_stop && upcount != blocklen) ? -1 : 0;
286                                 enabled = true;
287                                 status |= 0x30;
288 //#ifndef SINGLE_MODE_DMA
289                                 if(!_SINGLE_MODE_DMA) do_dma();
290 //#endif
291                                 break;
292                         case CMD_RESET_PORT_A_TIMING:
293                                 PORTA_TIMING |= 3;
294                                 break;
295                         case CMD_RESET_PORT_B_TIMING:
296                                 PORTB_TIMING |= 3;
297                                 break;
298                         case CMD_FORCE_READY:
299                                 force_ready = true;
300 //#ifndef SINGLE_MODE_DMA
301                                 if(!_SINGLE_MODE_DMA) do_dma();
302 //#endif
303                                 break;
304                         case CMD_ENABLE_INTERRUPTS:
305                                 WR3 |= 0x20;
306                                 break;
307                         case CMD_DISABLE_INTERRUPTS:
308                                 WR3 &= ~0x20;
309                                 break;
310                         case CMD_REINITIALIZE_STATUS_BYTE:
311                                 status |= 0x30;
312                                 req_intr = false;
313                                 update_intr();
314                                 break;
315                         }
316                 }
317                 wr_ptr = 0;
318         } else {
319                 int nreg = wr_tmp[wr_ptr];
320 //#ifdef DMA_DEBUG
321                 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: WR[%d,%d]=%2x\n"), nreg >> 3, nreg & 7, data);
322 //#endif
323                 regs.t[nreg] = data;
324                 
325                 if(++wr_ptr >= wr_num) {
326                         wr_num = 0;
327                 }
328                 if(nreg == GET_REGNUM(INTERRUPT_CTRL)) {
329                         wr_num=0;
330                         if(data & 0x08) {
331                                 wr_tmp[wr_num++] = GET_REGNUM(PULSE_CTRL);
332                         }
333                         if(data & 0x10) {
334                                 wr_tmp[wr_num++] = GET_REGNUM(INTERRUPT_VECTOR);
335                         }
336                         wr_ptr = 0;
337                 } else if(wr_tmp[wr_num] == GET_REGNUM(READ_MASK)) {
338                         // from Xmillenium
339                         update_read_buffer();
340                 }
341         }
342 }
343
344 uint32_t Z80DMA::read_io8(uint32_t addr)
345 {
346         // return status if read buffer is empty (from Xmillenium)
347         if(rr_num == 0) {
348                 return status | (now_ready() ? 0 : 2) | (req_intr ? 0 : 8);
349         }
350         uint32_t data = rr_tmp[rr_ptr];
351         
352 //#ifdef DMA_DEBUG
353         if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: RR[%d]=%2x\n"), rr_ptr, data);
354 //#endif
355         if(++rr_ptr >= rr_num) {
356                 rr_ptr = 0;
357         }
358         return data;
359 }
360
361 void Z80DMA::write_signal(int id, uint32_t data, uint32_t mask)
362 {
363         // ready signal (wired-or)
364         bool prev_ready = now_ready();
365         
366         if(data & mask) {
367                 ready |= (1 << id);
368         } else {
369                 ready &= ~(1 << id);
370         }
371         if(!prev_ready && now_ready()) {
372                 if(INT_ON_READY) {
373                         request_intr(INT_RDY);
374                 }
375 //#ifndef SINGLE_MODE_DMA
376                 if(!_SINGLE_MODE_DMA) do_dma();
377 //#endif
378         }
379 }
380
381 bool Z80DMA::now_ready()
382 {
383         if(force_ready) {
384                 return true;
385         }
386         // FIXME: DRQ active is really L, but FDC class sends H
387         if(READY_ACTIVE_HIGH) {
388                 return (ready == 0);
389         } else {
390                 return (ready != 0);
391         }
392 }
393
394 void Z80DMA::update_read_buffer()
395 {
396         // note: return current count and address (from Xmillenium)
397         rr_ptr = rr_num = 0;
398         if(READ_MASK & 0x01) {
399                 rr_tmp[rr_num++] = status | (now_ready() ? 0 : 2) | (req_intr ? 0 : 8);
400         }
401         if(READ_MASK & 0x02) {
402                 rr_tmp[rr_num++] = upcount & 0xff;//BLOCKLEN_L;
403         }
404         if(READ_MASK & 0x04) {
405                 rr_tmp[rr_num++] = upcount >> 8;//BLOCKLEN_H;
406         }
407         if(READ_MASK & 0x08) {
408                 rr_tmp[rr_num++] = addr_a & 0xff;//PORTA_ADDRESS_L;
409         }
410         if(READ_MASK & 0x10) {
411                 rr_tmp[rr_num++] = addr_a >> 8;//PORTA_ADDRESS_H;
412         }
413         if(READ_MASK & 0x20) {
414                 rr_tmp[rr_num++] = addr_b & 0xff;//PORTB_ADDRESS_L;
415         }
416         if(READ_MASK & 0x40) {
417                 rr_tmp[rr_num++] = addr_b >> 8;//PORTB_ADDRESS_H;
418         }
419 }
420
421 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
422
423 void Z80DMA::do_dma()
424 {
425         if(!enabled) {
426                 return;
427         }
428         bool occured = false;
429         bool finished = false;
430         bool found = false;
431         
432         // from Xmillenium (thanks Y.S.)
433         if(BLOCKLEN == 0) {
434                 blocklen = 65537;
435         } else if(BLOCKLEN == 0xffff) {
436                 blocklen = (int)65536;
437         } else {
438                 blocklen = BLOCKLEN + 1;
439         }
440         
441         // Workaround of MinGW's (older) GCC.
442         // messages: crosses initialization of 'int wait_w' etc.
443         uint32_t data = 0;
444         int wait_r = 0, wait_w = 0;
445         
446 //#ifndef SINGLE_MODE_DMA
447 restart:
448 //#endif
449         while(enabled && now_ready() && !(upcount == blocklen || found)) {
450                 if(dma_stop) {
451                         if(upcount < blocklen) {
452                                 upcount++;
453                         }
454                         dma_stop = false;
455                         goto inc_ports;
456                 }
457                 
458                 // request bus
459                 request_bus();
460                 
461                 // read
462                 data = 0;
463                 wait_r = wait_w = 0;
464                 
465                 if(PORTA_IS_SOURCE) {
466                         if(PORTA_MEMORY) {
467                                 data = d_mem->read_dma_data8w(addr_a, &wait_r);
468 //#ifdef DMA_DEBUG
469                                 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: RAM[%4x]=%2x -> "), addr_a, data);
470 //#endif
471                         } else {
472                                 data = d_io->read_dma_io8w(addr_a, &wait_r);
473 //#ifdef DMA_DEBUG
474                                 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: INP(%4x)=%2x -> "), addr_a, data);
475 //#endif
476                         }
477                         if(d_cpu != NULL) {
478                                 if(CHECK_WAIT_SIGNAL) {
479                                         d_cpu->set_extra_clock(PORTA_CYCLE_LEN + wait_r);
480                                 } else {
481                                         d_cpu->set_extra_clock(PORTA_CYCLE_LEN);
482                                 }
483                         }
484                 } else {
485                         if(PORTB_MEMORY) {
486                                 data = d_mem->read_dma_data8w(addr_b, &wait_r);
487 //#ifdef DMA_DEBUG
488                                 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: RAM[%4x]=%2x -> "), addr_b, data);
489 //#endif
490                         } else {
491                                 data = d_io->read_dma_io8w(addr_b, &wait_r);
492 //#ifdef DMA_DEBUG
493                                 if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: INP(%4x)=%2x -> "), addr_b, data);
494 //#endif
495                         }
496                         if(d_cpu != NULL) {
497                                 if(CHECK_WAIT_SIGNAL) {
498                                         d_cpu->set_extra_clock(PORTB_CYCLE_LEN + wait_r);
499                                 } else {
500                                         d_cpu->set_extra_clock(PORTB_CYCLE_LEN);
501                                 }
502                         }
503                 }
504                 
505                 // write
506                 if(TRANSFER_MODE == TM_TRANSFER || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
507                         if(PORTA_IS_SOURCE) {
508                                 if(PORTB_MEMORY) {
509 //#ifdef DMA_DEBUG
510                                         if(_DMA_DEBUG) this->out_debug_log(_T("RAM[%4x]\n"), addr_b);
511 //#endif
512                                         d_mem->write_dma_data8w(addr_b, data, &wait_w);
513                                 } else {
514 //#ifdef DMA_DEBUG
515                                         if(_DMA_DEBUG) this->out_debug_log(_T("OUT(%4x)\n"), addr_b);
516 //#endif
517                                         d_io->write_dma_io8w(addr_b, data, &wait_w);
518                                 }
519                                 if(d_cpu != NULL) {
520                                         if(CHECK_WAIT_SIGNAL) {
521                                                 d_cpu->set_extra_clock(PORTB_CYCLE_LEN + wait_w);
522                                         } else {
523                                                 d_cpu->set_extra_clock(PORTB_CYCLE_LEN);
524                                         }
525                                 }
526                         } else {
527                                 if(PORTA_MEMORY) {
528 //#ifdef DMA_DEBUG
529                                         if(_DMA_DEBUG) this->out_debug_log(_T("RAM[%4x]\n"), addr_a);
530 //#endif
531                                         d_mem->write_dma_data8w(addr_a, data, &wait_w);
532                                 } else {
533 //#ifdef DMA_DEBUG
534                                         if(_DMA_DEBUG) this->out_debug_log(_T("OUT(%4x)\n"), addr_a);
535 //#endif
536                                         d_io->write_dma_io8w(addr_a, data, &wait_w);
537                                 }
538                                 if(d_cpu != NULL) {
539                                         if(CHECK_WAIT_SIGNAL) {
540                                                 d_cpu->set_extra_clock(PORTA_CYCLE_LEN + wait_w);
541                                         } else {
542                                                 d_cpu->set_extra_clock(PORTA_CYCLE_LEN);
543                                         }
544                                 }
545                         }
546                 }
547                 
548                 // release bus
549                 if(OPERATING_MODE == OM_BYTE) {
550                         release_bus();
551                 }
552                 
553                 // search
554                 if(TRANSFER_MODE == TM_SEARCH || TRANSFER_MODE == TM_SEARCH_TRANSFER) {
555                         if((data & MASK_BYTE) == (MATCH_BYTE & MASK_BYTE)) {
556                                 found = true;
557                         }
558                 }
559                 upcount++;
560                 occured = true;
561                 
562                 if(found || (BLOCKLEN == 0 && !now_ready())) {
563                         if(upcount < blocklen) {
564                                 upcount--;
565                         }
566                         dma_stop = true;
567                         break;
568                 }
569 inc_ports:
570                 if(PORTA_IS_SOURCE) {
571                         addr_a += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
572                 } else {
573                         addr_b += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
574                 }
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;
578                         } else {
579                                 addr_a += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
580                         }
581                 }
582 //#ifdef SINGLE_MODE_DMA
583                 if(_SINGLE_MODE_DMA) {
584                         if(OPERATING_MODE == OM_BYTE) {
585                                 break;
586                         }
587                 }
588 //#endif
589         }
590         
591 //#ifdef DMA_DEBUG
592         if(_DMA_DEBUG) {
593                 if(occured) {
594                         this->out_debug_log(_T("Z80DMA: COUNT=%d BLOCKLEN=%d FOUND=%d\n"), upcount, blocklen, found ? 1 : 0);
595                 }
596         }
597 //#endif
598         if(occured && (upcount == blocklen || found)) {
599                 // auto restart
600                 if(AUTO_RESTART && upcount == blocklen && !force_ready) {
601 //#ifdef DMA_DEBUG
602                         if(_DMA_DEBUG) this->out_debug_log(_T("Z80DMA: AUTO RESTART !!!\n"));
603 //#endif
604                         upcount = 0;
605 //#ifndef SINGLE_MODE_DMA
606                         if(!_SINGLE_MODE_DMA) goto restart;
607 //#endif
608                 }
609                 
610                 // update status
611                 status = 1;
612                 if(!found) {
613                         status |= 0x10;
614                 }
615                 if(upcount != blocklen) {
616                         status |= 0x20;
617                 }
618                 enabled = false;
619                 
620                 // request interrupt
621                 int level = 0;
622                 if(upcount == blocklen) {
623                         // transfer/search done
624                         if(INT_ON_END_OF_BLOCK) {
625                                 level |= INT_END_OF_BLOCK;
626                         }
627                         finished = true;
628                 }
629                 if(found) {
630                         // match found
631                         if(INT_ON_MATCH) {
632                                 level |= INT_MATCH;
633                         }
634                         if(STOP_ON_MATCH) {
635                                 finished = true;
636                         }
637                 }
638                 if(level) {
639                         request_intr(level);
640                 }
641         }
642         
643         // release bus
644         if(finished || OPERATING_MODE == OM_BYTE || (OPERATING_MODE == OM_BURST && !now_ready())) {
645                 release_bus();
646         }
647 }
648
649 void Z80DMA::request_bus()
650 {
651         if(!bus_master) {
652                 if(d_cpu != NULL) {
653 //#ifdef SINGLE_MODE_DMA
654                         if(_SINGLE_MODE_DMA) d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
655 //#endif
656                         d_cpu->set_extra_clock(2);
657                 }
658                 bus_master = true;
659         }
660 }
661
662 void Z80DMA::release_bus()
663 {
664         if(bus_master) {
665                 if(d_cpu != NULL) {
666 //#ifdef SINGLE_MODE_DMA
667                         if(_SINGLE_MODE_DMA) d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
668 //#endif
669                         if(OPERATING_MODE == OM_BYTE) {
670                                 d_cpu->set_extra_clock(1);
671                         } else {
672                                 d_cpu->set_extra_clock(2);
673                         }
674                 }
675                 bus_master = false;
676         }
677 }
678
679 void Z80DMA::request_intr(int level)
680 {
681         if(!in_service && INTERRUPT_ENABLE) {
682                 req_intr = true;
683                 
684                 if(STATUS_AFFECTS_VECTOR) {
685                         vector = (uint8_t)((INTERRUPT_VECTOR & 0xf9) | (level << 1));
686                 } else {
687                         vector = (uint8_t)INTERRUPT_VECTOR;
688                 }
689                 update_intr();
690         }
691 }
692
693 void Z80DMA::set_intr_iei(bool val)
694 {
695         if(iei != val) {
696                 iei = val;
697                 update_intr();
698         }
699 }
700
701 #define set_intr_oei(val) { \
702         if(oei != val) { \
703                 oei = val; \
704                 if(d_child != NULL) { \
705                         d_child->set_intr_iei(oei); \
706                 } \
707         } \
708 }
709
710 void Z80DMA::update_intr()
711 {
712         bool next;
713         
714         // set oei signal
715         if((next = iei) == true) {
716                 if(in_service) {
717                         next = false;
718                 }
719         }
720         set_intr_oei(next);
721         
722         // set int signal
723         if((next = iei) == true) {
724                 next = (!in_service && req_intr);
725         }
726         if(d_cpu != NULL) {
727                 d_cpu->set_intr_line(next, true, intr_bit);
728         }
729 }
730
731 uint32_t Z80DMA::get_intr_ack()
732 {
733         // ack (M1=IORQ=L)
734         if(in_service) {
735                 // invalid interrupt status
736                 return 0xff;
737         } else if(req_intr) {
738                 req_intr = false;
739                 in_service = true;
740                 enabled = false;
741                 update_intr();
742                 return vector;
743         }
744         if(d_child != NULL) {
745                 return d_child->get_intr_ack();
746         }
747         return 0xff;
748 }
749
750 void Z80DMA::notify_intr_reti()
751 {
752         // detect RETI
753         if(in_service) {
754                 in_service = false;
755                 update_intr();
756                 return;
757         }
758         if(d_child != NULL) {
759                 d_child->notify_intr_reti();
760         }
761 }
762
763 #define STATE_VERSION   2
764
765 bool Z80DMA::process_state(FILEIO* state_fio, bool loading)
766 {
767         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
768                 return false;
769         }
770         if(!state_fio->StateCheckInt32(this_device_id)) {
771                 return false;
772         }
773         //state_fio->StateBuffer(&regs, sizeof(regs), 1);
774         {
775                 for(int i = 0; i < 7; i++) {
776                         for(int j = 0; j < 8; j++) {
777                                 state_fio->StateUint16(regs.m[i][j]);
778                         }
779                 }
780                 for(int i = 0; i < (6 * 8 + 1 + 1); i++) {
781                         state_fio->StateUint16(regs.t[i]);
782                 }
783         }
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]);
788         }
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]);
794         }
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);
812         return true;
813 }