Merge NP21/W rev.36

This commit is contained in:
Tomohiro Yoshidomi 2017-10-21 19:00:34 +09:00
parent 8875c9c80d
commit 896fd5a93b
74 changed files with 8903 additions and 1535 deletions

View File

@ -1,6 +1,6 @@
Neko Project II 0.86 kai rev.13
Neko Project II 0.86 kai rev.14
===
Oct 2, 2017
Oct 21, 2017
Build SDL2 port
---
@ -300,6 +300,14 @@ I/O:0x00D0
Release
---
* Oct 21, 2017 (rev.14)
- Merge NP21/w rev.36
* Mate-X PCM
* Sound Blaster 16
* OPL3 (MAME codes is GPL licence)
* Auto IDE BIOS
* Oct 16, 2017 (rev.13)
- Refix BEEP PCM
* Oct 2, 2017 (rev.13)
- remove CDDA mod
* Sep 20, 2017
@ -316,7 +324,6 @@ Release
- [libretro] state save/load
* Aug 23, 2017 (rev.10)
- Merge NP21/w rev.35 beta1
* SB16
* Aug 22, 2017
- Merge 私家
Merged

View File

@ -27,6 +27,7 @@
#if defined(SUPPORT_HRTIMER)
#include "timemng.h"
#endif
#include "fmboard.h"
#define BIOS_SIMULATE
@ -97,8 +98,8 @@ static void bios_reinitbyswitch(void) {
UINT8 biosflag;
UINT8 extmem; // LARGE_MEM //UINT16 extmem;
UINT8 boot;
FILEH fh;
OEMCHAR path[MAX_PATH];
//FILEH fh;
//OEMCHAR path[MAX_PATH];
if (!(pccore.dipsw[2] & 0x80)) {
#if defined(CPUCORE_IA32)
@ -483,8 +484,13 @@ UINT MEMCALL biosfunc(UINT32 adrs) {
bios_screeninit();
if (((pccore.model & PCMODELMASK) >= PCMODEL_VX) &&
(pccore.sound & 0x7e)) {
iocore_out8(0x188, 0x27);
iocore_out8(0x18a, 0x3f);
if(g_nSoundID == SOUNDID_MATE_X_PCM || g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_WSS){
iocore_out8(0x188, 0x27);
iocore_out8(0x18a, 0x30);
}else{
iocore_out8(0x188, 0x27);
iocore_out8(0x18a, 0x3f);
}
}
return(1);

View File

@ -12,9 +12,81 @@
#include "sound/fmboard.h"
#include "sound/sound.h"
#include "sound/soundrom.h"
#include "mpu98ii.h"
static int opna_idx = 0;
/* for OPL */
#ifdef USE_MAME
static void *opl3;
static int samplerate;
void *YMF262Init(INT clock, INT rate);
void YMF262ResetChip(void *chip);
void YMF262Shutdown(void *chip);
INT YMF262Write(void *chip, INT a, INT v);
UINT8 YMF262Read(void *chip, INT a);
void YMF262UpdateOne(void *chip, INT16 **buffer, INT length);
static void IOOUTCALL sb16_o20d2(UINT port, REG8 dat) {
(void)port;
g_opl.addr = dat;
g_opl3.s.addrl = dat; // Key Display用
YMF262Write(opl3, 0, dat);
}
static void IOOUTCALL sb16_o21d2(UINT port, REG8 dat) {
(void)port;
g_opl.reg[g_opl.addr] = dat;
//S98_put(NORMAL2608, g_opl.addr, dat);
opl3_writeRegister(&g_opl3, g_opl3.s.addrl, dat); // Key Display用
YMF262Write(opl3, 1, dat);
}
static void IOOUTCALL sb16_o22d2(UINT port, REG8 dat) {
(void)port;
g_opl.addr2 = dat;
g_opl3.s.addrh = dat; // Key Display用
YMF262Write(opl3, 2, dat);
}
static void IOOUTCALL sb16_o23d2(UINT port, REG8 dat) {
(void)port;
g_opl.reg[g_opl.addr2 + 0x100] = dat;
opl3_writeExtendedRegister(&g_opl3, g_opl3.s.addrh, dat); // Key Display用
//S98_put(EXTEND2608, opl.addr2, dat);
YMF262Write(opl3, 3, dat);
}
static void IOOUTCALL sb16_o28d2(UINT port, REG8 dat) {
/**
* PC/ATで言うところのAdlib互換ポート
* UltimaUnderWorldではこちらを叩く
*/
port = dat;
YMF262Write(opl3, 0, dat);
}
static void IOOUTCALL sb16_o29d2(UINT port, REG8 dat) {
port = dat;
YMF262Write(opl3, 1, dat);
}
static REG8 IOINPCALL sb16_i20d2(UINT port) {
(void)port;
return YMF262Read(opl3, 0);
}
static REG8 IOINPCALL sb16_i22d2(UINT port) {
(void)port;
return YMF262Read(opl3, 1);
}
static REG8 IOINPCALL sb16_i28d2(UINT port) {
(void)port;
return YMF262Read(opl3, 0);
}
#endif
static void IOOUTCALL ymf_o188(UINT port, REG8 dat)
{
g_opna[opna_idx].s.addrl = dat;
@ -41,6 +113,7 @@ static void IOOUTCALL ymf_o18a(UINT port, REG8 dat)
(void)port;
}
static void IOOUTCALL ymf_o18c(UINT port, REG8 dat)
{
if (g_opna[opna_idx].s.extend)
@ -142,7 +215,18 @@ static REG8 IOINPCALL ymf_ia460(UINT port)
return (0x80 | (cs4231.extfunc & 1));
}
}
char srnf;
static void IOOUTCALL srnf_oa460(UINT port, REG8 dat)
{
srnf = dat;
(void)port;
}
static REG8 IOINPCALL srnf_ia460(UINT port)
{
(void)port;
return (srnf);
}
static REG8 IOINPCALL wss_i881e(UINT port)
@ -179,33 +263,16 @@ static REG8 IOINPCALL wss_i548f(UINT port)
else return 0;// from PC-9821Nr166
}
/*static REG8 IOINPCALL wss_ff(UINT port)
{
(void)port;
return (0xFF);
}*/
static REG8 IOINPCALL wss_i148c(UINT port)
{
return (0xFE);
}
static REG8 IOINPCALL wss_i148d(UINT port)
{
return (0x80);
}
static void IOOUTCALL ym_o1488(UINT port, REG8 dat) //FM Music Register Address Port
{
g_opl3.s.addrl = dat;
(void)port;
}
REG8 opl_data;
static void IOOUTCALL ym_o1489(UINT port, REG8 dat) //FM Music Data Port
{
opl3_writeRegister(&g_opl3, g_opl3.s.addrl, dat);
opl_data = dat;
(void)port;
}
@ -223,46 +290,72 @@ static void IOOUTCALL ym_o148b(UINT port, REG8 dat) //Advanced FM Music Data Por
static REG8 IOINPCALL ym_i1488(UINT port) //FM Music Status Port
{
TRACEOUT(("%x read",port));
// if (opl_data == 0x80) return 0xe0;
if (opl_data == 0x21) return 0xc0;
return 0;
}
static REG8 IOINPCALL ym_i1489(UINT port) // ???
{
TRACEOUT(("%x read",port));
return opl3_readRegister(&g_opl3, g_opl3.s.addrl);
}
static REG8 IOINPCALL ym_i148a(UINT port) //Advanced FM Music Status Port
{
TRACEOUT(("%x read",port));
return opl3_readStatus(&g_opl3);
}
static REG8 IOINPCALL ym_i148b(UINT port) // ???
{
TRACEOUT(("%x read",port));
return opl3_readExtendedRegister(&g_opl3, g_opl3.s.addrh);
}
REG8 sound118;
static void IOOUTCALL csctrl_o148e(UINT port, REG8 dat) {
TRACEOUT(("write %x %x",port,dat));
sound118 = dat;
}
static REG8 IOINPCALL csctrl_i148e(UINT port) {
return(sound118);
TRACEOUT(("%x read",port));
}
REG8 control118;
static REG8 IOINPCALL csctrl_i148f(UINT port) {
TRACEOUT(("%x read",port));
(void)port;
if(sound118 == 0) return(0x03);
if(sound118 == 0x05) {
if(control118 == 0x04)return (0x04);
else if(control118 == 0) return 0;}
if(sound118 == 0) return(0x3);//PC-9801-118は3だけどYMFは0xff 2000はこれだけじゃまだダメ
if(sound118 == 0x05){
if(control118==4)return 4;
if(control118==0x0c) return 4;
if(control118==0)return 0;
}
if(sound118 == 0x04) return (0x00);
if(sound118 == 0x21) return (0x00);
if(sound118 == 0xff) return (0x00);
if(sound118 == 0x21) switch(0x00/*mpu98.irqnum2*/){//MIDI割り込み 00:IRQ10 01:IRQ6 02:IRQ5 03:IRQ3
case 10:return 0;
case 6: return 1;
case 5: return 2;
case 3: return 3;
default: return 0;
}
if(sound118 == 0xff) return (0x05);//bit0 MIDI割り込みあり bit1:Cb Na7 bit2:Mate-X bit3:A-Mate Ce2
else
return(0xff);
}
static void IOOUTCALL csctrl_o148f(UINT port, REG8 dat) {
TRACEOUT(("write %x %x",port,dat));
//if (sound118 == 0x21) switch(dat){
// case 0:mpu98.irqnum2 = 10;break;
// case 1:mpu98.irqnum2 = 6;break;
// case 2:mpu98.irqnum2 = 5;break;
// case 3:mpu98.irqnum2 = 3;break;
// default: break;
//}
control118 = dat;
}
/*
@ -317,15 +410,62 @@ static REG8 IOINPCALL csctrl_i486(UINT port) {
}
static REG8 IOINPCALL sb98_i2ad2(UINT port) {
TRACEOUT(("%x read",port));
return(0xaa);
}
static REG8 IOINPCALL sb98_i2ed2(UINT port) {
TRACEOUT(("%x read",port));
return(0xff);
}
static REG8 IOINPCALL sb98_i81d2(UINT port) {
// TRACEOUT(("%x read",port));
return(0xbf);
}
// ----
#ifdef USE_MAME
static SINT32 oplfm_softvolume_L = 0;
static SINT32 oplfm_softvolume_R = 0;
static SINT32 oplfm_softvolumereg_L = 0xff;
static SINT32 oplfm_softvolumereg_R = 0xff;
void SOUNDCALL opl3gen_getpcm2(void* opl3, SINT32 *pcm, UINT count) {
UINT i;
INT16 *buf[4];
INT16 s1l,s1r,s2l,s2r;
SINT32 oplfm_volume;
SINT32 *outbuf = pcm;
buf[0] = &s1l;
buf[1] = &s1r;
buf[2] = &s2l;
buf[3] = &s2r;
oplfm_volume = np2cfg.vol_fm;
if(oplfm_softvolumereg_L != cs4231.devvolume[0x30]){
oplfm_softvolumereg_L = cs4231.devvolume[0x30];
if(oplfm_softvolumereg_L & 0x80){ // FM L Mute
oplfm_softvolume_L = 0;
}else{
oplfm_softvolume_L = ((~oplfm_softvolumereg_L) & 0x1f); // FM L Volume
}
}
if(oplfm_softvolumereg_R != cs4231.devvolume[0x31]){
oplfm_softvolumereg_R = cs4231.devvolume[0x31];
if(oplfm_softvolumereg_R & 0x80){ // FM R Mute
oplfm_softvolume_R = 0;
}else{
oplfm_softvolume_R = ((~oplfm_softvolumereg_R) & 0x1f); // FM R Volume
}
}
for (i=0; i < count; i++) {
s1l = s1r = s2l = s2r = 0;
YMF262UpdateOne(opl3, buf, 1);
outbuf[0] += (SINT32)(((s1l << 1) * oplfm_volume * oplfm_softvolume_L) >> 10);
outbuf[1] += (SINT32)(((s1r << 1) * oplfm_volume * oplfm_softvolume_R) >> 10);
outbuf += 2;
}
}
#endif
static const IOOUT ymf_o[4] = {
ymf_o188, ymf_o18a, ymf_o18c, ymf_o18e};
@ -356,6 +496,25 @@ void board118_reset(const NP2CFG *pConfig)
cs4231io_reset();
soundrom_load(0xcc000, OEMTEXT("118"));
fmboard_extreg(extendchannel);
#ifdef SUPPORT_SOUND_SB16
#ifdef USE_MAME
if (opl3) {
if (samplerate != pConfig->samplingrate) {
YMF262Shutdown(opl3);
opl3 = YMF262Init(14400000, pConfig->samplingrate);
samplerate = pConfig->samplingrate;
} else {
YMF262ResetChip(opl3);
}
}
ZeroMemory(&g_sb16, sizeof(g_sb16));
ZeroMemory(&g_opl, sizeof(g_opl));
// ボードデフォルト IO:D2 DMA:3 INT:5
g_sb16.base = 0xd2;
g_sb16.dmach = 0x3;
g_sb16.dmairq = 0x5;
#endif
#endif
(void)pConfig;
}
@ -364,96 +523,62 @@ void board118_reset(const NP2CFG *pConfig)
*/
void board118_bind(void)
{
cs4231io_bind();
if(g_nSoundID==SOUNDID_PC_9801_86_WSS){
opna_idx = 1;
}else{
opna_idx = 0;
}
if(g_nSoundID==SOUNDID_PC_9801_86_WSS){
opna_bind(&g_opna[opna_idx]);
cs4231io_bind();
//cbuscore_attachsndex(0x188, ymf_o, ymf_i);
iocore_attachout(0xb460, ymf_oa460);
iocore_attachinp(0xb460, ymf_ia460);
//iocore_attachout(0x1488, ym_o1488);
//iocore_attachinp(0x1488, ym_i1488);
//iocore_attachout(0x1489, ym_o1489);
//iocore_attachout(0x148a, ym_o148a);
//iocore_attachout(0x148b, ym_o148b);
opl3_bind(&g_opl3);
//iocore_attachout(0x148e,csctrl_o148e);
//iocore_attachinp(0x148e,csctrl_i148e);
//iocore_attachout(0x148f,csctrl_o148f);
//iocore_attachinp(0x148f,csctrl_i148f);
//iocore_attachout(0x548e, wss_o548e);// YMF-701
//iocore_attachinp(0x548e, wss_i548e);// YMF-701
//iocore_attachinp(0x548f, wss_i548f);// YMF-701
//iocore_attachinp(0x486,csctrl_i486);
//iocore_attachinp(0x1480, ymf_ia460);
//iocore_attachinp(0x1481, ymf_ia460);
//
////偽SB-16 mode
// iocore_attachout(0x20d2, ym_o1488);//sb16 opl
// iocore_attachinp(0x20d2, ym_i1488);//sb16 opl
// iocore_attachout(0x21d2, ym_o1489);//sb16 opl
// iocore_attachout(0x22d2, ym_o148a);//sb16 opl3
// iocore_attachout(0x23d2, ym_o148b);//sb16 opl3
// iocore_attachout(0x28d2, ym_o1488);//sb16 opl?
// iocore_attachinp(0x28d2, ym_i1488);//sb16 opl
// iocore_attachout(0x29d2, ym_o1489);//sb16 opl?
// iocore_attachinp(0x81d2, csctrl_i486);// sb16 midi port
// iocore_attachinp(0x2ad2, sb98_i2ad2);// DSP Read Data Port
// iocore_attachinp(0x2ed2, sb98_i2ed2);// DSP Read Buffer Status (Bit 7)
//iocore_attachinp(0x881e, wss_i881e);
//iocore_attachinp(0x148c, wss_i148c);
//iocore_attachinp(0x148d, wss_i148d);
if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM){
iocore_attachout(cs4231.port[1], ymf_oa460);
iocore_attachinp(cs4231.port[1], ymf_ia460);
iocore_attachinp(0x881e, wss_i881e);
}else{
opna_bind(&g_opna[opna_idx]);
cs4231io_bind();
cbuscore_attachsndex(0x188, ymf_o, ymf_i);
cbuscore_attachsndex(cs4231.port[4],ymf_o, ymf_i);
#ifdef USE_MAME
iocore_attachout(cs4231.port[9], sb16_o20d2);
iocore_attachinp(cs4231.port[9], sb16_i20d2);
iocore_attachout(cs4231.port[9]+1, sb16_o21d2);
iocore_attachout(cs4231.port[9]+2, sb16_o22d2);
iocore_attachout(cs4231.port[9]+3, sb16_o23d2);
iocore_attachout(0x1488, ym_o1488);
iocore_attachinp(0x1488, ym_i1488);
iocore_attachout(0x1489, ym_o1489);
iocore_attachout(0x148a, ym_o148a);
iocore_attachout(0x148b, ym_o148b);
opl3_bind(&g_opl3);
if (!opl3) {
opl3 = YMF262Init(14400000, np2cfg.samplingrate);
samplerate = np2cfg.samplingrate;
}
sound_streamregist(opl3, (SOUNDCB)opl3gen_getpcm2);
#else
iocore_attachout(cs4231.port[9], ym_o1488);
iocore_attachinp(cs4231.port[9], ym_i1488);
iocore_attachout(cs4231.port[9]+1, ym_o1489);
iocore_attachout(cs4231.port[9]+2, ym_o148a);
iocore_attachout(cs4231.port[9]+3, ym_o148b);
#endif
opl3_bind(&g_opl3); // MAME使用の場合Key Display用
iocore_attachout(0xa460, ymf_oa460);
iocore_attachinp(0xa460, ymf_ia460);
iocore_attachout(cs4231.port[1], ymf_oa460);
iocore_attachinp(cs4231.port[1], ymf_ia460);
iocore_attachout(0x148e,csctrl_o148e);
iocore_attachinp(0x148e,csctrl_i148e);
iocore_attachout(0x148f,csctrl_o148f);
iocore_attachinp(0x148f,csctrl_i148f);
iocore_attachout(0x548e, wss_o548e);// YMF-701
iocore_attachinp(0x548e, wss_i548e);// YMF-701
iocore_attachinp(0x548f, wss_i548f);// YMF-701
iocore_attachinp(0x486,csctrl_i486);
iocore_attachinp(0x1480, ymf_ia460);
iocore_attachinp(0x1481, ymf_ia460);
//偽SB-16 mode
iocore_attachout(0x20d2, ym_o1488);//sb16 opl
iocore_attachinp(0x20d2, ym_i1488);//sb16 opl
iocore_attachout(0x21d2, ym_o1489);//sb16 opl
iocore_attachout(0x22d2, ym_o148a);//sb16 opl3
iocore_attachout(0x23d2, ym_o148b);//sb16 opl3
iocore_attachout(0x28d2, ym_o1488);//sb16 opl?
iocore_attachinp(0x28d2, ym_i1488);//sb16 opl
iocore_attachout(0x29d2, ym_o1489);//sb16 opl?
iocore_attachinp(0x81d2, csctrl_i486);// sb16 midi port
iocore_attachinp(0x2ad2, sb98_i2ad2);// DSP Read Data Port
iocore_attachinp(0x2ed2, sb98_i2ed2);// DSP Read Buffer Status (Bit 7)
//iocore_attachout(cs4231.port[15],srnf_oa460);//SRN-Fは必要なときだけ使う
//iocore_attachinp(cs4231.port[15],srnf_ia460);
//srnf = 0x81;
iocore_attachout(cs4231.port[14],csctrl_o148e);
iocore_attachinp(cs4231.port[14],csctrl_i148e);
iocore_attachout(cs4231.port[14]+1,csctrl_o148f);
iocore_attachinp(cs4231.port[14]+1,csctrl_i148f);
iocore_attachout(cs4231.port[6], wss_o548e);// YMF-701
iocore_attachinp(cs4231.port[6], wss_i548e);// YMF-701
iocore_attachinp(cs4231.port[6]+1, wss_i548f);// YMF-701
iocore_attachinp(cs4231.port[11]+6,csctrl_i486);
iocore_attachinp(0x881e, wss_i881e);
iocore_attachinp(0x148c, wss_i148c);
iocore_attachinp(0x148d, wss_i148d);
// iocore_attachout(cs4231.port[10], mpu98ii_o0);//MIDI PORT mpu98ii.c側で調整
// iocore_attachinp(cs4231.port[10], mpu98ii_i0);
// iocore_attachout(cs4231.port[10]+1, mpu98ii_o2);
// iocore_attachinp(cs4231.port[10]+1, mpu98ii_i2);
//mpu98.irqnum = mpu98.irqnum2;
}
}

View File

@ -1,206 +1,243 @@
#include "compiler.h"
#include "pccore.h"
#include "iocore.h"
#include "cbuscore.h"
#include "boardso.h"
#include "sound.h"
#include "ct1741io.h"
#include "ct1745io.h"
#include "fmboard.h"
//#include "s98.h"
#ifdef SUPPORT_SOUND_SB16
/**
* Creative Sound Blaster 16(98)
* YMF262-M(OPL3) + CT1741(PCM) + CT1745(MIXER) + YM2203(OPN - option)
*
* IO:D2 DMA:3 INT:5
*/
static void *opl3;
static const UINT8 sb16base[] = {0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde};
static int samplerate;
void *YMF262Init(INT clock, INT rate);
void YMF262ResetChip(void *chip);
void YMF262Shutdown(void *chip);
INT YMF262Write(void *chip, INT a, INT v);
UINT8 YMF262Read(void *chip, INT a);
void YMF262UpdateOne(void *chip, INT16 **buffer, INT length);
static void IOOUTCALL sb16_o0400(UINT port, REG8 dat) {
port = dat;
}
static void IOOUTCALL sb16_o0500(UINT port, REG8 dat) {
port = dat;
}
static void IOOUTCALL sb16_o0600(UINT port, REG8 dat) {
port = dat;
}
static void IOOUTCALL sb16_o0700(UINT port, REG8 dat) {
port = dat;
}
static void IOOUTCALL sb16_o8000(UINT port, REG8 dat) {
/* MIDI Data Port */
// TRACEOUT(("SB16-midi commands: %.2x", dat));
port = dat;
}
static void IOOUTCALL sb16_o8100(UINT port, REG8 dat) {
/* MIDI Stat Port */
// TRACEOUT(("SB16-midi status: %.2x", dat));
port = dat;
}
static void IOOUTCALL sb16_o2000(UINT port, REG8 dat) {
(void)port;
g_opl.addr = dat;
YMF262Write(opl3, 0, dat);
}
static void IOOUTCALL sb16_o2100(UINT port, REG8 dat) {
(void)port;
g_opl.reg[g_opl.addr] = dat;
//S98_put(NORMAL2608, g_opl.addr, dat);
YMF262Write(opl3, 1, dat);
}
static void IOOUTCALL sb16_o2200(UINT port, REG8 dat) {
(void)port;
g_opl.addr2 = dat;
YMF262Write(opl3, 2, dat);
}
static void IOOUTCALL sb16_o2300(UINT port, REG8 dat) {
(void)port;
g_opl.reg[g_opl.addr2 + 0x100] = dat;
//S98_put(EXTEND2608, opl.addr2, dat);
YMF262Write(opl3, 3, dat);
}
static void IOOUTCALL sb16_o2800(UINT port, REG8 dat) {
/**
* PC/ATで言うところのAdlib互換ポート
* UltimaUnderWorldではこちらを叩く
*/
port = dat;
YMF262Write(opl3, 0, dat);
}
static void IOOUTCALL sb16_o2900(UINT port, REG8 dat) {
port = dat;
YMF262Write(opl3, 1, dat);
}
static REG8 IOINPCALL sb16_i0400(UINT port) {
return 0xff;
}
static REG8 IOINPCALL sb16_i0500(UINT port) {
return 0;
}
static REG8 IOINPCALL sb16_i0600(UINT port) {
return 0;
}
static REG8 IOINPCALL sb16_i0700(UINT port) {
return 0;
}
static REG8 IOINPCALL sb16_i8000(UINT port) {
/* Midi Port */
return 0;
}
static REG8 IOINPCALL sb16_i8100(UINT port) {
/* Midi Port */
return 0;
}
static REG8 IOINPCALL sb16_i2000(UINT port) {
(void)port;
return YMF262Read(opl3, 0);
}
static REG8 IOINPCALL sb16_i2200(UINT port) {
(void)port;
return YMF262Read(opl3, 1);
}
static REG8 IOINPCALL sb16_i2800(UINT port) {
(void)port;
return YMF262Read(opl3, 0);
}
// ----
void SOUNDCALL opl3gen_getpcm(void* opl3, SINT32 *pcm, UINT count) {
UINT i;
INT16 *buf[4];
INT16 s1l,s1r,s2l,s2r;
SINT32 *outbuf = pcm;
buf[0] = &s1l;
buf[1] = &s1r;
buf[2] = &s2l;
buf[3] = &s2r;
for (i=0; i < count; i++) {
s1l = s1r = s2l = s2r = 0;
YMF262UpdateOne(opl3, buf, 1);
outbuf[0] += s1l << 1;
outbuf[1] += s1r << 1;
outbuf += 2;
}
}
void boardsb16_reset(const NP2CFG *pConfig) {
if (opl3) {
if (samplerate != pConfig->samplingrate) {
YMF262Shutdown(opl3);
opl3 = YMF262Init(14400000, pConfig->samplingrate);
samplerate = pConfig->samplingrate;
} else {
YMF262ResetChip(opl3);
}
}
ZeroMemory(&g_sb16, sizeof(g_sb16));
ZeroMemory(&g_opl, sizeof(g_opl));
// ボードデフォルト IO:D2 DMA:3 INT:5
g_sb16.base = 0xd2;
g_sb16.dmach = 0x3;
g_sb16.dmairq = 0x5;
ct1745io_reset();
ct1741io_reset();
}
void boardsb16_bind(void) {
ct1745io_bind();
ct1741io_bind();
iocore_attachout(0x2000 + g_sb16.base, sb16_o2000); /* FM Music Register Address Port */
iocore_attachout(0x2100 + g_sb16.base, sb16_o2100); /* FM Music Data Port */
iocore_attachout(0x2200 + g_sb16.base, sb16_o2200); /* Advanced FM Music Register Address Port */
iocore_attachout(0x2300 + g_sb16.base, sb16_o2300); /* Advanced FM Music Data Port */
iocore_attachout(0x2800 + g_sb16.base, sb16_o2800); /* FM Music Register Port */
iocore_attachout(0x2900 + g_sb16.base, sb16_o2900); /* FM Music Data Port */
iocore_attachinp(0x2000 + g_sb16.base, sb16_i2000); /* FM Music Status Port */
iocore_attachinp(0x2200 + g_sb16.base, sb16_i2200); /* Advanced FM Music Status Port */
iocore_attachinp(0x2800 + g_sb16.base, sb16_i2800); /* FM Music Status Port */
iocore_attachout(0x0400 + g_sb16.base, sb16_o0400); /* GAME Port */
iocore_attachout(0x0500 + g_sb16.base, sb16_o0500); /* GAME Port */
iocore_attachout(0x0600 + g_sb16.base, sb16_o0600); /* GAME Port */
iocore_attachout(0x0700 + g_sb16.base, sb16_o0700); /* GAME Port */
iocore_attachinp(0x0400 + g_sb16.base, sb16_i0400); /* GAME Port */
iocore_attachinp(0x0500 + g_sb16.base, sb16_i0500); /* GAME Port */
iocore_attachinp(0x0600 + g_sb16.base, sb16_i0600); /* GAME Port */
iocore_attachinp(0x0700 + g_sb16.base, sb16_i0700); /* GAME Port */
iocore_attachout(0x8000 + g_sb16.base, sb16_o8000); /* MIDI Port */
iocore_attachout(0x8100 + g_sb16.base, sb16_o8100); /* MIDI Port */
iocore_attachinp(0x8000 + g_sb16.base, sb16_i8000); /* MIDI Port */
iocore_attachinp(0x8100 + g_sb16.base, sb16_i8100); /* MIDI Port */
if (!opl3) {
opl3 = YMF262Init(14400000, np2cfg.samplingrate);
samplerate = np2cfg.samplingrate;
}
sound_streamregist(opl3, (SOUNDCB)opl3gen_getpcm);
}
#include "compiler.h"
#include "pccore.h"
#include "iocore.h"
#include "cbuscore.h"
#include "boardso.h"
#include "sound.h"
#include "ct1741io.h"
#include "ct1745io.h"
#include "fmboard.h"
//#include "s98.h"
#ifdef SUPPORT_SOUND_SB16
/**
* Creative Sound Blaster 16(98)
* YMF262-M(OPL3) + CT1741(PCM) + CT1745(MIXER) + YM2203(OPN - option)
*
* IO:D2 DMA:3 INT:5
*/
static void *opl3;
static const UINT8 sb16base[] = {0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde};
static int samplerate;
#ifdef USE_MAME
void *YMF262Init(INT clock, INT rate);
void YMF262ResetChip(void *chip);
void YMF262Shutdown(void *chip);
INT YMF262Write(void *chip, INT a, INT v);
UINT8 YMF262Read(void *chip, INT a);
void YMF262UpdateOne(void *chip, INT16 **buffer, INT length);
#endif
static void IOOUTCALL sb16_o0400(UINT port, REG8 dat) {
port = dat;
}
static void IOOUTCALL sb16_o0500(UINT port, REG8 dat) {
port = dat;
}
static void IOOUTCALL sb16_o0600(UINT port, REG8 dat) {
port = dat;
}
static void IOOUTCALL sb16_o0700(UINT port, REG8 dat) {
port = dat;
}
static void IOOUTCALL sb16_o8000(UINT port, REG8 dat) {
/* MIDI Data Port */
// TRACEOUT(("SB16-midi commands: %.2x", dat));
port = dat;
}
static void IOOUTCALL sb16_o8100(UINT port, REG8 dat) {
/* MIDI Stat Port */
// TRACEOUT(("SB16-midi status: %.2x", dat));
port = dat;
}
static void IOOUTCALL sb16_o2000(UINT port, REG8 dat) {
(void)port;
g_opl.addr = dat;
#ifdef USE_MAME
YMF262Write(opl3, 0, dat);
g_opl3.s.addrl = dat; // Key Display用
#endif
}
static void IOOUTCALL sb16_o2100(UINT port, REG8 dat) {
(void)port;
g_opl.reg[g_opl.addr] = dat;
//S98_put(NORMAL2608, g_opl.addr, dat);
#ifdef USE_MAME
YMF262Write(opl3, 1, dat);
opl3_writeRegister(&g_opl3, g_opl3.s.addrl, dat); // Key Display用
#endif
}
static void IOOUTCALL sb16_o2200(UINT port, REG8 dat) {
(void)port;
g_opl.addr2 = dat;
#ifdef USE_MAME
YMF262Write(opl3, 2, dat);
g_opl3.s.addrh = dat; // Key Display用
#endif
}
static void IOOUTCALL sb16_o2300(UINT port, REG8 dat) {
(void)port;
g_opl.reg[g_opl.addr2 + 0x100] = dat;
//S98_put(EXTEND2608, opl.addr2, dat);
#ifdef USE_MAME
YMF262Write(opl3, 3, dat);
opl3_writeExtendedRegister(&g_opl3, g_opl3.s.addrh, dat); // Key Display用
#endif
}
static void IOOUTCALL sb16_o2800(UINT port, REG8 dat) {
/**
* PC/ATで言うところのAdlib互換ポート
* UltimaUnderWorldではこちらを叩く
*/
port = dat;
#ifdef USE_MAME
YMF262Write(opl3, 0, dat);
#endif
}
static void IOOUTCALL sb16_o2900(UINT port, REG8 dat) {
port = dat;
#ifdef USE_MAME
YMF262Write(opl3, 1, dat);
#endif
}
static REG8 IOINPCALL sb16_i0400(UINT port) {
return 0xff;
}
static REG8 IOINPCALL sb16_i0500(UINT port) {
return 0;
}
static REG8 IOINPCALL sb16_i0600(UINT port) {
return 0;
}
static REG8 IOINPCALL sb16_i0700(UINT port) {
return 0;
}
static REG8 IOINPCALL sb16_i8000(UINT port) {
/* Midi Port */
return 0;
}
static REG8 IOINPCALL sb16_i8100(UINT port) {
/* Midi Port */
return 0;
}
static REG8 IOINPCALL sb16_i2000(UINT port) {
(void)port;
#ifdef USE_MAME
return YMF262Read(opl3, 0);
#endif
}
static REG8 IOINPCALL sb16_i2200(UINT port) {
(void)port;
#ifdef USE_MAME
return YMF262Read(opl3, 1);
#endif
}
static REG8 IOINPCALL sb16_i2800(UINT port) {
(void)port;
#ifdef USE_MAME
return YMF262Read(opl3, 0);
#endif
}
// ----
void SOUNDCALL opl3gen_getpcm(void* opl3, SINT32 *pcm, UINT count) {
UINT i;
INT16 *buf[4];
INT16 s1l,s1r,s2l,s2r;
SINT32 *outbuf = pcm;
SINT32 oplfm_volume;
oplfm_volume = np2cfg.vol_fm;
buf[0] = &s1l;
buf[1] = &s1r;
buf[2] = &s2l;
buf[3] = &s2r;
for (i=0; i < count; i++) {
s1l = s1r = s2l = s2r = 0;
#ifdef USE_MAME
YMF262UpdateOne(opl3, buf, 1);
#endif
outbuf[0] += (SINT32)(((s1l << 1) * oplfm_volume) >> 5);
outbuf[1] += (SINT32)(((s1r << 1) * oplfm_volume) >> 5);
outbuf += 2;
}
}
void boardsb16_reset(const NP2CFG *pConfig) {
if (opl3) {
if (samplerate != pConfig->samplingrate) {
#ifdef USE_MAME
YMF262Shutdown(opl3);
opl3 = YMF262Init(14400000, pConfig->samplingrate);
#endif
samplerate = pConfig->samplingrate;
} else {
#ifdef USE_MAME
YMF262ResetChip(opl3);
#endif
}
}
ZeroMemory(&g_sb16, sizeof(g_sb16));
ZeroMemory(&g_opl, sizeof(g_opl));
// ボードデフォルト IO:D2 DMA:3 INT:5
g_sb16.base = 0xd2;
g_sb16.dmach = 0x3;
g_sb16.dmairq = 0x5;
ct1745io_reset();
ct1741io_reset();
}
void boardsb16_bind(void) {
opl3_reset(&g_opl3, OPL3_HAS_OPL3L|OPL3_HAS_OPL3);
ct1745io_bind();
ct1741io_bind();
iocore_attachout(0x2000 + g_sb16.base, sb16_o2000); /* FM Music Register Address Port */
iocore_attachout(0x2100 + g_sb16.base, sb16_o2100); /* FM Music Data Port */
iocore_attachout(0x2200 + g_sb16.base, sb16_o2200); /* Advanced FM Music Register Address Port */
iocore_attachout(0x2300 + g_sb16.base, sb16_o2300); /* Advanced FM Music Data Port */
iocore_attachout(0x2800 + g_sb16.base, sb16_o2800); /* FM Music Register Port */
iocore_attachout(0x2900 + g_sb16.base, sb16_o2900); /* FM Music Data Port */
iocore_attachinp(0x2000 + g_sb16.base, sb16_i2000); /* FM Music Status Port */
iocore_attachinp(0x2200 + g_sb16.base, sb16_i2200); /* Advanced FM Music Status Port */
iocore_attachinp(0x2800 + g_sb16.base, sb16_i2800); /* FM Music Status Port */
iocore_attachout(0x0400 + g_sb16.base, sb16_o0400); /* GAME Port */
iocore_attachout(0x0500 + g_sb16.base, sb16_o0500); /* GAME Port */
iocore_attachout(0x0600 + g_sb16.base, sb16_o0600); /* GAME Port */
iocore_attachout(0x0700 + g_sb16.base, sb16_o0700); /* GAME Port */
iocore_attachinp(0x0400 + g_sb16.base, sb16_i0400); /* GAME Port */
iocore_attachinp(0x0500 + g_sb16.base, sb16_i0500); /* GAME Port */
iocore_attachinp(0x0600 + g_sb16.base, sb16_i0600); /* GAME Port */
iocore_attachinp(0x0700 + g_sb16.base, sb16_i0700); /* GAME Port */
iocore_attachout(0x8000 + g_sb16.base, sb16_o8000); /* MIDI Port */
iocore_attachout(0x8100 + g_sb16.base, sb16_o8100); /* MIDI Port */
iocore_attachinp(0x8000 + g_sb16.base, sb16_i8000); /* MIDI Port */
iocore_attachinp(0x8100 + g_sb16.base, sb16_i8100); /* MIDI Port */
if (!opl3) {
#ifdef USE_MAME
opl3 = YMF262Init(14400000, np2cfg.samplingrate);
#endif
samplerate = np2cfg.samplingrate;
}
sound_streamregist(opl3, (SOUNDCB)opl3gen_getpcm);
opl3_bind(&g_opl3); // MAME使用の場合Key Display用
}
#endif

View File

@ -8,7 +8,7 @@
#include "fmboard.h"
static const UINT8 cs4231dma[] = {0xff,0x00,0x01,0x03,0xff,0xff,0xff,0xff};
static const UINT8 cs4231dma[] = {0xff,0x00,0x01,0x03,0xff,0x00,0x01,0x03};
static const UINT8 cs4231irq[] = {0xff,0x03,0x06,0x0a,0x0c,0xff,0xff,0xff};
@ -68,6 +68,8 @@ static REG8 IOINPCALL csctrl_ic2d(UINT port) {
return((REG8)(cs4231.port[num] >> 8));
}
REG8 sa3_control;
REG8 sa3_control;
UINT8 sa3data[256];
static void IOOUTCALL csctrl_o480(UINT port, REG8 dat) {
sa3_control = dat;
@ -75,22 +77,47 @@ static void IOOUTCALL csctrl_o480(UINT port, REG8 dat) {
}
static REG8 IOINPCALL csctrl_i480(UINT port) {
TRACEOUT(("read %x",port));
return sa3_control;
(void)port;
}
static REG8 IOINPCALL csctrl_i481(UINT port) {
static void IOOUTCALL csctrl_o481(UINT port, REG8 dat) {
sa3data[sa3_control] = dat;
(void)port;
if(sa3_control == 0x17) return 0;
if(sa3_control == 0x18) return 0;
else return 0;
}
static REG8 IOINPCALL csctrl_i481(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return sa3data[sa3_control];
}
REG8 f4a_control;
UINT8 f4bdata[256];
static void IOOUTCALL csctrl_of4a(UINT port, REG8 dat) {
f4a_control = dat;
(void)port;
}
static REG8 IOINPCALL csctrl_if4a(UINT port) {
TRACEOUT(("read %x",port));
return f4a_control;
(void)port;
}
static void IOOUTCALL csctrl_of4b(UINT port, REG8 dat) {
f4bdata[f4a_control] = dat;
(void)port;
}
static REG8 IOINPCALL csctrl_if4b(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return f4bdata[f4a_control];
}
static REG8 IOINPCALL csctrl_iac6d(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return (0x54);
}
@ -101,43 +128,47 @@ static REG8 IOINPCALL csctrl_iac6e(UINT port) {
(void)port;
return 0;
}
static void IOOUTCALL csctrl_o51ee(UINT port, REG8 dat) {
(void)port;
}
static void IOOUTCALL csctrl_o51ef(UINT port, REG8 dat) {
(void)port;
}
static void IOOUTCALL csctrl_o56ef(UINT port, REG8 dat) {
(void)port;
}
static void IOOUTCALL csctrl_o57ef(UINT port, REG8 dat) {
(void)port;
}
static void IOOUTCALL csctrl_o5bef(UINT port, REG8 dat) {
static REG8 IOINPCALL srnf_i51ee(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return (0x02);
}
static REG8 IOINPCALL csctrl_i51ee(UINT port) {
static REG8 IOINPCALL srnf_i51ef(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return 0x1;//0b1;
}
static REG8 IOINPCALL csctrl_i51ef(UINT port) {
(void)port;
return (0xc2);
}
static REG8 IOINPCALL csctrl_i56ef(UINT port) {
(void)port;
return 0x10;//(0b00010000);
}
static REG8 IOINPCALL csctrl_i57ef(UINT port) {
(void)port;
return 0xc0;//(0b11000000);
}
static REG8 IOINPCALL csctrl_i5bef(UINT port) {
(void)port;
return 0x0a;//(0b00001010);
return 0xc2;
}
static REG8 IOINPCALL srnf_i56ef(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return (0x9f);
}
static REG8 IOINPCALL srnf_i57ef(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return (0xc0);
}
static REG8 IOINPCALL srnf_i59ef(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return 0x3;
}
static REG8 IOINPCALL srnf_i5bef(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return (0x0e);
}
static REG8 IOINPCALL ifab(UINT port) {
TRACEOUT(("read %x",port));
(void)port;
return (0);
}
// ----
@ -145,14 +176,6 @@ static REG8 IOINPCALL csctrl_i5bef(UINT port) {
void cs4231io_reset(void) {
cs4231.enable = 1;
if(g_nSoundID==SOUNDID_PC_9801_86_WSS){
cs4231.adrs = 0x0a;////0b00 001 010 INT0 DMA1
}else{
cs4231.adrs = 0x22;////0b00 100 010 INT5 DMA1
}
cs4231.dmairq = cs4231irq[(cs4231.adrs >> 3) & 7];
cs4231.dmach = cs4231dma[cs4231.adrs & 7];
/* 7 未使用
R/W 6
R/W 5-3 PCM音源割り込みアドレス
@ -168,13 +191,16 @@ void cs4231io_reset(void) {
011b= DMA #3
100b101b=
111b= DMAを使用しない
*/
if ((cs4231.adrs & 7) == 0x1/*0b001*/) cs4231.dmach = 0x00;
if ((cs4231.adrs & 7) == 0x2/*0b010*/) cs4231.dmach = 0x01;
if ((cs4231.adrs & 7) == 0x3/*0b011*/) cs4231.dmach = 0x03;
if ((cs4231.adrs & 7) == 0x6/*0b110*/) cs4231.dmach = 0x01;//YMF-701,715
if ((cs4231.adrs & 7) == 0x0/*0b000*/) cs4231.dmach = 0x01;//YMF-701,715
if ((cs4231.adrs & 7) == 0x7/*0b111*/) cs4231.dmach = 0xff;
*/
if(g_nSoundID==SOUNDID_PC_9801_86_WSS){
cs4231.adrs = 0x0a;////0b00 001 010 INT0 DMA1
}else if(g_nSoundID==SOUNDID_MATE_X_PCM){
cs4231.adrs = 0x22;////0b00 100 010 INT0 DMA1
}else{
cs4231.adrs = 0x23;////0b00 100 011 INT5 DMA3
}
cs4231.dmairq = cs4231irq[(cs4231.adrs >> 3) & 7];
cs4231.dmach = cs4231dma[cs4231.adrs & 7];
if (cs4231.dmach != 0xff) {
dmac_attach(DMADEV_CS4231, cs4231.dmach);
}
@ -186,38 +212,14 @@ void cs4231io_reset(void) {
}
cs4231.port[2] = 0x0f48; // WSS FIFO port
cs4231.port[4] = 0x0188; // OPN port
cs4231.port[5] = 0x0f4a; // canbe mixer i/o port?
/*Port    bit 
0F4Ah  R/W  7-0
PnP  00h:
 01h: OPNA ON/OFF???
 02h: ()
 03h: ()
 30h: FM音源
 31h: FM音源
 32h: CD-ROM
 33h: CD-ROM
 34h:
 35h:
 36h: ()
 
0F4Bh  R/W  7 
PnP  0:
 1:
 6-5 使
 4-0
 00000b:
  
  
 11111b:
*/
cs4231.port[5] = 0x0f4a; // canbe mixer i/o port?
cs4231.port[6] = 0x548e; // YMF-701/715?
cs4231.port[8] = 0x1480; // Joystick
cs4231.port[9] = 0x1488; // OPL3
cs4231.port[10] = 0x148c; // MIDI
cs4231.port[11] = 0x0480; //9801-118 control? OPLという情報もありだが…
cs4231.port[11] = 0x0480; //9801-118 control?
cs4231.port[14] = 0x148e; //9801-118 config
cs4231.port[15] = 0xffff;
cs4231.port[15] = 0xa460; //空いてるのでこっちを利用
TRACEOUT(("CS4231 - IRQ = %d", cs4231.dmairq));
TRACEOUT(("CS4231 - DMA channel = %d", cs4231.dmach));
@ -240,7 +242,16 @@ PnP
cs4231.reg.monoinput=0xc0;//1a from PC-9821Nr166
cs4231.reg.reserved3=0x80; //1b from PC-9821Nr166
cs4231.reg.reserved4=0x80; //1d from PC-9821Nr166
cs4231.intflag = 0x22;// 0x22??
cs4231.intflag = 0xcc;
sa3data[7] = 7;
sa3data[8] = 7;
switch (cs4231.dmairq){
case 0x0c:f4bdata[1] = 0;break;
case 0x0a:f4bdata[1] = 0x02;break;
case 0x03:f4bdata[1] = 0x03;break;
case 0x05:f4bdata[1] = 0x08;break;
}
}
void cs4231io_bind(void) {
@ -259,39 +270,37 @@ void cs4231io_bind(void) {
iocore_attachinp(0xac6d, csctrl_iac6d);
iocore_attachinp(0xac6e, csctrl_iac6e);
/* 必要な時だけ有効にすべき
//WSN-F???
iocore_attachout(0x51ee, csctrl_o51ee);
iocore_attachout(0x51ef, csctrl_o51ef);
iocore_attachout(0x56ef, csctrl_o56ef);
iocore_attachout(0x57ef, csctrl_o57ef);
iocore_attachout(0x5bef, csctrl_o5bef);
iocore_attachinp(0x51ee, csctrl_i51ee);
iocore_attachinp(0x51ef, csctrl_i51ef);
iocore_attachinp(0x56ef, csctrl_i56ef);
iocore_attachinp(0x57ef, csctrl_i57ef);
iocore_attachinp(0x5bef, csctrl_i5bef);
iocore_attachinp(0x51ee, srnf_i51ee);//7番めに読まれる
iocore_attachinp(0x51ef, srnf_i51ef);//1番最初にC2を返す
// iocore_attachinp(0x52ef, srnf_i52ef);//f40等を読み書きしたあとここを読んでエラー
iocore_attachinp(0x56ef, srnf_i56ef);//2番めに読まれて割り込み等の設定 4番めに2回読まれ直す
iocore_attachinp(0x57ef, srnf_i57ef);//5番めに読まれる
iocore_attachinp(0x59ef, srnf_i59ef);//3番めに読まれて何か調査 3と4でとりあえず通る
// iocore_attachinp(0x5aef, srnf_i5aef);//8番めに読まれて終わり
iocore_attachinp(0x5bef, srnf_i5bef);//6番めに読まれる
*/
}
}
int acicounter;
void IOOUTCALL cs4231io0_w8(UINT port, REG8 value) {
switch(port - cs4231.port[0]) {
case 0x00:
cs4231.adrs = value;
cs4231.adrs = value &= ~0x40;
cs4231.dmairq = cs4231irq[(value >> 3) & 7];
cs4231.dmach = cs4231dma[value & 7];
if ((value & 7) == 0x1/*0b001*/) cs4231.dmach = 0x00;
if ((value & 7) == 0x2/*0b010*/) cs4231.dmach = 0x01;
if ((value & 7) == 0x3/*0b011*/) cs4231.dmach = 0x03;
if ((value & 7) == 0x6/*0b110*/) cs4231.dmach = 0x01;// YMF-701,715
if ((value & 7) == 0x0/*0b000*/) cs4231.dmach = 0x01;// YMF-701.715
if ((value & 7) == 0x7/*0b111*/) cs4231.dmach = 0xff;
dmac_detach(DMADEV_CS4231);
if (cs4231.dmach != 0xff) {
if ((cs4231.adrs >>2) & 1){
if (cs4231.dmach == 0)dmac_attach(DMADEV_NONE, 1);
else dmac_attach(DMADEV_NONE, 0);
}
dmac_attach(DMADEV_CS4231, cs4231.dmach);
#if 0
if (cs4231.sdc_enable) {
if (cs4231.reg.iface & SDC) {
dmac.dmach[cs4231.dmach].ready = 1;
dmac_check();
}
@ -299,50 +308,58 @@ void IOOUTCALL cs4231io0_w8(UINT port, REG8 value) {
}
break;
case 0x04:
cs4231.index = value;
TRACEOUT(("index %x", cs4231.index & 0x1f));
case 0x04://Index Address
if ( !(cs4231.index & MCE) && (value & MCE) && (cs4231.reg.iface & (CAL0|CAL1) ) ) acicounter = 1;
if (!(cs4231.index & MCE)) cs4231.intflag |=(PRDY|CRDY);
cs4231.index = value & ~(INIT|TRD);
break;
case 0x05:
case 0x05://Index_Data
cs4231_control(cs4231.index & 0x1f, value);
TRACEOUT(("register %x", value ));
break;
case 0x06:
pic_resetirq(cs4231.dmairq);
cs4231.intflag &= 0xfe;
cs4231.reg.featurestatus &= 0x8f;
//TRACEOUT(("status %x", value));
case 0x06://Status
if (cs4231.intflag & INt) {
pic_resetirq(cs4231.dmairq);
}
cs4231.intflag &= ~INt;
cs4231.reg.featurestatus &= ~(PI|TI|CI);
break;
case 0x07:
cs4231_datasend(value);
// TRACEOUT(("PCM %x", value));
break;
}
}
REG8 IOINPCALL cs4231io0_r8(UINT port) {
REG8 ret;
switch(port - cs4231.port[0]) {
case 0x00:
return(cs4231.adrs);
case 0x03:
return(0x04);
// return(0x05);//PC-9821Nr
case 0x04:
TRACEOUT(("index r 0x%02x", cs4231.index & 0x7f));
if (cs4231.reg.mode_id & 0x40) return (cs4231.index &= 0x0f);
else return (cs4231.index &= 0x1f);
// return(cs4231.index & 0x7f);
case 0x05:
if ((cs4231.index & 0x1f) == 0x0c) return (cs4231.reg.mode_id |= 0x8a); //why 8a???
case 0x04://Index address
return(cs4231.index & ~(INIT|TRD|MCE));
case 0x05://Index Data
switch (cs4231.index & 0x1f){
case 0x0b://featurestatus
if(acicounter){
TRACEOUT(("acicounter"));
acicounter -= 1;
cs4231.reg.errorstatus |= ACI;
}else cs4231.reg.errorstatus &= ~ACI;
break;
case 0x0d:return 0;
default:
break;
}
return(*(((UINT8 *)(&cs4231.reg)) + (cs4231.index & 0x1f)));
case 0x06:
TRACEOUT(("status r 0x%02x", cs4231.intflag));
pic_resetirq(cs4231.dmairq);
return(cs4231.intflag);
if (cs4231.reg.errorstatus & (1 << 6)) cs4231.intflag |= SER;
return (cs4231.intflag);
case 0x07:
return (0x80);
}
return(0);
}
@ -353,6 +370,22 @@ void IOOUTCALL cs4231io5_w8(UINT port, REG8 value) {
case 0x00:
cs4231.extindex = value;
break;
case 0x01:
switch(cs4231.extindex){
case 0x02: // MODEM L ?
case 0x03: // MODEM R ?
case 0x30: // FM音源 L
case 0x31: // FM音源 R
case 0x32: // CD-DA L
case 0x33: // CD-DA R
case 0x34: // TV L
case 0x35: // TV R
case 0x36: // MODEM mono ?
// bit7:mute, bit6,5:reserved, bit4-0:volume(00000(MAX) - 11111(MIN))
cs4231.devvolume[cs4231.extindex] = value;
}
break;
}
}
@ -363,8 +396,20 @@ REG8 IOINPCALL cs4231io5_r8(UINT port) {
return(cs4231.extindex);
case 0x01:
if (cs4231.extindex == 1) {
switch(cs4231.extindex){
case 1:
return(0); // means opna int5 ???
case 0x02: // MODEM L ?
case 0x03: // MODEM R ?
case 0x30: // FM音源 L
case 0x31: // FM音源 R
case 0x32: // CD-DA L
case 0x33: // CD-DA R
case 0x34: // TV L
case 0x35: // TV R
case 0x36: // MODEM mono ?
// bit7:mute, bit6,5:reserved, bit4-0:volume(00000(MAX) - 11111(MIN))
return cs4231.devvolume[cs4231.extindex];
}
break;
}

View File

@ -1,4 +1,4 @@

#ifdef __cplusplus
extern "C" {
@ -18,3 +18,42 @@ REG8 IOINPCALL cs4231io5_r8(UINT port);
}
#endif
//Index Address Register 0xf44
#define TRD (1 << 5) //cs4231.index bit5 Transfer Request Disable
#define MCE (1 << 6) //cs4231.index bit6 Mode Change Enable
#define INIT (1 << 7)//cs4231.index bit7 Ititialization
//Status Register 0xf46
#define INt (1 << 0) //cs4231.intflag bit0 Interrupt Status
#define PRDY (1 << 1) //cs4231.intflag bit1 Playback Data Ready(PIO data)
#define PLR (1 << 2) //cs4231.intflag bit2 Playback Left/Right Sample
#define PULR (1 << 3) //cs4231.intflag bit3 Playback Upper/Lower Byte
#define SER (1 << 4) //cs4231.intflag bit4 Sample Error
#define CRDY (1 << 5) //cs4231.intflag bit5 Capture Data Ready(PIO)
#define CLR (1 << 6) //cs4231.intflag bit6 Capture Left/Right Sample
#define CUL (1 << 7) //cs4231.intglag bit7 Capture Upper/Lower Byte
//cs4231.reg.iface(9)
#define PEN (1 << 0) //bit0 Playback Enable set and reset without MCE
#define CEN (1 << 1) //bit1 Capture Enable
#define SDC (1 << 2) //bit2 Single DMA Channel 0 Dual 1 Single 逆と思ってたので修正すべし
#define CAL0 (1 << 3) //bit3 Calibration 0 No Calibration 1 Converter calibration
#define CAL1 (1 << 4) //bit4 2 DAC calibration 3 Full Calibration
#define PPIO (1 << 6) //bit6 Playback PIO Enable 0 DMA 1 PIO
#define CPIO (1 << 7) //bit7 Capture PIO Enable 0 DMA 1 PIO
//cs4231.reg.errorstatus(10)
#define ACI (1 << 5) //bit5 Auto-calibrate In-Progress
//cs4231.reg.pinctrl(11)
#define IEN (1 << 1) //bit1 Interrupt Enable reflect cs4231.intflag bit0
#define DEN (1 << 3) //bit3 Dither Enable only active in 8-bit unsigned mode
//cs4231.reg.modeid(12)
#define MODE2 (1 << 6) //bit6
//cs4231.reg.featurestatus(24)
#define PI (1 << 4) //bit4 Playback Interrupt pending from Playback DMA count registers
#define CI (1 << 5) //bit5 Capture Interrupt pending from record DMA count registers when SDC=1 non-functional
#define TI (1 << 6) //bit6 Timer Interrupt pending from timer count registers
// PI,CI,TI bits are reset by writing a "0" to the particular interrupt bit or by writing any value to the Status register

View File

@ -13,36 +13,6 @@
* Creative SoundBlaster16 mixer CT1745
*/
enum {
MIXER_RESET = 0x00,
MIXER_VOL_START = 0x30,
MIXER_VOL_END = 0x47,
MIXER_MASTER_LEFT = 0x0,
MIXER_MASTER_RIGHT,
MIXER_VOC_LEFT,
MIXER_VOC_RIGHT,
MIXER_MIDI_LEFT,
MIXER_MIDI_RIGHT,
MIXER_CD_LEFT,
MIXER_CD_RIGHT,
MIXER_LINE_LEFT,
MIXER_LINE_RIGHT,
MIXER_MIC,
MIXER_PCSPEAKER,
MIXER_OUT_SW,
MIXER_IN_SW_LEFT,
MIXER_IN_SW_RIGHT,
MIXER_IN_GAIN_LEFT,
MIXER_IN_GAIN_RIGHT,
MIXER_OUT_GAIN_LEFT,
MIXER_OUT_GAIN_RIGHT,
MIXER_AGC,
MIXER_TREBLE_LEFT,
MIXER_TREBLE_RIGHT,
MIXER_BASS_LEFT,
MIXER_BASS_RIGHT
};
static void ct1745_mixer_reset() {
ZeroMemory(g_sb16.mixreg, sizeof(g_sb16.mixreg));
@ -70,7 +40,7 @@ static void IOOUTCALL sb16_o2500(UINT port, REG8 dat) {
if (g_sb16.mixsel >= MIXER_VOL_START &&
g_sb16.mixsel <= MIXER_VOL_END) {
g_sb16.mixreg[g_sb16.mixsel - MIXER_VOL_START] = dat;
g_sb16.mixreg[g_sb16.mixsel] = dat;
return;
}

View File

@ -1,6 +1,36 @@
#ifdef __cplusplus
extern "C" {
#endif
enum {
MIXER_RESET = 0x00,
MIXER_VOL_START = 0x30,
MIXER_MASTER_LEFT = 0x30,
MIXER_MASTER_RIGHT,
MIXER_VOC_LEFT,
MIXER_VOC_RIGHT,
MIXER_MIDI_LEFT,
MIXER_MIDI_RIGHT,
MIXER_CD_LEFT,
MIXER_CD_RIGHT,
MIXER_LINE_LEFT,
MIXER_LINE_RIGHT,
MIXER_MIC,
MIXER_PCSPEAKER,
MIXER_OUT_SW,
MIXER_IN_SW_LEFT,
MIXER_IN_SW_RIGHT,
MIXER_IN_GAIN_LEFT,
MIXER_IN_GAIN_RIGHT,
MIXER_OUT_GAIN_LEFT,
MIXER_OUT_GAIN_RIGHT,
MIXER_AGC,
MIXER_TREBLE_LEFT,
MIXER_TREBLE_RIGHT,
MIXER_BASS_LEFT,
MIXER_BASS_RIGHT,
MIXER_VOL_END = 0x47
};
void ct1745io_reset(void);
void ct1745io_bind(void);

View File

@ -19,6 +19,8 @@
#include "sound.h"
#include "idebios.res"
#include "bios/biosmem.h"
#include "fmboard.h"
#include "cs4231io.h"
IDEIO ideio;
@ -1205,6 +1207,10 @@ REG16 IOINPCALL ideio_r16(UINT port) {
// ----
#if 1
static SINT32 cdda_softvolume_L = 0;
static SINT32 cdda_softvolume_R = 0;
static SINT32 cdda_softvolumereg_L = 0xff;
static SINT32 cdda_softvolumereg_R = 0xff;
static BRESULT SOUNDCALL playdevaudio(IDEDRV drv, SINT32 *pcm, UINT count) {
SXSIDEV sxsi;
@ -1212,11 +1218,44 @@ static BRESULT SOUNDCALL playdevaudio(IDEDRV drv, SINT32 *pcm, UINT count) {
const UINT8 *ptr;
SINT sampl;
SINT sampr;
double sampbias = soundcfg.rate / 44100.0;
SINT samploop;
double samploop2 = 0.0;
SINT samploopcount;
double sampcount2 = 0.0;
SINT32 buf_l;
SINT32 buf_r;
SINT32 buf_count;
SINT32 samplen_n;
SINT32 samplen_d;
static SINT32 sampcount2_n = 0;
SINT32 sampcount2_d;
samplen_n = soundcfg.rate;
samplen_d = 44100;
//if(samplen_n > samplen_d){
// // XXX: サンプリングレートが大きい場合のオーバーフロー対策・・・
// samplen_n /= 100;
// samplen_d /= 100;
//}
//if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_MATE_X_PCM || g_nSoundID == SOUNDID_PC_9801_86_WSS){
// if(cdda_softvolumereg_L != cs4231.devvolume[0x32]){
// cdda_softvolumereg_L = cs4231.devvolume[0x32];
// if(cdda_softvolumereg_L & 0x80){ // FM L Mute
// cdda_softvolume_L = 0;
// }else{
// cdda_softvolume_L = ((~cdda_softvolumereg_L) & 0x1f); // FM L Volume
// }
// }
// if(cdda_softvolumereg_R != cs4231.devvolume[0x33]){
// cdda_softvolumereg_R = cs4231.devvolume[0x33];
// if(cdda_softvolumereg_R & 0x80){ // FM R Mute
// cdda_softvolume_R = 0;
// }else{
// cdda_softvolume_R = ((~cdda_softvolumereg_R) & 0x1f); // FM R Volume
// }
// }
//}else{
cdda_softvolume_L = 0x1f;
cdda_softvolume_R = 0x1f;
cdda_softvolumereg_L = 0;
cdda_softvolumereg_R = 0;
//}
sxsi = sxsi_getptr(drv->sxsidrv);
if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) ||
@ -1225,38 +1264,49 @@ const UINT8 *ptr;
return(FAILURE);
}
while(count) {
r = min(count, drv->dabufrem * sampbias);
r = min(count, drv->dabufrem * samplen_n / samplen_d);
if (r) {
count -= r;
ptr = drv->dabuf + 2352 - drv->dabufrem * 4;
drv->dabufrem -= r / sampbias;
if(sampbias >= 1.0) {
sampcount2 = sampbias;
ptr = drv->dabuf + 2352 - (drv->dabufrem * 4);
drv->dabufrem -= r * samplen_d / samplen_n;
if(samplen_n < samplen_d){
//sampcount2_n = 0;
sampcount2_d = samplen_d;
buf_l = buf_r = buf_count = 0;
do {
sampl = ((SINT8)ptr[1] << 8) + ptr[0];
sampr = ((SINT8)ptr[3] << 8) + ptr[2];
pcm[0] += (SINT)((int)(sampl)*np2cfg.davolume/255);
pcm[1] += (SINT)((int)(sampr)*np2cfg.davolume/255);
sampcount2 -= 1.0;
if(sampcount2 < 1.0) {
sampcount2 += sampbias;
ptr += 4;
sampcount2_n += samplen_n;
buf_l += (SINT)((int)(sampl)*np2cfg.davolume*cdda_softvolume_L/255/31);
buf_r += (SINT)((int)(sampr)*np2cfg.davolume*cdda_softvolume_R/255/31);
buf_count++;
if(sampcount2_n > sampcount2_d){
pcm[0] += buf_l / buf_count;
pcm[1] += buf_r / buf_count;
//pcm[0] += (SINT)((int)(sampl)*np2cfg.davolume/255);
//pcm[1] += (SINT)((int)(sampr)*np2cfg.davolume/255);
pcm += 2 * (sampcount2_n / sampcount2_d);
--r;
sampcount2_n = sampcount2_n % sampcount2_d;
buf_l = buf_r = buf_count = 0;
}
} while(r > 0);
}else{
sampcount2_n = samplen_n;
sampcount2_d = samplen_d;
do {
sampl = ((SINT8)ptr[1] << 8) + ptr[0];
sampr = ((SINT8)ptr[3] << 8) + ptr[2];
pcm[0] += (SINT)((int)(sampl)*np2cfg.davolume*cdda_softvolume_L/255/31);
pcm[1] += (SINT)((int)(sampr)*np2cfg.davolume*cdda_softvolume_L/255/31);
sampcount2_n -= sampcount2_d;
if(sampcount2_n <= 0){
sampcount2_n += samplen_n;
ptr += 4;
}
pcm += 2;
} while(--r);
} else {
do {
sampl = ((SINT8)ptr[1] << 8) + ptr[0];
sampr = ((SINT8)ptr[3] << 8) + ptr[2];
samploopcount = (sampbias + samploop2) < 1.0 ? 1 : (SINT)(sampbias + samploop2);
for(samploop = 0; samploop < samploopcount; samploop++) {
pcm[samploop * 2 + 0] += (SINT)((int)(sampl)*np2cfg.davolume/255);
pcm[samploop * 2 + 1] += (SINT)((int)(sampr)*np2cfg.davolume/255);
}
ptr += 4 * (1.0 / sampbias < 1.0 ? 1 : (SINT)(1.0 / sampbias + samploop2));
pcm += 2 * samploopcount;
samploop2 = ((SINT)((sampbias + samploop2) * 1000) % 1000) / 1000.0;
} while(--r);
}
}
if (count == 0) {
@ -1276,6 +1326,149 @@ const UINT8 *ptr;
}
return(SUCCESS);
}
//static BRESULT SOUNDCALL playdevaudio(IDEDRV drv, SINT32 *pcm, UINT count) {
//
// SXSIDEV sxsi;
// UINT r;
//const UINT8 *ptr;
// SINT sampl;
// SINT sampr;
// double samplen;
// double sampcount2;
//
// samplen = (double)soundcfg.rate / 44100;
//
// sxsi = sxsi_getptr(drv->sxsidrv);
// if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) ||
// (!(sxsi->flag & SXSIFLAG_READY))) {
// drv->daflag = 0x14;
// return(FAILURE);
// }
// while(count) {
// r = min(count, drv->dabufrem * samplen);
// if (r) {
// count -= r;
// ptr = drv->dabuf + 2352 - (drv->dabufrem * 4);
// drv->dabufrem -= r / samplen;
// if(samplen < 1.0){
// sampcount2 = 0;
// do {
// sampl = ((SINT8)ptr[1] << 8) + ptr[0];
// sampr = ((SINT8)ptr[3] << 8) + ptr[2];
// ptr += 4;
// sampcount2 += samplen;
// if((int)(sampcount2) > 0){
// pcm[0] += (SINT)((int)(sampl)*np2cfg.davolume/255);
// pcm[1] += (SINT)((int)(sampr)*np2cfg.davolume/255);
// pcm += 2 * (int)(sampcount2);
// --r;
// sampcount2 = sampcount2 - (int)sampcount2;
// }
// } while(r > 0);
// }else{
// sampcount2 = samplen;
// do {
// sampl = ((SINT8)ptr[1] << 8) + ptr[0];
// sampr = ((SINT8)ptr[3] << 8) + ptr[2];
// pcm[0] += (SINT)((int)(sampl)*np2cfg.davolume/255);
// pcm[1] += (SINT)((int)(sampr)*np2cfg.davolume/255);
// sampcount2 -= 1.0;
// if(sampcount2 < 1.0){
// sampcount2 += samplen;
// ptr += 4;
// }
// pcm += 2;
// } while(--r);
// }
// }
// if (count == 0) {
// break;
// }
// if (drv->dalength == 0) {
// drv->daflag = 0x13;
// return(FAILURE);
// }
// if (sxsicd_readraw(sxsi, drv->dacurpos, drv->dabuf) != SUCCESS) {
// drv->daflag = 0x14;
// return(FAILURE);
// }
// drv->dalength--;
// drv->dacurpos++;
// drv->dabufrem = sizeof(drv->dabuf) / 4;
// }
// return(SUCCESS);
//}
//static BRESULT SOUNDCALL playdevaudio(IDEDRV drv, SINT32 *pcm, UINT count) {
//
// SXSIDEV sxsi;
// UINT r;
//const UINT8 *ptr;
// SINT sampl;
// SINT sampr;
// double sampbias = soundcfg.rate / 44100.0;
// SINT samploop;
// double samploop2 = 0.0;
// SINT samploopcount;
// double sampcount2 = 0.0;
//
// sxsi = sxsi_getptr(drv->sxsidrv);
// if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) ||
// (!(sxsi->flag & SXSIFLAG_READY))) {
// drv->daflag = 0x14;
// return(FAILURE);
// }
// while(count) {
// r = min(count, drv->dabufrem * sampbias);
// if (r) {
// count -= r;
// ptr = drv->dabuf + 2352 - drv->dabufrem * 4;
// drv->dabufrem -= r / sampbias;
// if(sampbias >= 1.0) {
// sampcount2 = sampbias;
// do {
// sampl = ((SINT8)ptr[1] << 8) + ptr[0];
// sampr = ((SINT8)ptr[3] << 8) + ptr[2];
// pcm[0] += (SINT)((int)(sampl)*np2cfg.davolume/255);
// pcm[1] += (SINT)((int)(sampr)*np2cfg.davolume/255);
// sampcount2 -= 1.0;
// if(sampcount2 < 1.0) {
// sampcount2 += sampbias;
// ptr += 4;
// }
// pcm += 2;
// } while(--r);
// } else {
// do {
// sampl = ((SINT8)ptr[1] << 8) + ptr[0];
// sampr = ((SINT8)ptr[3] << 8) + ptr[2];
// samploopcount = (sampbias + samploop2) < 1.0 ? 1 : (SINT)(sampbias + samploop2);
// for(samploop = 0; samploop < samploopcount; samploop++) {
// pcm[samploop * 2 + 0] += (SINT)((int)(sampl)*np2cfg.davolume/255);
// pcm[samploop * 2 + 1] += (SINT)((int)(sampr)*np2cfg.davolume/255);
// }
// ptr += 4 * (1.0 / sampbias < 1.0 ? 1 : (SINT)(1.0 / sampbias + samploop2));
// pcm += 2 * samploopcount;
// samploop2 = ((SINT)((sampbias + samploop2) * 1000) % 1000) / 1000.0;
// } while(--r);
// }
// }
// if (count == 0) {
// break;
// }
// if (drv->dalength == 0) {
// drv->daflag = 0x13;
// return(FAILURE);
// }
// if (sxsicd_readraw(sxsi, drv->dacurpos, drv->dabuf) != SUCCESS) {
// drv->daflag = 0x14;
// return(FAILURE);
// }
// drv->dalength--;
// drv->dacurpos++;
// drv->dabufrem = sizeof(drv->dabuf) / 4;
// }
// return(SUCCESS);
//}
static void SOUNDCALL playaudio(void *hdl, SINT32 *pcm, UINT count) {
@ -1343,6 +1536,7 @@ void ideio_reset(const NP2CFG *pConfig) {
REG8 i;
IDEDRV drv;
OEMCHAR tmpbiosname[16];
UINT8 useidebios;
ZeroMemory(&ideio, sizeof(ideio));
for (i=0; i<4; i++) {
@ -1354,7 +1548,21 @@ void ideio_reset(const NP2CFG *pConfig) {
ideio.wwait = np2cfg.idewwait;
ideio.bios = IDETC_NOBIOS;
if(np2cfg.idebios){
useidebios = np2cfg.idebios;
if(useidebios && np2cfg.autoidebios){
SXSIDEV sxsi;
for (i=0; i<4; i++) {
sxsi = sxsi_getptr(i);
if ((sxsi != NULL) && (np2cfg.idetype[i] == SXSIDEV_HDD) &&
(sxsi->devtype == SXSIDEV_HDD) && (sxsi->flag & SXSIFLAG_READY)) {
if(sxsi->surfaces != 8 || sxsi->sectors != 17){
TRACEOUT(("Incompatible CHS parameter detected. IDE BIOS automatically disabled."));
useidebios = 0;
}
}
}
}
if(useidebios){
_tcscpy(tmpbiosname, OEMTEXT("ide.rom"));
getbiospath(path, tmpbiosname, NELEMENTS(path));
fh = file_open_rb(path);

View File

@ -7,6 +7,8 @@
#include "iocore.h"
#include "cbuscore.h"
#include "mpu98ii.h"
#include "fmboard.h"
enum {
@ -1098,6 +1100,13 @@ void mpu98ii_bind(void) {
iocore_attachout(0x331, mpu98ii_o2);
iocore_attachinp(0x331, mpu98ii_i2);
}
// PC-9801-118
if(g_nSoundID == SOUNDID_PC_9801_118){
iocore_attachout(cs4231.port[10], mpu98ii_o0);
iocore_attachinp(cs4231.port[10], mpu98ii_i0);
iocore_attachout(cs4231.port[10]+1, mpu98ii_o2);
iocore_attachinp(cs4231.port[10]+1, mpu98ii_i2);
}
}
void mpu98ii_callback(void) {

View File

@ -18,14 +18,14 @@ enum {
#endif
#ifndef LOADINTELDWORD
#define LOADINTELDWORD(a) (((UINT32)(((UINT8*)a)[0])) | \
((UINT32)(((UINT8*)a)[1]) << 8) | \
((UINT32)(((UINT8*)a)[2]) << 16) | \
((UINT32)(((UINT8*)a)[3]) << 24))
#define LOADINTELDWORD(a) (((UINT32)(((UINT8*)(a))[0])) | \
((UINT32)(((UINT8*)(a))[1]) << 8) | \
((UINT32)(((UINT8*)(a))[2]) << 16) | \
((UINT32)(((UINT8*)(a))[3]) << 24))
#endif
#ifndef LOADINTELWORD
#define LOADINTELWORD(a) (((UINT16)((UINT8*)a)[0]) | ((UINT16)(((UINT8*)a)[1]) << 8))
#define LOADINTELWORD(a) (((UINT16)((UINT8*)(a))[0]) | ((UINT16)(((UINT8*)(a))[1]) << 8))
#endif
#ifndef STOREINTELDWORD
@ -43,25 +43,25 @@ enum {
/* Big Ending */
#ifndef LOADMOTOROLAQWORD
#define LOADMOTOROLAQWORD(a) (((UINT64)((UINT8*)a)[7]) | \
((UINT64)(((UINT8*)a)[6]) << 8) | \
((UINT64)(((UINT8*)a)[5]) << 16) | \
((UINT64)(((UINT8*)a)[4]) << 24) | \
((UINT64)(((UINT8*)a)[3]) << 32) | \
((UINT64)(((UINT8*)a)[2]) << 40) | \
((UINT64)(((UINT8*)a)[1]) << 48) | \
((UINT64)(((UINT8*)a)[0]) << 56))
#define LOADMOTOROLAQWORD(a) (((UINT64)((UINT8*)(a))[7]) | \
((UINT64)(((UINT8*)(a))[6]) << 8) | \
((UINT64)(((UINT8*)(a))[5]) << 16) | \
((UINT64)(((UINT8*)(a))[4]) << 24) | \
((UINT64)(((UINT8*)(a))[3]) << 32) | \
((UINT64)(((UINT8*)(a))[2]) << 40) | \
((UINT64)(((UINT8*)(a))[1]) << 48) | \
((UINT64)(((UINT8*)(a))[0]) << 56))
#endif
#ifndef LOADMOTOROLADWORD
#define LOADMOTOROLADWORD(a) (((UINT32)((UINT8*)a)[3]) | \
((UINT32)(((UINT8*)a)[2]) << 8) | \
((UINT32)(((UINT8*)a)[1]) << 16) | \
((UINT32)(((UINT8*)a)[0]) << 24))
#define LOADMOTOROLADWORD(a) (((UINT32)((UINT8*)(a))[3]) | \
((UINT32)(((UINT8*)(a))[2]) << 8) | \
((UINT32)(((UINT8*)(a))[1]) << 16) | \
((UINT32)(((UINT8*)(a))[0]) << 24))
#endif
#ifndef LOADMOTOROLAWORD
#define LOADMOTOROLAWORD(a) (((UINT16)((UINT8*)a)[1]) | ((UINT16)(((UINT8*)a)[0]) << 8))
#define LOADMOTOROLAWORD(a) (((UINT16)((UINT8*)(a))[1]) | ((UINT16)(((UINT8*)(a))[0]) << 8))
#endif
#ifndef STOREMOTOROLAQWORD

View File

@ -168,4 +168,4 @@ static BRESULT opencdm(SXSIDEV sxsi, const OEMCHAR *fname) {
}
#endif
#endif
#endif

View File

@ -159,4 +159,4 @@ opencue_err2:
return(FAILURE);
}
#endif
#endif

View File

@ -77,4 +77,4 @@ openiso_err1:
return(FAILURE);
}
#endif
#endif

View File

@ -281,4 +281,4 @@ openmds_err2:
return(FAILURE);
}
#endif
#endif

View File

@ -346,4 +346,4 @@ opennrg_err2:
return(FAILURE);
}
#endif
#endif

View File

@ -724,4 +724,4 @@ sxsiope_err1:
return(FAILURE);
}
#endif
#endif

View File

@ -83,4 +83,4 @@ const _XDFINFO *xdf;
return(SUCCESS);
}
#endif
#endif

View File

@ -489,15 +489,16 @@ BRESULT fdd_readid_d88(FDDFILE fdd) {
/* 170101 ST modified to work on Windows 9x/2000 form ... */
if (++fdc.crcn >= sectors) {
fdc.crcn = 0;
if(fdc.mt) {
fdc.hd ^= 1;
if (fdc.hd == 0) {
fdc.treg[fdc.us]++;
}
}
else {
fdc.treg[fdc.us]++;
}
/* np21w rev36 removed */
//if(fdc.mt) {
// fdc.hd ^= 1;
// if (fdc.hd == 0) {
// fdc.treg[fdc.us]++;
// }
//}
//else {
// fdc.treg[fdc.us]++;
//}
}
fdc.C = fdc.treg[fdc.us];
fdc.H = fdc.hd;

View File

@ -434,4 +434,4 @@ BRESULT fdd_write_dcp(FDDFILE fdd) {
return(SUCCESS);
}
#endif
#endif

View File

@ -941,4 +941,4 @@ BRESULT fdd_readid_nfd1(FDDFILE fdd) {
}
//
#endif
#endif

View File

@ -251,4 +251,4 @@ BRESULT fdd_readid_vfdd(FDDFILE fdd) {
return(SUCCESS);
}
#endif
#endif

View File

@ -832,4 +832,4 @@ BOOL fdd_isformating(void) {
return(FALSE);
}
#endif
#endif

View File

@ -276,4 +276,4 @@ BOOL fdd_isformating(void);
}
#endif
#endif
#endif

802
io/dmac.c
View File

@ -1,368 +1,434 @@
/**
* @file dmac.c
* @brief Implementation of the DMA controller
*/
#include "compiler.h"
#include "dmac.h"
#include "cpucore.h"
#include "iocore.h"
#include "sound.h"
#include "cs4231.h"
#include "sasiio.h"
void DMACCALL dma_dummyout(REG8 data) {
(void)data;
}
REG8 DMACCALL dma_dummyin(void) {
return(0xff);
}
REG8 DMACCALL dma_dummyproc(REG8 func) {
(void)func;
return(0);
}
static const DMAPROC dmaproc[] = {
{dma_dummyout, dma_dummyin, dma_dummyproc}, // NONE
{fdc_datawrite, fdc_dataread, fdc_dmafunc}, // 2HD
{fdc_datawrite, fdc_dataread, fdc_dmafunc}, // 2DD
#if defined(SUPPORT_SASI)
{sasi_datawrite, sasi_dataread, sasi_dmafunc}, // SASI
#else
{dma_dummyout, dma_dummyin, dma_dummyproc}, // SASI
#endif
{dma_dummyout, dma_dummyin, dma_dummyproc}, // SCSI
#if !defined(DISABLE_SOUND)
{dma_dummyout, dma_dummyin, cs4231dmafunc}, // CS4231
#else
{dma_dummyout, dma_dummyin, dma_dummyproc}, // SASI
#endif
};
// ----
void dmac_check(void) {
BOOL workchg;
DMACH ch;
REG8 bit;
workchg = FALSE;
ch = dmac.dmach;
bit = 1;
do {
if ((!(dmac.mask & bit)) && (ch->ready)) {
if (!(dmac.work & bit)) {
dmac.work |= bit;
if (ch->proc.extproc(DMAEXT_START)) {
dmac.stat &= ~bit;
dmac.working |= bit;
workchg = TRUE;
}
}
}
else {
if (dmac.work & bit) {
dmac.work &= ~bit;
dmac.working &= ~bit;
ch->proc.extproc(DMAEXT_BREAK);
workchg = TRUE;
}
}
bit <<= 1;
ch++;
} while(bit & 0x0f);
if (workchg) {
nevent_forceexit();
}
}
UINT dmac_getdatas(DMACH dmach, UINT8 *buf, UINT size) {
UINT leng;
UINT32 addr;
UINT i;
leng = min(dmach->leng.w, size);
if (leng) {
addr = dmach->adrs.d; // + mask
if (!(dmach->mode & 0x20)) { // dir +
for (i=0; i<leng; i++) {
buf[i] = MEMP_READ8(addr + i);
}
dmach->adrs.d += leng;
}
else { // dir -
for (i=0; i<leng; i++) {
buf[i] = MEMP_READ8(addr - i);
}
dmach->adrs.d -= leng;
}
dmach->leng.w -= leng;
if (dmach->leng.w == 0) {
dmach->proc.extproc(DMAEXT_END);
}
}
return(leng);
}
// ---- I/O
static void IOOUTCALL dmac_o01(UINT port, REG8 dat) {
DMACH dmach;
int lh;
dmach = dmac.dmach + ((port >> 2) & 3);
lh = dmac.lh;
dmac.lh = (UINT8)(lh ^ 1);
dmach->adrs.b[lh + DMA32_LOW] = dat;
dmach->adrsorg.b[lh] = dat;
}
static void IOOUTCALL dmac_o03(UINT port, REG8 dat) {
int ch;
DMACH dmach;
int lh;
ch = (port >> 2) & 3;
dmach = dmac.dmach + ch;
lh = dmac.lh;
dmac.lh = lh ^ 1;
dmach->leng.b[lh] = dat;
dmach->lengorg.b[lh] = dat;
dmac.stat &= ~(1 << ch);
}
static void IOOUTCALL dmac_o13(UINT port, REG8 dat) {
dmac.dmach[dat & 3].sreq = dat;
(void)port;
}
static void IOOUTCALL dmac_o15(UINT port, REG8 dat) {
if (dat & 4) {
dmac.mask |= (1 << (dat & 3));
}
else {
dmac.mask &= ~(1 << (dat & 3));
}
dmac_check();
(void)port;
}
static void IOOUTCALL dmac_o17(UINT port, REG8 dat) {
dmac.dmach[dat & 3].mode = dat;
(void)port;
}
static void IOOUTCALL dmac_o19(UINT port, REG8 dat) {
dmac.lh = DMA16_LOW;
(void)port;
(void)dat;
}
static void IOOUTCALL dmac_o1b(UINT port, REG8 dat) {
dmac.mask = 0x0f;
(void)port;
(void)dat;
}
static void IOOUTCALL dmac_o1f(UINT port, REG8 dat) {
dmac.mask = dat;
dmac_check();
(void)port;
}
static void IOOUTCALL dmac_o21(UINT port, REG8 dat) {
DMACH dmach;
dmach = dmac.dmach + (((port >> 1) + 1) & 3);
#if defined(CPUCORE_IA32)
dmach->adrs.b[DMA32_HIGH + DMA16_LOW] = dat;
#else
// IA16ÅÍ ver0.75ųŒø<EFBFBD>Aver0.76Å<EFBFBD>C<EFBFBD>³
dmach->adrs.b[DMA32_HIGH + DMA16_LOW] = dat & 0x0f;
#endif
/* 170101 ST modified to work on Windows 9x/2000 */
dmach->adrs.b[DMA32_HIGH + DMA16_HIGH] = 0;
}
static void IOOUTCALL dmac_o29(UINT port, REG8 dat) {
DMACH dmach;
dmach = dmac.dmach + (dat & 3);
dmach->bound = dat;
(void)port;
}
/* 170101 ST modified to work on Windows 9x/2000 form ... */
static void IOOUTCALL dmac_oE01(UINT port, REG8 dat) {
DMACH dmach;
dmach = dmac.dmach + ((port >> 1) & 0x07) - 2;
dmach->adrs.b[DMA32_HIGH + DMA16_HIGH] = dat;
}
/* 170101 ST modified to work on Windows 9x/2000 ... to */
static REG8 IOINPCALL dmac_i01(UINT port) {
DMACH dmach;
int lh;
dmach = dmac.dmach + ((port >> 2) & 3);
lh = dmac.lh;
dmac.lh = lh ^ 1;
return(dmach->adrs.b[lh + DMA32_LOW]);
}
static REG8 IOINPCALL dmac_i03(UINT port) {
DMACH dmach;
int lh;
dmach = dmac.dmach + ((port >> 2) & 3);
lh = dmac.lh;
dmac.lh = lh ^ 1;
return(dmach->leng.b[lh]);
}
static REG8 IOINPCALL dmac_i11(UINT port) {
(void)port;
return(dmac.stat); // ToDo!!
}
// ---- I/F
static const IOOUT dmaco00[16] = {
dmac_o01, dmac_o03, dmac_o01, dmac_o03,
dmac_o01, dmac_o03, dmac_o01, dmac_o03,
NULL, dmac_o13, dmac_o15, dmac_o17,
dmac_o19, dmac_o1b, NULL, dmac_o1f};
static const IOINP dmaci00[16] = {
dmac_i01, dmac_i03, dmac_i01, dmac_i03,
dmac_i01, dmac_i03, dmac_i01, dmac_i03,
dmac_i11, NULL, NULL, NULL,
NULL, NULL, NULL, NULL};
static const IOOUT dmaco21[8] = {
dmac_o21, dmac_o21, dmac_o21, dmac_o21,
dmac_o29, NULL, NULL, NULL};
void dmac_reset(const NP2CFG *pConfig) {
ZeroMemory(&dmac, sizeof(dmac));
dmac.lh = DMA16_LOW;
dmac.mask = 0xf;
dmac_procset();
// TRACEOUT(("sizeof(_DMACH) = %d", sizeof(_DMACH)));
(void)pConfig;
}
void dmac_bind(void) {
iocore_attachsysoutex(0x0001, 0x0ce1, dmaco00, 16);
iocore_attachsysinpex(0x0001, 0x0ce1, dmaci00, 16);
iocore_attachsysoutex(0x0021, 0x0cf1, dmaco21, 8);
/* 170101 ST modified to work on Windows 9x/2000 form ... */
iocore_attachout(0x0e05, dmac_oE01);
iocore_attachout(0x0e07, dmac_oE01);
iocore_attachout(0x0e09, dmac_oE01);
iocore_attachout(0x0e0b, dmac_oE01);
/* 170101 ST modified to work on Windows 9x/2000 ... to */
}
// ----
static void dmacset(REG8 channel) {
DMADEV *dev;
DMADEV *devterm;
UINT dmadev;
dev = dmac.device;
devterm = dev + dmac.devices;
dmadev = DMADEV_NONE;
while(dev < devterm) {
if (dev->channel == channel) {
dmadev = dev->device;
}
dev++;
}
if (dmadev >= NELEMENTS(dmaproc)) {
dmadev = 0;
}
// TRACEOUT(("dmac set %d - %d", channel, dmadev));
dmac.dmach[channel].proc = dmaproc[dmadev];
}
void dmac_procset(void) {
REG8 i;
for (i=0; i<4; i++) {
dmacset(i);
}
}
void dmac_attach(REG8 device, REG8 channel) {
dmac_detach(device);
if (dmac.devices < NELEMENTS(dmac.device)) {
dmac.device[dmac.devices].device = device;
dmac.device[dmac.devices].channel = channel;
dmac.devices++;
dmacset(channel);
}
}
void dmac_detach(REG8 device) {
DMADEV *dev;
DMADEV *devterm;
REG8 ch;
dev = dmac.device;
devterm = dev + dmac.devices;
while(dev < devterm) {
if (dev->device == device) {
break;
}
dev++;
}
if (dev < devterm) {
ch = dev->channel;
dev++;
while(dev < devterm) {
*(dev - 1) = *dev;
dev++;
}
dmac.devices--;
dmacset(ch);
}
}
/**
* @file dmac.c
* @brief Implementation of the DMA controller
*/
#include "compiler.h"
#include "dmac.h"
#include "cpucore.h"
#include "iocore.h"
#include "sound.h"
#include "cs4231.h"
#include "sasiio.h"
void DMACCALL dma_dummyout(REG8 data) {
TRACEOUT(("dma_dummyout"));
(void)data;
}
REG8 DMACCALL dma_dummyin(void) {
TRACEOUT(("dma_dummyin"));
return(0xff);
}
REG8 DMACCALL dma_dummyproc(REG8 func) {
(void)func;
return(0);
}
static const DMAPROC dmaproc[] = {
{dma_dummyout, dma_dummyin, dma_dummyproc}, // NONE
{fdc_datawrite, fdc_dataread, fdc_dmafunc}, // 2HD
{fdc_datawrite, fdc_dataread, fdc_dmafunc}, // 2DD
#if defined(SUPPORT_SASI)
{sasi_datawrite, sasi_dataread, sasi_dmafunc}, // SASI
#else
{dma_dummyout, dma_dummyin, dma_dummyproc}, // SASI
#endif
{dma_dummyout, dma_dummyin, dma_dummyproc}, // SCSI
#if !defined(DISABLE_SOUND)
{dma_dummyout, dma_dummyin, cs4231dmafunc}, // CS4231
#else
{dma_dummyout, dma_dummyin, dma_dummyproc}, // SASI
#endif
};
// ----
UINT8 bank;
UINT8 bank2;
void dmac_check(void) {
BOOL workchg;
DMACH ch;
REG8 bit;
workchg = FALSE;
ch = dmac.dmach;
bit = 1;
do {
if ((!(dmac.mask & bit)) && (ch->ready)) {
if (!(dmac.work & bit)) {
dmac.work |= bit;
if (ch->proc.extproc(DMAEXT_START)) {
dmac.stat &= ~bit;
dmac.working |= bit;
workchg = TRUE;
}
}
}
else {
if (dmac.work & bit) {
dmac.work &= ~bit;
dmac.working &= ~bit;
ch->proc.extproc(DMAEXT_BREAK);
workchg = TRUE;
}
}
bit <<= 1;
ch++;
} while(bit & 0x0f);
if (workchg) {
nevent_forceexit();
}
}
UINT dmac_getdatas(DMACH dmach, UINT8 *buf, UINT size) {
UINT leng;
UINT32 addr;
UINT i;
leng = min(dmach->leng.w, size);
if (leng) {
addr = dmach->adrs.d; // + mask
if (!(dmach->mode & 0x20)) { // dir +
for (i=0; i<leng; i++) {
buf[i] = MEMP_READ8(addr + i);
}
dmach->adrs.d += leng;
}
else { // dir -
for (i=0; i<leng; i++) {
buf[i] = MEMP_READ8(addr - i);
}
dmach->adrs.d -= leng;
}
dmach->leng.w -= leng;
if (dmach->leng.w == 0) {
dmach->proc.extproc(DMAEXT_END);
}
}
return(leng);
}
// ---- I/O
static void IOOUTCALL dmac_o01(UINT port, REG8 dat) {
DMACH dmach;
int lh;
dmach = dmac.dmach + ((port >> 2) & 3);
lh = dmac.lh;
dmac.lh = (UINT8)(lh ^ 1);
dmach->adrs.b[lh + DMA32_LOW] = dat;
dmach->adrsorg.b[lh] = dat;
dmach->startaddr = dmach->adrs.d;
}
static void IOOUTCALL dmac_o03(UINT port, REG8 dat) {
int ch;
DMACH dmach;
int lh;
ch = (port >> 2) & 3;
dmach = dmac.dmach + ch;
lh = dmac.lh;
dmac.lh = lh ^ 1;
dmach->leng.b[lh] = dat;
dmach->lengorg.b[lh] = dat;
dmac.stat &= ~(1 << ch);
//dmach->startcount =dmach->leng.w;
//dmach->lastaddr = dmach->startaddr + dmach->leng.w;
dmach->startcount = dmach->leng.w;
dmach->lastaddr = dmach->startaddr + dmach->leng.w;
}
static void IOOUTCALL dmac_o13_(UINT port, REG8 dat) {
if (dat& 4)
dmac.stat |= 1 << ((dat & 3) +4);
else
dmac.stat &= ~(1 << ((dat & 3) +4));
dmac.stat &=~(1 << (dat & 3));
dmac_check();
(void)port;
}
static void IOOUTCALL dmac_o13(UINT port, REG8 dat) {
dmac.dmach[dat & 3].sreq = dat;
dmac_check();
(void)port;
}
static void IOOUTCALL dmac_o15(UINT port, REG8 dat) {
if (dat & 4) {
dmac.mask |= (1 << (dat & 3));
}
else {
dmac.mask &= ~(1 << (dat & 3));
}
dmac_check();
(void)port;
}
static void IOOUTCALL dmac_o17(UINT port, REG8 dat) {
dmac.dmach[dat & 3].mode = dat;
(void)port;
}
static void IOOUTCALL dmac_o19(UINT port, REG8 dat) {
dmac.lh = DMA16_LOW;
(void)port;
(void)dat;
}
static void IOOUTCALL dmac_o1b(UINT port, REG8 dat) {
dmac.mask = 0x0f;
dmac.dmach[0].adrs.d = 0;
dmac.dmach[0].leng.w = 0;
dmac.dmach[1].adrs.d = 0;
dmac.dmach[1].leng.w = 0;
dmac.dmach[2].adrs.d = 0;
dmac.dmach[2].leng.w = 0;
dmac.dmach[3].adrs.d = 0;
dmac.dmach[3].leng.w = 0;
(void)port;
(void)dat;
}
static void IOOUTCALL dmac_o1d(UINT port, REG8 dat) {
dmac.mask = 0;
dmac_check();
(void)port;
(void)dat;
}
static void IOOUTCALL dmac_o1f(UINT port, REG8 dat) {
dmac.mask = dat;
dmac_check();
(void)port;
}
static void IOOUTCALL dmac_o21(UINT port, REG8 dat) {//バンク設定
DMACH dmach;
dmach = dmac.dmach + (((port >> 1) + 1) & 3);
#if defined(CPUCORE_IA32)
dmach->adrs.b[DMA32_HIGH + DMA16_LOW] = dat;
#else
// IA16では ver0.75で無効、ver0.76で修正
dmach->adrs.b[DMA32_HIGH + DMA16_LOW] = dat & 0x0f;//V30は20bitまで
#endif
dmach->adrs.b[DMA32_HIGH + DMA16_HIGH] = 0;//25bitより上はここでは転送できない→0E05
bank = dat;
if (dmach->bound != 3){
dmach->startaddr = dmach->adrs.d;
dmach->lastaddr = (bank <<16 | dmach->lastaddr);
}
else
{
dmach->startaddr = bank << 16 | dmach->adrs.d;
dmach->lastaddr = (bank <<16 | dmach->lastaddr);
TRACEOUT(("port =%x ch=%x bank = %x dma_address = %x\n",port,((port >> 1) + 1) & 3, dat, dmach->adrs.d));
}
}
static void IOOUTCALL dmac_o29(UINT port, REG8 dat) {
DMACH dmach;
dmach = dmac.dmach + (dat & 3);
// dmach = dmac.dmach + (dat & 0xf);
// TRACEOUT (("dmach %x",dat));// PC-98は4chしか持ってない
dmach->bound = (dat >> 2) & 3;
(void)port;
TRACEOUT(("port =%x ch= %x dma bound =%x\n",port,dat & 03 ,dmach->bound));
}
static REG8 IOINPCALL dmac_i01(UINT port) {
DMACH dmach;
int lh;
dmach = dmac.dmach + ((port >> 2) & 3);
lh = dmac.lh;
dmac.lh = lh ^ 1;
return(dmach->adrs.b[lh + DMA32_LOW]);
}
static REG8 IOINPCALL dmac_i03(UINT port) {
DMACH dmach;
int lh;
dmach = dmac.dmach + ((port >> 2) & 3);
lh = dmac.lh;
dmac.lh = lh ^ 1;
return(dmach->leng.b[lh]);
}
static REG8 IOINPCALL dmac_i11(UINT port) {
(void)port;
return(dmac.stat &= 0xf0); // ToDo!!
}
static void IOOUTCALL dmac_oe05(UINT port, REG8 dat) {
DMACH dmach;
// dmach = dmac.dmach + (((port >> 1) - 2) & 3);//qemu
// dmach = dmac.dmach + ((port >> 1) & 0x07) - 2;//np21/w
char channel;
//switch(port){//シフト計算は頭がおかしくなるのでswitchでごまかしました
// case 0xe05:channel = 0;break;
// case 0xe07:channel = 1;break;
// case 0xe09:channel = 2;break;
// case 0xe0b:channel = 3;
//}
channel = ((port - 0x05) & 0x07) >> 1;
dmach = dmac.dmach + channel;
dmach->adrs.b[DMA32_HIGH + DMA16_HIGH] = dat;
bank2 = dat;
dmach->startaddr = ((bank2 &0x7f) << 24) | dmach->adrs.d;
dmach->lastaddr = ((bank2 &0x7f) << 24) | (dmach->lastaddr);
TRACEOUT(("32bit DMA ch %x bank %x\n",channel, dmach->adrs.b[3]));
}
static void IOOUTCALL dmac_o2b(UINT port, REG8 dat) {
(void)port;
}
// ---- I/F
static const IOOUT dmaco00[16] = {
dmac_o01, dmac_o03, dmac_o01, dmac_o03,
dmac_o01, dmac_o03, dmac_o01, dmac_o03,
NULL, dmac_o13, dmac_o15, dmac_o17,
dmac_o19, dmac_o1b, dmac_o1d, dmac_o1f};
static const IOINP dmaci00[16] = {
dmac_i01, dmac_i03, dmac_i01, dmac_i03,
dmac_i01, dmac_i03, dmac_i01, dmac_i03,
dmac_i11, NULL, NULL, NULL,
NULL, NULL, NULL, NULL};
static const IOOUT dmaco21[8] = {
dmac_o21, dmac_o21, dmac_o21, dmac_o21,
dmac_o29, NULL, NULL, NULL};
void dmac_reset(const NP2CFG *pConfig) {
ZeroMemory(&dmac, sizeof(dmac));
dmac.lh = DMA16_LOW;
dmac.mask = 0xf;
dmac_procset();
TRACEOUT(("sizeof(_DMACH) = %d", sizeof(_DMACH)));
(void)pConfig;
}
void dmac_bind(void) {
iocore_attachsysoutex(0x0001, 0x0ce1, dmaco00, 16);
iocore_attachsysinpex(0x0001, 0x0ce1, dmaci00, 16);
iocore_attachsysoutex(0x0021, 0x0cf1, dmaco21, 8);
iocore_attachout(0x0e05, dmac_oe05); //DMA ch.0
iocore_attachout(0x0e07, dmac_oe05); //DMA ch.1
iocore_attachout(0x0e09, dmac_oe05); //DMA ch.2
iocore_attachout(0x0e0b, dmac_oe05); //DMA ch.3
//0x489はnecio.cで使ってる
//PC-H98??? EMM386.exeを組み込むと現れる
// iocore_attachout(0x2b,dmac_o11);
// iocore_attachinp(0x2d,dmac_i11);//when 0x2b = c8???
}
// ----
static void dmacset(REG8 channel) {
DMADEV *dev;
DMADEV *devterm;
UINT dmadev;
dev = dmac.device;
devterm = dev + dmac.devices;
dmadev = DMADEV_NONE;
while(dev < devterm) {
if (dev->channel == channel) {
dmadev = dev->device;
}
dev++;
}
if (dmadev >= NELEMENTS(dmaproc)) {
dmadev = 0;
}
switch(dmadev){
case 0:TRACEOUT(("dmac set %d - dummy", channel));break;
case 1:TRACEOUT(("dmac set %d - 2HD", channel));break;
case 2:TRACEOUT(("dmac set %d - 2DD", channel));break;
case 3:TRACEOUT(("dmac set %d - SASI", channel));break;
case 4:TRACEOUT(("dmac set %d - SCSI", channel));break;
case 5:TRACEOUT(("dmac set %d - cs4231p", channel));break;
}
dmac.dmach[channel].proc = dmaproc[dmadev];
}
void dmac_procset(void) {
REG8 i;
for (i=0; i<4; i++) {
dmacset(i);
}
}
void dmac_attach(REG8 device, REG8 channel) {
dmac_detach(device);
if (dmac.devices < NELEMENTS(dmac.device)) {
dmac.device[dmac.devices].device = device;
dmac.device[dmac.devices].channel = channel;
dmac.devices++;
dmacset(channel);
}
}
void dmac_detach(REG8 device) {
DMADEV *dev;
DMADEV *devterm;
REG8 ch;
dev = dmac.device;
devterm = dev + dmac.devices;
while(dev < devterm) {
if (dev->device == device) {
break;
}
dev++;
}
if (dev < devterm) {
ch = dev->channel;
dev++;
while(dev < devterm) {
*(dev - 1) = *dev;
dev++;
}
dmac.devices--;
//if (ch < 5)
dmacset(ch);
}
}

240
io/dmac.h
View File

@ -1,119 +1,121 @@
/**
* @file dmac.h
* @brief Interface of the DMA controller
*/
#pragma once
#include "pccore.h"
#ifndef DMACCALL
#define DMACCALL
#endif
enum {
DMAEXT_START = 0,
DMAEXT_END = 1,
DMAEXT_BREAK = 2,
DMA_INITSIGNALONLY = 1,
DMADEV_NONE = 0,
DMADEV_2HD = 1,
DMADEV_2DD = 2,
DMADEV_SASI = 3,
DMADEV_SCSI = 4,
DMADEV_CS4231 = 5,
DMADEV_CT1741 = 6
};
#if defined(BYTESEX_LITTLE)
enum {
DMA16_LOW = 0,
DMA16_HIGH = 1,
DMA32_LOW = 0,
DMA32_HIGH = 2
};
#elif defined(BYTESEX_BIG)
enum {
DMA16_LOW = 1,
DMA16_HIGH = 0,
DMA32_LOW = 2,
DMA32_HIGH = 0
};
#endif
typedef struct {
void (DMACCALL * outproc)(REG8 data);
REG8 (DMACCALL * inproc)(void);
REG8 (DMACCALL * extproc)(REG8 action);
} DMAPROC;
typedef struct {
union {
UINT8 b[4];
UINT16 w[2];
UINT32 d;
} adrs;
union {
UINT8 b[2];
UINT16 w;
} leng;
union {
UINT8 b[2];
UINT16 w;
} adrsorg;
union {
UINT8 b[2];
UINT16 w;
} lengorg;
UINT8 bound;
UINT8 action;
DMAPROC proc;
UINT8 mode;
UINT8 sreq;
UINT8 ready;
UINT8 mask;
} _DMACH, *DMACH;
typedef struct {
UINT8 device;
UINT8 channel;
} DMADEV;
typedef struct {
_DMACH dmach[4];
int lh;
UINT8 work;
UINT8 working;
UINT8 mask;
UINT8 stat;
UINT devices;
DMADEV device[8];
} _DMAC, *DMAC;
#ifdef __cplusplus
extern "C" {
#endif
void DMACCALL dma_dummyout(REG8 data);
REG8 DMACCALL dma_dummyin(void);
REG8 DMACCALL dma_dummyproc(REG8 func);
void dmac_reset(const NP2CFG *pConfig);
void dmac_bind(void);
void dmac_extbind(void);
void dmac_check(void);
UINT dmac_getdatas(DMACH dmach, UINT8 *buf, UINT size);
void dmac_procset(void);
void dmac_attach(REG8 device, REG8 channel);
void dmac_detach(REG8 device);
#ifdef __cplusplus
}
#endif
/**
* @file dmac.h
* @brief Interface of the DMA controller
*/
#pragma once
#include "pccore.h"
#ifndef DMACCALL
#define DMACCALL
#endif
enum {
DMAEXT_START = 0,
DMAEXT_END = 1,
DMAEXT_BREAK = 2,
DMA_INITSIGNALONLY = 1,
DMADEV_NONE = 0,
DMADEV_2HD = 1,
DMADEV_2DD = 2,
DMADEV_SASI = 3,
DMADEV_SCSI = 4,
DMADEV_CS4231 = 5,
DMADEV_CT1741 = 6
};
#if defined(BYTESEX_LITTLE)
enum {
DMA16_LOW = 0,
DMA16_HIGH = 1,
DMA32_LOW = 0,
DMA32_HIGH = 2
};
#elif defined(BYTESEX_BIG)
enum {
DMA16_LOW = 1,
DMA16_HIGH = 0,
DMA32_LOW = 2,
DMA32_HIGH = 0
};
#endif
typedef struct {
void (DMACCALL * outproc)(REG8 data);
REG8 (DMACCALL * inproc)(void);
REG8 (DMACCALL * extproc)(REG8 action);
} DMAPROC;
typedef struct {
UINT32 startaddr;
UINT32 lastaddr;
UINT16 startcount;
union {
UINT8 b[4];
UINT16 w[2];
UINT32 d;
} adrs;
union {
UINT8 b[2];
UINT16 w;
} leng;
union {
UINT8 b[2];
UINT16 w;
} adrsorg;
union {
UINT8 b[2];
UINT16 w;
} lengorg;
UINT8 bound;
UINT8 action;
DMAPROC proc;
UINT8 mode;
UINT8 sreq;
UINT8 ready;
UINT8 mask;
} _DMACH, *DMACH;
typedef struct {
UINT8 device;
UINT8 channel;
} DMADEV;
typedef struct {
_DMACH dmach[8];
int lh;
UINT8 work;
UINT8 working;
UINT8 mask;
UINT8 stat;
UINT devices;
DMADEV device[8];
} _DMAC, *DMAC;
#ifdef __cplusplus
extern "C" {
#endif
void DMACCALL dma_dummyout(REG8 data);
REG8 DMACCALL dma_dummyin(void);
REG8 DMACCALL dma_dummyproc(REG8 func);
void dmac_reset(const NP2CFG *pConfig);
void dmac_bind(void);
void dmac_extbind(void);
void dmac_check(void);
UINT dmac_getdatas(DMACH dmach, UINT8 *buf, UINT size);
void dmac_procset(void);
void dmac_attach(REG8 device, REG8 channel);
void dmac_detach(REG8 device);
#ifdef __cplusplus
}
#endif

View File

@ -66,8 +66,8 @@ SOURCES_C += $(NP2_PATH)/sdl2/libretro/libretro-common/compat/compat_strcasestr
$(NP2_PATH)/i386c/ia32/instructions/fpu/fpemul_dosbox.c
OBJECTS = $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o)
CXXFLAGS += -D__LIBRETRO__ $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CFLAGS += -D__LIBRETRO__ $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CXXFLAGS += -D__LIBRETRO__ $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
CFLAGS += -D__LIBRETRO__ $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
LDFLAGS += -lm -lpthread $(fpic)
ifeq ($(platform), unix)
CXXFLAGS += -DSUPPORT_NET -DSUPPORT_LGY98

View File

@ -3,7 +3,7 @@
* @brief The version
*/
#define NP2VER_CORE "ver.0.86 kai rev.13"
#define NP2VER_CORE "ver.0.86 kai rev.14"
// #define NP2VER_WIN9X
// #define NP2VER_MACOSX

View File

@ -84,7 +84,7 @@ const OEMCHAR np2version[] = OEMTEXT(NP2VER_CORE);
1, 0x000000, 0xffffff,
44100, 250, 4, 0,
{0, 0, 0}, 0xd1, 0x7f, 0xd1, 0, 0, 1,
3, {0x0c, 0x0c, 0x08, 0x06, 0x03, 0x0c}, 64, 64, 64, 64, 64, 64,
3, {0x0c, 0x0c, 0x08, 0x06, 0x03, 0x0c}, 64, 64, 64, 64, 64,
1, 0x82, 0,
0, {0x17, 0x04, 0x1f}, {0x0c, 0x0c, 0x02, 0x10, 0x3f, 0x3f},
#if defined(SUPPORT_FMGEN)
@ -97,7 +97,7 @@ const OEMCHAR np2version[] = OEMTEXT(NP2VER_CORE);
{OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")},
{SXSIDEV_HDD, SXSIDEV_HDD, SXSIDEV_CDROM, SXSIDEV_HDD},
{OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")},
1, 0, 0, 40000,
1, 1, 0, 0, 0,
#else
{OEMTEXT(""), OEMTEXT("")},
#endif

View File

@ -53,6 +53,7 @@ enum tagSoundId
SOUNDID_SB16 = 0x41, /*!< Sound Blaster 16 */
SOUNDID_MATE_X_PCM = 0x60, /*!< Mate-X PCM */
SOUNDID_PC_9801_86_WSS = 0x64, /*!< PC-9801-86 + Mate-X PCM(B460) */
SOUNDID_PC_9801_86_118 = 0x68, /*!< PC-9801-86 + PC-9801-118(B460) */
SOUNDID_AMD98 = 0x80, /*!< AMD-98 */
SOUNDID_SOUNDORCHESTRA = 0x32, /*!< SOUND ORCHESTRA */
SOUNDID_SOUNDORCHESTRAV = 0x82, /*!< SOUND ORCHESTRA-V */
@ -131,7 +132,6 @@ struct tagNP2Config
UINT8 vol_adpcm;
UINT8 vol_pcm;
UINT8 vol_rhythm;
UINT8 vol_cdda; // ’ljÁ(kaiE)
UINT8 mpuenable;
UINT8 mpuopt;
@ -160,6 +160,7 @@ struct tagNP2Config
UINT8 idetype[4]; // ver0.86w
OEMCHAR idecd[4][MAX_PATH]; // ver0.85w
UINT8 idebios; // ver0.86w rev20
UINT8 autoidebios; // ver0.86w rev36
UINT32 iderwait; // IDE読み取りの割り込み遅延時間(clock)。 np21w ver0.86 rev19
UINT32 idewwait; // IDE書き込みの割り込み遅延時間(clock)。 np21w ver0.86 rev18
UINT32 idemwait; // IDE BIOSがある場合の割り込み遅延最小値 np21w ver0.86 rev26

View File

@ -17,6 +17,7 @@ INCFLAGS := -I$(NP2_PATH) \
-I$(NP2_PATH)/mem \
-I$(NP2_PATH)/sound \
-I$(NP2_PATH)/sound/vermouth \
-I$(NP2_PATH)/sound/mame \
-I$(NP2_PATH)/sound/fmgen \
-I$(NP2_PATH)/trap \
-I$(NP2_PATH)/vram \
@ -64,6 +65,7 @@ SOURCES_C := $(NP2_PATH)/calendar.c \
$(NP2_PATH)/sdl2/trace.c \
$(wildcard $(NP2_PATH)/sound/*.c) \
$(wildcard $(NP2_PATH)/sound/getsnd/*.c) \
$(wildcard $(NP2_PATH)/sound/mame/*.c) \
$(wildcard $(NP2_PATH)/sound/vermouth/*.c) \
$(wildcard $(NP2_PATH)/trap/*.c) \
$(wildcard $(NP2_PATH)/vram/*.c) \

View File

@ -290,8 +290,8 @@ SOURCES_C += $(NP2_PATH)/sdl2/libretro/libretro-common/compat/compat_strcasestr
$(NP2_PATH)/i386c/ia32/instructions/fpu/fpemul_dosbox.c
OBJECTS = $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o)
CXXFLAGS += -D__LIBRETRO__ $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CFLAGS += -D__LIBRETRO__ $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CXXFLAGS += -D__LIBRETRO__ $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
CFLAGS += -D__LIBRETRO__ $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
LDFLAGS += -lm -lpthread $(fpic)
ifeq ($(platform), unix)

View File

@ -33,8 +33,8 @@ SOURCES_C += $(wildcard $(NP2_PATH)/i286c/*.c) \
$(NP2_PATH)/sdl2/unix/main.c
OBJECTS = $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o)
CXXFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CXXFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
CFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
LDFLAGS += -lm $(fpic) -lpthread $(SDL_LIBS) -lSDL2_ttf -lSDL2_mixer
ifeq ($(SUPPORT_NET), 1)

View File

@ -32,8 +32,8 @@ SOURCES_C += $(wildcard $(NP2_PATH)/i286c/*.c) \
$(NP2_PATH)/sdl2/win32/main.c
OBJECTS = $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o)
CXXFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CXXFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
CFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
LDFLAGS += -lm $(fpic) $(SDL_LIBS) -lSDL2_ttf -lSDL2_mixer
ifeq ($(SUPPORT_NET), 1)

View File

@ -39,8 +39,8 @@ SOURCES_C += $(wildcard $(NP2_PATH)/i386c/*.c) \
$(NP2_PATH)/sdl2/unix/main.c
OBJECTS = $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o)
CXXFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DCPUCORE_IA32 -DSUPPORT_PC9821 -DUSE_FPU -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DCPUCORE_IA32 -DSUPPORT_PC9821 -DUSE_FPU -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CXXFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DCPUCORE_IA32 -DSUPPORT_PC9821 -DUSE_FPU -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
CFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DCPUCORE_IA32 -DSUPPORT_PC9821 -DUSE_FPU -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
LDFLAGS += -lm $(fpic) -lpthread $(SDL_LIBS) -lSDL2_ttf -lSDL2_mixer
ifeq ($(SUPPORT_NET), 1)

View File

@ -38,8 +38,8 @@ SOURCES_C += $(wildcard $(NP2_PATH)/i386c/*.c) \
$(NP2_PATH)/sdl2/win32/main.c
OBJECTS = $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o)
CXXFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DCPUCORE_IA32 -DSUPPORT_PC9821 -DUSE_FPU -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DCPUCORE_IA32 -DSUPPORT_PC9821 -DUSE_FPU -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN
CXXFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DCPUCORE_IA32 -DSUPPORT_PC9821 -DUSE_FPU -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
CFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) -DUSE_SDLAUDIO -DUSE_SDLMIXER -DCPUCORE_IA32 -DSUPPORT_PC9821 -DUSE_FPU -DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DUSE_MAME -DSUPPORT_SOUND_SB16
LDFLAGS += -lm $(fpic) $(SDL_LIBS) -lSDL2_ttf -lSDL2_mixer
ifeq ($(SUPPORT_NET), 1)

View File

@ -547,6 +547,19 @@ static const INITBL iniitem[] = {
{"SCSIHDD1", INITYPE_STR, np2cfg.scsihdd[1], MAX_PATH},
{"SCSIHDD2", INITYPE_STR, np2cfg.scsihdd[2], MAX_PATH},
{"SCSIHDD3", INITYPE_STR, np2cfg.scsihdd[3], MAX_PATH},
#endif
#if defined(SUPPORT_IDEIO)
{"HDD3FILE", INIRO_STR, np2cfg.sasihdd[2], MAX_PATH},
{"HDD4FILE", INIRO_STR, np2cfg.sasihdd[3], MAX_PATH},
{"HDD1TYPE", INIRO_UINT8, &np2cfg.idetype[2], 0},
{"HDD2TYPE", INIRO_UINT8, &np2cfg.idetype[2], 0},
{"HDD3TYPE", INIRO_UINT8, &np2cfg.idetype[2], 0},
{"HDD4TYPE", INIRO_UINT8, &np2cfg.idetype[2], 0},
{"IDE_BIOS", INIRO_BOOL, &np2cfg.idebios, 0},
{"AIDEBIOS", INIRO_BOOL, &np2cfg.autoidebios, 0},
{"IDERWAIT", INITYPE_UINT32, &np2cfg.iderwait, 0},
{"IDEWWAIT", INITYPE_UINT32, &np2cfg.idewwait, 0},
{"IDEMWAIT", INITYPE_UINT32, &np2cfg.idemwait, 0},
#endif
{"SampleHz", INITYPE_UINT32, &np2cfg.samplingrate, 0},
{"Latencys", INITYPE_UINT16, &np2cfg.delayms, 0},
@ -569,7 +582,7 @@ static const INITBL iniitem[] = {
{"volume_A", INIMAX_UINT8, &np2cfg.vol_adpcm, 128},
{"volume_P", INIMAX_UINT8, &np2cfg.vol_pcm, 128},
{"volume_R", INIMAX_UINT8, &np2cfg.vol_rhythm, 128},
{"volume_C", INIMAX_UINT8, &np2cfg.vol_cdda, 128},
{"DAVOLUME", INIMAX_UINT8, &np2cfg.davolume, 128},
{"usefmgen", INITYPE_BOOL, &np2cfg.usefmgen, 0},

View File

@ -40,16 +40,20 @@
#endif
typedef int32_t SINT;
typedef int32_t INT;
typedef uint32_t UINT;
typedef int8_t SINT8;
typedef int8_t INT8;
typedef uint8_t UINT8;
typedef int16_t SINT16;
typedef int16_t INT16;
typedef uint16_t UINT16;
typedef int32_t SINT32;
typedef int32_t INT32;
typedef uint32_t UINT32;
typedef int64_t SINT64;
typedef int64_t INT64;
typedef uint64_t UINT64;
typedef int32_t* INTPTR;

View File

@ -880,7 +880,7 @@ void retro_set_environment(retro_environment_t cb)
{ "np2_skipline" , "Skipline Revisions; Full 255 lines|ON|OFF" },
{ "np2_realpal" , "Real Palettes; OFF|ON" },
{ "np2_lcd" , "LCD; OFF|ON" },
{ "np2_SNDboard" , "Sound Board (Restart); PC9801-86|PC9801-26K + 86|PC9801-86 + Chibi-oto|PC9801-118|Speak Board|Spark Board|Sound Orchestra|Sound Orchestra-V|AMD-98|Otomi-chanx2|Otomi-chanx2 + 86|None|PC9801-14|PC9801-26K" },
{ "np2_SNDboard" , "Sound Board (Restart); PC9801-86|PC9801-26K + 86|PC9801-86 + Chibi-oto|PC9801-118|PC9801-86 + Mate-X PCM(B460)|Mate-X PCM(B460)|Chibi-oto|Speak Board|Spark Board|Sound Orchestra|Sound Orchestra-V|Sound Blaster 16|AMD-98|Otomi-chanx2|Otomi-chanx2 + 86|None|PC9801-14|PC9801-26K" },
{ "np2_jast_snd" , "JastSound; OFF|ON" },
{ "np2_usefmgen" , "Sound Generator; fmgen|Default" },
{ "np2_volume_F" , "Volume FM; 64|68|72|76|80|84|88|92|96|100|104|108|112|116|120|124|128|0|4|8|12|16|20|24|28|32|36|40|44|48|52|56|60" },
@ -888,6 +888,7 @@ void retro_set_environment(retro_environment_t cb)
{ "np2_volume_A" , "Volume ADPCM; 64|68|72|76|80|84|88|92|96|100|104|108|112|116|120|124|128|0|4|8|12|16|20|24|28|32|36|40|44|48|52|56|60" },
{ "np2_volume_P" , "Volume PCM; 64|68|72|76|80|84|88|92|96|100|104|108|112|116|120|124|128|0|4|8|12|16|20|24|28|32|36|40|44|48|52|56|60" },
{ "np2_volume_R" , "Volume RHYTHM; 64|68|72|76|80|84|88|92|96|100|104|108|112|116|120|124|128|0|4|8|12|16|20|24|28|32|36|40|44|48|52|56|60" },
{ "np2_volume_C" , "Volume CD-DA; 128|136|144|154|160|168|196|184|192|200|208|216|224|232|240|248|255|0|8|16|24|32|40|48|56|64|72|80|88|96|104|112|120" },
{ "np2_Seek_Snd" , "Floppy Seek Sound; OFF|ON" },
{ "np2_Seek_Vol" , "Volume Floppy Seek; 80|84|88|92|96|100|104|108|112|116|120|124|128|0|4|8|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76" },
{ "np2_BEEP_vol" , "Volume Beep; 3|0|1|2" },
@ -1008,6 +1009,10 @@ static void update_variables(void)
np2cfg.SOUND_SW = 0x14;
else if (strcmp(var.value, "PC9801-118") == 0)
np2cfg.SOUND_SW = 0x08;
else if (strcmp(var.value, "PC9801-86 + Mate-X PCM(B460)") == 0)
np2cfg.SOUND_SW = 0x64;
else if (strcmp(var.value, "Mate-X PCM(B460)") == 0)
np2cfg.SOUND_SW = 0x60;
else if (strcmp(var.value, "Speak Board") == 0)
np2cfg.SOUND_SW = 0x20;
else if (strcmp(var.value, "Spark Board") == 0)
@ -1016,6 +1021,8 @@ static void update_variables(void)
np2cfg.SOUND_SW = 0x32;
else if (strcmp(var.value, "Sound Orchestra-V") == 0)
np2cfg.SOUND_SW = 0x82;
else if (strcmp(var.value, "Sound Blaster 16") == 0)
np2cfg.SOUND_SW = 0x41;
else if (strcmp(var.value, "AMD-98") == 0)
np2cfg.SOUND_SW = 0x80;
else if (strcmp(var.value, "Otomi-chanx2") == 0)
@ -1114,6 +1121,15 @@ static void update_variables(void)
#endif /* defined(SUPPORT_FMGEN) */
}
var.key = "np2_volume_C";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
np2cfg.davolume = atoi(var.value);
rhythm_setvol(np2cfg.davolume);
}
var.key = "np2_Seek_Snd";
var.value = NULL;

View File

@ -388,6 +388,16 @@ static void sys_cmd(MENUID id) {
update |= SYS_UPDATECFG;
break;
case MID_PC9801_86_MX:
np2cfg.SOUND_SW = 0x64;
update |= SYS_UPDATECFG;
break;
case MID_PC9801_MX:
np2cfg.SOUND_SW = 0x60;
update |= SYS_UPDATECFG;
break;
case MID_SPEAKBOARD:
np2cfg.SOUND_SW = 0x20;
update |= SYS_UPDATECFG;
@ -408,6 +418,11 @@ static void sys_cmd(MENUID id) {
update |= SYS_UPDATECFG;
break;
case MID_SB16:
np2cfg.SOUND_SW = 0x41;
update |= SYS_UPDATECFG;
break;
case MID_AMD98:
np2cfg.SOUND_SW = 0x80;
update |= SYS_UPDATECFG;

View File

@ -93,10 +93,13 @@ enum {
MID_PC9801_26_86,
MID_PC9801_86_CB,
MID_PC9801_118,
MID_PC9801_86_MX,
MID_PC9801_MX,
MID_SPEAKBOARD,
MID_SPARKBOARD,
MID_SOUNDORCHESTRA,
MID_SOUNDORCHESTRAV,
MID_SB16,
MID_AMD98,
#if defined(SUPPORT_PX)
MID_PX1,

View File

@ -87,10 +87,13 @@ static const char str_pc980186[] = "PC-9801-86";
static const char str_pc980126k86[] = "PC-9801-26K + 86";
static const char str_pc980186cb[] = "PC-9801-86 + Chibi-oto";
static const char str_pc9801118[] = "PC-9801-118";
static const char str_pc980186mx[] = "PC-9801-86 + Mate-X PCM(B460)";
static const char str_pc9801mx[] = "Mate-X PCM(B460)";
static const char str_spreakboard[] = "Speak board";
static const char str_sparkboard[] = "Spark board";
static const char str_sndorchestra[] = "Sound Orchestra";
static const char str_sndorchestrav[] = "Sound Orchestra-V";
static const char str_sb16[] = "Sound Blaster 16";
static const char str_amd98[] = "AMD-98";
#if defined(SUPPORT_PX)
static const char str_px1[] = "Otomi-chanx2";
@ -325,10 +328,13 @@ static const MSYSITEM s_snd[] = {
{str_pc980126k86, NULL, MID_PC9801_26_86, 0},
{str_pc980186cb, NULL, MID_PC9801_86_CB, 0},
{str_pc9801118, NULL, MID_PC9801_118, 0},
{str_pc980186mx, NULL, MID_PC9801_86_MX, 0},
{str_pc9801mx, NULL, MID_PC9801_MX, 0},
{str_spreakboard, NULL, MID_SPEAKBOARD, 0},
{str_sparkboard, NULL, MID_SPARKBOARD, 0},
{str_sndorchestra, NULL, MID_SOUNDORCHESTRA, 0},
{str_sndorchestrav, NULL, MID_SOUNDORCHESTRAV,0},
{str_sndorchestrav, NULL, MID_SOUNDORCHESTRAV, 0},
{str_sb16, NULL, MID_SB16, 0},
{str_amd98, NULL, MID_AMD98, 0},
#if defined(SUPPORT_PX)
{str_px1, NULL, MID_PX1, 0},

View File

@ -40,18 +40,23 @@ typedef unsigned int UINT;
typedef unsigned long ULONG;
typedef signed char SINT8;
typedef signed char INT8;
typedef unsigned char UINT8;
typedef signed short SINT16;
typedef signed short INT16;
typedef unsigned short UINT16;
typedef signed int SINT32;
typedef signed int INT32;
typedef unsigned int UINT32;
#if __WORDSIZE == 64
typedef signed long int SINT64;
typedef signed long int INT64;
typedef unsigned long int UINT64;
#else
__extension__
typedef signed long long int SINT64;
typedef signed long int SINT64;
__extension__
typedef signed long int INT64;
__extension__
typedef unsigned long long int UINT64;
#endif

View File

@ -29,28 +29,36 @@
#ifndef __GNUC__
typedef signed int SINT;
typedef signed char SINT8;
typedef signed char INT8;
typedef unsigned char UINT8;
typedef signed short SINT16;
typedef signed short INT16;
typedef unsigned short UINT16;
typedef signed int SINT32;
typedef signed int INT32;
typedef unsigned int UINT32;
typedef signed long long SINT64;
typedef unsigned long long SINT64;
typedef signed long long INT64;
typedef unsigned long long UINT64;
typedef signed int SINT;
typedef signed int INT;
typedef unsigned int UINT;
#else
#include <stdlib.h>
typedef signed char SINT8;
typedef signed char INT8;
typedef unsigned char UINT8;
typedef signed short SINT16;
typedef signed short INT16;
typedef unsigned short UINT16;
typedef signed int SINT32;
typedef signed int INT32;
typedef unsigned int UINT32;
typedef signed long long SINT64;
typedef signed long long INT64;
typedef unsigned long long UINT64;
typedef signed int SINT;
typedef signed int INT;
typedef unsigned int UINT;
#endif

View File

@ -1,96 +1,140 @@
/**
sudo make - * @file cs4231.h
* @brief Interface of the CS4231
*/
#pragma once
#include "sound.h"
#include "io/dmac.h"
enum {
//
CS4231_BUFFERS = (1 << 9),
CS4231_BUFMASK = (CS4231_BUFFERS - 1)
};
typedef struct {
UINT8 adc_l; // 0
UINT8 adc_r; // 1
UINT8 aux1_l; // 2
UINT8 aux1_r; // 3
UINT8 aux2_l; // 4
UINT8 aux2_r; // 5
UINT8 dac_l; // 6
UINT8 dac_r; // 7
UINT8 datafmt; // 8
UINT8 iface; // 9
UINT8 pinctrl; // a
UINT8 errorstatus; //b
UINT8 mode_id; //c
UINT8 loopctrl; //d
UINT8 playcount[2]; //e-f
UINT8 featurefunc[2]; //10-11
UINT8 line_l; //12
UINT8 line_r; //13
UINT8 timer[2]; //14-15
UINT8 reserved1; //16
UINT8 reserved2; //17
UINT8 featurestatus; //18
UINT8 chipid; //19
UINT8 monoinput; //1a
UINT8 reserved3; //1b
UINT8 cap_datafmt; //1c
UINT8 reserved4; //1d
UINT8 cap_basecount[2]; //1e-1f
} CS4231REG;
typedef struct {
UINT bufsize;
UINT bufdatas;
UINT bufpos;
UINT32 pos12;
UINT32 step12;
UINT8 enable;
UINT8 portctrl;
UINT8 dmairq;
UINT8 dmach;
UINT32 port[16];
UINT8 adrs;
UINT8 index;
UINT8 intflag;
UINT8 outenable;
UINT8 extfunc;
UINT8 extindex;
CS4231REG reg;
UINT8 buffer[CS4231_BUFFERS];
} _CS4231, *CS4231;
typedef struct {
UINT rate;
} CS4231CFG;
#ifdef __cplusplus
extern "C"
{
#endif
void cs4231_dma(NEVENTITEM item);
REG8 DMACCALL cs4231dmafunc(REG8 func);
void cs4231_datasend(REG8 dat);
void cs4231_initialize(UINT rate);
void cs4231_setvol(UINT vol);
void cs4231_reset(void);
void cs4231_update(void);
void cs4231_control(UINT index, REG8 dat);
void SOUNDCALL cs4231_getpcm(CS4231 cs, SINT32 *pcm, UINT count);
#ifdef __cplusplus
}
#endif
/**
sudo make - * @file cs4231.h
* @brief Interface of the CS4231
*/
#pragma once
#include "sound.h"
#include "io/dmac.h"
enum {
CS4231_BUFFERS = (1 << 9),
CS4231_BUFMASK = (CS4231_BUFFERS - 1)
};
typedef struct {
UINT8 adc_l; // 0
UINT8 adc_r; // 1
UINT8 aux1_l; // 2
UINT8 aux1_r; // 3
UINT8 aux2_l; // 4
UINT8 aux2_r; // 5
UINT8 dac_l; // 6
UINT8 dac_r; // 7
UINT8 datafmt; // 8
UINT8 iface; // 9
UINT8 pinctrl; // a
UINT8 errorstatus; //b
UINT8 mode_id; //c
UINT8 loopctrl; //d
UINT8 playcount[2]; //e-f
UINT8 featurefunc[2]; //10-11
UINT8 line_l; //12
UINT8 line_r; //13
UINT8 timer[2]; //14-15
UINT8 reserved1; //16
UINT8 reserved2; //17
UINT8 featurestatus; //18
UINT8 chipid; //19
UINT8 monoinput; //1a
UINT8 reserved3; //1b
UINT8 cap_datafmt; //1c
UINT8 reserved4; //1d
UINT8 cap_basecount[2]; //1e-1f
} CS4231REG;
typedef struct {
UINT bufsize; // サウンド再生用の循環バッファサイズ。データのread/writeは4byte単位16bitステレオの1サンプル単位で行うこと
UINT bufdatas; // = (bufwpos-bufpos)&CS4231_BUFMASK
UINT bufpos; // バッファの読み取り位置。bufwposと一致してもよいが追い越してはいけない
UINT bufwpos; // バッファの書き込み位置。周回遅れのbufposに追いついてはいけない一致も不可
UINT32 pos12;
UINT32 step12;
UINT8 enable;
UINT8 portctrl;
UINT8 dmairq;
UINT8 dmach;
UINT16 port[16];
UINT8 adrs;
UINT8 index;
UINT8 intflag;
UINT8 outenable;
UINT8 extfunc;
UINT8 extindex;
UINT16 timer;
SINT32 timercounter;
CS4231REG reg;
UINT8 buffer[CS4231_BUFFERS];
UINT8 devvolume[0x100];
} _CS4231, *CS4231;
typedef struct {
UINT rate;
} CS4231CFG;
#ifdef __cplusplus
extern "C"
{
#endif
//Index Address Register 0xf44
#define TRD (1 << 5) //cs4231.index bit5 Transfer Request Disable
#define MCE (1 << 6) //cs4231.index bit6 Mode Change Enable
//Status Register 0xf46
#define INt (1 << 0) //cs4231.intflag bit0 Interrupt Status
#define PRDY (1 << 1) //cs4231.intflag bit1 Playback Data Ready(PIO data)
#define PLR (1 << 2) //cs4231.intflag bit2 Playback Left/Right Sample
#define PULR (1 << 3) //cs4231.intflag bit3 Playback Upper/Lower Byte
#define SER (1 << 4) //cs4231.intflag bit4 Sample Error
#define CRDY (1 << 5) //cs4231.intflag bit5 Capture Data Ready
#define CLR (1 << 6) //cs4231.intflag bit6 Capture Left/Right Sample
#define CUL (1 << 7) //cs4231.intglag bit7 Capture Upper/Lower Byte
//cs4231.reg.iface(9)
#define PEN (1 << 0) //bit0 Playback Enable set and reset without MCE
#define CEN (1 << 1) //bit1 Capture Enable
#define SDC (1 << 2) //bit2 Single DMA Channel 0 Dual 1 Single 逆と思ってたので修正すべし
#define CAL0 (1 << 3) //bit3 Calibration 0 No Calibration 1 Converter calibration
#define CAL1 (1 << 4) //bit4 2 DAC calibration 3 Full Calibration
#define PPIO (1 << 6) //bit6 Playback PIO Enable 0 DMA 1 PIO
#define CPIO (1 << 7) //bit7 Capture PIO Enable 0 DMA 1 PIO
//cs4231.reg.errorstatus(11)b
#define ACI (1 << 5) //bit5 Auto-calibrate In-Progress
//cs4231.reg.pinctrl(10)a
#define IEN (1 << 1) //bit1 Interrupt Enable reflect cs4231.intflag bit0
#define DEN (1 << 3) //bit3 Dither Enable only active in 8-bit unsigned mode
//cs4231.reg.modeid(12)c
#define MODE2 (1 << 6) //bit6
//cs4231.reg.featurestatus(24)0x18
#define PI (1 << 4) //bit4 Playback Interrupt pending from Playback DMA count registers
#define CI (1 << 5) //bit5 Capture Interrupt pending from record DMA count registers when SDC=1 non-functional
#define TI (1 << 6) //bit6 Timer Interrupt pending from timer count registers
// PI,CI,TI bits are reset by writing a "0" to the particular interrupt bit or by writing any value to the Status register
void cs4231_dma(NEVENTITEM item);
REG8 DMACCALL cs4231dmafunc(REG8 func);
void cs4231_datasend(REG8 dat);
void cs4231_initialize(UINT rate);
void cs4231_setvol(UINT vol);
void cs4231_reset(void);
void cs4231_update(void);
void cs4231_control(UINT index, REG8 dat);
void SOUNDCALL cs4231_getpcm(CS4231 cs, SINT32 *pcm, UINT count);
#ifdef __cplusplus
}
#endif

View File

@ -1,237 +1,410 @@
/**
* @file cs4231c.c
* @brief Implementation of the CS4231
*/
#include "compiler.h"
#include "cs4231.h"
#include "iocore.h"
#include "fmboard.h"
CS4231CFG cs4231cfg;
enum {
CS4231REG_LINPUT = 0x00,
CS4231REG_RINPUT = 0x01,
CS4231REG_AUX1L = 0x02,
CS4231REG_AUX1R = 0x03,
CS4231REG_AUX2L = 0x04,
CS4231REG_AUX2R = 0x05,
CS4231REG_LOUTPUT = 0x06,
CS4231REG_ROUTPUT = 0x07,
CS4231REG_PLAYFMT = 0x08,
CS4231REG_INTERFACE = 0x09,
CS4231REG_PINCTRL = 0x0a,
CS4231REG_TESTINIT = 0x0b,
CS4231REG_MISCINFO = 0x0c,
CS4231REG_LOOPBACK = 0x0d,
CS4231REG_PLAYCNTM = 0x0e,
CS4231REG_PLAYCNTL = 0x0f,
CS4231REG_FEATURE1 = 0x10,
CS4231REG_FEATURE2 = 0x11,
CS4231REG_LLINEIN = 0x12,
CS4231REG_RLINEIN = 0x13,
CS4231REG_TIMERL = 0x14,
CS4231REG_TIMERH = 0x15,
CS4231REG_RESERVED1= 0x16,
CS4231REG_RESERVED2= 0x17,
CS4231REG_IRQSTAT = 0x18,
CS4231REG_VERSION = 0x19,
CS4231REG_MONOCTRL = 0x1a,
CS4231REG_RECFMT = 0x1c,
CS4231REG_PLAYFREQ = 0x1d,
CS4231REG_RECCNTM = 0x1e,
CS4231REG_RECCNTL = 0x1f
};
static const UINT32 cs4231xtal64[2] = {24576000/64, 16934400/64};
static const UINT8 cs4231cnt64[8] = {
3072/64, // 8000/ 5510
1536/64, // 16000/11025
896/64, // 27420/18900
768/64, // 32000/22050
448/64, // 54840/37800
384/64, // 64000/44100
512/64, // 48000/33075
2560/64}; // 9600/ 6620
// 640:441
void cs4231_initialize(UINT rate) {
cs4231cfg.rate = rate;
}
void cs4231_setvol(UINT vol) {
(void)vol;
}
void cs4231_dma(NEVENTITEM item) {
DMACH dmach;
UINT rem;
UINT pos;
UINT size;
UINT r;
SINT32 cnt;
if (item->flag & NEVENT_SETEVENT) {
if (cs4231.dmach != 0xff) {
sound_sync();
dmach = dmac.dmach + cs4231.dmach;
if (cs4231.bufsize > cs4231.bufdatas) {
rem = cs4231.bufsize - cs4231.bufdatas;
pos = (cs4231.bufpos + cs4231.bufdatas) & CS4231_BUFMASK;
size = min(rem, CS4231_BUFFERS - pos);
r = dmac_getdatas(dmach, cs4231.buffer + pos, size);
rem -= r;
cs4231.bufdatas += r;
if (r != size) {
r = dmac_getdatas(dmach, cs4231.buffer, rem);
cs4231.bufdatas += r;
}
}
if ((dmach->leng.w) && (cs4231cfg.rate)) {
cnt = pccore.realclock * 16 / cs4231cfg.rate;
nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_RELATIVE);
}
}
}
(void)item;
}
void cs4231_datasend(REG8 dat) {
UINT pos;
if (cs4231.reg.iface & 0x40) { // PIO play enable
if (cs4231.bufsize <= cs4231.bufdatas) {
sound_sync();
}
if (cs4231.bufsize > cs4231.bufdatas) {
pos = (cs4231.bufpos + cs4231.bufdatas) & CS4231_BUFMASK;
cs4231.buffer[pos] = dat;
cs4231.bufdatas++;
}
}
}
REG8 DMACCALL cs4231dmafunc(REG8 func) {
SINT32 cnt;
TRACEOUT(("dmafunc %x",func));
switch(func) {
case DMAEXT_START:
if (cs4231cfg.rate) {
cnt = pccore.realclock * 16 / cs4231cfg.rate;
nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_ABSOLUTE);
}
break;
case DMAEXT_END:
if ((cs4231.reg.pinctrl & 2) && (cs4231.dmairq != 0xff)) {
cs4231.intflag |=1;
cs4231.reg.featurestatus |= 0x10;
pic_setirq(cs4231.dmairq);
}
break;
case DMAEXT_BREAK:
nevent_reset(NEVENT_CS4231);
break;
}
return(0);
}
void cs4231_reset(void) {
ZeroMemory(&cs4231, sizeof(cs4231));
cs4231.bufsize = CS4231_BUFFERS;
// cs4231.proc = cs4231_nodecode;
cs4231.dmach = 0xff;
cs4231.dmairq = 0xff;
FillMemory(cs4231.port, sizeof(cs4231.port), 0xff);
}
void cs4231_update(void) {
}
static void setdataalign(void) {
UINT step;
step = (0 - cs4231.bufpos) & 3;
if (step) {
cs4231.bufpos += step;
cs4231.bufdatas -= min(step, cs4231.bufdatas);
}
cs4231.bufdatas &= ~3;
}
void cs4231_control(UINT idx, REG8 dat) {
UINT8 modify;
DMACH dmach;
cs4231.index |= 0x40;
modify = ((UINT8 *)&cs4231.reg)[idx] ^ dat;
((UINT8 *)&cs4231.reg)[idx] = dat;
switch(idx) {
case CS4231REG_MISCINFO:
if (cs4231.reg.mode_id & 0x40) cs4231.index &= 0x0f;
else cs4231.index &= 0x1f;
break;
}
switch(idx) {
case CS4231REG_PLAYFMT:
TRACEOUT(("PLAYFMT= %x",dat));
if (modify & 0xf0) {
setdataalign();
}
if (modify & 0x0f) {
if (cs4231cfg.rate) {
UINT32 r;
r = cs4231xtal64[dat & 1] / cs4231cnt64[(dat >> 1) & 7];
TRACEOUT(("samprate = %d", r));
r <<= 12;
r /= cs4231cfg.rate;
cs4231.step12 = r;
TRACEOUT(("step12 = %d", r));
}
else {
cs4231.step12 = 0;
}
}
break;
case CS4231REG_INTERFACE:
if (modify & 5) {
if (cs4231.dmach != 0xff) {
dmach = dmac.dmach + cs4231.dmach;
if ((dat & 0x1) == 0x1) {
dmach->ready = 1;
}
else {
dmach->ready = 0;
}
dmac_check();
}
if (!(dat & 1)) { // stop!
cs4231.pos12 = 0;
}
}
break;
case CS4231REG_IRQSTAT:
if (modify & 0x10) {
pic_resetirq(cs4231.dmairq);
cs4231.intflag &= 0xfe;
}
break;
}
}
/**
* @file cs4231c.c
* @brief Implementation of the CS4231
*/
#include "compiler.h"
#include "cs4231.h"
#include "iocore.h"
#include "fmboard.h"
#include "dmac.h"
#include "cpucore.h"
#ifndef CPU_STAT_PM
#define CPU_STAT_PM 0
#endif
CS4231CFG cs4231cfg;
static SINT32 cs4231_totalsample = 0;
enum {
CS4231REG_LINPUT = 0x00,
CS4231REG_RINPUT = 0x01,
CS4231REG_AUX1L = 0x02,
CS4231REG_AUX1R = 0x03,
CS4231REG_AUX2L = 0x04,
CS4231REG_AUX2R = 0x05,
CS4231REG_LOUTPUT = 0x06,
CS4231REG_ROUTPUT = 0x07,
CS4231REG_PLAYFMT = 0x08,
CS4231REG_INTERFACE = 0x09,
CS4231REG_PINCTRL = 0x0a,
CS4231REG_TESTINIT = 0x0b,
CS4231REG_MISCINFO = 0x0c,
CS4231REG_LOOPBACK = 0x0d,
CS4231REG_PLAYCNTM = 0x0e,
CS4231REG_PLAYCNTL = 0x0f,
CS4231REG_FEATURE1 = 0x10,
CS4231REG_FEATURE2 = 0x11,
CS4231REG_LLINEIN = 0x12,
CS4231REG_RLINEIN = 0x13,
CS4231REG_TIMERL = 0x14,
CS4231REG_TIMERH = 0x15,
CS4231REG_RESERVED1= 0x16,
CS4231REG_RESERVED2= 0x17,
CS4231REG_IRQSTAT = 0x18,
CS4231REG_VERSION = 0x19,
CS4231REG_MONOCTRL = 0x1a,
CS4231REG_RECFMT = 0x1c,
CS4231REG_PLAYFREQ = 0x1d,
CS4231REG_RECCNTM = 0x1e,
CS4231REG_RECCNTL = 0x1f
};
UINT dmac_getdata_(DMACH dmach, UINT8 *buf, UINT offset, UINT size);
static const UINT32 cs4231xtal64[2] = {24576000/64, 16934400/64};
static const UINT8 cs4231cnt64[8] = {
3072/64, // 8000/ 5510
1536/64, // 16000/11025
896/64, // 27420/18900
768/64, // 32000/22050
448/64, // 54840/37800
384/64, // 64000/44100
512/64, // 48000/33075
2560/64}; // 9600/ 6620
// 640:441
void cs4231_initialize(UINT rate) {
cs4231cfg.rate = rate;
}
void cs4231_setvol(UINT vol) {
(void)vol;
}
// CS4231 DMA処理
void cs4231_dma(NEVENTITEM item) {
DMACH dmach;
UINT rem;
UINT pos;
UINT size;
UINT r;
SINT32 cnt;
if (item->flag & NEVENT_SETEVENT) {
if (cs4231.dmach != 0xff) {
dmach = dmac.dmach + cs4231.dmach;
// サウンド再生用バッファに送る?(cs4231g.c)
sound_sync();
// バッファに空きがあればデータを読み出す
if (cs4231.bufsize-4 > cs4231.bufdatas) {
rem = min(cs4231.bufsize - 4 - cs4231.bufdatas, 512); //読み取り単位は16bitステレオの1サンプル分(4byte)にしておかないと雑音化する
pos = cs4231.bufwpos & CS4231_BUFMASK; // バッファ書き込み位置
size = min(rem, dmach->startcount); // バッファ書き込みサイズ
r = dmac_getdata_(dmach, cs4231.buffer, pos, size); // DMA読み取り実行
cs4231.bufwpos = (cs4231.bufwpos + r) & CS4231_BUFMASK; // バッファ書き込み位置を更新
cs4231.bufdatas += r; // バッファ内の有効なデータ数を更新 = (bufwpos-bufpos)&CS4231_BUFMASK
}
// まだデータがありそうならNEVENTをセット
if ((dmach->leng.w) && (cs4231cfg.rate)) {
cnt = pccore.realclock * 4 / cs4231cfg.rate;
nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_RELATIVE);
}
}
}
(void)item;
}
// PIO再生用
void cs4231_datasend(REG8 dat) {
UINT pos;
if (cs4231.reg.iface & PPIO) { // PIO play enable
if (cs4231.bufsize <= cs4231.bufdatas) {
sound_sync();
}
if (cs4231.bufsize > cs4231.bufdatas) {
pos = (cs4231.bufwpos) & CS4231_BUFMASK;
cs4231.buffer[pos] = dat;
cs4231.bufdatas++;
cs4231.bufwpos = (cs4231.bufwpos + 1) & CS4231_BUFMASK;
}
}
}
// DMA再生開始・終了・中断時に呼ばれるつもり
REG8 DMACCALL cs4231dmafunc(REG8 func) {
SINT32 cnt;
switch(func) {
case DMAEXT_START:
if (cs4231cfg.rate) {
//DMACH dmach;
//dmach = dmac.dmach + cs4231.dmach;
//dmach->adrs.d = dmach->startaddr;
//cs4231.bufpos = cs4231.bufwpos;
//cs4231.bufdatas = 0;
cs4231_totalsample = 0;
cnt = pccore.realclock * 4 / cs4231cfg.rate;
nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_ABSOLUTE);
}
break;
case DMAEXT_END:
// ここでの割り込みは要らない?
//if ((cs4231.reg.pinctrl & IEN) && (cs4231.dmairq != 0xff)) {
// cs4231.intflag |= INt;
// cs4231.reg.featurestatus |= PI;
// pic_setirq(cs4231.dmairq);
//}
break;
case DMAEXT_BREAK:
//{
// DMACH dmach;
// dmach = dmac.dmach + cs4231.dmach;
// dmach->adrs.d = dmach->startaddr;
//}
nevent_reset(NEVENT_CS4231);
break;
}
return(0);
}
void cs4231_reset(void) {
ZeroMemory(&cs4231, sizeof(cs4231));
cs4231.bufsize = CS4231_BUFFERS;
// cs4231.proc = cs4231_nodecode;
cs4231.dmach = 0xff;
cs4231.dmairq = 0xff;
//cs4231.timer = 200; // XXX: 何も入れてくれないのでそれっぽいのを入れる・・・(10usec単位)
cs4231_totalsample = 0;
FillMemory(cs4231.port, sizeof(cs4231.port), 0xff);
}
void cs4231_update(void) {
}
// バッファ位置のズレ修正用(雑音化防止)
static void setdataalign(void) {
UINT step;
// バッファ位置がズレていたら修正4byte単位に
step = (0 - cs4231.bufpos) & 3;
if (step) {
cs4231.bufpos += step;
cs4231.bufdatas -= min(step, cs4231.bufdatas);
}
cs4231.bufdatas &= ~3;
step = (0 - cs4231.bufwpos) & 3;
if (step) {
cs4231.bufwpos += step;
}
}
// CS4231 Indexed Data registerの処理
void cs4231_control(UINT idx, REG8 dat) {
UINT8 modify;
DMACH dmach;
switch(idx){
case 0xd:
break;
case 0xc:
dat &= 0x40;
dat |= 0x8a;
break;
case 0xb://ErrorStatus
case 0x19://Version ID
return;
default:
break;
}
dmach = dmac.dmach + cs4231.dmach;
modify = ((UINT8 *)&cs4231.reg)[idx] ^ dat;
((UINT8 *)&cs4231.reg)[idx] = dat;
switch(idx) {
case CS4231REG_PLAYFMT:
// 再生フォーマット設定とか Fs and Playback Data Format (I8)
if (modify & 0xf0) {
//dmach->adrs.d = dmach->startaddr;
cs4231.bufpos = cs4231.bufwpos;
cs4231.bufdatas = 0;
setdataalign();
}
if (cs4231cfg.rate) {
UINT32 r;
r = cs4231xtal64[dat & 1] / cs4231cnt64[(dat >> 1) & 7];
TRACEOUT(("samprate = %d", r));
r <<= 12;
r /= cs4231cfg.rate;
cs4231.step12 = r;
TRACEOUT(("step12 = %d", r));
}
else {
cs4231.step12 = 0;
}
break;
case CS4231REG_INTERFACE:
// 再生録音の有効無効とかDMAとかの設定 Interface Configuration (I9)
if (modify & PEN ) {
if (cs4231.dmach != 0xff) {
dmach = dmac.dmach + cs4231.dmach;
if ((dat & (PEN)) == (PEN)){
dmach->ready = 1;
}
else {
dmach->ready = 0;
}
dmac_check();
}
if (!(dat & PEN)) { // stop!
cs4231.pos12 = 0;
}
}
break;
case CS4231REG_IRQSTAT:
// バッファオーバーラン・アンダーランや割り込みを検出するためのレジスタ Alternate Feature Status (I24)
if (modify & PI) {
/* XXX: TI CI */
pic_resetirq (cs4231.dmairq);
cs4231.intflag &= ~INt;
}
break;
case CS4231REG_PLAYCNTM:
// Playback Upper Base (I14)
// cs4231.reg.playcount[0]
break;
case CS4231REG_PLAYCNTL:
// Playback Lower Base (I15)
// cs4231.reg.playcount[1]
break;
//case CS4231REG_TIMERL:
// // CS4231 割り込みタイマー設定(下位バイト)
// cs4231.reg.timer[0]
// break;
//case CS4231REG_TIMERH:
// // CS4231 割り込みタイマー設定(上位バイト)
// cs4231.reg.timer[1]
// break;
}
}
// 各フォーマットの割り込み間隔テーブルたぶん1サンプルあたりのバイト数
//static const SINT32 cs4231_irqsamples[16] = {
// 1 , // 0: 8bit PCM
// 1*2,
// 1 , // 1: u-Law
// 1 ,
// 1*2, // 2: 16bit PCM(little endian)?
// 1*4,
// 1 , // 3: A-Law
// 1 ,
// 1 , // 4:
// 1 ,
// 1 , // 5: ADPCM
// 1 ,
// 1*2, // 6: 16bit PCM
// 1*4,
// 1 , // 7: ADPCM
// 1 };
static const SINT32 cs4231_playcountshift[16] = {
1 , // 0: 8bit PCM
1*2,
1 , // 1: u-Law
1 ,
1*2, // 2: 16bit PCM(little endian)?
1*4,
1 , // 3: A-Law
1 ,
1 , // 4:
1 ,
1 , // 5: ADPCM
1 ,
1*2, // 6: 16bit PCM
1*4,
1 , // 7: ADPCM
1 };
// CS4231 DMAデータ読み取り
UINT dmac_getdata_(DMACH dmach, UINT8 *buf, UINT offset, UINT size) {
UINT leng; // 読み取り数
UINT lengsum; // 合計読み取り数
UINT32 addr;
UINT i;
SINT32 sampleirq = 0; // 割り込みまでに必要なデータ転送数(byte)
lengsum = 0;
while(size > 0) {
leng = min(dmach->leng.w, size);
if (leng) {
addr = dmach->adrs.d; // 現在のメモリ読み取り位置
if (!(dmach->mode & 0x20)) { // dir +
// +方向にDMA転送
for (i=0; i<leng ; i++) {
buf[offset] = MEMP_READ8(addr);
addr++;
if(addr > dmach->lastaddr){
addr = dmach->startaddr;
}
offset = (offset+1) & CS4231_BUFMASK;
}
dmach->adrs.d = addr;
}
else { // dir -
// -方向にDMA転送
for (i=0; i<leng; i++) {
buf[offset] = MEMP_READ8(addr);
addr--;
if(addr < dmach->startaddr){
addr = dmach->lastaddr;
}
offset = (offset-1) & CS4231_BUFMASK;
}
dmach->adrs.d = addr;
}
dmach->leng.w -= leng;
if (dmach->leng.w <= 0) {
dmach->leng.w = dmach->startcount; // 戻す
dmach->proc.extproc(DMAEXT_END);
}
// 読み取り数と残り数更新
lengsum += leng;
size -= leng;
// Playback Countだけデータを転送したら割り込みを発生させる
if ((cs4231.reg.pinctrl & IEN) && (cs4231.dmairq != 0xff)) {
int playcount = (cs4231.reg.playcount[1]|(cs4231.reg.playcount[0] << 8)) * cs4231_playcountshift[cs4231.reg.datafmt >> 4];
// 読み取り数カウント
cs4231_totalsample += leng;
if(cs4231_totalsample >= playcount){
cs4231_totalsample -= playcount;
cs4231.intflag |= INt;
cs4231.reg.featurestatus |= PI;
pic_setirq(cs4231.dmairq);
}
}
//// XXX: 一定バイト数読む毎に割り込みする(あまり根拠のない実装・・・)
//sampleirq = cs4231_irqsamples[cs4231.reg.datafmt >> 4] * ((cs4231.step12*cs4231cfg.rate)>>12) / 32; // * 1100/1000; //XXX: 割り込み間隔実験式
//if(cs4231_totalsample >= sampleirq){
// if ((cs4231.reg.pinctrl & 2) && (cs4231.dmairq != 0xff)) {
// //cs4231.intflag |= INt;
// //cs4231.reg.featurestatus |= PI;
// //pic_setirq(cs4231.dmairq);
// }
// cs4231_totalsample -= sampleirq;
//}
}else{
break;
}
}
return(lengsum);
}

View File

@ -5,15 +5,23 @@
#include "compiler.h"
#include "cs4231.h"
#include "iocore.h"
#include "sound/fmboard.h"
#include <math.h>
extern CS4231CFG cs4231cfg;
static SINT32 cs4231_DACvolume_L = 1024;
static SINT32 cs4231_DACvolume_R = 1024;
static UINT16 cs4231_DACvolumereg_L = 0xff;
static UINT16 cs4231_DACvolumereg_R = 0xff;
static void SOUNDCALL pcm8m(CS4231 cs, SINT32 *pcm, UINT count) {
UINT leng;
UINT32 leng;
UINT32 pos12;
SINT32 fract;
UINT samppos;
UINT32 samppos;
const UINT8 *ptr1;
const UINT8 *ptr2;
SINT32 samp1;
@ -37,24 +45,24 @@ const UINT8 *ptr2;
samp1 = (ptr1[0] - 0x80) << 8;
samp2 = (ptr2[0] - 0x80) << 8;
samp1 += ((samp2 - samp1) * fract) >> 12;
pcm[0] += samp1;
pcm[1] += samp1;
pcm[0] += (samp1 * cs4231_DACvolume_L * np2cfg.vol_pcm) >> 15;
pcm[1] += (samp1 * cs4231_DACvolume_R * np2cfg.vol_pcm) >> 15;
pcm += 2;
pos12 += cs->step12;
} while(--count);
leng = min(leng, (pos12 >> 12));
cs->bufdatas -= (leng << 0);
cs->bufpos += (leng << 0);
cs->bufpos = (cs->bufpos + (leng << 0)) & CS4231_BUFMASK;
cs->pos12 = pos12 & ((1 << 12) - 1);
}
static void SOUNDCALL pcm8s(CS4231 cs, SINT32 *pcm, UINT count) {
UINT leng;
UINT32 leng;
UINT32 pos12;
SINT32 fract;
UINT samppos;
UINT32 samppos;
const UINT8 *ptr1;
const UINT8 *ptr2;
SINT32 samp1;
@ -78,27 +86,27 @@ const UINT8 *ptr2;
samp1 = (ptr1[0] - 0x80) << 8;
samp2 = (ptr2[0] - 0x80) << 8;
samp1 += ((samp2 - samp1) * fract) >> 12;
pcm[0] += samp1;
pcm[0] += (samp1 * cs4231_DACvolume_L * np2cfg.vol_pcm) >> 15;
samp1 = (ptr1[1] - 0x80) << 8;
samp2 = (ptr2[1] - 0x80) << 8;
samp1 += ((samp2 - samp1) * fract) >> 12;
pcm[1] += samp1;
pcm[1] += (samp1 * cs4231_DACvolume_R * np2cfg.vol_pcm) >> 15;
pcm += 2;
pos12 += cs->step12;
} while(--count);
leng = min(leng, (pos12 >> 12));
cs->bufdatas -= (leng << 1);
cs->bufpos += (leng << 1);
cs->bufpos = (cs->bufpos + (leng << 1)) & CS4231_BUFMASK;
cs->pos12 = pos12 & ((1 << 12) - 1);
}
static void SOUNDCALL pcm16m(CS4231 cs, SINT32 *pcm, UINT count) {
UINT leng;
UINT32 leng;
UINT32 pos12;
SINT32 fract;
UINT samppos;
UINT32 samppos;
const UINT8 *ptr1;
const UINT8 *ptr2;
SINT32 samp1;
@ -122,24 +130,24 @@ const UINT8 *ptr2;
samp1 = (((SINT8)ptr1[0]) << 8) + ptr1[1];
samp2 = (((SINT8)ptr2[0]) << 8) + ptr2[1];
samp1 += ((samp2 - samp1) * fract) >> 12;
pcm[0] += samp1;
pcm[1] += samp1;
pcm[0] += (samp1 * cs4231_DACvolume_L * np2cfg.vol_pcm) >> 15;
pcm[1] += (samp1 * cs4231_DACvolume_R * np2cfg.vol_pcm) >> 15;
pcm += 2;
pos12 += cs->step12;
} while(--count);
leng = min(leng, (pos12 >> 12));
cs->bufdatas -= (leng << 1);
cs->bufpos += (leng << 1);
cs->bufpos = (cs->bufpos + (leng << 1)) & CS4231_BUFMASK;
cs->pos12 = pos12 & ((1 << 12) - 1);
}
static void SOUNDCALL pcm16s(CS4231 cs, SINT32 *pcm, UINT count) {
UINT leng;
UINT32 leng;
UINT32 pos12;
SINT32 fract;
UINT samppos;
UINT32 samppos;
const UINT8 *ptr1;
const UINT8 *ptr2;
SINT32 samp1;
@ -163,37 +171,32 @@ const UINT8 *ptr2;
samp1 = (((SINT8)ptr1[0]) << 8) + ptr1[1];
samp2 = (((SINT8)ptr2[0]) << 8) + ptr2[1];
samp1 += ((samp2 - samp1) * fract) >> 12;
pcm[0] += samp1;
pcm[0] += (samp1 * cs4231_DACvolume_L * np2cfg.vol_pcm) >> 15;
samp1 = (((SINT8)ptr1[2]) << 8) + ptr1[3];
samp2 = (((SINT8)ptr2[2]) << 8) + ptr2[3];
samp1 += ((samp2 - samp1) * fract) >> 12;
pcm[1] += samp1;
pcm[1] += (samp1 * cs4231_DACvolume_R * np2cfg.vol_pcm) >> 15;
pcm += 2;
pos12 += cs->step12;
} while(--count);
leng = min(leng, (pos12 >> 12));
cs->bufdatas -= (leng << 2);
cs->bufpos += (leng << 2);
cs->bufpos = (cs->bufpos + (leng << 2)) & CS4231_BUFMASK;
cs->pos12 = pos12 & ((1 << 12) - 1);
}
static void SOUNDCALL pcm16m_ex(CS4231 cs, SINT32 *pcm, UINT count) {
UINT leng;
UINT32 leng;
UINT32 pos12;
SINT32 fract;
UINT samppos;
UINT32 samppos;
const UINT8 *ptr1;
const UINT8 *ptr2;
SINT32 samp1;
SINT32 samp2;
UINT8 oddflag = 0;
if(cs->bufdatas & 1){
oddflag = 1;
}
leng = cs->bufdatas >> 1;
if (!leng) {
return;
@ -212,36 +215,29 @@ const UINT8 *ptr2;
samp1 = (((SINT8)ptr1[1]) << 8) + ptr1[0];
samp2 = (((SINT8)ptr2[1]) << 8) + ptr2[0];
samp1 += ((samp2 - samp1) * fract) >> 12;
pcm[0] += samp1;
pcm[1] += samp1;
pcm[0] += (samp1 * cs4231_DACvolume_L * np2cfg.vol_pcm) >> 15;
pcm[1] += (samp1 * cs4231_DACvolume_R * np2cfg.vol_pcm) >> 15;
pcm += 2;
pos12 += cs->step12;
} while(--count);
if(oddflag){
cs->bufdatas--;
}
leng = min(leng, (pos12 >> 12));
cs->bufdatas -= (leng << 1);
cs->bufpos += (leng << 1);
cs->bufpos = (cs->bufpos + (leng << 1)) & CS4231_BUFMASK;
cs->pos12 = pos12 & ((1 << 12) - 1);
}
static void SOUNDCALL pcm16s_ex(CS4231 cs, SINT32 *pcm, UINT count) {
UINT leng;
UINT32 leng;
UINT32 pos12;
SINT32 fract;
UINT samppos;
UINT32 samppos;
const UINT8 *ptr1;
const UINT8 *ptr2;
SINT32 samp1;
SINT32 samp2;
UINT8 oddflag = 0;
if(cs->bufdatas & 1){
oddflag = 1;
}
leng = cs->bufdatas >> 2;
if (!leng) {
return;
@ -260,21 +256,18 @@ const UINT8 *ptr2;
samp1 = (((SINT8)ptr1[1]) << 8) + ptr1[0];
samp2 = (((SINT8)ptr2[1]) << 8) + ptr2[0];
samp1 += ((samp2 - samp1) * fract) >> 12;
pcm[0] += samp1;
pcm[0] += (samp1 * cs4231_DACvolume_L * np2cfg.vol_pcm) >> 15;
samp1 = (((SINT8)ptr1[3]) << 8) + ptr1[2];
samp2 = (((SINT8)ptr2[3]) << 8) + ptr2[2];
samp1 += ((samp2 - samp1) * fract) >> 12;
pcm[1] += samp1;
pcm[1] += (samp1 * cs4231_DACvolume_R * np2cfg.vol_pcm) >> 15;
pcm += 2;
pos12 += cs->step12;
} while(--count);
if(oddflag){
cs->bufdatas--;
}
leng = min(leng, (pos12 >> 12));
cs->bufdatas -= (leng << 2);
cs->bufpos += (leng << 2);
cs->bufpos = (cs->bufpos + (leng << 2)) & CS4231_BUFMASK;
cs->pos12 = pos12 & ((1 << 12) - 1);
}
@ -293,7 +286,7 @@ static const CS4231FN cs4231fn[16] = {
pcm8s,
nomake, // 1: u-Law
nomake,
pcm16m_ex, // 2:
pcm16m_ex, // 2: 16bit PCM(little endian)?
pcm16s_ex,
nomake, // 3: A-Law
nomake,
@ -312,7 +305,39 @@ static const CS4231FN cs4231fn[16] = {
void SOUNDCALL cs4231_getpcm(CS4231 cs, SINT32 *pcm, UINT count) {
if ((cs->reg.iface & 1) && (count)) {
if(cs4231_DACvolumereg_L != cs->reg.dac_l){
cs4231_DACvolumereg_L = cs->reg.dac_l;
if(cs->reg.dac_l & 0x80){ // DAC L Mute
cs4231_DACvolume_L = 0;
}else{
cs4231_DACvolume_L = (int)(pow(10, -1.5 * ((cs4231_DACvolumereg_L) & 0x3f) / 20.0) * 1024); // DAC L Volume (1bit毎に-1.5dB)
}
}
if(cs4231_DACvolumereg_R != cs->reg.dac_r){
cs4231_DACvolumereg_R = cs->reg.dac_r;
if(cs->reg.dac_r & 0x80){ // DAC R Mute
cs4231_DACvolume_R = 0;
}else{
cs4231_DACvolume_R = (int)(pow(10, -1.5 * ((cs4231_DACvolumereg_R) & 0x3f) / 20.0) * 1024); // DAC R Volume (1bit毎に-1.5dB)
}
}
(*cs4231fn[cs->reg.datafmt >> 4])(cs, pcm, count);
//// CS4231タイマー割り込み手抜き
//if ((cs->reg.pinctrl & 2) && (cs->dmairq != 0xff) && (cs->timer)) {
// static double timercount = 0;
// int decval = 0;
// timercount += (double)count/44100 * 1000 * 100; // 10usec timer
// decval = (int)(timercount);
// timercount -= (double)decval;
// cs->timercounter -= decval;
// if(cs->timercounter < 0){
// cs->timercounter = 3000;//cs->timer;
// cs->intflag |= INt;
// cs->reg.featurestatus |= PI;
// pic_setirq(cs->dmairq);
// }
//}
}
}

View File

@ -182,6 +182,7 @@ void fmboard_reset(const NP2CFG *pConfig, SOUNDID nSoundID)
break;
case SOUNDID_PC_9801_118:
g_nSoundID = nSoundID; // XXX: 先に設定
board118_reset(pConfig);
break;
@ -218,6 +219,12 @@ void fmboard_reset(const NP2CFG *pConfig, SOUNDID nSoundID)
case SOUNDID_SOUNDORCHESTRAV:
boardso_reset(pConfig, TRUE);
break;
#if defined(SUPPORT_SOUND_SB16)
case SOUNDID_SB16:
boardsb16_reset(pConfig);
break;
#endif // defined(SUPPORT_SOUND_SB16)
#if defined(SUPPORT_PX)
case SOUNDID_PX1:
@ -293,6 +300,12 @@ void fmboard_bind(void) {
boardso_bind();
break;
#if defined(SUPPORT_SOUND_SB16)
case SOUNDID_SB16:
boardsb16_bind();
break;
#endif // defined(SUPPORT_SOUND_SB16)
#if defined(SUPPORT_PX)
case SOUNDID_PX1:
boardpx1_bind();
@ -303,11 +316,6 @@ void fmboard_bind(void) {
break;
#endif // defined(SUPPORT_PX)
#if defined(SUPPORT_SOUND_SB16)
case SOUNDID_SB16:
boardsb16_bind();
break;
#endif // defined(SUPPORT_SOUND_SB16)
default:
break;
}

View File

@ -30,7 +30,7 @@ typedef struct {
UINT8 dmach;
UINT16 base;
UINT8 mixsel;
UINT8 mixreg[0x18];
UINT8 mixreg[0x100];
} SB16;
#ifdef __cplusplus

27
sound/mame/driver.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#ifndef __DRIVER_H__
#define __DRIVER_H__
#define HAS_YM3812 1
#define HAS_YM3526 0
#define HAS_Y8950 1
#define HAS_YMF262 1
#if defined(_MSC_VER)
#pragma warning(disable: 4244)
#pragma warning(disable: 4245)
#define INLINE __inline static
#elif defined(__BORLANDC__)
#define INLINE __inline
#elif defined(__GNUC__)
#define INLINE __inline__
#else
#define INLINE static
#endif
#define logerror(x,y,z)
//typedef signed int stream_sample_t;
typedef signed short stream_sample_t;
#endif /* __DRIVER_H__ */

214
sound/mame/fm.h Normal file
View File

@ -0,0 +1,214 @@
/*
File: fm.h -- header file for software emulation for FM sound generator
*/
#ifndef _H_FM_FM_
#define _H_FM_FM_
#ifdef __cplusplus
extern "C" {
#endif
/* --- select emulation chips --- */
#define BUILD_YM2203 (HAS_YM2203) /* build YM2203(OPN) emulator */
#define BUILD_YM2608 (HAS_YM2608) /* build YM2608(OPNA) emulator */
#define BUILD_YM2610 (HAS_YM2610) /* build YM2610(OPNB) emulator */
#define BUILD_YM2610B (HAS_YM2610B) /* build YM2610B(OPNB?)emulator */
#define BUILD_YM2612 (HAS_YM2612 || HAS_YM3438) /* build YM2612(OPN2) emulator */
/* select bit size of output : 8 or 16 */
#define FM_SAMPLE_BITS 16
/* select timer system internal or external */
#define FM_INTERNAL_TIMER 0
/* --- speedup optimize --- */
/* busy flag enulation , The definition of FM_GET_TIME_NOW() is necessary. */
#define FM_BUSY_FLAG_SUPPORT 0
//#define FM_BUSY_FLAG_SUPPORT 1
/* --- external SSG(YM2149/AY-3-8910)emulator interface port */
/* used by YM2203,YM2608,and YM2610 */
struct ssg_callbacks
{
void (*set_clock)(void *param, int clock);
void (*write)(void *param, int address, int data);
int (*read)(void *param);
void (*reset)(void *param);
};
/* --- external callback funstions for realtime update --- */
/* for busy flag emulation , function FM_GET_TIME_NOW() should */
/* return present time in seconds with "double" precision */
/* in timer.c */
#define FM_GET_TIME_NOW() timer_get_time()
#if BUILD_YM2203
/* in 2203intf.c */
void YM2203UpdateRequest(void *param);
#define YM2203UpdateReq(chip) YM2203UpdateRequest(chip)
#endif
#if BUILD_YM2608
/* in 2608intf.c */
void YM2608UpdateRequest(void *param);
#define YM2608UpdateReq(chip) YM2608UpdateRequest(chip);
#endif
#if BUILD_YM2610
/* in 2610intf.c */
void YM2610UpdateRequest(void *param);
#define YM2610UpdateReq(chip) YM2610UpdateRequest(chip);
#endif
#if BUILD_YM2612
/* in 2612intf.c */
void YM2612UpdateRequest(void *param);
#define YM2612UpdateReq(chip) YM2612UpdateRequest(chip);
#endif
/* compiler dependence */
#if 1
#ifndef OSD_CPU_H
#define OSD_CPU_H
typedef unsigned char UINT8; /* unsigned 8bit */
typedef unsigned short UINT16; /* unsigned 16bit */
typedef unsigned int UINT32; /* unsigned 32bit */
typedef signed char INT8; /* signed 8bit */
typedef signed short INT16; /* signed 16bit */
typedef signed int INT32; /* signed 32bit */
#endif
#endif
#ifndef INLINE
#define INLINE static __inline__
#endif
//typedef stream_sample_t FMSAMPLE;
/*
#if (FM_SAMPLE_BITS==16)
typedef INT16 FMSAMPLE;
#endif
#if (FM_SAMPLE_BITS==8)
typedef unsigned char FMSAMPLE;
#endif
*/
typedef void (*FM_TIMERHANDLER)(void *param,int c,int cnt,double stepTime);
typedef void (*FM_IRQHANDLER)(void *param,int irq);
/* FM_TIMERHANDLER : Stop or Start timer */
/* int n = chip number */
/* int c = Channel 0=TimerA,1=TimerB */
/* int count = timer count (0=stop) */
/* doube stepTime = step time of one count (sec.)*/
/* FM_IRQHHANDLER : IRQ level changing sense */
/* int n = chip number */
/* int irq = IRQ level 0=OFF,1=ON */
#if BUILD_YM2203
/* -------------------- YM2203(OPN) Interface -------------------- */
/*
** Initialize YM2203 emulator(s).
**
** 'num' is the number of virtual YM2203's to allocate
** 'baseclock'
** 'rate' is sampling rate
** 'TimerHandler' timer callback handler when timer start and clear
** 'IRQHandler' IRQ callback handler when changed IRQ level
** return 0 = success
*/
void * YM2203Init(void *param, int index, int baseclock, int rate,
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const struct ssg_callbacks *ssg);
/*
** shutdown the YM2203 emulators
*/
void YM2203Shutdown(void *chip);
/*
** reset all chip registers for YM2203 number 'num'
*/
void YM2203ResetChip(void *chip);
/*
** update one of chip
*/
void YM2203UpdateOne(void *chip, FMSAMPLE *buffer, int length);
/*
** Write
** return : InterruptLevel
*/
int YM2203Write(void *chip,int a,unsigned char v);
/*
** Read
** return : InterruptLevel
*/
unsigned char YM2203Read(void *chip,int a);
/*
** Timer OverFlow
*/
int YM2203TimerOver(void *chip, int c);
/*
** State Save
*/
void YM2203Postload(void *chip);
#endif /* BUILD_YM2203 */
#if BUILD_YM2608
/* -------------------- YM2608(OPNA) Interface -------------------- */
void * YM2608Init(void *param, int index, int baseclock, int rate,
void *pcmroma,int pcmsizea,
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const struct ssg_callbacks *ssg);
void YM2608Shutdown(void *chip);
void YM2608ResetChip(void *chip);
void YM2608UpdateOne(void *chip, FMSAMPLE **buffer, int length);
int YM2608Write(void *chip, int a,unsigned char v);
unsigned char YM2608Read(void *chip,int a);
int YM2608TimerOver(void *chip, int c );
void YM2608Postload(void *chip);
#endif /* BUILD_YM2608 */
#if (BUILD_YM2610||BUILD_YM2610B)
/* -------------------- YM2610(OPNB) Interface -------------------- */
void * YM2610Init(void *param, int index, int baseclock, int rate,
void *pcmroma,int pcmasize,void *pcmromb,int pcmbsize,
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const struct ssg_callbacks *ssg);
void YM2610Shutdown(void *chip);
void YM2610ResetChip(void *chip);
void YM2610UpdateOne(void *chip, FMSAMPLE **buffer, int length);
#if BUILD_YM2610B
void YM2610BUpdateOne(void *chip, FMSAMPLE **buffer, int length);
#endif
int YM2610Write(void *chip, int a,unsigned char v);
unsigned char YM2610Read(void *chip,int a);
int YM2610TimerOver(void *chip, int c );
void YM2610Postload(void *chip);
#endif /* BUILD_YM2610 */
#if BUILD_YM2612
void * YM2612Init(void *param, int index, int baseclock, int rate,
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler);
void YM2612Shutdown(void *chip);
void YM2612ResetChip(void *chip);
void YM2612UpdateOne(void *chip, FMSAMPLE **buffer, int length);
int YM2612Write(void *chip, int a,unsigned char v);
unsigned char YM2612Read(void *chip,int a);
int YM2612TimerOver(void *chip, int c );
void YM2612Postload(void *chip);
#endif /* BUILD_YM2612 */
#ifdef __cplusplus
}
#endif
#endif /* _H_FM_FM_ */

2480
sound/mame/fmopl.c Normal file

File diff suppressed because it is too large Load Diff

111
sound/mame/fmopl.h Normal file
View File

@ -0,0 +1,111 @@
#ifndef __FMOPL_H_
#define __FMOPL_H_
/* --- select emulation chips --- */
#define BUILD_YM3812 (HAS_YM3812)
//#define BUILD_YM3526 (HAS_YM3526)
#define BUILD_Y8950 (HAS_Y8950)
/* select output bits size of output : 8 or 16 */
#define OPL_SAMPLE_BITS 16
/* compiler dependence */
#ifndef OSD_CPU_H
#define OSD_CPU_H
typedef unsigned char UINT8; /* unsigned 8bit */
typedef unsigned short UINT16; /* unsigned 16bit */
typedef unsigned int UINT32; /* unsigned 32bit */
typedef signed char INT8; /* signed 8bit */
typedef signed short INT16; /* signed 16bit */
typedef signed int INT32; /* signed 32bit */
#endif
typedef stream_sample_t OPLSAMPLE;
/*
#if (OPL_SAMPLE_BITS==16)
typedef INT16 OPLSAMPLE;
#endif
#if (OPL_SAMPLE_BITS==8)
typedef INT8 OPLSAMPLE;
#endif
*/
typedef void (*OPL_TIMERHANDLER)(void *param,int timer,double interval_Sec);
typedef void (*OPL_IRQHANDLER)(void *param,int irq);
typedef void (*OPL_UPDATEHANDLER)(void *param,int min_interval_us);
typedef void (*OPL_PORTHANDLER_W)(void *param,unsigned char data);
typedef unsigned char (*OPL_PORTHANDLER_R)(void *param);
#if BUILD_YM3812
void *YM3812Init(int clock, int rate);
void YM3812Shutdown(void *chip);
void YM3812ResetChip(void *chip);
int YM3812Write(void *chip, int a, int v);
unsigned char YM3812Read(void *chip, int a);
int YM3812TimerOver(void *chip, int c);
void YM3812UpdateOne(void *chip, OPLSAMPLE *buffer, int length);
void YM3812SetTimerHandler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
void YM3812SetIRQHandler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
void YM3812SetUpdateHandler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
#endif
#if BUILD_YM3526
/*
** Initialize YM3526 emulator(s).
**
** 'num' is the number of virtual YM3526's to allocate
** 'clock' is the chip clock in Hz
** 'rate' is sampling rate
*/
void *YM3526Init(int clock, int rate);
/* shutdown the YM3526 emulators*/
void YM3526Shutdown(void *chip);
void YM3526ResetChip(void *chip);
int YM3526Write(void *chip, int a, int v);
unsigned char YM3526Read(void *chip, int a);
int YM3526TimerOver(void *chip, int c);
/*
** Generate samples for one of the YM3526's
**
** 'which' is the virtual YM3526 number
** '*buffer' is the output buffer pointer
** 'length' is the number of samples that should be generated
*/
void YM3526UpdateOne(void *chip, OPLSAMPLE *buffer, int length);
void YM3526SetTimerHandler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
void YM3526SetIRQHandler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
void YM3526SetUpdateHandler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
#endif
#if BUILD_Y8950
/* Y8950 port handlers */
void Y8950SetPortHandler(void *chip, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, void *param);
void Y8950SetKeyboardHandler(void *chip, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, void *param);
void Y8950SetDeltaTMemory(void *chip, void * deltat_mem_ptr, int deltat_mem_size );
void * Y8950Init (int clock, int rate);
void Y8950Shutdown (void *chip);
void Y8950ResetChip (void *chip);
int Y8950Write (void *chip, int a, int v);
unsigned char Y8950Read (void *chip, int a);
int Y8950TimerOver (void *chip, int c);
void Y8950UpdateOne (void *chip, OPLSAMPLE *buffer, int length);
void Y8950SetTimerHandler (void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
void Y8950SetIRQHandler (void *chip, OPL_IRQHANDLER IRQHandler, void *param);
void Y8950SetUpdateHandler (void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
#endif
#endif /* __FMOPL_H_ */

654
sound/mame/ymdeltat.c Normal file
View File

@ -0,0 +1,654 @@
/*
**
** File: ymdeltat.c
**
** YAMAHA DELTA-T adpcm sound emulation subroutine
** used by fmopl.c (Y8950) and fm.c (YM2608 and YM2610/B)
**
** Base program is YM2610 emulator by Hiromitsu Shioya.
** Written by Tatsuyuki Satoh
** Improvements by Jarek Burczynski (bujar at mame dot net)
**
**
** History:
**
** 03-08-2003 Jarek Burczynski:
** - fixed BRDY flag implementation.
**
** 24-07-2003 Jarek Burczynski, Frits Hilderink:
** - fixed delault value for control2 in YM_DELTAT_ADPCM_Reset
**
** 22-07-2003 Jarek Burczynski, Frits Hilderink:
** - fixed external memory support
**
** 15-06-2003 Jarek Burczynski:
** - implemented CPU -> AUDIO ADPCM synthesis (via writes to the ADPCM data reg $08)
** - implemented support for the Limit address register
** - supported two bits from the control register 2 ($01): RAM TYPE (x1 bit/x8 bit), ROM/RAM
** - implemented external memory access (read/write) via the ADPCM data reg reads/writes
** Thanks go to Frits Hilderink for the example code.
**
** 14-06-2003 Jarek Burczynski:
** - various fixes to enable proper support for status register flags: BSRDY, PCM BSY, ZERO
** - modified EOS handling
**
** 05-04-2003 Jarek Burczynski:
** - implemented partial support for external/processor memory on sample replay
**
** 01-12-2002 Jarek Burczynski:
** - fixed first missing sound in gigandes thanks to previous fix (interpolator) by ElSemi
** - renamed/removed some YM_DELTAT struct fields
**
** 28-12-2001 Acho A. Tang
** - added EOS status report on ADPCM playback.
**
** 05-08-2001 Jarek Burczynski:
** - now_step is initialized with 0 at the start of play.
**
** 12-06-2001 Jarek Burczynski:
** - corrected end of sample bug in YM_DELTAT_ADPCM_CALC.
** Checked on real YM2610 chip - address register is 24 bits wide.
** Thanks go to Stefan Jokisch (stefan.jokisch@gmx.de) for tracking down the problem.
**
** TO DO:
** Check size of the address register on the other chips....
**
** Version 0.72
**
** sound chips that have this unit:
** YM2608 OPNA
** YM2610/B OPNB
** Y8950 MSX AUDIO
**
*/
#include "driver.h"
//#include "state.h"
#include "fm.h"
#include "ymdeltat.h"
#define YM_DELTAT_DELTA_MAX (24576)
#define YM_DELTAT_DELTA_MIN (127)
#define YM_DELTAT_DELTA_DEF (127)
#define YM_DELTAT_DECODE_RANGE 32768
#define YM_DELTAT_DECODE_MIN (-(YM_DELTAT_DECODE_RANGE))
#define YM_DELTAT_DECODE_MAX ((YM_DELTAT_DECODE_RANGE)-1)
/* Forecast to next Forecast (rate = *8) */
/* 1/8 , 3/8 , 5/8 , 7/8 , 9/8 , 11/8 , 13/8 , 15/8 */
const INT32 ym_deltat_decode_tableB1[16] = {
1, 3, 5, 7, 9, 11, 13, 15,
-1, -3, -5, -7, -9, -11, -13, -15,
};
/* delta to next delta (rate= *64) */
/* 0.9 , 0.9 , 0.9 , 0.9 , 1.2 , 1.6 , 2.0 , 2.4 */
const INT32 ym_deltat_decode_tableB2[16] = {
57, 57, 57, 57, 77, 102, 128, 153,
57, 57, 57, 57, 77, 102, 128, 153
};
#if 0
void YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT)
{
logerror("BRDY_callback reached (flag set) !\n");
/* set BRDY bit in status register */
if(DELTAT->status_set_handler)
if(DELTAT->status_change_BRDY_bit)
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
}
#endif
UINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT)
{
UINT8 v = 0;
/* external memory read */
if ( (DELTAT->portstate & 0xe0)==0x20 )
{
/* two dummy reads */
if (DELTAT->memread)
{
DELTAT->now_addr = DELTAT->start << 1;
DELTAT->memread--;
return 0;
}
if ( DELTAT->now_addr != (DELTAT->end<<1) )
{
v = DELTAT->memory[DELTAT->now_addr>>1];
/*logerror("YM Delta-T memory read $%08x, v=$%02x\n", DELTAT->now_addr >> 1, v);*/
DELTAT->now_addr+=2; /* two nibbles at a time */
/* reset BRDY bit in status register, which means we are reading the memory now */
if(DELTAT->status_reset_handler)
if(DELTAT->status_change_BRDY_bit)
(DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
/* setup a timer that will callback us in 10 master clock cycles for Y8950
* in the callback set the BRDY flag to 1 , which means we have another data ready.
* For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.
*/
/* set BRDY bit in status register */
if(DELTAT->status_set_handler)
if(DELTAT->status_change_BRDY_bit)
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
}
else
{
/* set EOS bit in status register */
if(DELTAT->status_set_handler)
if(DELTAT->status_change_EOS_bit)
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);
}
}
return v;
}
/* 0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */
static UINT8 dram_rightshift[4]={3,0,0,0};
/* DELTA-T ADPCM write register */
void YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v)
{
if(r>=0x10) return;
DELTAT->reg[r] = v; /* stock data */
switch( r )
{
case 0x00:
/*
START:
Accessing *external* memory is started when START bit (D7) is set to "1", so
you must set all conditions needed for recording/playback before starting.
If you access *CPU-managed* memory, recording/playback starts after
read/write of ADPCM data register $08.
REC:
0 = ADPCM synthesis (playback)
1 = ADPCM analysis (record)
MEMDATA:
0 = processor (*CPU-managed*) memory (means: using register $08)
1 = external memory (using start/end/limit registers to access memory: RAM or ROM)
SPOFF:
controls output pin that should disable the speaker while ADPCM analysis
RESET and REPEAT only work with external memory.
some examples:
value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning:
C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register
80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register
60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08
20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08
*/
/* handle emulation mode */
if(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)
{
v |= 0x20; /* YM2610 always uses external memory and doesn't even have memory flag bit. */
}
DELTAT->portstate = v & (0x80|0x40|0x20|0x10|0x01); /* start, rec, memory mode, repeat flag copy, reset(bit0) */
if( DELTAT->portstate&0x80 )/* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */
{
/* set PCM BUSY bit */
DELTAT->PCM_BSY = 1;
/* start ADPCM */
DELTAT->now_step = 0;
DELTAT->acc = 0;
DELTAT->prev_acc = 0;
DELTAT->adpcml = 0;
DELTAT->adpcmd = YM_DELTAT_DELTA_DEF;
DELTAT->now_data = 0;
}
if( DELTAT->portstate&0x20 ) /* do we access external memory? */
{
DELTAT->now_addr = DELTAT->start << 1;
DELTAT->memread = 2; /* two dummy reads needed before accesing external memory via register $08*/
/* if yes, then let's check if ADPCM memory is mapped and big enough */
if(DELTAT->memory == 0)
{
// logerror("YM Delta-T ADPCM rom not mapped\n");
DELTAT->portstate = 0x00;
DELTAT->PCM_BSY = 0;
}
else
{
if( DELTAT->end >= DELTAT->memory_size ) /* Check End in Range */
{
// logerror("YM Delta-T ADPCM end out of range: $%08x\n", DELTAT->end);
DELTAT->end = DELTAT->memory_size - 1;
}
if( DELTAT->start >= DELTAT->memory_size ) /* Check Start in Range */
{
// logerror("YM Delta-T ADPCM start out of range: $%08x\n", DELTAT->start);
DELTAT->portstate = 0x00;
DELTAT->PCM_BSY = 0;
}
}
}
else /* we access CPU memory (ADPCM data register $08) so we only reset now_addr here */
{
DELTAT->now_addr = 0;
}
if( DELTAT->portstate&0x01 )
{
DELTAT->portstate = 0x00;
/* clear PCM BUSY bit (in status register) */
DELTAT->PCM_BSY = 0;
/* set BRDY flag */
if(DELTAT->status_set_handler)
if(DELTAT->status_change_BRDY_bit)
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
}
break;
case 0x01: /* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */
/* handle emulation mode */
if(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)
{
v |= 0x01; /* YM2610 always uses ROM as an external memory and doesn't tave ROM/RAM memory flag bit. */
}
DELTAT->pan = &DELTAT->output_pointer[(v>>6)&0x03];
if ((DELTAT->control2 & 3) != (v & 3))
{
/*0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */
if (DELTAT->DRAMportshift != dram_rightshift[v&3])
{
DELTAT->DRAMportshift = dram_rightshift[v&3];
/* final shift value depends on chip type and memory type selected:
8 for YM2610 (ROM only),
5 for ROM for Y8950 and YM2608,
5 for x8bit DRAMs for Y8950 and YM2608,
2 for x1bit DRAMs for Y8950 and YM2608.
*/
/* refresh addresses */
DELTAT->start = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift);
DELTAT->end = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift);
DELTAT->end += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1;
DELTAT->limit = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift);
}
}
DELTAT->control2 = v;
break;
case 0x02: /* Start Address L */
case 0x03: /* Start Address H */
DELTAT->start = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift);
/*logerror("DELTAT start: 02=%2x 03=%2x addr=%8x\n",DELTAT->reg[0x2], DELTAT->reg[0x3],DELTAT->start );*/
break;
case 0x04: /* Stop Address L */
case 0x05: /* Stop Address H */
DELTAT->end = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift);
DELTAT->end += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1;
/*logerror("DELTAT end : 04=%2x 05=%2x addr=%8x\n",DELTAT->reg[0x4], DELTAT->reg[0x5],DELTAT->end );*/
break;
case 0x06: /* Prescale L (ADPCM and Record frq) */
case 0x07: /* Prescale H */
break;
case 0x08: /* ADPCM data */
/*
some examples:
value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning:
C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register
80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register
60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08
20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08
*/
/* external memory write */
if ( (DELTAT->portstate & 0xe0)==0x60 )
{
if (DELTAT->memread)
{
DELTAT->now_addr = DELTAT->start << 1;
DELTAT->memread = 0;
}
/*logerror("YM Delta-T memory write $%08x, v=$%02x\n", DELTAT->now_addr >> 1, v);*/
if ( DELTAT->now_addr != (DELTAT->end<<1) )
{
DELTAT->memory[DELTAT->now_addr>>1] = v;
DELTAT->now_addr+=2; /* two nibbles at a time */
/* reset BRDY bit in status register, which means we are processing the write */
if(DELTAT->status_reset_handler)
if(DELTAT->status_change_BRDY_bit)
(DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
/* setup a timer that will callback us in 10 master clock cycles for Y8950
* in the callback set the BRDY flag to 1 , which means we have written the data.
* For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.
*/
/* set BRDY bit in status register */
if(DELTAT->status_set_handler)
if(DELTAT->status_change_BRDY_bit)
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
}
else
{
/* set EOS bit in status register */
if(DELTAT->status_set_handler)
if(DELTAT->status_change_EOS_bit)
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);
}
return;
}
/* ADPCM synthesis from CPU */
if ( (DELTAT->portstate & 0xe0)==0x80 )
{
DELTAT->CPU_data = v;
/* Reset BRDY bit in status register, which means we are full of data */
if(DELTAT->status_reset_handler)
if(DELTAT->status_change_BRDY_bit)
(DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
return;
}
break;
case 0x09: /* DELTA-N L (ADPCM Playback Prescaler) */
case 0x0a: /* DELTA-N H */
DELTAT->delta = (DELTAT->reg[0xa]*0x0100 | DELTAT->reg[0x9]);
DELTAT->step = (UINT32)( (double)(DELTAT->delta /* *(1<<(YM_DELTAT_SHIFT-16)) */ ) * (DELTAT->freqbase) );
/*logerror("DELTAT deltan:09=%2x 0a=%2x\n",DELTAT->reg[0x9], DELTAT->reg[0xa]);*/
break;
case 0x0b: /* Output level control (volume, linear) */
{
INT32 oldvol = DELTAT->volume;
DELTAT->volume = (v&0xff) * (DELTAT->output_range/256) / YM_DELTAT_DECODE_RANGE;
/* v * ((1<<16)>>8) >> 15;
* thus: v * (1<<8) >> 15;
* thus: output_range must be (1 << (15+8)) at least
* v * ((1<<23)>>8) >> 15;
* v * (1<<15) >> 15;
*/
/*logerror("DELTAT vol = %2x\n",v&0xff);*/
if( oldvol != 0 )
{
DELTAT->adpcml = (int)((double)DELTAT->adpcml / (double)oldvol * (double)DELTAT->volume);
}
}
break;
case 0x0c: /* Limit Address L */
case 0x0d: /* Limit Address H */
DELTAT->limit = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift);
/*logerror("DELTAT limit: 0c=%2x 0d=%2x addr=%8x\n",DELTAT->reg[0xc], DELTAT->reg[0xd],DELTAT->limit );*/
break;
}
}
void YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan,int emulation_mode)
{
DELTAT->now_addr = 0;
DELTAT->now_step = 0;
DELTAT->step = 0;
DELTAT->start = 0;
DELTAT->end = 0;
DELTAT->limit = ~0; /* this way YM2610 and Y8950 (both of which don't have limit address reg) will still work */
DELTAT->volume = 0;
DELTAT->pan = &DELTAT->output_pointer[pan];
DELTAT->acc = 0;
DELTAT->prev_acc = 0;
DELTAT->adpcmd = 127;
DELTAT->adpcml = 0;
DELTAT->emulation_mode = (UINT8)emulation_mode;
DELTAT->portstate = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x20 : 0;
DELTAT->control2 = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x01 : 0; /* default setting depends on the emulation mode. MSX demo called "facdemo_4" doesn't setup control2 register at all and still works */
DELTAT->DRAMportshift = dram_rightshift[DELTAT->control2 & 3];
/* The flag mask register disables the BRDY after the reset, however
** as soon as the mask is enabled the flag needs to be set. */
/* set BRDY bit in status register */
if(DELTAT->status_set_handler)
if(DELTAT->status_change_BRDY_bit)
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
}
void YM_DELTAT_postload(YM_DELTAT *DELTAT,UINT8 *regs)
{
int r;
/* to keep adpcml */
DELTAT->volume = 0;
/* update */
for(r=1;r<16;r++)
YM_DELTAT_ADPCM_Write(DELTAT,r,regs[r]);
DELTAT->reg[0] = regs[0];
/* current rom data */
if (DELTAT->memory)
DELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1) );
}
void YM_DELTAT_savestate(const char *statename,int num,YM_DELTAT *DELTAT)
{
#ifdef __STATE_H__
state_save_register_UINT8 (statename, num, "DeltaT.portstate", &DELTAT->portstate, 1);
state_save_register_UINT32(statename, num, "DeltaT.address" , &DELTAT->now_addr , 1);
state_save_register_UINT32(statename, num, "DeltaT.step" , &DELTAT->now_step , 1);
state_save_register_INT32 (statename, num, "DeltaT.acc" , &DELTAT->acc , 1);
state_save_register_INT32 (statename, num, "DeltaT.prev_acc" , &DELTAT->prev_acc , 1);
state_save_register_INT32 (statename, num, "DeltaT.adpcmd" , &DELTAT->adpcmd , 1);
state_save_register_INT32 (statename, num, "DeltaT.adpcml" , &DELTAT->adpcml , 1);
#endif
}
#define YM_DELTAT_Limit(val,max,min) \
{ \
if ( val > max ) val = max; \
else if ( val < min ) val = min; \
}
INLINE void YM_DELTAT_synthesis_from_external_memory(YM_DELTAT *DELTAT)
{
UINT32 step;
int data;
DELTAT->now_step += DELTAT->step;
if ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) )
{
step = DELTAT->now_step >> YM_DELTAT_SHIFT;
DELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1;
do{
if ( DELTAT->now_addr == (DELTAT->limit<<1) )
DELTAT->now_addr = 0;
if ( DELTAT->now_addr == (DELTAT->end<<1) ) { /* 12-06-2001 JB: corrected comparison. Was > instead of == */
if( DELTAT->portstate&0x10 ){
/* repeat start */
DELTAT->now_addr = DELTAT->start<<1;
DELTAT->acc = 0;
DELTAT->adpcmd = YM_DELTAT_DELTA_DEF;
DELTAT->prev_acc = 0;
}else{
/* set EOS bit in status register */
if(DELTAT->status_set_handler)
if(DELTAT->status_change_EOS_bit)
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);
/* clear PCM BUSY bit (reflected in status register) */
DELTAT->PCM_BSY = 0;
DELTAT->portstate = 0;
DELTAT->adpcml = 0;
DELTAT->prev_acc = 0;
return;
}
}
if( DELTAT->now_addr&1 ) data = DELTAT->now_data & 0x0f;
else
{
DELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1));
data = DELTAT->now_data >> 4;
}
DELTAT->now_addr++;
/* 12-06-2001 JB: */
/* YM2610 address register is 24 bits wide.*/
/* The "+1" is there because we use 1 bit more for nibble calculations.*/
/* WARNING: */
/* Side effect: we should take the size of the mapped ROM into account */
DELTAT->now_addr &= ( (1<<(24+1))-1);
/* store accumulator value */
DELTAT->prev_acc = DELTAT->acc;
/* Forecast to next Forecast */
DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8);
YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN);
/* delta to next delta */
DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64;
YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN );
/* ElSemi: Fix interpolator. */
/*DELTAT->prev_acc = prev_acc + ((DELTAT->acc - prev_acc) / 2 );*/
}while(--step);
}
/* ElSemi: Fix interpolator. */
DELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step);
DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step);
DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume;
/* output for work of output channels (outd[OPNxxxx])*/
*(DELTAT->pan) += DELTAT->adpcml;
}
INLINE void YM_DELTAT_synthesis_from_CPU_memory(YM_DELTAT *DELTAT)
{
UINT32 step;
int data;
DELTAT->now_step += DELTAT->step;
if ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) )
{
step = DELTAT->now_step >> YM_DELTAT_SHIFT;
DELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1;
do{
if( DELTAT->now_addr&1 )
{
data = DELTAT->now_data & 0x0f;
DELTAT->now_data = DELTAT->CPU_data;
/* after we used CPU_data, we set BRDY bit in status register,
* which means we are ready to accept another byte of data */
if(DELTAT->status_set_handler)
if(DELTAT->status_change_BRDY_bit)
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
}
else
{
data = DELTAT->now_data >> 4;
}
DELTAT->now_addr++;
/* store accumulator value */
DELTAT->prev_acc = DELTAT->acc;
/* Forecast to next Forecast */
DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8);
YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN);
/* delta to next delta */
DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64;
YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN );
}while(--step);
}
/* ElSemi: Fix interpolator. */
DELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step);
DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step);
DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume;
/* output for work of output channels (outd[OPNxxxx])*/
*(DELTAT->pan) += DELTAT->adpcml;
}
/* ADPCM B (Delta-T control type) */
void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT)
{
/*
some examples:
value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning:
80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register
C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register
60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08
20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08
*/
if ( (DELTAT->portstate & 0xe0)==0xa0 )
{
YM_DELTAT_synthesis_from_external_memory(DELTAT);
return;
}
if ( (DELTAT->portstate & 0xe0)==0x80 )
{
/* ADPCM synthesis from CPU-managed memory (from reg $08) */
YM_DELTAT_synthesis_from_CPU_memory(DELTAT); /* change output based on data in ADPCM data reg ($08) */
return;
}
//todo: ADPCM analysis
// if ( (DELTAT->portstate & 0xe0)==0xc0 )
// if ( (DELTAT->portstate & 0xe0)==0xe0 )
return;
}

