#include "opna.h"
#include "fmgeninl.h"
+#include "../../common.h"
#include "../../fileio.h"
+#include "../../statesub.h"
+
+
#define BUILD_OPN
#define BUILD_OPNA
#define BUILD_OPNB
+#define BUILD_OPN2
// TOFIX:
// ---------------------------------------------------------------------------
// OPNBase
-#if defined(BUILD_OPN) || defined(BUILD_OPNA) || defined (BUILD_OPNB)
+#if defined(BUILD_OPN) || defined(BUILD_OPNA) || defined (BUILD_OPNB) || defined(BUILD_OPN2)
uint32 OPNBase::lfotable[8]; // OPNA/B \97p
{
is_ay3_891x = false;
prescale = 0;
+ static int __num = 0;
+ chip_num = __num++;
}
// \83p\83\89\83\81\81[\83^\83Z\83b\83g
//
#define OPN_BASE_STATE_VERSION 4
+void OPNBase::DeclState(void *f)
+{
+ Timer::DeclState(f);
+ DECL_STATE_ENTRY_INT32(fmvolume_l);
+ DECL_STATE_ENTRY_INT32(fmvolume_r);
+ DECL_STATE_ENTRY_UINT32(clock);
+ DECL_STATE_ENTRY_UINT32(rate);
+ DECL_STATE_ENTRY_UINT32(psgrate);
+ DECL_STATE_ENTRY_UINT32(status);
+ DECL_STATE_ENTRY_BOOL(interrupt);
+ DECL_STATE_ENTRY_UINT8(prescale);
+ chip.DeclState(f);
+ psg.DeclState(f);
+}
+
void OPNBase::SaveState(void *f)
{
FILEIO *state_fio = (FILEIO *)f;
- state_fio->FputUint32_BE(OPN_BASE_STATE_VERSION);
-
- Timer::SaveState(f);
- state_fio->FputInt32_BE(fmvolume_l);
- state_fio->FputInt32_BE(fmvolume_r);
- state_fio->FputUint32_BE(clock);
- state_fio->FputUint32_BE(rate);
- state_fio->FputUint32_BE(psgrate);
- state_fio->FputUint32_BE(status);
- state_fio->FputBool(interrupt);
- state_fio->FputUint8(prescale);
+ if(state_entry != NULL) {
+ state_entry->save_state(state_fio);
+ }
chip.SaveState(f);
psg.SaveState(f);
+// state_fio->FputUint32_BE(OPN_BASE_STATE_VERSION);
+
+// Timer::SaveState(f);
+// state_fio->FputInt32_BE(fmvolume_l);
+// state_fio->FputInt32_BE(fmvolume_r);
+// state_fio->FputUint32_BE(clock);
+// state_fio->FputUint32_BE(rate);
+// state_fio->FputUint32_BE(psgrate);
+// state_fio->FputUint32_BE(status);
+// state_fio->FputBool(interrupt);
+// state_fio->FputUint8(prescale);
}
bool OPNBase::LoadState(void *f)
{
FILEIO *state_fio = (FILEIO *)f;
- if(state_fio->FgetUint32_BE() != OPN_BASE_STATE_VERSION) {
- return false;
- }
- if(!Timer::LoadState(f)) {
- return false;
+ bool mb = false;
+ if(state_entry != NULL) {
+ mb = state_entry->load_state(state_fio);
}
- fmvolume_l = state_fio->FgetInt32_BE();
- fmvolume_r = state_fio->FgetInt32_BE();
- clock = state_fio->FgetUint32_BE();
- rate = state_fio->FgetUint32_BE();
- psgrate = state_fio->FgetUint32_BE();
- status = state_fio->FgetUint32_BE();
- interrupt = state_fio->FgetBool();
- prescale = state_fio->FgetUint8();
+ if(!mb) return false;
+// if(state_fio->FgetUint32_BE() != OPN_BASE_STATE_VERSION) {
+// return false;
+// }
+// if(!Timer::LoadState(f)) {
+// return false;
+// }
+// fmvolume_l = state_fio->FgetInt32_BE();
+// fmvolume_r = state_fio->FgetInt32_BE();
+// clock = state_fio->FgetUint32_BE();
+// rate = state_fio->FgetUint32_BE();
+// psgrate = state_fio->FgetUint32_BE();
+// status = state_fio->FgetUint32_BE();
+// interrupt = state_fio->FgetBool();
+// prescale = state_fio->FgetUint8();
{
// Make force-restore around prescaler and timers. 20180625 K.O
uint bak = prescale;
return true;
}
-#endif // defined(BUILD_OPN) || defined(BUILD_OPNA) || defined (BUILD_OPNB)
+#endif // defined(BUILD_OPN) || defined(BUILD_OPNA) || defined (BUILD_OPNB) || defined(BUILD_OPN2)
// ---------------------------------------------------------------------------
// YM2203
//
#define OPN_STATE_VERSION 2
-void OPN::SaveState(void *f)
+void OPN::DeclState(void *f)
{
- FILEIO *state_fio = (FILEIO *)f;
-
- state_fio->FputUint32_BE(OPN_STATE_VERSION);
+
+ p_logger = (CSP_Logger *)f;
+ state_entry = new csp_state_utils(OPN_STATE_VERSION, chip_num, _T("FMGEN::OPN::"), p_logger);
+
+ OPNBase::DeclState(f);
- OPNBase::SaveState(f);
for(int i = 0; i < 3; i++) {
- state_fio->FputUint32_BE(fnum[i]);
+ DECL_STATE_ENTRY_UINT32_MEMBER((fnum[i]), i);
+ DECL_STATE_ENTRY_UINT32_MEMBER((fnum3[i]), i);
}
+ DECL_STATE_ENTRY_1D_ARRAY(fnum2, sizeof(fnum2));
for(int i = 0; i < 3; i++) {
- state_fio->FputUint32_BE(fnum3[i]);
- }
- //state_fio->Fwrite(fnum, sizeof(fnum), 1);
- //state_fio->Fwrite(fnum3, sizeof(fnum3), 1);
- state_fio->Fwrite(fnum2, sizeof(fnum2), 1);
+ ch[i].DeclState(f);
+ }
+}
+
+void OPN::SaveState(void *f)
+{
+ FILEIO *state_fio = (FILEIO *)f;
+ OPNBase::SaveState(f);
+// state_fio->FputUint32_BE(OPN_STATE_VERSION);
+//
+// OPNBase::SaveState(f);
+// for(int i = 0; i < 3; i++) {
+// state_fio->FputUint32_BE(fnum[i]);
+// }
+// for(int i = 0; i < 3; i++) {
+// state_fio->FputUint32_BE(fnum3[i]);
+// }
+// //state_fio->Fwrite(fnum, sizeof(fnum), 1);
+// //state_fio->Fwrite(fnum3, sizeof(fnum3), 1);
+// state_fio->Fwrite(fnum2, sizeof(fnum2), 1);
for(int i = 0; i < 3; i++) {
ch[i].SaveState(f);
}
{
FILEIO *state_fio = (FILEIO *)f;
- if(state_fio->FgetUint32_BE() != OPN_STATE_VERSION) {
- return false;
- }
- if(!OPNBase::LoadState(f)) {
- return false;
- }
- for(int i = 0; i < 3; i++) {
- fnum[i] = state_fio->FgetUint32_BE();
- }
- for(int i = 0; i < 3; i++) {
- fnum3[i] = state_fio->FgetUint32_BE();
- }
- //state_fio->Fread(fnum, sizeof(fnum), 1);
- //state_fio->Fread(fnum3, sizeof(fnum3), 1);
- state_fio->Fread(fnum2, sizeof(fnum2), 1);
+ bool mb = false;
+ mb = OPNBase::LoadState(f);
+ if(!mb) return false;
+// if(state_fio->FgetUint32_BE() != OPN_STATE_VERSION) {
+// return false;
+// }
+// if(!OPNBase::LoadState(f)) {
+// return false;
+// }
+// for(int i = 0; i < 3; i++) {
+// fnum[i] = state_fio->FgetUint32_BE();
+// }
+// for(int i = 0; i < 3; i++) {
+// fnum3[i] = state_fio->FgetUint32_BE();
+// }
+// //state_fio->Fread(fnum, sizeof(fnum), 1);
+// //state_fio->Fread(fnum3, sizeof(fnum3), 1);
+// state_fio->Fread(fnum2, sizeof(fnum2), 1);
for(int i = 0; i < 3; i++) {
if(!ch[i].LoadState(f)) {
return false;
//
#define OPNA_BASE_STATE_VERSION 2
-void OPNABase::SaveState(void *f)
+void OPNABase::DeclState(void *f)
{
- FILEIO *state_fio = (FILEIO *)f;
-
- state_fio->FputUint32_BE(OPNA_BASE_STATE_VERSION);
+
+ OPNBase::DeclState(f);
- OPNBase::SaveState(f);
- state_fio->Fwrite(pan, sizeof(pan), 1);
- state_fio->Fwrite(fnum2, sizeof(fnum2), 1);
- state_fio->FputUint8(reg22);
- state_fio->FputUint32_BE(reg29);
- state_fio->FputUint32_BE(stmask);
- state_fio->FputUint32_BE(statusnext);
- state_fio->FputUint32_BE(lfocount);
- state_fio->FputUint32_BE(lfodcount);
+ DECL_STATE_ENTRY_1D_ARRAY(pan, sizeof(pan));
+ DECL_STATE_ENTRY_1D_ARRAY(fnum2, sizeof(fnum2));
+ DECL_STATE_ENTRY_UINT8(reg22);
+ DECL_STATE_ENTRY_UINT32(reg29);
+ DECL_STATE_ENTRY_UINT32(stmask);
+ DECL_STATE_ENTRY_UINT32(statusnext);
+ DECL_STATE_ENTRY_UINT32(lfocount);
+ DECL_STATE_ENTRY_UINT32(lfodcount);
//state_fio->Fwrite(fnum, sizeof(fnum), 1);
//state_fio->Fwrite(fnum3, sizeof(fnum3), 1);
for(int i = 0; i < 6; i++) {
- state_fio->FputUint32_BE(fnum[i]);
+ DECL_STATE_ENTRY_UINT32_MEMBER((fnum[i]), i);
}
for(int i = 0; i < 3; i++) {
- state_fio->FputUint32_BE(fnum3[i]);
+ DECL_STATE_ENTRY_UINT32_MEMBER((fnum3[i]), i);
}
- state_fio->Fwrite(adpcmbuf, 0x40000, 1);
- state_fio->FputUint32_BE(adpcmmask);
- state_fio->FputUint32_BE(adpcmnotice);
- state_fio->FputUint32_BE(startaddr);
- state_fio->FputUint32_BE(stopaddr);
- state_fio->FputUint32_BE(memaddr);
- state_fio->FputUint32_BE(limitaddr);
- state_fio->FputInt32_BE(adpcmlevel);
- state_fio->FputInt32_BE(adpcmvolume_l);
- state_fio->FputInt32_BE(adpcmvolume_r);
- state_fio->FputInt32_BE(adpcmvol_l);
- state_fio->FputInt32_BE(adpcmvol_r);
- state_fio->FputUint32_BE(deltan);
- state_fio->FputInt32_BE(adplc);
- state_fio->FputInt32_BE(adpld);
- state_fio->FputUint32_BE(adplbase);
- state_fio->FputInt32_BE(adpcmx);
- state_fio->FputInt32_BE(adpcmd);
- state_fio->FputInt32_BE(adpcmout_l);
- state_fio->FputInt32_BE(adpcmout_r);
- state_fio->FputInt32_BE(apout0_l);
- state_fio->FputInt32_BE(apout0_r);
- state_fio->FputInt32_BE(apout1_l);
- state_fio->FputInt32_BE(apout1_r);
- state_fio->FputUint32_BE(adpcmreadbuf);
- state_fio->FputBool(adpcmplay);
- state_fio->FputInt8(granuality);
- state_fio->FputBool(adpcmmask_);
- state_fio->FputUint8(control1);
- state_fio->FputUint8(control2);
- state_fio->Fwrite(adpcmreg, sizeof(adpcmreg), 1);
- state_fio->FputInt32_BE(rhythmmask_);
+ DECL_STATE_ENTRY_1D_ARRAY(adpcmbuf, 0x40000);
+ DECL_STATE_ENTRY_UINT32(adpcmmask);
+ DECL_STATE_ENTRY_UINT32(adpcmnotice);
+ DECL_STATE_ENTRY_UINT32(startaddr);
+ DECL_STATE_ENTRY_UINT32(stopaddr);
+ DECL_STATE_ENTRY_UINT32(memaddr);
+ DECL_STATE_ENTRY_UINT32(limitaddr);
+ DECL_STATE_ENTRY_INT32(adpcmlevel);
+ DECL_STATE_ENTRY_INT32(adpcmvolume_l);
+ DECL_STATE_ENTRY_INT32(adpcmvolume_r);
+ DECL_STATE_ENTRY_INT32(adpcmvol_l);
+ DECL_STATE_ENTRY_INT32(adpcmvol_r);
+ DECL_STATE_ENTRY_UINT32(deltan);
+ DECL_STATE_ENTRY_INT32(adplc);
+ DECL_STATE_ENTRY_INT32(adpld);
+ DECL_STATE_ENTRY_UINT32(adplbase);
+ DECL_STATE_ENTRY_INT32(adpcmx);
+ DECL_STATE_ENTRY_INT32(adpcmd);
+ DECL_STATE_ENTRY_INT32(adpcmout_l);
+ DECL_STATE_ENTRY_INT32(adpcmout_r);
+ DECL_STATE_ENTRY_INT32(apout0_l);
+ DECL_STATE_ENTRY_INT32(apout0_r);
+ DECL_STATE_ENTRY_INT32(apout1_l);
+ DECL_STATE_ENTRY_INT32(apout1_r);
+ DECL_STATE_ENTRY_UINT32(adpcmreadbuf);
+ DECL_STATE_ENTRY_BOOL(adpcmplay);
+ DECL_STATE_ENTRY_INT8(granuality);
+ DECL_STATE_ENTRY_BOOL(adpcmmask_);
+ DECL_STATE_ENTRY_UINT8(control1);
+ DECL_STATE_ENTRY_UINT8(control2);
+ DECL_STATE_ENTRY_1D_ARRAY(adpcmreg, sizeof(adpcmreg));
+ DECL_STATE_ENTRY_INT32(rhythmmask_);
+
+ for(int i = 0; i < 6; i++) {
+ ch[i].DeclState(f);
+ }
+}
+void OPNABase::SaveState(void *f)
+{
+ FILEIO *state_fio = (FILEIO *)f;
+ if(state_entry != NULL) {
+ state_entry->save_state(state_fio);
+ }
+ chip.SaveState(f);
+ psg.SaveState(f);
+
+// state_fio->FputUint32_BE(OPNA_BASE_STATE_VERSION);
+
+// OPNBase::SaveState(f);
+// state_fio->Fwrite(pan, sizeof(pan), 1);
+// state_fio->Fwrite(fnum2, sizeof(fnum2), 1);
+// state_fio->FputUint8(reg22);
+// state_fio->FputUint32_BE(reg29);
+// state_fio->FputUint32_BE(stmask);
+// state_fio->FputUint32_BE(statusnext);
+// state_fio->FputUint32_BE(lfocount);
+// state_fio->FputUint32_BE(lfodcount);
+// //state_fio->Fwrite(fnum, sizeof(fnum), 1);
+// //state_fio->Fwrite(fnum3, sizeof(fnum3), 1);
+// for(int i = 0; i < 6; i++) {
+// state_fio->FputUint32_BE(fnum[i]);
+// }
+// for(int i = 0; i < 3; i++) {
+// state_fio->FputUint32_BE(fnum3[i]);
+// }
+// state_fio->Fwrite(adpcmbuf, 0x40000, 1);
+// state_fio->FputUint32_BE(adpcmmask);
+// state_fio->FputUint32_BE(adpcmnotice);
+// state_fio->FputUint32_BE(startaddr);
+// state_fio->FputUint32_BE(stopaddr);
+// state_fio->FputUint32_BE(memaddr);
+// state_fio->FputUint32_BE(limitaddr);
+// state_fio->FputInt32_BE(adpcmlevel);
+// state_fio->FputInt32_BE(adpcmvolume_l);
+// state_fio->FputInt32_BE(adpcmvolume_r);
+// state_fio->FputInt32_BE(adpcmvol_l);
+// state_fio->FputInt32_BE(adpcmvol_r);
+// state_fio->FputUint32_BE(deltan);
+// state_fio->FputInt32_BE(adplc);
+// state_fio->FputInt32_BE(adpld);
+// state_fio->FputUint32_BE(adplbase);
+// state_fio->FputInt32_BE(adpcmx);
+// state_fio->FputInt32_BE(adpcmd);
+// state_fio->FputInt32_BE(adpcmout_l);
+// state_fio->FputInt32_BE(adpcmout_r);
+// state_fio->FputInt32_BE(apout0_l);
+// state_fio->FputInt32_BE(apout0_r);
+// state_fio->FputInt32_BE(apout1_l);
+// state_fio->FputInt32_BE(apout1_r);
+// state_fio->FputUint32_BE(adpcmreadbuf);
+// state_fio->FputBool(adpcmplay);
+// state_fio->FputInt8(granuality);
+// state_fio->FputBool(adpcmmask_);
+// state_fio->FputUint8(control1);
+// state_fio->FputUint8(control2);
+// state_fio->Fwrite(adpcmreg, sizeof(adpcmreg), 1);
+// state_fio->FputInt32_BE(rhythmmask_);
for(int i = 0; i < 6; i++) {
ch[i].SaveState(f);
}
{
FILEIO *state_fio = (FILEIO *)f;
- if(state_fio->FgetUint32_BE() != OPNA_BASE_STATE_VERSION) {
+ bool mb = false;
+ if(state_entry != NULL) {
+ mb = state_entry->load_state(state_fio);
+ }
+ if(!mb) return false;
+ {
+ // Make force-restore around prescaler and timers. 20180625 K.O
+ uint bak = prescale;
+ prescale = 10;
+ SetPrescaler(bak);
+ }
+ if(!chip.LoadState(f)) {
return false;
}
- if(!OPNBase::LoadState(f)) {
+ if(!psg.LoadState(f)) {
return false;
}
- state_fio->Fread(pan, sizeof(pan), 1);
- state_fio->Fread(fnum2, sizeof(fnum2), 1);
- reg22 = state_fio->FgetUint8();
- reg29 = state_fio->FgetUint32_BE();
- stmask = state_fio->FgetUint32_BE();
- statusnext = state_fio->FgetUint32_BE();
- lfocount = state_fio->FgetUint32_BE();
- lfodcount = state_fio->FgetUint32_BE();
- //state_fio->Fread(fnum, sizeof(fnum), 1);
- //state_fio->Fread(fnum3, sizeof(fnum3), 1);
- for(int i = 0; i < 6; i++) {
- fnum[i] = state_fio->FgetUint32_BE();
- }
- for(int i = 0; i < 3; i++) {
- fnum3[i] = state_fio->FgetUint32_BE();
- }
- state_fio->Fread(adpcmbuf, 0x40000, 1);
- adpcmmask = state_fio->FgetUint32_BE();
- adpcmnotice = state_fio->FgetUint32_BE();
- startaddr = state_fio->FgetUint32_BE();
- stopaddr = state_fio->FgetUint32_BE();
- memaddr = state_fio->FgetUint32_BE();
- limitaddr = state_fio->FgetUint32_BE();
- adpcmlevel = state_fio->FgetInt32_BE();
- adpcmvolume_l = state_fio->FgetInt32_BE();
- adpcmvolume_r = state_fio->FgetInt32_BE();
- adpcmvol_l = state_fio->FgetInt32_BE();
- adpcmvol_r = state_fio->FgetInt32_BE();
- deltan = state_fio->FgetUint32_BE();
- adplc = state_fio->FgetInt32_BE();
- adpld = state_fio->FgetInt32_BE();
- adplbase = state_fio->FgetUint32_BE();
- adpcmx = state_fio->FgetInt32_BE();
- adpcmd = state_fio->FgetInt32_BE();
- adpcmout_l = state_fio->FgetInt32_BE();
- adpcmout_r = state_fio->FgetInt32_BE();
- apout0_l = state_fio->FgetInt32_BE();
- apout0_r = state_fio->FgetInt32_BE();
- apout1_l = state_fio->FgetInt32_BE();
- apout1_r = state_fio->FgetInt32_BE();
- adpcmreadbuf = state_fio->FgetUint32_BE();
- adpcmplay = state_fio->FgetBool();
- granuality = state_fio->FgetInt8();
- adpcmmask_ = state_fio->FgetBool();
- control1 = state_fio->FgetUint8();
- control2 = state_fio->FgetUint8();
- state_fio->Fread(adpcmreg, sizeof(adpcmreg), 1);
- rhythmmask_ = state_fio->FgetInt32_BE();
+// if(state_fio->FgetUint32_BE() != OPNA_BASE_STATE_VERSION) {
+// return false;
+// }
+// if(!OPNBase::LoadState(f)) {
+// return false;
+// }
+// state_fio->Fread(pan, sizeof(pan), 1);
+// state_fio->Fread(fnum2, sizeof(fnum2), 1);
+// reg22 = state_fio->FgetUint8();
+// reg29 = state_fio->FgetUint32_BE();
+// stmask = state_fio->FgetUint32_BE();
+// statusnext = state_fio->FgetUint32_BE();
+// lfocount = state_fio->FgetUint32_BE();
+// lfodcount = state_fio->FgetUint32_BE();
+// //state_fio->Fread(fnum, sizeof(fnum), 1);
+// //state_fio->Fread(fnum3, sizeof(fnum3), 1);
+// for(int i = 0; i < 6; i++) {
+// fnum[i] = state_fio->FgetUint32_BE();
+// }
+// for(int i = 0; i < 3; i++) {
+// fnum3[i] = state_fio->FgetUint32_BE();
+// }
+// state_fio->Fread(adpcmbuf, 0x40000, 1);
+// adpcmmask = state_fio->FgetUint32_BE();
+// adpcmnotice = state_fio->FgetUint32_BE();
+// startaddr = state_fio->FgetUint32_BE();
+// stopaddr = state_fio->FgetUint32_BE();
+// memaddr = state_fio->FgetUint32_BE();
+// limitaddr = state_fio->FgetUint32_BE();
+// adpcmlevel = state_fio->FgetInt32_BE();
+// adpcmvolume_l = state_fio->FgetInt32_BE();
+// adpcmvolume_r = state_fio->FgetInt32_BE();
+// adpcmvol_l = state_fio->FgetInt32_BE();
+// adpcmvol_r = state_fio->FgetInt32_BE();
+// deltan = state_fio->FgetUint32_BE();
+// adplc = state_fio->FgetInt32_BE();
+// adpld = state_fio->FgetInt32_BE();
+// adplbase = state_fio->FgetUint32_BE();
+// adpcmx = state_fio->FgetInt32_BE();
+// adpcmd = state_fio->FgetInt32_BE();
+// adpcmout_l = state_fio->FgetInt32_BE();
+// adpcmout_r = state_fio->FgetInt32_BE();
+// apout0_l = state_fio->FgetInt32_BE();
+// apout0_r = state_fio->FgetInt32_BE();
+// apout1_l = state_fio->FgetInt32_BE();
+// apout1_r = state_fio->FgetInt32_BE();
+// adpcmreadbuf = state_fio->FgetUint32_BE();
+// adpcmplay = state_fio->FgetBool();
+// granuality = state_fio->FgetInt8();
+// adpcmmask_ = state_fio->FgetBool();
+// control1 = state_fio->FgetUint8();
+// control2 = state_fio->FgetUint8();
+/// state_fio->Fread(adpcmreg, sizeof(adpcmreg), 1);
+// rhythmmask_ = state_fio->FgetInt32_BE();
for(int i = 0; i < 6; i++) {
if(!ch[i].LoadState(f)) {
return false;
FILEIO file;
uint32 fsize;
_TCHAR buf[_MAX_PATH] = _T("");
+ memset(buf, 0x00, sizeof(buf));
if (path)
- _tcsncpy(buf, path, _MAX_PATH);
- _tcsncat(buf, _T("2608_"), _MAX_PATH);
- _tcsncat(buf, rhythmname[i], _MAX_PATH);
- _tcsncat(buf, _T(".WAV"), _MAX_PATH);
+ _tcsncpy(buf, path, _MAX_PATH - 1);
+ _tcsncat(buf, _T("2608_"), _MAX_PATH - 1);
+ _tcsncat(buf, rhythmname[i], _MAX_PATH- 1);
+ _tcsncat(buf, _T(".WAV"), _MAX_PATH - 1);
if (!file.Fopen(buf, FILEIO_READ_BINARY))
{
if (i != 5)
break;
- if (path)
- _tcsncpy(buf, path, _MAX_PATH);
- _tcsncpy(buf, _T("2608_RYM.WAV"), _MAX_PATH);
+ memset(buf, 0x00, sizeof(buf));
+ if (path) {
+ _tcsncpy(buf, path, _MAX_PATH - 1);
+ }
+ _tcsncat(buf, _T("2608_RYM.WAV"), _MAX_PATH - 1);
if (!file.Fopen(buf, FILEIO_READ_BINARY))
break;
}
- struct
- {
- uint32 chunksize;
- uint16 tag;
- uint16 nch;
- uint32 rate;
- uint32 avgbytes;
- uint16 align;
- uint16 bps;
- uint16 size;
- } whdr;
-
- file.Fseek(0x10, FILEIO_SEEK_SET);
+ wav_header_t whdr;
+ wav_chunk_t chunk;
+
file.Fread(&whdr, sizeof(whdr), 1);
uint8 subchunkname[4];
- fsize = 4 + whdr.chunksize - sizeof(whdr);
- do
+ bool is_eof = false;
+ file.Fseek(EndianFromLittle_DWORD(whdr.fmt_chunk.size) - 16, FILEIO_SEEK_CUR);
+ while(1)
{
- file.Fseek(fsize, FILEIO_SEEK_CUR);
- file.Fread(&subchunkname, 4, 1);
- file.Fread(&fsize, 4, 1);
- } while (memcmp("data", subchunkname, 4));
-
+ if(file.Fread(&chunk, sizeof(chunk), 1) != 1) {
+ is_eof = true;
+ break;
+ }
+ if(strncmp(chunk.id, "data", 4) == 0) {
+ break;
+ }
+ file.Fseek(EndianFromLittle_DWORD(chunk.size), FILEIO_SEEK_CUR);
+ }
+ if(is_eof) {
+// fsize = 8192;
+// rhythm[i].rate = whdr.sample_rate;
+// rhythm[i].step = rhythm[i].rate * 1024 / rate;
+// rhythm[i].pos = rhythm[i].size = fsize * 1024;
+// delete rhythm[i].sample;
+// rhythm[i].sample = new int16[fsize];
+// memset(rhythm[i].sample, 0x00, fsize * 2);
+ file.Fclose();
+ break;
+ }
+ fsize = EndianFromLittle_DWORD(chunk.size);
+
fsize /= 2;
- if (fsize >= 0x100000 || whdr.tag != 1 || whdr.nch != 1)
+ if ((fsize >= 0x100000) || (EndianFromLittle_WORD(whdr.format_id) != 1) || (EndianFromLittle_WORD(whdr.channels) != 1))
break;
fsize = Max(fsize, (1<<31)/1024);
rhythm[i].sample = new int16[fsize];
if (!rhythm[i].sample)
break;
+ for(int __iptr = 0; __iptr < fsize; __iptr++) {
+ union {
+ int16_t s16;
+ struct {
+ uint8_t l, h;
+ } b;
+ } pair16;
+ pair16.b.l = file.FgetUint8();
+ pair16.b.h = file.FgetUint8();
+ rhythm[i].sample[__iptr] = pair16.s16;
+ }
+ //file.Fread(rhythm[i].sample, fsize * 2, 1);
- file.Fread(rhythm[i].sample, fsize * 2, 1);
-
- rhythm[i].rate = whdr.rate;
+ rhythm[i].rate = EndianFromLittle_DWORD(whdr.sample_rate);
rhythm[i].step = rhythm[i].rate * 1024 / rate;
rhythm[i].pos = rhythm[i].size = fsize * 1024;
+ file.Fclose();
}
if (i != 6)
{
+// printf("NG %d\n", i);
for (i=0; i<6; i++)
{
delete[] rhythm[i].sample;
}
return false;
}
+// printf("OK\n");
return true;
}
//
#define OPNA_STATE_VERSION 4
+void OPNA::DeclState(void *f)
+{
+ p_logger = (CSP_Logger *)f;
+ state_entry = new csp_state_utils(OPNA_STATE_VERSION, chip_num, _T("FMGEN::OPNA::"), p_logger);
+
+ OPNABase::DeclState(f);
+
+ for(int i = 0; i < 6; i++) {
+ DECL_STATE_ENTRY_UINT8_MEMBER((rhythm[i].pan), i);
+ DECL_STATE_ENTRY_INT8_MEMBER((rhythm[i].level), i);
+ DECL_STATE_ENTRY_UINT32_MEMBER((rhythm[i].pos), i);
+ }
+ DECL_STATE_ENTRY_INT8(rhythmtl);
+ DECL_STATE_ENTRY_INT32(rhythmtvol_l);
+ DECL_STATE_ENTRY_INT32(rhythmtvol_r);
+ DECL_STATE_ENTRY_UINT8(rhythmkey);
+}
void OPNA::SaveState(void *f)
{
FILEIO *state_fio = (FILEIO *)f;
- state_fio->FputUint32_BE(OPNA_STATE_VERSION);
-
OPNABase::SaveState(f);
- for(int i = 0; i < 6; i++) {
- state_fio->FputUint8(rhythm[i].pan);
- state_fio->FputInt8(rhythm[i].level);
- state_fio->FputUint32_BE(rhythm[i].pos);
- }
- state_fio->FputInt8(rhythmtl);
- state_fio->FputInt32_BE(rhythmtvol_l);
- state_fio->FputInt32_BE(rhythmtvol_r);
- state_fio->FputUint8(rhythmkey);
+// state_fio->FputUint32_BE(OPNA_STATE_VERSION);
+
+// OPNABase::SaveState(f);
+// for(int i = 0; i < 6; i++) {
+// state_fio->FputUint8(rhythm[i].pan);
+// state_fio->FputInt8(rhythm[i].level);
+// state_fio->FputUint32_BE(rhythm[i].pos);
+// }
+// state_fio->FputInt8(rhythmtl);
+// state_fio->FputInt32_BE(rhythmtvol_l);
+// state_fio->FputInt32_BE(rhythmtvol_r);
+// state_fio->FputUint8(rhythmkey);
}
bool OPNA::LoadState(void *f)
{
FILEIO *state_fio = (FILEIO *)f;
- if(state_fio->FgetUint32_BE() != OPNA_STATE_VERSION) {
- return false;
- }
- if(!OPNABase::LoadState(f)) {
- return false;
- }
- for(int i = 0; i < 6; i++) {
- rhythm[i].pan = state_fio->FgetUint8();
- rhythm[i].level = state_fio->FgetInt8();
- rhythm[i].pos = state_fio->FgetUint32_BE();
- }
- rhythmtl = state_fio->FgetInt8();
- rhythmtvol_l = state_fio->FgetInt32_BE();
- rhythmtvol_r = state_fio->FgetInt32_BE();
- rhythmkey = state_fio->FgetUint8();
+ bool mb = false;
+ mb = OPNABase::LoadState(f);
+ if(!mb) return false;
+// if(state_fio->FgetUint32_BE() != OPNA_STATE_VERSION) {
+// return false;
+// }
+// if(!OPNABase::LoadState(f)) {
+// return false;
+// }
+// for(int i = 0; i < 6; i++) {
+// rhythm[i].pan = state_fio->FgetUint8();
+// rhythm[i].level = state_fio->FgetInt8();
+// rhythm[i].pos = state_fio->FgetUint32_BE();
+// }
+// rhythmtl = state_fio->FgetInt8();
+// rhythmtvol_l = state_fio->FgetInt32_BE();
+// rhythmtvol_r = state_fio->FgetInt32_BE();
+// rhythmkey = state_fio->FgetUint8();
return true;
}
#endif // BUILD_OPNB
+// ---------------------------------------------------------------------------
+// YM2612 common part
+// ---------------------------------------------------------------------------
+
+#if defined(BUILD_OPN2)
+
+int OPN2Base::amtable[FM_LFOENTS] = { -1, };
+int OPN2Base::pmtable[FM_LFOENTS];
+
+int32 OPN2Base::tltable[FM_TLENTS+FM_TLPOS];
+bool OPN2Base::tablehasmade = false;
+
+OPN2Base::OPN2Base()
+{
+
+ MakeTable2();
+ BuildLFOTable();
+ for (int i=0; i<6; i++)
+ {
+ ch[i].SetChip(&chip);
+ ch[i].SetType(typeN);
+ }
+}
+
+OPN2Base::~OPN2Base()
+{
+}
+
+// ---------------------------------------------------------------------------
+// \8f\89\8aú\89»
+//
+bool OPN2Base::Init(uint c, uint r, bool)
+{
+ RebuildTimeTable();
+
+ Reset();
+
+ SetVolumeFM(0, 0);
+ SetVolumePSG(0, 0);
+ SetChannelMask(0);
+ return true;
+}
+
+// ---------------------------------------------------------------------------
+// \83e\81[\83u\83\8b\8dì\90¬
+//
+void OPN2Base::MakeTable2()
+{
+ if (!tablehasmade)
+ {
+ for (int i=-FM_TLPOS; i<FM_TLENTS; i++)
+ {
+ tltable[i+FM_TLPOS] = uint(65536. * pow(2.0, i * -16. / FM_TLENTS))-1;
+ }
+
+ tablehasmade = true;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// \83\8a\83Z\83b\83g
+//
+void OPN2Base::Reset()
+{
+ int i;
+
+ OPNBase::Reset();
+ for (i=0x20; i<0x28; i++) SetReg(i, 0);
+ for (i=0x30; i<0xc0; i++) SetReg(i, 0);
+ for (i=0x130; i<0x1c0; i++) SetReg(i, 0);
+ for (i=0x100; i<0x110; i++) SetReg(i, 0);
+ for (i=0x10; i<0x20; i++) SetReg(i, 0);
+ for (i=0; i<6; i++)
+ {
+ pan[i] = 3;
+ ch[i].Reset();
+ }
+
+ stmask = ~0x1c;
+ statusnext = 0;
+ lfocount = 0;
+ status = 0;
+ UpdateStatus();
+}
+
+// ---------------------------------------------------------------------------
+// \83T\83\93\83v\83\8a\83\93\83O\83\8c\81[\83g\95Ï\8dX
+//
+bool OPN2Base::SetRate(uint c, uint r, bool)
+{
+ c /= 2; // \8f]\97\88\94Å\82Æ\82Ì\8cÝ\8a·\90«\82ð\8fd\8e\8b\82µ\82½\82¯\82è\82á\83R\83\81\83\93\83g\83A\83E\83g\82µ\82æ\82¤
+
+ OPNBase::Init(c, r);
+
+ RebuildTimeTable();
+
+ lfodcount = reg22 & 0x08 ? lfotable[reg22 & 7] : 0;
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// \83`\83\83\83\93\83l\83\8b\83}\83X\83N\82Ì\90Ý\92è
+//
+void OPN2Base::SetChannelMask(uint mask)
+{
+ for (int i=0; i<6; i++)
+ ch[i].Mute(!!(mask & (1 << i)));
+}
+
+// ---------------------------------------------------------------------------
+// \83\8c\83W\83X\83^\83A\83\8c\83C\82É\83f\81[\83^\82ð\90Ý\92è
+//
+void OPN2Base::SetReg(uint addr, uint data)
+{
+ int c = addr & 3;
+ switch (addr)
+ {
+ uint modified;
+
+ // Timer -----------------------------------------------------------------
+ case 0x24: case 0x25:
+ SetTimerA(addr, data);
+ break;
+
+ case 0x26:
+ SetTimerB(data);
+ break;
+
+ case 0x27:
+ SetTimerControl(data);
+ break;
+
+ // Misc ------------------------------------------------------------------
+ case 0x28: // Key On/Off
+ if ((data & 3) < 3)
+ {
+ c = (data & 3) + (data & 4 ? 3 : 0);
+ ch[c].KeyControl(data >> 4);
+ }
+ break;
+
+ // Status Mask -----------------------------------------------------------
+ case 0x29:
+ reg29 = data;
+// UpdateStatus(); //?
+ break;
+
+ // Prescaler -------------------------------------------------------------
+ case 0x2d: case 0x2e: case 0x2f:
+ SetPrescaler(addr-0x2d);
+ break;
+
+ // F-Number --------------------------------------------------------------
+ case 0x1a0: case 0x1a1: case 0x1a2:
+ c += 3;
+ case 0xa0: case 0xa1: case 0xa2:
+ fnum[c] = data + fnum2[c] * 0x100;
+ ch[c].SetFNum(fnum[c]);
+ break;
+
+ case 0x1a4: case 0x1a5: case 0x1a6:
+ c += 3;
+ case 0xa4 : case 0xa5: case 0xa6:
+ fnum2[c] = uint8(data);
+ break;
+
+ case 0xa8: case 0xa9: case 0xaa:
+ fnum3[c] = data + fnum2[c+6] * 0x100;
+ break;
+
+ case 0xac : case 0xad: case 0xae:
+ fnum2[c+6] = uint8(data);
+ break;
+
+ // Algorithm -------------------------------------------------------------
+
+ case 0x1b0: case 0x1b1: case 0x1b2:
+ c += 3;
+ case 0xb0: case 0xb1: case 0xb2:
+ ch[c].SetFB((data >> 3) & 7);
+ ch[c].SetAlgorithm(data & 7);
+ break;
+
+ case 0x1b4: case 0x1b5: case 0x1b6:
+ c += 3;
+ case 0xb4: case 0xb5: case 0xb6:
+ pan[c] = (data >> 6) & 3;
+ ch[c].SetMS(data);
+ break;
+
+ // LFO -------------------------------------------------------------------
+ case 0x22:
+ modified = reg22 ^ data;
+ reg22 = data;
+ if (modified & 0x8)
+ lfocount = 0;
+ lfodcount = reg22 & 8 ? lfotable[reg22 & 7] : 0;
+ break;
+
+ // PSG -------------------------------------------------------------------
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ break;
+
+ // \89¹\90F ------------------------------------------------------------------
+ default:
+ if (c < 3)
+ {
+ if (addr & 0x100)
+ c += 3;
+ OPNBase::SetParameter(&ch[c], addr, data);
+ }
+ break;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// \83X\83e\81[\83^\83X\83t\83\89\83O\90Ý\92è
+//
+void OPN2Base::SetStatus(uint bits)
+{
+ if (!(status & bits))
+ {
+// LOG2("SetStatus(%.2x %.2x)\n", bits, stmask);
+ status |= bits & stmask;
+ UpdateStatus();
+ }
+// else
+// LOG1("SetStatus(%.2x) - ignored\n", bits);
+}
+
+void OPN2Base::ResetStatus(uint bits)
+{
+ status &= ~bits;
+// LOG1("ResetStatus(%.2x)\n", bits);
+ UpdateStatus();
+}
+
+inline void OPN2Base::UpdateStatus()
+{
+// LOG2("%d:INT = %d\n", Diag::GetCPUTick(), (status & stmask & reg29) != 0);
+ Intr((status & stmask & reg29) != 0);
+}
+
+// ---------------------------------------------------------------------------
+// \8d\87\90¬
+// in: buffer \8d\87\90¬\90æ
+// nsamples \8d\87\90¬\83T\83\93\83v\83\8b\90\94
+//
+void OPN2Base::FMMix(Sample* buffer, int nsamples)
+{
+ if (fmvolume_l > 0 || fmvolume_r > 0)
+ {
+ // \8f\80\94õ
+ // Set F-Number
+ if (!(regtc & 0xc0))
+ csmch->SetFNum(fnum[csmch-ch]);
+ else
+ {
+ // \8cø\89Ê\89¹\83\82\81[\83h
+ csmch->op[0].SetFNum(fnum3[1]); csmch->op[1].SetFNum(fnum3[2]);
+ csmch->op[2].SetFNum(fnum3[0]); csmch->op[3].SetFNum(fnum[2]);
+ }
+
+ int act = (((ch[2].Prepare() << 2) | ch[1].Prepare()) << 2) | ch[0].Prepare();
+ if (reg29 & 0x80)
+ act |= (ch[3].Prepare() | ((ch[4].Prepare() | (ch[5].Prepare() << 2)) << 2)) << 6;
+ if (!(reg22 & 0x08))
+ act &= 0x555;
+
+ if (act & 0x555)
+ {
+ Mix6(buffer, nsamples, act);
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+void OPN2Base::MixSubSL(int activech, ISample** dest)
+{
+ if (activech & 0x001) (*dest[0] = ch[0].CalcL());
+ if (activech & 0x004) (*dest[1] += ch[1].CalcL());
+ if (activech & 0x010) (*dest[2] += ch[2].CalcL());
+ if (activech & 0x040) (*dest[3] += ch[3].CalcL());
+ if (activech & 0x100) (*dest[4] += ch[4].CalcL());
+ if (activech & 0x400) (*dest[5] += ch[5].CalcL());
+}
+
+inline void OPN2Base::MixSubS(int activech, ISample** dest)
+{
+ if (activech & 0x001) (*dest[0] = ch[0].Calc());
+ if (activech & 0x004) (*dest[1] += ch[1].Calc());
+ if (activech & 0x010) (*dest[2] += ch[2].Calc());
+ if (activech & 0x040) (*dest[3] += ch[3].Calc());
+ if (activech & 0x100) (*dest[4] += ch[4].Calc());
+ if (activech & 0x400) (*dest[5] += ch[5].Calc());
+}
+
+// ---------------------------------------------------------------------------
+
+void OPN2Base::BuildLFOTable()
+{
+ if (amtable[0] == -1)
+ {
+ for (int c=0; c<256; c++)
+ {
+ int v;
+ if (c < 0x40) v = c * 2 + 0x80;
+ else if (c < 0xc0) v = 0x7f - (c - 0x40) * 2 + 0x80;
+ else v = (c - 0xc0) * 2;
+ pmtable[c] = v;
+
+ if (c < 0x80) v = 0xff - c * 2;
+ else v = (c - 0x80) * 2;
+ amtable[c] = v & ~3;
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+inline void OPN2Base::LFO()
+{
+// LOG3("%4d - %8d, %8d\n", c, lfocount, lfodcount);
+
+// Operator::SetPML(pmtable[(lfocount >> (FM_LFOCBITS+1)) & 0xff]);
+// Operator::SetAML(amtable[(lfocount >> (FM_LFOCBITS+1)) & 0xff]);
+ chip.SetPML(pmtable[(lfocount >> (FM_LFOCBITS+1)) & 0xff]);
+ chip.SetAML(amtable[(lfocount >> (FM_LFOCBITS+1)) & 0xff]);
+ lfocount += lfodcount;
+}
+
+// ---------------------------------------------------------------------------
+// \8d\87\90¬
+//
+//#define IStoSampleL(s) ((Limit(s, 0x7fff, -0x8000) * fmvolume_l) >> 14)
+//#define IStoSampleR(s) ((Limit(s, 0x7fff, -0x8000) * fmvolume_r) >> 14)
+
+void OPN2Base::Mix6(Sample* buffer, int nsamples, int activech)
+{
+ // Mix
+ ISample ibuf[4];
+ ISample* idest[6];
+ idest[0] = &ibuf[pan[0]];
+ idest[1] = &ibuf[pan[1]];
+ idest[2] = &ibuf[pan[2]];
+ idest[3] = &ibuf[pan[3]];
+ idest[4] = &ibuf[pan[4]];
+ idest[5] = &ibuf[pan[5]];
+
+ Sample* limit = buffer + nsamples * 2;
+ for (Sample* dest = buffer; dest < limit; dest+=2)
+ {
+ ibuf[1] = ibuf[2] = ibuf[3] = 0;
+ if (activech & 0xaaa)
+ LFO(), MixSubSL(activech, idest);
+ else
+ MixSubS(activech, idest);
+ StoreSample(dest[0], IStoSampleL(ibuf[2] + ibuf[3]));
+ StoreSample(dest[1], IStoSampleR(ibuf[1] + ibuf[3]));
+ }
+}
+// ---------------------------------------------------------------------------
+// \83X\83e\81[\83g\83Z\81[\83u
+//
+#define OPN2_BASE_STATE_VERSION 1
+
+void OPN2Base::DeclState(void *f)
+{
+
+ OPNBase::DeclState(f);
+
+ DECL_STATE_ENTRY_1D_ARRAY(pan, sizeof(pan));
+ DECL_STATE_ENTRY_1D_ARRAY(fnum2, sizeof(fnum2));
+ DECL_STATE_ENTRY_UINT8(reg22);
+ DECL_STATE_ENTRY_UINT32(reg29);
+ DECL_STATE_ENTRY_UINT32(stmask);
+ DECL_STATE_ENTRY_UINT32(statusnext);
+ DECL_STATE_ENTRY_UINT32(lfocount);
+ DECL_STATE_ENTRY_UINT32(lfodcount);
+ //state_fio->Fwrite(fnum, sizeof(fnum), 1);
+ //state_fio->Fwrite(fnum3, sizeof(fnum3), 1);
+ for(int i = 0; i < 6; i++) {
+ DECL_STATE_ENTRY_UINT32_MEMBER((fnum[i]), i);
+ }
+ for(int i = 0; i < 3; i++) {
+ DECL_STATE_ENTRY_UINT32_MEMBER((fnum3[i]), i);
+ }
+ for(int i = 0; i < 6; i++) {
+ ch[i].DeclState(f);
+ }
+}
+
+void OPN2Base::SaveState(void *f)
+{
+ FILEIO *state_fio = (FILEIO *)f;
+ if(state_entry != NULL) {
+ state_entry->save_state(state_fio);
+ }
+ chip.SaveState(f);
+ for(int i = 0; i < 6; i++) {
+ ch[i].SaveState(f);
+ }
+}
+
+bool OPN2Base::LoadState(void *f)
+{
+ FILEIO *state_fio = (FILEIO *)f;
+
+ bool mb = false;
+ if(state_entry != NULL) {
+ mb = state_entry->load_state(state_fio);
+ }
+ if(!mb) return false;
+ {
+ // Make force-restore around prescaler and timers. 20180625 K.O
+ uint bak = prescale;
+ prescale = 10;
+ SetPrescaler(bak);
+ }
+ if(!chip.LoadState(f)) {
+ return false;
+ }
+ for(int i = 0; i < 6; i++) {
+ if(!ch[i].LoadState(f)) {
+ return false;
+ }
+ }
+ return true;
+}
+#endif // defined(BUILD_OPN2)
+
+// ---------------------------------------------------------------------------
+// YM2612(OPN2)
+// ---------------------------------------------------------------------------
+
+#ifdef BUILD_OPN2
+
+// ---------------------------------------------------------------------------
+// \83\8c\83W\83X\83^\8eæ\93¾
+//
+uint OPN2::GetReg(uint addr)
+{
+ return 0;
+}
+
+// ---------------------------------------------------------------------------
+// \8d\\92z
+//
+OPN2::OPN2()
+{
+ csmch = &ch[2]; // ToDo: Check register.
+}
+// ---------------------------------------------------------------------------
+
+OPN2::~OPN2()
+{
+}
+
+// ---------------------------------------------------------------------------
+// \8f\89\8aú\89»
+//
+bool OPN2::Init(uint c, uint r, bool ipflag, const _TCHAR* path)
+{
+ rate = 8000;
+ if (!SetRate(c, r, ipflag))
+ return false;
+ if (!OPN2Base::Init(c, r, ipflag))
+ return false;
+
+ Reset();
+ return true;
+}
+// ---------------------------------------------------------------------------
+// \83\8a\83Z\83b\83g
+//
+void OPN2::Reset()
+{
+ reg29 = 0x1f;
+ OPN2Base::Reset();
+}
+// ---------------------------------------------------------------------------
+// \83T\83\93\83v\83\8a\83\93\83O\83\8c\81[\83g\95Ï\8dX
+//
+bool OPN2::SetRate(uint c, uint r, bool ipflag)
+{
+ if (!OPN2Base::SetRate(c, r, ipflag))
+ return false;
+ return true;
+}
+
+// ---------------------------------------------------------------------------
+// \83\8c\83W\83X\83^\83A\83\8c\83C\82É\83f\81[\83^\82ð\90Ý\92è
+//
+void OPN2::SetReg(uint addr, uint data)
+{
+ addr &= 0x1ff;
+
+ switch (addr)
+ {
+ case 0x29:
+ reg29 = data;
+// UpdateStatus(); //?
+ break;
+
+ default:
+ OPN2Base::SetReg(addr, data);
+ break;
+ }
+}
+
+
+
+// ---------------------------------------------------------------------------
+// \8d\87\90¬
+// in: buffer \8d\87\90¬\90æ
+// nsamples \8d\87\90¬\83T\83\93\83v\83\8b\90\94
+//
+void OPN2::Mix(Sample* buffer, int nsamples)
+{
+ FMMix(buffer, nsamples);
+}
+
+// ---------------------------------------------------------------------------
+// \83X\83e\81[\83g\83Z\81[\83u
+//
+#define OPN2_STATE_VERSION 1
+
+void OPN2::DeclState(void *f)
+{
+ p_logger = (CSP_Logger *)f;
+ state_entry = new csp_state_utils(OPN2_STATE_VERSION, chip_num, _T("FMGEN::OPN2::"), p_logger);
+
+ OPN2Base::DeclState(f);
+}
+
+void OPN2::SaveState(void *f)
+{
+ FILEIO *state_fio = (FILEIO *)f;
+ OPN2Base::SaveState(f);
+}
+
+bool OPN2::LoadState(void *f)
+{
+ FILEIO *state_fio = (FILEIO *)f;
+
+ bool mb = false;
+ mb = OPN2Base::LoadState(f);
+ if(!mb) return false;
+
+ return true;
+}
+
+#endif // BUILD_OPN2
+
} // namespace FM