PC-98 86PCM Support

This commit is contained in:
nanshiki
2022-08-14 16:45:15 +09:00
parent d0066f0e58
commit 54815780e9
8 changed files with 77 additions and 95 deletions

View File

@@ -147,10 +147,6 @@ static inline void FillMemory(void *p,size_t l,unsigned char c) {
}
#endif
static inline void pcm86io_bind(void) {
/* dummy */
}
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -18,7 +18,7 @@ libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler
snd_pc98/common/parts.c snd_pc98/generic/keydisp.c snd_pc98/sound/adpcmc.c snd_pc98/sound/adpcmg.c \
snd_pc98/sound/rhythmc.c snd_pc98/sound/sound.c snd_pc98/sound/getsnd/getwave.c snd_pc98/sound/getsnd/getsmix.c \
snd_pc98/sound/getsnd/getsnd.c snd_pc98/x11/dosio.c snd_pc98/sound/fmboard.c snd_pc98/sound/soundrom.c \
snd_pc98/cbus/board86.c snd_pc98/sound/fmtimer.c snd_pc98/cbus/board26k.c 8255.cpp opl2board/opl2board.cpp opl3duoboard/opl3duoboard.cpp \
snd_pc98/cbus/board86.c snd_pc98/cbus/pcm86io.c snd_pc98/sound/fmtimer.c snd_pc98/cbus/board26k.c 8255.cpp opl2board/opl2board.cpp opl3duoboard/opl3duoboard.cpp \
RetroWaveLib/Board/OPL3.c \
RetroWaveLib/Platform/Win32_SerialPort.c \
RetroWaveLib/Platform/POSIX_SerialPort.c \

View File