82
sound/mame/ymdeltat.h Normal file
View File

@ -0,0 +1,82 @@
#ifndef __YMDELTAT_H_
#define __YMDELTAT_H_
#define YM_DELTAT_SHIFT (16)
#define YM_DELTAT_EMULATION_MODE_NORMAL 0
#define YM_DELTAT_EMULATION_MODE_YM2610 1
typedef void (*STATUS_CHANGE_HANDLER)(void *chip, UINT8 status_bits);
/* DELTA-T (adpcm type B) struct */
typedef struct deltat_adpcm_state { /* AT: rearranged and tigntened structure */
UINT8 *memory;
INT32 *output_pointer;/* pointer of output pointers */
INT32 *pan; /* pan : &output_pointer[pan] */
double freqbase;
#if 0
double write_time; /* Y8950: 10 cycles of main clock; YM2608: 20 cycles of main clock */
double read_time; /* Y8950: 8 cycles of main clock; YM2608: 18 cycles of main clock */
#endif
UINT32 memory_size;
int output_range;
UINT32 now_addr; /* current address */
UINT32 now_step; /* currect step */
UINT32 step; /* step */
UINT32 start; /* start address */
UINT32 limit; /* limit address */
UINT32 end; /* end address */
UINT32 delta; /* delta scale */
INT32 volume; /* current volume */
INT32 acc; /* shift Measurement value*/
INT32 adpcmd; /* next Forecast */
INT32 adpcml; /* current value */
INT32 prev_acc; /* leveling value */
UINT8 now_data; /* current rom data */
UINT8 CPU_data; /* current data from reg 08 */
UINT8 portstate; /* port status */
UINT8 control2; /* control reg: SAMPLE, DA/AD, RAM TYPE (x8bit / x1bit), ROM/RAM */
UINT8 portshift; /* address bits shift-left:
** 8 for YM2610,
** 5 for Y8950 and YM2608 */
UINT8 DRAMportshift; /* address bits shift-right:
** 0 for ROM and x8bit DRAMs,
** 3 for x1 DRAMs */
UINT8 memread; /* needed for reading/writing external memory */
/* handlers and parameters for the status flags support */
STATUS_CHANGE_HANDLER status_set_handler;
STATUS_CHANGE_HANDLER status_reset_handler;
/* note that different chips have these flags on different
** bits of the status register
*/
void * status_change_which_chip; /* this chip id */
UINT8 status_change_EOS_bit; /* 1 on End Of Sample (record/playback/cycle time of AD/DA converting has passed)*/
UINT8 status_change_BRDY_bit; /* 1 after recording 2 datas (2x4bits) or after reading/writing 1 data */
UINT8 status_change_ZERO_bit; /* 1 if silence lasts for more than 290 miliseconds on ADPCM recording */
/* neither Y8950 nor YM2608 can generate IRQ when PCMBSY bit changes, so instead of above,
** the statusflag gets ORed with PCM_BSY (below) (on each read of statusflag of Y8950 and YM2608)
*/
UINT8 PCM_BSY; /* 1 when ADPCM is playing; Y8950/YM2608 only */
UINT8 reg[16]; /* adpcm registers */
UINT8 emulation_mode; /* which chip we're emulating */
}YM_DELTAT;
/*void YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT);*/
UINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT);
void YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v);
void YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan,int emulation_mode);
void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT);
void YM_DELTAT_postload(YM_DELTAT *DELTAT,UINT8 *regs);
void YM_DELTAT_savestate(const char *statename,int num,YM_DELTAT *DELTAT);
#endif

