--- xmil/io/dmac.c 2004/08/11 16:09:04 1.4 +++ xmil/io/dmac.c 2009/03/23 15:02:25 1.8 @@ -6,59 +6,87 @@ #include "ievent.h" -static REG8 iswork(const DMAC *d) { +#define DMACMD(a) (((a) >> 2) & 0x1f) - REG8 r; - r = d->cmd; - if ((r & 3) == 0) return(FALSE); - if (d->enable == 0) return(FALSE); - if (d->ENDB_FLG != 0) return(FALSE); // mod - if (r & 2) { - if (d->MACH_FLG != 0) return(FALSE); // mod - } +static REG8 iswork(const DMAC *d) { + + if (d->enable == 0) return(0); + if (!(d->WR0 & 3)) return(0); +#if !defined(DMAS_STOIC) + if (d->ENDB_FLG != 0) return(0); + if ((d->WR0 & 2) && (d->MACH_FLG != 0)) return(0); +#else + if (!(d->flag & DMAF_ENDB)) return(0); + if ((d->WR0 & 2) && (!(d->flag & DMAF_MACH))) return(0); +#endif if (d->mode != 1) { - if ((d->WR[5] ^ d->ready) & 8) return(FALSE); + if ((d->WR5 ^ d->ready) & 8) return(0); } - return(TRUE); + return(1); } void dmac_sendready(BRESULT ready) { + DMAC *d; REG8 working; + d = &dma; if (!ready) { - dma.working = FALSE; - dma.ready = 8; +#if !defined(DMAS_STOIC) + d->working = FALSE; +#else + d->flag &= ~DMAF_WORKING; +#endif + d->ready = 8; } else { - dma.ready = 0; + d->ready = 0; working = iswork(&dma); - if (dma.working != working) { - dma.working = working; +#if !defined(DMAS_STOIC) + if (d->working != working) { + d->working = working; + nevent_forceexit(); + } +#else + if ((d->flag ^ working) & DMAF_WORKING) { + d->flag ^= DMAF_WORKING; nevent_forceexit(); } +#endif } } + BRESULT ieitem_dmac(UINT id) { + DMAC *d; REG8 vect; - if (dma.INT_ENBL) { + d = &dma; + if (d->INT_ENBL) { vect = 0; - if ((dma.INT_FLG & 1) && (dma.MACH_FLG)) { +#if !defined(DMAS_STOIC) + if ((d->INT_FLG & 1) && (d->MACH_FLG)) { + vect = 2; + } + else if ((d->INT_FLG & 2) && (d->ENDB_FLG)) { + vect = 4; + } +#else + if ((d->INT_FLG & 1) && (!(d->flag & DMAF_MACH))) { vect = 2; } - else if ((dma.INT_FLG & 2) && (dma.ENDB_FLG)) { + else if ((d->INT_FLG & 2) && (!(d->flag & DMAF_ENDB))) { vect = 4; } +#endif if (vect) { - if (dma.INT_FLG & 0x20) { - vect += (dma.INT_VCT & 0xf9); + if (d->INT_FLG & 0x20) { + vect += (d->INT_VCT & 0xf9); } else { - vect = dma.INT_VCT; + vect = d->INT_VCT; } Z80_INTERRUPT(vect); return(TRUE); @@ -69,283 +97,371 @@ BRESULT ieitem_dmac(UINT id) { } -// ---- +/* ---- */ -static void setdmareaddat(void) { +static void setdmareaddat(DMAC *d) { - UINT cnt; REG8 rrmsk; + UINT8 *ptr; - cnt = 0; - rrmsk = dma.RR_MSK; + rrmsk = d->RR_MSK; + ptr = d->rtbl; if (rrmsk & 0x01) { - dma.RR_TBL[cnt++] = offsetof(DMAC, RR); + *ptr++ = offsetof(DMAC, RR); } if (rrmsk & 0x02) { - dma.RR_TBL[cnt++] = offsetof(DMAC, BYT_N.b.l); + *ptr++ = offsetof(DMAC, leng.b.nl); } if (rrmsk & 0x04) { - dma.RR_TBL[cnt++] = offsetof(DMAC, BYT_N.b.h); + *ptr++ = offsetof(DMAC, leng.b.nh); } if (rrmsk & 0x08) { - dma.RR_TBL[cnt++] = offsetof(DMAC, CNT_A.b.l); + *ptr++ = offsetof(DMAC, cnt_a.b.addrl); } if (rrmsk & 0x10) { - dma.RR_TBL[cnt++] = offsetof(DMAC, CNT_A.b.h); + *ptr++ = offsetof(DMAC, cnt_a.b.addrh); } if (rrmsk & 0x20) { - dma.RR_TBL[cnt++] = offsetof(DMAC, CNT_B.b.l); + *ptr++ = offsetof(DMAC, cnt_b.b.addrl); } if (rrmsk & 0x40) { - dma.RR_TBL[cnt++] = offsetof(DMAC, CNT_B.b.h); + *ptr++ = offsetof(DMAC, cnt_b.b.addrh); } - dma.RR_CNT = (UINT8)cnt; - dma.RR_OFF = 0; + d->rcnt = (UINT8)(ptr - d->rtbl); + d->rptr = 0; } +static void enable(DMAC *d) { -void IOOUTCALL dmac_o(UINT port, REG8 value) { - - REG8 wr; REG8 working; - dma.enable = 0; - - if (!dma.WR_CNT) { - wr = 6; - dma.WR_CNT = 0; - dma.WR_OFF = 0; - if (!(value & 0x80)) { - if ((value & 3) != 0) { - wr = 0; - } - else if (value & 4) { - wr = 1; - } - else { - wr = 2; - } + d->enable = 1; + working = iswork(d); +#if !defined(DMAS_STOIC) + if (d->working != working) { + d->working = working; + if (d->mode == 1) { + z80dmap(); } else { - if ((value & 3) == 0) { - wr = 3; - } - else if (((value & 3) == 1) && (value >> 5) != 7) { - wr = 4; - } - else if (((value & 7) == 2) && (!(value & 0x40))) { - wr = 5; - } - else if ((value & 3) == 3) { - wr = 6; - } + nevent_forceexit(); + } + } +#else + if ((d->flag ^ working) & DMAF_WORKING) { + d->flag ^= DMAF_WORKING; + if (d->mode == 1) { + z80dmap(); } - dma.WR[wr] = value; - switch(wr) { - case 0: - dma.cmd = (UINT8)(value & 3); + else { + nevent_forceexit(); + } + } +#endif +} + +static void disable(DMAC *d) { + + if (!d->enable) + { + d->enable = 0; +#if !defined(DMAS_STOIC) + d->working = 0; +#else + d->flag &= ~DMAF_WORKING; +#endif + } +} + +void IOOUTCALL dmac_o(UINT port, REG8 value) { + + DMAC *d; + REG8 cmd; + REG8 mode; + + /* TRACEOUT(("out %.4x %.2x", port, value)); */ + + d = &dma; + if (!d->wcnt) { + disable(d); + d->wptr = 0; + if (!(value & 0x80)) { + if ((value & 3) != 0) { + d->WR0 = value; if (value & 0x08) { - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, ADR_A.b.l); + d->wtbl[d->wcnt++] = offsetof(DMAC, addr.b.al); } if (value & 0x10) { - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, ADR_A.b.h); + d->wtbl[d->wcnt++] = offsetof(DMAC, addr.b.ah); } if (value & 0x20) { - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, BYT_L.b.l); + d->wtbl[d->wcnt++] = offsetof(DMAC, leng.b.ll); } if (value & 0x40) { - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, BYT_L.b.h); + d->wtbl[d->wcnt++] = offsetof(DMAC, leng.b.lh); + } + } + else { + if (value & 4) { + d->cnt_a.b.flag = value; + } + else { + d->cnt_b.b.flag = value; } - break; - - case 1: - case 2: if (value & 0x40) { - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, dummydat); + d->wtbl[d->wcnt++] = offsetof(DMAC, dummydat); } - break; - - case 3: + } + } + else { + cmd = value & 3; + if (cmd == 0) { + /* d->WR3 = value; */ if (value & 0x08) { - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, MASK_BYT); + d->wtbl[d->wcnt++] = offsetof(DMAC, MASK_BYT); } if (value & 0x10) { - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, MACH_BYT); - } - dma.INT_ENBL = (UINT8)((value & 0x20)?1:0); - dma.enable = (UINT8)((value & 0x40)?1:0); - break; - - case 4: - dma.mode = (UINT8)((dma.WR[4] >> 5) & 3); - if (value & 0x04) { - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, ADR_B.b.l); - } - if (value & 0x08) { - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, ADR_B.b.h); + d->wtbl[d->wcnt++] = offsetof(DMAC, MACH_BYT); } - if (value & 0x10){ - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, INT_FLG); + d->INT_ENBL = (UINT8)((value & 0x20)?1:0); + if (value & 0x40) + { + enable(d); + } + } + else if (cmd == 1) { + mode = (REG8)(value & (3 << 5)); + if (mode != (3 << 5)) { + d->WR4 = value; + d->mode = (UINT8)(mode >> 5); + if (value & 0x04) { + d->wtbl[d->wcnt++] = offsetof(DMAC, addr.b.bl); + } + if (value & 0x08) { + d->wtbl[d->wcnt++] = offsetof(DMAC, addr.b.bh); + } + if (value & 0x10) { + d->wtbl[d->wcnt++] = offsetof(DMAC, INT_FLG); + } + } + } +#if 1 + else if (cmd == 2) { + if (!(value & 0x44)) { + d->WR5 = value; } - break; - - case 6: - switch(value) { - case 0x83: // dma disable - dma.enable = 0; + } +#else + else if (((value & 7) == 2) && (!(value & 0x40))) { + d->WR5 = value; + } +#endif + else if (cmd == 3) { + switch(DMACMD(value)) { + case DMACMD(0x83): /* dma disable */ break; - case 0x87: // dma enable - dma.enable = 1; + case DMACMD(0x87): /* dma enable */ +#if !defined(DMAS_STOIC) + d->increment = 0; +#else + d->flag &= ~DMAF_INCREMENT; +#endif + enable(d); break; - case 0x8b: // re-init status byte - dma.MACH_FLG = 0; - dma.ENDB_FLG = 0; + case DMACMD(0x8b): /* re-init status byte */ +#if !defined(DMAS_STOIC) + d->MACH_FLG = 0; + d->ENDB_FLG = 0; +#else + d->flag |= DMAF_MACH | DMAF_ENDB; +#endif break; - case 0xa7: // イニシエイトリードシーケンス - setdmareaddat(); + case DMACMD(0xa7): /* イニシエイトリードシーケンス */ + setdmareaddat(d); break; - case 0xab: // interrupt enable - dma.INT_ENBL = 1; + case DMACMD(0xab): /* interrupt enable */ + d->INT_ENBL = 1; break; - case 0xaf: // interrupt disable - dma.INT_ENBL = 0; + case DMACMD(0xaf): /* interrupt disable */ + d->INT_ENBL = 0; break; - case 0xb3: // force ready - dma.ready = (dma.WR[5] & 0x08); + case DMACMD(0xb3): /* force ready */ + d->ready = (d->WR5 & 0x08); break; - case 0xbb: // read mask follows - dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, RR_MSK); + case DMACMD(0xbb): /* read mask follows */ + d->wtbl[d->wcnt++] = offsetof(DMAC, RR_MSK); break; - case 0xbf: // read status byte - dma.RR_MSK = 1; - setdmareaddat(); + case DMACMD(0xbf): /* read status byte */ + d->RR_MSK = 1; + setdmareaddat(d); break; - case 0xc3: // reset - // ローグアライアンス // ver0.25 - dma.cmd = 0; - dma.enable = 0; - dma.INT_ENBL = 0; + case DMACMD(0xc3): /* reset */ + /* ローグアライアンス */ /* ver0.25 */ + d->WR0 &= ~3; /* 0でいいと思うケド… */ +#if !defined(DMAS_STOIC) + d->increment = 0; +#else + d->flag &= ~DMAF_INCREMENT; +#endif + /* d->enable = 0; */ + d->INT_ENBL = 0; break; - case 0xc7: // リセットタイミングA - case 0xcb: // リセットタイミングB + case DMACMD(0xc7): /* リセットタイミングA */ + case DMACMD(0xcb): /* リセットタイミングB */ break; - case 0xcf: // ロード - dma.mode = (UINT8)((dma.WR[4] >> 5) & 3); - dma.CNT_A.w = dma.ADR_A.w; - dma.CNT_B.w = dma.ADR_B.w; - dma.BYT_N.w = 0; - dma.ENDB_FLG = 0; - dma.MACH_FLG = 0; // 0619 - dma.enable = 0; + case DMACMD(0xcf): /* ロード */ + /* d->mode = (UINT8)((d->WR4 >> 5) & 3); */ + d->cnt_a.w.addr = d->addr.w.a; + d->cnt_b.w.addr = d->addr.w.b; + d->leng.w.n = 0; +#if !defined(DMAS_STOIC) + d->MACH_FLG = 0; + d->ENDB_FLG = 0; +#else + d->flag |= DMAF_MACH | DMAF_ENDB; +#endif + /* d->enable = 0; */ break; - case 0xd3: // コンティニュー - if (dma.DMA_STOP) { // 前回途中でNOT READY - dma.DMA_STOP = 0; - // ここでインクリメントするのはちょい無理が… - switch(dma.WR[1] & 0x30) { + case DMACMD(0xd3): /* コンティニュー */ +#if !defined(DMAS_STOIC) + if (d->increment) { + d->increment = 0; + switch(d->cnt_a.b.flag & 0x30) { case 0x00: - dma.CNT_A.w--; + d->cnt_a.w.addr--; break; case 0x10: - dma.CNT_A.w++; + d->cnt_a.w.addr++; break; } - switch(dma.WR[2] & 0x30) { + switch(d->cnt_b.b.flag & 0x30) { case 0x00: - dma.CNT_B.w--; + d->cnt_b.w.addr--; break; case 0x10: - dma.CNT_B.w++; + d->cnt_b.w.addr++; break; } } - dma.BYT_N.w = 0; // 0619 - dma.MACH_FLG = 0; // 0619 - dma.ENDB_FLG = 0; - dma.enable = 1; +#else + if (d->flag & DMAF_INCREMENT) { + d->flag &= ~DMAF_INCREMENT; + switch(d->cnt_a.b.flag & 0x30) { + case 0x00: + d->cnt_a.w.addr--; + break; + + case 0x10: + d->cnt_a.w.addr++; + break; + } + switch(d->cnt_b.b.flag & 0x30) { + case 0x00: + d->cnt_b.w.addr--; + break; + + case 0x10: + d->cnt_b.w.addr++; + break; + } + } +#endif +#if !defined(DMAS_STOIC) + d->MACH_FLG = 0; + d->ENDB_FLG = 0; +#else + d->flag |= DMAF_MACH | DMAF_ENDB; +#endif + d->leng.w.n = 0; + enable(d); break; } - break; + } } } else { - *(((UINT8 *)&dma) + dma.WR_TBL[dma.WR_OFF]) = value; - if (dma.WR_TBL[dma.WR_OFF] == offsetof(DMAC, INT_FLG)) { + *(((UINT8 *)d) + d->wtbl[d->wptr]) = value; + if (d->wtbl[d->wptr] == offsetof(DMAC, INT_FLG)) { if (value & 0x08) { - dma.WR_TBL[dma.WR_OFF + dma.WR_CNT] = offsetof(DMAC, INT_PLS); - dma.WR_CNT++; + d->wtbl[d->wptr + d->wcnt] = offsetof(DMAC, INT_PLS); + d->wcnt++; } if (value & 0x10) { - dma.WR_TBL[dma.WR_OFF + dma.WR_CNT] = offsetof(DMAC, INT_VCT); - dma.WR_CNT++; + d->wtbl[d->wptr + d->wcnt] = offsetof(DMAC, INT_VCT); + d->wcnt++; } } - else if (dma.WR_TBL[dma.WR_OFF] == offsetof(DMAC, RR_MSK)) { - setdmareaddat(); - } - dma.WR_OFF++; - dma.WR_CNT--; - } - - working = iswork(&dma); - if (dma.working != working) { - dma.working = working; - if (working) { - nevent_forceexit(); + else if (d->wtbl[d->wptr] == offsetof(DMAC, RR_MSK)) { + setdmareaddat(d); } + d->wptr++; + d->wcnt--; } (void)port; } REG8 IOINPCALL dmac_i(UINT port) { + DMAC *d; REG8 ret; + d = &dma; ret = 0xcc; - if (dma.enable) { + if (d->enable) { ret |= 0x01; } - if ((dma.mode != 1) && ((dma.WR[5] ^ dma.ready) & 8)) { + if ((d->mode != 1) && ((d->WR5 ^ d->ready) & 8)) { ret |= 0x02; } - if (!dma.MACH_FLG) { +#if !defined(DMAS_STOIC) + if (!d->MACH_FLG) { ret |= 0x10; } - if (!dma.ENDB_FLG) { + if (!d->ENDB_FLG) { ret |= 0x20; } - dma.RR = ret; - if (dma.RR_CNT) { - if (dma.RR_OFF >= dma.RR_CNT) { - dma.RR_OFF = 0; +#else + ret |= (d->flag & (DMAF_MACH | DMAF_ENDB)); +#endif + d->RR = ret; + if (d->rcnt) { + if (d->rptr >= d->rcnt) { + d->rptr = 0; } - ret = (*(((UINT8 *)&dma) + dma.RR_TBL[dma.RR_OFF++])); + ret = (*(((UINT8 *)d) + d->rtbl[d->rptr++])); } (void)port; + /* TRACEOUT(("inp %.4x %.2x", port, ret)); */ return(ret); } -// ---- +/* reset */ void dmac_reset(void) { - ZeroMemory(&dma, sizeof(dma)); - dma.ready = 8; - dma.RR = 0x38; + DMAC *d; + + d = &dma; + ZeroMemory(d, sizeof(*d)); +#if defined(DMAS_STOIC) + d->flag = DMAF_MACH | DMAF_ENDB; +#endif + d->ready = 8; + d->RR = 0x38; }