| version 1.3, 2003/10/25 20:51:53 | version 1.25, 2005/05/20 13:59:47 | 
| Line 3 | Line 3 | 
 | // | // | 
 |  |  | 
 | #include        "compiler.h" | #include        "compiler.h" | 
| #include        "i286.h" | #include        "cpucore.h" | 
 | #include        "pccore.h" | #include        "pccore.h" | 
 | #include        "iocore.h" | #include        "iocore.h" | 
 | #include        "sound.h" | #include        "sound.h" | 
 | #include        "beep.h" | #include        "beep.h" | 
 |  | #include        "board14.h" | 
 |  |  | 
 |  |  | 
| // #define      uPD71054                                                                // NP2はuPD8253Cベース | #define BEEPCOUNTEREX                                   // BEEPアイドル時のカウンタをα倍に | 
|  | #if defined(CPUCORE_IA32) | 
|  | #define uPD71054 | 
|  | #endif | 
 |  |  | 
 |  |  | 
 | // --- Interval timer | // --- Interval timer | 
 |  |  | 
| // ver0.31 常に回す… | static void setsystimerevent(UINT32 cnt, BOOL absolute) { | 
| static void setsystimerevent_noint(BOOL absolute) { |  | 
|  |  | 
| nevent_set(NEVENT_ITIMER, pc.multiple << 16, systimer_noint, absolute); |  | 
| } |  | 
|  |  | 
| void systimer_noint(NEVENTITEM item) { |  | 
 |  |  | 
 | if (item->flag & NEVENT_SETEVENT) { |  | 
 | setsystimerevent_noint(NEVENT_RELATIVE); |  | 
 | } |  | 
 | } |  | 
 |  |  | 
 | static void setsystimerevent(BOOL absolute) { |  | 
 |  |  | 
 | SINT32  cnt; |  | 
 |  |  | 
 | cnt = pit.value[0].w; |  | 
 | if (cnt > 8) {                                                                  // 根拠なし | if (cnt > 8) {                                                                  // 根拠なし | 
| cnt *= pc.multiple; | cnt *= pccore.multiple; | 
 | } | } | 
 | else { | else { | 
| cnt = pc.multiple << 16; | cnt = pccore.multiple << 16; | 
 | } | } | 
 | nevent_set(NEVENT_ITIMER, cnt, systimer, absolute); | nevent_set(NEVENT_ITIMER, cnt, systimer, absolute); | 
 | } | } | 
 |  |  | 
 | void systimer(NEVENTITEM item) { | void systimer(NEVENTITEM item) { | 
 |  |  | 
 |  | PITCH   pitch; | 
 |  |  | 
 | if (item->flag & NEVENT_SETEVENT) { | if (item->flag & NEVENT_SETEVENT) { | 
| if ((pit.mode[0] & 0x0c) == 0x04) { | pitch = pit.ch + 0; | 
|  | if (pitch->flag & PIT_FLAG_I) { | 
|  | pitch->flag &= ~PIT_FLAG_I; | 
|  | pic_setirq(0); | 
|  | } | 
|  | if ((pitch->ctrl & 0x0c) == 0x04) { | 
 | // レートジェネレータ | // レートジェネレータ | 
| setsystimerevent(NEVENT_RELATIVE); | pitch->flag |= PIT_FLAG_I; | 
|  | setsystimerevent(pitch->value, NEVENT_RELATIVE); | 
 | } | } | 
 | else { | else { | 
| setsystimerevent_noint(NEVENT_RELATIVE); | setsystimerevent(0, NEVENT_RELATIVE); | 
 | } | } | 
 | } | } | 
 | pic_setirq(0); |  | 
 | } | } | 
 |  |  | 
 |  |  | 
 | // --- Beep | // --- Beep | 
 |  |  | 
