diff --git a/papers/format.md b/papers/format.md index 5eaf385fd..013f2c5d2 100644 --- a/papers/format.md +++ b/papers/format.md @@ -29,6 +29,8 @@ furthermore, an `or reserved` indicates this field is always present, but is res the format versions are: +- 99: Furnace dev99 +- 98: Furnace dev98 - 97: Furnace dev97 - 96: Furnace dev96 - 95: Furnace dev95 @@ -226,8 +228,9 @@ size | description | - 0xb9: Namco WSG - 3 channels | - 0xba: Namco 15xx - 8 channels | - 0xbb: Namco CUS30 - 8 channels - | - 0xbc: YM2612 extra features - 8 channels + | - 0xbc: reserved - 8 channels | - 0xbd: YM2612 extra features extended - 11 channels + | - 0xbe: YM2612 extra features - 7 channels | - 0xde: YM2610B extended - 19 channels | - 0xe0: QSound - 19 channels | - 0xfd: Dummy System - 8 channels @@ -304,7 +307,11 @@ size | description 1 | pitch macro is linear (>=90) or reserved 1 | pitch slide speed in full linear pitch mode (>=94) or reserved 1 | old octave boundary behavior (>=97) or reserved - 13 | reserved + 1 | disable OPN2 DAC volume control (>=98) or reserved + 1 | new volume scaling strategy (>=99) or reserved + 1 | volume macro still applies after end (>=99) or reserved + 1 | broken outVol (>=99) or reserved + 9 | reserved --- | **virtual tempo data** 2 | virtual tempo numerator of first song (>=96) or reserved 2 | virtual tempo denominator of first song (>=96) or reserved diff --git a/src/engine/engine.h b/src/engine/engine.h index 6e09d20f5..94c122195 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -45,8 +45,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev98" -#define DIV_ENGINE_VERSION 98 +#define DIV_VERSION "dev99" +#define DIV_ENGINE_VERSION 99 // for imports #define DIV_VERSION_MOD 0xff01 diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 7e5dbaf6e..637f7b244 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -168,6 +168,9 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { ds.snDutyReset=true; ds.oldOctaveBoundary=false; ds.noOPN2Vol=true; + ds.newVolumeScaling=false; + ds.volMacroLinger=false; + ds.brokenOutVol=true; // ??? // 1.1 compat flags if (ds.version>24) { @@ -1035,6 +1038,11 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { if (ds.version<97) { // actually should be 98 but yky uses this feature ahead of time ds.noOPN2Vol=true; } + if (ds.version<99) { + ds.newVolumeScaling=false; + ds.volMacroLinger=false; + ds.brokenOutVol=true; + } ds.isDMF=false; reader.readS(); // reserved @@ -1422,7 +1430,16 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { } else { reader.readC(); } - for (int i=0; i<12; i++) { + if (ds.version>=99) { + ds.newVolumeScaling=reader.readC(); + ds.volMacroLinger=reader.readC(); + ds.brokenOutVol=reader.readC(); + } else { + reader.readC(); + reader.readC(); + reader.readC(); + } + for (int i=0; i<9; i++) { reader.readC(); } } @@ -2891,7 +2908,10 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->writeC(song.pitchSlideSpeed); w->writeC(song.oldOctaveBoundary); w->writeC(song.noOPN2Vol); - for (int i=0; i<12; i++) { + w->writeC(song.newVolumeScaling); + w->writeC(song.volMacroLinger); + w->writeC(song.brokenOutVol); + for (int i=0; i<9; i++) { w->writeC(0); } diff --git a/src/engine/song.h b/src/engine/song.h index 86801efda..c9d98275a 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -113,6 +113,7 @@ enum DivSystem { DIV_SYSTEM_NAMCO_CUS30, DIV_SYSTEM_YM2612_FRAC, DIV_SYSTEM_YM2612_FRAC_EXT, + DIV_SYSTEM_RESERVED_8, DIV_SYSTEM_DUMMY }; @@ -397,6 +398,9 @@ struct DivSong { bool pitchMacroIsLinear; bool oldOctaveBoundary; bool noOPN2Vol; + bool newVolumeScaling; + bool volMacroLinger; + bool brokenOutVol; std::vector ins; std::vector wave; @@ -491,7 +495,10 @@ struct DivSong { snDutyReset(false), pitchMacroIsLinear(true), oldOctaveBoundary(false), - noOPN2Vol(false) { + noOPN2Vol(false), + newVolumeScaling(true), + volMacroLinger(true), + brokenOutVol(false) { for (int i=0; i<32; i++) { system[i]=DIV_SYSTEM_NULL; systemVol[i]=64; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 2fef000c3..cb3d5e2f2 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -2022,20 +2022,30 @@ void DivEngine::registerSystems() { namcoEffectHandler ); + // replace with an 8-channel chip in a future + sysDefs[DIV_SYSTEM_RESERVED_8]=new DivSysDef( + "Reserved", NULL, 0xbc, 0, 8, false, true, 0, false, + "this was YM2612_FRAC, but due to changes this ID is reserved.", + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"}, + {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"}, + {DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD} + ); + sysDefs[DIV_SYSTEM_YM2612_FRAC]=new DivSysDef( - "Yamaha YM2612 (OPN2) with DualPCM", NULL, 0xbc, 0, 8, true, false, 0, false, + "Yamaha YM2612 (OPN2) with DualPCM", NULL, 0xbe, 0, 7, true, false, 0, false, "this chip is mostly known for being in the Sega Genesis (but it also was on the FM Towns computer).\nthis system uses software mixing to provide two sample channels.", - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6/PCM 1", "PCM 2", "CSM Timer"}, - {"F1", "F2", "F3", "F4", "F5", "P1", "P2", "CSM"}, - {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_NOISE}, - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AMIGA, DIV_INS_FM}, - {DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_AMIGA, DIV_INS_NULL, DIV_INS_NULL}, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6/PCM 1", "PCM 2"}, + {"F1", "F2", "F3", "F4", "F5", "P1", "P2"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AMIGA}, + {DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_AMIGA, DIV_INS_NULL}, opn2EffectHandler, fmPostEffectHandler ); sysDefs[DIV_SYSTEM_YM2612_FRAC_EXT]=new DivSysDef( - "Yamaha YM2612 (OPN2) Extended Channel 3 with DualPCM", NULL, 0xbd, 0, 11, true, false, 0, false, + "Yamaha YM2612 (OPN2) Extended Channel 3 with DualPCM and CSM", NULL, 0xbd, 0, 11, true, false, 0, false, "this chip is mostly known for being in the Sega Genesis (but it also was on the FM Towns computer).\nthis system uses software mixing to provide two sample channels.\nthis one is in Extended Channel mode, which turns the second FM channel into four operators with independent notes/frequencies.", {"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6/PCM 1", "PCM 2", "CSM Timer"}, {"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "P1", "P2", "CSM"},