--- np2/cbus/amd98.c 2003/10/16 17:58:01 1.1.1.1 +++ np2/cbus/amd98.c 2004/06/26 15:47:00 1.15 @@ -1,33 +1,207 @@ #include "compiler.h" +#include #include "pccore.h" #include "iocore.h" #include "cbuscore.h" #include "amd98.h" #include "sound.h" #include "fmboard.h" -#include "beep.h" -#include "s98.h" -static void setamd98event(BOOL absolute) { +// ないよりあったほーが良い程度のリズム… +static struct { + PMIXHDR hdr; + PMIXTRK trk[4]; + UINT rate; + UINT enable; +} amd98r; + + +static void pcmmake1(PMIXDAT *dat, UINT rate, + int vol, double hz, double env) { + + UINT i; + double x; + double y; + double slast; + double s; + double v; + UINT size; + SINT16 *ptr; + + x = 44100.0 * 2.0 * PI / ((double)rate * hz); + y = 44100.0 / 256.0 / (double)rate; + slast = 0.0; + for (i=0; i= 0.0)) { + break; + } + slast = s; + } + size = i; + if (!size) { + return; + } + ptr = (SINT16 *)_MALLOC(size * sizeof(SINT16), "AMD98"); + if (ptr == NULL) { + return; + } + for (i=0; isample = ptr; + dat->samples = size; +} - SINT32 cnt; +static void pcmmake2(PMIXDAT *dat, UINT rate, + int vol, double hz, double env, double k) { - if (pit.value[3].w > 8) { // 根拠なし - cnt = pc.multiple * pit.value[3].w; + UINT i; + double x; + double y; + double p; + double s; + double slast; + double v; + UINT size; + SINT16 *ptr; + + x = 2.0 * PI * hz / (double)rate; + y = 44100.0 / 256.0 / (double)rate; + p = 0.0; + slast = 0.0; + for (i=0; i= 0.0)) { + break; + } + slast = s; + } + size = i; + if (!size) { + return; + } + ptr = (SINT16 *)_MALLOC(size * sizeof(SINT16), "AMD98"); + if (ptr == NULL) { + return; + } + p = 0.0; + for (i=0; isample = ptr; + dat->samples = size; +} + + +void amd98_initialize(UINT rate) { + + ZeroMemory(&amd98r, sizeof(amd98r)); + amd98r.rate = rate; +} + +void amd98_deinitialize(void) { + + int i; + void *ptr; + + amd98r.hdr.enable = 0; + for (i=0; i<4; i++) { + ptr = amd98r.trk[i].data.sample; + amd98r.trk[i].data.sample = NULL; + if (ptr) { + _MFREE(ptr); + } + } +} + +static void amd98_rhythmload(void) { + + UINT i; + + if (!amd98r.hdr.enable) { + TRACEOUT(("AMD98 Rhythm load")); + amd98r.hdr.enable = 0x0f; + // bd + pcmmake1(&amd98r.trk[0].data, amd98r.rate, + 24000, 889.0476190476, 0.9446717478); + // lt + pcmmake2(&amd98r.trk[1].data, amd98r.rate, + 6400, 172.9411764706, 0.8665145391, 0.9960000000); + // ht + pcmmake2(&amd98r.trk[2].data, amd98r.rate, + 9600, 213.0000000000, 0.8665145391, 0.9960000000); + // sd + pcmmake1(&amd98r.trk[3].data, amd98r.rate, + 12000, 255.4400000000, 0.8538230481); + for (i=0; i<4; i++) { + amd98r.trk[i].flag = PMIXFLAG_L | PMIXFLAG_R; + amd98r.trk[i].volume = 1 << 12; + } + } +} + + +// ---- + +static void amd98_rhythm(UINT map) { + + PMIXTRK *trk; + UINT bit; + + map &= 0x0f; + if (map == 0) { + return; + } + sound_sync(); + trk = amd98r.trk; + bit = 0x01; + do { + if ((map & bit) && (trk->data.sample)) { + trk->pcm = trk->data.sample; + trk->remain = trk->data.samples; + amd98r.hdr.playing |= bit; + } + trk++; + bit <<= 1; + } while (bit < 0x10); +} + + +// ---- + +static void setamd98event(UINT32 cnt, BOOL absolute) { + + if (cnt > 8) { // 根拠なし + cnt *= pccore.multiple; } else { - cnt = pc.multiple << 16; + cnt = pccore.multiple << 16; + } + if (!(pccore.cpumode & CPUMODE_8MHZ)) { + cnt = cnt * 16 / 13; // cnt * 2457600 / 1996800 } nevent_set(NEVENT_MUSICGEN, cnt, amd98int, absolute); } void amd98int(NEVENTITEM item) { + PITCH pitch; + if (item->flag & NEVENT_SETEVENT) { - if ((pit.mode[3] & 0x0c) == 0x04) { + pitch = pit.ch + 4; + if ((pitch->ctrl & 0x0c) == 0x04) { // レートジェネレータ - setamd98event(NEVENT_RELATIVE); + setamd98event(pitch->value, NEVENT_RELATIVE); } } pic_setirq(0x0d); @@ -37,19 +211,19 @@ void amd98int(NEVENTITEM item) { // ---- -static void IOOUTCALL amd_od8(UINT port, BYTE dat) { +static void IOOUTCALL amd_od8(UINT port, REG8 dat) { opn.opnreg = dat; (void)port; } -static void IOOUTCALL amd_od9(UINT port, BYTE dat) { +static void IOOUTCALL amd_od9(UINT port, REG8 dat) { opn.extreg = dat; (void)port; } -static void IOOUTCALL amd_oda(UINT port, BYTE dat) { +static void IOOUTCALL amd_oda(UINT port, REG8 dat) { if (opn.opnreg < 0x0e) { psggen_setreg(&psg1, opn.opnreg, dat); @@ -60,35 +234,25 @@ static void IOOUTCALL amd_oda(UINT port, (void)port; } -static void IOOUTCALL amd_odb(UINT port, BYTE dat) { +static void IOOUTCALL amd_odb(UINT port, REG8 dat) { if (opn.extreg < 0x0e) { psggen_setreg(&psg2, opn.extreg, dat); } else if (opn.extreg == 0x0f) { - BYTE b; + REG8 b; b = psg2.reg.io2; if ((b & 1) > (dat & 1)) { b &= 0xc2; if (b == 0x42) { -// TRACEOUT(0xfff0, psg_1.reg.io2); amd98.psg3reg = psg1.reg.io2; } else if (b == 0x40) { -// TRACEOUT(0xfff1, psg_1.reg.io2); if (amd98.psg3reg < 0x0e) { - psggen_setreg(&psg3, amd98.psg3reg, - psg1.reg.io2); + psggen_setreg(&psg3, amd98.psg3reg, psg1.reg.io2); } else if (amd98.psg3reg == 0x0f) { - int r; -static const BYTE amdr[] = {0x01, 0x08, 0x10, 0x20, 0x06, 0x40}; - sound_sync(); - for (r=0; r<6; r++) { - if (psg1.reg.io2 & amdr[r]) { -// rhythm_play(&rhythm, r, 0); - } - } + amd98_rhythm(psg1.reg.io2); } } } @@ -97,33 +261,93 @@ static const BYTE amdr[] = {0x01, 0x08, (void)port; } -static void IOOUTCALL amd_odc(UINT port, BYTE dat) { +static void IOOUTCALL amd_odc(UINT port, REG8 dat) { + + PITCH pitch; + + pitch = pit.ch + 4; + if (pit_setcount(pitch, dat)) { + return; + } + setamd98event(pitch->value, NEVENT_ABSOLUTE); + (void)port; +} + +static void IOOUTCALL amd_ode(UINT port, REG8 dat) { + + pit_setflag(pit.ch + 4, dat); + (void)port; +} + +static REG8 IOINPCALL amd_ida(UINT port) { - itimer_setcount(3, dat); - setamd98event(NEVENT_ABSOLUTE); + if (opn.opnreg < 0x0e) { + return(psggen_getreg(&psg1, opn.opnreg)); + } + else if (opn.opnreg == 0x0f) { + return(psg1.reg.io2); + } (void)port; + return(0xff); } -static void IOOUTCALL amd_ode(UINT port, BYTE dat) { +static REG8 IOINPCALL amd_idb(UINT port) { - itimer_setflag(3, dat); + if (opn.extreg < 0x0e) { + return(psggen_getreg(&psg2, opn.extreg)); + } + else if (opn.extreg == 0x0f) { + return(psg2.reg.io2); + } (void)port; + return(0xff); } +#if defined(TRACE) +static REG8 IOINPCALL amd_inp(UINT port) { + + TRACEOUT(("amd inp - %.4x", port)); + return(0xff); +} +#endif // ---- +static void psgpanset(PSGGEN psg) { + + psggen_setpan(psg, 0, 1); + psggen_setpan(psg, 1, 0); + psggen_setpan(psg, 2, 2); +} + void amd98_bind(void) { + amd98_rhythmload(); + + psgpanset(&psg1); + psgpanset(&psg2); + psgpanset(&psg3); + psggen_restore(&psg1); + psggen_restore(&psg2); + psggen_restore(&psg3); sound_streamregist(&psg1, (SOUNDCB)psggen_getpcm); sound_streamregist(&psg2, (SOUNDCB)psggen_getpcm); sound_streamregist(&psg3, (SOUNDCB)psggen_getpcm); -// sound_streamregist(&rhythm, (SOUNDCB)rhythm_getpcm); + sound_streamregist(&amd98r, (SOUNDCB)pcmmix_getpcm); iocore_attachout(0xd8, amd_od8); iocore_attachout(0xd9, amd_od9); iocore_attachout(0xda, amd_oda); iocore_attachout(0xdb, amd_odb); iocore_attachout(0xdc, amd_odc); iocore_attachout(0xde, amd_ode); + + iocore_attachinp(0xda, amd_ida); + iocore_attachinp(0xdb, amd_idb); +#if defined(TRACE) + iocore_attachinp(0xd8, amd_inp); + iocore_attachinp(0xd9, amd_inp); + iocore_attachinp(0xdc, amd_inp); + iocore_attachinp(0xde, amd_inp); +#endif }