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