2762
sound/mame/ymf262.c Normal file

File diff suppressed because it is too large Load Diff

55
sound/mame/ymf262.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef YMF262_H
#define YMF262_H
#define BUILD_YMF262 (HAS_YMF262)
/* select number of output bits: 8 or 16 */
#define OPL3_SAMPLE_BITS 16
/* compiler dependence */
#ifndef OSD_CPU_H
#define OSD_CPU_H
typedef unsigned char UINT8; /* unsigned 8bit */
typedef unsigned short UINT16; /* unsigned 16bit */
typedef unsigned int UINT32; /* unsigned 32bit */
typedef signed char INT8; /* signed 8bit */
typedef signed short INT16; /* signed 16bit */
typedef signed int INT32; /* signed 32bit */
#endif
typedef stream_sample_t OPL3SAMPLE;
/*
#if (OPL3_SAMPLE_BITS==16)
typedef INT16 OPL3SAMPLE;
#endif
#if (OPL3_SAMPLE_BITS==8)
typedef INT8 OPL3SAMPLE;
#endif
*/
typedef void (*OPL3_TIMERHANDLER)(void *param,int timer,double interval_Sec);
typedef void (*OPL3_IRQHANDLER)(void *param,int irq);
typedef void (*OPL3_UPDATEHANDLER)(void *param,int min_interval_us);
#if BUILD_YMF262
void *YMF262Init(int clock, int rate);
void YMF262Shutdown(void *chip);
void YMF262ResetChip(void *chip);
int YMF262Write(void *chip, int a, int v);
unsigned char YMF262Read(void *chip, int a);
int YMF262TimerOver(void *chip, int c);
void YMF262UpdateOne(void *chip, OPL3SAMPLE **buffers, int length);
void YMF262SetTimerHandler(void *chip, OPL3_TIMERHANDLER TimerHandler, void *param);
void YMF262SetIRQHandler(void *chip, OPL3_IRQHANDLER IRQHandler, void *param);
void YMF262SetUpdateHandler(void *chip, OPL3_UPDATEHANDLER UpdateHandler, void *param);
#endif
#endif /* YMF262_H */

