diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 000000000..3ece4a3e9 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1 @@ + diff --git a/CMakeLists.txt b/CMakeLists.txt index c8c7372c1..d6581775f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -754,7 +754,7 @@ if (WARNINGS_ARE_ERRORS) ) endif() -if (MSVC) +if (WIN32) add_executable(furnace WIN32 ${USED_SOURCES}) elseif(ANDROID AND NOT TERMUX) add_library(furnace SHARED ${USED_SOURCES}) diff --git a/demos/arcade/ToHeart_QoH98_TPower_Asuka120Style.fur b/demos/arcade/ToHeart_QoH98_TPower_Asuka120Style.fur new file mode 100644 index 000000000..ce0c73bad Binary files /dev/null and b/demos/arcade/ToHeart_QoH98_TPower_Asuka120Style.fur differ diff --git a/demos/genesis/Puyopuyo~n_DopplegangerArle-TsuuStyle.fur b/demos/genesis/Puyopuyo~n_DopplegangerArle-TsuuStyle.fur new file mode 100644 index 000000000..53866b5b2 Binary files /dev/null and b/demos/genesis/Puyopuyo~n_DopplegangerArle-TsuuStyle.fur differ diff --git a/demos/misc/Inner Machinations YM2610B.fur b/demos/misc/Inner Machinations YM2610B.fur new file mode 100644 index 000000000..b6e72a593 Binary files /dev/null and b/demos/misc/Inner Machinations YM2610B.fur differ diff --git a/demos/multichip/Sky Chaze Zone 32X.fur b/demos/multichip/Sky Chaze Zone 32X.fur new file mode 100644 index 000000000..3a19b4166 Binary files /dev/null and b/demos/multichip/Sky Chaze Zone 32X.fur differ diff --git a/demos/opl/PhantomBreakerBattleGrounds_ShinjukuStage-OPL3.fur b/demos/opl/PhantomBreakerBattleGrounds_ShinjukuStage-OPL3.fur new file mode 100644 index 000000000..3ba0598e0 Binary files /dev/null and b/demos/opl/PhantomBreakerBattleGrounds_ShinjukuStage-OPL3.fur differ diff --git a/demos/opl/TeamInnocent-BGM4-OPL3Plus.fur b/demos/opl/TeamInnocent-BGM4-OPL3Plus.fur new file mode 100644 index 000000000..9043c2635 Binary files /dev/null and b/demos/opl/TeamInnocent-BGM4-OPL3Plus.fur differ diff --git a/demos/snes/tetristheme.fur b/demos/snes/tetristheme.fur new file mode 100644 index 000000000..e7ab8578c Binary files /dev/null and b/demos/snes/tetristheme.fur differ diff --git a/demos/x16/Melody of Certain Feelings.fur b/demos/x16/Melody of Certain Feelings.fur new file mode 100644 index 000000000..eacec7a9a Binary files /dev/null and b/demos/x16/Melody of Certain Feelings.fur differ diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 4a2a4b59f..be2ac933c 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -337,6 +337,7 @@ void DivPlatformAY8910::tick(bool sysTick) { chan[i].dac.rate=((double)rate*((sunsoft||clockSel)?8.0:16.0))/(double)(MAX(1,off*chan[i].freq)); if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate); } + if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].keyOn) { //rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63))); diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 85eca7512..fb2584c98 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -270,7 +270,7 @@ void DivPlatformAY8930::tick(bool sysTick) { if (chan[i].std.pitch.had) { if (chan[i].std.pitch.mode) { chan[i].pitch2+=chan[i].std.pitch.val; - CLAMP_VAR(chan[i].pitch2,-32768,32767); + CLAMP_VAR(chan[i].pitch2,-65535,65535); } else { chan[i].pitch2=chan[i].std.pitch.val; } @@ -336,6 +336,7 @@ void DivPlatformAY8930::tick(bool sysTick) { chan[i].dac.rate=((double)chipClock*4.0)/(double)(MAX(1,off*chan[i].freq)); if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate); } + if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].keyOn) { if (!chan[i].nextPSGMode.dac) { diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index bdee28a41..6e6c317c9 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -284,14 +284,14 @@ void DivPlatformGB::tick(bool sysTick) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (i==3) { // noise - int ntPos=chan[i].baseFreq; + int ntPos=chan[i].baseFreq+chan[i].pitch2; if (ntPos<0) ntPos=0; if (ntPos>255) ntPos=255; chan[i].freq=noiseTable[ntPos]; } else { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER); if (chan[i].freq>2047) chan[i].freq=2047; - if (chan[i].freq<0) chan[i].freq=0; + if (chan[i].freq<1) chan[i].freq=1; } if (chan[i].keyOn) { if (i==2) { // wave diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index 3af55a0d6..435384c46 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -278,6 +278,7 @@ void DivPlatformNES::tick(bool sysTick) { ntPos+=chan[i].arpOff; } } + ntPos+=chan[i].pitch2; if (parent->song.properNoiseLayout) { chan[i].freq=15-(ntPos&15); } else { diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index e8ad6db41..3efbd7c8c 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -242,6 +242,7 @@ void DivPlatformPCE::tick(bool sysTick) { chan[i].dacRate=((double)chipClock/2)/MAX(1,off*chan[i].freq); if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dacRate); } + if (chan[i].freq<1) chan[i].freq=1; if (chan[i].freq>4095) chan[i].freq=4095; chWrite(i,0x02,chan[i].freq&0xff); chWrite(i,0x03,chan[i].freq>>8); diff --git a/src/engine/platform/sound/ay8910.cpp b/src/engine/platform/sound/ay8910.cpp index c7be503e7..530b03d0c 100644 --- a/src/engine/platform/sound/ay8910.cpp +++ b/src/engine/platform/sound/ay8910.cpp @@ -1064,12 +1064,11 @@ void ay8910_device::sound_stream_update(short** outputs, int outLen) tone = &m_tone[chan]; const int period = std::max(1, tone->period) * (m_step_mul << 1); tone->count += is_expanded_mode() ? 32 : ((m_feature & PSG_HAS_EXPANDED_MODE) ? 1 : 2); - while (tone->count >= period) - { - tone->duty_cycle = (tone->duty_cycle - 1) & 0x1f; - tone->output = is_expanded_mode() ? BIT(duty_cycle[tone_duty(tone)], tone->duty_cycle) : BIT(tone->duty_cycle, 0); - tone->count -= period; - } + if (tone->count>=period) { + tone->duty_cycle = (tone->duty_cycle - (tone->count/period)) & 0x1f; + tone->output = is_expanded_mode() ? BIT(duty_cycle[tone_duty(tone)], tone->duty_cycle) : BIT(tone->duty_cycle, 0); + tone->count = tone->count % period; + } } const int period_noise = (int)(noise_period()) * m_step_mul; diff --git a/src/engine/platform/sound/namco.cpp b/src/engine/platform/sound/namco.cpp index 473a80c6e..ee4c1b16a 100644 --- a/src/engine/platform/sound/namco.cpp +++ b/src/engine/platform/sound/namco.cpp @@ -659,11 +659,13 @@ void namco_audio_device::sound_stream_update(short** outputs, int len) { lmix[i]+=l_noise_data; rmix[i]+=r_noise_data; + voice->last_out=(l_noise_data+r_noise_data)>>1; } else { lmix[i]+=-l_noise_data; rmix[i]+=-r_noise_data; + voice->last_out=-((l_noise_data+r_noise_data)>>1); } if (hold) diff --git a/src/engine/platform/tx81z.cpp b/src/engine/platform/tx81z.cpp index c3f647417..2b119abbe 100644 --- a/src/engine/platform/tx81z.cpp +++ b/src/engine/platform/tx81z.cpp @@ -152,6 +152,14 @@ void DivPlatformTX81Z::tick(bool sysTick) { chan[i].freqChanged=true; } + if (chan[i].std.panL.had) { + chan[i].chVolL=(chan[i].std.panL.val&2)>>1; + chan[i].chVolR=chan[i].std.panL.val&1; + chan[i].freqChanged=true; + + 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 (chan[i].std.phaseReset.had) { if (chan[i].std.phaseReset.val==1 && chan[i].active) { chan[i].keyOn=true; diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index f23cf935c..169537463 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -715,6 +715,17 @@ void DivPlatformYM2608::tick(bool sysTick) { } chan[15].freqChanged=true; } + + if (chan[15].std.pitch.had) { + if (chan[15].std.pitch.mode) { + chan[15].pitch2+=chan[15].std.pitch.val; + CLAMP_VAR(chan[15].pitch2,-65535,65535); + } else { + chan[15].pitch2=chan[15].std.pitch.val; + } + chan[15].freqChanged=true; + } + if (chan[15].std.panL.had) { if (chan[15].pan!=(chan[15].std.panL.val&3)) { chan[15].pan=chan[15].std.panL.val&3; diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 605d767f7..d33a073c6 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -650,6 +650,17 @@ void DivPlatformYM2610::tick(bool sysTick) { } chan[adpcmBChanOffs].freqChanged=true; } + + if (chan[adpcmBChanOffs].std.pitch.had) { + if (chan[adpcmBChanOffs].std.pitch.mode) { + chan[adpcmBChanOffs].pitch2+=chan[adpcmBChanOffs].std.pitch.val; + CLAMP_VAR(chan[adpcmBChanOffs].pitch2,-65535,65535); + } else { + chan[adpcmBChanOffs].pitch2=chan[adpcmBChanOffs].std.pitch.val; + } + chan[adpcmBChanOffs].freqChanged=true; + } + if (chan[adpcmBChanOffs].std.panL.had) { if (chan[adpcmBChanOffs].pan!=(chan[adpcmBChanOffs].std.panL.val&3)) { chan[adpcmBChanOffs].pan=chan[adpcmBChanOffs].std.panL.val&3; diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index 0586d5b71..a8c4d6046 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -717,6 +717,17 @@ void DivPlatformYM2610B::tick(bool sysTick) { } chan[adpcmBChanOffs].freqChanged=true; } + + if (chan[adpcmBChanOffs].std.pitch.had) { + if (chan[adpcmBChanOffs].std.pitch.mode) { + chan[adpcmBChanOffs].pitch2+=chan[adpcmBChanOffs].std.pitch.val; + CLAMP_VAR(chan[adpcmBChanOffs].pitch2,-65535,65535); + } else { + chan[adpcmBChanOffs].pitch2=chan[adpcmBChanOffs].std.pitch.val; + } + chan[adpcmBChanOffs].freqChanged=true; + } + if (chan[adpcmBChanOffs].std.panL.had) { if (chan[adpcmBChanOffs].pan!=(chan[adpcmBChanOffs].std.panL.val&3)) { chan[adpcmBChanOffs].pan=chan[adpcmBChanOffs].std.panL.val&3; diff --git a/src/gui/about.cpp b/src/gui/about.cpp index 95dded953..fd229ecf6 100644 --- a/src/gui/about.cpp +++ b/src/gui/about.cpp @@ -71,6 +71,7 @@ const char* aboutLine[]={ "DeMOSic", "DevEd", "Dippy", + "djtuBIG-MaliceX", "dumbut", "FΛDE", "Forte", @@ -99,6 +100,7 @@ const char* aboutLine[]={ "SuperJet Spade", "SwapXFO", "TakuikaNinja", + "TCORPStudios", "The Blender Fiddler", "TheDuccinator", "theloredev", diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 09ac9a060..3c13fdeb5 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -5279,7 +5279,9 @@ void FurnaceGUI::drawInsEdit() { if (volMax>0) { macroList.push_back(FurnaceGUIMacroDesc(volumeLabel,&ins->std.volMacro,volMin,volMax,160,uiColors[GUI_COLOR_MACRO_VOLUME])); } - macroList.push_back(FurnaceGUIMacroDesc("Arpeggio",&ins->std.arpMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,0,true,ins->std.arpMacro.val)); + if (ins->type!=DIV_INS_MSM6258 && ins->type!=DIV_INS_MSM6295) { + macroList.push_back(FurnaceGUIMacroDesc("Arpeggio",&ins->std.arpMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,0,true,ins->std.arpMacro.val)); + } if (dutyMax>0) { if (ins->type==DIV_INS_MIKEY) { macroList.push_back(FurnaceGUIMacroDesc(dutyLabel,&ins->std.dutyMacro,0,dutyMax,160,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,mikeyFeedbackBits)); @@ -5317,7 +5319,7 @@ void FurnaceGUI::drawInsEdit() { } } } - if (ins->type!=DIV_INS_MSM5232) { + if (ins->type!=DIV_INS_MSM5232 && ins->type!=DIV_INS_MSM6258 && ins->type!=DIV_INS_MSM6295) { macroList.push_back(FurnaceGUIMacroDesc("Pitch",&ins->std.pitchMacro,-2048,2047,160,uiColors[GUI_COLOR_MACRO_PITCH],true,macroRelativeMode)); } if (ins->type==DIV_INS_FM ||