@@ -42,8 +42,7 @@ MixerChannel *pc98_mixer = NULL;
NP2CFG pccore;
static Bitu pcm86_ia460(Bitu port, Bitu iolen);
static unsigned int baseio;
extern "C" void pcm86io_setid(unsigned int baseio);
extern unsigned char pc98_mem_msw_m[8];
bool pc98_soundbios_rom_load = true;
@@ -140,43 +139,6 @@ Bitu pc98_fm86_read(Bitu port,Bitu iolen) {
return ~0ul;
}
static Bitu pcm86_ia460(Bitu port, Bitu iolen) {
(void)port;
(void)iolen;
return (baseio == 0x288 ? 0x53 : 0x43); // Hack return Sound ID
/* Sound ID baseio 0x188: 4 0x288: 5 */
}
#if 0
static Bitu pcm86_ia466(Bitu port, Bitu /*iolen*/) {
// Port 0xa466 Read: FIFO status
LOG_MSG("read port a466h: Always return 0x80 (FIFO Full)");
return 0x80;
}
static Bitu pcm86_ia468(Bitu port, Bitu /*iolen*/) {
// Port 0xa468 Read: FIFO control
LOG_MSG("read port a468h: Always return 0");
return 0;
}
static Bitu pcm86_ia46a(Bitu port, Bitu /*iolen*/) {
// Port 0xa46a Read: D/A converter control
LOG_MSG("read port a468h: Always return 0xB2");
return 0xB2;
}
static Bitu pcm86_ia46c(Bitu port, Bitu /*iolen*/) {
// Port 0xa46c Read: Read FIFO
LOG_MSG("read port a46ch: Always return 0");
return 0;
}
static Bitu pcm86_ia66e(Bitu port, Bitu /*iolen*/) {
// Port 0xa66e Read: Mute control
LOG_MSG("read port a66eh: Always return 0");
return 0;
}
#endif
// four I/O ports, 2 ports apart
void cbuscore_attachsndex(UINT port, const IOOUT *out, const IOINP *inp) {
LOG_MSG("cbuscore_attachsndex(port=0x%x)",port);
@@ -190,7 +152,6 @@ void cbuscore_attachsndex(UINT port, const IOOUT *out, const IOINP *inp) {
IO_RegisterWriteHandler(port+(i*2),pc98_fm86_write,IO_MB);
cbusm.out = out[i];
}
IO_RegisterReadHandler(0xa460, pcm86_ia460, IO_MB);
}
void pic_setirq(REG8 irq) {
@@ -425,7 +386,7 @@ void PC98_FM_OnEnterPC98(Section *sec) {
if (!pc98fm_init) {
unsigned char fmirqidx;
//unsigned int baseio;
unsigned int baseio;
std::string board;
int irq;
@@ -568,7 +529,8 @@ void PC98_FM_OnEnterPC98(Section *sec) {
}
fmboard_bind();
fmboard_extenable(true);
// Set sound ID
pcm86io_setid(baseio);
// WARNING: Some parts of the borrowed code assume 44100, 22050, or 11025 and
// will misrender if given any other sample rate (especially the OPNA synth).
@@ -580,7 +542,6 @@ void PC98_FM_OnEnterPC98(Section *sec) {
if (was_pc98fm_init) {
fmboard_on_reset();
fmboard_bind(); // FIXME: Re-binds I/O ports as well
fmboard_extenable(true);
}
}

View File

@@ -1,7 +1,4 @@
#include "compiler.h"
#include "cpucore.h"
#include "pccore.h"
#include "iocore.h"
#include "np2glue.h"
#include "pcm86io.h"
#include "sound.h"
#include "fmboard.h"
@@ -16,11 +13,10 @@ static const SINT32 pcm86rescue[] = {PCM86_RESCUE * 32, PCM86_RESCUE * 24,
PCM86_RESCUE * 8, PCM86_RESCUE * 6,
PCM86_RESCUE * 4, PCM86_RESCUE * 3};
static void IOOUTCALL pcm86_oa460(UINT port, REG8 val) {
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
pcm86.extfunc = val;
pcm86.soundflags = (pcm86.soundflags & 0xfe) | (val & 1);
fmboard_extenable((REG8)(val & 1));
(void)port;
}
@@ -43,33 +39,33 @@ static void IOOUTCALL pcm86_oa468(UINT port, REG8 val) {
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
sound_sync();
xchgbit = pcm86.fifo ^ val;
// <EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD>Z<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD>
// バッファリセット判定
if ((xchgbit & 8) && (val & 8)) {
pcm86.readpos = 0; // <EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD>Z<EFBFBD>b<EFBFBD>g
pcm86.readpos = 0; // バッファリセット
pcm86.wrtpos = 0;
pcm86.realbuf = 0;
pcm86.virbuf = 0;
pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
pcm86.lastclock <<= 6;
//pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
//pcm86.lastclock <<= 6;
}
if ((xchgbit & 0x10) && (!(val & 0x10))) {
pcm86.irqflag = 0;
// pcm86.write = 0;
// pcm86.reqirq = 0;
}
// <EFBFBD>T<EFBFBD><EFBFBD><EFBFBD>v<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>O<EFBFBD><EFBFBD><EFBFBD>[<5B>g<EFBFBD>ύX
// サンプリングレート変更
if (xchgbit & 7) {
pcm86.rescue = pcm86rescue[val & 7] << pcm86.stepbit;
pcm86_setpcmrate(val);
}
#if 1 // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>d<EFBFBD><EFBFBD><EFBFBD>ȃo<EFBFBD>O....
#if 1 // これ重大なバグ....
pcm86.fifo = val;
#else
pcm86.fifo = val & (~0x10);
#endif
if ((xchgbit & 0x80) && (val & 0x80)) {
pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
pcm86.lastclock <<= 6;
//pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
//pcm86.lastclock <<= 6;
}
pcm86_setnextintr();
(void)port;
@@ -114,13 +110,13 @@ static void IOOUTCALL pcm86_oa46c(UINT port, REG8 val) {
pcm86.buffer[pcm86.wrtpos] = val;
pcm86.wrtpos = (pcm86.wrtpos + 1) & PCM86_BUFMSK;
pcm86.realbuf++;
// <EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40>I<EFBFBD>[<5B>o<EFBFBD>[<5B>t<EFBFBD><74><EFBFBD>[<5B>̊Ď<CC8A>
// バッファオーバーフローの監視
if (pcm86.realbuf >= PCM86_REALBUFSIZE) {
#if 1
pcm86.realbuf -= 4;
pcm86.readpos = (pcm86.readpos + 4) & PCM86_BUFMSK;
#else
pcm86.realbuf &= 3; // align4<EFBFBD><EFBFBD><EFBFBD>߃E<EFBFBD>`
pcm86.realbuf &= 3; // align4決めウチ
pcm86.realbuf += PCM86_REALBUFSIZE - 4;
#endif
}
@@ -132,9 +128,9 @@ static void IOOUTCALL pcm86_oa46c(UINT port, REG8 val) {
pcm86.buffer[pcm86.wrtpos] = val;
pcm86.wrtpos = (pcm86.wrtpos + 1) & PCM86_BUFMSK;
pcm86.realbuf++;
// <EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40>I<EFBFBD>[<5B>o<EFBFBD>[<5B>t<EFBFBD><74><EFBFBD>[<5B>̊Ď<CC8A>
// バッファオーバーフローの監視
if (pcm86.realbuf >= PCM86_REALBUFSIZE) {
pcm86.realbuf &= 3; // align4<EFBFBD><EFBFBD><EFBFBD>߃E<EFBFBD>`
pcm86.realbuf &= 3; // align4決めウチ
pcm86.realbuf += PCM86_REALBUFSIZE - 4;
}
// pcm86.write = 1;
@@ -146,17 +142,23 @@ static void IOOUTCALL pcm86_oa46c(UINT port, REG8 val) {
static REG8 IOINPCALL pcm86_ia460(UINT port) {
(void)port;
return(0x40 | (pcm86.extfunc & 1));
(void)port;
return pcm86.soundflags;
}
// Bit0 flips syncronizing with the sampling rate set by port A468h.
// but I could not think of a good way to implement it.
// NEC Windows 3.1 sound driver freeze if bit0 does not change,
// so I have added a process to switch it on each call.
static uint8_t lrclock;
static REG8 IOINPCALL pcm86_ia466(UINT port) {
UINT32 past;
UINT32 cnt;
UINT32 stepclock;
// UINT32 past;
// UINT32 cnt;
// UINT32 stepclock;
REG8 ret;
#if 0
past = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
past <<= 6;
past -= pcm86.lastclock;
@@ -171,11 +173,14 @@ static REG8 IOINPCALL pcm86_ia466(UINT port) {
}
}
ret = ((past << 1) >= stepclock)?1:0;
if (pcm86.virbuf >= PCM86_LOGICALBUF) { // <20>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40>t<EFBFBD><74>
#endif
lrclock ^= 1;
ret = lrclock & 1;
if (pcm86.realbuf >= PCM86_REALBUFSIZE) { // バッファフル
ret |= 0x80;
}
else if (!pcm86.virbuf) { // <EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40>O
ret |= 0x40; // <EFBFBD><EFBFBD><EFBFBD>ƕρc
else if (!pcm86.realbuf) { // バッファ0
ret |= 0x40; // ちと変…
}
(void)port;
// TRACEOUT(("86pcm in %.4x %.2x", port, ret));
@@ -191,7 +196,7 @@ static REG8 IOINPCALL pcm86_ia468(UINT port) {
if (pcm86gen_intrq()) {
ret |= 0x10;
}
#elif 1 // <EFBFBD>ނ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>H
#elif 1 // むしろこう?
if (pcm86.fifo & 0x20) {
sound_sync();
if (pcm86.virbuf <= pcm86.fifosize) {
@@ -231,26 +236,33 @@ static REG8 IOINPCALL pcm86_inpdummy(UINT port) {
return(0);
}
static const IOOUT pcm86_o1[4] = {
pcm86_oa460, NULL, NULL, NULL };
// ----
static const IOINP pcm86_i1[4] = {
pcm86_ia460, NULL, NULL, NULL};
static const IOOUT pcm86_o2[4] = {
pcm86_oa466, pcm86_oa468, pcm86_oa46a, pcm86_oa46c };
static const IOINP pcm86_i2[4] = {
pcm86_ia466, pcm86_ia468, pcm86_ia46a, pcm86_inpdummy};
void pcm86io_bind(void) {
sound_streamregist(&pcm86, (SOUNDCB)pcm86gen_getpcm);
iocore_attachout(0xa460, pcm86_oa460);
iocore_attachout(0xa466, pcm86_oa466);
iocore_attachout(0xa468, pcm86_oa468);
iocore_attachout(0xa46a, pcm86_oa46a);
iocore_attachout(0xa46c, pcm86_oa46c);
iocore_attachinp(0xa460, pcm86_ia460);
iocore_attachinp(0xa462, pcm86_inpdummy);
iocore_attachinp(0xa464, pcm86_inpdummy);
iocore_attachinp(0xa466, pcm86_ia466);
iocore_attachinp(0xa468, pcm86_ia468);
iocore_attachinp(0xa46a, pcm86_ia46a);
iocore_attachinp(0xa46c, pcm86_inpdummy);
iocore_attachinp(0xa46e, pcm86_inpdummy);
//sound_streamregist(&pcm86, (SOUNDCB)pcm86gen_getpcm);
cbuscore_attachsndex(0xa460, pcm86_o1, pcm86_i1);
cbuscore_attachsndex(0xa466, pcm86_o2, pcm86_i2);
}
void pcm86io_setid(unsigned int baseio)
{
if(baseio == 0x288) {
// PC-9801-86 port=028xh
pcm86.soundflags = 0x50;
} else {
// PC-9801-86 port=018xh
pcm86.soundflags = 0x40;
}
}

View File

@@ -46,7 +46,7 @@ typedef struct {
UINT stepmask;
UINT8 fifo;
UINT8 extfunc;
UINT8 soundflags; /*!< <20>T<EFBFBD>E<EFBFBD><45><EFBFBD>h <20>t<EFBFBD><74><EFBFBD>O (A460) */
UINT8 dactrl;
UINT8 _write;
UINT8 stepbit;

View File

@@ -120,6 +120,11 @@ void pcm86_setnextintr(void) {
}
void SOUNDCALL pcm86gen_checkbuf(void) {
if (pcm86.realbuf <= pcm86.fifosize) {
pcm86.reqirq = 0;
pcm86.irqflag = 1;
pic_setirq(fmtimer.irq);
}
#if 0
long bufs;
UINT32 past;
@@ -165,7 +170,7 @@ BOOL pcm86gen_intrq(void) {
}
if (pcm86.fifo & 0x20) {
sound_sync();
if ((pcm86.reqirq) && (pcm86.virbuf <= pcm86.fifosize)) {
if ((pcm86.reqirq) && (pcm86.realbuf <= pcm86.fifosize)) {
pcm86.reqirq = 0;
pcm86.irqflag = 1;
return(TRUE);

View File

@@ -1167,6 +1167,7 @@ for /d %%i in ($(SolutionDir)\..\contrib\translations\*) do copy %%i\*.lng "$(Ou
<ClCompile Include="..\src\hardware\serialport\serialfile.cpp" />
<ClCompile Include="..\src\hardware\snd_pc98\cbus\board26k.c" />
<ClCompile Include="..\src\hardware\snd_pc98\cbus\board86.c" />
<ClCompile Include="..\src\hardware\snd_pc98\cbus\pcm86io.c" />
<ClCompile Include="..\src\hardware\snd_pc98\common\parts.c" />
<ClCompile Include="..\src\hardware\snd_pc98\generic\keydisp.c" />
<ClCompile Include="..\src\hardware\snd_pc98\sound\adpcmc.c" />
@@ -1807,6 +1808,7 @@ for /d %%i in ($(SolutionDir)\..\contrib\translations\*) do copy %%i\*.lng "$(Ou
<ClInclude Include="..\src\hardware\serialport\softmodem.h" />
<ClInclude Include="..\src\hardware\snd_pc98\cbus\board26k.h" />
<ClInclude Include="..\src\hardware\snd_pc98\cbus\board86.h" />
<ClInclude Include="..\src\hardware\snd_pc98\cbus\pcm86io.h" />
<ClInclude Include="..\src\hardware\snd_pc98\common\parts.h" />
<ClInclude Include="..\src\hardware\snd_pc98\common\profile.h" />
<ClInclude Include="..\src\hardware\snd_pc98\common\wavefile.h" />

View File

@@ -1596,6 +1596,9 @@
<ClCompile Include="..\src\misc\mkdir_p.cpp">
<Filter>Sources\misc</Filter>
</ClCompile>
<ClCompile Include="..\src\hardware\snd_pc98\cbus\pcm86io.c">
<Filter>Sources\hardware\snd_pc98\cbus</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\aviwriter\avi.h">
@@ -2531,6 +2534,9 @@
<ClInclude Include="..\src\libs\mt32\Display.h">
<Filter>Sources\libs\mt32</Filter>
</ClInclude>
<ClInclude Include="..\src\hardware\snd_pc98\cbus\pcm86io.h">
<Filter>Sources\hardware\snd_pc98\cbus</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\src\winres.rc">