View File

@ -1,74 +1,78 @@
/**
* @file opngencfg.h
* @brief Interface of the OPN generator
*/
#pragma once
enum
{
FMDIV_BITS = 10,
FMDIV_ENT = (1 << FMDIV_BITS),
FMVOL_SFTBIT = 4
};
#if defined(OPNGENX86)
#define SIN_BITS 11
#define EVC_BITS 10
#define ENV_BITS 16
#define FREQ_BITS 21
#define ENVTBL_BIT 14
#define SINTBL_BIT 14
#else
#define SIN_BITS 10
#define EVC_BITS 10
#define ENV_BITS 16
#define FREQ_BITS 21
#define ENVTBL_BIT 14
#define SINTBL_BIT 15
#endif
#define TL_BITS (FREQ_BITS + 2)
#define OPM_OUTSB (TL_BITS + 2 - 16) /* OPM output 16bit */
#define SIN_ENT (1L << SIN_BITS)
#define EVC_ENT (1L << EVC_BITS)
#define EC_ATTACK 0 /* ATTACK start */
#define EC_DECAY (EVC_ENT << ENV_BITS) /* DECAY start */
#define EC_OFF ((2 * EVC_ENT) << ENV_BITS) /* OFF */
enum
{
/* slot number */
OPNSLOT1 = 0,
OPNSLOT2 = 1,
OPNSLOT3 = 2,
OPNSLOT4 = 3,
EM_ATTACK = 4,
EM_DECAY1 = 3,
EM_DECAY2 = 2,
EM_RELEASE = 1,
EM_OFF = 0
};
typedef struct
{
SINT32 calc1024;
SINT32 fmvol;
UINT ratebit;
UINT vr_en;
SINT32 vr_l;
SINT32 vr_r;
SINT32 sintable[SIN_ENT];
SINT32 envtable[EVC_ENT];
SINT32 envcurve[EVC_ENT*2 + 1];
} OPNCFG;
extern OPNCFG opncfg;
/**
* @file opngencfg.h
* @brief Interface of the OPN generator
*/
#pragma once
enum
{
FMDIV_BITS = 10,
FMDIV_ENT = (1 << FMDIV_BITS),
FMVOL_SFTBIT = 4
};
#if defined(OPNGENX86)
#define SIN_BITS 11
#define EVC_BITS 10
#define ENV_BITS 16
#define FREQ_BITS 21
#define ENVTBL_BIT 14
#define SINTBL_BIT 14
#else
#define SIN_BITS 10
#define EVC_BITS 10
#define ENV_BITS 16
#define FREQ_BITS 21
#define ENVTBL_BIT 14
#define SINTBL_BIT 15
#endif
#define TL_BITS (FREQ_BITS + 2)
#define OPM_OUTSB (TL_BITS + 2 - 16) /* OPM output 16bit */
#define SIN_ENT (1L << SIN_BITS)
#define EVC_ENT (1L << EVC_BITS)
#define EC_ATTACK 0 /* ATTACK start */
#define EC_DECAY (EVC_ENT << ENV_BITS) /* DECAY start */
#define EC_OFF ((2 * EVC_ENT) << ENV_BITS) /* OFF */
enum
{
/* slot number */
OPNSLOT1 = 0,
OPNSLOT2 = 1,
OPNSLOT3 = 2,
OPNSLOT4 = 3,
EM_ATTACK = 4,
EM_DECAY1 = 3,
EM_DECAY2 = 2,
EM_RELEASE = 1,
EM_OFF = 0
};
typedef struct
{
SINT32 calc1024;
SINT32 fmvol;
UINT ratebit;
UINT vr_en;
SINT32 vr_l;
SINT32 vr_r;
SINT32 sintable[SIN_ENT];
SINT32 envtable[EVC_ENT];
SINT32 envcurve[EVC_ENT*2 + 1];
#if defined(SUPPORT_FMGEN)
UINT8 usefmgen;
#endif /* SUPPORT_FMGEN */
} OPNCFG;
extern OPNCFG opncfg;

