|
|
| version 1.12, 2003/12/13 19:59:41 | version 1.25, 2005/05/20 13:59:47 |
|---|---|
| Line 3 | Line 3 |
| // | // |
| #include "compiler.h" | #include "compiler.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アイドル時のカウンタをα倍に | #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]; | |
| 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.intr[0]) { | pitch = pit.ch + 0; |
| pit.intr[0] = 0; | if (pitch->flag & PIT_FLAG_I) { |
| pitch->flag &= ~PIT_FLAG_I; | |
| pic_setirq(0); | pic_setirq(0); |
| } | } |
| if ((pit.mode[0] & 0x0c) == 0x04) { | if ((pitch->ctrl & 0x0c) == 0x04) { |
| // レートジェネレータ | // レートジェネレータ |
| pit.intr[0] = 1; | pitch->flag |= PIT_FLAG_I; |
| setsystimerevent(NEVENT_RELATIVE); | setsystimerevent(pitch->value, NEVENT_RELATIVE); |
| } | } |
| else { | else { |
| nevent_set(NEVENT_ITIMER, pc.multiple << 16, | setsystimerevent(0, NEVENT_RELATIVE); |
| systimer, NEVENT_RELATIVE); | |
| } | } |
| } | } |
| } | } |
| Line 65 void systimer(NEVENTITEM item) { | Line 55 void systimer(NEVENTITEM item) { |
| // --- Beep | // --- Beep |
| #if defined(BEEPCOUNTEREX) | #if defined(BEEPCOUNTEREX) |
| static void setbeepeventex(BOOL absolute) { | static void setbeepeventex(UINT32 cnt, BOOL absolute) { |
| UINT32 cnt; | |
| cnt = pit.value[1]; | |
| if (cnt > 2) { | if (cnt > 2) { |
| cnt *= pc.multiple; | cnt *= pccore.multiple; |
| } | } |
| else { | else { |
| cnt = pc.multiple << 16; | cnt = pccore.multiple << 16; |
| } | } |
| while(cnt < 0x100000) { | while(cnt < 0x100000) { |
| cnt <<= 1; | cnt <<= 1; |
| Line 83 static void setbeepeventex(BOOL absolute | Line 70 static void setbeepeventex(BOOL absolute |
| } | } |
| #endif | #endif |
| static void setbeepevent(BOOL absolute) { | static void setbeepevent(UINT32 cnt, BOOL absolute) { |
| SINT32 cnt; | |
| cnt = pit.value[1]; | |
| 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 |
| { | { |
| #if defined(BEEPCOUNTEREX) | #if defined(BEEPCOUNTEREX) |
| setbeepeventex(NEVENT_RELATIVE); | setbeepeventex(pitch->value, NEVENT_RELATIVE); |
| #else | #else |
| setbeepevent(NEVENT_RELATIVE); | setbeepevent(pitch->value, NEVENT_RELATIVE); |
| #endif | #endif |
| } | } |
| } | } |
| Line 121 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] > 1) { | |
| cnt = pc.multiple * pit.value[2] * rs232c.mul; | |
| } | } |
| else { | else { |
| cnt = (pc.multiple << 16) * rs232c.mul; | 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 UINT pit_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]); | |
| 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] & (~1)); | return(pitch->value & (~1)); |
| #endif | #endif |
| } | } |
| clock = nevent_getremain(NEVENT_BEEP); | |
| #if defined(BEEPCOUNTEREX) | #if defined(BEEPCOUNTEREX) |
| clock = nevent_getremain(NEVENT_ITIMER + ch); | if (clock >= 0) { |
| if (clock < 0) { | clock /= pccore.multiple; |
| return(0); | if (pitch->value > 2) { |
| } | clock %= pitch->value; |
| clock /= pc.multiple; | } |
| if (pit.value[1] > 2) { | else { |
| clock %= pit.value[1]; | clock = LOW16(clock); |
| } | } |
| else { | return(clock); |
| clock >>= 16; | } |
| } | #else |
| return(clock); | break; |
| #endif | #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(clock / pc.multiple); | |
| } | } |
| return(0); | return(0); |
| } | } |
| void pit_setflag(int ch, REG8 value) { | static void latchcmd(PITCH pitch, REG8 ctrl) { |
| pit.flag[ch] = 0; | UINT8 flag; |
| if (value & 0x30) { | |
| pit.mode[ch] = (UINT8)value; | 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 pit_setflag(PITCH pitch, REG8 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] = (UINT16)pit_latch(ch); | |
| } | } |
| } | } |
| BOOL pit_setcount(int ch, REG8 value) { | BOOL pit_setcount(PITCH pitch, REG8 value) { |
| switch(pit.mode[ch] & 0x30) { | UINT8 flag; |
| case 0x10: // access low | |
| pit.value[ch] = value; | switch(pitch->ctrl & PIT_CTRL_RL) { |
| case PIT_RL_L: // access low | |
| pitch->value = value; | |
| break; | break; |
| case 0x20: // access high | case PIT_RL_H: // access high |
| pit.value[ch] = 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] &= 0xff00; | pitch->flag = flag ^ PIT_FLAG_W; |
| pit.value[ch] += value; | if (!(flag & PIT_FLAG_W)) { |
| pit.flag[ch] ^= 2; | pitch->value &= 0xff00; |
| pitch->value += value; | |
| return(TRUE); | return(TRUE); |
| } | } |
| pit.value[ch] &= 0x00ff; | pitch->value &= 0x00ff; |
| pit.value[ch] += 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); |
| } | } |
| REG8 pit_getcount(int ch) { | REG8 pit_getstat(PITCH pitch) { |
| UINT8 flag; | |
| UINT8 rl; | |
| UINT16 w; | |
| REG8 ret; | REG8 ret; |
| REG16 w; | |
| if (!(pit.mode[ch] & 0x30)) { | flag = pitch->flag; |
| w = pit.latch[ch]; | #if defined(uPD71054) |
| if (flag & PIT_FLAG_S) { | |
| flag &= ~PIT_FLAG_S; | |
| ret = pitch->stat; | |
| } | } |
| else { | else |
| w = pit_latch(ch); | #endif |
| } | { |
| switch(pit.mode[ch] & 0x30) { | rl = pitch->ctrl & PIT_CTRL_RL; |
| case 0x10: // access low | if (flag & (PIT_FLAG_C | PIT_FLAG_L)) { |
| return((UINT8)w); | flag &= ~PIT_FLAG_C; |
| if (rl == PIT_RL_ALL) { | |
| case 0x20: // access high | flag ^= PIT_FLAG_L; |
| return((UINT8)(w >> 8)); | } |
| } | w = pitch->latch; |
| if (!(pit.flag[ch] & 1)) { // access word | } |
| ret = (UINT8)w; | else { |
| } | w = getcount(pitch); |
| else { | } |
| ret = (UINT8)(w >> 8); | 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 256 REG8 pit_getcount(int ch) { | Line 321 REG8 pit_getcount(int ch) { |
| // system timer | // system timer |
| static void IOOUTCALL pit_o71(UINT port, REG8 dat) { | static void IOOUTCALL pit_o71(UINT port, REG8 dat) { |
| // TRACEOUT(("pic o71: %x", dat)); | PITCH pitch; |
| if (pit_setcount(0, dat)) { | |
| pitch = pit.ch + 0; | |
| if (pit_setcount(pitch, dat)) { | |
| return; | return; |
| } | } |
| pic.pi[0].irr &= (~1); | pic.pi[0].irr &= (~1); |
| pit.intr[0] = 1; | pitch->flag |= PIT_FLAG_I; |
| setsystimerevent(NEVENT_ABSOLUTE); | setsystimerevent(pitch->value, NEVENT_ABSOLUTE); |
| (void)port; | (void)port; |
| } | } |
| // beep | // beep |
| static void IOOUTCALL pit_o73(UINT port, REG8 dat) { | static void IOOUTCALL pit_o73(UINT port, REG8 dat) { |
| if (pit_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]); | |
| } | } |
| (void)port; | (void)port; |
| } | } |
| Line 285 static void IOOUTCALL pit_o73(UINT port, | Line 353 static void IOOUTCALL pit_o73(UINT port, |
| // rs-232c | // rs-232c |
| static void IOOUTCALL pit_o75(UINT port, REG8 dat) { | static void IOOUTCALL pit_o75(UINT port, REG8 dat) { |
| if (pit_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, REG8 dat) { | static void IOOUTCALL pit_o77(UINT port, REG8 dat) { |
| int ch; | UINT chnum; |
| PITCH pitch; | |
| // TRACEOUT(("pic o77: %x", dat)); | chnum = (dat >> 6) & 3; |
| ch = (dat >> 6) & 3; | if (chnum != 3) { |
| if (ch != 3) { | pitch = pit.ch + chnum; |
| pit_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); |
| if (dat & 0x30) { // 一応ラッチ時は割り込みをセットしない | if (dat & 0x30) { // 一応ラッチ時は割り込みをセットしない |
| pit.intr[0] = 1; | pitch->flag |= PIT_FLAG_I; |
| // setsystimerevent(NEVENT_ABSOLUTE); | |
| } | } |
| } | } |
| 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 REG8 IOINPCALL pit_i71(UINT port) { | static REG8 IOINPCALL pit_i71(UINT port) { |
| return(pit_getcount((port >> 1) & 3)); | return(pit_getstat(pit.ch + ((port >> 1) & 3))); |
| } | } |
| Line 332 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] = 998; // 4MHz | pit.ch[0].ctrl = 0x30; |
| } | pit.ch[0].ch = 0; |
| else { | pit.ch[0].flag = PIT_FLAG_I; |
| pit.value[1] = 1229; // 5MHz | pit.ch[0].ctrl = 0x56 & 0x3f; |
| } | pit.ch[1].ch = 1; |
| pit.intr[0] = 1; | pit.ch[1].value = beepcnt; |
| pit.mode[0] = 0x30; | pit.ch[2].ctrl = 0xb6 & 0x3f; |
| pit.mode[1] = 0x56; | pit.ch[2].ch = 2; |
| pit.mode[2] = 0xb6; | #if !defined(DISABLE_SOUND) |
| pit.mode[3] = 0x36; | pit.ch[3].ctrl = 0x36; |
| setsystimerevent(NEVENT_ABSOLUTE); | pit.ch[3].ch = 3; |
| beep_hzset(pit.value[1]); | 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); | |
| } | } |