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