View File

@ -45,6 +45,7 @@ private:
CComboData m_cmbsm; //!< セカンダリ マスタ
CComboData m_cmbss; //!< セカンダリ スレーブ
CWndProc m_chkidebios; //!< Use IDE BIOS
CWndProc m_chkautoidebios; //!< Auto IDE BIOS
CWndProc m_nudrwait; //!< 割り込み(書き込み)ディレイ
CWndProc m_nudwwait; //!< 割り込み(書き込み)ディレイ
};
@ -100,12 +101,22 @@ BOOL CIdeDlg::OnInitDialog()
_stprintf(numbuf, _T("%d"), np2cfg.idewwait);
m_nudwwait.SetWindowTextW(numbuf);
m_chkautoidebios.SubclassDlgItem(IDC_AUTOIDEBIOS, this);
if(np2cfg.autoidebios){
m_chkautoidebios.SendMessage(BM_SETCHECK , BST_CHECKED , 0);
}else{
m_chkautoidebios.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0);
}
m_chkidebios.SubclassDlgItem(IDC_USEIDEBIOS, this);
if(np2cfg.idebios)
if(np2cfg.idebios){
m_chkidebios.SendMessage(BM_SETCHECK , BST_CHECKED , 0);
else
m_chkautoidebios.EnableWindow(TRUE);
}else{
m_chkidebios.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0);
m_chkautoidebios.EnableWindow(FALSE);
}
m_cmbpm.SetFocus();
return FALSE;
@ -163,6 +174,11 @@ void CIdeDlg::OnOK()
np2cfg.idebios = (m_chkidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0);
update |= SYS_UPDATECFG;
}
if (np2cfg.autoidebios != (m_chkautoidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0))
{
np2cfg.autoidebios = (m_chkautoidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0);
update |= SYS_UPDATECFG;
}
sysmng_update(update);
@ -184,6 +200,9 @@ BOOL CIdeDlg::OnCommand(WPARAM wParam, LPARAM lParam)
case IDC_IDE3TYPE:
case IDC_IDE4TYPE:
return TRUE;
case IDC_USEIDEBIOS:
m_chkautoidebios.EnableWindow((m_chkidebios.SendMessage(BM_GETCHECK , 0 , 0) ? TRUE : FALSE));
return TRUE;
}
return FALSE;
}