| static void setbeepevent(BOOL absolute) { | #if defined(BEEPCOUNTEREX) | 
|  | static void setbeepeventex(UINT32 cnt, BOOL absolute) { | 
|  |  | 
|  | if (cnt > 2) { | 
|  | cnt *= pccore.multiple; | 
|  | } | 
|  | else { | 
|  | cnt = pccore.multiple << 16; | 
|  | } | 
|  | while(cnt < 0x100000) { | 
|  | cnt <<= 1; | 
|  | } | 
|  | nevent_set(NEVENT_BEEP, (SINT32)cnt, beeponeshot, absolute); | 
|  | } | 
|  | #endif | 
 |  |  | 
| SINT32  cnt; | static void setbeepevent(UINT32 cnt, BOOL absolute) { | 
 |  |  | 
 | cnt = pit.value[1].w; |  | 
 | if (cnt > 2) { | if (cnt > 2) { | 
| cnt *= pc.multiple; | cnt *= pccore.multiple; | 
 | } | } | 
 | else { | else { | 
| cnt = pc.multiple << 16; | cnt = pccore.multiple << 16; | 
 | } | } | 
 | nevent_set(NEVENT_BEEP, cnt, beeponeshot, absolute); | nevent_set(NEVENT_BEEP, cnt, beeponeshot, absolute); | 
 | } | } | 
 |  |  | 
 | void beeponeshot(NEVENTITEM item) { | void beeponeshot(NEVENTITEM item) { | 
 |  |  | 
 |  | PITCH   pitch; | 
 |  |  | 
 | if (item->flag & NEVENT_SETEVENT) { | if (item->flag & NEVENT_SETEVENT) { | 
| if (!(pit.mode[1] & 0x0c)) {                                                            // ver0.30 | pitch = pit.ch + 1; | 
|  | if (!(pitch->ctrl & 0x0c)) { | 
 | beep_lheventset(0); | beep_lheventset(0); | 
 | } | } | 
| #ifdef uPD71054 | #if defined(uPD71054) | 
| if ((pit.mode[1] & 0x06) == 0x02) | if ((pitch->ctrl & 0x06) == 0x02) | 
 | #else | #else | 
| if (pit.mode[1] & 0x02) | if (pitch->ctrl & 0x02) | 
 | #endif | #endif | 
 | { | { | 
| setbeepevent(NEVENT_RELATIVE); | #if defined(BEEPCOUNTEREX) | 
|  | setbeepeventex(pitch->value, NEVENT_RELATIVE); | 
|  | #else | 
|  | setbeepevent(pitch->value, NEVENT_RELATIVE); | 
|  | #endif | 
 | } | } | 
 | } | } | 
 | } | } | 
