From 90a9a86e09c7b9f240e64c10a5b4e42b0d0fb34f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Nov 2025 01:40:19 -0500 Subject: [PATCH] giga-refactor, part 9 new format saving compatibility flags now part of own struct --- papers/format.md | 11 +- src/engine/cmdStream.cpp | 2 +- src/engine/dispatch.h | 8 +- src/engine/engine.cpp | 16 +- src/engine/engine.h | 2 +- src/engine/fileOps/dmf.cpp | 90 +-- src/engine/fileOps/fc.cpp | 12 +- src/engine/fileOps/ftm.cpp | 4 +- src/engine/fileOps/fur.cpp | 718 ++++++++++------------- src/engine/fileOps/it.cpp | 14 +- src/engine/fileOps/mod.cpp | 10 +- src/engine/fileOps/s3m.cpp | 12 +- src/engine/fileOps/tfm.cpp | 4 +- src/engine/fileOps/xm.cpp | 16 +- src/engine/macroInt.cpp | 2 +- src/engine/platform/amiga.cpp | 6 +- src/engine/platform/arcade.cpp | 6 +- src/engine/platform/ay.cpp | 8 +- src/engine/platform/ay8930.cpp | 8 +- src/engine/platform/bifurcator.cpp | 6 +- src/engine/platform/bubsyswsg.cpp | 6 +- src/engine/platform/c140.cpp | 6 +- src/engine/platform/c64.cpp | 4 +- src/engine/platform/dave.cpp | 6 +- src/engine/platform/es5506.cpp | 14 +- src/engine/platform/esfm.cpp | 8 +- src/engine/platform/fds.cpp | 8 +- src/engine/platform/fmshared_OPN.h | 6 +- src/engine/platform/ga20.cpp | 6 +- src/engine/platform/gb.cpp | 10 +- src/engine/platform/gbadma.cpp | 4 +- src/engine/platform/gbaminmod.cpp | 6 +- src/engine/platform/genesis.cpp | 16 +- src/engine/platform/genesisext.cpp | 12 +- src/engine/platform/k007232.cpp | 6 +- src/engine/platform/k053260.cpp | 6 +- src/engine/platform/lynx.cpp | 8 +- src/engine/platform/mmc5.cpp | 6 +- src/engine/platform/msm5232.cpp | 12 +- src/engine/platform/msm6258.cpp | 2 +- src/engine/platform/msm6295.cpp | 2 +- src/engine/platform/multipcm.cpp | 4 +- src/engine/platform/n163.cpp | 8 +- src/engine/platform/namcowsg.cpp | 10 +- src/engine/platform/nds.cpp | 6 +- src/engine/platform/nes.cpp | 12 +- src/engine/platform/opl.cpp | 10 +- src/engine/platform/opll.cpp | 6 +- src/engine/platform/pce.cpp | 20 +- src/engine/platform/pcmdac.cpp | 4 +- src/engine/platform/pcspkr.cpp | 6 +- src/engine/platform/pet.cpp | 6 +- src/engine/platform/pokemini.cpp | 6 +- src/engine/platform/pokey.cpp | 10 +- src/engine/platform/pong.cpp | 6 +- src/engine/platform/powernoise.cpp | 6 +- src/engine/platform/pv1000.cpp | 4 +- src/engine/platform/qsound.cpp | 6 +- src/engine/platform/rf5c68.cpp | 6 +- src/engine/platform/saa.cpp | 10 +- src/engine/platform/scc.cpp | 6 +- src/engine/platform/scvtone.cpp | 8 +- src/engine/platform/segapcm.cpp | 20 +- src/engine/platform/sid2.cpp | 4 +- src/engine/platform/sid3.cpp | 6 +- src/engine/platform/sm8521.cpp | 10 +- src/engine/platform/sms.cpp | 18 +- src/engine/platform/snes.cpp | 4 +- src/engine/platform/su.cpp | 10 +- src/engine/platform/supervision.cpp | 6 +- src/engine/platform/swan.cpp | 6 +- src/engine/platform/t6w28.cpp | 10 +- src/engine/platform/ted.cpp | 6 +- src/engine/platform/tia.cpp | 4 +- src/engine/platform/tx81z.cpp | 8 +- src/engine/platform/vb.cpp | 6 +- src/engine/platform/vera.cpp | 4 +- src/engine/platform/vic20.cpp | 4 +- src/engine/platform/vrc6.cpp | 6 +- src/engine/platform/x1_010.cpp | 6 +- src/engine/platform/ym2203.cpp | 10 +- src/engine/platform/ym2203ext.cpp | 6 +- src/engine/platform/ym2608.cpp | 10 +- src/engine/platform/ym2608ext.cpp | 10 +- src/engine/platform/ym2610.cpp | 10 +- src/engine/platform/ym2610b.cpp | 10 +- src/engine/platform/ym2610bext.cpp | 10 +- src/engine/platform/ym2610ext.cpp | 10 +- src/engine/platform/ymz280b.cpp | 8 +- src/engine/platform/zxbeeper.cpp | 4 +- src/engine/platform/zxbeeperquadtone.cpp | 6 +- src/engine/playback.cpp | 124 ++-- src/engine/song.cpp | 228 ++++++- src/engine/song.h | 163 +++-- src/engine/vgmOps.cpp | 2 +- src/gui/compatFlags.cpp | 152 ++--- src/gui/exportOptions.cpp | 2 +- src/gui/insEdit.cpp | 16 +- src/gui/sysConf.cpp | 4 +- 99 files changed, 1145 insertions(+), 1047 deletions(-) diff --git a/papers/format.md b/papers/format.md index 888535b91..79f5446a4 100644 --- a/papers/format.md +++ b/papers/format.md @@ -135,7 +135,9 @@ size | description STR | system name (Japanese) STR | album/category/game name (Japanese) 4f | A-4 tuning + 1 | automatic system name --- | **system definition** + 4f | master volume, 1.0f=100% 2 | total number of channels 2 | number of chips --- | **chip definition (×numChips)** @@ -149,11 +151,10 @@ size | description 4?? | patchbay | - see next section for more details. 1 | automatic patchbay - --- | **song elements** + --- | **song elements (repeated until element type is 0)** 1 | element type - 4?? | pointers to elements - | - a zero pointer means "end of list". - | - if the element is unique, only a single pointer will be present. + 4 | number of elements + 4?? | pointers to elements (×numElements) ``` ## list of sound chips @@ -313,7 +314,7 @@ the following element types are available: 09 | CMNT | song comments* 0a | GROV | groove pattern -* element is unique (read only one pointer and assume the pointer list is over) +* element is unique (number of elements shall be 1) ** first pointer is for instruments, second for wavetables and third for samples ``` diff --git a/src/engine/cmdStream.cpp b/src/engine/cmdStream.cpp index 6b5d9ee93..9060d85a6 100644 --- a/src/engine/cmdStream.cpp +++ b/src/engine/cmdStream.cpp @@ -596,7 +596,7 @@ bool DivCSPlayer::tick() { } if (chan[i].portaSpeed) { - e->dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed*(e->song.linearPitch?e->song.pitchSlideSpeed:1),chan[i].portaTarget)); + e->dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed*(e->song.compatFlags.linearPitch?e->song.compatFlags.pitchSlideSpeed:1),chan[i].portaTarget)); } if (chan[i].arp && !chan[i].portaSpeed) { if (chan[i].arpTicks==0) { diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index c7c3b797f..5c277bb35 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -1082,10 +1082,10 @@ class DivDispatch { #define NOTE_FNUM_BLOCK(x,bits,blk) parent->calcBaseFreqFNumBlock(chipClock,CHIP_FREQBASE,x,bits,blk) // this is for volume scaling calculation. -#define VOL_SCALE_LINEAR(x,y,range) ((parent->song.ceilVolumeScaling)?((((x)*(y))+(range-1))/(range)):(((x)*(y))/(range))) +#define VOL_SCALE_LINEAR(x,y,range) ((parent->song.compatFlags.ceilVolumeScaling)?((((x)*(y))+(range-1))/(range)):(((x)*(y))/(range))) #define VOL_SCALE_LOG(x,y,range) (CLAMP(((x)+(y))-(range),0,(range))) -#define VOL_SCALE_LINEAR_BROKEN(x,y,range) ((parent->song.newVolumeScaling)?(VOL_SCALE_LINEAR(x,y,range)):(VOL_SCALE_LOG(x,y,range))) -#define VOL_SCALE_LOG_BROKEN(x,y,range) ((parent->song.newVolumeScaling)?(VOL_SCALE_LOG(x,y,range)):(VOL_SCALE_LINEAR(x,y,range))) +#define VOL_SCALE_LINEAR_BROKEN(x,y,range) ((parent->song.compatFlags.newVolumeScaling)?(VOL_SCALE_LINEAR(x,y,range)):(VOL_SCALE_LOG(x,y,range))) +#define VOL_SCALE_LOG_BROKEN(x,y,range) ((parent->song.compatFlags.newVolumeScaling)?(VOL_SCALE_LOG(x,y,range)):(VOL_SCALE_LINEAR(x,y,range))) // these are here for convenience. // it is encouraged to use these, since you get an exact value this way. @@ -1098,7 +1098,7 @@ class DivDispatch { if ((x)<(xMin)) (x)=(xMin); \ if ((x)>(xMax)) (x)=(xMax); -#define NEW_ARP_STRAT (parent->song.linearPitch && !parent->song.oldArpStrategy) +#define NEW_ARP_STRAT (parent->song.compatFlags.linearPitch && !parent->song.compatFlags.oldArpStrategy) #define HACKY_LEGATO_MESS chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode && !NEW_ARP_STRAT #endif diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index b9d94c773..b6bb98de4 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -168,7 +168,7 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul return _("FFxx: Stop song"); default: if ((effect&0xf0)==0x90) { - if (song.oldSampleOffset) { + if (song.compatFlags.oldSampleOffset) { return _("9xxx: Set sample offset*256"); } switch (effect) { @@ -205,7 +205,7 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul void DivEngine::calcSongTimestamps() { if (curSubSong!=NULL) { - curSubSong->calcTimestamps(song.chans,song.grooves,song.jumpTreatment,song.ignoreJumpAtEnd,song.brokenSpeedSel,song.delayBehavior); + curSubSong->calcTimestamps(song.chans,song.grooves,song.compatFlags.jumpTreatment,song.compatFlags.ignoreJumpAtEnd,song.compatFlags.brokenSpeedSel,song.compatFlags.delayBehavior); } } @@ -1813,7 +1813,7 @@ int DivEngine::calcBaseFreq(double clock, double divider, int note, bool period) }*/ double DivEngine::calcBaseFreq(double clock, double divider, int note, bool period) { - if (song.linearPitch) { // linear + if (song.compatFlags.linearPitch) { // linear return (note<<7); } double base=(period?(song.tuning*0.0625):song.tuning)*pow(2.0,(float)(note+3)/12.0); @@ -1863,7 +1863,7 @@ double DivEngine::calcBaseFreq(double clock, double divider, int note, bool peri return bf|((block)<<(bits)); int DivEngine::calcBaseFreqFNumBlock(double clock, double divider, int note, int bits, int fixedBlock) { - if (song.linearPitch) { // linear + if (song.compatFlags.linearPitch) { // linear return (note<<7); } int bf=calcBaseFreq(clock,divider,note,false); @@ -1876,10 +1876,10 @@ int DivEngine::calcBaseFreqFNumBlock(double clock, double divider, int note, int int DivEngine::calcFreq(int base, int pitch, int arp, bool arpFixed, bool period, int octave, int pitch2, double clock, double divider, int blockBits, int fixedBlock) { // linear pitch - if (song.linearPitch) { + if (song.compatFlags.linearPitch) { // do frequency calculation here int nbase=base+pitch+pitch2; - if (!song.oldArpStrategy) { + if (!song.compatFlags.oldArpStrategy) { if (arpFixed) { nbase=(arp<<7)+pitch+pitch2; } else { @@ -2178,7 +2178,7 @@ void DivEngine::reset() { chan[i].volMax=(disCont[song.dispatchOfChan[i]].dispatch->dispatch(DivCommand(DIV_CMD_GET_VOLMAX,song.dispatchChanOfChan[i]))<<8)|0xff; } chan[i].volume=chan[i].volMax; - if (!song.linearPitch) chan[i].vibratoFine=4; + if (!song.compatFlags.linearPitch) chan[i].vibratoFine=4; } extValue=0; extValuePresent=0; @@ -2436,7 +2436,7 @@ double DivEngine::getSamplePreviewRate() { } double DivEngine::getCenterRate() { - return song.oldCenterRate?8363.0:8372.0; + return song.compatFlags.oldCenterRate?8363.0:8372.0; } String DivEngine::getConfigPath() { diff --git a/src/engine/engine.h b/src/engine/engine.h index 16785587b..5a173c829 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -55,7 +55,7 @@ class DivWorkPool; #define DIV_UNSTABLE -#define DIV_VERSION "inf2 - DO NOT SAVE!" +#define DIV_VERSION "inf2/dev240 - DO NOT LOAD!" #define DIV_ENGINE_VERSION 240 // for imports #define DIV_VERSION_MOD 0xff01 diff --git a/src/engine/fileOps/dmf.cpp b/src/engine/fileOps/dmf.cpp index 2557e4b6d..a009848bc 100644 --- a/src/engine/fileOps/dmf.cpp +++ b/src/engine/fileOps/dmf.cpp @@ -172,56 +172,56 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { // compatibility flags if (!getConfInt("noDMFCompat",0)) { - ds.limitSlides=true; - ds.linearPitch=1; - ds.loopModality=0; - ds.properNoiseLayout=false; - ds.waveDutyIsVol=false; + ds.compatFlags.limitSlides=true; + ds.compatFlags.linearPitch=1; + ds.compatFlags.loopModality=0; + ds.compatFlags.properNoiseLayout=false; + ds.compatFlags.waveDutyIsVol=false; // TODO: WHAT?! geodude.dmf fails when this is true // but isn't that how Defle behaves??? - ds.resetMacroOnPorta=false; - ds.legacyVolumeSlides=true; - ds.compatibleArpeggio=true; - ds.noteOffResetsSlides=true; - ds.targetResetsSlides=true; - ds.arpNonPorta=false; - ds.algMacroBehavior=false; - ds.brokenShortcutSlides=false; - ds.ignoreDuplicateSlides=true; - ds.brokenDACMode=true; - ds.oneTickCut=false; - ds.newInsTriggersInPorta=true; - ds.arp0Reset=true; - ds.brokenSpeedSel=true; - ds.noSlidesOnFirstTick=false; - ds.rowResetsArpPos=false; - ds.ignoreJumpAtEnd=true; - ds.buggyPortaAfterSlide=true; - ds.gbInsAffectsEnvelope=true; - ds.ignoreDACModeOutsideIntendedChannel=false; - ds.e1e2AlsoTakePriority=true; - ds.fbPortaPause=true; - ds.snDutyReset=true; - ds.oldOctaveBoundary=false; - ds.noOPN2Vol=true; - ds.newVolumeScaling=false; - ds.volMacroLinger=false; - ds.brokenOutVol=true; - ds.brokenOutVol2=true; - ds.e1e2StopOnSameNote=true; - ds.brokenPortaArp=false; - ds.snNoLowPeriods=true; - ds.disableSampleMacro=true; - ds.preNoteNoEffect=true; - ds.oldDPCM=true; - ds.delayBehavior=0; - ds.jumpTreatment=2; - ds.oldAlwaysSetVolume=true; + ds.compatFlags.resetMacroOnPorta=false; + ds.compatFlags.legacyVolumeSlides=true; + ds.compatFlags.compatibleArpeggio=true; + ds.compatFlags.noteOffResetsSlides=true; + ds.compatFlags.targetResetsSlides=true; + ds.compatFlags.arpNonPorta=false; + ds.compatFlags.algMacroBehavior=false; + ds.compatFlags.brokenShortcutSlides=false; + ds.compatFlags.ignoreDuplicateSlides=true; + ds.compatFlags.brokenDACMode=true; + ds.compatFlags.oneTickCut=false; + ds.compatFlags.newInsTriggersInPorta=true; + ds.compatFlags.arp0Reset=true; + ds.compatFlags.brokenSpeedSel=true; + ds.compatFlags.noSlidesOnFirstTick=false; + ds.compatFlags.rowResetsArpPos=false; + ds.compatFlags.ignoreJumpAtEnd=true; + ds.compatFlags.buggyPortaAfterSlide=true; + ds.compatFlags.gbInsAffectsEnvelope=true; + ds.compatFlags.ignoreDACModeOutsideIntendedChannel=false; + ds.compatFlags.e1e2AlsoTakePriority=true; + ds.compatFlags.fbPortaPause=true; + ds.compatFlags.snDutyReset=true; + ds.compatFlags.oldOctaveBoundary=false; + ds.compatFlags.noOPN2Vol=true; + ds.compatFlags.newVolumeScaling=false; + ds.compatFlags.volMacroLinger=false; + ds.compatFlags.brokenOutVol=true; + ds.compatFlags.brokenOutVol2=true; + ds.compatFlags.e1e2StopOnSameNote=true; + ds.compatFlags.brokenPortaArp=false; + ds.compatFlags.snNoLowPeriods=true; + ds.compatFlags.disableSampleMacro=true; + ds.compatFlags.preNoteNoEffect=true; + ds.compatFlags.oldDPCM=true; + ds.compatFlags.delayBehavior=0; + ds.compatFlags.jumpTreatment=2; + ds.compatFlags.oldAlwaysSetVolume=true; // 1.1 compat flags if (ds.version>24) { - ds.waveDutyIsVol=true; - ds.legacyVolumeSlides=false; + ds.compatFlags.waveDutyIsVol=true; + ds.compatFlags.legacyVolumeSlides=false; } // Neo Geo detune is caused by Defle running Neo Geo at the wrong clock. diff --git a/src/engine/fileOps/fc.cpp b/src/engine/fileOps/fc.cpp index 027dda971..0b45e7ac6 100644 --- a/src/engine/fileOps/fc.cpp +++ b/src/engine/fileOps/fc.cpp @@ -147,12 +147,12 @@ bool DivEngine::loadFC(unsigned char* file, size_t len) { DivSong ds; ds.tuning=436.0; ds.version=DIV_VERSION_FC; - //ds.linearPitch=0; - //ds.pitchMacroIsLinear=false; - //ds.noSlidesOnFirstTick=true; - //ds.rowResetsArpPos=true; - ds.pitchSlideSpeed=8; - ds.ignoreJumpAtEnd=false; + //ds.compatFlags.linearPitch=0; + //ds.compatFlags.pitchMacroIsLinear=false; + //ds.compatFlags.noSlidesOnFirstTick=true; + //ds.compatFlags.rowResetsArpPos=true; + ds.compatFlags.pitchSlideSpeed=8; + ds.compatFlags.ignoreJumpAtEnd=false; // load here if (!reader.seek(0,SEEK_SET)) { diff --git a/src/engine/fileOps/ftm.cpp b/src/engine/fileOps/ftm.cpp index daf27cb4e..60ebdcd87 100644 --- a/src/engine/fileOps/ftm.cpp +++ b/src/engine/fileOps/ftm.cpp @@ -495,7 +495,7 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si } ds.subsong.clear(); - ds.linearPitch = 0; + ds.compatFlags.linearPitch = 0; unsigned int pal = 0; @@ -2378,7 +2378,7 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si CHECK_BLOCK_VERSION(3); unsigned int linear_pitch = reader.readI(); - ds.linearPitch = linear_pitch == 0 ? 0 : 1; + ds.compatFlags.linearPitch = linear_pitch == 0 ? 0 : 1; if (blockVersion >= 2) { int fineTuneCents = reader.readC() * 100; diff --git a/src/engine/fileOps/fur.cpp b/src/engine/fileOps/fur.cpp index 99c1a798a..7f72ade40 100644 --- a/src/engine/fileOps/fur.cpp +++ b/src/engine/fileOps/fur.cpp @@ -673,144 +673,151 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { addWarning("this module was created with a downstream version of Furnace. certain features may not be compatible."); } + if (ds.version>=240) { + logE("not yet! I am still working on it!"); + lastError="not yet! I am still working on it!"; + delete[] file; + return false; + } + if (ds.version>DIV_ENGINE_VERSION) { logW("this module was created with a more recent version of Furnace!"); addWarning("this module was created with a more recent version of Furnace!"); } if (ds.version<37) { // compat flags not stored back then - ds.limitSlides=true; - ds.linearPitch=1; - ds.loopModality=0; + ds.compatFlags.limitSlides=true; + ds.compatFlags.linearPitch=1; + ds.compatFlags.loopModality=0; } if (ds.version<43) { - ds.properNoiseLayout=false; - ds.waveDutyIsVol=false; + ds.compatFlags.properNoiseLayout=false; + ds.compatFlags.waveDutyIsVol=false; } if (ds.version<45) { - ds.resetMacroOnPorta=true; - ds.legacyVolumeSlides=true; - ds.compatibleArpeggio=true; - ds.noteOffResetsSlides=true; - ds.targetResetsSlides=true; + ds.compatFlags.resetMacroOnPorta=true; + ds.compatFlags.legacyVolumeSlides=true; + ds.compatFlags.compatibleArpeggio=true; + ds.compatFlags.noteOffResetsSlides=true; + ds.compatFlags.targetResetsSlides=true; } if (ds.version<46) { - ds.arpNonPorta=true; - ds.algMacroBehavior=true; + ds.compatFlags.arpNonPorta=true; + ds.compatFlags.algMacroBehavior=true; } else { - ds.arpNonPorta=false; - ds.algMacroBehavior=false; + ds.compatFlags.arpNonPorta=false; + ds.compatFlags.algMacroBehavior=false; } if (ds.version<49) { - ds.brokenShortcutSlides=true; + ds.compatFlags.brokenShortcutSlides=true; } if (ds.version<50) { - ds.ignoreDuplicateSlides=false; + ds.compatFlags.ignoreDuplicateSlides=false; } if (ds.version<62) { - ds.stopPortaOnNoteOff=true; + ds.compatFlags.stopPortaOnNoteOff=true; } if (ds.version<64) { - ds.brokenDACMode=false; + ds.compatFlags.brokenDACMode=false; } if (ds.version<65) { - ds.oneTickCut=false; + ds.compatFlags.oneTickCut=false; } if (ds.version<66) { - ds.newInsTriggersInPorta=false; + ds.compatFlags.newInsTriggersInPorta=false; } if (ds.version<69) { - ds.arp0Reset=false; + ds.compatFlags.arp0Reset=false; } if (ds.version<71) { - ds.noSlidesOnFirstTick=false; - ds.rowResetsArpPos=false; - ds.ignoreJumpAtEnd=true; + ds.compatFlags.noSlidesOnFirstTick=false; + ds.compatFlags.rowResetsArpPos=false; + ds.compatFlags.ignoreJumpAtEnd=true; } if (ds.version<72) { - ds.buggyPortaAfterSlide=true; - ds.gbInsAffectsEnvelope=false; + ds.compatFlags.buggyPortaAfterSlide=true; + ds.compatFlags.gbInsAffectsEnvelope=false; } if (ds.version<78) { - ds.sharedExtStat=false; + ds.compatFlags.sharedExtStat=false; } if (ds.version<83) { - ds.ignoreDACModeOutsideIntendedChannel=true; - ds.e1e2AlsoTakePriority=false; + ds.compatFlags.ignoreDACModeOutsideIntendedChannel=true; + ds.compatFlags.e1e2AlsoTakePriority=false; } if (ds.version<84) { - ds.newSegaPCM=false; + ds.compatFlags.newSegaPCM=false; } if (ds.version<85) { - ds.fbPortaPause=true; + ds.compatFlags.fbPortaPause=true; } if (ds.version<86) { - ds.snDutyReset=true; + ds.compatFlags.snDutyReset=true; } if (ds.version<90) { - ds.pitchMacroIsLinear=false; + ds.compatFlags.pitchMacroIsLinear=false; } if (ds.version<97) { - ds.oldOctaveBoundary=true; + ds.compatFlags.oldOctaveBoundary=true; } if (ds.version<97) { // actually should be 98 but yky uses this feature ahead of time - ds.noOPN2Vol=true; + ds.compatFlags.noOPN2Vol=true; } if (ds.version<99) { - ds.newVolumeScaling=false; - ds.volMacroLinger=false; - ds.brokenOutVol=true; + ds.compatFlags.newVolumeScaling=false; + ds.compatFlags.volMacroLinger=false; + ds.compatFlags.brokenOutVol=true; } if (ds.version<100) { - ds.e1e2StopOnSameNote=false; + ds.compatFlags.e1e2StopOnSameNote=false; } if (ds.version<101) { - ds.brokenPortaArp=true; + ds.compatFlags.brokenPortaArp=true; } if (ds.version<108) { - ds.snNoLowPeriods=true; + ds.compatFlags.snNoLowPeriods=true; } if (ds.version<110) { - ds.delayBehavior=1; + ds.compatFlags.delayBehavior=1; } if (ds.version<113) { - ds.jumpTreatment=1; + ds.compatFlags.jumpTreatment=1; } if (ds.version<115) { ds.autoSystem=false; } if (ds.version<117) { - ds.disableSampleMacro=true; + ds.compatFlags.disableSampleMacro=true; } if (ds.version<121) { - ds.brokenOutVol2=false; + ds.compatFlags.brokenOutVol2=false; } if (ds.version<130) { - ds.oldArpStrategy=true; + ds.compatFlags.oldArpStrategy=true; } if (ds.version<138) { - ds.brokenPortaLegato=true; + ds.compatFlags.brokenPortaLegato=true; } if (ds.version<155) { - ds.brokenFMOff=true; + ds.compatFlags.brokenFMOff=true; } if (ds.version<168) { - ds.preNoteNoEffect=true; + ds.compatFlags.preNoteNoEffect=true; } if (ds.version<183) { - ds.oldDPCM=true; + ds.compatFlags.oldDPCM=true; } if (ds.version<184) { - ds.resetArpPhaseOnNewNote=false; + ds.compatFlags.resetArpPhaseOnNewNote=false; } if (ds.version<188) { - ds.ceilVolumeScaling=false; + ds.compatFlags.ceilVolumeScaling=false; } if (ds.version<191) { - ds.oldAlwaysSetVolume=true; + ds.compatFlags.oldAlwaysSetVolume=true; } if (ds.version<200) { - ds.oldSampleOffset=true; + ds.compatFlags.oldSampleOffset=true; } ds.isDMF=false; @@ -1003,89 +1010,89 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { // compatibility flags if (ds.version>=37) { - ds.limitSlides=reader.readC(); - ds.linearPitch=reader.readC(); - ds.loopModality=reader.readC(); + ds.compatFlags.limitSlides=reader.readC(); + ds.compatFlags.linearPitch=reader.readC(); + ds.compatFlags.loopModality=reader.readC(); if (ds.version>=43) { - ds.properNoiseLayout=reader.readC(); + ds.compatFlags.properNoiseLayout=reader.readC(); } else { reader.readC(); } if (ds.version>=43) { - ds.waveDutyIsVol=reader.readC(); + ds.compatFlags.waveDutyIsVol=reader.readC(); } else { reader.readC(); } if (ds.version>=45) { - ds.resetMacroOnPorta=reader.readC(); + ds.compatFlags.resetMacroOnPorta=reader.readC(); } else { reader.readC(); } if (ds.version>=45) { - ds.legacyVolumeSlides=reader.readC(); + ds.compatFlags.legacyVolumeSlides=reader.readC(); } else { reader.readC(); } if (ds.version>=45) { - ds.compatibleArpeggio=reader.readC(); + ds.compatFlags.compatibleArpeggio=reader.readC(); } else { reader.readC(); } if (ds.version>=45) { - ds.noteOffResetsSlides=reader.readC(); + ds.compatFlags.noteOffResetsSlides=reader.readC(); } else { reader.readC(); } if (ds.version>=45) { - ds.targetResetsSlides=reader.readC(); + ds.compatFlags.targetResetsSlides=reader.readC(); } else { reader.readC(); } if (ds.version>=47) { - ds.arpNonPorta=reader.readC(); + ds.compatFlags.arpNonPorta=reader.readC(); } else { reader.readC(); } if (ds.version>=47) { - ds.algMacroBehavior=reader.readC(); + ds.compatFlags.algMacroBehavior=reader.readC(); } else { reader.readC(); } if (ds.version>=49) { - ds.brokenShortcutSlides=reader.readC(); + ds.compatFlags.brokenShortcutSlides=reader.readC(); } else { reader.readC(); } if (ds.version>=50) { - ds.ignoreDuplicateSlides=reader.readC(); + ds.compatFlags.ignoreDuplicateSlides=reader.readC(); } else { reader.readC(); } if (ds.version>=62) { - ds.stopPortaOnNoteOff=reader.readC(); - ds.continuousVibrato=reader.readC(); + ds.compatFlags.stopPortaOnNoteOff=reader.readC(); + ds.compatFlags.continuousVibrato=reader.readC(); } else { reader.readC(); reader.readC(); } if (ds.version>=64) { - ds.brokenDACMode=reader.readC(); + ds.compatFlags.brokenDACMode=reader.readC(); } else { reader.readC(); } if (ds.version>=65) { - ds.oneTickCut=reader.readC(); + ds.compatFlags.oneTickCut=reader.readC(); } else { reader.readC(); } if (ds.version>=66) { - ds.newInsTriggersInPorta=reader.readC(); + ds.compatFlags.newInsTriggersInPorta=reader.readC(); } else { reader.readC(); } if (ds.version>=69) { - ds.arp0Reset=reader.readC(); + ds.compatFlags.arp0Reset=reader.readC(); } else { reader.readC(); } @@ -1167,101 +1174,101 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { if (ds.version>=70) { // extended compat flags - ds.brokenSpeedSel=reader.readC(); + ds.compatFlags.brokenSpeedSel=reader.readC(); if (ds.version>=71) { - ds.noSlidesOnFirstTick=reader.readC(); - ds.rowResetsArpPos=reader.readC(); - ds.ignoreJumpAtEnd=reader.readC(); + ds.compatFlags.noSlidesOnFirstTick=reader.readC(); + ds.compatFlags.rowResetsArpPos=reader.readC(); + ds.compatFlags.ignoreJumpAtEnd=reader.readC(); } else { reader.readC(); reader.readC(); reader.readC(); } if (ds.version>=72) { - ds.buggyPortaAfterSlide=reader.readC(); - ds.gbInsAffectsEnvelope=reader.readC(); + ds.compatFlags.buggyPortaAfterSlide=reader.readC(); + ds.compatFlags.gbInsAffectsEnvelope=reader.readC(); } else { reader.readC(); reader.readC(); } if (ds.version>=78) { - ds.sharedExtStat=reader.readC(); + ds.compatFlags.sharedExtStat=reader.readC(); } else { reader.readC(); } if (ds.version>=83) { - ds.ignoreDACModeOutsideIntendedChannel=reader.readC(); - ds.e1e2AlsoTakePriority=reader.readC(); + ds.compatFlags.ignoreDACModeOutsideIntendedChannel=reader.readC(); + ds.compatFlags.e1e2AlsoTakePriority=reader.readC(); } else { reader.readC(); reader.readC(); } if (ds.version>=84) { - ds.newSegaPCM=reader.readC(); + ds.compatFlags.newSegaPCM=reader.readC(); } else { reader.readC(); } if (ds.version>=85) { - ds.fbPortaPause=reader.readC(); + ds.compatFlags.fbPortaPause=reader.readC(); } else { reader.readC(); } if (ds.version>=86) { - ds.snDutyReset=reader.readC(); + ds.compatFlags.snDutyReset=reader.readC(); } else { reader.readC(); } if (ds.version>=90) { - ds.pitchMacroIsLinear=reader.readC(); + ds.compatFlags.pitchMacroIsLinear=reader.readC(); } else { reader.readC(); } if (ds.version>=94) { - ds.pitchSlideSpeed=reader.readC(); + ds.compatFlags.pitchSlideSpeed=reader.readC(); } else { reader.readC(); } if (ds.version>=97) { - ds.oldOctaveBoundary=reader.readC(); + ds.compatFlags.oldOctaveBoundary=reader.readC(); } else { reader.readC(); } if (ds.version>=98) { - ds.noOPN2Vol=reader.readC(); + ds.compatFlags.noOPN2Vol=reader.readC(); } else { reader.readC(); } if (ds.version>=99) { - ds.newVolumeScaling=reader.readC(); - ds.volMacroLinger=reader.readC(); - ds.brokenOutVol=reader.readC(); + ds.compatFlags.newVolumeScaling=reader.readC(); + ds.compatFlags.volMacroLinger=reader.readC(); + ds.compatFlags.brokenOutVol=reader.readC(); } else { reader.readC(); reader.readC(); reader.readC(); } if (ds.version>=100) { - ds.e1e2StopOnSameNote=reader.readC(); + ds.compatFlags.e1e2StopOnSameNote=reader.readC(); } else { reader.readC(); } if (ds.version>=101) { - ds.brokenPortaArp=reader.readC(); + ds.compatFlags.brokenPortaArp=reader.readC(); } else { reader.readC(); } if (ds.version>=108) { - ds.snNoLowPeriods=reader.readC(); + ds.compatFlags.snNoLowPeriods=reader.readC(); } else { reader.readC(); } if (ds.version>=110) { - ds.delayBehavior=reader.readC(); + ds.compatFlags.delayBehavior=reader.readC(); } else { reader.readC(); } if (ds.version>=113) { - ds.jumpTreatment=reader.readC(); + ds.compatFlags.jumpTreatment=reader.readC(); } else { reader.readC(); } @@ -1271,17 +1278,17 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { reader.readC(); } if (ds.version>=117) { - ds.disableSampleMacro=reader.readC(); + ds.compatFlags.disableSampleMacro=reader.readC(); } else { reader.readC(); } if (ds.version>=121) { - ds.brokenOutVol2=reader.readC(); + ds.compatFlags.brokenOutVol2=reader.readC(); } else { reader.readC(); } if (ds.version>=130) { - ds.oldArpStrategy=reader.readC(); + ds.compatFlags.oldArpStrategy=reader.readC(); } else { reader.readC(); } @@ -1341,39 +1348,39 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { if (ds.version>=136) ds.patchbayAuto=reader.readC(); if (ds.version>=138) { - ds.brokenPortaLegato=reader.readC(); + ds.compatFlags.brokenPortaLegato=reader.readC(); if (ds.version>=155) { - ds.brokenFMOff=reader.readC(); + ds.compatFlags.brokenFMOff=reader.readC(); } else { reader.readC(); } if (ds.version>=168) { - ds.preNoteNoEffect=reader.readC(); + ds.compatFlags.preNoteNoEffect=reader.readC(); } else { reader.readC(); } if (ds.version>=183) { - ds.oldDPCM=reader.readC(); + ds.compatFlags.oldDPCM=reader.readC(); } else { reader.readC(); } if (ds.version>=184) { - ds.resetArpPhaseOnNewNote=reader.readC(); + ds.compatFlags.resetArpPhaseOnNewNote=reader.readC(); } else { reader.readC(); } if (ds.version>=188) { - ds.ceilVolumeScaling=reader.readC(); + ds.compatFlags.ceilVolumeScaling=reader.readC(); } else { reader.readC(); } if (ds.version>=191) { - ds.oldAlwaysSetVolume=reader.readC(); + ds.compatFlags.oldAlwaysSetVolume=reader.readC(); } else { reader.readC(); } if (ds.version>=200) { - ds.oldSampleOffset=reader.readC(); + ds.compatFlags.oldSampleOffset=reader.readC(); } else { reader.readC(); } @@ -2127,9 +2134,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { } // warn on partial pitch linearity - if (ds.linearPitch>1) { - ds.linearPitch=1; - } else if (ds.version<237 && ds.linearPitch!=0) { + if (ds.compatFlags.linearPitch>1) { + ds.compatFlags.linearPitch=1; + } else if (ds.version<237 && ds.compatFlags.linearPitch!=0) { addWarning("this song used partial pitch linearity, which has been removed from Furnace. you may have to adjust your song."); } ds.recalcChans(); @@ -2174,17 +2181,15 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { std::vector wavePtr; std::vector samplePtr; std::vector patPtr; + std::vector groovePtr; int assetDirPtr[3]; - size_t ptrSeek, subSongPtrSeek, sysFlagsPtrSeek, blockStartSeek, blockEndSeek, assetDirPtrSeek; - size_t subSongIndex=0; - DivSubSong* subSong=song.subsong[subSongIndex]; - warnings=""; + int compatFlagPtr=0; + int commentPtr=0; + size_t blockStartSeek, blockEndSeek; + size_t sng2PtrSeek=0, flagPtrSeek=0, adirPtrSeek=0, ins2PtrSeek=0, wavePtrSeek=0, smp2PtrSeek=0, patnPtrSeek=0, cflgPtrSeek=0; + size_t cmntPtrSeek=0, grovPtrSeek=0; - // please remove once INF2 is ready. - logE("do not save yet! I still am working on it!"); - lastError="do not save yet! I still am working on it!"; - saveLock.unlock(); - return NULL; + warnings=""; // fail if values are out of range /* @@ -2271,227 +2276,131 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { } /// SONG INFO - w->write("INFO",4); + w->write("INF2",4); blockStartSeek=w->tell(); w->writeI(0); - w->writeC(subSong->timeBase); - // these are for compatibility - w->writeC(subSong->speeds.val[0]); - w->writeC((subSong->speeds.len>=2)?subSong->speeds.val[1]:subSong->speeds.val[0]); - w->writeC(subSong->arpLen); - w->writeF(subSong->hz); - w->writeS(subSong->patLen); - w->writeS(subSong->ordersLen); - w->writeC(subSong->hilightA); - w->writeC(subSong->hilightB); - w->writeS(song.insLen); - w->writeS(song.waveLen); - w->writeS(song.sampleLen); - w->writeI(patsToWrite.size()); - - for (int i=0; i=song.systemLen) { - w->writeC(0); - } else { - w->writeC(systemToFileFur(song.system[i])); - } - } - - for (int i=0; iwriteC(song.systemVol[i]*64.0f); - } - - for (int i=0; iwriteC(song.systemPan[i]*127.0f); - } - - // chip flags (we'll seek here later) - sysFlagsPtrSeek=w->tell(); - for (int i=0; iwriteI(0); - } - - // song name + // song information w->writeString(song.name,false); - // song author w->writeString(song.author,false); - - w->writeF(song.tuning); - - // compatibility flags - w->writeC(song.limitSlides); - w->writeC(song.linearPitch); - w->writeC(song.loopModality); - w->writeC(song.properNoiseLayout); - w->writeC(song.waveDutyIsVol); - w->writeC(song.resetMacroOnPorta); - w->writeC(song.legacyVolumeSlides); - w->writeC(song.compatibleArpeggio); - w->writeC(song.noteOffResetsSlides); - w->writeC(song.targetResetsSlides); - w->writeC(song.arpNonPorta); - w->writeC(song.algMacroBehavior); - w->writeC(song.brokenShortcutSlides); - w->writeC(song.ignoreDuplicateSlides); - w->writeC(song.stopPortaOnNoteOff); - w->writeC(song.continuousVibrato); - w->writeC(song.brokenDACMode); - w->writeC(song.oneTickCut); - w->writeC(song.newInsTriggersInPorta); - w->writeC(song.arp0Reset); - - ptrSeek=w->tell(); - // instrument pointers (we'll seek here later) - for (int i=0; iwriteI(0); - } - - // wavetable pointers (we'll seek here later) - for (int i=0; iwriteI(0); - } - - // sample pointers (we'll seek here later) - for (int i=0; iwriteI(0); - } - - // pattern pointers (we'll seek here later) - for (size_t i=0; iwriteI(0); - } - - for (int i=0; iordersLen; j++) { - w->writeC(subSong->orders.ord[i][j]); - } - } - - for (int i=0; iwriteC(subSong->pat[i].effectCols); - } - - for (int i=0; iwriteC( - (subSong->chanShow[i]?1:0)| - (subSong->chanShowChanOsc[i]?2:0) - ); - } - - for (int i=0; iwriteC(subSong->chanCollapse[i]); - } - - for (int i=0; iwriteString(subSong->chanName[i],false); - } - - for (int i=0; iwriteString(subSong->chanShortName[i],false); - } - - w->writeString(song.notes,false); - - w->writeF(song.masterVol); - - // extended compat flags - w->writeC(song.brokenSpeedSel); - w->writeC(song.noSlidesOnFirstTick); - w->writeC(song.rowResetsArpPos); - w->writeC(song.ignoreJumpAtEnd); - w->writeC(song.buggyPortaAfterSlide); - w->writeC(song.gbInsAffectsEnvelope); - w->writeC(song.sharedExtStat); - w->writeC(song.ignoreDACModeOutsideIntendedChannel); - w->writeC(song.e1e2AlsoTakePriority); - w->writeC(song.newSegaPCM); - w->writeC(song.fbPortaPause); - w->writeC(song.snDutyReset); - w->writeC(song.pitchMacroIsLinear); - w->writeC(song.pitchSlideSpeed); - w->writeC(song.oldOctaveBoundary); - w->writeC(song.noOPN2Vol); - w->writeC(song.newVolumeScaling); - w->writeC(song.volMacroLinger); - w->writeC(song.brokenOutVol); - w->writeC(song.e1e2StopOnSameNote); - w->writeC(song.brokenPortaArp); - w->writeC(song.snNoLowPeriods); - w->writeC(song.delayBehavior); - w->writeC(song.jumpTreatment); - w->writeC(song.autoSystem); - w->writeC(song.disableSampleMacro); - w->writeC(song.brokenOutVol2); - w->writeC(song.oldArpStrategy); - - // first subsong virtual tempo - w->writeS(subSong->virtualTempoN); - w->writeS(subSong->virtualTempoD); - - // subsong list - w->writeString(subSong->name,false); - w->writeString(subSong->notes,false); - w->writeC((unsigned char)(song.subsong.size()-1)); - w->writeC(0); // reserved - w->writeC(0); - w->writeC(0); - subSongPtrSeek=w->tell(); - // subsong pointers (we'll seek here later) - for (size_t i=0; i<(song.subsong.size()-1); i++) { - w->writeI(0); - } - - // additional metadata w->writeString(song.systemName,false); w->writeString(song.category,false); w->writeString(song.nameJ,false); w->writeString(song.authorJ,false); w->writeString(song.systemNameJ,false); w->writeString(song.categoryJ,false); + w->writeF(song.tuning); + w->writeC(song.autoSystem); + + // system definition + w->writeF(song.masterVol); + w->writeS(song.chans); + w->writeS(song.systemLen); - // system output config for (int i=0; iwriteS(systemToFileFur(song.system[i])); + w->writeS(song.systemChans[i]); w->writeF(song.systemVol[i]); w->writeF(song.systemPan[i]); w->writeF(song.systemPanFR[i]); } + + // patchbay w->writeI(song.patchbay.size()); for (unsigned int i: song.patchbay) { w->writeI(i); } w->writeC(song.patchbayAuto); - // even more compat flags - w->writeC(song.brokenPortaLegato); - w->writeC(song.brokenFMOff); - w->writeC(song.preNoteNoEffect); - w->writeC(song.oldDPCM); - w->writeC(song.resetArpPhaseOnNewNote); - w->writeC(song.ceilVolumeScaling); - w->writeC(song.oldAlwaysSetVolume); - w->writeC(song.oldSampleOffset); - - // speeds of first song - w->writeC(subSong->speeds.len); - for (int i=0; i<16; i++) { - w->writeC(subSong->speeds.val[i]); - } - - // groove list - w->writeC((unsigned char)song.grooves.size()); - for (const DivGroovePattern& i: song.grooves) { - w->writeC(i.len); - for (int j=0; j<16; j++) { - w->writeC(i.val[j]); + /// song elements + // sub-songs + if (!song.subsong.empty()) { + w->writeC(0x01); + w->writeI(song.subsong.size()); + sng2PtrSeek=w->tell(); + for (size_t i=0; iwriteI(0); } } - - // asset dir pointers (we'll seek here later) - assetDirPtrSeek=w->tell(); - w->writeI(0); - w->writeI(0); - w->writeI(0); + // chip flags + if (true) { + w->writeC(0x02); + w->writeI(song.systemLen); + flagPtrSeek=w->tell(); + for (int i=0; iwriteI(0); + } + } + // asset directories + if (true) { + w->writeC(0x03); + w->writeI(3); + adirPtrSeek=w->tell(); + w->writeI(0); + w->writeI(0); + w->writeI(0); + } + // instruments + if (!song.ins.empty()) { + w->writeC(0x04); + w->writeI(song.ins.size()); + ins2PtrSeek=w->tell(); + for (size_t i=0; iwriteI(0); + } + } + // wavetables + if (!song.wave.empty()) { + w->writeC(0x05); + w->writeI(song.wave.size()); + wavePtrSeek=w->tell(); + for (size_t i=0; iwriteI(0); + } + } + // samples + if (!song.sample.empty()) { + w->writeC(0x06); + w->writeI(song.sample.size()); + smp2PtrSeek=w->tell(); + for (size_t i=0; iwriteI(0); + } + } + // patterns + if (!patsToWrite.empty()) { + w->writeC(0x07); + w->writeI(patsToWrite.size()); + patnPtrSeek=w->tell(); + for (size_t i=0; iwriteI(0); + } + } + // compat flags + if (!song.compatFlags.areDefaults()) { + w->writeC(0x08); + w->writeI(1); + cflgPtrSeek=w->tell(); + w->writeI(0); + } + // song comments + if (!song.notes.empty()) { + w->writeC(0x09); + w->writeI(1); + cmntPtrSeek=w->tell(); + w->writeI(0); + } + // groove patterns + if (!song.grooves.empty()) { + w->writeC(0x0a); + w->writeI(song.grooves.size()); + grovPtrSeek=w->tell(); + for (size_t i=0; iwriteI(0); + } + } + + w->writeC(0); blockEndSeek=w->tell(); w->seek(blockStartSeek,SEEK_SET); @@ -2499,68 +2408,10 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->seek(0,SEEK_END); /// SUBSONGS - subSongPtr.reserve(song.subsong.size() - 1); - for (subSongIndex=1; subSongIndextell()); - w->write("SONG",4); - blockStartSeek=w->tell(); - w->writeI(0); - - w->writeC(subSong->timeBase); - w->writeC(subSong->speeds.val[0]); - w->writeC((subSong->speeds.len>=2)?subSong->speeds.val[1]:subSong->speeds.val[0]); - w->writeC(subSong->arpLen); - w->writeF(subSong->hz); - w->writeS(subSong->patLen); - w->writeS(subSong->ordersLen); - w->writeC(subSong->hilightA); - w->writeC(subSong->hilightB); - w->writeS(subSong->virtualTempoN); - w->writeS(subSong->virtualTempoD); - - w->writeString(subSong->name,false); - w->writeString(subSong->notes,false); - - for (int i=0; iordersLen; j++) { - w->writeC(subSong->orders.ord[i][j]); - } - } - - for (int i=0; iwriteC(subSong->pat[i].effectCols); - } - - for (int i=0; iwriteC( - (subSong->chanShow[i]?1:0)| - (subSong->chanShowChanOsc[i]?2:0) - ); - } - - for (int i=0; iwriteC(subSong->chanCollapse[i]); - } - - for (int i=0; iwriteString(subSong->chanName[i],false); - } - - for (int i=0; iwriteString(subSong->chanShortName[i],false); - } - - // speeds - w->writeC(subSong->speeds.len); - for (int i=0; i<16; i++) { - w->writeC(subSong->speeds.val[i]); - } - - blockEndSeek=w->tell(); - w->seek(blockStartSeek,SEEK_SET); - w->writeI(blockEndSeek-blockStartSeek-4); - w->seek(0,SEEK_END); + song.subsong[i]->putData(w,song.chans); } /// CHIP FLAGS @@ -2585,6 +2436,27 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->seek(0,SEEK_END); } + /// COMPAT FLAGS + if (!song.compatFlags.areDefaults()) { + compatFlagPtr=w->tell(); + song.compatFlags.putData(w); + } + + /// SONG COMMENTS + if (!song.notes.empty()) { + commentPtr=w->tell(); + w->write("CMNT",4); + blockStartSeek=w->tell(); + w->writeI(0); + + w->writeString(song.notes,false); + + blockEndSeek=w->tell(); + w->seek(blockStartSeek,SEEK_SET); + w->writeI(blockEndSeek-blockStartSeek-4); + w->seek(0,SEEK_END); + } + /// ASSET DIRECTORIES assetDirPtr[0]=w->tell(); putAssetDirData(w,song.insDir); @@ -2724,43 +2596,71 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { } /// POINTERS - w->seek(ptrSeek,SEEK_SET); - - for (int i=0; iwriteI(insPtr[i]); + // sub-songs + if (sng2PtrSeek) { + w->seek(sng2PtrSeek,SEEK_SET); + for (size_t i=0; i<=song.subsong.size(); i++) { + w->writeI(subSongPtr[i]); + } } - - // wavetable pointers - for (int i=0; iwriteI(wavePtr[i]); + // chip flags + if (flagPtrSeek) { + w->seek(flagPtrSeek,SEEK_SET); + for (int i=0; iwriteI(sysFlagsPtr[i]); + } } - - // sample pointers - for (int i=0; iwriteI(samplePtr[i]); + // asset directories + if (adirPtrSeek) { + w->seek(adirPtrSeek,SEEK_SET); + w->writeI(assetDirPtr[0]); + w->writeI(assetDirPtr[1]); + w->writeI(assetDirPtr[2]); } - - // pattern pointers - for (int i: patPtr) { - w->writeI(i); + // instruments + if (ins2PtrSeek) { + w->seek(ins2PtrSeek,SEEK_SET); + for (int i: insPtr) { + w->writeI(i); + } } - - // subsong pointers - w->seek(subSongPtrSeek,SEEK_SET); - for (size_t i=0; i<(song.subsong.size()-1); i++) { - w->writeI(subSongPtr[i]); + // wavetables + if (wavePtrSeek) { + w->seek(wavePtrSeek,SEEK_SET); + for (int i: wavePtr) { + w->writeI(i); + } } - - // flag pointers - w->seek(sysFlagsPtrSeek,SEEK_SET); - for (size_t i=0; iwriteI(sysFlagsPtr[i]); + // samples + if (smp2PtrSeek) { + w->seek(smp2PtrSeek,SEEK_SET); + for (int i: samplePtr) { + w->writeI(i); + } } - - // asset dir pointers - w->seek(assetDirPtrSeek,SEEK_SET); - for (size_t i=0; i<3; i++) { - w->writeI(assetDirPtr[i]); + // patterns + if (patnPtrSeek) { + w->seek(patnPtrSeek,SEEK_SET); + for (int i: patPtr) { + w->writeI(i); + } + } + // compat flags + if (cflgPtrSeek) { + w->seek(cflgPtrSeek,SEEK_SET); + w->writeI(compatFlagPtr); + } + // song comments + if (cmntPtrSeek) { + w->seek(cmntPtrSeek,SEEK_SET); + w->writeI(commentPtr); + } + // groove patterns + if (grovPtrSeek) { + w->seek(grovPtrSeek,SEEK_SET); + for (int i: groovePtr) { + w->writeI(i); + } } saveLock.unlock(); diff --git a/src/engine/fileOps/it.cpp b/src/engine/fileOps/it.cpp index 3ea6c2bfc..6424a8f41 100644 --- a/src/engine/fileOps/it.cpp +++ b/src/engine/fileOps/it.cpp @@ -219,10 +219,10 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { try { DivSong ds; ds.version=DIV_VERSION_IT; - ds.noSlidesOnFirstTick=true; - ds.rowResetsArpPos=true; - ds.ignoreJumpAtEnd=false; - ds.pitchSlideSpeed=8; + ds.compatFlags.noSlidesOnFirstTick=true; + ds.compatFlags.rowResetsArpPos=true; + ds.compatFlags.ignoreJumpAtEnd=false; + ds.compatFlags.pitchSlideSpeed=8; logV("Impulse Tracker module"); @@ -277,9 +277,9 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { } if (flags&8) { - ds.linearPitch=1; + ds.compatFlags.linearPitch=1; } else { - ds.linearPitch=0; + ds.compatFlags.linearPitch=0; } unsigned char globalVol=reader.readC(); @@ -1667,7 +1667,7 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { for (int i=0; i<(maxChan+32)>>5; i++) { ds.system[i]=DIV_SYSTEM_ES5506; ds.systemFlags[i].set("amigaVol",true); - if (!ds.linearPitch) { + if (!ds.compatFlags.linearPitch) { ds.systemFlags[i].set("amigaPitch",true); } } diff --git a/src/engine/fileOps/mod.cpp b/src/engine/fileOps/mod.cpp index 774a0004b..67e87bc68 100644 --- a/src/engine/fileOps/mod.cpp +++ b/src/engine/fileOps/mod.cpp @@ -41,11 +41,11 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { DivSong ds; ds.tuning=436.0; ds.version=DIV_VERSION_MOD; - ds.linearPitch=0; - ds.noSlidesOnFirstTick=true; - ds.rowResetsArpPos=true; - ds.ignoreJumpAtEnd=false; - ds.delayBehavior=0; + ds.compatFlags.linearPitch=0; + ds.compatFlags.noSlidesOnFirstTick=true; + ds.compatFlags.rowResetsArpPos=true; + ds.compatFlags.ignoreJumpAtEnd=false; + ds.compatFlags.delayBehavior=0; int insCount=31; bool bypassLimits=false; diff --git a/src/engine/fileOps/s3m.cpp b/src/engine/fileOps/s3m.cpp index 3c03ad2d9..4537b3f66 100644 --- a/src/engine/fileOps/s3m.cpp +++ b/src/engine/fileOps/s3m.cpp @@ -79,12 +79,12 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { try { DivSong ds; ds.version=DIV_VERSION_S3M; - ds.linearPitch=0; - ds.pitchMacroIsLinear=false; - ds.noSlidesOnFirstTick=true; - ds.rowResetsArpPos=true; - ds.ignoreJumpAtEnd=false; - ds.pitchSlideSpeed=12; + ds.compatFlags.linearPitch=0; + ds.compatFlags.pitchMacroIsLinear=false; + ds.compatFlags.noSlidesOnFirstTick=true; + ds.compatFlags.rowResetsArpPos=true; + ds.compatFlags.ignoreJumpAtEnd=false; + ds.compatFlags.pitchSlideSpeed=12; logV("Scream Tracker 3 module"); diff --git a/src/engine/fileOps/tfm.cpp b/src/engine/fileOps/tfm.cpp index 7ea370f1d..75100351a 100644 --- a/src/engine/fileOps/tfm.cpp +++ b/src/engine/fileOps/tfm.cpp @@ -551,7 +551,7 @@ bool DivEngine::loadTFMv1(unsigned char* file, size_t len) { ds.systemLen=1; ds.system[0]=DIV_SYSTEM_YM2612; - ds.loopModality=1; + ds.compatFlags.loopModality=1; unsigned char speed=reader.readCNoRLE(); unsigned char interleaveFactor=reader.readCNoRLE(); @@ -746,7 +746,7 @@ bool DivEngine::loadTFMv2(unsigned char* file, size_t len) { ds.systemLen=1; ds.system[0]=DIV_SYSTEM_YM2612; - ds.loopModality=1; + ds.compatFlags.loopModality=1; unsigned char magic[8]={0}; diff --git a/src/engine/fileOps/xm.cpp b/src/engine/fileOps/xm.cpp index 57e59ab3a..73c9a1697 100644 --- a/src/engine/fileOps/xm.cpp +++ b/src/engine/fileOps/xm.cpp @@ -207,12 +207,12 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { try { DivSong ds; ds.version=DIV_VERSION_XM; - //ds.linearPitch=0; - //ds.pitchMacroIsLinear=false; - ds.noSlidesOnFirstTick=true; - ds.rowResetsArpPos=true; - ds.ignoreJumpAtEnd=false; - ds.pitchSlideSpeed=8; + //ds.compatFlags.linearPitch=0; + //ds.compatFlags.pitchMacroIsLinear=false; + ds.compatFlags.noSlidesOnFirstTick=true; + ds.compatFlags.rowResetsArpPos=true; + ds.compatFlags.ignoreJumpAtEnd=false; + ds.compatFlags.pitchSlideSpeed=8; logV("Extended Module"); @@ -251,7 +251,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { unsigned short totalChans=reader.readS(); unsigned short patCount=reader.readS(); ds.insLen=(unsigned short)reader.readS(); - ds.linearPitch=(reader.readS()&1)?1:0; + ds.compatFlags.linearPitch=(reader.readS()&1)?1:0; ds.subsong[0]->speeds.val[0]=reader.readS(); ds.subsong[0]->speeds.len=1; double bpm=(unsigned short)reader.readS(); @@ -304,7 +304,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { for (int i=0; i<(totalChans+31)>>5; i++) { ds.system[i]=DIV_SYSTEM_ES5506; ds.systemFlags[i].set("amigaVol",true); - ds.systemFlags[i].set("amigaPitch",(ds.linearPitch==0)); + ds.systemFlags[i].set("amigaPitch",(ds.compatFlags.linearPitch==0)); ds.systemFlags[i].set("volScale",3900); } ds.systemLen=(totalChans+31)>>5; diff --git a/src/engine/macroInt.cpp b/src/engine/macroInt.cpp index 9978c7278..f32a02592 100644 --- a/src/engine/macroInt.cpp +++ b/src/engine/macroInt.cpp @@ -43,7 +43,7 @@ void DivMacroStruct::prepare(DivInstrumentMacro& source, DivEngine* e) { mode=source.mode; type=(source.open>>1)&3; activeRelease=source.open&8; - linger=(source.macroType==DIV_MACRO_VOL && e->song.volMacroLinger); + linger=(source.macroType==DIV_MACRO_VOL && e->song.compatFlags.volMacroLinger); lfoPos=LFO_PHASE; } diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index 69d04193b..d3d9fb676 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -668,7 +668,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].writeVol=true; } @@ -752,9 +752,9 @@ int DivPlatformAmiga::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/arcade.cpp b/src/engine/platform/arcade.cpp index d36b40216..c3de63d51 100644 --- a/src/engine/platform/arcade.cpp +++ b/src/engine/platform/arcade.cpp @@ -260,7 +260,7 @@ void DivPlatformArcade::tick(bool sysTick) { } else { rWrite(chanOffs[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)|((chan[i].chVolL&1)<<6)|((chan[i].chVolR&1)<<7)); } - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[i]|opOffs[j]; DivInstrumentFM::Operator& op=chan[i].state.op[j]; if (isMuted[i] || !op.enable) { @@ -379,7 +379,7 @@ void DivPlatformArcade::tick(bool sysTick) { for (int i=0; i<8; i++) { if (chan[i].freqChanged) { chan[i].freq=chan[i].baseFreq+chan[i].pitch-128+chan[i].pitch2; - if (!parent->song.oldArpStrategy) { + if (!parent->song.compatFlags.oldArpStrategy) { if (chan[i].fixedArp) { chan[i].freq=(chan[i].baseNoteOverride<<7)+chan[i].pitch-128+chan[i].pitch2; } else { @@ -862,7 +862,7 @@ int DivPlatformArcade::dispatch(DivCommand c) { return 127; break; case DIV_CMD_PRE_PORTA: - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_LINEAR(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_LINEAR(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_PRE_NOTE: diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index f32437737..a5458c42a 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -716,7 +716,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } //chan[c.chan].keyOn=true; @@ -735,7 +735,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (!(chan[c.chan].nextPSGMode.val&8)) { @@ -942,9 +942,9 @@ int DivPlatformAY8910::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AY)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AY)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_PRE_NOTE: diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 653ffdc13..d7454b4d2 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -544,7 +544,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } //chan[c.chan].keyOn=true; @@ -563,7 +563,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (!(chan[c.chan].nextPSGMode.val&8)) { @@ -764,9 +764,9 @@ int DivPlatformAY8930::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AY8930)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AY8930)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_PRE_NOTE: diff --git a/src/engine/platform/bifurcator.cpp b/src/engine/platform/bifurcator.cpp index 200a59dec..f67f69f50 100644 --- a/src/engine/platform/bifurcator.cpp +++ b/src/engine/platform/bifurcator.cpp @@ -176,7 +176,7 @@ int DivPlatformBifurcator::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -250,9 +250,9 @@ int DivPlatformBifurcator::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_BIFURCATOR_STATE_LOAD: diff --git a/src/engine/platform/bubsyswsg.cpp b/src/engine/platform/bubsyswsg.cpp index 5b615dbba..d6c07f445 100644 --- a/src/engine/platform/bubsyswsg.cpp +++ b/src/engine/platform/bubsyswsg.cpp @@ -164,7 +164,7 @@ int DivPlatformBubSysWSG::dispatch(DivCommand c) { chan[c.chan].keyOn=true; rWrite(2+c.chan,(chan[c.chan].wave<<5)|chan[c.chan].vol); chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (chan[c.chan].wave<0) { @@ -243,9 +243,9 @@ int DivPlatformBubSysWSG::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SCC)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SCC)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/c140.cpp b/src/engine/platform/c140.cpp index 559d7225f..f6ea8893a 100644 --- a/src/engine/platform/c140.cpp +++ b/src/engine/platform/c140.cpp @@ -357,7 +357,7 @@ int DivPlatformC140::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].volChangedL=true; chan[c.chan].volChangedR=true; @@ -445,9 +445,9 @@ int DivPlatformC140::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index d2615a9be..51b1f25e2 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -574,12 +574,12 @@ int DivPlatformC64::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta || parent->song.preNoteNoEffect) { + if (parent->song.compatFlags.resetMacroOnPorta || parent->song.compatFlags.preNoteNoEffect) { chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_C64)); chan[c.chan].keyOn=true; } } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_PRE_NOTE: diff --git a/src/engine/platform/dave.cpp b/src/engine/platform/dave.cpp index 9e12ef095..365f358b5 100644 --- a/src/engine/platform/dave.cpp +++ b/src/engine/platform/dave.cpp @@ -358,7 +358,7 @@ int DivPlatformDave::dispatch(DivCommand c) { chan[c.chan].keyOn=true; chan[c.chan].writeVol=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } chan[c.chan].insChanged=false; @@ -471,9 +471,9 @@ int DivPlatformDave::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_DAVE)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_DAVE)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/es5506.cpp b/src/engine/platform/es5506.cpp index 3160781f4..6086b1d10 100644 --- a/src/engine/platform/es5506.cpp +++ b/src/engine/platform/es5506.cpp @@ -23,7 +23,7 @@ #include #define PITCH_OFFSET ((double)(16*2048*(chanMax+1))) -#define NOTE_ES5506(c,note) ((amigaPitch && !parent->song.linearPitch)?parent->calcBaseFreq(COLOR_NTSC*16,chan[c].pcm.freqOffs,note,true):parent->calcBaseFreq(chipClock,chan[c].pcm.freqOffs,note,false)) +#define NOTE_ES5506(c,note) ((amigaPitch && !parent->song.compatFlags.linearPitch)?parent->calcBaseFreq(COLOR_NTSC*16,chan[c].pcm.freqOffs,note,true):parent->calcBaseFreq(chipClock,chan[c].pcm.freqOffs,note,false)) #define rWrite(a,...) {if(!skipRegisterWrites) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__)); }} #define immWrite(a,...) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__));} @@ -603,7 +603,7 @@ void DivPlatformES5506::tick(bool sysTick) { const unsigned int length=s->samples-1; const unsigned int end=start+(length<<11); const unsigned int nextBank=(offES5506>>22)&3; - const double nextFreqOffs=((amigaPitch && !parent->song.linearPitch)?16:PITCH_OFFSET)*off; + const double nextFreqOffs=((amigaPitch && !parent->song.compatFlags.linearPitch)?16:PITCH_OFFSET)*off; chan[i].pcm.loopMode=loopMode; chan[i].pcm.bank=nextBank; chan[i].pcm.start=start; @@ -746,7 +746,7 @@ void DivPlatformES5506::tick(bool sysTick) { chan[i].pcm.nextPos=0; } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - if (amigaPitch && !parent->song.linearPitch) { + if (amigaPitch && !parent->song.compatFlags.linearPitch) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch*16,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,2,chan[i].pitch2*16,16*COLOR_NTSC,chan[i].pcm.freqOffs); chan[i].freq=PITCH_OFFSET*(COLOR_NTSC/chan[i].freq)/(chipClock/16.0); chan[i].freq=CLAMP(chan[i].freq,0,0x1ffff); @@ -767,7 +767,7 @@ void DivPlatformES5506::tick(bool sysTick) { } chan[i].pcm.loopStart=(chan[i].pcm.start+(s->loopStart<<11))&0xfffff800; chan[i].pcm.loopEnd=(chan[i].pcm.start+((s->loopEnd)<<11))&0xffffff80; - chan[i].pcm.freqOffs=((amigaPitch && !parent->song.linearPitch)?16:PITCH_OFFSET)*off; + chan[i].pcm.freqOffs=((amigaPitch && !parent->song.compatFlags.linearPitch)?16:PITCH_OFFSET)*off; unsigned int startPos=chan[i].pcm.direction?chan[i].pcm.end:chan[i].pcm.start; if (chan[i].pcm.nextPos) { const unsigned int start=chan[i].pcm.start; @@ -1212,7 +1212,7 @@ int DivPlatformES5506::dispatch(DivCommand c) { int nextFreq=chan[c.chan].baseFreq; int destFreq=NOTE_ES5506(c.chan,c.value2+chan[c.chan].sampleNoteDelta); bool return2=false; - if (amigaPitch && !parent->song.linearPitch) { + if (amigaPitch && !parent->song.compatFlags.linearPitch) { c.value*=16; } if (destFreq>nextFreq) { @@ -1244,9 +1244,9 @@ int DivPlatformES5506::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_ES5506)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_ES5506)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { chan[c.chan].nextNote=chan[c.chan].note; chan[c.chan].noteChanged.note=1; } diff --git a/src/engine/platform/esfm.cpp b/src/engine/platform/esfm.cpp index 90b2f6607..8173edf8d 100644 --- a/src/engine/platform/esfm.cpp +++ b/src/engine/platform/esfm.cpp @@ -337,7 +337,7 @@ void DivPlatformESFM::tick(bool sysTick) { if (chan[i].freqChanged) { int mul=2; int fixedBlock=chan[i].state.fm.block; - if (!parent->song.linearPitch) { + if (!parent->song.compatFlags.linearPitch) { mul=octave(chan[i].baseFreq,fixedBlock)*2; } chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,mul,chan[i].pitch2,chipClock,CHIP_FREQBASE); @@ -569,7 +569,7 @@ int DivPlatformESFM::dispatch(DivCommand c) { bool return2=false; int mul=1; int fixedBlock=0; - if (!parent->song.linearPitch) { + if (!parent->song.compatFlags.linearPitch) { fixedBlock=chan[c.chan].state.fm.block; mul=octave(chan[c.chan].baseFreq,fixedBlock); } @@ -586,7 +586,7 @@ int DivPlatformESFM::dispatch(DivCommand c) { return2=true; } } - if (!chan[c.chan].portaPause && !parent->song.linearPitch) { + if (!chan[c.chan].portaPause && !parent->song.compatFlags.linearPitch) { if (mul!=octave(newFreq,fixedBlock)) { chan[c.chan].portaPause=true; break; @@ -987,7 +987,7 @@ int DivPlatformESFM::dispatch(DivCommand c) { return 63; break; case DIV_CMD_PRE_PORTA: - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); } chan[c.chan].inPorta=c.value; diff --git a/src/engine/platform/fds.cpp b/src/engine/platform/fds.cpp index 958f86fce..6865d6581 100644 --- a/src/engine/platform/fds.cpp +++ b/src/engine/platform/fds.cpp @@ -132,7 +132,7 @@ void DivPlatformFDS::tick(bool sysTick) { if (chan[i].std.duty.had) { chan[i].duty=chan[i].std.duty.val; if (i==3) { - if (parent->song.properNoiseLayout) { + if (parent->song.compatFlags.properNoiseLayout) { chan[i].duty&=1; } else if (chan[i].duty>1) { chan[i].duty=1; @@ -264,7 +264,7 @@ int DivPlatformFDS::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (chan[c.chan].wave<0) { @@ -390,9 +390,9 @@ int DivPlatformFDS::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FDS)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FDS)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index ca3542b40..b1aa07b32 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -31,7 +31,7 @@ int newFreq; \ bool return2=false; \ if (_targetChan.portaPause) { \ - if (parent->song.oldOctaveBoundary) { \ + if (parent->song.compatFlags.oldOctaveBoundary) { \ if ((_targetChan.portaPauseFreq&0xf800)>(_targetChan.baseFreq&0xf800)) { \ _targetChan.baseFreq=((_targetChan.baseFreq&0x7ff)>>1)|(_targetChan.portaPauseFreq&0xf800); \ } else { \ @@ -59,7 +59,7 @@ /* what the heck! */ \ if (!_targetChan.portaPause) { \ if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) { \ - if (parent->song.fbPortaPause) { \ + if (parent->song.compatFlags.fbPortaPause) { \ _targetChan.portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800); \ _targetChan.portaPause=true; \ break; \ @@ -68,7 +68,7 @@ } \ } \ if ((newFreq&0x7ff)0) { \ - if (parent->song.fbPortaPause) { \ + if (parent->song.compatFlags.fbPortaPause) { \ _targetChan.portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800); \ _targetChan.portaPause=true; \ break; \ diff --git a/src/engine/platform/ga20.cpp b/src/engine/platform/ga20.cpp index b45a8a8a4..7090b3f4f 100644 --- a/src/engine/platform/ga20.cpp +++ b/src/engine/platform/ga20.cpp @@ -261,7 +261,7 @@ int DivPlatformGA20::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].volumeChanged=true; } @@ -332,9 +332,9 @@ int DivPlatformGA20::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 819df4c16..1fb343170 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -224,7 +224,7 @@ void DivPlatformGB::tick(bool sysTick) { if (i!=2) { rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(chan[i].soundLen&63))); } else if (!chan[i].softEnv) { - if (parent->song.waveDutyIsVol) { + if (parent->song.compatFlags.waveDutyIsVol) { rWrite(16+i*5+2,(model==GB_MODEL_AGB_NATIVE?gbVolMapEx:gbVolMap)[(chan[i].std.duty.val&3)<<2]); } } @@ -439,7 +439,7 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].outVol=chan[c.chan].envVol; } } else if (chan[c.chan].softEnv && c.chan!=2) { - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].envVol=chan[c.chan].outVol; } @@ -478,7 +478,7 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].soundLen=ins->gb.soundLen; chan[c.chan].vol=chan[c.chan].envVol; chan[c.chan].outVol=chan[c.chan].vol; - if (parent->song.gbInsAffectsEnvelope) { + if (parent->song.compatFlags.gbInsAffectsEnvelope) { rWrite(16+c.chan*5+2,((chan[c.chan].vol<<4))|(chan[c.chan].envLen&7)|((chan[c.chan].envDir&1)<<3)); } } @@ -567,9 +567,9 @@ int DivPlatformGB::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_GB)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_GB)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GB_SWEEP_DIR: diff --git a/src/engine/platform/gbadma.cpp b/src/engine/platform/gbadma.cpp index 2a848cc09..bbc592a69 100644 --- a/src/engine/platform/gbadma.cpp +++ b/src/engine/platform/gbadma.cpp @@ -237,7 +237,7 @@ int DivPlatformGBADMA::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].envVol=2; } if (chan[c.chan].useWave) { @@ -321,7 +321,7 @@ int DivPlatformGBADMA::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } chan[c.chan].inPorta=c.value; break; diff --git a/src/engine/platform/gbaminmod.cpp b/src/engine/platform/gbaminmod.cpp index 89af91c62..75070ebb0 100644 --- a/src/engine/platform/gbaminmod.cpp +++ b/src/engine/platform/gbaminmod.cpp @@ -417,7 +417,7 @@ int DivPlatformGBAMinMod::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -503,9 +503,9 @@ int DivPlatformGBAMinMod::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index d7edd37a2..0d607319c 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -68,7 +68,7 @@ void DivPlatformGenesis::processDAC(int iRate) { if (chan[i].dacSample!=-1) { DivSample* s=parent->getSample(chan[i].dacSample); if (!isMuted[i] && s->samples>0 && chan[i].dacPossamples) { - if (parent->song.noOPN2Vol) { + if (parent->song.compatFlags.noOPN2Vol) { chan[i].dacOutput=s->data8[chan[i].dacDirection?(s->samples-chan[i].dacPos-1):chan[i].dacPos]; } else { chan[i].dacOutput=(s->data8[chan[i].dacDirection?(s->samples-chan[i].dacPos-1):chan[i].dacPos]*dacVolTable[chan[i].outVol])>>7; @@ -110,7 +110,7 @@ void DivPlatformGenesis::processDAC(int iRate) { if (s->samples>0 && chan[5].dacPossamples) { if (!isMuted[5]) { int sample; - if (parent->song.noOPN2Vol) { + if (parent->song.compatFlags.noOPN2Vol) { sample=s->data8[chan[5].dacDirection?(s->samples-chan[5].dacPos-1):chan[5].dacPos]; } else { sample=(s->data8[chan[5].dacDirection?(s->samples-chan[5].dacPos-1):chan[5].dacPos]*dacVolTable[chan[5].outVol])>>7; @@ -122,7 +122,7 @@ void DivPlatformGenesis::processDAC(int iRate) { chan[5].dacPos=s->loopStart; } else if (chan[5].dacPos>=s->samples) { chan[5].dacSample=-1; - if (parent->song.brokenDACMode) { + if (parent->song.compatFlags.brokenDACMode) { rWrite(0x2b,0); } } @@ -768,7 +768,7 @@ void DivPlatformGenesis::tick(bool sysTick) { if (chan[i].std.alg.had) { chan[i].state.alg=chan[i].std.alg.val; rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[i]|opOffs[j]; DivInstrumentFM::Operator& op=chan[i].state.op[j]; if (isMuted[i] || !op.enable) { @@ -863,7 +863,7 @@ void DivPlatformGenesis::tick(bool sysTick) { for (int i=0; i<512; i++) { if (pendingWrites[i]!=oldWrites[i]) { - if (i==0x2b && pendingWrites[i]!=0 && !parent->song.brokenDACMode) { + if (i==0x2b && pendingWrites[i]!=0 && !parent->song.compatFlags.brokenDACMode) { if (chan[5].keyOn) chan[5].keyOn=false; chan[5].keyOff=true; } @@ -894,7 +894,7 @@ void DivPlatformGenesis::tick(bool sysTick) { for (int i=0; isong.linearPitch) { + if (parent->song.compatFlags.linearPitch) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[i].state.block); } else { int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE,11); @@ -1131,7 +1131,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { if (c.chan>=5 && c.chansong.brokenDACMode) { + if (parent->song.compatFlags.brokenDACMode) { rWrite(0x2b,0); if (chan[c.chan].dacMode) break; } @@ -1200,7 +1200,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { break; } case DIV_CMD_NOTE_PORTA: { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { int destFreq=NOTE_FREQUENCY(c.value2+chan[c.chan].sampleNoteDelta); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 02fa2be79..034a75986 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -153,7 +153,7 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { } else { opChan[ch].pan=(c.value2>0)|((c.value>0)<<1); } - if (parent->song.sharedExtStat) { + if (parent->song.compatFlags.sharedExtStat) { for (int i=0; i<4; i++) { if (ch==i) continue; opChan[i].pan=opChan[ch].pan; @@ -169,7 +169,7 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { break; } case DIV_CMD_NOTE_PORTA: { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { int destFreq=NOTE_FREQUENCY(c.value2); bool return2=false; if (destFreq>opChan[ch].baseFreq) { @@ -197,7 +197,7 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { } case DIV_CMD_SAMPLE_MODE: { // not ignored actually! - if (!parent->song.ignoreDACModeOutsideIntendedChannel) { + if (!parent->song.compatFlags.ignoreDACModeOutsideIntendedChannel) { chan[5].dacMode=c.value; rWrite(0x2b,c.value<<7); } @@ -547,7 +547,7 @@ void DivPlatformGenesisExt::tick(bool sysTick) { if (opChan[i].std.alg.had) { chan[extChanOffs].state.alg=opChan[i].std.alg.val; rWrite(chanOffs[extChanOffs]+ADDR_FB_ALG,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[j]; DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[j]; if (isOpMuted[j] || !op.enable) { @@ -578,7 +578,7 @@ void DivPlatformGenesisExt::tick(bool sysTick) { if (opChan[i].std.panL.had) { opChan[i].pan=opChan[i].std.panL.val&3; - if (parent->song.sharedExtStat) { + if (parent->song.compatFlags.sharedExtStat) { for (int j=0; j<4; j++) { if (i==j) continue; opChan[j].pan=opChan[i].pan; @@ -648,7 +648,7 @@ void DivPlatformGenesisExt::tick(bool sysTick) { unsigned char hardResetMask=0; if (extMode) for (int i=0; i<4; i++) { if (opChan[i].freqChanged) { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,2,opChan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[extChanOffs].state.block); } else { int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,2,opChan[i].pitch2); diff --git a/src/engine/platform/k007232.cpp b/src/engine/platform/k007232.cpp index 0fa8aaace..e67485214 100644 --- a/src/engine/platform/k007232.cpp +++ b/src/engine/platform/k007232.cpp @@ -324,7 +324,7 @@ int DivPlatformK007232::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; if (!isMuted[c.chan]) { chan[c.chan].volumeChanged=true; @@ -405,9 +405,9 @@ int DivPlatformK007232::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/k053260.cpp b/src/engine/platform/k053260.cpp index 4b1b4bc39..6206aaac5 100644 --- a/src/engine/platform/k053260.cpp +++ b/src/engine/platform/k053260.cpp @@ -255,7 +255,7 @@ int DivPlatformK053260::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -331,9 +331,9 @@ int DivPlatformK053260::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/lynx.cpp b/src/engine/platform/lynx.cpp index d2e99ceb3..d25a94107 100644 --- a/src/engine/platform/lynx.cpp +++ b/src/engine/platform/lynx.cpp @@ -361,7 +361,7 @@ int DivPlatformLynx::dispatch(DivCommand c) { chan[c.chan].active=true; WRITE_VOLUME(c.chan,(isMuted[c.chan]?0:(chan[c.chan].vol&127))); chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -429,7 +429,7 @@ int DivPlatformLynx::dispatch(DivCommand c) { } } chan[c.chan].freqChanged=true; - if (chan[c.chan].pcm && parent->song.linearPitch) { + if (chan[c.chan].pcm && parent->song.compatFlags.linearPitch) { chan[c.chan].sampleBaseFreq=chan[c.chan].baseFreq; } if (return2) { @@ -451,9 +451,9 @@ int DivPlatformLynx::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/mmc5.cpp b/src/engine/platform/mmc5.cpp index 5f66585e2..c85fc9854 100644 --- a/src/engine/platform/mmc5.cpp +++ b/src/engine/platform/mmc5.cpp @@ -229,7 +229,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } rWrite(0x5000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6)); @@ -313,9 +313,9 @@ int DivPlatformMMC5::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/msm5232.cpp b/src/engine/platform/msm5232.cpp index d0325ae60..31648f6fe 100644 --- a/src/engine/platform/msm5232.cpp +++ b/src/engine/platform/msm5232.cpp @@ -157,7 +157,7 @@ void DivPlatformMSM5232::tick(bool sysTick) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE); chan[i].freq=chan[i].baseFreq+chan[i].pitch+chan[i].pitch2-(12<<7); - if (!parent->song.oldArpStrategy) { + if (!parent->song.compatFlags.oldArpStrategy) { if (chan[i].fixedArp) { chan[i].freq=(chan[i].baseNoteOverride<<7)+(chan[i].pitch)-(12<<7); } else { @@ -206,7 +206,7 @@ int DivPlatformMSM5232::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } chan[c.chan].insChanged=false; @@ -249,13 +249,13 @@ int DivPlatformMSM5232::dispatch(DivCommand c) { int destFreq=NOTE_LINEAR(c.value2); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { - chan[c.chan].baseFreq+=c.value*parent->song.pitchSlideSpeed; + chan[c.chan].baseFreq+=c.value*parent->song.compatFlags.pitchSlideSpeed; if (chan[c.chan].baseFreq>=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; } } else { - chan[c.chan].baseFreq-=c.value*parent->song.pitchSlideSpeed; + chan[c.chan].baseFreq-=c.value*parent->song.compatFlags.pitchSlideSpeed; if (chan[c.chan].baseFreq<=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; @@ -291,9 +291,9 @@ int DivPlatformMSM5232::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_LINEAR(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_LINEAR(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/msm6258.cpp b/src/engine/platform/msm6258.cpp index 8fbcccaad..f5e4e8b56 100644 --- a/src/engine/platform/msm6258.cpp +++ b/src/engine/platform/msm6258.cpp @@ -101,7 +101,7 @@ void DivPlatformMSM6258::acquire(short** buf, size_t len) { void DivPlatformMSM6258::tick(bool sysTick) { for (int i=0; i<1; i++) { - if (!parent->song.disableSampleMacro) { + if (!parent->song.compatFlags.disableSampleMacro) { chan[i].std.next(); if (chan[i].std.duty.had) { if (rateSel!=(chan[i].std.duty.val&3)) { diff --git a/src/engine/platform/msm6295.cpp b/src/engine/platform/msm6295.cpp index c084802f1..d4d1fe19d 100644 --- a/src/engine/platform/msm6295.cpp +++ b/src/engine/platform/msm6295.cpp @@ -122,7 +122,7 @@ void DivPlatformMSM6295::acquire(short** buf, size_t len) { void DivPlatformMSM6295::tick(bool sysTick) { for (int i=0; i<4; i++) { - if (!parent->song.disableSampleMacro) { + if (!parent->song.compatFlags.disableSampleMacro) { chan[i].std.next(); if (chan[i].std.vol.had) { chan[i].outVol=VOL_SCALE_LOG_BROKEN(chan[i].std.vol.val,chan[i].vol,8); diff --git a/src/engine/platform/multipcm.cpp b/src/engine/platform/multipcm.cpp index 7e1a0ce29..3a91d6c4b 100644 --- a/src/engine/platform/multipcm.cpp +++ b/src/engine/platform/multipcm.cpp @@ -389,9 +389,9 @@ int DivPlatformMultiPCM::dispatch(DivCommand c) { return 127; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MULTIPCM)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MULTIPCM)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); } chan[c.chan].inPorta=c.value; diff --git a/src/engine/platform/n163.cpp b/src/engine/platform/n163.cpp index b10a28eb0..2476e7e53 100644 --- a/src/engine/platform/n163.cpp +++ b/src/engine/platform/n163.cpp @@ -386,13 +386,13 @@ int DivPlatformN163::dispatch(DivCommand c) { int destFreq=destFreqD; bool return2=false; if (destFreq>chan[c.chan].baseFreq) { - chan[c.chan].baseFreq+=c.value*((parent->song.linearPitch)?1:16); + chan[c.chan].baseFreq+=c.value*((parent->song.compatFlags.linearPitch)?1:16); if (chan[c.chan].baseFreq>=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; } } else { - chan[c.chan].baseFreq-=c.value*((parent->song.linearPitch)?1:16); + chan[c.chan].baseFreq-=c.value*((parent->song.compatFlags.linearPitch)?1:16); if (chan[c.chan].baseFreq<=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; @@ -456,12 +456,12 @@ int DivPlatformN163::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) { + if (parent->song.compatFlags.resetMacroOnPorta) { chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_N163)); chan[c.chan].keyOn=true; } } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/namcowsg.cpp b/src/engine/platform/namcowsg.cpp index 6fea2e923..95c2583dd 100644 --- a/src/engine/platform/namcowsg.cpp +++ b/src/engine/platform/namcowsg.cpp @@ -353,7 +353,7 @@ int DivPlatformNamcoWSG::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (chan[c.chan].wave<0) { @@ -406,13 +406,13 @@ int DivPlatformNamcoWSG::dispatch(DivCommand c) { int destFreq=NOTE_FREQUENCY(c.value2); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { - chan[c.chan].baseFreq+=c.value*((parent->song.linearPitch)?1:8); + chan[c.chan].baseFreq+=c.value*((parent->song.compatFlags.linearPitch)?1:8); if (chan[c.chan].baseFreq>=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; } } else { - chan[c.chan].baseFreq-=c.value*((parent->song.linearPitch)?1:8); + chan[c.chan].baseFreq-=c.value*((parent->song.compatFlags.linearPitch)?1:8); if (chan[c.chan].baseFreq<=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; @@ -440,9 +440,9 @@ int DivPlatformNamcoWSG::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/nds.cpp b/src/engine/platform/nds.cpp index 7fe0a3cd1..fa77f2296 100644 --- a/src/engine/platform/nds.cpp +++ b/src/engine/platform/nds.cpp @@ -334,7 +334,7 @@ int DivPlatformNDS::dispatch(DivCommand c) { chan[c.chan].busy=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -422,9 +422,9 @@ int DivPlatformNDS::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_NDS)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_NDS)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index d56b57288..5330548d0 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -326,7 +326,7 @@ void DivPlatformNES::tick(bool sysTick) { if (chan[i].std.duty.had) { chan[i].duty=chan[i].std.duty.val; if (i==3) { - if (parent->song.properNoiseLayout) { + if (parent->song.compatFlags.properNoiseLayout) { chan[i].duty&=1; } else if (chan[i].duty>1) { chan[i].duty=1; @@ -372,7 +372,7 @@ void DivPlatformNES::tick(bool sysTick) { ntPos+=chan[i].pitch2; if (isE) { chan[i].freq=31-(ntPos&31); - } else if (parent->song.properNoiseLayout) { + } else if (parent->song.compatFlags.properNoiseLayout) { chan[i].freq=15-(ntPos&15); } else { if (ntPos<0) ntPos=0; @@ -578,12 +578,12 @@ int DivPlatformNES::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_NES)); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (c.chan==2) { rWrite(0x4000+c.chan*4,linearCount); - } else if (!parent->song.brokenOutVol2) { + } else if (!parent->song.compatFlags.brokenOutVol2) { rWrite(0x4000+c.chan*4,(chan[c.chan].envMode<<4)|chan[c.chan].vol|((chan[c.chan].duty&3)<<6)); } if (resetSweep && c.chan<2) { @@ -752,9 +752,9 @@ int DivPlatformNES::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_NES)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_NES)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index b2bcf042f..ff8c69799 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -1515,7 +1515,7 @@ void DivPlatformOPL::tick(bool sysTick) { if (chan[i].freqChanged) { int mul=2; int fixedBlock=chan[i].state.block; - if (!parent->song.linearPitch) { + if (!parent->song.compatFlags.linearPitch) { mul=octave(chan[i].baseFreq,fixedBlock)*2; } chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,mul,chan[i].pitch2,chipClock,CHIP_FREQBASE); @@ -2082,7 +2082,7 @@ int DivPlatformOPL::dispatch(DivCommand c) { bool return2=false; int mul=1; int fixedBlock=0; - if (!parent->song.linearPitch) { + if (!parent->song.compatFlags.linearPitch) { fixedBlock=chan[c.chan].state.block; mul=octave(chan[c.chan].baseFreq,fixedBlock); } @@ -2099,7 +2099,7 @@ int DivPlatformOPL::dispatch(DivCommand c) { return2=true; } } - if (!chan[c.chan].portaPause && !parent->song.linearPitch) { + if (!chan[c.chan].portaPause && !parent->song.compatFlags.linearPitch) { if (mul!=octave(newFreq,fixedBlock)) { chan[c.chan].portaPause=true; break; @@ -2583,9 +2583,9 @@ int DivPlatformOPL::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (PCM_CHECK(c.chan) && chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MULTIPCM)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MULTIPCM)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { chan[c.chan].baseFreq=(PCM_CHECK(c.chan))?NOTE_PCM(chan[c.chan].note): ((c.chan==adpcmChan)?(NOTE_ADPCMB(chan[c.chan].note)):(NOTE_FREQUENCY(chan[c.chan].note))); } diff --git a/src/engine/platform/opll.cpp b/src/engine/platform/opll.cpp index e29d43e08..b64ccbbf5 100644 --- a/src/engine/platform/opll.cpp +++ b/src/engine/platform/opll.cpp @@ -341,7 +341,7 @@ void DivPlatformOPLL::tick(bool sysTick) { if (chan[i].freqChanged) { int mul=2; int fixedBlock=chan[i].state.block; - if (!parent->song.linearPitch) { + if (!parent->song.compatFlags.linearPitch) { mul=octave(chan[i].baseFreq,fixedBlock)*2; } chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,mul,chan[i].pitch2,chipClock,CHIP_FREQBASE); @@ -684,7 +684,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) { bool return2=false; int mul=1; int fixedBlock=0; - if (!parent->song.linearPitch) { + if (!parent->song.compatFlags.linearPitch) { fixedBlock=chan[c.chan].state.block; mul=octave(chan[c.chan].baseFreq,fixedBlock); } @@ -956,7 +956,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (c.chan>=9 && !properDrums) return 0; - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_PRE_NOTE: diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index 3023aa1fc..c410c3d09 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -103,7 +103,7 @@ void DivPlatformPCE::acquireDirect(blip_buffer_t** bb, size_t len) { signed char dacData=((signed char)((unsigned char)s->data8[chan[i].dacPos]^0x80))>>3; chan[i].dacOut=CLAMP(dacData,-16,15); if (!isMuted[i]) { - chWrite(i,0x04,parent->song.disableSampleMacro?0xdf:(0xc0|chan[i].outVol)); + chWrite(i,0x04,parent->song.compatFlags.disableSampleMacro?0xdf:(0xc0|chan[i].outVol)); chWrite(i,0x06,chan[i].dacOut&0x1f); } else { chWrite(i,0x04,0xc0); @@ -233,7 +233,7 @@ void DivPlatformPCE::tick(bool sysTick) { chan[i].dacPos=0; } chan[i].dacPeriod=0; - chWrite(i,0x04,parent->song.disableSampleMacro?0xdf:(0xc0|chan[i].vol)); + chWrite(i,0x04,parent->song.compatFlags.disableSampleMacro?0xdf:(0xc0|chan[i].vol)); addWrite(0xffff0000+(i<<8),chan[i].dacSample); chan[i].keyOn=true; } @@ -269,11 +269,11 @@ void DivPlatformPCE::tick(bool sysTick) { if (i>=4) { int noiseSeek=(chan[i].fixedArp?chan[i].baseNoteOverride:(chan[i].note+chan[i].arpOff))+chan[i].pitch2; - if (!parent->song.properNoiseLayout && noiseSeek<0) noiseSeek=0; + if (!parent->song.compatFlags.properNoiseLayout && noiseSeek<0) noiseSeek=0; if (!NEW_ARP_STRAT) { noiseSeek=chan[i].noiseSeek; } - chWrite(i,0x07,chan[i].noise?(0x80|(parent->song.properNoiseLayout?(noiseSeek&31):noiseFreq[noiseSeek%12])):0); + chWrite(i,0x07,chan[i].noise?(0x80|(parent->song.compatFlags.properNoiseLayout?(noiseSeek&31):noiseFreq[noiseSeek%12])):0); } if (chan[i].keyOn) { //rWrite(16+i*5,0x80); @@ -324,7 +324,7 @@ int DivPlatformPCE::dispatch(DivCommand c) { break; } else { if (dumpWrites) { - chWrite(c.chan,0x04,parent->song.disableSampleMacro?0xdf:(0xc0|chan[c.chan].vol)); + chWrite(c.chan,0x04,parent->song.compatFlags.disableSampleMacro?0xdf:(0xc0|chan[c.chan].vol)); addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dacSample); } } @@ -341,7 +341,7 @@ int DivPlatformPCE::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -359,7 +359,7 @@ int DivPlatformPCE::dispatch(DivCommand c) { chan[c.chan].keyOn=true; chWrite(c.chan,0x04,0x80|chan[c.chan].vol); chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (chan[c.chan].wave<0) { @@ -476,9 +476,9 @@ int DivPlatformPCE::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: @@ -503,7 +503,7 @@ void DivPlatformPCE::muteChannel(int ch, bool mute) { isMuted[ch]=mute; chWrite(ch,0x05,isMuted[ch]?0:chan[ch].pan); if (!isMuted[ch] && (chan[ch].pcm && chan[ch].dacSample!=-1)) { - chWrite(ch,0x04,parent->song.disableSampleMacro?0xdf:(0xc0|chan[ch].outVol)); + chWrite(ch,0x04,parent->song.compatFlags.disableSampleMacro?0xdf:(0xc0|chan[ch].outVol)); chWrite(ch,0x06,chan[ch].dacOut&0x1f); } } diff --git a/src/engine/platform/pcmdac.cpp b/src/engine/platform/pcmdac.cpp index 42b9babd9..817ec5a5d 100644 --- a/src/engine/platform/pcmdac.cpp +++ b/src/engine/platform/pcmdac.cpp @@ -365,7 +365,7 @@ int DivPlatformPCMDAC::dispatch(DivCommand c) { chan[0].active=true; chan[0].keyOn=true; chan[0].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[0].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[0].std.vol.will) { chan[0].envVol=64; } if (chan[0].useWave) { @@ -446,7 +446,7 @@ int DivPlatformPCMDAC::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[0].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[0].macroInit(parent->getIns(chan[0].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[0].macroInit(parent->getIns(chan[0].ins,DIV_INS_AMIGA)); } chan[0].inPorta=c.value; break; diff --git a/src/engine/platform/pcspkr.cpp b/src/engine/platform/pcspkr.cpp index c35ba724d..25a53196f 100644 --- a/src/engine/platform/pcspkr.cpp +++ b/src/engine/platform/pcspkr.cpp @@ -470,7 +470,7 @@ int DivPlatformPCSpeaker::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -537,9 +537,9 @@ int DivPlatformPCSpeaker::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/pet.cpp b/src/engine/platform/pet.cpp index fc78165d7..d299d0d62 100644 --- a/src/engine/platform/pet.cpp +++ b/src/engine/platform/pet.cpp @@ -158,7 +158,7 @@ int DivPlatformPET::dispatch(DivCommand c) { chan[0].active=true; chan[0].keyOn=true; chan[0].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[0].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[0].std.vol.will) { chan[0].outVol=chan[0].vol; } break; @@ -227,9 +227,9 @@ int DivPlatformPET::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[0].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[0].macroInit(parent->getIns(chan[0].ins,DIV_INS_PET)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[0].macroInit(parent->getIns(chan[0].ins,DIV_INS_PET)); } - if (!chan[0].inPorta && c.value && !parent->song.brokenPortaArp && chan[0].std.arp.will && !NEW_ARP_STRAT) chan[0].baseFreq=NOTE_PERIODIC(chan[0].note); + if (!chan[0].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[0].std.arp.will && !NEW_ARP_STRAT) chan[0].baseFreq=NOTE_PERIODIC(chan[0].note); chan[0].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/pokemini.cpp b/src/engine/platform/pokemini.cpp index 9e29277e4..5f4516e41 100644 --- a/src/engine/platform/pokemini.cpp +++ b/src/engine/platform/pokemini.cpp @@ -175,7 +175,7 @@ int DivPlatformPokeMini::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_POKEMINI)); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -241,9 +241,9 @@ int DivPlatformPokeMini::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_POKEMINI)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_POKEMINI)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/pokey.cpp b/src/engine/platform/pokey.cpp index dbb0d7fd8..35a362247 100644 --- a/src/engine/platform/pokey.cpp +++ b/src/engine/platform/pokey.cpp @@ -184,7 +184,7 @@ void DivPlatformPOKEY::tick(bool sysTick) { for (int i=0; i<4; i++) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,parent->song.linearPitch?chan[i].pitch:0,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,parent->song.linearPitch?chan[i].pitch2:0,chipClock,CHIP_DIVIDER); + chan[i].freq=parent->calcFreq(chan[i].baseFreq,parent->song.compatFlags.linearPitch?chan[i].pitch:0,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,parent->song.compatFlags.linearPitch?chan[i].pitch2:0,chipClock,CHIP_DIVIDER); if ((i==0 && !(audctl&64)) || (i==2 && !(audctl&32)) || i==1 || i==3) { chan[i].freq/=7; @@ -223,7 +223,7 @@ void DivPlatformPOKEY::tick(bool sysTick) { } // non-linear pitch - if (!parent->song.linearPitch) { + if (!parent->song.compatFlags.linearPitch) { chan[i].freq-=chan[i].pitch; } @@ -297,7 +297,7 @@ int DivPlatformPOKEY::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].ctlChanged=true; } @@ -383,9 +383,9 @@ int DivPlatformPOKEY::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_POKEY)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_POKEY)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/pong.cpp b/src/engine/platform/pong.cpp index 19c478711..ce855c22a 100644 --- a/src/engine/platform/pong.cpp +++ b/src/engine/platform/pong.cpp @@ -101,7 +101,7 @@ int DivPlatformPong::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -168,9 +168,9 @@ int DivPlatformPong::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/powernoise.cpp b/src/engine/platform/powernoise.cpp index c7870e31e..8051ed2ce 100644 --- a/src/engine/platform/powernoise.cpp +++ b/src/engine/platform/powernoise.cpp @@ -288,7 +288,7 @@ int DivPlatformPowerNoise::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } chan[c.chan].keyOn=true; @@ -372,9 +372,9 @@ int DivPlatformPowerNoise::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: { if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_POWERNOISE)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_POWERNOISE)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); } chan[c.chan].inPorta=c.value; diff --git a/src/engine/platform/pv1000.cpp b/src/engine/platform/pv1000.cpp index 11cab5457..633260635 100644 --- a/src/engine/platform/pv1000.cpp +++ b/src/engine/platform/pv1000.cpp @@ -182,9 +182,9 @@ int DivPlatformPV1000::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PV1000)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PV1000)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index 6b8b4089a..213de85f1 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -488,7 +488,7 @@ int DivPlatformQSound::dispatch(DivCommand c) { chan[c.chan].keyOn=true; chan[c.chan].keyOff=false; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; if (chan[c.chan].isNewQSound) { chan[c.chan].resVol=(chan[c.chan].outVol*16383)/255; @@ -594,9 +594,9 @@ int DivPlatformQSound::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=QS_NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=QS_NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/rf5c68.cpp b/src/engine/platform/rf5c68.cpp index 831d47e1c..45a16255a 100644 --- a/src/engine/platform/rf5c68.cpp +++ b/src/engine/platform/rf5c68.cpp @@ -210,7 +210,7 @@ int DivPlatformRF5C68::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -284,9 +284,9 @@ int DivPlatformRF5C68::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/saa.cpp b/src/engine/platform/saa.cpp index 624bde5bf..5283a5176 100644 --- a/src/engine/platform/saa.cpp +++ b/src/engine/platform/saa.cpp @@ -211,7 +211,7 @@ int DivPlatformSAA1099::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (isMuted[c.chan]) { @@ -261,13 +261,13 @@ int DivPlatformSAA1099::dispatch(DivCommand c) { int destFreq=NOTE_PERIODIC(c.value2); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { - chan[c.chan].baseFreq+=c.value*((parent->song.linearPitch)?1:(8-chan[c.chan].freqH)); + chan[c.chan].baseFreq+=c.value*((parent->song.compatFlags.linearPitch)?1:(8-chan[c.chan].freqH)); if (chan[c.chan].baseFreq>=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; } } else { - chan[c.chan].baseFreq-=c.value*((parent->song.linearPitch)?1:(8-chan[c.chan].freqH)); + chan[c.chan].baseFreq-=c.value*((parent->song.compatFlags.linearPitch)?1:(8-chan[c.chan].freqH)); if (chan[c.chan].baseFreq<=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; @@ -318,9 +318,9 @@ int DivPlatformSAA1099::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SAA1099)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SAA1099)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_PRE_NOTE: diff --git a/src/engine/platform/scc.cpp b/src/engine/platform/scc.cpp index 56e160181..f500bf4a5 100644 --- a/src/engine/platform/scc.cpp +++ b/src/engine/platform/scc.cpp @@ -172,7 +172,7 @@ int DivPlatformSCC::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (!isMuted[c.chan]) { @@ -253,9 +253,9 @@ int DivPlatformSCC::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SCC)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SCC)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/scvtone.cpp b/src/engine/platform/scvtone.cpp index e5dfe9a43..2d78d3a9d 100644 --- a/src/engine/platform/scvtone.cpp +++ b/src/engine/platform/scvtone.cpp @@ -100,7 +100,7 @@ void DivPlatformSCV::tick(bool sysTick) { } else { chan[i].freq=(chan[i].baseFreq+chan[i].pitch+chan[i].pitch2+143); } - if (!parent->song.oldArpStrategy) { + if (!parent->song.compatFlags.oldArpStrategy) { if (chan[i].fixedArp) { chan[i].freq=(chan[i].baseNoteOverride)+chan[i].pitch+chan[i].pitch2; } else { @@ -186,7 +186,7 @@ int DivPlatformSCV::dispatch(DivCommand c) { chan[c.chan].keyOn=true; //chwrite(c.chan,0x04,0x80|chan[c.chan].vol); chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } chan[c.chan].insChanged=false; @@ -267,9 +267,9 @@ int DivPlatformSCV::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_UPD1771C)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_UPD1771C)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) { chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); } chan[c.chan].inPorta=c.value; diff --git a/src/engine/platform/segapcm.cpp b/src/engine/platform/segapcm.cpp index c659b8f2a..877d76f4d 100644 --- a/src/engine/platform/segapcm.cpp +++ b/src/engine/platform/segapcm.cpp @@ -66,7 +66,7 @@ void DivPlatformSegaPCM::tick(bool sysTick) { for (int i=0; i<16; i++) { chan[i].std.next(); - if (parent->song.newSegaPCM) { + if (parent->song.compatFlags.newSegaPCM) { if (chan[i].std.vol.had) { chan[i].outVol=(chan[i].vol*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul; chan[i].chVolL=(chan[i].outVol*chan[i].chPanL)/127; @@ -89,13 +89,13 @@ void DivPlatformSegaPCM::tick(bool sysTick) { chan[i].pcm.freq=-1; } - if (parent->song.newSegaPCM) if (chan[i].std.panL.had) { + if (parent->song.compatFlags.newSegaPCM) if (chan[i].std.panL.had) { chan[i].chPanL=chan[i].std.panL.val&127; chan[i].chVolL=(chan[i].outVol*chan[i].chPanL)/127; rWrite(2+(i<<3),chan[i].chVolL); } - if (parent->song.newSegaPCM) if (chan[i].std.panR.had) { + if (parent->song.compatFlags.newSegaPCM) if (chan[i].std.panR.had) { chan[i].chPanR=chan[i].std.panR.val&127; chan[i].chVolR=(chan[i].outVol*chan[i].chPanR)/127; rWrite(3+(i<<3),chan[i].chVolR); @@ -120,7 +120,7 @@ void DivPlatformSegaPCM::tick(bool sysTick) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { chan[i].freq=chan[i].baseFreq+(chan[i].pitch)-128+(oldSlides?0:chan[i].pitch2); - if (!parent->song.oldArpStrategy) { + if (!parent->song.compatFlags.oldArpStrategy) { if (chan[i].fixedArp) { chan[i].freq=(chan[i].baseNoteOverride<<7)+chan[i].pitch-128+(chan[i].pitch2<<(oldSlides?1:0)); } else { @@ -204,10 +204,10 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) { chan[c.chan].pcm.freq=-1; } chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; - if (parent->song.newSegaPCM) { + if (parent->song.compatFlags.newSegaPCM) { chan[c.chan].chVolL=(chan[c.chan].outVol*chan[c.chan].chPanL)/127; chan[c.chan].chVolR=(chan[c.chan].outVol*chan[c.chan].chPanR)/127; rWrite(2+(c.chan<<3),chan[c.chan].chVolL); @@ -240,7 +240,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) { if (!chan[c.chan].std.vol.has) { chan[c.chan].outVol=c.value; } - if (parent->song.newSegaPCM) { + if (parent->song.compatFlags.newSegaPCM) { chan[c.chan].chVolL=(c.value*chan[c.chan].chPanL)/127; chan[c.chan].chVolR=(c.value*chan[c.chan].chPanR)/127; } else { @@ -262,7 +262,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) { chan[c.chan].ins=c.value; break; case DIV_CMD_PANNING: { - if (parent->song.newSegaPCM) { + if (parent->song.compatFlags.newSegaPCM) { chan[c.chan].chPanL=c.value>>1; chan[c.chan].chPanR=c.value2>>1; chan[c.chan].chVolL=(chan[c.chan].outVol*chan[c.chan].chPanL)/127; @@ -284,7 +284,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) { case DIV_CMD_NOTE_PORTA: { int destFreq=((c.value2+chan[c.chan].sampleNoteDelta)<<7); int newFreq; - int mul=(oldSlides || !parent->song.linearPitch)?8:1; + int mul=(oldSlides || !parent->song.compatFlags.linearPitch)?8:1; bool return2=false; if (destFreq>chan[c.chan].baseFreq) { newFreq=chan[c.chan].baseFreq+c.value*mul; @@ -334,7 +334,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) { return 127; break; case DIV_CMD_PRE_PORTA: - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=(chan[c.chan].note<<7); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=(chan[c.chan].note<<7); chan[c.chan].inPorta=c.value; break; case DIV_CMD_PRE_NOTE: diff --git a/src/engine/platform/sid2.cpp b/src/engine/platform/sid2.cpp index 010fec0cb..8e6339a9c 100644 --- a/src/engine/platform/sid2.cpp +++ b/src/engine/platform/sid2.cpp @@ -445,12 +445,12 @@ int DivPlatformSID2::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta || parent->song.preNoteNoEffect) { + if (parent->song.compatFlags.resetMacroOnPorta || parent->song.compatFlags.preNoteNoEffect) { chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SID2)); chan[c.chan].keyOn=true; } } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/sid3.cpp b/src/engine/platform/sid3.cpp index 284488428..9dd44849c 100644 --- a/src/engine/platform/sid3.cpp +++ b/src/engine/platform/sid3.cpp @@ -845,7 +845,7 @@ int DivPlatformSID3::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } //chan[c.chan].keyOn=true; @@ -997,12 +997,12 @@ int DivPlatformSID3::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta || parent->song.preNoteNoEffect) { + if (parent->song.compatFlags.resetMacroOnPorta || parent->song.compatFlags.preNoteNoEffect) { chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SID3)); chan[c.chan].keyOn=true; } } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_PANNING: { diff --git a/src/engine/platform/sm8521.cpp b/src/engine/platform/sm8521.cpp index 5c1153aab..2801ca6b2 100644 --- a/src/engine/platform/sm8521.cpp +++ b/src/engine/platform/sm8521.cpp @@ -208,7 +208,7 @@ int DivPlatformSM8521::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (chan[c.chan].wave<0) { @@ -267,13 +267,13 @@ int DivPlatformSM8521::dispatch(DivCommand c) { int destFreq=NOTE_PERIODIC(c.value2); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { - chan[c.chan].baseFreq+=c.value*((parent->song.linearPitch)?1:8); + chan[c.chan].baseFreq+=c.value*((parent->song.compatFlags.linearPitch)?1:8); if (chan[c.chan].baseFreq>=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; } } else { - chan[c.chan].baseFreq-=c.value*((parent->song.linearPitch)?1:8); + chan[c.chan].baseFreq-=c.value*((parent->song.compatFlags.linearPitch)?1:8); if (chan[c.chan].baseFreq<=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; @@ -293,9 +293,9 @@ int DivPlatformSM8521::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SM8521)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SM8521)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 636cf6560..1b6b6d543 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -190,7 +190,7 @@ void DivPlatformSMS::acquireDirect(blip_buffer_t** bb, size_t len) { double DivPlatformSMS::NOTE_SN(int ch, int note) { double CHIP_DIVIDER=toneDivider; if (ch==3) CHIP_DIVIDER=noiseDivider; - if (parent->song.linearPitch || !easyNoise) { + if (parent->song.compatFlags.linearPitch || !easyNoise) { return NOTE_PERIODIC(note); } int easyStartingPeriod=16; @@ -210,7 +210,7 @@ int DivPlatformSMS::snCalcFreq(int ch) { if (chan[ch].fixedArp) { curFreq=chan[ch].baseNoteOverride<<7; } - if (parent->song.linearPitch && easyNoise && curFreq>easyThreshold) { + if (parent->song.compatFlags.linearPitch && easyNoise && curFreq>easyThreshold) { int ret=(((easyStartingPeriod<<7))-(curFreq-(easyThreshold)))>>7; if (ret<0) ret=0; return ret; @@ -242,7 +242,7 @@ void DivPlatformSMS::tick(bool sysTick) { } if (i==3) { if (chan[i].std.duty.had) { - if (chan[i].std.duty.val!=snNoiseMode || parent->song.snDutyReset) { + if (chan[i].std.duty.val!=snNoiseMode || parent->song.compatFlags.snDutyReset) { snNoiseMode=chan[i].std.duty.val; if (chan[i].std.duty.val<2) { chan[3].freqChanged=false; @@ -277,7 +277,7 @@ void DivPlatformSMS::tick(bool sysTick) { if (chan[i].freqChanged) { chan[i].freq=snCalcFreq(i); if (chan[i].freq>1023) chan[i].freq=1023; - if (parent->song.snNoLowPeriods) { + if (parent->song.compatFlags.snNoLowPeriods) { if (chan[i].freq<8) chan[i].freq=1; } else { if (chan[i].freq<0) chan[i].freq=0; @@ -297,7 +297,7 @@ void DivPlatformSMS::tick(bool sysTick) { chan[3].freq=snCalcFreq(3); //parent->calcFreq(chan[3].baseFreq,chan[3].pitch,chan[3].fixedArp?chan[3].baseNoteOverride:chan[3].arpOff,chan[3].fixedArp,true,0,chan[3].pitch2,chipClock,noiseDivider); if (chan[3].freq>1023) chan[3].freq=1023; - if (parent->song.snNoLowPeriods) { + if (parent->song.compatFlags.snNoLowPeriods) { if (chan[3].actualNote>0x5d) chan[3].freq=0x01; } if (chan[3].freq<0) chan[3].freq=0; @@ -359,13 +359,13 @@ int DivPlatformSMS::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].keyOff=false; - //if (!parent->song.brokenOutVol2) { + //if (!parent->song.compatFlags.brokenOutVol2) { chan[c.chan].writeVol=true; chan[c.chan].outVol=chan[c.chan].vol; //rWrite(0,0x90|c.chan<<5|(isMuted[c.chan]?15:(15-(chan[c.chan].vol&15)))); //} chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -451,9 +451,9 @@ int DivPlatformSMS::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_SN(c.chan,chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_SN(c.chan,chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index 6d7c90629..be76b48b3 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -390,7 +390,7 @@ int DivPlatformSNES::dispatch(DivCommand c) { chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); // this is the fix. it needs testing. - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { if (chan[c.chan].outVol!=chan[c.chan].vol) chan[c.chan].shallWriteVol=true; chan[c.chan].outVol=chan[c.chan].vol; } @@ -482,7 +482,7 @@ int DivPlatformSNES::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SNES)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SNES)); } chan[c.chan].inPorta=c.value; break; diff --git a/src/engine/platform/su.cpp b/src/engine/platform/su.cpp index 84c84f6d1..5195dabbd 100644 --- a/src/engine/platform/su.cpp +++ b/src/engine/platform/su.cpp @@ -327,7 +327,7 @@ int DivPlatformSoundUnit::dispatch(DivCommand c) { chan[c.chan].hwSeqDelay=0; chWrite(c.chan,0x02,chan[c.chan].vol); chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } chan[c.chan].insChanged=false; @@ -484,13 +484,13 @@ int DivPlatformSoundUnit::dispatch(DivCommand c) { int destFreq=NOTE_SU(c.chan,c.value2+chan[c.chan].sampleNoteDelta); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { - chan[c.chan].baseFreq+=c.value*((parent->song.linearPitch)?1:(1+(chan[c.chan].baseFreq>>9))); + chan[c.chan].baseFreq+=c.value*((parent->song.compatFlags.linearPitch)?1:(1+(chan[c.chan].baseFreq>>9))); if (chan[c.chan].baseFreq>=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; } } else { - chan[c.chan].baseFreq-=c.value*((parent->song.linearPitch)?1:(1+(chan[c.chan].baseFreq>>9))); + chan[c.chan].baseFreq-=c.value*((parent->song.compatFlags.linearPitch)?1:(1+(chan[c.chan].baseFreq>>9))); if (chan[c.chan].baseFreq<=destFreq) { chan[c.chan].baseFreq=destFreq; return2=true; @@ -519,9 +519,9 @@ int DivPlatformSoundUnit::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SU)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SU)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_SU(c.chan,chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_SU(c.chan,chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_C64_PW_SLIDE: diff --git a/src/engine/platform/supervision.cpp b/src/engine/platform/supervision.cpp index 0a391f1ca..57ab61d34 100644 --- a/src/engine/platform/supervision.cpp +++ b/src/engine/platform/supervision.cpp @@ -297,7 +297,7 @@ int DivPlatformSupervision::dispatch(DivCommand c) { chan[c.chan].keyOn=true; //chwrite(c.chan,0x04,0x80|chan[c.chan].vol); chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } chan[c.chan].insChanged=false; @@ -384,9 +384,9 @@ int DivPlatformSupervision::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SUPERVISION)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SUPERVISION)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index ca5c0906c..19ba44719 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -405,7 +405,7 @@ int DivPlatformSwan::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (chan[c.chan].wave<0) { @@ -538,9 +538,9 @@ int DivPlatformSwan::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SWAN)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SWAN)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/t6w28.cpp b/src/engine/platform/t6w28.cpp index a02e47681..44276f82d 100644 --- a/src/engine/platform/t6w28.cpp +++ b/src/engine/platform/t6w28.cpp @@ -95,7 +95,7 @@ void DivPlatformT6W28::writeOutVol(int ch) { double DivPlatformT6W28::NOTE_SN(int ch, int note) { double CHIP_DIVIDER=16; if (ch==3) CHIP_DIVIDER=15; - if (parent->song.linearPitch || !easyNoise) { + if (parent->song.compatFlags.linearPitch || !easyNoise) { return NOTE_PERIODIC(note); } if (note>107) { @@ -105,7 +105,7 @@ double DivPlatformT6W28::NOTE_SN(int ch, int note) { } int DivPlatformT6W28::snCalcFreq(int ch) { - if (parent->song.linearPitch && easyNoise && chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2>(107<<7)) { + if (parent->song.compatFlags.linearPitch && easyNoise && chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2>(107<<7)) { int ret=(((13<<7)+0x40)-(chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2-(107<<7)))>>7; if (ret<0) ret=0; return ret; @@ -187,7 +187,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; writeOutVol(c.chan); } @@ -270,9 +270,9 @@ int DivPlatformT6W28::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_T6W28)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_T6W28)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_SN(c.chan,chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_SN(c.chan,chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/ted.cpp b/src/engine/platform/ted.cpp index 46c38ebd6..d505c44a0 100644 --- a/src/engine/platform/ted.cpp +++ b/src/engine/platform/ted.cpp @@ -149,7 +149,7 @@ int DivPlatformTED::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } chan[c.chan].insChanged=false; @@ -230,9 +230,9 @@ int DivPlatformTED::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_TED)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_TED)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/tia.cpp b/src/engine/platform/tia.cpp index e8e3c0d3d..45e3fccc0 100644 --- a/src/engine/platform/tia.cpp +++ b/src/engine/platform/tia.cpp @@ -295,7 +295,7 @@ int DivPlatformTIA::dispatch(DivCommand c) { chan[c.chan].keyOn=true; rWrite(0x15+c.chan,chan[c.chan].shape); chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (chan[c.chan].insChanged) { @@ -395,7 +395,7 @@ int DivPlatformTIA::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_TIA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_TIA)); } chan[c.chan].inPorta=c.value; break; diff --git a/src/engine/platform/tx81z.cpp b/src/engine/platform/tx81z.cpp index 658eface1..6cf6906a1 100644 --- a/src/engine/platform/tx81z.cpp +++ b/src/engine/platform/tx81z.cpp @@ -229,7 +229,7 @@ void DivPlatformTX81Z::tick(bool sysTick) { if (chan[i].std.alg.had) { chan[i].state.alg=chan[i].std.alg.val; immWrite(chanOffs[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)|(chan[i].active?0x40:0)|(chan[i].chVolR<<7)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[i]|opOffs[j]; DivInstrumentFM::Operator& op=chan[i].state.op[j]; if (isMuted[i] || !op.enable) { @@ -321,7 +321,7 @@ void DivPlatformTX81Z::tick(bool sysTick) { } // fixed pitch - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { bool freqChangeOp=false; if (op.egt) { @@ -416,7 +416,7 @@ void DivPlatformTX81Z::tick(bool sysTick) { for (int i=0; i<8; i++) { if (chan[i].freqChanged) { chan[i].freq=chan[i].baseFreq+chan[i].pitch-128+chan[i].pitch2; - if (!parent->song.oldArpStrategy) { + if (!parent->song.compatFlags.oldArpStrategy) { if (chan[i].fixedArp) { chan[i].freq=(chan[i].baseNoteOverride<<7)+chan[i].pitch-128+chan[i].pitch2; } else { @@ -1006,7 +1006,7 @@ int DivPlatformTX81Z::dispatch(DivCommand c) { return 127; break; case DIV_CMD_PRE_PORTA: - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_LINEAR(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_LINEAR(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_PRE_NOTE: diff --git a/src/engine/platform/vb.cpp b/src/engine/platform/vb.cpp index ae75f0044..a0be3efb5 100644 --- a/src/engine/platform/vb.cpp +++ b/src/engine/platform/vb.cpp @@ -297,7 +297,7 @@ int DivPlatformVB::dispatch(DivCommand c) { } chWrite(4,0x00,0x80); } - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; writeEnv(c.chan); } @@ -445,9 +445,9 @@ int DivPlatformVB::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/vera.cpp b/src/engine/platform/vera.cpp index 29f6df07d..62ea0d6dd 100644 --- a/src/engine/platform/vera.cpp +++ b/src/engine/platform/vera.cpp @@ -347,7 +347,7 @@ int DivPlatformVERA::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VERA)); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -421,7 +421,7 @@ int DivPlatformVERA::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VERA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VERA)); } if (!chan[c.chan].inPorta && c.value && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=calcNoteFreq(c.chan,chan[c.chan].note); chan[c.chan].inPorta=c.value; diff --git a/src/engine/platform/vic20.cpp b/src/engine/platform/vic20.cpp index 0a3e763a2..21f8f1e6b 100644 --- a/src/engine/platform/vic20.cpp +++ b/src/engine/platform/vic20.cpp @@ -247,9 +247,9 @@ int DivPlatformVIC20::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VIC)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VIC)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/vrc6.cpp b/src/engine/platform/vrc6.cpp index 18a7be76a..62e2bd658 100644 --- a/src/engine/platform/vrc6.cpp +++ b/src/engine/platform/vrc6.cpp @@ -297,7 +297,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } //chan[c.chan].keyOn=true; @@ -418,9 +418,9 @@ int DivPlatformVRC6::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VRC6)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VRC6)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/x1_010.cpp b/src/engine/platform/x1_010.cpp index 36f0d26ee..b8615f30f 100644 --- a/src/engine/platform/x1_010.cpp +++ b/src/engine/platform/x1_010.cpp @@ -614,7 +614,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) { chan[c.chan].keyOn=true; chan[c.chan].envChanged=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } if (chan[c.chan].wave<0) { @@ -729,9 +729,9 @@ int DivPlatformX1_010::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_X1_010)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_X1_010)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NoteX1_010(c.chan,chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NoteX1_010(c.chan,chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_FREQ: diff --git a/src/engine/platform/ym2203.cpp b/src/engine/platform/ym2203.cpp index 98fd77a36..562043820 100644 --- a/src/engine/platform/ym2203.cpp +++ b/src/engine/platform/ym2203.cpp @@ -551,7 +551,7 @@ void DivPlatformYM2203::tick(bool sysTick) { if (chan[i].std.alg.had) { chan[i].state.alg=chan[i].std.alg.val; rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[i]|opOffs[j]; DivInstrumentFM::Operator& op=chan[i].state.op[j]; if (isMuted[i] || !op.enable) { @@ -661,7 +661,7 @@ void DivPlatformYM2203::tick(bool sysTick) { for (int i=0; i<3; i++) { if (i==2 && extMode) continue; if (chan[i].freqChanged) { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[i].state.block); } else { int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2); @@ -797,7 +797,7 @@ int DivPlatformYM2203::dispatch(DivCommand c) { chan[c.chan].keyOff=true; chan[c.chan].keyOn=false; chan[c.chan].active=false; - if (parent->song.brokenFMOff) chan[c.chan].macroInit(NULL); + if (parent->song.compatFlags.brokenFMOff) chan[c.chan].macroInit(NULL); break; case DIV_CMD_NOTE_OFF_ENV: chan[c.chan].keyOff=true; @@ -867,7 +867,7 @@ int DivPlatformYM2203::dispatch(DivCommand c) { } break; } - if (c.chan>(psgChanOffs-1) || parent->song.linearPitch) { // PSG + if (c.chan>(psgChanOffs-1) || parent->song.compatFlags.linearPitch) { // PSG int destFreq=NOTE_FNUM_BLOCK(c.value2,11,chan[c.chan].state.block); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { @@ -1156,7 +1156,7 @@ int DivPlatformYM2203::dispatch(DivCommand c) { case DIV_CMD_PRE_PORTA: if (c.chan>(2+isCSM)) { if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); } } chan[c.chan].inPorta=c.value; diff --git a/src/engine/platform/ym2203ext.cpp b/src/engine/platform/ym2203ext.cpp index c4679f22c..1a389de42 100644 --- a/src/engine/platform/ym2203ext.cpp +++ b/src/engine/platform/ym2203ext.cpp @@ -146,7 +146,7 @@ int DivPlatformYM2203Ext::dispatch(DivCommand c) { break; } case DIV_CMD_NOTE_PORTA: { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { int destFreq=NOTE_FREQUENCY(c.value2); bool return2=false; if (destFreq>opChan[ch].baseFreq) { @@ -472,7 +472,7 @@ void DivPlatformYM2203Ext::tick(bool sysTick) { if (opChan[i].std.alg.had) { chan[extChanOffs].state.alg=opChan[i].std.alg.val; rWrite(chanOffs[extChanOffs]+ADDR_FB_ALG,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[j]; DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[j]; if (isOpMuted[j] || !op.enable) { @@ -551,7 +551,7 @@ void DivPlatformYM2203Ext::tick(bool sysTick) { unsigned char hardResetMask=0; if (extMode) for (int i=0; i<4; i++) { if (opChan[i].freqChanged) { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,4,opChan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[extChanOffs].state.block); } else { int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,4,opChan[i].pitch2); diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index 26ecfbc63..87f2a604c 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -794,7 +794,7 @@ void DivPlatformYM2608::tick(bool sysTick) { if (chan[i].std.alg.had) { chan[i].state.alg=chan[i].std.alg.val; rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[i]|opOffs[j]; DivInstrumentFM::Operator& op=chan[i].state.op[j]; if (isMuted[i] || !op.enable) { @@ -916,7 +916,7 @@ void DivPlatformYM2608::tick(bool sysTick) { for (int i=0; i<6; i++) { if (i==2 && extMode) continue; if (chan[i].freqChanged) { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[i].state.block); } else { int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2); @@ -1238,7 +1238,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) { chan[c.chan].keyOff=true; chan[c.chan].keyOn=false; chan[c.chan].active=false; - if (parent->song.brokenFMOff) chan[c.chan].macroInit(NULL); + if (parent->song.compatFlags.brokenFMOff) chan[c.chan].macroInit(NULL); break; case DIV_CMD_NOTE_OFF_ENV: chan[c.chan].keyOff=true; @@ -1340,7 +1340,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) { } break; } - if (c.chan>(5+isCSM) || parent->song.linearPitch) { // PSG, ADPCM-B + if (c.chan>(5+isCSM) || parent->song.compatFlags.linearPitch) { // PSG, ADPCM-B int destFreq=NOTE_OPNB(c.chan,c.value2+chan[c.chan].sampleNoteDelta); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { @@ -1651,7 +1651,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) { case DIV_CMD_PRE_PORTA: if (c.chan>5) { if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); } } chan[c.chan].inPorta=c.value; diff --git a/src/engine/platform/ym2608ext.cpp b/src/engine/platform/ym2608ext.cpp index 670df9f6e..926b90cf8 100644 --- a/src/engine/platform/ym2608ext.cpp +++ b/src/engine/platform/ym2608ext.cpp @@ -150,7 +150,7 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) { } else { opChan[ch].pan=(c.value2>0)|((c.value>0)<<1); } - if (parent->song.sharedExtStat) { + if (parent->song.compatFlags.sharedExtStat) { for (int i=0; i<4; i++) { if (ch==i) continue; opChan[i].pan=opChan[ch].pan; @@ -166,7 +166,7 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) { break; } case DIV_CMD_NOTE_PORTA: { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { int destFreq=NOTE_FREQUENCY(c.value2); bool return2=false; if (destFreq>opChan[ch].baseFreq) { @@ -510,7 +510,7 @@ void DivPlatformYM2608Ext::tick(bool sysTick) { if (opChan[i].std.alg.had) { chan[extChanOffs].state.alg=opChan[i].std.alg.val; rWrite(chanOffs[extChanOffs]+ADDR_FB_ALG,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[j]; DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[j]; if (isOpMuted[j] || !op.enable) { @@ -541,7 +541,7 @@ void DivPlatformYM2608Ext::tick(bool sysTick) { if (opChan[i].std.panL.had) { opChan[i].pan=opChan[i].std.panL.val&3; - if (parent->song.sharedExtStat) { + if (parent->song.compatFlags.sharedExtStat) { for (int j=0; j<4; j++) { if (i==j) continue; opChan[j].pan=opChan[i].pan; @@ -612,7 +612,7 @@ void DivPlatformYM2608Ext::tick(bool sysTick) { unsigned char hardResetMask=0; if (extMode) for (int i=0; i<4; i++) { if (opChan[i].freqChanged) { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,4,opChan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[extChanOffs].state.block); } else { int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,4,opChan[i].pitch2); diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index e8e2123a9..cc3b70f66 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -714,7 +714,7 @@ void DivPlatformYM2610::tick(bool sysTick) { if (chan[i].std.alg.had) { chan[i].state.alg=chan[i].std.alg.val; rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[i]|opOffs[j]; DivInstrumentFM::Operator& op=chan[i].state.op[j]; if (isMuted[i] || !op.enable) { @@ -836,7 +836,7 @@ void DivPlatformYM2610::tick(bool sysTick) { for (int i=0; i<(psgChanOffs-isCSM); i++) { if (i==1 && extMode) continue; if (chan[i].freqChanged) { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[i].state.block); } else { int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2,chipClock,CHIP_FREQBASE,11); @@ -1178,7 +1178,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) { chan[c.chan].keyOff=true; chan[c.chan].keyOn=false; chan[c.chan].active=false; - if (parent->song.brokenFMOff) chan[c.chan].macroInit(NULL); + if (parent->song.compatFlags.brokenFMOff) chan[c.chan].macroInit(NULL); break; case DIV_CMD_NOTE_OFF_ENV: chan[c.chan].keyOff=true; @@ -1280,7 +1280,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) { } break; } - if (c.chan>=psgChanOffs || parent->song.linearPitch) { // PSG, ADPCM-B + if (c.chan>=psgChanOffs || parent->song.compatFlags.linearPitch) { // PSG, ADPCM-B int destFreq=NOTE_OPNB(c.chan,c.value2+chan[c.chan].sampleNoteDelta); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { @@ -1591,7 +1591,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) { case DIV_CMD_PRE_PORTA: if (c.chan>=psgChanOffs) { if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); } } chan[c.chan].inPorta=c.value; diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index 413bdcbae..12f75e1b9 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -783,7 +783,7 @@ void DivPlatformYM2610B::tick(bool sysTick) { if (chan[i].std.alg.had) { chan[i].state.alg=chan[i].std.alg.val; rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[i]|opOffs[j]; DivInstrumentFM::Operator& op=chan[i].state.op[j]; if (isMuted[i] || !op.enable) { @@ -905,7 +905,7 @@ void DivPlatformYM2610B::tick(bool sysTick) { for (int i=0; i<(psgChanOffs-isCSM); i++) { if (i==2 && extMode) continue; if (chan[i].freqChanged) { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[i].state.block); } else { int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2); @@ -1247,7 +1247,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { chan[c.chan].keyOff=true; chan[c.chan].keyOn=false; chan[c.chan].active=false; - if (parent->song.brokenFMOff) chan[c.chan].macroInit(NULL); + if (parent->song.compatFlags.brokenFMOff) chan[c.chan].macroInit(NULL); break; case DIV_CMD_NOTE_OFF_ENV: chan[c.chan].keyOff=true; @@ -1349,7 +1349,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { } break; } - if (c.chan>=psgChanOffs || parent->song.linearPitch) { // PSG, ADPCM-B + if (c.chan>=psgChanOffs || parent->song.compatFlags.linearPitch) { // PSG, ADPCM-B int destFreq=NOTE_OPNB(c.chan,c.value2+chan[c.chan].sampleNoteDelta); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { @@ -1660,7 +1660,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { case DIV_CMD_PRE_PORTA: if (c.chan>=psgChanOffs) { if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); } } chan[c.chan].inPorta=c.value; diff --git a/src/engine/platform/ym2610bext.cpp b/src/engine/platform/ym2610bext.cpp index d08c14c34..075540580 100644 --- a/src/engine/platform/ym2610bext.cpp +++ b/src/engine/platform/ym2610bext.cpp @@ -146,7 +146,7 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) { } else { opChan[ch].pan=(c.value2>0)|((c.value>0)<<1); } - if (parent->song.sharedExtStat) { + if (parent->song.compatFlags.sharedExtStat) { for (int i=0; i<4; i++) { if (ch==i) continue; opChan[i].pan=opChan[ch].pan; @@ -162,7 +162,7 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) { break; } case DIV_CMD_NOTE_PORTA: { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { int destFreq=NOTE_FREQUENCY(c.value2); bool return2=false; if (destFreq>opChan[ch].baseFreq) { @@ -503,7 +503,7 @@ void DivPlatformYM2610BExt::tick(bool sysTick) { if (opChan[i].std.alg.had) { chan[extChanOffs].state.alg=opChan[i].std.alg.val; rWrite(chanOffs[extChanOffs]+ADDR_FB_ALG,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[j]; DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[j]; if (isOpMuted[j] || !op.enable) { @@ -534,7 +534,7 @@ void DivPlatformYM2610BExt::tick(bool sysTick) { if (opChan[i].std.panL.had) { opChan[i].pan=opChan[i].std.panL.val&3; - if (parent->song.sharedExtStat) { + if (parent->song.compatFlags.sharedExtStat) { for (int j=0; j<4; j++) { if (i==j) continue; opChan[j].pan=opChan[i].pan; @@ -604,7 +604,7 @@ void DivPlatformYM2610BExt::tick(bool sysTick) { unsigned char hardResetMask=0; if (extMode) for (int i=0; i<4; i++) { if (opChan[i].freqChanged) { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,4,opChan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[extChanOffs].state.block); } else { int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,4,opChan[i].pitch2); diff --git a/src/engine/platform/ym2610ext.cpp b/src/engine/platform/ym2610ext.cpp index 0ae983065..fa55460ce 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -146,7 +146,7 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) { } else { opChan[ch].pan=(c.value2>0)|((c.value>0)<<1); } - if (parent->song.sharedExtStat) { + if (parent->song.compatFlags.sharedExtStat) { for (int i=0; i<4; i++) { if (ch==i) continue; opChan[i].pan=opChan[ch].pan; @@ -162,7 +162,7 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) { break; } case DIV_CMD_NOTE_PORTA: { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { int destFreq=NOTE_FREQUENCY(c.value2); bool return2=false; if (destFreq>opChan[ch].baseFreq) { @@ -503,7 +503,7 @@ void DivPlatformYM2610Ext::tick(bool sysTick) { if (opChan[i].std.alg.had) { chan[extChanOffs].state.alg=opChan[i].std.alg.val; rWrite(chanOffs[extChanOffs]+ADDR_FB_ALG,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3)); - if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) { + if (!parent->song.compatFlags.algMacroBehavior) for (int j=0; j<4; j++) { unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[j]; DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[j]; if (isOpMuted[j] || !op.enable) { @@ -534,7 +534,7 @@ void DivPlatformYM2610Ext::tick(bool sysTick) { if (opChan[i].std.panL.had) { opChan[i].pan=opChan[i].std.panL.val&3; - if (parent->song.sharedExtStat) { + if (parent->song.compatFlags.sharedExtStat) { for (int j=0; j<4; j++) { if (i==j) continue; opChan[j].pan=opChan[i].pan; @@ -604,7 +604,7 @@ void DivPlatformYM2610Ext::tick(bool sysTick) { unsigned char hardResetMask=0; if (extMode) for (int i=0; i<4; i++) { if (opChan[i].freqChanged) { - if (parent->song.linearPitch) { + if (parent->song.compatFlags.linearPitch) { opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,4,opChan[i].pitch2,chipClock,CHIP_FREQBASE,11,chan[extChanOffs].state.block); } else { int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,opChan[i].fixedArp?opChan[i].baseNoteOverride:opChan[i].arpOff,opChan[i].fixedArp,false,4,opChan[i].pitch2); diff --git a/src/engine/platform/ymz280b.cpp b/src/engine/platform/ymz280b.cpp index 6684f4011..55350818a 100644 --- a/src/engine/platform/ymz280b.cpp +++ b/src/engine/platform/ymz280b.cpp @@ -241,7 +241,7 @@ int DivPlatformYMZ280B::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } break; @@ -287,7 +287,7 @@ int DivPlatformYMZ280B::dispatch(DivCommand c) { case DIV_CMD_NOTE_PORTA: { int destFreq=NOTE_FREQUENCY(c.value2+chan[c.chan].sampleNoteDelta); bool return2=false; - int multiplier=(parent->song.linearPitch)?1:256; + int multiplier=(parent->song.compatFlags.linearPitch)?1:256; if (destFreq>chan[c.chan].baseFreq) { chan[c.chan].baseFreq+=c.value*multiplier; if (chan[c.chan].baseFreq>=destFreq) { @@ -316,9 +316,9 @@ int DivPlatformYMZ280B::dispatch(DivCommand c) { } case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: diff --git a/src/engine/platform/zxbeeper.cpp b/src/engine/platform/zxbeeper.cpp index 7e0dbe74d..3475d36f2 100644 --- a/src/engine/platform/zxbeeper.cpp +++ b/src/engine/platform/zxbeeper.cpp @@ -212,9 +212,9 @@ int DivPlatformZXBeeper::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/platform/zxbeeperquadtone.cpp b/src/engine/platform/zxbeeperquadtone.cpp index 5fd27689c..3c3b93f92 100644 --- a/src/engine/platform/zxbeeperquadtone.cpp +++ b/src/engine/platform/zxbeeperquadtone.cpp @@ -190,7 +190,7 @@ int DivPlatformZXBeeperQuadTone::dispatch(DivCommand c) { chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); chan[c.chan].insChanged=false; - if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { + if (!parent->song.compatFlags.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; writeOutVol(c.chan); } @@ -293,9 +293,9 @@ int DivPlatformZXBeeperQuadTone::dispatch(DivCommand c) { break; case DIV_CMD_PRE_PORTA: if (chan[c.chan].active && c.value2) { - if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_POKEMINI)); + if (parent->song.compatFlags.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_POKEMINI)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && !parent->song.compatFlags.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_FREQUENCY(chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index f9bda8a9b..a59fb3c8d 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -664,9 +664,9 @@ void DivEngine::processRow(int i, bool afterDelay) { // - 2: DefleMask (same as 1) // in the case of normal, the jump row (changePos) is not reset to 0 // this means that you can do 0Dxx 0Byy and it'll work, taking you to row xx of order yy - if (changeOrd==-1 || song.jumpTreatment==0) { + if (changeOrd==-1 || song.compatFlags.jumpTreatment==0) { changeOrd=effectVal; - if (song.jumpTreatment==1 || song.jumpTreatment==2) { + if (song.compatFlags.jumpTreatment==1 || song.compatFlags.jumpTreatment==2) { changePos=0; } } @@ -676,23 +676,23 @@ void DivEngine::processRow(int i, bool afterDelay) { // if there is a 0Dxx effect on the very last order, it is ignored // COMPAT FLAG: simultaneous jump treatment - if (song.jumpTreatment==2) { + if (song.compatFlags.jumpTreatment==2) { // - 2: DefleMask (jump to next order unless it is the last one and ignoreJumpAtEnd is on) - if ((curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd)) { + if ((curOrder<(curSubSong->ordersLen-1) || !song.compatFlags.ignoreJumpAtEnd)) { // changeOrd -2 means increase order by 1 // it overrides a previous 0Bxx effect changeOrd=-2; changePos=effectVal; } - } else if (song.jumpTreatment==1) { + } else if (song.compatFlags.jumpTreatment==1) { // - 1: old Furnace (same as 2 but ignored if 0Bxx is present) - if (changeOrd<0 && (curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd)) { + if (changeOrd<0 && (curOrder<(curSubSong->ordersLen-1) || !song.compatFlags.ignoreJumpAtEnd)) { changeOrd=-2; changePos=effectVal; } } else { // - 0: normal - if (curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd) { + if (curOrder<(curSubSong->ordersLen-1) || !song.compatFlags.ignoreJumpAtEnd) { // set the target order if not set, allowing you to use 0B and 0D regardless of position if (changeOrd<0) { changeOrd=-2; @@ -710,8 +710,8 @@ void DivEngine::processRow(int i, bool afterDelay) { // - delays equal or greater to the speed are ignored // - 2: lax (default) // - no delay is ever ignored unless overridden by another - bool comparison=(song.delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<(nextSpeed*(curSubSong->timeBase+1))); - if (song.delayBehavior==2) comparison=true; + bool comparison=(song.compatFlags.delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<(nextSpeed*(curSubSong->timeBase+1))); + if (song.compatFlags.delayBehavior==2) comparison=true; if (comparison) { // set the delay row, order and timer chan[i].rowDelay=effectVal; @@ -762,7 +762,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // COMPAT FLAG: legacy volume slides // - sets volume to max once a vol slide down has finished (thus setting volume to volMax+1) - if (song.legacyVolumeSlides && chan[i].volume==chan[i].volMax+1) { + if (song.compatFlags.legacyVolumeSlides && chan[i].volume==chan[i].volMax+1) { logV("forcing volume"); chan[i].volume=chan[i].volMax; dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8)); @@ -780,7 +780,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // COMPAT FLAG: reset slides on note off (inverted in the GUI) // - a portamento/pitch slide will be halted upon encountering note off // - this will not occur if the stopPortaOnNoteOff flag is on and this is a portamento - if (chan[i].inPorta && song.noteOffResetsSlides) { + if (chan[i].inPorta && song.compatFlags.noteOffResetsSlides) { // stopOnOff will be false if stopPortaOnNoteOff flag is off if (chan[i].stopOnOff) { chan[i].portaNote=-1; @@ -805,7 +805,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].keyOn=false; chan[i].keyOff=true; // same thing here regarding reset slide behavior - if (chan[i].inPorta && song.noteOffResetsSlides) { + if (chan[i].inPorta && song.compatFlags.noteOffResetsSlides) { if (chan[i].stopOnOff) { chan[i].portaNote=-1; chan[i].portaSpeed=-1; @@ -843,7 +843,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].doNote=true; // COMPAT FLAG: compatible arpeggio // - once a new note plays, arp will not be applied for this tick - if (chan[i].arp!=0 && song.compatibleArpeggio) { + if (chan[i].arp!=0 && song.compatFlags.compatibleArpeggio) { chan[i].arpYield=true; } } @@ -872,7 +872,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // COMPAT FLAG: legacy ALWAYS_SET_VOLUME behavior (oldAlwaysSetVolume) // - prior to its addition, volume changes wouldn't be effective depending on the system if the volume is the same as the current one // - afterwards, volume change is made regardless in order to set the bottom byte of volume ("subvolume") - if (!song.oldAlwaysSetVolume || disCont[song.dispatchOfChan[i]].dispatch->getLegacyAlwaysSetVolume() || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->newData[whatRow][DIV_PAT_VOL]) { + if (!song.compatFlags.oldAlwaysSetVolume || disCont[song.dispatchOfChan[i]].dispatch->getLegacyAlwaysSetVolume() || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->newData[whatRow][DIV_PAT_VOL]) { // here we let dispatchCmd() know we can do MIDI aftertouch if there isn't a note if (pat->newData[whatRow][DIV_PAT_NOTE]==-1) { chan[i].midiAftertouch=true; @@ -982,7 +982,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // - 02xx still works // - a previous portamento (03xx) will prevent this slide from occurring // - E1xy/E2xy also will if *another* flag is set - if (song.ignoreDuplicateSlides && (lastSlide==0x01 || lastSlide==0x1337)) break; + if (song.compatFlags.ignoreDuplicateSlides && (lastSlide==0x01 || lastSlide==0x1337)) break; lastSlide=0x01; if (effectVal==0) { chan[i].portaNote=-1; @@ -994,12 +994,12 @@ void DivEngine::processRow(int i, bool afterDelay) { // - this prompts dispatch to stop processing arp macros during a slide // - this only happens if pitch linearity is set to None // - if we don't let dispatch know, the slide will never occur as arp takes over - if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); + if (!song.compatFlags.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); } else { // COMPAT FLAG: limit slide range // - this confines pitch slides from dispatch->getPortaFloor to C-8 (I think) // - yep, the lowest portamento note depends on the system... - chan[i].portaNote=song.limitSlides?0x60:255; + chan[i].portaNote=song.compatFlags.limitSlides?0x60:255; chan[i].portaSpeed=effectVal; dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); // most of these are used for compat flag handling @@ -1013,7 +1013,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // - this prompts dispatch to stop processing arp macros during a slide // - this only happens if pitch linearity is set to None // - if we don't let dispatch know, the slide will never occur as arp takes over - if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0)); + if (!song.compatFlags.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0)); } break; case 0x02: // pitch slide down @@ -1022,7 +1022,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // - 01xx still works // - a previous portamento (03xx) will prevent this slide from occurring // - E1xy/E2xy also will if *another* flag is set - if (song.ignoreDuplicateSlides && (lastSlide==0x02 || lastSlide==0x1337)) break; + if (song.compatFlags.ignoreDuplicateSlides && (lastSlide==0x02 || lastSlide==0x1337)) break; lastSlide=0x02; if (effectVal==0) { chan[i].portaNote=-1; @@ -1030,12 +1030,12 @@ void DivEngine::processRow(int i, bool afterDelay) { dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); chan[i].inPorta=false; // COMPAT FLAG: arpeggio inhibits non-porta slides - if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); + if (!song.compatFlags.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); } else { // COMPAT FLAG: limit slide range // - this confines pitch slides from dispatch->getPortaFloor to C-8 (I think) // - yep, the lowest portamento note depends on the system... - chan[i].portaNote=(song.limitSlides && song.dispatchChanOfChan[i]>=0)?disCont[song.dispatchOfChan[i]].dispatch->getPortaFloor(song.dispatchChanOfChan[i]):-60; + chan[i].portaNote=(song.compatFlags.limitSlides && song.dispatchChanOfChan[i]>=0)?disCont[song.dispatchOfChan[i]].dispatch->getPortaFloor(song.dispatchChanOfChan[i]):-60; chan[i].portaSpeed=effectVal; dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); chan[i].portaStop=true; @@ -1044,7 +1044,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].wasShorthandPorta=false; chan[i].inPorta=false; // COMPAT FLAG: arpeggio inhibits non-porta slides - if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0)); + if (!song.compatFlags.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0)); } break; case 0x03: // portamento @@ -1064,7 +1064,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // COMPAT FLAG: buggy portamento after sliding // - you might want to slide up or down and then 03xx to return to the original note // - if a porta to the same note is attempted after slide, for some reason it does not occur - if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.buggyPortaAfterSlide) { + if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.compatFlags.buggyPortaAfterSlide) { chan[i].portaNote=chan[i].note; chan[i].portaSpeed=-1; } else { @@ -1084,7 +1084,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // COMPAT FLAG: stop portamento on note off // - if a portamento is called and then a note off occurs, stop portamento before the next note // - ...unless noteOffResetsSlides is disabled - chan[i].stopOnOff=song.stopPortaOnNoteOff; // what?! + chan[i].stopOnOff=song.compatFlags.stopPortaOnNoteOff; // what?! chan[i].scheduledSlideReset=false; dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,1)); // this is used to inhibit any other slide commands if the respective compat flag is enabled @@ -1144,7 +1144,7 @@ void DivEngine::processRow(int i, bool afterDelay) { calledPorta=true; // COMPAT FLAG: buggy portamento after sliding // yes, this also affects 06xy. - if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.buggyPortaAfterSlide) { + if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.compatFlags.buggyPortaAfterSlide) { chan[i].portaNote=chan[i].note; chan[i].portaSpeed=-1; } else { @@ -1157,7 +1157,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // this is the same as 03xx. chan[i].portaStop=true; if (chan[i].keyOn) chan[i].doNote=false; - chan[i].stopOnOff=song.stopPortaOnNoteOff; // what?! + chan[i].stopOnOff=song.compatFlags.stopPortaOnNoteOff; // what?! chan[i].scheduledSlideReset=false; dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,1)); lastSlide=0x1337; // i hate this so much @@ -1224,7 +1224,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].arp=effectVal; // COMPAT FLAG: reset note to base on arp stop (inverted in the GUI) // - a 0000 effect resets arpeggio position - if (chan[i].arp==0 && song.arp0Reset) { + if (chan[i].arp==0 && song.compatFlags.arp0Reset) { chan[i].resetArp=true; } dispatchCmd(DivCommand(DIV_CMD_HINT_ARPEGGIO,i,chan[i].arp)); @@ -1246,7 +1246,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // COMPAT FLAG: old sample offset effect // - before 0.6.3 the sample offset effect was 9xxx, where `xxx` is multiplied by 256 // - the effect was then changed to 90xx/91xx/92xx, allowing you to set the low, mid and high bytes of the offset respectively - if (song.oldSampleOffset) { + if (song.compatFlags.oldSampleOffset) { // send sample position now dispatchCmd(DivCommand(DIV_CMD_SAMPLE_POS,i,(((effect&0x0f)<<8)|effectVal)*256)); } else { @@ -1279,7 +1279,7 @@ void DivEngine::processRow(int i, bool afterDelay) { // - ignore cut if equal or greater than speed // - 2: lax (default) // - no cut is ever ignored unless overridden by another - if (effectVal>0 && (song.delayBehavior==2 || effectVal0 && (song.compatFlags.delayBehavior==2 || effectVal0 && (song.delayBehavior==2 || effectVal0 && (song.compatFlags.delayBehavior==2 || effectVal0 && (song.delayBehavior==2 || effectVal0 && (song.compatFlags.delayBehavior==2 || effectVal=0)?disCont[song.dispatchOfChan[i]].dispatch->getPortaFloor(song.dispatchChanOfChan[i]):-60; + chan[i].portaNote=(song.compatFlags.limitSlides && song.dispatchChanOfChan[i]>=0)?disCont[song.dispatchOfChan[i]].dispatch->getPortaFloor(song.dispatchChanOfChan[i]):-60; } chan[i].portaSpeed=effectVal; chan[i].portaStop=true; @@ -1688,13 +1688,13 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].scheduledSlideReset=false; chan[i].inPorta=false; // COMPAT FLAG: arpeggio inhibits non-porta slides - if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0)); - dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed*(song.linearPitch?song.pitchSlideSpeed:1),chan[i].portaNote)); + if (!song.compatFlags.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0)); + dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed*(song.compatFlags.linearPitch?song.compatFlags.pitchSlideSpeed:1),chan[i].portaNote)); chan[i].portaNote=-1; chan[i].portaSpeed=-1; chan[i].inPorta=false; // COMPAT FLAG: arpeggio inhibits non-porta slides - if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); + if (!song.compatFlags.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); break; } } @@ -1797,7 +1797,7 @@ void DivEngine::nextRow() { for (int i=0; i=2)?speeds.val[1]:speeds.val[0]; unsigned char speed1=speeds.val[0]; @@ -1913,7 +1913,7 @@ void DivEngine::nextRow() { // COMPAT FLAG: pre-note does not take effect into consideration // - a bug which does not cancel pre-note before a portamento or during legato // - fixed in 0.6pre9 - if (!song.preNoteNoEffect) { + if (!song.compatFlags.preNoteNoEffect) { // handle portamento if (pat->newData[curRow][DIV_PAT_FX(j)]==0x03 && pat->newData[curRow][DIV_PAT_FXVAL(j)]!=0 && pat->newData[curRow][DIV_PAT_FXVAL(j)]!=-1) { doPreparePreNote=false; @@ -1947,7 +1947,7 @@ void DivEngine::nextRow() { // COMPAT FLAG: auto-insert one tick gap between notes // - simulates behavior of certain Amiga/C64 sound drivers where a one-tick cut occurred before another note - if (song.oneTickCut) { + if (song.compatFlags.oneTickCut) { bool doPrepareCut=true; int addition=0; @@ -2158,7 +2158,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { // - 0: reset channels. call playSub() to seek back to the loop position // - 1: soft-reset channels. same as 0 for now // - 2: don't reset - if (song.loopModality!=2) { + if (song.compatFlags.loopModality!=2) { playSub(true); } } @@ -2205,7 +2205,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { // volume slides and tremolo // COMPAT FLAG: don't slide on the first tick of a row // - Amiga/PC tracker behavior where slides and vibrato do not take course during the first tick of a row - if (!song.noSlidesOnFirstTick || !firstTick) { + if (!song.compatFlags.noSlidesOnFirstTick || !firstTick) { // volume slides if (chan[i].volSpeed!=0) { // the call to GET_VOLUME is part of a compatibility process @@ -2255,7 +2255,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { // COMPAT FLAG: legacy volume slides // - sets volume to max once a vol slide down has finished (thus setting volume to volMax+1) // - there is more to this, such as the first step of volume macro resulting in unpredictable behavior, but I don't feel like implementing THAT... - if (song.legacyVolumeSlides) { + if (song.compatFlags.legacyVolumeSlides) { chan[i].volume=chan[i].volMax+1; } else { chan[i].volume=0; @@ -2418,7 +2418,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { // portamento and pitch slides // COMPAT FLAG: don't slide on the first tick of a row // - Amiga/PC tracker behavior where slides and vibrato do not take course during the first tick of a row - if (!song.noSlidesOnFirstTick || !firstTick) { + if (!song.compatFlags.noSlidesOnFirstTick || !firstTick) { // portamento only runs if the channel has been used and the porta speed is higher than 0 if ((chan[i].keyOn || chan[i].keyOff) && chan[i].portaSpeed>0) { // send a portamento update command to the dispatch. @@ -2428,7 +2428,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { // - 1: full (pitch slides linear... we multiply the portamento speed by a user-defined multiplier) // COMPAT FLAG: reset pitch slide/portamento upon reaching target (inverted in the GUI) // - when disabled, portamento remains active after it has finished - if (dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed*(song.linearPitch?song.pitchSlideSpeed:1),chan[i].portaNote))==2 && chan[i].portaStop && song.targetResetsSlides) { + if (dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed*(song.compatFlags.linearPitch?song.compatFlags.pitchSlideSpeed:1),chan[i].portaNote))==2 && chan[i].portaStop && song.compatFlags.targetResetsSlides) { // if we are here, it means we reached the target and shall stop chan[i].portaSpeed=0; dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); @@ -2454,7 +2454,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { // COMPAT FLAG: reset slides on note off (inverted in the GUI) // - a portamento/pitch slide will be halted upon encountering note off // - this will not occur if the stopPortaOnNoteOff flag is on and this is a portamento - if (chan[i].inPorta && song.noteOffResetsSlides) { + if (chan[i].inPorta && song.compatFlags.noteOffResetsSlides) { chan[i].keyOff=true; chan[i].keyOn=false; // stopOnOff will be false if stopPortaOnNoteOff flag is off @@ -2503,7 +2503,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { } // COMPAT FLAG: reset arp position on row change // - simulates Amiga/PC tracker behavior where the next row resets arp pos - if (song.rowResetsArpPos && firstTick) { + if (song.compatFlags.rowResetsArpPos && firstTick) { chan[i].arpStage=-1; } // arpeggio (actually) diff --git a/src/engine/song.cpp b/src/engine/song.cpp index 970dae4b6..ef1366b53 100644 --- a/src/engine/song.cpp +++ b/src/engine/song.cpp @@ -22,6 +22,8 @@ #include #include +static DivCompatFlags defaultFlags; + TimeMicros DivSongTimestamps::getTimes(int order, int row) { if (order<0 || order>=DIV_MAX_PATTERNS) return TimeMicros(-1,0); if (row<0 || row>=DIV_MAX_ROWS) return TimeMicros(-1,0); @@ -448,6 +450,66 @@ void DivSubSong::calcTimestamps(int chans, std::vector& groove logV("song length: %s; %" PRIu64 " ticks",ts.totalTime.toString(6,TA_TIME_FORMAT_AUTO),ts.totalTicks); } +void DivSubSong::putData(SafeWriter* w, int chans) { + size_t blockStartSeek, blockEndSeek; + w->write("SNG2",4); + blockStartSeek=w->tell(); + w->writeI(0); + + w->writeF(hz); + w->writeC(arpLen); + w->writeC(timeBase); + w->writeS(patLen); + w->writeS(ordersLen); + w->writeC(hilightA); + w->writeC(hilightB); + w->writeS(virtualTempoN); + w->writeS(virtualTempoD); + + // speeds + w->writeS(speeds.len); + for (int i=0; i<16; i++) { + w->writeS(speeds.val[i]); + } + + w->writeString(name,false); + w->writeString(notes,false); + + for (int i=0; iwriteC(orders.ord[i][j]); + } + } + + for (int i=0; iwriteC(pat[i].effectCols); + } + + for (int i=0; iwriteC( + (chanShow[i]?1:0)| + (chanShowChanOsc[i]?2:0) + ); + } + + for (int i=0; iwriteC(chanCollapse[i]); + } + + for (int i=0; iwriteString(chanName[i],false); + } + + for (int i=0; iwriteString(chanShortName[i],false); + } + + blockEndSeek=w->tell(); + w->seek(blockStartSeek,SEEK_SET); + w->writeI(blockEndSeek-blockStartSeek-4); + w->seek(0,SEEK_END); +} + void DivSubSong::clearData() { for (int i=0; iordersLen) { - i->calcTimestamps(chans,grooves,jumpTreatment,ignoreJumpAtEnd,brokenSpeedSel,delayBehavior,curStart); + i->calcTimestamps(chans,grooves,compatFlags.jumpTreatment,compatFlags.ignoreJumpAtEnd,compatFlags.brokenSpeedSel,compatFlags.delayBehavior,curStart); if (!i->ts.isLoopable) break; // make sure we don't pick the same range twice @@ -809,3 +871,167 @@ void DivSong::unload() { } subsong.clear(); } + +void DivGroovePattern::putData(SafeWriter* w) { + size_t blockStartSeek, blockEndSeek; + w->write("GROV",4); + blockStartSeek=w->tell(); + w->writeI(0); + + w->writeS(len); + for (int i=0; i<16; i++) { + w->writeS(val[i]); + } + + blockEndSeek=w->tell(); + w->seek(blockStartSeek,SEEK_SET); + w->writeI(blockEndSeek-blockStartSeek-4); + w->seek(0,SEEK_END); +} + +void DivCompatFlags::setDefaults() { + limitSlides=false; + linearPitch=1; + pitchSlideSpeed=4; + loopModality=2; + delayBehavior=2; + jumpTreatment=0; + properNoiseLayout=true; + waveDutyIsVol=false; + resetMacroOnPorta=false; + legacyVolumeSlides=false; + compatibleArpeggio=false; + noteOffResetsSlides=true; + targetResetsSlides=true; + arpNonPorta=false; + algMacroBehavior=false; + brokenShortcutSlides=false; + ignoreDuplicateSlides=false; + stopPortaOnNoteOff=false; + continuousVibrato=false; + brokenDACMode=false; + oneTickCut=false; + newInsTriggersInPorta=true; + arp0Reset=true; + brokenSpeedSel=false; + noSlidesOnFirstTick=false; + rowResetsArpPos=false; + ignoreJumpAtEnd=false; + buggyPortaAfterSlide=false; + gbInsAffectsEnvelope=true; + sharedExtStat=true; + ignoreDACModeOutsideIntendedChannel=false; + e1e2AlsoTakePriority=false; + newSegaPCM=true; + fbPortaPause=false; + snDutyReset=false; + pitchMacroIsLinear=true; + oldOctaveBoundary=false; + noOPN2Vol=false; + newVolumeScaling=true; + volMacroLinger=true; + brokenOutVol=false; + brokenOutVol2=false; + e1e2StopOnSameNote=false; + brokenPortaArp=false; + snNoLowPeriods=false; + disableSampleMacro=false; + oldArpStrategy=false; + brokenPortaLegato=false; + brokenFMOff=false; + preNoteNoEffect=false; + oldDPCM=false; + resetArpPhaseOnNewNote=false; + ceilVolumeScaling=false; + oldAlwaysSetVolume=false; + oldSampleOffset=false; + oldCenterRate=true; +} + +bool DivCompatFlags::areDefaults() { + return (*this==defaultFlags); +} + +#define CHECK_AND_STORE_BOOL(_x) \ + if (_x!=defaultFlags._x) { \ + c.set(#_x,_x); \ + } + +#define CHECK_AND_STORE_UNSIGNED_CHAR(_x) \ + if (_x!=defaultFlags._x) { \ + c.set(#_x,(int)_x); \ + } + +void DivCompatFlags::putData(SafeWriter* w) { + DivConfig c; + size_t blockStartSeek, blockEndSeek; + + CHECK_AND_STORE_BOOL(limitSlides); + CHECK_AND_STORE_UNSIGNED_CHAR(linearPitch); + CHECK_AND_STORE_UNSIGNED_CHAR(pitchSlideSpeed); + CHECK_AND_STORE_UNSIGNED_CHAR(loopModality); + CHECK_AND_STORE_UNSIGNED_CHAR(delayBehavior); + CHECK_AND_STORE_UNSIGNED_CHAR(jumpTreatment); + CHECK_AND_STORE_BOOL(properNoiseLayout); + CHECK_AND_STORE_BOOL(waveDutyIsVol); + CHECK_AND_STORE_BOOL(resetMacroOnPorta); + CHECK_AND_STORE_BOOL(legacyVolumeSlides); + CHECK_AND_STORE_BOOL(compatibleArpeggio); + CHECK_AND_STORE_BOOL(noteOffResetsSlides); + CHECK_AND_STORE_BOOL(targetResetsSlides); + CHECK_AND_STORE_BOOL(arpNonPorta); + CHECK_AND_STORE_BOOL(algMacroBehavior); + CHECK_AND_STORE_BOOL(brokenShortcutSlides); + CHECK_AND_STORE_BOOL(ignoreDuplicateSlides); + CHECK_AND_STORE_BOOL(stopPortaOnNoteOff); + CHECK_AND_STORE_BOOL(continuousVibrato); + CHECK_AND_STORE_BOOL(brokenDACMode); + CHECK_AND_STORE_BOOL(oneTickCut); + CHECK_AND_STORE_BOOL(newInsTriggersInPorta); + CHECK_AND_STORE_BOOL(arp0Reset); + CHECK_AND_STORE_BOOL(brokenSpeedSel); + CHECK_AND_STORE_BOOL(noSlidesOnFirstTick); + CHECK_AND_STORE_BOOL(rowResetsArpPos); + CHECK_AND_STORE_BOOL(ignoreJumpAtEnd); + CHECK_AND_STORE_BOOL(buggyPortaAfterSlide); + CHECK_AND_STORE_BOOL(gbInsAffectsEnvelope); + CHECK_AND_STORE_BOOL(sharedExtStat); + CHECK_AND_STORE_BOOL(ignoreDACModeOutsideIntendedChannel); + CHECK_AND_STORE_BOOL(e1e2AlsoTakePriority); + CHECK_AND_STORE_BOOL(newSegaPCM); + CHECK_AND_STORE_BOOL(fbPortaPause); + CHECK_AND_STORE_BOOL(snDutyReset); + CHECK_AND_STORE_BOOL(pitchMacroIsLinear); + CHECK_AND_STORE_BOOL(oldOctaveBoundary); + CHECK_AND_STORE_BOOL(noOPN2Vol); + CHECK_AND_STORE_BOOL(newVolumeScaling); + CHECK_AND_STORE_BOOL(volMacroLinger); + CHECK_AND_STORE_BOOL(brokenOutVol); + CHECK_AND_STORE_BOOL(brokenOutVol2); + CHECK_AND_STORE_BOOL(e1e2StopOnSameNote); + CHECK_AND_STORE_BOOL(brokenPortaArp); + CHECK_AND_STORE_BOOL(snNoLowPeriods); + CHECK_AND_STORE_BOOL(disableSampleMacro); + CHECK_AND_STORE_BOOL(oldArpStrategy); + CHECK_AND_STORE_BOOL(brokenPortaLegato); + CHECK_AND_STORE_BOOL(brokenFMOff); + CHECK_AND_STORE_BOOL(preNoteNoEffect); + CHECK_AND_STORE_BOOL(oldDPCM); + CHECK_AND_STORE_BOOL(resetArpPhaseOnNewNote); + CHECK_AND_STORE_BOOL(ceilVolumeScaling); + CHECK_AND_STORE_BOOL(oldAlwaysSetVolume); + CHECK_AND_STORE_BOOL(oldSampleOffset); + CHECK_AND_STORE_BOOL(oldCenterRate); + + String data=c.toString(); + w->write("CFLG",4); + blockStartSeek=w->tell(); + w->writeI(0); + + w->writeString(data,false); + + blockEndSeek=w->tell(); + w->seek(blockStartSeek,SEEK_SET); + w->writeI(blockEndSeek-blockStartSeek-4); + w->seek(0,SEEK_END); +} diff --git a/src/engine/song.h b/src/engine/song.h index d34f7bc9d..35cf30c6f 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -163,6 +163,7 @@ enum DivEffectType: unsigned short { struct DivGroovePattern { unsigned char val[16]; unsigned char len; + void putData(SafeWriter* w); DivGroovePattern(): len(1) { memset(val,6,16); @@ -229,6 +230,11 @@ struct DivSubSong { */ void calcTimestamps(int chans, std::vector& grooves, int jumpTreatment, int ignoreJumpAtEnd, int brokenSpeedSel, int delayBehavior, int firstPat=0); + /** + * write sub-song block to a SafeWriter. + */ + void putData(SafeWriter* w, int chans); + void clearData(); void removeUnusedPatterns(); void optimizePatterns(); @@ -269,42 +275,7 @@ struct DivEffectStorage { storageLen(0) {} }; -struct DivSong { - unsigned short version; - bool isDMF; - - // system - int chans; - DivSystem system[DIV_MAX_CHIPS]; - unsigned short systemChans[DIV_MAX_CHIPS]; - unsigned char systemLen; - float systemVol[DIV_MAX_CHIPS]; - float systemPan[DIV_MAX_CHIPS]; - float systemPanFR[DIV_MAX_CHIPS]; - DivConfig systemFlags[DIV_MAX_CHIPS]; - - // song information - String name, author, systemName; - - // legacy song information - // those will be stored in .fur and mapped to VGM as: - // category -> game name - // writer -> ripper - // createdDate -> year - String carrier, composer, vendor, category, writer, arranger, copyright, manGroup, manInfo, createdDate, revisionDate; - - // more VGM specific stuff - String nameJ, authorJ, categoryJ, systemNameJ; - - // other things - String notes; - - // module details - int insLen, waveLen, sampleLen; - float masterVol; - float tuning; - - // compatibility flags +struct DivCompatFlags { bool limitSlides; // linear pitch unsigned char linearPitch; @@ -364,9 +335,7 @@ struct DivSong { bool brokenPortaArp; bool snNoLowPeriods; bool disableSampleMacro; - bool autoSystem; bool oldArpStrategy; - bool patchbayAuto; bool brokenPortaLegato; bool brokenFMOff; bool preNoteNoEffect; @@ -375,9 +344,67 @@ struct DivSong { bool ceilVolumeScaling; bool oldAlwaysSetVolume; bool oldSampleOffset; - // TODO: this flag is not saved to the file yet. + // new flags as of dev240 bool oldCenterRate; + void setDefaults(); + bool areDefaults(); + void putData(SafeWriter* w); + + bool operator==(const DivCompatFlags& other) { + return (memcmp(this,&other,sizeof(DivCompatFlags))==0); + } + bool operator!=(const DivCompatFlags& other) { + return (memcmp(this,&other,sizeof(DivCompatFlags))!=0); + } + + DivCompatFlags() { + memset(this,0,sizeof(DivCompatFlags)); + setDefaults(); + } +}; + +struct DivSong { + unsigned short version; + bool isDMF; + + // system + int chans; + DivSystem system[DIV_MAX_CHIPS]; + unsigned short systemChans[DIV_MAX_CHIPS]; + unsigned char systemLen; + float systemVol[DIV_MAX_CHIPS]; + float systemPan[DIV_MAX_CHIPS]; + float systemPanFR[DIV_MAX_CHIPS]; + DivConfig systemFlags[DIV_MAX_CHIPS]; + + // song information + String name, author, systemName; + + // legacy song information + // those will be stored in .fur and mapped to VGM as: + // category -> game name + // writer -> ripper + // createdDate -> year + String carrier, composer, vendor, category, writer, arranger, copyright, manGroup, manInfo, createdDate, revisionDate; + + // more VGM specific stuff + String nameJ, authorJ, categoryJ, systemNameJ; + + // other things + String notes; + + // module details + int insLen, waveLen, sampleLen; + float masterVol; + float tuning; + + bool autoSystem; + bool patchbayAuto; + + // compatibility flags + DivCompatFlags compatFlags; + std::vector ins; std::vector wave; std::vector sample; @@ -481,64 +508,8 @@ struct DivSong { sampleLen(0), masterVol(1.0f), tuning(440.0f), - limitSlides(false), - linearPitch(1), - pitchSlideSpeed(4), - loopModality(2), - delayBehavior(2), - jumpTreatment(0), - properNoiseLayout(true), - waveDutyIsVol(false), - resetMacroOnPorta(false), - legacyVolumeSlides(false), - compatibleArpeggio(false), - noteOffResetsSlides(true), - targetResetsSlides(true), - arpNonPorta(false), - algMacroBehavior(false), - brokenShortcutSlides(false), - ignoreDuplicateSlides(false), - stopPortaOnNoteOff(false), - continuousVibrato(false), - brokenDACMode(false), - oneTickCut(false), - newInsTriggersInPorta(true), - arp0Reset(true), - brokenSpeedSel(false), - noSlidesOnFirstTick(false), - rowResetsArpPos(false), - ignoreJumpAtEnd(false), - buggyPortaAfterSlide(false), - gbInsAffectsEnvelope(true), - sharedExtStat(true), - ignoreDACModeOutsideIntendedChannel(false), - e1e2AlsoTakePriority(false), - newSegaPCM(true), - fbPortaPause(false), - snDutyReset(false), - pitchMacroIsLinear(true), - oldOctaveBoundary(false), - noOPN2Vol(false), - newVolumeScaling(true), - volMacroLinger(true), - brokenOutVol(false), - brokenOutVol2(false), - e1e2StopOnSameNote(false), - brokenPortaArp(false), - snNoLowPeriods(false), - disableSampleMacro(false), autoSystem(true), - oldArpStrategy(false), - patchbayAuto(true), - brokenPortaLegato(false), - brokenFMOff(false), - preNoteNoEffect(false), - oldDPCM(false), - resetArpPhaseOnNewNote(false), - ceilVolumeScaling(false), - oldAlwaysSetVolume(false), - oldSampleOffset(false), - oldCenterRate(true) { + patchbayAuto(true) { memset(dispatchFirstChan,0,DIV_MAX_CHANS*sizeof(int)); memset(dispatchChanOfChan,0,DIV_MAX_CHANS*sizeof(int)); memset(dispatchOfChan,0,DIV_MAX_CHANS*sizeof(int)); diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 6b59a7e86..9cdeb9767 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -2736,7 +2736,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p countDown--; break; } - if (song.loopModality!=2) countDown=0; + if (song.compatFlags.loopModality!=2) countDown=0; if (countDown>0 && !beenOneLoopAlready) { loopTickSong++; diff --git a/src/gui/compatFlags.cpp b/src/gui/compatFlags.cpp index 6a1573d21..994a780b3 100644 --- a/src/gui/compatFlags.cpp +++ b/src/gui/compatFlags.cpp @@ -32,134 +32,134 @@ void FurnaceGUI::drawCompatFlags() { ImGui::TextWrapped(_("these flags are designed to provide better DefleMask/older Furnace compatibility.\nit is recommended to disable most of these unless you rely on specific quirks.")); if (ImGui::BeginTabBar("settingsTab")) { if (ImGui::BeginTabItem(_("DefleMask"))) { - if (ImGui::Checkbox(_("Limit slide range"),&e->song.limitSlides)) { + if (ImGui::Checkbox(_("Limit slide range"),&e->song.compatFlags.limitSlides)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, slides are limited to a compatible range.\nmay cause problems with slides in negative octaves.")); } - if (InvCheckbox(_("Compatible noise layout on NES and PC Engine"),&e->song.properNoiseLayout)) { + if (InvCheckbox(_("Compatible noise layout on NES and PC Engine"),&e->song.compatFlags.properNoiseLayout)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("use a rather unusual compatible noise frequency layout.\nremoves some noise frequencies on PC Engine.")); } - if (ImGui::Checkbox(_("Game Boy instrument duty is wave volume"),&e->song.waveDutyIsVol)) { + if (ImGui::Checkbox(_("Game Boy instrument duty is wave volume"),&e->song.compatFlags.waveDutyIsVol)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("if enabled, an instrument with duty macro in the wave channel will be mapped to wavetable volume.")); } - if (ImGui::Checkbox(_("Restart macro on portamento"),&e->song.resetMacroOnPorta)) { + if (ImGui::Checkbox(_("Restart macro on portamento"),&e->song.compatFlags.resetMacroOnPorta)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, a portamento effect will reset the channel's macro if used in combination with a note.")); } - if (ImGui::Checkbox(_("Legacy volume slides"),&e->song.legacyVolumeSlides)) { + if (ImGui::Checkbox(_("Legacy volume slides"),&e->song.compatFlags.legacyVolumeSlides)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("simulate glitchy volume slide behavior by silently overflowing the volume when the slide goes below 0.")); } - if (ImGui::Checkbox(_("Compatible arpeggio"),&e->song.compatibleArpeggio)) { + if (ImGui::Checkbox(_("Compatible arpeggio"),&e->song.compatFlags.compatibleArpeggio)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("delay arpeggio by one tick on every new note.")); } - if (ImGui::Checkbox(_("Disable DAC when sample ends"),&e->song.brokenDACMode)) { + if (ImGui::Checkbox(_("Disable DAC when sample ends"),&e->song.compatFlags.brokenDACMode)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, the DAC in YM2612 will be disabled if there isn't any sample playing.")); } - if (ImGui::Checkbox(_("Broken speed alternation"),&e->song.brokenSpeedSel)) { + if (ImGui::Checkbox(_("Broken speed alternation"),&e->song.compatFlags.brokenSpeedSel)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("determines next speed based on whether the row is odd/even instead of alternating between speeds.")); } - if (ImGui::Checkbox(_("Ignore duplicate slide effects"),&e->song.ignoreDuplicateSlides)) { + if (ImGui::Checkbox(_("Ignore duplicate slide effects"),&e->song.compatFlags.ignoreDuplicateSlides)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("if this is on, only the first slide of a row in a channel will be considered.")); } - if (ImGui::Checkbox(_("Ignore 0Dxx on the last order"),&e->song.ignoreJumpAtEnd)) { + if (ImGui::Checkbox(_("Ignore 0Dxx on the last order"),&e->song.compatFlags.ignoreJumpAtEnd)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("if this is on, a jump to next row effect will not take place when it is on the last order of a song.")); } - if (ImGui::Checkbox(_("Buggy portamento after pitch slide"),&e->song.buggyPortaAfterSlide)) { + if (ImGui::Checkbox(_("Buggy portamento after pitch slide"),&e->song.compatFlags.buggyPortaAfterSlide)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("simulates a bug in where portamento does not work after sliding.")); } - if (ImGui::Checkbox(_("FM pitch slide octave boundary odd behavior"),&e->song.fbPortaPause)) { + if (ImGui::Checkbox(_("FM pitch slide octave boundary odd behavior"),&e->song.compatFlags.fbPortaPause)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("if this is on, a pitch slide that crosses the octave boundary will stop for one tick and then continue from the nearest octave boundary.\nfor .dmf compatibility.")); } - if (InvCheckbox(_("Don't apply Game Boy envelope on note-less instrument change"),&e->song.gbInsAffectsEnvelope)) { + if (InvCheckbox(_("Don't apply Game Boy envelope on note-less instrument change"),&e->song.compatFlags.gbInsAffectsEnvelope)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("if this is on, an instrument change will not affect the envelope.")); } - if (ImGui::Checkbox(_("Ignore DAC mode change outside of intended channel in ExtCh mode"),&e->song.ignoreDACModeOutsideIntendedChannel)) { + if (ImGui::Checkbox(_("Ignore DAC mode change outside of intended channel in ExtCh mode"),&e->song.compatFlags.ignoreDACModeOutsideIntendedChannel)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("if this is on, 17xx has no effect on the operator channels in YM2612.")); } - if (ImGui::Checkbox(_("E1xy/E2xy also take priority over slide stops"),&e->song.e1e2AlsoTakePriority)) { + if (ImGui::Checkbox(_("E1xy/E2xy also take priority over slide stops"),&e->song.compatFlags.e1e2AlsoTakePriority)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("does this make any sense by now?")); } - if (ImGui::Checkbox(_("E1xy/E2xy stop when repeating the same note"),&e->song.e1e2StopOnSameNote)) { + if (ImGui::Checkbox(_("E1xy/E2xy stop when repeating the same note"),&e->song.compatFlags.e1e2StopOnSameNote)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("ugh, if only this wasn't a thing...")); } - if (ImGui::Checkbox(_("SN76489 duty macro always resets phase"),&e->song.snDutyReset)) { + if (ImGui::Checkbox(_("SN76489 duty macro always resets phase"),&e->song.compatFlags.snDutyReset)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, duty macro will always reset phase, even if its value hasn't changed.")); } - if (InvCheckbox(_("Broken volume scaling strategy"),&e->song.newVolumeScaling)) { + if (InvCheckbox(_("Broken volume scaling strategy"),&e->song.compatFlags.newVolumeScaling)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled:\n- log scaling: multiply\n- linear scaling: subtract\nwhen disabled:\n- log scaling: subtract\n- linear scaling: multiply")); } - if (InvCheckbox(_("Don't persist volume macro after it finishes"),&e->song.volMacroLinger)) { + if (InvCheckbox(_("Don't persist volume macro after it finishes"),&e->song.compatFlags.volMacroLinger)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, a value in the volume column that happens after the volume macro is done will disregard the macro.")); } - if (ImGui::Checkbox(_("Broken output volume on instrument change"),&e->song.brokenOutVol)) { + if (ImGui::Checkbox(_("Broken output volume on instrument change"),&e->song.compatFlags.brokenOutVol)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("if enabled, no checks for the presence of a volume macro will be made.\nthis will cause the last macro value to linger unless a value in the volume column is present.")); } - if (ImGui::Checkbox(_("Broken output volume - Episode 2 (PLEASE KEEP ME DISABLED)"),&e->song.brokenOutVol2)) { + if (ImGui::Checkbox(_("Broken output volume - Episode 2 (PLEASE KEEP ME DISABLED)"),&e->song.compatFlags.brokenOutVol2)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("these compatibility flags are getting SO damn ridiculous and out of control.\nas you may have guessed, this one exists due to yet ANOTHER DefleMask-specific behavior.\nplease keep this off at all costs, because I will not support it when ROM export comes.\noh, and don't start an argument out of it. Furnace isn't a DefleMask replacement, and no,\nI am not trying to make it look like one with all these flags.\n\noh, and what about the other flags that don't have to do with DefleMask?\nthose are for .mod import, future FamiTracker import and personal taste!\n\nend of rant")); } - if (ImGui::Checkbox(_("Treat SN76489 periods under 8 as 1"),&e->song.snNoLowPeriods)) { + if (ImGui::Checkbox(_("Treat SN76489 periods under 8 as 1"),&e->song.compatFlags.snNoLowPeriods)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -168,115 +168,115 @@ void FurnaceGUI::drawCompatFlags() { ImGui::EndTabItem(); } if (ImGui::BeginTabItem(_("Old Furnace"))) { - if (ImGui::Checkbox(_("Arpeggio inhibits non-porta slides"),&e->song.arpNonPorta)) { + if (ImGui::Checkbox(_("Arpeggio inhibits non-porta slides"),&e->song.compatFlags.arpNonPorta)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.5.5")); } - if (ImGui::Checkbox(_("Wack FM algorithm macro"),&e->song.algMacroBehavior)) { + if (ImGui::Checkbox(_("Wack FM algorithm macro"),&e->song.compatFlags.algMacroBehavior)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.5.5")); } - if (ImGui::Checkbox(_("Broken shortcut slides (E1xy/E2xy)"),&e->song.brokenShortcutSlides)) { + if (ImGui::Checkbox(_("Broken shortcut slides (E1xy/E2xy)"),&e->song.compatFlags.brokenShortcutSlides)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.5.7")); } - if (ImGui::Checkbox(_("Stop portamento on note off"),&e->song.stopPortaOnNoteOff)) { + if (ImGui::Checkbox(_("Stop portamento on note off"),&e->song.compatFlags.stopPortaOnNoteOff)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre1")); } - if (InvCheckbox(_("Don't allow instrument change during slides"),&e->song.newInsTriggersInPorta)) { + if (InvCheckbox(_("Don't allow instrument change during slides"),&e->song.compatFlags.newInsTriggersInPorta)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre1")); } - if (InvCheckbox(_("Don't reset note to base on arpeggio stop"),&e->song.arp0Reset)) { + if (InvCheckbox(_("Don't reset note to base on arpeggio stop"),&e->song.compatFlags.arp0Reset)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre1")); } - if (InvCheckbox(_("ExtCh channel status is not shared among operators"),&e->song.sharedExtStat)) { + if (InvCheckbox(_("ExtCh channel status is not shared among operators"),&e->song.compatFlags.sharedExtStat)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre1")); } - if (InvCheckbox(_("Disable new SegaPCM features (macros and better panning)"),&e->song.newSegaPCM)) { + if (InvCheckbox(_("Disable new SegaPCM features (macros and better panning)"),&e->song.compatFlags.newSegaPCM)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre1")); } - if (ImGui::Checkbox(_("Old FM octave boundary behavior"),&e->song.oldOctaveBoundary)) { + if (ImGui::Checkbox(_("Old FM octave boundary behavior"),&e->song.compatFlags.oldOctaveBoundary)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre1")); } - if (ImGui::Checkbox(_("Disable OPN2 DAC volume control"),&e->song.noOPN2Vol)) { + if (ImGui::Checkbox(_("Disable OPN2 DAC volume control"),&e->song.compatFlags.noOPN2Vol)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre1")); } - if (ImGui::Checkbox(_("Broken initial position of portamento after arpeggio"),&e->song.brokenPortaArp)) { + if (ImGui::Checkbox(_("Broken initial position of portamento after arpeggio"),&e->song.compatFlags.brokenPortaArp)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre1.5")); } - if (ImGui::Checkbox(_("Disable new sample features"),&e->song.disableSampleMacro)) { + if (ImGui::Checkbox(_("Disable new sample features"),&e->song.compatFlags.disableSampleMacro)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre2")); } - if (ImGui::Checkbox(_("Old arpeggio macro + pitch slide strategy"),&e->song.oldArpStrategy)) { + if (ImGui::Checkbox(_("Old arpeggio macro + pitch slide strategy"),&e->song.compatFlags.oldArpStrategy)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre2")); } - if (ImGui::Checkbox(_("Broken portamento during legato"),&e->song.brokenPortaLegato)) { + if (ImGui::Checkbox(_("Broken portamento during legato"),&e->song.compatFlags.brokenPortaLegato)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre4")); } - if (ImGui::Checkbox(_("Broken macros in some FM chips after note off"),&e->song.brokenFMOff)) { + if (ImGui::Checkbox(_("Broken macros in some FM chips after note off"),&e->song.compatFlags.brokenFMOff)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre5")); } - if (ImGui::Checkbox(_("Pre-note does not take effects into consideration"),&e->song.preNoteNoEffect)) { + if (ImGui::Checkbox(_("Pre-note does not take effects into consideration"),&e->song.compatFlags.preNoteNoEffect)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6pre9")); } - if (ImGui::Checkbox(_("Disable new NES DPCM features"),&e->song.oldDPCM)) { + if (ImGui::Checkbox(_("Disable new NES DPCM features"),&e->song.compatFlags.oldDPCM)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6.1")); } - if (ImGui::Checkbox(_("Legacy technical ALWAYS_SET_VOLUME behavior"),&e->song.oldAlwaysSetVolume)) { + if (ImGui::Checkbox(_("Legacy technical ALWAYS_SET_VOLUME behavior"),&e->song.compatFlags.oldAlwaysSetVolume)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("behavior changed in 0.6.1\nthis flag will be removed if I find out that none of the songs break after disabling it.")); } - if (ImGui::Checkbox(_("Old sample offset effect"),&e->song.oldSampleOffset)) { + if (ImGui::Checkbox(_("Old sample offset effect"),&e->song.compatFlags.oldSampleOffset)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -285,13 +285,13 @@ void FurnaceGUI::drawCompatFlags() { ImGui::EndTabItem(); } if (ImGui::BeginTabItem(_(".mod import"))) { - if (ImGui::Checkbox(_("Don't slide on the first tick of a row"),&e->song.noSlidesOnFirstTick)) { + if (ImGui::Checkbox(_("Don't slide on the first tick of a row"),&e->song.compatFlags.noSlidesOnFirstTick)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("simulates ProTracker's behavior of not applying volume/pitch slides on the first tick of a row.")); } - if (ImGui::Checkbox(_("Reset arpeggio position on row change"),&e->song.rowResetsArpPos)) { + if (ImGui::Checkbox(_("Reset arpeggio position on row change"),&e->song.compatFlags.rowResetsArpPos)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -302,15 +302,15 @@ void FurnaceGUI::drawCompatFlags() { if (ImGui::BeginTabItem(_("Pitch/Playback"))) { ImGui::Text(_("Pitch linearity:")); ImGui::Indent(); - if (ImGui::RadioButton(_("None"),!e->song.linearPitch)) { - e->song.linearPitch=0; + if (ImGui::RadioButton(_("None"),!e->song.compatFlags.linearPitch)) { + e->song.compatFlags.linearPitch=0; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("like ProTracker/FamiTracker")); } - if (ImGui::RadioButton(_("Full"),e->song.linearPitch)) { - e->song.linearPitch=1; + if (ImGui::RadioButton(_("Full"),e->song.compatFlags.linearPitch)) { + e->song.compatFlags.linearPitch=1; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -318,34 +318,34 @@ void FurnaceGUI::drawCompatFlags() { } ImGui::Unindent(); - if (e->song.linearPitch) { + if (e->song.compatFlags.linearPitch) { ImGui::SameLine(); ImGui::SetNextItemWidth(120.0f*dpiScale); - if (ImGui::InputScalar(_("Pitch slide speed multiplier"),ImGuiDataType_U8,&e->song.pitchSlideSpeed,&_ONE,&_ONE)) { - if (e->song.pitchSlideSpeed<1) e->song.pitchSlideSpeed=1; - if (e->song.pitchSlideSpeed>64) e->song.pitchSlideSpeed=64; + if (ImGui::InputScalar(_("Pitch slide speed multiplier"),ImGuiDataType_U8,&e->song.compatFlags.pitchSlideSpeed,&_ONE,&_ONE)) { + if (e->song.compatFlags.pitchSlideSpeed<1) e->song.compatFlags.pitchSlideSpeed=1; + if (e->song.compatFlags.pitchSlideSpeed>64) e->song.compatFlags.pitchSlideSpeed=64; MARK_MODIFIED; } } ImGui::Text(_("Loop modality:")); ImGui::Indent(); - if (ImGui::RadioButton(_("Reset channels"),e->song.loopModality==0)) { - e->song.loopModality=0; + if (ImGui::RadioButton(_("Reset channels"),e->song.compatFlags.loopModality==0)) { + e->song.compatFlags.loopModality=0; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("select to reset channels on loop. may trigger a voltage click on every loop!")); } - if (ImGui::RadioButton(_("Soft reset channels"),e->song.loopModality==1)) { - e->song.loopModality=1; + if (ImGui::RadioButton(_("Soft reset channels"),e->song.compatFlags.loopModality==1)) { + e->song.compatFlags.loopModality=1; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("select to turn channels off on loop.")); } - if (ImGui::RadioButton(_("Do nothing"),e->song.loopModality==2)) { - e->song.loopModality=2; + if (ImGui::RadioButton(_("Do nothing"),e->song.compatFlags.loopModality==2)) { + e->song.compatFlags.loopModality=2; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -355,22 +355,22 @@ void FurnaceGUI::drawCompatFlags() { ImGui::Text(_("Cut/delay effect policy:")); ImGui::Indent(); - if (ImGui::RadioButton(_("Strict"),e->song.delayBehavior==0)) { - e->song.delayBehavior=0; + if (ImGui::RadioButton(_("Strict"),e->song.compatFlags.delayBehavior==0)) { + e->song.compatFlags.delayBehavior=0; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("only when time is less than speed (like DefleMask/ProTracker)")); } - if (ImGui::RadioButton(_("Strict (old)"),e->song.delayBehavior==1)) { - e->song.delayBehavior=1; + if (ImGui::RadioButton(_("Strict (old)"),e->song.compatFlags.delayBehavior==1)) { + e->song.compatFlags.delayBehavior=1; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("only when time is less than or equal to speed (original buggy behavior)")); } - if (ImGui::RadioButton(_("Lax"),e->song.delayBehavior==2)) { - e->song.delayBehavior=2; + if (ImGui::RadioButton(_("Lax"),e->song.compatFlags.delayBehavior==2)) { + e->song.compatFlags.delayBehavior=2; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -380,22 +380,22 @@ void FurnaceGUI::drawCompatFlags() { ImGui::Text(_("Simultaneous jump (0B+0D) treatment:")); ImGui::Indent(); - if (ImGui::RadioButton(_("Normal"),e->song.jumpTreatment==0)) { - e->song.jumpTreatment=0; + if (ImGui::RadioButton(_("Normal"),e->song.compatFlags.jumpTreatment==0)) { + e->song.compatFlags.jumpTreatment=0; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("accept 0B+0D to jump to a specific row of an order")); } - if (ImGui::RadioButton(_("Old Furnace"),e->song.jumpTreatment==1)) { - e->song.jumpTreatment=1; + if (ImGui::RadioButton(_("Old Furnace"),e->song.compatFlags.jumpTreatment==1)) { + e->song.compatFlags.jumpTreatment=1; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("only accept the first jump effect")); } - if (ImGui::RadioButton(_("DefleMask"),e->song.jumpTreatment==2)) { - e->song.jumpTreatment=2; + if (ImGui::RadioButton(_("DefleMask"),e->song.compatFlags.jumpTreatment==2)) { + e->song.compatFlags.jumpTreatment=2; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -405,7 +405,7 @@ void FurnaceGUI::drawCompatFlags() { ImGui::EndTabItem(); } if (ImGui::BeginTabItem(_("Other"))) { - if (ImGui::Checkbox(_("Auto-insert one tick gap between notes"),&e->song.oneTickCut)) { + if (ImGui::Checkbox(_("Auto-insert one tick gap between notes"),&e->song.compatFlags.oneTickCut)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -414,37 +414,37 @@ void FurnaceGUI::drawCompatFlags() { ImGui::Separator(); - if (InvCheckbox(_("Don't reset slides after note off"),&e->song.noteOffResetsSlides)) { + if (InvCheckbox(_("Don't reset slides after note off"),&e->song.compatFlags.noteOffResetsSlides)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, note off will not reset the channel's slide effect.")); } - if (InvCheckbox(_("Don't reset portamento after reaching target"),&e->song.targetResetsSlides)) { + if (InvCheckbox(_("Don't reset portamento after reaching target"),&e->song.compatFlags.targetResetsSlides)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, the slide effect will not be disabled after it reaches its target.")); } - if (ImGui::Checkbox(_("Continuous vibrato"),&e->song.continuousVibrato)) { + if (ImGui::Checkbox(_("Continuous vibrato"),&e->song.compatFlags.continuousVibrato)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, vibrato phase/position will not be reset on a new note.")); } - if (InvCheckbox(_("Pitch macro is not linear"),&e->song.pitchMacroIsLinear)) { + if (InvCheckbox(_("Pitch macro is not linear"),&e->song.compatFlags.pitchMacroIsLinear)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, the pitch macro of an instrument is in frequency/period space.")); } - if (ImGui::Checkbox(_("Reset arpeggio effect position on new note"),&e->song.resetArpPhaseOnNewNote)) { + if (ImGui::Checkbox(_("Reset arpeggio effect position on new note"),&e->song.compatFlags.resetArpPhaseOnNewNote)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(_("when enabled, arpeggio effect (00xy) position is reset on a new note.")); } - if (ImGui::Checkbox(_("Volume scaling rounds up"),&e->song.ceilVolumeScaling)) { + if (ImGui::Checkbox(_("Volume scaling rounds up"),&e->song.compatFlags.ceilVolumeScaling)) { MARK_MODIFIED; } if (ImGui::IsItemHovered()) { diff --git a/src/gui/exportOptions.cpp b/src/gui/exportOptions.cpp index 2af9d1f47..2c1918cac 100644 --- a/src/gui/exportOptions.cpp +++ b/src/gui/exportOptions.cpp @@ -266,7 +266,7 @@ void FurnaceGUI::drawExportVGM(bool onWindow) { ImGui::EndCombo(); } ImGui::Checkbox(_("loop"),&vgmExportLoop); - if (vgmExportLoop && e->song.loopModality==2) { + if (vgmExportLoop && e->song.compatFlags.loopModality==2) { ImGui::Text(_("loop trail:")); ImGui::Indent(); if (ImGui::RadioButton(_("auto-detect"),vgmExportTrailingTicks==-1)) { diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 5dca05399..f22a1dbb2 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -3448,10 +3448,10 @@ void FurnaceGUI::insTabSample(DivInstrument* ins) { const char* sampleTabName=_("Sample"); if (ins->type==DIV_INS_NES) sampleTabName=_("DPCM"); if (ImGui::BeginTabItem(sampleTabName)) { - if (ins->type==DIV_INS_NES && e->song.oldDPCM) { + if (ins->type==DIV_INS_NES && e->song.compatFlags.oldDPCM) { ImGui::Text(_("new DPCM features disabled (compatibility)!")); if (ImGui::Button(_("click here to enable them."))) { - e->song.oldDPCM=false; + e->song.compatFlags.oldDPCM=false; MARK_MODIFIED; } ImGui::EndTabItem(); @@ -4694,7 +4694,7 @@ void FurnaceGUI::insTabFM(DivInstrument* ins) { op.egt=egtOn; } if (egtOn) { - pushWarningColor(susOn && !e->song.linearPitch); + pushWarningColor(susOn && !e->song.compatFlags.linearPitch); if (ImGui::Checkbox(_("Pitch control"),&susOn)) { PARAMETER op.sus=susOn; // HACK: reset zoom and scroll in fixed pitch macros so that they draw correctly @@ -4703,7 +4703,7 @@ void FurnaceGUI::insTabFM(DivInstrument* ins) { } popWarningColor(); if (ImGui::IsItemHovered()) { - if (susOn && !e->song.linearPitch) { + if (susOn && !e->song.compatFlags.linearPitch) { ImGui::SetTooltip(_("only works on linear pitch! go to Compatibility Flags > Pitch/Playback and set Pitch linearity to Full.")); } else { ImGui::SetTooltip(_("use op's arpeggio and pitch macros control instead of block/f-num macros")); @@ -5470,7 +5470,7 @@ void FurnaceGUI::insTabFM(DivInstrument* ins) { P(CWSliderScalar("##FINE",ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN,tempID)); rightClickable } else { bool susOn=op.sus; - pushWarningColor(susOn && !e->song.linearPitch); + pushWarningColor(susOn && !e->song.compatFlags.linearPitch); if (ImGui::Checkbox(_("Pitch control"),&susOn)) { PARAMETER op.sus=susOn; // HACK: reset zoom and scroll in fixed pitch macros so that they draw correctly @@ -5479,7 +5479,7 @@ void FurnaceGUI::insTabFM(DivInstrument* ins) { } popWarningColor(); if (ImGui::IsItemHovered()) { - if (susOn && !e->song.linearPitch) { + if (susOn && !e->song.compatFlags.linearPitch) { ImGui::SetTooltip(_("only works on linear pitch! go to Compatibility Flags > Pitch/Playback and set Pitch linearity to Full.")); } else { ImGui::SetTooltip(_("use op's arpeggio and pitch macros control instead of block/f-num macros")); @@ -5793,7 +5793,7 @@ void FurnaceGUI::insTabFM(DivInstrument* ins) { bool susOn=op.sus; if (fixedOn) { ImGui::SameLine(); - pushWarningColor(susOn && !e->song.linearPitch); + pushWarningColor(susOn && !e->song.compatFlags.linearPitch); if (ImGui::Checkbox(_("Pitch control"),&susOn)) { PARAMETER op.sus=susOn; // HACK: reset zoom and scroll in fixed pitch macros so that they draw correctly @@ -5802,7 +5802,7 @@ void FurnaceGUI::insTabFM(DivInstrument* ins) { } popWarningColor(); if (ImGui::IsItemHovered()) { - if (susOn && !e->song.linearPitch) { + if (susOn && !e->song.compatFlags.linearPitch) { ImGui::SetTooltip(_("only works on linear pitch! go to Compatibility Flags > Pitch/Playback and set Pitch linearity to Full.")); } else { ImGui::SetTooltip(_("use op's arpeggio and pitch macros control instead of block/f-num macros")); diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index 2dced97a5..69b90c701 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -1322,11 +1322,11 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl if (ImGui::Checkbox(_("Amiga channel volumes (64)"),&amigaVol)) { altered=true; } - pushWarningColor(amigaPitch && e->song.linearPitch); + pushWarningColor(amigaPitch && e->song.compatFlags.linearPitch); if (ImGui::Checkbox(_("Amiga-like pitch (non-linear pitch only)"),&amigaPitch)) { altered=true; } - if (amigaPitch && e->song.linearPitch) { + if (amigaPitch && e->song.compatFlags.linearPitch) { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("pitch linearity is set to linear. this won't do anything!"); }