View File

@ -132,15 +132,19 @@ void opl3_bind(POPL3 opl3)
pExt->Reset();
}
else
{
oplgen_reset(&opl3->oplgen, nBaseClock);
{
#ifndef USE_MAME
oplgen_reset(&opl3->oplgen, nBaseClock);
#endif
}
restore(opl3);
#ifndef USE_MAME
if (pExt == NULL)
{
sound_streamregist(&opl3->oplgen, (SOUNDCB)oplgen_getpcm);
}
}
#endif
keydisp_bindopl3(opl3->s.reg, (cCaps & OPL3_HAS_OPL3) ? 18 : 9, nBaseClock);
}
@ -236,8 +240,10 @@ static void writeRegister(POPL3 opl3, UINT nAddress, REG8 cData)
pExt->WriteRegister(nAddress, cData);
}
else
{
{
#ifndef USE_MAME
sound_sync();
#endif
oplgen_setreg(&opl3->oplgen, nAddress, cData);
}
}
@ -317,8 +323,10 @@ static void writeExtendedRegister(POPL3 opl3, UINT nAddress, REG8 cData)
}
//#if 0
else
{
{
#ifndef USE_MAME
sound_sync();
#endif
oplgen_setreg(&opl3->oplgen, nAddress + 0x100, cData);
}
//#endif

View File

@ -500,6 +500,7 @@ static const PFTBL s_IniItems[] =
PFVAL("IDE3TYPE", PFTYPE_UINT8, &np2cfg.idetype[2]),
PFVAL("IDE4TYPE", PFTYPE_UINT8, &np2cfg.idetype[3]),
PFVAL("IDE_BIOS", PFTYPE_BOOL, &np2cfg.idebios), // ŽÀ‹@IDE BIOSŽg—p
PFVAL("AIDEBIOS", PFTYPE_BOOL, &np2cfg.autoidebios), // 実機IDE BIOS使用を自動設定する
PFVAL("IDERWAIT", PFTYPE_UINT32, &np2cfg.iderwait),
PFVAL("IDEWWAIT", PFTYPE_UINT32, &np2cfg.idewwait),
PFVAL("IDEMWAIT", PFTYPE_UINT32, &np2cfg.idemwait),
@ -527,7 +528,6 @@ static const PFTBL s_IniItems[] =
PFMAX("volume_A", PFTYPE_UINT8, &np2cfg.vol_adpcm, 128),
PFMAX("volume_P", PFTYPE_UINT8, &np2cfg.vol_pcm, 128),
PFMAX("volume_R", PFTYPE_UINT8, &np2cfg.vol_rhythm, 128),
PFMAX("volume_C", PFTYPE_UINT8, &np2cfg.vol_cdda, 128), // CD-DA(kaiE)
PFVAL("Seek_Snd", PFTYPE_BOOL, &np2cfg.MOTOR),
PFMAX("Seek_Vol", PFTYPE_UINT8, &np2cfg.MOTORVOL, 100),

View File

@ -367,6 +367,9 @@ void xmenu_update(HMENU hMenu)
CheckMenuItem(hMenu, IDM_MATE_X_PCM, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_MATE_X_PCM));
CheckMenuItem(hMenu, IDM_SPEAKBOARD, MF_BYCOMMAND | MFCHECK(SOUND_SW == 0x20));
CheckMenuItem(hMenu, IDM_SPARKBOARD, MF_BYCOMMAND | MFCHECK(SOUND_SW == 0x40));
#if defined(SUPPORT_SOUND_SB16)
CheckMenuItem(hMenu, IDM_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SB16));
#endif // defined(SUPPORT_SOUND_SB16)
#if defined(SUPPORT_PX)
CheckMenuItem(hMenu, IDM_PX1, MF_BYCOMMAND | MFCHECK(SOUND_SW == 0x30));
CheckMenuItem(hMenu, IDM_PX2, MF_BYCOMMAND | MFCHECK(SOUND_SW == 0x50));

