diff --git a/papers/newIns.md b/papers/newIns.md index d0967205b..425d39ea9 100644 --- a/papers/newIns.md +++ b/papers/newIns.md @@ -40,13 +40,14 @@ the following feature codes are recognized: - `LD`: OPL drums mode data - `SN`: SNES ins data - `N1`: Namco 163 ins data -- `FD`: FDS ins data +- `FD`: FDS/Virtual Boy ins data - `WS`: wavetable synth data - `SL`: list of samples - `WL`: list of wavetables - `MP`: MultiPCM ins data - `SU`: Sound Unit ins data - `ES`: ES5506 ins data +- `X1`: X1-010 ins data # FM data (FM) diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index 2c792df04..b3e386b79 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -23,7 +23,158 @@ #include "../ta-log.h" #include "../fileutils.h" -void DivInstrument::putInsData2(SafeWriter* w, bool fui) { +const DivInstrument defaultIns; + +void DivInstrument::writeFeatureNA(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureFM(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureMA(SafeWriter* w) { + +} + +void DivInstrument::writeFeature64(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureGB(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureSM(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureOx(SafeWriter* w, int op) { + +} + +void DivInstrument::writeFeatureLD(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureSN(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureN1(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureFD(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureWS(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureSL(SafeWriter* w, const DivSong* song) { + +} + +void DivInstrument::writeFeatureWL(SafeWriter* w, const DivSong* song) { + +} + +void DivInstrument::writeFeatureMP(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureSU(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureES(SafeWriter* w) { + +} + +void DivInstrument::writeFeatureX1(SafeWriter* w) { + +} + +#define _C(x) x==a.x + +bool DivInstrumentFM::operator==(const DivInstrumentFM& a) { + return true; +} + +bool DivInstrumentFM::Operator::operator==(const DivInstrumentFM::Operator& a) { + return ( + _C(enable) && + _C(am) && + _C(ar) && + _C(dr) && + _C(mult) && + _C(rr) && + _C(sl) && + _C(tl) && + _C(dt2) && + _C(rs) && + _C(dt) && + _C(d2r) && + _C(ssgEnv) && + _C(dam) && + _C(dvb) && + _C(egt) && + _C(ksl) && + _C(sus) && + _C(vib) && + _C(ws) && + _C(ksr) && + _C(kvs) + ); +} + +bool DivInstrumentGB::operator==(const DivInstrumentGB& a) { + return true; +} + +bool DivInstrumentC64::operator==(const DivInstrumentC64& a) { + return true; +} + +bool DivInstrumentAmiga::operator==(const DivInstrumentAmiga& a) { + return true; +} + +bool DivInstrumentX1_010::operator==(const DivInstrumentX1_010& a) { + return true; +} + +bool DivInstrumentN163::operator==(const DivInstrumentN163& a) { + return true; +} + +bool DivInstrumentFDS::operator==(const DivInstrumentFDS& a) { + return true; +} + +bool DivInstrumentMultiPCM::operator==(const DivInstrumentMultiPCM& a) { + return true; +} + +bool DivInstrumentWaveSynth::operator==(const DivInstrumentWaveSynth& a) { + return true; +} + +bool DivInstrumentSoundUnit::operator==(const DivInstrumentSoundUnit& a) { + return true; +} + +bool DivInstrumentES5506::operator==(const DivInstrumentES5506& a) { + return true; +} + +bool DivInstrumentSNES::operator==(const DivInstrumentSNES& a) { + return true; +} + +void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song) { size_t blockStartSeek, blockEndSeek; if (fui) { @@ -45,10 +196,7 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui) { bool feature64=false; bool featureGB=false; bool featureSM=false; - bool featureO1=false; - bool featureO2=false; - bool featureO3=false; - bool featureO4=false; + bool featureOx[4]; bool featureLD=false; bool featureSN=false; bool featureN1=false; @@ -59,10 +207,361 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui) { bool featureMP=false; bool featureSU=false; bool featureES=false; + bool featureX1=false; - // almost 40 years of C++, and there still isn't a way to easily compare two structs. - // even Java, which many regard as having a slow runtime, has .equals(). - + bool checkForWL=false; + + featureOx[0]=false; + featureOx[1]=false; + featureOx[2]=false; + featureOx[3]=false; + + // turn on base features if .fui + if (fui) { + switch (type) { + case DIV_INS_STD: + break; + case DIV_INS_FM: + featureFM=true; + break; + case DIV_INS_GB: + featureGB=true; + checkForWL=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_C64: + feature64=true; + break; + case DIV_INS_AMIGA: + featureSM=true; + break; + case DIV_INS_PCE: + checkForWL=true; + featureSM=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_AY: + featureSM=true; + break; + case DIV_INS_AY8930: + featureSM=true; + break; + case DIV_INS_TIA: + break; + case DIV_INS_SAA1099: + break; + case DIV_INS_VIC: + break; + case DIV_INS_PET: + break; + case DIV_INS_VRC6: + featureSM=true; + break; + case DIV_INS_OPLL: + featureFM=true; + if (fm.fixedDrums) featureLD=true; + break; + case DIV_INS_OPL: + featureFM=true; + if (fm.fixedDrums) featureLD=true; + break; + case DIV_INS_FDS: + checkForWL=true; + featureFD=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_VBOY: + checkForWL=true; + featureFD=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_N163: + checkForWL=true; + featureN1=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_SCC: + checkForWL=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_OPZ: + featureFM=true; + break; + case DIV_INS_POKEY: + break; + case DIV_INS_BEEPER: + break; + case DIV_INS_SWAN: + checkForWL=true; + featureSM=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_MIKEY: + featureSM=true; + break; + case DIV_INS_VERA: + break; + case DIV_INS_X1_010: + checkForWL=true; + featureX1=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_VRC6_SAW: + break; + case DIV_INS_ES5506: + featureSM=true; + featureES=true; + break; + case DIV_INS_MULTIPCM: + featureSM=true; + featureMP=true; + break; + case DIV_INS_SNES: + featureSM=true; + featureSN=true; + checkForWL=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_SU: + featureSM=true; + featureSU=true; + break; + case DIV_INS_NAMCO: + checkForWL=true; + if (ws.enabled) featureWS=true; + break; + case DIV_INS_OPL_DRUMS: + featureFM=true; + if (fm.fixedDrums) featureLD=true; + break; + case DIV_INS_OPM: + featureFM=true; + break; + case DIV_INS_NES: + break; + case DIV_INS_MSM6258: + featureSM=true; + break; + case DIV_INS_MSM6295: + featureSM=true; + break; + case DIV_INS_ADPCMA: + featureSM=true; + break; + case DIV_INS_ADPCMB: + featureSM=true; + break; + case DIV_INS_SEGAPCM: + featureSM=true; + break; + case DIV_INS_QSOUND: + featureSM=true; + break; + case DIV_INS_YMZ280B: + featureSM=true; + break; + case DIV_INS_RF5C68: + featureSM=true; + break; + case DIV_INS_MSM5232: + break; + case DIV_INS_T6W28: + break; + + case DIV_INS_MAX: + break; + case DIV_INS_NULL: + break; + } + } else { + // turn on features depending on what is set + // almost 40 years of C++, and there still isn't an official way to easily compare two structs. + // even Java, which many regard as having a slow runtime, has .equals(). + if (fm!=defaultIns.fm) { + featureFM=true; + featureLD=true; + } + if (c64!=defaultIns.c64) { + feature64=true; + } + if (gb!=defaultIns.gb) { + featureGB=true; + } + if (amiga!=defaultIns.amiga) { + featureSM=true; + } + if (snes!=defaultIns.snes) { + featureSN=true; + } + if (n163!=defaultIns.n163) { + featureN1=true; + } + if (fds!=defaultIns.fds) { + featureFD=true; + } + if (ws!=defaultIns.ws) { + featureWS=true; + } + if (multipcm!=defaultIns.multipcm) { + featureMP=true; + } + if (su!=defaultIns.su) { + featureSU=true; + } + if (es5506!=defaultIns.es5506) { + featureES=true; + } + if (x1_010!=defaultIns.x1_010) { + featureX1=true; + } + } + + // check ins name + if (!name.empty()) { + featureNA=true; + } + + // check macros + if (std.volMacro.len || + std.arpMacro.len || + std.dutyMacro.len || + std.waveMacro.len || + std.pitchMacro.len || + std.ex1Macro.len || + std.ex2Macro.len || + std.ex3Macro.len || + std.algMacro.len || + std.fbMacro.len || + std.fmsMacro.len || + std.amsMacro.len || + std.panLMacro.len || + std.panRMacro.len || + std.phaseResetMacro.len || + std.ex4Macro.len || + std.ex5Macro.len || + std.ex6Macro.len || + std.ex7Macro.len || + std.ex8Macro.len) { + featureMA=true; + } + + // check whether to write wavetable list + if (checkForWL && fui) { + if (std.waveMacro.len || ws.enabled) { + featureWL=true; + } + } + + if (featureFM) { + // check FM macros + int opCount=4; + bool storeExtendedAsWell=true; + if (fui) { + if (type==DIV_INS_OPLL) { + opCount=2; + } else if (type==DIV_INS_OPL) { + opCount=(fm.ops==4)?4:2; + } else if (type==DIV_INS_FM || type==DIV_INS_OPM) { + storeExtendedAsWell=false; + } + } + for (int i=0; itell(); if (!fui) { diff --git a/src/engine/instrument.h b/src/engine/instrument.h index 0f434181c..145da66a3 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -23,6 +23,8 @@ #include "dataErrors.h" #include "../ta-utils.h" +class DivSong; + // NOTICE! // before adding new instrument types to this struct, please ask me first. // absolutely zero support granted to conflicting formats. @@ -95,11 +97,21 @@ struct DivInstrumentFM { unsigned char alg, fb, fms, ams, fms2, ams2, ops, opllPreset; bool fixedDrums; unsigned short kickFreq, snareHatFreq, tomTopFreq; + + bool operator==(const DivInstrumentFM& a); + bool operator!=(const DivInstrumentFM& a) { + return !(*this==a); + } struct Operator { bool enable; unsigned char am, ar, dr, mult, rr, sl, tl, dt2, rs, dt, d2r, ssgEnv; unsigned char dam, dvb, egt, ksl, sus, vib, ws, ksr; // YMU759/OPL/OPZ unsigned char kvs; + + bool operator==(const Operator& a); + bool operator!=(const Operator& a) { + return !(*this==a); + } Operator(): enable(true), am(0), @@ -294,6 +306,12 @@ struct DivInstrumentGB { unsigned char cmd; unsigned short data; } hwSeq[256]; + + bool operator==(const DivInstrumentGB& a); + bool operator!=(const DivInstrumentGB& a) { + return !(*this==a); + } + DivInstrumentGB(): envVol(15), envDir(0), @@ -316,6 +334,11 @@ struct DivInstrumentC64 { unsigned short cut; bool hp, lp, bp, ch3off; + bool operator==(const DivInstrumentC64& a); + bool operator!=(const DivInstrumentC64& a) { + return !(*this==a); + } + DivInstrumentC64(): triOn(false), sawOn(true), @@ -357,6 +380,11 @@ struct DivInstrumentAmiga { unsigned char waveLen; SampleMap noteMap[120]; + bool operator==(const DivInstrumentAmiga& a); + bool operator!=(const DivInstrumentAmiga& a) { + return !(*this==a); + } + /** * get the sample at specified note. * @return the sample. @@ -398,6 +426,11 @@ struct DivInstrumentAmiga { struct DivInstrumentX1_010 { int bankSlot; + bool operator==(const DivInstrumentX1_010& a); + bool operator!=(const DivInstrumentX1_010& a) { + return !(*this==a); + } + DivInstrumentX1_010(): bankSlot(0) {} }; @@ -406,6 +439,11 @@ struct DivInstrumentN163 { int wave, wavePos, waveLen; unsigned char waveMode; + bool operator==(const DivInstrumentN163& a); + bool operator!=(const DivInstrumentN163& a) { + return !(*this==a); + } + DivInstrumentN163(): wave(-1), wavePos(0), @@ -418,6 +456,12 @@ struct DivInstrumentFDS { int modSpeed, modDepth; // this is here for compatibility. bool initModTableWithFirstWave; + + bool operator==(const DivInstrumentFDS& a); + bool operator!=(const DivInstrumentFDS& a) { + return !(*this==a); + } + DivInstrumentFDS(): modSpeed(0), modDepth(0), @@ -430,6 +474,11 @@ struct DivInstrumentMultiPCM { unsigned char ar, d1r, dl, d2r, rr, rc; unsigned char lfo, vib, am; + bool operator==(const DivInstrumentMultiPCM& a); + bool operator!=(const DivInstrumentMultiPCM& a) { + return !(*this==a); + } + DivInstrumentMultiPCM(): ar(15), d1r(15), dl(0), d2r(0), rr(15), rc(15), lfo(0), vib(0), am(0) { @@ -468,6 +517,12 @@ struct DivInstrumentWaveSynth { unsigned char effect; bool oneShot, enabled, global; unsigned char speed, param1, param2, param3, param4; + + bool operator==(const DivInstrumentWaveSynth& a); + bool operator!=(const DivInstrumentWaveSynth& a) { + return !(*this==a); + } + DivInstrumentWaveSynth(): wave1(0), wave2(0), @@ -485,6 +540,12 @@ struct DivInstrumentWaveSynth { struct DivInstrumentSoundUnit { bool switchRoles; + + bool operator==(const DivInstrumentSoundUnit& a); + bool operator!=(const DivInstrumentSoundUnit& a) { + return !(*this==a); + } + DivInstrumentSoundUnit(): switchRoles(false) {} }; @@ -520,6 +581,12 @@ struct DivInstrumentES5506 { }; Filter filter; Envelope envelope; + + bool operator==(const DivInstrumentES5506& a); + bool operator!=(const DivInstrumentES5506& a) { + return !(*this==a); + } + DivInstrumentES5506(): filter(Filter()), envelope(Envelope()) {} @@ -537,6 +604,12 @@ struct DivInstrumentSNES { GainMode gainMode; unsigned char gain; unsigned char a, d, s, r; + + bool operator==(const DivInstrumentSNES& a); + bool operator!=(const DivInstrumentSNES& a) { + return !(*this==a); + } + DivInstrumentSNES(): useEnv(true), sus(false), @@ -564,6 +637,28 @@ struct DivInstrument { DivInstrumentSoundUnit su; DivInstrumentES5506 es5506; DivInstrumentSNES snes; + + /** + * these are internal functions. + */ + void writeFeatureNA(SafeWriter* w); + void writeFeatureFM(SafeWriter* w); + void writeFeatureMA(SafeWriter* w); + void writeFeature64(SafeWriter* w); + void writeFeatureGB(SafeWriter* w); + void writeFeatureSM(SafeWriter* w); + void writeFeatureOx(SafeWriter* w, int op); + void writeFeatureLD(SafeWriter* w); + void writeFeatureSN(SafeWriter* w); + void writeFeatureN1(SafeWriter* w); + void writeFeatureFD(SafeWriter* w); + void writeFeatureWS(SafeWriter* w); + void writeFeatureSL(SafeWriter* w, const DivSong* song); + void writeFeatureWL(SafeWriter* w, const DivSong* song); + void writeFeatureMP(SafeWriter* w); + void writeFeatureSU(SafeWriter* w); + void writeFeatureES(SafeWriter* w); + void writeFeatureX1(SafeWriter* w); /** * save the instrument to a SafeWriter. @@ -575,7 +670,7 @@ struct DivInstrument { * save the instrument to a SafeWriter using new format. * @param w the SafeWriter in question. */ - void putInsData2(SafeWriter* w, bool fui=false); + void putInsData2(SafeWriter* w, bool fui=false, const DivSong* song=NULL); /** * read instrument data in .fui format.