| Line 93  void beeponeshot(NEVENTITEM item) { | Line 108  void beeponeshot(NEVENTITEM item) { | 
 |  |  | 
 | // --- RS-232C | // --- RS-232C | 
 |  |  | 
| static void setrs232cevent(BOOL absolute) { | static void setrs232cevent(UINT32 cnt, BOOL absolute) { | 
 |  |  | 
| SINT32  cnt; | if (cnt > 1) { | 
|  | cnt *= pccore.multiple; | 
| if (pit.value[2].w > 1) { |  | 
| cnt = pc.multiple * pit.value[2].w * rs232c.mul;                        // ver0.29 |  | 
 | } | } | 
 | else { | else { | 
| cnt = (pc.multiple << 16) * rs232c.mul;                                         // ver0.29 | cnt = pccore.multiple << 16; | 
 | } | } | 
 |  | cnt *= rs232c.mul; | 
 | nevent_set(NEVENT_RS232C, cnt, rs232ctimer, absolute); | nevent_set(NEVENT_RS232C, cnt, rs232ctimer, absolute); | 
 | } | } | 
 |  |  | 
 | void rs232ctimer(NEVENTITEM item) { | void rs232ctimer(NEVENTITEM item) { | 
 |  |  | 
 |  | PITCH   pitch; | 
 |  |  | 
 | if (item->flag & NEVENT_SETEVENT) { | if (item->flag & NEVENT_SETEVENT) { | 
| if ((pit.mode[2] & 0x0c) == 0x04) { | pitch = pit.ch + 2; | 
|  | if (pitch->flag & PIT_FLAG_I) { | 
|  | pitch->flag &= ~PIT_FLAG_I; | 
|  | rs232c_callback(); | 
|  | } | 
|  | if ((pitch->ctrl & 0x0c) == 0x04) { | 
 | // レートジェネレータ | // レートジェネレータ | 
| setrs232cevent(NEVENT_RELATIVE); | setrs232cevent(pitch->value, NEVENT_RELATIVE); | 
|  | } | 
|  | else { | 
|  | setrs232cevent(0, NEVENT_RELATIVE); | 
 | } | } | 
 | } | } | 
 | rs232c_callback(); |  | 
 | } | } | 
 |  |  | 
 |  |  | 
 | // --------------------------------------------------------------------------- | // --------------------------------------------------------------------------- | 
 |  |  | 
| static UINT16 itimer_latch(int ch) { | static UINT getcount(const _PITCH *pitch) { | 
 |  |  | 
 | SINT32  clock; | SINT32  clock; | 
 |  |  | 
| if (ch == 1) { | switch(pitch->ch) { | 
| switch(pit.mode[1] & 0x06) { | case 0: | 
| case 0x00: | clock = nevent_getremain(NEVENT_ITIMER); | 
| case 0x04: | break; | 
| return(pit.value[1].w); |  | 
|  | case 1: | 
|  | switch(pitch->ctrl & 0x06) { | 
|  | #ifdef uPD71054                         // ? | 
|  | //                              case 0x00: | 
|  | #endif | 
|  | case 0x04: | 
|  | return(pitch->value); | 
 | #ifdef uPD71054 | #ifdef uPD71054 | 
| case 0x06: | case 0x06: | 
| return(pit.value[1].w & 0xfffe); | return(pitch->value & (~1)); | 
 | #endif | #endif | 
| } | } | 
|  | clock = nevent_getremain(NEVENT_BEEP); | 
|  | #if defined(BEEPCOUNTEREX) | 
|  | if (clock >= 0) { | 
|  | clock /= pccore.multiple; | 
|  | if (pitch->value > 2) { | 
|  | clock %= pitch->value; | 
|  | } | 
|  | else { | 
|  | clock = LOW16(clock); | 
|  | } | 
|  | return(clock); | 
|  | } | 
|  | #else | 
|  | break; | 
|  | #endif | 
|  |  | 
|  | case 2: | 
|  | clock = nevent_getremain(NEVENT_RS232C); | 
|  | break; | 
|  |  | 
|  | #if !defined(DISABLE_SOUND) | 
|  | case 3: | 
|  | return(board14_pitcount()); | 
|  | #endif | 
|  |  | 
|  | default: | 
|  | clock = 0; | 
|  | break; | 
 | } | } | 
| clock = nevent_getremain(NEVENT_ITIMER + ch); | if (clock > 0) { | 
| if (clock >= 0) { | return(clock / pccore.multiple); | 
| return((UINT16)(clock / pc.multiple)); |  | 
 | } | } | 
 | return(0); | return(0); | 
 | } | } | 
 |  |  | 
 |  | static void latchcmd(PITCH pitch, REG8 ctrl) { | 
 |  |  | 
 |  | UINT8   flag; | 
 |  |  | 
 |  | flag = pitch->flag; | 
 |  | if (!(ctrl & PIT_LATCH_S)) { | 
 |  | flag |= PIT_FLAG_S; | 
 |  | pitch->stat = pitch->ctrl; | 
 |  | } | 
 |  | if (!(ctrl & PIT_LATCH_C)) { | 
 |  | flag |= PIT_FLAG_C; | 
 |  | flag &= ~PIT_FLAG_L; | 
 |  | pitch->latch = getcount(pitch); | 
 |  | } | 
 |  | pitch->flag = flag; | 
 |  | } | 
 |  |  | 
 |  |  | 
| void itimer_setflag(int ch, BYTE value) { | // ---- | 
 |  |  | 
| pit.flag[ch] = 0; | void pit_setflag(PITCH pitch, REG8 value) { | 
| if (value & 0x30) { |  | 
| pit.mode[ch] = value; | if (value & PIT_CTRL_RL) { | 
|  | pitch->ctrl = (UINT8)((value & 0x3f) | PIT_STAT_CMD); | 
|  | pitch->flag &= ~(PIT_FLAG_R | PIT_FLAG_W | PIT_FLAG_L | | 
|  | PIT_FLAG_S | PIT_FLAG_C); | 
 | } | } | 
 | else {                                                                                                          // latch | else {                                                                                                          // latch | 
| pit.mode[ch] &= ~0x30; | latchcmd(pitch, ~PIT_LATCH_C); | 
| pit.latch[ch].w = itimer_latch(ch); |  | 
 | } | } | 
 | } | } | 
 |  |  | 
| BOOL itimer_setcount(int ch, BYTE value) { | BOOL pit_setcount(PITCH pitch, REG8 value) { | 
|  |  | 
|  | UINT8   flag; | 
 |  |  | 
| switch(pit.mode[ch] & 0x30) { | switch(pitch->ctrl & PIT_CTRL_RL) { | 
| case 0x10:              // access low | case PIT_RL_L:          // access low | 
| pit.value[ch].w = value; | pitch->value = value; | 
 | break; | break; | 
 |  |  | 
| case 0x20:              // access high | case PIT_RL_H:          // access high | 
| pit.value[ch].w = value << 8; | pitch->value = value << 8; | 
 | break; | break; | 
 |  |  | 
| case 0x30:              // access word | case PIT_RL_ALL:        // access word | 
| if (!(pit.flag[ch] & 2)) { | flag = pitch->flag; | 
| pit.value[ch].w &= 0xff00; | pitch->flag = flag ^ PIT_FLAG_W; | 
| pit.value[ch].w += value; | if (!(flag & PIT_FLAG_W)) { | 
| pit.flag[ch] ^= 2; | pitch->value &= 0xff00; | 
|  | pitch->value += value; | 
 | return(TRUE); | return(TRUE); | 
 | } | } | 
| pit.value[ch].w &= 0x00ff; | pitch->value &= 0x00ff; | 
| pit.value[ch].w += value << 8; | pitch->value += value << 8; | 
| pit.flag[ch] ^= 2; |  | 
 | break; | break; | 
 | } | } | 
 |  | pitch->ctrl &= ~PIT_STAT_CMD; | 
 |  | if (((pitch->ctrl & 0x06) == 0x02) && (pitch->flag & PIT_FLAG_I)) { | 
 |  | return(TRUE); | 
 |  | } | 
 | return(FALSE); | return(FALSE); | 
 | } | } | 
 |  |  | 
| BYTE itimer_getcount(int ch) { | REG8 pit_getstat(PITCH pitch) { | 
 |  |  | 
| BYTE    ret; | UINT8   flag; | 
| union { | UINT8   rl; | 
| BYTE    b[2]; | UINT16  w; | 
| UINT16  w; | REG8    ret; | 
| } tim; |  | 
|  | flag = pitch->flag; | 
| if (!(pit.mode[ch] & 0x30)) { | #if defined(uPD71054) | 
| tim.w = pit.latch[ch].w; | if (flag & PIT_FLAG_S) { | 
| } | flag &= ~PIT_FLAG_S; | 
| else { | ret = pitch->stat; | 
| tim.w = itimer_latch(ch);                                                                       // ver0.30 |  | 
| } |  | 
| switch(pit.mode[ch] & 0x30) { |  | 
| case 0x10:                                              // access low |  | 
| return((BYTE)tim.w); |  | 
|  |  | 
| case 0x20:                                              // access high |  | 
| return((BYTE)(tim.w >> 8)); |  | 
| } |  | 
| // access word |  | 
| if (!(pit.flag[ch] & 1)) { |  | 
| ret = (BYTE)tim.w; |  | 
 | } | } | 
| else { | else | 
| ret = (BYTE)(tim.w >> 8); | #endif | 
|  | { | 
|  | rl = pitch->ctrl & PIT_CTRL_RL; | 
|  | if (flag & (PIT_FLAG_C | PIT_FLAG_L)) { | 
|  | flag &= ~PIT_FLAG_C; | 
|  | if (rl == PIT_RL_ALL) { | 
|  | flag ^= PIT_FLAG_L; | 
|  | } | 
|  | w = pitch->latch; | 
|  | } | 
|  | else { | 
|  | w = getcount(pitch); | 
|  | } | 
|  | switch(rl) { | 
|  | case PIT_RL_L:                                          // access low | 
|  | ret = (UINT8)w; | 
|  | break; | 
|  |  | 
|  | case PIT_RL_H: | 
|  | ret = (UINT8)(w >> 8); | 
|  | break; | 
|  |  | 
|  | case PIT_RL_ALL: | 
|  | default: | 
|  | if (!(flag & PIT_FLAG_R)) { | 
|  | ret = (UINT8)w; | 
|  | } | 
|  | else { | 
|  | ret = (UINT8)(w >> 8); | 
|  | } | 
|  | flag ^= PIT_FLAG_R; | 
|  | break; | 
|  | } | 
 | } | } | 
| pit.flag[ch] ^= 1; | pitch->flag = flag; | 
 | return(ret); | return(ret); | 
 | } | } | 
 |  |  | 
| Line 216  BYTE itimer_getcount(int ch) { | Line 319  BYTE itimer_getcount(int ch) { | 
 | // ---- I/O | // ---- I/O | 
 |  |  | 
 | // system timer | // system timer | 
| static void IOOUTCALL pit_o71(UINT port, BYTE dat) { | static void IOOUTCALL pit_o71(UINT port, REG8 dat) { | 
|  |  | 
|  | PITCH   pitch; | 
 |  |  | 
| //      TRACEOUT(("pic71: %d", dat)); | pitch = pit.ch + 0; | 
| if (itimer_setcount(0, dat)) { | if (pit_setcount(pitch, dat)) { | 
 | return; | return; | 
 | } | } | 
 | pic.pi[0].irr &= (~1); | pic.pi[0].irr &= (~1); | 
| setsystimerevent(NEVENT_ABSOLUTE); | pitch->flag |= PIT_FLAG_I; | 
|  | setsystimerevent(pitch->value, NEVENT_ABSOLUTE); | 
 | (void)port; | (void)port; | 
 | } | } | 
 |  |  | 
 | // beep | // beep | 
| static void IOOUTCALL pit_o73(UINT port, BYTE dat) { | static void IOOUTCALL pit_o73(UINT port, REG8 dat) { | 
 |  |  | 
| if (itimer_setcount(1, dat)) { | PITCH   pitch; | 
|  |  | 
|  | pitch = pit.ch + 1; | 
|  | if (pit_setcount(pitch, dat)) { | 
 | return; | return; | 
 | } | } | 
| setbeepevent(NEVENT_ABSOLUTE); | setbeepevent(pitch->value, NEVENT_ABSOLUTE); | 
| if (!(pit.mode[1] & 0x0c)) { | beep_lheventset(1);                                                                                             // ver0.79 | 
| beep_lheventset(1); | if (pitch->ctrl & 0x0c) { | 
| } | beep_hzset(pitch->value); | 
| else { |  | 
| beep_hzset(pit.value[1].w); |  | 
 | } | } | 
 | (void)port; | (void)port; | 
 | } | } | 
 |  |  | 
 | // rs-232c | // rs-232c | 
| static void IOOUTCALL pit_o75(UINT port, BYTE dat) { | static void IOOUTCALL pit_o75(UINT port, REG8 dat) { | 
 |  |  | 
| if (itimer_setcount(2, dat)) { | PITCH   pitch; | 
|  |  | 
|  | pitch = pit.ch + 2; | 
|  | if (pit_setcount(pitch, dat)) { | 
 | return; | return; | 
 | } | } | 
 |  | pitch->flag |= PIT_FLAG_I; | 
 | rs232c_open(); | rs232c_open(); | 
| setrs232cevent(NEVENT_ABSOLUTE); | setrs232cevent(pitch->value, NEVENT_ABSOLUTE); | 
 | (void)port; | (void)port; | 
 | } | } | 
 |  |  | 
 | // ctrl | // ctrl | 
| static void IOOUTCALL pit_o77(UINT port, BYTE dat) { | static void IOOUTCALL pit_o77(UINT port, REG8 dat) { | 
 |  |  | 
| int             ch; | UINT    chnum; | 
|  | PITCH   pitch; | 
 |  |  | 
| //      TRACEOUT(("pic77: %x", dat)); | chnum = (dat >> 6) & 3; | 
| ch = (dat >> 6) & 3; | if (chnum != 3) { | 
| if (ch != 3) { | pitch = pit.ch + chnum; | 
| itimer_setflag(ch, dat); | pit_setflag(pitch, dat); | 
| if (ch == 0) {                  // 書込みで itimerのirrがリセットされる… | if (chnum == 0) {               // 書込みで itimerのirrがリセットされる… | 
 | pic.pi[0].irr &= (~1); | pic.pi[0].irr &= (~1); | 
| setsystimerevent(NEVENT_ABSOLUTE); | if (dat & 0x30) {       // 一応ラッチ時は割り込みをセットしない | 
|  | pitch->flag |= PIT_FLAG_I; | 
|  | } | 
 | } | } | 
| if (ch == 1) { | if (chnum == 1) { | 
 | beep_modeset(); | beep_modeset(); | 
 | } | } | 
 | } | } | 
 |  | #if defined(uPD71054) | 
 |  | else { | 
 |  | TRACEOUT(("multiple latch commands - %x", dat)); | 
 |  | for (chnum=0; chnum<3; chnum++) { | 
 |  | if (dat & (2 << chnum)) { | 
 |  | latchcmd(pit.ch + chnum, dat); | 
 |  | } | 
 |  | } | 
 |  | } | 
 |  | #endif | 
 | (void)port; | (void)port; | 
 | } | } | 
 |  |  | 
| static BYTE IOINPCALL pit_i71(UINT port) { | static REG8 IOINPCALL pit_i71(UINT port) { | 
 |  |  | 
| return(itimer_getcount((port >> 1) & 3)); | return(pit_getstat(pit.ch + ((port >> 1) & 3))); | 
 | } | } | 
 |  |  | 
 |  |  | 
| Line 290  static const IOINP piti71[4] = { | Line 414  static const IOINP piti71[4] = { | 
 |  |  | 
 | void itimer_reset(void) { | void itimer_reset(void) { | 
 |  |  | 
 |  | UINT16  beepcnt; | 
 |  |  | 
 | ZeroMemory(&pit, sizeof(pit)); | ZeroMemory(&pit, sizeof(pit)); | 
| if (pc.cpumode & CPUMODE_8MHz) { | beepcnt = (pccore.cpumode & CPUMODE_8MHZ)?998:1229; | 
| pit.value[1].w = 998;                   // 4MHz | pit.ch[0].ctrl = 0x30; | 
| } | pit.ch[0].ch = 0; | 
| else { | pit.ch[0].flag = PIT_FLAG_I; | 
| pit.value[1].w = 1229;                  // 5MHz | pit.ch[0].ctrl = 0x56 & 0x3f; | 
| } | pit.ch[1].ch = 1; | 
| pit.mode[0] = 0x30; | pit.ch[1].value = beepcnt; | 
| pit.mode[1] = 0x56; | pit.ch[2].ctrl = 0xb6 & 0x3f; | 
| pit.mode[2] = 0xb6; | pit.ch[2].ch = 2; | 
| pit.mode[3] = 0x36; | #if !defined(DISABLE_SOUND) | 
| setsystimerevent(NEVENT_ABSOLUTE); | pit.ch[3].ctrl = 0x36; | 
| beep_hzset(pit.value[1].w); | pit.ch[3].ch = 3; | 
|  | pit.ch[4].ctrl = 0x36; | 
|  | pit.ch[4].ch = 4; | 
|  | #endif | 
|  | setsystimerevent(0, NEVENT_ABSOLUTE); | 
|  | beep_lheventset(1);                                                                                             // ver0.79 | 
|  | beep_hzset(beepcnt); | 
|  | //      setrs232cevent(0, NEVENT_ABSOLUTE); | 
 | } | } | 
 |  |  | 
 | void itimer_bind(void) { | void itimer_bind(void) { | 
 |  |  | 
 | iocore_attachsysoutex(0x0071, 0x0cf1, pito71, 4); | iocore_attachsysoutex(0x0071, 0x0cf1, pito71, 4); | 
 | iocore_attachsysinpex(0x0071, 0x0cf1, piti71, 4); | iocore_attachsysinpex(0x0071, 0x0cf1, piti71, 4); | 
 |  | iocore_attachout(0x3fd9, pit_o71); | 
 | iocore_attachout(0x3fdb, pit_o73); | iocore_attachout(0x3fdb, pit_o73); | 
 |  | iocore_attachout(0x3fdd, pit_o75); | 
 | iocore_attachout(0x3fdf, pit_o77); | iocore_attachout(0x3fdf, pit_o77); | 
 |  | iocore_attachinp(0x3fd9, pit_i71); | 
 | iocore_attachinp(0x3fdb, pit_i71); | iocore_attachinp(0x3fdb, pit_i71); | 
 |  | iocore_attachinp(0x3fdd, pit_i71); | 
 | } | } | 
 |  |  |