View File

@ -835,6 +835,25 @@ static void OnCommand(HWND hWnd, WPARAM wParam)
case IDM_SCSI3EJECT:
diskdrv_setsxsi(0x23, NULL);
break;
case IDM_SCSI0STATE:
case IDM_SCSI1STATE:
case IDM_SCSI2STATE:
case IDM_SCSI3STATE:
{
const OEMCHAR *fname;
fname = sxsi_getfilename(uID - IDM_SCSI0STATE + 0x20);
if(!fname || !(*fname)){
fname = diskdrv_getsxsi(uID - IDM_IDE0STATE + 0x20);
}
if(fname && *fname){
TCHAR seltmp[500];
_tcscpy(seltmp, OEMTEXT("/select,"));
_tcscat(seltmp, fname);
ShellExecute(NULL, NULL, OEMTEXT("explorer.exe"), seltmp, NULL, SW_SHOWNORMAL);
}
}
break;
#endif
case IDM_WINDOW:
@ -1097,6 +1116,13 @@ static void OnCommand(HWND hWnd, WPARAM wParam)
np2cfg.SOUND_SW = 0x40;
update |= SYS_UPDATECFG | SYS_UPDATESBOARD;
break;
#if defined(SUPPORT_SOUND_SB16)
case IDM_SB16:
np2cfg.SOUND_SW = SOUNDID_SB16;
update |= SYS_UPDATECFG | SYS_UPDATESBOARD;
break;
#endif // defined(SUPPORT_SOUND_SB16)
#if defined(SUPPORT_PX)
case IDM_PX1:
@ -2444,7 +2470,7 @@ void unloadNP2INI(){
//np2net_shutdown();
#endif
pccore_term();
//pccore_term();
CSoundMng::GetInstance()->Close();
CSoundMng::Deinitialize();

View File

@ -280,6 +280,7 @@
#define IDC_IDERWAIT 19106
#define IDC_SPINIDERWAIT 19107
#define IDC_USEIDEBIOS 19108
#define IDC_AUTOIDEBIOS 19109
#define IDS_APP_NAME2 30001
#define IDS_APP_NAME21 30002
#define IDS_FILENAME_HELP 30003
@ -586,6 +587,7 @@
#define IDM_SOUNDORCHESTRAV 40656
#define IDM_PC9801_86_WSS 40657
#define IDM_MATE_X_PCM 40658
#define IDM_SB16 40659
#define IDM_MEM640 40661
#define IDM_MEM16 40662
#define IDM_MEM36 40663

View File

@ -537,6 +537,7 @@ BEGIN
LTEXT "Interrupt Delay(Write)",IDC_STATIC,8,100,70,8
LTEXT "clock",IDC_STATIC,126,100,32,8
CONTROL "Use IDE BIOS",IDC_USEIDEBIOS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,120,200,10
CONTROL "Auto IDE BIOS",IDC_AUTOIDEBIOS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,134,80,10
DEFPUSHBUTTON "&OK",IDOK,92,130,44,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,140,130,44,14
END
@ -923,6 +924,7 @@ BEGIN
MENUITEM "Sp&ark board", IDM_SPARKBOARD
MENUITEM "Sound &Orchestra", IDM_SOUNDORCHESTRA
MENUITEM "Sound Orchestra-&V", IDM_SOUNDORCHESTRAV
MENUITEM "Sound &Blaster 16", IDM_SB16
MENUITEM "&AMD-98", IDM_AMD98
MENUITEM "&JastSound", IDM_JASTSOUND
MENUITEM SEPARATOR
@ -1111,24 +1113,32 @@ BEGIN
MENUITEM "&Open...", IDM_SCSI0OPEN
MENUITEM SEPARATOR
MENUITEM "&Remove", IDM_SCSI0EJECT
MENUITEM SEPARATOR
MENUITEM " ", IDM_SCSI0STATE
END
POPUP "SCSI #1"
BEGIN
MENUITEM "&Open...", IDM_SCSI1OPEN
MENUITEM SEPARATOR
MENUITEM "&Remove", IDM_SCSI1EJECT
MENUITEM SEPARATOR
MENUITEM " ", IDM_SCSI1STATE
END
POPUP "SCSI #2"
BEGIN
MENUITEM "&Open...", IDM_SCSI2OPEN
MENUITEM SEPARATOR
MENUITEM "&Remove", IDM_SCSI2EJECT
MENUITEM SEPARATOR
MENUITEM " ", IDM_SCSI2STATE
END
POPUP "SCSI #3"
BEGIN
MENUITEM "&Open...", IDM_SCSI3OPEN
MENUITEM SEPARATOR
MENUITEM "&Remove", IDM_SCSI3EJECT
MENUITEM SEPARATOR
MENUITEM " ", IDM_SCSI3STATE
END
END

View File

@ -530,6 +530,7 @@ BEGIN
LTEXT "Interrupt Delay(Write)",IDC_STATIC,8,100,70,8
LTEXT "clock",IDC_STATIC,126,100,32,8
CONTROL "Use IDE BIOS",IDC_USEIDEBIOS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,120,200,10
CONTROL "Auto IDE BIOS",IDC_AUTOIDEBIOS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,134,80,10
DEFPUSHBUTTON "&OK",IDOK,92,130,44,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,140,130,44,14
END
@ -916,6 +917,7 @@ BEGIN
MENUITEM "Sp&ark board", IDM_SPARKBOARD
MENUITEM "Sound &Orchestra", IDM_SOUNDORCHESTRA
MENUITEM "Sound Orchestra-&V", IDM_SOUNDORCHESTRAV
MENUITEM "Sound &Blaster 16", IDM_SB16
MENUITEM "&AMD-98", IDM_AMD98
MENUITEM "&JastSound", IDM_JASTSOUND
MENUITEM SEPARATOR

View File

@ -25,8 +25,8 @@ IDR_MANIFEST IRT_MANIFEST MOVEABLE PURE "..\\np2.mnf"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,8,6,35
PRODUCTVERSION 0,8,6,35
FILEVERSION 0,8,6,36
PRODUCTVERSION 0,8,6,36
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -42,10 +42,10 @@ BEGIN
BLOCK "041103a4"
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileVersion", "0, 8, 6, 35\0"
VALUE "FileVersion", "0, 8, 6, 36\0"
VALUE "LegalCopyright", "ねこさん開発ちーむ\0"
VALUE "ProductVersion", "0, 8, 6, 35\0"
VALUE "ProductVersion", "0, 8, 6, 36\0"
#ifdef _USRDLL
VALUE "FileDescription", "PC-98x1series emulator resource file\0"
VALUE "ProductName", "Neko Project II resource file\0"

View File

@ -529,6 +529,7 @@ BEGIN
LTEXT "割り込み遅延(WRITE)",IDC_STATIC,8,100,70,8
LTEXT "clock",IDC_STATIC,126,100,32,8
CONTROL "実機IDE BIOSを使用",IDC_USEIDEBIOS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,120,200,10
CONTROL "IDE BIOSŽ©“®ON/OFF",IDC_AUTOIDEBIOS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,134,80,10
DEFPUSHBUTTON "&OK",IDOK,92,130,44,14,WS_GROUP
PUSHBUTTON "キャンセル",IDCANCEL,140,130,44,14
END
@ -915,6 +916,7 @@ BEGIN
MENUITEM "Sp&ark board", IDM_SPARKBOARD
MENUITEM "Sound &Orchestra", IDM_SOUNDORCHESTRA
MENUITEM "Sound Orchestra-&V", IDM_SOUNDORCHESTRAV
MENUITEM "Sound &Blaster 16", IDM_SB16
MENUITEM "&AMD-98", IDM_AMD98
MENUITEM "&JastSound", IDM_JASTSOUND
MENUITEM SEPARATOR
@ -1115,24 +1117,32 @@ BEGIN
MENUITEM "開く(&O)...", IDM_SCSI0OPEN
MENUITEM SEPARATOR
MENUITEM "取り外し(&R)...", IDM_SCSI0EJECT
MENUITEM SEPARATOR
MENUITEM " ", IDM_SCSI0STATE
END
POPUP "SCSI #1"
BEGIN
MENUITEM "開く(&O)...", IDM_SCSI1OPEN
MENUITEM SEPARATOR
MENUITEM "取り外し(&R)...", IDM_SCSI1EJECT
MENUITEM SEPARATOR
MENUITEM " ", IDM_SCSI1STATE
END
POPUP "SCSI #2"
BEGIN
MENUITEM "開く(&O)...", IDM_SCSI2OPEN
MENUITEM SEPARATOR
MENUITEM "取り外し(&R)...", IDM_SCSI2EJECT
MENUITEM SEPARATOR
MENUITEM " ", IDM_SCSI2STATE
END
POPUP "SCSI #3"
BEGIN
MENUITEM "開く(&O)...", IDM_SCSI3OPEN
MENUITEM SEPARATOR
MENUITEM "取り外し(&R)...", IDM_SCSI3EJECT
MENUITEM SEPARATOR
MENUITEM " ", IDM_SCSI3STATE
END
END

View File

@ -561,9 +561,9 @@ BRESULT scrnmng_create(UINT8 scrnmode) {
}
}
}
if ((r = DirectDrawCreate(&devguid, &ddraw.ddraw1, NULL)) != DD_OK) {
if ((r = DirectDrawCreate(devlpguid, &ddraw.ddraw1, NULL)) != DD_OK) {
// プライマリで再挑戦
if (DirectDrawCreate(NULL, &ddraw.ddraw1, NULL) != DD_OK) {
if (DirectDrawCreate(np2oscfg.emuddraw ? (LPGUID)DDCREATE_EMULATIONONLY : NULL, &ddraw.ddraw1, NULL) != DD_OK) {
goto scre_err;
}
}
@ -1350,4 +1350,4 @@ void scrnmng_bltwab() {
}
}
#endif
}
}

View File

@ -127,10 +127,13 @@ COMMON_SOURCES= $(real_topsrcdir)/x11/main.c \
$(real_topsrcdir)/cbus/board26k.c \
$(real_topsrcdir)/cbus/board86.c \
$(real_topsrcdir)/cbus/boardpx.c \
$(real_topsrcdir)/cbus/boardsb16.c \
$(real_topsrcdir)/cbus/boardso.c \
$(real_topsrcdir)/cbus/boardspb.c \
$(real_topsrcdir)/cbus/boardx2.c \
$(real_topsrcdir)/cbus/cs4231io.c \
$(real_topsrcdir)/cbus/ct1741io.c \
$(real_topsrcdir)/cbus/ct1745io.c \
$(real_topsrcdir)/cbus/pcm86io.c \
$(real_topsrcdir)/cbus/sasiio.c \
$(real_topsrcdir)/cbus/scsiio.c \
@ -250,6 +253,9 @@ COMMON_SOURCES= $(real_topsrcdir)/x11/main.c \
$(real_topsrcdir)/sound/fmgen/fmgen_opm.cpp \
$(real_topsrcdir)/sound/fmgen/fmgen_opna.cpp \
$(real_topsrcdir)/sound/fmgen/fmgen_psg.cpp \
$(real_topsrcdir)/sound/mame/fmopl.c \
$(real_topsrcdir)/sound/mame/ymdeltat.c \
$(real_topsrcdir)/sound/mame/ymf262.c \
\
$(real_topsrcdir)/vram/vram.c \
$(real_topsrcdir)/vram/scrndraw.c \
@ -298,7 +304,7 @@ AM_CPPFLAGS= -I$(real_topsrcdir) \
-I$(real_topsrcdir)/vram \
$(GTK_CFLAGS) $(SDL_CFLAGS) $(LIBUSB1_CFLAGS) \
$(X11_CFLAGS) $(XEXT_CFLAGS) \
-DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DSUPPORT_NET -DSUPPORT_LGY98
-DSUPPORT_LARGE_HDD -DSUPPORT_VPCVHD -DSUPPORT_KAI_IMAGES -DHOOK_SYSKEY -DALLOW_MULTIRUN -DSUPPORT_NET -DSUPPORT_LGY98 -DUSE_MAME -DSUPPORT_SOUND_SB16
if BUILD_ALL
AM_CPPFLAGS+= -DX11_BUILD_ALL
endif

4
x11/compiler.h Executable file → Normal file
View File

@ -86,13 +86,17 @@
#include <glib.h>
typedef gint32 SINT;
typedef gint32 INT;
typedef guint32 UINT;
typedef gint8 SINT8;
typedef gint8 INT8;
typedef gint16 SINT16;
typedef gint16 INT16;
typedef gint32 SINT32;
typedef gint32 INT32;
typedef gint64 SINT64;
typedef gint64 INT64;
typedef guint8 UINT8;
typedef guint16 UINT16;

View File

@ -57,6 +57,7 @@ static const struct {
{ "ADPCM", &np2cfg.vol_adpcm, 0.0, 128.0 },
{ "PCM", &np2cfg.vol_pcm, 0.0, 128.0 },
{ "Rhythm", &np2cfg.vol_rhythm, 0.0, 128.0 },
{ "CD-DA", &np2cfg.davolume, 0.0, 255.0 },
};
static GObject *mixer_adj[NELEMENTS(mixer_vol_tbl)];
@ -625,9 +626,10 @@ mixer_default_button_clicked(GtkButton *b, gpointer d)
{
int i;
for (i = 0; i < NELEMENTS(mixer_vol_tbl); i++) {
for (i = 0; i < NELEMENTS(mixer_vol_tbl) - 1; i++) {
gtk_adjustment_set_value(GTK_ADJUSTMENT(mixer_adj[i]), 64.0);
}
gtk_adjustment_set_value(GTK_ADJUSTMENT(mixer_adj[5]), 128.0);
#if defined(SUPPORT_FMGEN)
OPNA_SetVolumeFM(g_opna[0].fmgen, pow((double)np2cfg.vol_fm / 128, 0.12) * (20 + 192) - 192);
OPNA_SetVolumePSG(g_opna[0].fmgen, pow((double)np2cfg.vol_ssg / 128, 0.12) * (20 + 192) - 192);

View File

@ -271,10 +271,13 @@ static GtkRadioActionEntry soundboard_entries[] = {
{ "pc-9801-26k-86", NULL, "PC-9801-26_K + 86", NULL, NULL, 0x06 },
{ "pc-9801-86-cb", NULL, "PC-9801-86 + _Chibi-oto", NULL, NULL, 0x14 },
{ "pc-9801-118", NULL, "PC-9801-11_8", NULL, NULL, 0x08 },
{ "pc-9801-86-mx", NULL, "PC-9801-86 + Mate-X PCM(B460)", NULL, NULL, 0x64 },
{ "pc-9801-mx", NULL, "Mate-X PCM(B460)", NULL, NULL, 0x60 },
{ "speakboard", NULL, "S_peak board", NULL, NULL, 0x20 },
{ "sparkboard", NULL, "Sp_ark board", NULL, NULL, 0x40 },
{ "sndorchestra", NULL, "Sound Orchestra", NULL, NULL, 0x32 },
{ "sndorchestrav", NULL, "Sound Orchestra-V", NULL, NULL, 0x82 },
{ "sb16", NULL, "Sound Blaster 16", NULL, NULL, 0x41 },
{ "amd98", NULL, "_AMD98", NULL, NULL, 0x80 },
#if defined(SUPPORT_PX)
{ "px1", NULL, "Otomi-chanx2", NULL, NULL, 0x30 },
@ -469,10 +472,13 @@ static const gchar *ui_info =
" <menuitem action='pc-9801-26k-86'/>\n"
" <menuitem action='pc-9801-86-cb'/>\n"
" <menuitem action='pc-9801-118'/>\n"
" <menuitem action='pc-9801-86-mx'/>\n"
" <menuitem action='pc-9801-mx'/>\n"
" <menuitem action='speakboard'/>\n"
" <menuitem action='sparkboard'/>\n"
" <menuitem action='sndorchestra'/>\n"
" <menuitem action='sndorchestrav'/>\n"
" <menuitem action='sb16'/>\n"
" <menuitem action='amd98'/>\n"
#if defined(SUPPORT_PX)
" <menuitem action='px1'/>\n"

View File

@ -541,6 +541,19 @@ static INITBL iniitem[] = {
{"HDD1FILE", INITYPE_STR, np2cfg.sasihdd[0], MAX_PATH},
{"HDD2FILE", INITYPE_STR, np2cfg.sasihdd[1], MAX_PATH},
#if defined(SUPPORT_IDEIO)
{"HDD3FILE", INIRO_STR, np2cfg.sasihdd[2], MAX_PATH},
{"HDD4FILE", INIRO_STR, np2cfg.sasihdd[3], MAX_PATH},
{"HDD1TYPE", INIRO_UINT8, &np2cfg.idetype[2], 0},
{"HDD2TYPE", INIRO_UINT8, &np2cfg.idetype[2], 0},
{"HDD3TYPE", INIRO_UINT8, &np2cfg.idetype[2], 0},
{"HDD4TYPE", INIRO_UINT8, &np2cfg.idetype[2], 0},
{"IDE_BIOS", INIRO_BOOL, &np2cfg.idebios, 0},
{"AIDEBIOS", INIRO_BOOL, &np2cfg.autoidebios, 0},
{"IDERWAIT", INITYPE_UINT32, &np2cfg.iderwait, 0},
{"IDEWWAIT", INITYPE_UINT32, &np2cfg.idewwait, 0},
{"IDEMWAIT", INITYPE_UINT32, &np2cfg.idemwait, 0},
#endif
{"SampleHz", INITYPE_UINT32, &np2cfg.samplingrate, 0},
{"Latencys", INITYPE_UINT16, &np2cfg.delayms, 0},
@ -563,7 +576,7 @@ static INITBL iniitem[] = {
{"volume_A", INIMAX_UINT8, &np2cfg.vol_adpcm, 128},
{"volume_P", INIMAX_UINT8, &np2cfg.vol_pcm, 128},
{"volume_R", INIMAX_UINT8, &np2cfg.vol_rhythm, 128},
{"volume_C", INIMAX_UINT8, &np2cfg.vol_cdda, 128},
{"DAVOLUME", INIMAX_UINT8, &np2cfg.davolume, 128},
{"usefmgen", INITYPE_BOOL, &np2cfg.usefmgen, 0},