From 07822de0a22fb7092c6bf1020b8ee8b1c3050cf6 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 25 Sep 2022 17:31:01 -0500 Subject: [PATCH 1/9] curr -> cur --- src/engine/platform/ay.cpp | 40 +++++++++++++++++----------------- src/engine/platform/ay.h | 4 ++-- src/engine/platform/ay8930.cpp | 40 +++++++++++++++++----------------- src/engine/platform/ay8930.h | 4 ++-- src/gui/debug.cpp | 16 +++++++------- 5 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 2719f0bb..05fdfa57 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -115,7 +115,7 @@ const unsigned char dacLogTableAY[256]={ void DivPlatformAY8910::runDAC() { for (int i=0; i<3; i++) { - if (chan[i].active && chan[i].currPSGMode.dac && chan[i].dac.sample!=-1) { + if (chan[i].active && chan[i].curPSGMode.dac && chan[i].dac.sample!=-1) { chan[i].dac.period+=chan[i].dac.rate; bool end=false; bool changed=false; @@ -215,22 +215,22 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l void DivPlatformAY8910::updateOutSel(bool immediate) { if (immediate) { immWrite(0x07, - ~((chan[0].currPSGMode.getTone())| - ((chan[1].currPSGMode.getTone())<<1)| - ((chan[2].currPSGMode.getTone())<<2)| - ((chan[0].currPSGMode.getNoise())<<2)| - ((chan[1].currPSGMode.getNoise())<<3)| - ((chan[2].currPSGMode.getNoise())<<4)| + ~((chan[0].curPSGMode.getTone())| + ((chan[1].curPSGMode.getTone())<<1)| + ((chan[2].curPSGMode.getTone())<<2)| + ((chan[0].curPSGMode.getNoise())<<2)| + ((chan[1].curPSGMode.getNoise())<<3)| + ((chan[2].curPSGMode.getNoise())<<4)| ((!ioPortA)<<6)| ((!ioPortB)<<7))); } else { rWrite(0x07, - ~((chan[0].currPSGMode.getTone())| - ((chan[1].currPSGMode.getTone())<<1)| - ((chan[2].currPSGMode.getTone())<<2)| - ((chan[0].currPSGMode.getNoise())<<2)| - ((chan[1].currPSGMode.getNoise())<<3)| - ((chan[2].currPSGMode.getNoise())<<4)| + ~((chan[0].curPSGMode.getTone())| + ((chan[1].curPSGMode.getTone())<<1)| + ((chan[2].curPSGMode.getTone())<<2)| + ((chan[0].curPSGMode.getNoise())<<2)| + ((chan[1].curPSGMode.getNoise())<<3)| + ((chan[2].curPSGMode.getNoise())<<4)| ((!ioPortA)<<6)| ((!ioPortB)<<7))); } @@ -266,7 +266,7 @@ void DivPlatformAY8910::tick(bool sysTick) { if (!chan[i].nextPSGMode.dac) { chan[i].nextPSGMode.val=(chan[i].std.wave.val+1)&7; if (chan[i].active) { - chan[i].currPSGMode.val=chan[i].nextPSGMode.val; + chan[i].curPSGMode.val=chan[i].nextPSGMode.val; } if (isMuted[i]) { rWrite(0x08+i,0); @@ -340,11 +340,11 @@ void DivPlatformAY8910::tick(bool sysTick) { //rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63))); //rWrite(16+i*5+2,((chan[i].vol<<4))|(ins->gb.envLen&7)|((ins->gb.envDir&1)<<3)); if (!chan[i].nextPSGMode.dac) { - chan[i].currPSGMode.val=chan[i].nextPSGMode.val; + chan[i].curPSGMode.val=chan[i].nextPSGMode.val; } } if (chan[i].keyOff) { - chan[i].currPSGMode.val=0; + chan[i].curPSGMode.val=0; rWrite(0x08+i,0); } rWrite((i)<<1,chan[i].freq&0xff); @@ -448,7 +448,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) { } chan[c.chan].dac.furnaceDAC=false; } - chan[c.chan].currPSGMode.dac=chan[c.chan].nextPSGMode.dac; + chan[c.chan].curPSGMode.dac=chan[c.chan].nextPSGMode.dac; break; } if (c.value!=DIV_NOTE_NULL) { @@ -553,7 +553,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) { if (c.value<16) { chan[c.chan].nextPSGMode.val=(c.value+1)&7; if (chan[c.chan].active) { - chan[c.chan].currPSGMode.val=chan[c.chan].nextPSGMode.val; + chan[c.chan].curPSGMode.val=chan[c.chan].nextPSGMode.val; } if (isMuted[c.chan]) { rWrite(0x08+c.chan,0); @@ -579,7 +579,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) { chan[c.chan].nextPSGMode.envelope&=~1; } if (!chan[c.chan].nextPSGMode.dac && chan[c.chan].active) { - chan[c.chan].currPSGMode.val=chan[c.chan].nextPSGMode.val; + chan[c.chan].curPSGMode.val=chan[c.chan].nextPSGMode.val; } if (isMuted[c.chan]) { rWrite(0x08+c.chan,0); @@ -626,7 +626,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) { case DIV_CMD_SAMPLE_MODE: chan[c.chan].nextPSGMode.dac=(c.value>0)?1:0; if (chan[c.chan].active) { - chan[c.chan].currPSGMode.dac=chan[c.chan].nextPSGMode.dac; + chan[c.chan].curPSGMode.dac=chan[c.chan].nextPSGMode.dac; } break; case DIV_CMD_SAMPLE_BANK: diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index 6a8dbc3d..854eb5fb 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -57,7 +57,7 @@ class DivPlatformAY8910: public DivDispatch { PSGMode(unsigned char v=0): val(v) {} }; - PSGMode currPSGMode; + PSGMode curPSGMode; PSGMode nextPSGMode; struct DAC { @@ -85,7 +85,7 @@ class DivPlatformAY8910: public DivDispatch { pitch2=0; } Channel(): - currPSGMode(PSGMode(0)), + curPSGMode(PSGMode(0)), nextPSGMode(PSGMode(1)), dac(DAC()), freq(0), diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 8bb34ae9..9a1067fe 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -111,7 +111,7 @@ const unsigned char dacLogTableAY8930[256]={ void DivPlatformAY8930::runDAC() { for (int i=0; i<3; i++) { - if (chan[i].active && chan[i].currPSGMode.dac && chan[i].dac.sample!=-1) { + if (chan[i].active && chan[i].curPSGMode.dac && chan[i].dac.sample!=-1) { chan[i].dac.period+=chan[i].dac.rate; bool end=false; bool changed=false; @@ -195,22 +195,22 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l void DivPlatformAY8930::updateOutSel(bool immediate) { if (immediate) { immWrite(0x07, - ~((chan[0].currPSGMode.getTone())| - ((chan[1].currPSGMode.getTone())<<1)| - ((chan[2].currPSGMode.getTone())<<2)| - ((chan[0].currPSGMode.getNoise())<<2)| - ((chan[1].currPSGMode.getNoise())<<3)| - ((chan[2].currPSGMode.getNoise())<<4)| + ~((chan[0].curPSGMode.getTone())| + ((chan[1].curPSGMode.getTone())<<1)| + ((chan[2].curPSGMode.getTone())<<2)| + ((chan[0].curPSGMode.getNoise())<<2)| + ((chan[1].curPSGMode.getNoise())<<3)| + ((chan[2].curPSGMode.getNoise())<<4)| ((!ioPortA)<<6)| ((!ioPortB)<<7))); } else { rWrite(0x07, - ~((chan[0].currPSGMode.getTone())| - ((chan[1].currPSGMode.getTone())<<1)| - ((chan[2].currPSGMode.getTone())<<2)| - ((chan[0].currPSGMode.getNoise())<<2)| - ((chan[1].currPSGMode.getNoise())<<3)| - ((chan[2].currPSGMode.getNoise())<<4)| + ~((chan[0].curPSGMode.getTone())| + ((chan[1].curPSGMode.getTone())<<1)| + ((chan[2].curPSGMode.getTone())<<2)| + ((chan[0].curPSGMode.getNoise())<<2)| + ((chan[1].curPSGMode.getNoise())<<3)| + ((chan[2].curPSGMode.getNoise())<<4)| ((!ioPortA)<<6)| ((!ioPortB)<<7))); } @@ -256,7 +256,7 @@ void DivPlatformAY8930::tick(bool sysTick) { if (!chan[i].nextPSGMode.dac) { chan[i].nextPSGMode.val=(chan[i].std.wave.val+1)&7; if (chan[i].active) { - chan[i].currPSGMode.val=chan[i].nextPSGMode.val; + chan[i].curPSGMode.val=chan[i].nextPSGMode.val; } if (isMuted[i]) { rWrite(0x08+i,0); @@ -337,7 +337,7 @@ void DivPlatformAY8930::tick(bool sysTick) { if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].keyOn) { if (!chan[i].nextPSGMode.dac) { - chan[i].currPSGMode.val=chan[i].nextPSGMode.val; + chan[i].curPSGMode.val=chan[i].nextPSGMode.val; } if (chan[i].insChanged) { if (!chan[i].std.ex1.will) immWrite(0x16+i,chan[i].duty); @@ -345,7 +345,7 @@ void DivPlatformAY8930::tick(bool sysTick) { } } if (chan[i].keyOff) { - chan[i].currPSGMode.val=0; + chan[i].curPSGMode.val=0; rWrite(0x08+i,0); } rWrite((i)<<1,chan[i].freq&0xff); @@ -449,7 +449,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) { } chan[c.chan].dac.furnaceDAC=false; } - chan[c.chan].currPSGMode.dac=chan[c.chan].nextPSGMode.dac; + chan[c.chan].curPSGMode.dac=chan[c.chan].nextPSGMode.dac; break; } if (c.value!=DIV_NOTE_NULL) { @@ -547,7 +547,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) { if (!chan[c.chan].nextPSGMode.dac) { chan[c.chan].nextPSGMode.val=(c.value+1)&7; if (chan[c.chan].active) { - chan[c.chan].currPSGMode.val=chan[c.chan].nextPSGMode.val; + chan[c.chan].curPSGMode.val=chan[c.chan].nextPSGMode.val; } if (isMuted[c.chan]) { rWrite(0x08+c.chan,0); @@ -572,7 +572,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) { chan[c.chan].nextPSGMode.envelope&=~1; } if (!chan[c.chan].nextPSGMode.dac && chan[c.chan].active) { - chan[c.chan].currPSGMode.val=chan[c.chan].nextPSGMode.val; + chan[c.chan].curPSGMode.val=chan[c.chan].nextPSGMode.val; } if (isMuted[c.chan]) { rWrite(0x08+c.chan,0); @@ -627,7 +627,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) { break; case DIV_CMD_SAMPLE_MODE: chan[c.chan].nextPSGMode.dac=(c.value>0)?1:0; - chan[c.chan].currPSGMode.dac=chan[c.chan].nextPSGMode.dac; + chan[c.chan].curPSGMode.dac=chan[c.chan].nextPSGMode.dac; break; case DIV_CMD_SAMPLE_BANK: sampleBank=c.value; diff --git a/src/engine/platform/ay8930.h b/src/engine/platform/ay8930.h index 2ec12c31..fa4b83d9 100644 --- a/src/engine/platform/ay8930.h +++ b/src/engine/platform/ay8930.h @@ -65,7 +65,7 @@ class DivPlatformAY8930: public DivDispatch { PSGMode(unsigned char v=0): val(v) {} }; - PSGMode currPSGMode; + PSGMode curPSGMode; PSGMode nextPSGMode; struct DAC { @@ -94,7 +94,7 @@ class DivPlatformAY8930: public DivDispatch { } Channel(): envelope(Envelope()), - currPSGMode(PSGMode(0)), + curPSGMode(PSGMode(0)), nextPSGMode(PSGMode(1)), dac(DAC()), freq(0), diff --git a/src/gui/debug.cpp b/src/gui/debug.cpp index f50aa15b..ddd50404 100644 --- a/src/gui/debug.cpp +++ b/src/gui/debug.cpp @@ -846,10 +846,10 @@ void putDispatchChan(void* data, int chanNum, int type) { ImGui::Text("- ins: %d",ch->ins); ImGui::Text("* psgMode:"); ImGui::Text(" * curr:"); - ImGui::Text(" - tone: %d",ch->currPSGMode.tone); - ImGui::Text(" - noise: %d",ch->currPSGMode.noise); - ImGui::Text(" - envelope: %d",ch->currPSGMode.envelope); - ImGui::Text(" - dac: %d",ch->currPSGMode.dac); + ImGui::Text(" - tone: %d",ch->curPSGMode.tone); + ImGui::Text(" - noise: %d",ch->curPSGMode.noise); + ImGui::Text(" - envelope: %d",ch->curPSGMode.envelope); + ImGui::Text(" - dac: %d",ch->curPSGMode.dac); ImGui::Text(" * next:"); ImGui::Text(" - tone: %d",ch->nextPSGMode.tone); ImGui::Text(" - noise: %d",ch->nextPSGMode.noise); @@ -892,10 +892,10 @@ void putDispatchChan(void* data, int chanNum, int type) { ImGui::Text(" - low: %d",ch->envelope.slideLow); ImGui::Text("* psgMode:"); ImGui::Text(" * curr:"); - ImGui::Text(" - tone: %d",ch->currPSGMode.tone); - ImGui::Text(" - noise: %d",ch->currPSGMode.noise); - ImGui::Text(" - envelope: %d",ch->currPSGMode.envelope); - ImGui::Text(" - dac: %d",ch->currPSGMode.dac); + ImGui::Text(" - tone: %d",ch->curPSGMode.tone); + ImGui::Text(" - noise: %d",ch->curPSGMode.noise); + ImGui::Text(" - envelope: %d",ch->curPSGMode.envelope); + ImGui::Text(" - dac: %d",ch->curPSGMode.dac); ImGui::Text(" * next:"); ImGui::Text(" - tone: %d",ch->nextPSGMode.tone); ImGui::Text(" - noise: %d",ch->nextPSGMode.noise); From 148d537a1827d6a2f9d170aff7decff491d84a09 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 25 Sep 2022 18:05:08 -0500 Subject: [PATCH 2/9] update contributing --- CONTRIBUTING.md | 1 + src/engine/sample.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 853020f9..ac6c5e0e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -75,6 +75,7 @@ additional guidelines: - if you are making major changes to the playback routine, make sure to test with older songs to ensure nothing breaks. - I will run a test suite to make sure this is the case. - if something breaks, you might want to add a compatibility flag (this requires changing the format though). +- do not use `#pragma once`. ## Demo Songs diff --git a/src/engine/sample.h b/src/engine/sample.h index 17ffb6fa..bfa38d64 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -20,8 +20,6 @@ #ifndef _SAMPLE_H #define _SAMPLE_H -#pragma once - #include "../ta-utils.h" #include From a6e434586370cce9284771f0f12eb12117b4e68c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 25 Sep 2022 20:07:21 -0500 Subject: [PATCH 3/9] PLENTY OF TODO WHEN I COME BACK CRASHES EVERYWHERE --- src/engine/platform/msm6258.cpp | 1 - src/engine/platform/msm6295.cpp | 13 +++++++----- src/engine/platform/nes.cpp | 6 +++--- src/engine/platform/nes.h | 1 + src/engine/platform/opl.cpp | 15 +++++++------- src/engine/platform/opl.h | 1 + src/engine/platform/qsound.cpp | 11 +++++----- src/engine/platform/qsound.h | 3 +++ src/engine/platform/rf5c68.cpp | 8 ++++++-- src/engine/platform/rf5c68.h | 1 + src/engine/platform/segapcm.cpp | 32 +++++++++++++++++------------- src/engine/platform/segapcm.h | 3 +++ src/engine/platform/snes.cpp | 6 ++++-- src/engine/platform/snes.h | 1 + src/engine/platform/su.cpp | 12 ++++++----- src/engine/platform/su.h | 1 + src/engine/platform/x1_010.cpp | 19 +++++++++--------- src/engine/platform/x1_010.h | 1 + src/engine/platform/ym2608.cpp | 15 +++++++------- src/engine/platform/ym2608.h | 1 + src/engine/platform/ym2610.cpp | 24 +++++++++++----------- src/engine/platform/ym2610b.cpp | 24 +++++++++++----------- src/engine/platform/ym2610shared.h | 9 +++++++-- src/engine/platform/ymz280b.cpp | 6 ++++-- src/engine/platform/ymz280b.h | 1 + src/engine/sample.h | 20 +------------------ src/engine/vgmOps.cpp | 16 ++++++++++++--- src/gui/debugWindow.cpp | 17 ---------------- 28 files changed, 141 insertions(+), 127 deletions(-) diff --git a/src/engine/platform/msm6258.cpp b/src/engine/platform/msm6258.cpp index ded3899e..05465bbe 100644 --- a/src/engine/platform/msm6258.cpp +++ b/src/engine/platform/msm6258.cpp @@ -382,7 +382,6 @@ void DivPlatformMSM6258::renderSamples() { } else { memcpy(adpcmMem+memPos,s->dataVOX,paddedLen); } - s->offVOX=memPos; memPos+=paddedLen; } adpcmMemLen=memPos+256; diff --git a/src/engine/platform/msm6295.cpp b/src/engine/platform/msm6295.cpp index a898ba15..8b9c573d 100644 --- a/src/engine/platform/msm6295.cpp +++ b/src/engine/platform/msm6295.cpp @@ -336,7 +336,10 @@ size_t DivPlatformMSM6295::getSampleMemUsage(int index) { } void DivPlatformMSM6295::renderSamples() { + unsigned int sampleOffVOX[256]; + memset(adpcmMem,0,getSampleMemCapacity(0)); + memset(sampleOffVOX,0,256*sizeof(unsigned int)); // sample data size_t memPos=128*8; @@ -355,7 +358,7 @@ void DivPlatformMSM6295::renderSamples() { } else { memcpy(adpcmMem+memPos,s->dataVOX,paddedLen); } - s->offVOX=memPos; + sampleOffVOX[i]=memPos; memPos+=paddedLen; } adpcmMemLen=memPos+256; @@ -363,10 +366,10 @@ void DivPlatformMSM6295::renderSamples() { // phrase book for (int i=0; isong.sample[i]; - int endPos=s->offVOX+s->lengthVOX; - adpcmMem[i*8]=(s->offVOX>>16)&0xff; - adpcmMem[1+i*8]=(s->offVOX>>8)&0xff; - adpcmMem[2+i*8]=(s->offVOX)&0xff; + int endPos=sampleOffVOX[i]+s->lengthVOX; + adpcmMem[i*8]=(sampleOffVOX[i]>>16)&0xff; + adpcmMem[1+i*8]=(sampleOffVOX[i]>>8)&0xff; + adpcmMem[2+i*8]=(sampleOffVOX[i])&0xff; adpcmMem[3+i*8]=(endPos>>16)&0xff; adpcmMem[4+i*8]=(endPos>>8)&0xff; adpcmMem[5+i*8]=(endPos)&0xff; diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index 06962d35..d087ac81 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -317,7 +317,7 @@ void DivPlatformNES::tick(bool sysTick) { dacRate=MIN(chan[4].freq*off,32000); if (chan[4].keyOn) { if (dpcmMode && !skipRegisterWrites && dacSample>=0 && dacSamplesong.sampleLen) { - unsigned int dpcmAddr=parent->getSample(dacSample)->offDPCM; + unsigned int dpcmAddr=sampleOffDPCM[dacSample]; unsigned int dpcmLen=(parent->getSample(dacSample)->lengthDPCM+15)>>4; if (dpcmLen>255) dpcmLen=255; goingToLoop=parent->getSample(dacSample)->isLoopable(); @@ -383,7 +383,7 @@ int DivPlatformNES::dispatch(DivCommand c) { if (dumpWrites && !dpcmMode) addWrite(0xffff0001,dacRate); chan[c.chan].furnaceDac=false; if (dpcmMode && !skipRegisterWrites) { - unsigned int dpcmAddr=parent->getSample(dacSample)->offDPCM; + unsigned int dpcmAddr=sampleOffDPCM[dacSample]; unsigned int dpcmLen=(parent->getSample(dacSample)->lengthDPCM+15)>>4; if (dpcmLen>255) dpcmLen=255; goingToLoop=parent->getSample(dacSample)->isLoopable(); @@ -724,7 +724,7 @@ void DivPlatformNES::renderSamples() { } else { memcpy(dpcmMem+memPos,s->dataDPCM,MIN(s->lengthDPCM,paddedLen)); } - s->offDPCM=memPos; + sampleOffDPCM[i]=memPos; memPos+=paddedLen; } dpcmMemLen=memPos; diff --git a/src/engine/platform/nes.h b/src/engine/platform/nes.h index 2a9923fa..e8e04e9e 100644 --- a/src/engine/platform/nes.h +++ b/src/engine/platform/nes.h @@ -78,6 +78,7 @@ class DivPlatformNES: public DivDispatch { xgm::NES_APU* nes1_NP; xgm::NES_DMC* nes2_NP; unsigned char regPool[128]; + unsigned int sampleOffDPCM[256]; friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index 5d81f083..76adeafd 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -690,9 +690,9 @@ int DivPlatformOPL::dispatch(DivCommand c) { if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); immWrite(8,0); - immWrite(9,(s->offB>>2)&0xff); - immWrite(10,(s->offB>>10)&0xff); - int end=s->offB+s->lengthB-1; + immWrite(9,(sampleOffB[chan[c.chan].sample]>>2)&0xff); + immWrite(10,(sampleOffB[chan[c.chan].sample]>>10)&0xff); + int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1; immWrite(11,(end>>2)&0xff); immWrite(12,(end>>10)&0xff); if (c.value!=DIV_NOTE_NULL) { @@ -721,9 +721,9 @@ int DivPlatformOPL::dispatch(DivCommand c) { if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(12*sampleBank+c.value%12); immWrite(8,0); - immWrite(9,(s->offB>>2)&0xff); - immWrite(10,(s->offB>>10)&0xff); - int end=s->offB+s->lengthB-1; + immWrite(9,(sampleOffB[chan[c.chan].sample]>>2)&0xff); + immWrite(10,(sampleOffB[chan[c.chan].sample]>>10)&0xff); + int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1; immWrite(11,(end>>2)&0xff); immWrite(12,(end>>10)&0xff); int freq=(65536.0*(double)s->rate)/(double)chipRateBase; @@ -1760,6 +1760,7 @@ size_t DivPlatformOPL::getSampleMemUsage(int index) { void DivPlatformOPL::renderSamples() { if (adpcmChan<0) return; memset(adpcmBMem,0,getSampleMemCapacity(0)); + memset(sampleOffB,0,256*sizeof(unsigned int)); size_t memPos=0; for (int i=0; isong.sampleLen; i++) { @@ -1778,7 +1779,7 @@ void DivPlatformOPL::renderSamples() { } else { memcpy(adpcmBMem+memPos,s->dataB,paddedLen); } - s->offB=memPos; + sampleOffB[i]=memPos; memPos+=paddedLen; } adpcmBMemLen=memPos+256; diff --git a/src/engine/platform/opl.h b/src/engine/platform/opl.h index 43f02790..41be2c89 100644 --- a/src/engine/platform/opl.h +++ b/src/engine/platform/opl.h @@ -90,6 +90,7 @@ class DivPlatformOPL: public DivDispatch { unsigned char* adpcmBMem; size_t adpcmBMemLen; DivOPLAInterface iface; + unsigned int sampleOffB[256]; ymfm::adpcm_b_engine* adpcmB; const unsigned char** slotsNonDrums; diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index 4f7d2545..2b54a90a 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -286,8 +286,8 @@ void DivPlatformQSound::tick(bool sysTick) { uint16_t qsound_end = 0; if (chan[i].sample>=0 && chan[i].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[i].sample); - qsound_bank = 0x8000 | (s->offQSound >> 16); - qsound_addr = s->offQSound & 0xffff; + qsound_bank = 0x8000 | (offPCM[chan[i].sample] >> 16); + qsound_addr = offPCM[chan[i].sample] & 0xffff; int loopStart=s->loopStart; int length = s->loopEnd; @@ -295,10 +295,10 @@ void DivPlatformQSound::tick(bool sysTick) { length = 65536 - 16; } if (loopStart == -1 || loopStart >= length) { - qsound_end = s->offQSound + length + 15; + qsound_end = offPCM[chan[i].sample] + length + 15; qsound_loop = 15; } else { - qsound_end = s->offQSound + length; + qsound_end = offPCM[chan[i].sample] + length; qsound_loop = length - loopStart; } } @@ -644,6 +644,7 @@ size_t DivPlatformQSound::getSampleMemUsage(int index) { return index == 0 ? sampleMemLen : 0; } +// TODO: ADPCM... come on... void DivPlatformQSound::renderSamples() { memset(sampleMem,0,getSampleMemCapacity()); @@ -671,7 +672,7 @@ void DivPlatformQSound::renderSamples() { sampleMem[(memPos+i)^0x8000]=s->data8[i]; } } - s->offQSound=memPos^0x8000; + offPCM[i]=memPos^0x8000; memPos+=length+16; } sampleMemLen=memPos+256; diff --git a/src/engine/platform/qsound.h b/src/engine/platform/qsound.h index 5e2a32fc..7743e594 100644 --- a/src/engine/platform/qsound.h +++ b/src/engine/platform/qsound.h @@ -72,6 +72,9 @@ class DivPlatformQSound: public DivDispatch { struct qsound_chip chip; unsigned short regPool[512]; + unsigned int offPCM[256]; + unsigned int offBS[256]; + friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); diff --git a/src/engine/platform/rf5c68.cpp b/src/engine/platform/rf5c68.cpp index 86d37372..e462e3d8 100644 --- a/src/engine/platform/rf5c68.cpp +++ b/src/engine/platform/rf5c68.cpp @@ -122,6 +122,9 @@ void DivPlatformRF5C68::tick(bool sysTick) { } else { chan[i].audPos=0; } + // TODO: BANG BANG BANG + // AAAAAAAAAAAAAAAAAAA + // ASGDJFJFSDGL;ASDHFKJLSHFLKAJSFHKLJVSJ if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { unsigned char keyon=regPool[8]&~(1<calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE)); if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].keyOn) { - unsigned int start=s->offRF5C68; + unsigned int start=sampleOffRFC[chan[i].sample]; unsigned int loop=start+s->length8; if (chan[i].audPos>0) { start=start+MIN(chan[i].audPos,s->length8); @@ -383,6 +386,7 @@ size_t DivPlatformRF5C68::getSampleMemUsage(int index) { void DivPlatformRF5C68::renderSamples() { memset(sampleMem,0,getSampleMemCapacity()); + memset(sampleOffRFC,0,256*sizeof(unsigned int)); size_t memPos=0; for (int i=0; isong.sampleLen; i++) { @@ -390,7 +394,7 @@ void DivPlatformRF5C68::renderSamples() { int length=s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT); int actualLength=MIN((int)(getSampleMemCapacity()-memPos)-31,length); if (actualLength>0) { - s->offRF5C68=memPos; + sampleOffRFC[i]=memPos; for (int j=0; jdata8[j]; diff --git a/src/engine/platform/rf5c68.h b/src/engine/platform/rf5c68.h index bcbb3da2..840ece46 100644 --- a/src/engine/platform/rf5c68.h +++ b/src/engine/platform/rf5c68.h @@ -66,6 +66,7 @@ class DivPlatformRF5C68: public DivDispatch { bool isMuted[8]; int chipType; unsigned char curChan; + unsigned int sampleOffRFC[256]; unsigned char* sampleMem; size_t sampleMemLen; diff --git a/src/engine/platform/segapcm.cpp b/src/engine/platform/segapcm.cpp index 650f54c9..5cd4a8e8 100644 --- a/src/engine/platform/segapcm.cpp +++ b/src/engine/platform/segapcm.cpp @@ -159,17 +159,17 @@ void DivPlatformSegaPCM::tick(bool sysTick) { int loopStart=s->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT); int actualLength=(s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)); if (actualLength>0xfeff) actualLength=0xfeff; - addWrite(0x10086+(i<<3),3+((s->offSegaPCM>>16)<<3)); - addWrite(0x10084+(i<<3),(s->offSegaPCM)&0xff); - addWrite(0x10085+(i<<3),(s->offSegaPCM>>8)&0xff); - addWrite(0x10006+(i<<3),MIN(255,((s->offSegaPCM&0xffff)+actualLength-1)>>8)); + addWrite(0x10086+(i<<3),3+((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); + addWrite(0x10084+(i<<3),(sampleOffSegaPCM[chan[i].pcm.sample])&0xff); + addWrite(0x10085+(i<<3),(sampleOffSegaPCM[chan[i].pcm.sample]>>8)&0xff); + addWrite(0x10006+(i<<3),MIN(255,((sampleOffSegaPCM[chan[i].pcm.sample]&0xffff)+actualLength-1)>>8)); if (loopStart<0 || loopStart>=actualLength) { - addWrite(0x10086+(i<<3),2+((s->offSegaPCM>>16)<<3)); + addWrite(0x10086+(i<<3),2+((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); } else { - int loopPos=(s->offSegaPCM&0xffff)+loopStart+s->loopOffP; + int loopPos=(sampleOffSegaPCM[chan[i].pcm.sample]&0xffff)+loopStart+s->loopOffP; addWrite(0x10004+(i<<3),loopPos&0xff); addWrite(0x10005+(i<<3),(loopPos>>8)&0xff); - addWrite(0x10086+(i<<3),((s->offSegaPCM>>16)<<3)); + addWrite(0x10086+(i<<3),((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); } } } else { @@ -178,17 +178,17 @@ void DivPlatformSegaPCM::tick(bool sysTick) { int loopStart=s->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT); int actualLength=(s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)); if (actualLength>65536) actualLength=65536; - addWrite(0x10086+(i<<3),3+((s->offSegaPCM>>16)<<3)); - addWrite(0x10084+(i<<3),(s->offSegaPCM)&0xff); - addWrite(0x10085+(i<<3),(s->offSegaPCM>>8)&0xff); - addWrite(0x10006+(i<<3),MIN(255,((s->offSegaPCM&0xffff)+actualLength-1)>>8)); + addWrite(0x10086+(i<<3),3+((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); + addWrite(0x10084+(i<<3),(sampleOffSegaPCM[chan[i].pcm.sample])&0xff); + addWrite(0x10085+(i<<3),(sampleOffSegaPCM[chan[i].pcm.sample]>>8)&0xff); + addWrite(0x10006+(i<<3),MIN(255,((sampleOffSegaPCM[chan[i].pcm.sample]&0xffff)+actualLength-1)>>8)); if (loopStart<0 || loopStart>=actualLength) { - addWrite(0x10086+(i<<3),2+((s->offSegaPCM>>16)<<3)); + addWrite(0x10086+(i<<3),2+((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); } else { - int loopPos=(s->offSegaPCM&0xffff)+loopStart+s->loopOffP; + int loopPos=(sampleOffSegaPCM[chan[i].pcm.sample]&0xffff)+loopStart+s->loopOffP; addWrite(0x10004+(i<<3),loopPos&0xff); addWrite(0x10005+(i<<3),(loopPos>>8)&0xff); - addWrite(0x10086+(i<<3),((s->offSegaPCM>>16)<<3)); + addWrite(0x10086+(i<<3),((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); } addWrite(0x10007+(i<<3),chan[i].pcm.freq); } @@ -451,6 +451,10 @@ void DivPlatformSegaPCM::reset() { } } + void DivPlatformSegaPCM::renderSamples() { + // TODO: THIS MESS + } + void DivPlatformSegaPCM::setFlags(unsigned int flags) { chipClock=8000000.0; rate=31250; diff --git a/src/engine/platform/segapcm.h b/src/engine/platform/segapcm.h index 888a3384..2a76143b 100644 --- a/src/engine/platform/segapcm.h +++ b/src/engine/platform/segapcm.h @@ -91,6 +91,8 @@ class DivPlatformSegaPCM: public DivDispatch { short oldWrites[256]; short pendingWrites[256]; + + unsigned int sampleOffSegaPCM[256]; friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); @@ -108,6 +110,7 @@ class DivPlatformSegaPCM: public DivDispatch { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); void notifyInsChange(int ins); + void renderSamples(); void setFlags(unsigned int flags); bool isStereo(); void poke(unsigned int addr, unsigned short val); diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index 7e0996d9..3686980f 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -178,6 +178,7 @@ void DivPlatformSNES::tick(bool sysTick) { updateWave(i); } } + // TODO: THIS WILL CRASH IF THE SAMPLE IS INVALID!!! if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { DivSample* s=parent->getSample(chan[i].sample); double off=(s->centerRate>=1)?((double)s->centerRate/8363.0):1.0; @@ -191,7 +192,7 @@ void DivPlatformSNES::tick(bool sysTick) { start=waveTableAddr(i); loop=start; } else { - start=s->offSNES; + start=sampleOff[chan[i].sample]; end=MIN(start+MAX(s->lengthBRR,1),getSampleMemCapacity()); loop=MAX(start,end-1); if (chan[i].audPos>0) { @@ -567,6 +568,7 @@ size_t DivPlatformSNES::getSampleMemUsage(int index) { void DivPlatformSNES::renderSamples() { memset(sampleMem,0,getSampleMemCapacity()); + memset(sampleOff,0,256*sizeof(unsigned int)); // skip past sample table and wavetable buffer size_t memPos=sampleTableBase+8*4+8*9*16; @@ -575,7 +577,7 @@ void DivPlatformSNES::renderSamples() { int length=s->lengthBRR; int actualLength=MIN((int)(getSampleMemCapacity()-memPos)/9*9,length); if (actualLength>0) { - s->offSNES=memPos; + sampleOff[i]=memPos; memcpy(&sampleMem[memPos],s->dataBRR,actualLength); memPos+=actualLength; } diff --git a/src/engine/platform/snes.h b/src/engine/platform/snes.h index 7ac5d524..ad8048f3 100644 --- a/src/engine/platform/snes.h +++ b/src/engine/platform/snes.h @@ -92,6 +92,7 @@ class DivPlatformSNES: public DivDispatch { signed char sampleMem[65536]; size_t sampleMemLen; + unsigned int sampleOff[256]; unsigned char regPool[0x80]; SPC_DSP dsp; friend void putDispatchChan(void*,int,int); diff --git a/src/engine/platform/su.cpp b/src/engine/platform/su.cpp index e36b424f..25fefa20 100644 --- a/src/engine/platform/su.cpp +++ b/src/engine/platform/su.cpp @@ -161,10 +161,11 @@ void DivPlatformSoundUnit::tick(bool sysTick) { if (chan[i].keyOn) { if (chan[i].pcm) { DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU); - DivSample* sample=parent->getSample(ins->amiga.getSample(chan[i].note)); + int sNum=ins->amiga.getSample(chan[i].note); + DivSample* sample=parent->getSample(sNum); if (sample!=NULL) { - unsigned int sampleEnd=sample->offSU+(sample->getLoopEndPosition()); - unsigned int off=sample->offSU+chan[i].hasOffset; + unsigned int sampleEnd=sampleOffSU[sNum]+(sample->getLoopEndPosition()); + unsigned int off=sampleOffSU[sNum]+chan[i].hasOffset; chan[i].hasOffset=0; if (sampleEnd>=getSampleMemCapacity(0)) sampleEnd=getSampleMemCapacity(0)-1; chWrite(i,0x0a,off&0xff); @@ -172,7 +173,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) { chWrite(i,0x0c,sampleEnd&0xff); chWrite(i,0x0d,sampleEnd>>8); if (sample->isLoopable()) { - unsigned int sampleLoop=sample->offSU+sample->getLoopStartPosition(); + unsigned int sampleLoop=sampleOffSU[sNum]+sample->getLoopStartPosition(); if (sampleLoop>=getSampleMemCapacity(0)) sampleLoop=getSampleMemCapacity(0)-1; chWrite(i,0x0e,sampleLoop&0xff); chWrite(i,0x0f,sampleLoop>>8); @@ -547,6 +548,7 @@ size_t DivPlatformSoundUnit::getSampleMemUsage(int index) { void DivPlatformSoundUnit::renderSamples() { memset(su->pcm,0,getSampleMemCapacity(0)); + memset(sampleOffSU,0,256*sizeof(unsigned int)); size_t memPos=0; for (int i=0; isong.sampleLen; i++) { @@ -563,7 +565,7 @@ void DivPlatformSoundUnit::renderSamples() { } else { memcpy(su->pcm+memPos,s->data8,paddedLen); } - s->offSU=memPos; + sampleOffSU[i]=memPos; memPos+=paddedLen; } sampleMemLen=memPos; diff --git a/src/engine/platform/su.h b/src/engine/platform/su.h index d94df8ea..784186c6 100644 --- a/src/engine/platform/su.h +++ b/src/engine/platform/su.h @@ -101,6 +101,7 @@ class DivPlatformSoundUnit: public DivDispatch { unsigned char ilCtrl, ilSize, fil1; unsigned char initIlCtrl, initIlSize, initFil1; signed char echoVol, initEchoVol; + unsigned int sampleOffSU[256]; int cycles, curChan, delay; short tempL; diff --git a/src/engine/platform/x1_010.cpp b/src/engine/platform/x1_010.cpp index 1c04267b..5f71b8fd 100644 --- a/src/engine/platform/x1_010.cpp +++ b/src/engine/platform/x1_010.cpp @@ -541,14 +541,14 @@ int DivPlatformX1_010::dispatch(DivCommand c) { DivSample* s=parent->getSample(chan[c.chan].sample); if (isBanked) { chan[c.chan].bankSlot=ins->x1_010.bankSlot; - bankSlot[chan[c.chan].bankSlot]=s->offX1_010>>17; - unsigned int bankedOffs=(chan[c.chan].bankSlot<<17)|(s->offX1_010&0x1ffff); + bankSlot[chan[c.chan].bankSlot]=sampleOffX1[chan[c.chan].sample]>>17; + unsigned int bankedOffs=(chan[c.chan].bankSlot<<17)|(sampleOffX1[chan[c.chan].sample]&0x1ffff); chWrite(c.chan,4,(bankedOffs>>12)&0xff); int end=(bankedOffs+MIN(s->length8,0x1ffff)+0xfff)&~0xfff; // padded chWrite(c.chan,5,(0x100-(end>>12))&0xff); } else { - chWrite(c.chan,4,(s->offX1_010>>12)&0xff); - int end=(s->offX1_010+s->length8+0xfff)&~0xfff; // padded + chWrite(c.chan,4,(sampleOffX1[chan[c.chan].sample]>>12)&0xff); + int end=(sampleOffX1[chan[c.chan].sample]+s->length8+0xfff)&~0xfff; // padded chWrite(c.chan,5,(0x100-(end>>12))&0xff); } if (c.value!=DIV_NOTE_NULL) { @@ -581,14 +581,14 @@ int DivPlatformX1_010::dispatch(DivCommand c) { } DivSample* s=parent->getSample(12*sampleBank+c.value%12); if (isBanked) { - bankSlot[chan[c.chan].bankSlot]=s->offX1_010>>17; - unsigned int bankedOffs=(chan[c.chan].bankSlot<<17)|(s->offX1_010&0x1ffff); + bankSlot[chan[c.chan].bankSlot]=sampleOffX1[chan[c.chan].sample]>>17; + unsigned int bankedOffs=(chan[c.chan].bankSlot<<17)|(sampleOffX1[chan[c.chan].sample]&0x1ffff); chWrite(c.chan,4,(bankedOffs>>12)&0xff); int end=(bankedOffs+MIN(s->length8,0x1ffff)+0xfff)&~0xfff; // padded chWrite(c.chan,5,(0x100-(end>>12))&0xff); } else { - chWrite(c.chan,4,(s->offX1_010>>12)&0xff); - int end=(s->offX1_010+s->length8+0xfff)&~0xfff; // padded + chWrite(c.chan,4,(sampleOffX1[chan[c.chan].sample]>>12)&0xff); + int end=(sampleOffX1[chan[c.chan].sample]+s->length8+0xfff)&~0xfff; // padded chWrite(c.chan,5,(0x100-(end>>12))&0xff); } chan[c.chan].baseFreq=(((unsigned int)s->rate)<<4)/(chipClock/512); @@ -945,6 +945,7 @@ size_t DivPlatformX1_010::getSampleMemUsage(int index) { void DivPlatformX1_010::renderSamples() { memset(sampleMem,0,getSampleMemCapacity()); + memset(sampleOffX1,0,256*sizeof(unsigned int)); size_t memPos=0; for (int i=0; isong.sampleLen; i++) { @@ -969,7 +970,7 @@ void DivPlatformX1_010::renderSamples() { } else { memcpy(sampleMem+memPos,s->data8,paddedLen); } - s->offX1_010=memPos; + sampleOffX1[i]=memPos; memPos+=paddedLen; } sampleMemLen=memPos+256; diff --git a/src/engine/platform/x1_010.h b/src/engine/platform/x1_010.h index 19fb9135..ce3e86c1 100644 --- a/src/engine/platform/x1_010.h +++ b/src/engine/platform/x1_010.h @@ -115,6 +115,7 @@ class DivPlatformX1_010: public DivDispatch, public vgsound_emu_mem_intf { bool isBanked=false; unsigned int bankSlot[8]; + unsigned int sampleOffX1[256]; unsigned char regPool[0x2000]; double NoteX1_010(int ch, int note); diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index 82a130ac..b247be44 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -684,9 +684,9 @@ int DivPlatformYM2608::dispatch(DivCommand c) { chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); - immWrite(0x102,(s->offB>>5)&0xff); - immWrite(0x103,(s->offB>>13)&0xff); - int end=s->offB+s->lengthB-1; + immWrite(0x102,(sampleOffB[chan[c.chan].sample]>>5)&0xff); + immWrite(0x103,(sampleOffB[chan[c.chan].sample]>>13)&0xff); + int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1; immWrite(0x104,(end>>5)&0xff); immWrite(0x105,(end>>13)&0xff); immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2); @@ -715,9 +715,9 @@ int DivPlatformYM2608::dispatch(DivCommand c) { chan[c.chan].sample=12*sampleBank+c.value%12; if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); - immWrite(0x102,(s->offB>>5)&0xff); - immWrite(0x103,(s->offB>>13)&0xff); - int end=s->offB+s->lengthB-1; + immWrite(0x102,(sampleOffB[chan[c.chan].sample]>>5)&0xff); + immWrite(0x103,(sampleOffB[chan[c.chan].sample]>>13)&0xff); + int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1; immWrite(0x104,(end>>5)&0xff); immWrite(0x105,(end>>13)&0xff); immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2); @@ -1334,6 +1334,7 @@ size_t DivPlatformYM2608::getSampleMemUsage(int index) { void DivPlatformYM2608::renderSamples() { memset(adpcmBMem,0,getSampleMemCapacity(0)); + memset(sampleOffB,0,256*sizeof(unsigned int)); size_t memPos=0; for (int i=0; isong.sampleLen; i++) { @@ -1352,7 +1353,7 @@ void DivPlatformYM2608::renderSamples() { } else { memcpy(adpcmBMem+memPos,s->dataB,paddedLen); } - s->offB=memPos; + sampleOffB[i]=memPos; memPos+=paddedLen; } adpcmBMemLen=memPos+256; diff --git a/src/engine/platform/ym2608.h b/src/engine/platform/ym2608.h index 073e381d..a1b52320 100644 --- a/src/engine/platform/ym2608.h +++ b/src/engine/platform/ym2608.h @@ -99,6 +99,7 @@ class DivPlatformYM2608: public DivPlatformOPN { unsigned char* adpcmBMem; size_t adpcmBMemLen; DivYM2608Interface iface; + unsigned int sampleOffB[256]; DivPlatformAY8910* ay; unsigned char sampleBank; diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 9e8f1847..794fc7d9 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -623,9 +623,9 @@ int DivPlatformYM2610::dispatch(DivCommand c) { chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); - immWrite(0x12,(s->offB>>8)&0xff); - immWrite(0x13,s->offB>>16); - int end=s->offB+s->lengthB-1; + immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff); + immWrite(0x13,sampleOffB[chan[c.chan].sample]>>16); + int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1; immWrite(0x14,(end>>8)&0xff); immWrite(0x15,end>>16); immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6)); @@ -654,9 +654,9 @@ int DivPlatformYM2610::dispatch(DivCommand c) { chan[c.chan].sample=12*sampleBank+c.value%12; if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(12*sampleBank+c.value%12); - immWrite(0x12,(s->offB>>8)&0xff); - immWrite(0x13,s->offB>>16); - int end=s->offB+s->lengthB-1; + immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff); + immWrite(0x13,sampleOffB[chan[c.chan].sample]>>16); + int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1; immWrite(0x14,(end>>8)&0xff); immWrite(0x15,end>>16); immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6)); @@ -694,9 +694,9 @@ int DivPlatformYM2610::dispatch(DivCommand c) { chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); - immWrite(0x110+c.chan-adpcmAChanOffs,(s->offA>>8)&0xff); - immWrite(0x118+c.chan-adpcmAChanOffs,s->offA>>16); - int end=s->offA+s->lengthA-1; + immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff); + immWrite(0x118+c.chan-adpcmAChanOffs,sampleOffA[chan[c.chan].sample]>>16); + int end=sampleOffA[chan[c.chan].sample]+s->lengthA-1; immWrite(0x120+c.chan-adpcmAChanOffs,(end>>8)&0xff); immWrite(0x128+c.chan-adpcmAChanOffs,end>>16); immWrite(0x108+c.chan-adpcmAChanOffs,isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol)); @@ -725,9 +725,9 @@ int DivPlatformYM2610::dispatch(DivCommand c) { chan[c.chan].sample=12*sampleBank+c.value%12; if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(12*sampleBank+c.value%12); - immWrite(0x110+c.chan-adpcmAChanOffs,(s->offA>>8)&0xff); - immWrite(0x118+c.chan-adpcmAChanOffs,s->offA>>16); - int end=s->offA+s->lengthA-1; + immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff); + immWrite(0x118+c.chan-adpcmAChanOffs,sampleOffA[chan[c.chan].sample]>>16); + int end=sampleOffA[chan[c.chan].sample]+s->lengthA-1; immWrite(0x120+c.chan-adpcmAChanOffs,(end>>8)&0xff); immWrite(0x128+c.chan-adpcmAChanOffs,end>>16); immWrite(0x108+c.chan-adpcmAChanOffs,isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol)); diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index bf854f36..941cee22 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -686,9 +686,9 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); - immWrite(0x12,(s->offB>>8)&0xff); - immWrite(0x13,s->offB>>16); - int end=s->offB+s->lengthB-1; + immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff); + immWrite(0x13,sampleOffB[chan[c.chan].sample]>>16); + int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1; immWrite(0x14,(end>>8)&0xff); immWrite(0x15,end>>16); immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6)); @@ -717,9 +717,9 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { chan[c.chan].sample=12*sampleBank+c.value%12; if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(12*sampleBank+c.value%12); - immWrite(0x12,(s->offB>>8)&0xff); - immWrite(0x13,s->offB>>16); - int end=s->offB+s->lengthB-1; + immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff); + immWrite(0x13,sampleOffB[chan[c.chan].sample]>>16); + int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1; immWrite(0x14,(end>>8)&0xff); immWrite(0x15,end>>16); immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6)); @@ -757,9 +757,9 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); - immWrite(0x110+c.chan-adpcmAChanOffs,(s->offA>>8)&0xff); - immWrite(0x118+c.chan-adpcmAChanOffs,s->offA>>16); - int end=s->offA+s->lengthA-1; + immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff); + immWrite(0x118+c.chan-adpcmAChanOffs,sampleOffA[chan[c.chan].sample]>>16); + int end=sampleOffA[chan[c.chan].sample]+s->lengthA-1; immWrite(0x120+c.chan-adpcmAChanOffs,(end>>8)&0xff); immWrite(0x128+c.chan-adpcmAChanOffs,end>>16); immWrite(0x108+c.chan-adpcmAChanOffs,isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol)); @@ -788,9 +788,9 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { chan[c.chan].sample=12*sampleBank+c.value%12; if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(12*sampleBank+c.value%12); - immWrite(0x110+c.chan-adpcmAChanOffs,(s->offA>>8)&0xff); - immWrite(0x118+c.chan-adpcmAChanOffs,s->offA>>16); - int end=s->offA+s->lengthA-1; + immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff); + immWrite(0x118+c.chan-adpcmAChanOffs,sampleOffA[chan[c.chan].sample]>>16); + int end=sampleOffA[chan[c.chan].sample]+s->lengthA-1; immWrite(0x120+c.chan-adpcmAChanOffs,(end>>8)&0xff); immWrite(0x128+c.chan-adpcmAChanOffs,end>>16); immWrite(0x108+c.chan-adpcmAChanOffs,isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol)); diff --git a/src/engine/platform/ym2610shared.h b/src/engine/platform/ym2610shared.h index e8bbd16f..920cf499 100644 --- a/src/engine/platform/ym2610shared.h +++ b/src/engine/platform/ym2610shared.h @@ -136,6 +136,9 @@ template class DivPlatformYM2610Base: public DivPlatformOPN { size_t adpcmBMemLen; DivYM2610Interface iface; + unsigned int sampleOffA[256]; + unsigned int sampleOffB[256]; + unsigned char sampleBank; bool extMode; @@ -207,6 +210,8 @@ template class DivPlatformYM2610Base: public DivPlatformOPN { void renderSamples() { memset(adpcmAMem,0,getSampleMemCapacity(0)); + memset(sampleOffA,0,256*sizeof(unsigned int)); + memset(sampleOffB,0,256*sizeof(unsigned int)); size_t memPos=0; for (int i=0; isong.sampleLen; i++) { @@ -225,7 +230,7 @@ template class DivPlatformYM2610Base: public DivPlatformOPN { } else { memcpy(adpcmAMem+memPos,s->dataA,paddedLen); } - s->offA=memPos; + sampleOffA[i]=memPos; memPos+=paddedLen; } adpcmAMemLen=memPos+256; @@ -249,7 +254,7 @@ template class DivPlatformYM2610Base: public DivPlatformOPN { } else { memcpy(adpcmBMem+memPos,s->dataB,paddedLen); } - s->offB=memPos; + sampleOffB[i]=memPos; memPos+=paddedLen; } adpcmBMemLen=memPos+256; diff --git a/src/engine/platform/ymz280b.cpp b/src/engine/platform/ymz280b.cpp index 143124b5..2e617c76 100644 --- a/src/engine/platform/ymz280b.cpp +++ b/src/engine/platform/ymz280b.cpp @@ -145,8 +145,9 @@ void DivPlatformYMZ280B::tick(bool sysTick) { // ADPCM has half the range if (s->depth==DIV_SAMPLE_DEPTH_YMZ_ADPCM && chan[i].freq>255) chan[i].freq=255; ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0)|(chan[i].freq>>8); + // TODO: AGAIN THIS WILL CRASH IF THE SAMPLE IS INVALID!!! if (chan[i].keyOn) { - unsigned int start=s->offYMZ280B; + unsigned int start=sampleOff[chan[i].sample]; unsigned int loopStart=0; unsigned int loopEnd=0; unsigned int end=MIN(start+s->getCurBufLen(),getSampleMemCapacity()-1); @@ -418,6 +419,7 @@ size_t DivPlatformYMZ280B::getSampleMemUsage(int index) { void DivPlatformYMZ280B::renderSamples() { memset(sampleMem,0,getSampleMemCapacity()); + memset(sampleOff,0,256*sizeof(unsigned int)); size_t memPos=0; for (int i=0; isong.sampleLen; i++) { @@ -427,7 +429,7 @@ void DivPlatformYMZ280B::renderSamples() { int actualLength=MIN((int)(getSampleMemCapacity()-memPos),length); if (actualLength>0) { memcpy(&sampleMem[memPos],src,actualLength); - s->offYMZ280B=memPos; + sampleOff[i]=memPos; memPos+=length; } if (actualLengthinit(); @@ -1501,12 +1504,16 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p unsigned int songOff=w->tell(); + // initialize sample offsets + memset(sampleOff8,0,256*sizeof(unsigned int)); + memset(sampleOffSegaPCM,0,256*sizeof(unsigned int)); + // write samples unsigned int sampleSeek=0; for (int i=0; ioff8=sampleSeek; + sampleOff8[i]=sampleSeek; sampleSeek+=sample->length8; } @@ -1556,7 +1563,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p } logV("- sample %d will be at %x with length %x",i,memPos,alignedSize); if (memPos>=16777216) break; - sample->offSegaPCM=memPos; + sampleOffSegaPCM[i]=memPos; unsigned int readPos=0; for (unsigned int j=0; j=(unsigned int)sample->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)) { @@ -1661,6 +1668,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p size_t sampleMemLen=writeZ280[i]->getSampleMemUsage(); unsigned char* sampleMem=new unsigned char[sampleMemLen]; memcpy(sampleMem,writeZ280[i]->getSampleMem(),sampleMemLen); + // TODO: please fix this later + /* for (int i=0; idepth==DIV_SAMPLE_DEPTH_16BIT) { @@ -1673,6 +1682,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p } } } + */ w->writeC(0x67); w->writeC(0x66); w->writeC(0x86); @@ -1900,7 +1910,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p if (sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)) { w->writeC(0x93); w->writeC(nextToTouch); - w->writeI(sample->off8+sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)); + w->writeI(sampleOff8[loopSample[nextToTouch]]+sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)); w->writeC(0x81); w->writeI(sample->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)-sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)); } diff --git a/src/gui/debugWindow.cpp b/src/gui/debugWindow.cpp index d3ecbc98..2c507bb4 100644 --- a/src/gui/debugWindow.cpp +++ b/src/gui/debugWindow.cpp @@ -191,23 +191,6 @@ void FurnaceGUI::drawDebug() { ImGui::Text("lengthBRR: %d",sample->lengthBRR); ImGui::Text("lengthVOX: %d",sample->lengthVOX); - ImGui::Text("off8: %x",sample->off8); - ImGui::Text("off16: %x",sample->off16); - ImGui::Text("off1: %x",sample->off1); - ImGui::Text("offDPCM: %x",sample->offDPCM); - ImGui::Text("offZ: %x",sample->offZ); - ImGui::Text("offQSoundA: %x",sample->offQSoundA); - ImGui::Text("offA: %x",sample->offA); - ImGui::Text("offB: %x",sample->offB); - ImGui::Text("offBRR: %x",sample->offBRR); - ImGui::Text("offVOX: %x",sample->offVOX); - ImGui::Text("offSegaPCM: %x",sample->offSegaPCM); - ImGui::Text("offQSound: %x",sample->offQSound); - ImGui::Text("offX1_010: %x",sample->offX1_010); - ImGui::Text("offSU: %x",sample->offSU); - ImGui::Text("offYMZ280B: %x",sample->offYMZ280B); - ImGui::Text("offRF5C68: %x",sample->offRF5C68); - ImGui::Text("samples: %d",sample->samples); ImGui::TreePop(); } From c27c650c11fc2047830de3cce84f289ae9be7e1b Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 25 Sep 2022 23:43:01 -0500 Subject: [PATCH 4/9] MIDI out: prevent out of range notes --- src/engine/playback.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index ca62009a..d9eb18f8 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -266,7 +266,11 @@ int DivEngine::dispatchCmd(DivCommand c) { if (chan[c.chan].curMidiNote>=0) { output->midiOut->send(TAMidiMessage(0x80|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); } - if (c.value!=DIV_NOTE_NULL) chan[c.chan].curMidiNote=c.value+12; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].curMidiNote=c.value+12; + if (chan[c.chan].curMidiNote<0) chan[c.chan].curMidiNote=0; + if (chan[c.chan].curMidiNote>127) chan[c.chan].curMidiNote=127; + } output->midiOut->send(TAMidiMessage(0x90|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); break; case DIV_CMD_NOTE_OFF: From 122694d7c98e98bd4ed00c4aa9c347d8f11d5e88 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 26 Sep 2022 01:27:36 -0500 Subject: [PATCH 5/9] MIDI output improvements --- src/engine/engine.cpp | 2 + src/engine/engine.h | 10 ++++ src/engine/playback.cpp | 122 ++++++++++++++++++++++++---------------- src/gui/gui.h | 4 ++ src/gui/settings.cpp | 26 +++++++++ 5 files changed, 117 insertions(+), 47 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index a7eac1b6..46f7ad03 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -3683,6 +3683,8 @@ bool DivEngine::initAudioBackend() { clampSamples=getConfInt("clampSamples",0); lowLatency=getConfInt("lowLatency",0); metroVol=(float)(getConfInt("metroVol",100))/100.0f; + midiOutClock=getConfInt("midiOutClock",0); + midiOutMode=getConfInt("midiOutMode",DIV_MIDI_MODE_NOTE); if (metroVol<0.0f) metroVol=0.0f; if (metroVol>2.0f) metroVol=2.0f; diff --git a/src/engine/engine.h b/src/engine/engine.h index 0e56b12f..2219b6e2 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -83,6 +83,12 @@ enum DivHaltPositions { DIV_HALT_BREAKPOINT }; +enum DivMIDIModes { + DIV_MIDI_MODE_OFF=0, + DIV_MIDI_MODE_NOTE, + DIV_MIDI_MODE_LIGHT_SHOW +}; + struct DivChannelState { std::vector delayed; int note, oldNote, lastIns, pitch, portaSpeed, portaNote; @@ -340,6 +346,8 @@ class DivEngine { bool lowLatency; bool systemsRegistered; bool hasLoadedSomething; + bool midiOutClock; + int midiOutMode; int softLockCount; int subticks, ticks, curRow, curOrder, prevRow, prevOrder, remainingLoops, totalLoops, lastLoopPos, exportLoopCount, nextSpeed; size_t curSubSongIndex; @@ -1008,6 +1016,8 @@ class DivEngine { lowLatency(false), systemsRegistered(false), hasLoadedSomething(false), + midiOutClock(false), + midiOutMode(DIV_MIDI_MODE_NOTE), softLockCount(0), subticks(0), ticks(0), diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index d9eb18f8..fedfc94e 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -257,52 +257,79 @@ int DivEngine::dispatchCmd(DivCommand c) { if (output) if (!skipping && output->midiOut!=NULL) { if (output->midiOut->isDeviceOpen()) { - int scaledVol=(chan[c.chan].volume*127)/MAX(1,chan[c.chan].volMax); - if (scaledVol<0) scaledVol=0; - if (scaledVol>127) scaledVol=127; - switch (c.cmd) { - case DIV_CMD_NOTE_ON: - case DIV_CMD_LEGATO: - if (chan[c.chan].curMidiNote>=0) { - output->midiOut->send(TAMidiMessage(0x80|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); + if (midiOutMode==DIV_MIDI_MODE_NOTE) { + int scaledVol=(chan[c.chan].volume*127)/MAX(1,chan[c.chan].volMax); + if (scaledVol<0) scaledVol=0; + if (scaledVol>127) scaledVol=127; + switch (c.cmd) { + case DIV_CMD_NOTE_ON: + case DIV_CMD_LEGATO: + if (chan[c.chan].curMidiNote>=0) { + output->midiOut->send(TAMidiMessage(0x80|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); + } + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].curMidiNote=c.value+12; + if (chan[c.chan].curMidiNote<0) chan[c.chan].curMidiNote=0; + if (chan[c.chan].curMidiNote>127) chan[c.chan].curMidiNote=127; + } + output->midiOut->send(TAMidiMessage(0x90|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); + break; + case DIV_CMD_NOTE_OFF: + case DIV_CMD_NOTE_OFF_ENV: + if (chan[c.chan].curMidiNote>=0) { + output->midiOut->send(TAMidiMessage(0x80|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); + } + chan[c.chan].curMidiNote=-1; + break; + case DIV_CMD_INSTRUMENT: + if (chan[c.chan].lastIns!=c.value) { + output->midiOut->send(TAMidiMessage(0xc0|(c.chan&15),c.value,0)); + } + break; + case DIV_CMD_VOLUME: + if (chan[c.chan].curMidiNote>=0 && chan[c.chan].midiAftertouch) { + chan[c.chan].midiAftertouch=false; + output->midiOut->send(TAMidiMessage(0xa0|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); + } + break; + case DIV_CMD_PITCH: { + int pitchBend=8192+(c.value<<5); + if (pitchBend<0) pitchBend=0; + if (pitchBend>16383) pitchBend=16383; + if (pitchBend!=chan[c.chan].midiPitch) { + chan[c.chan].midiPitch=pitchBend; + output->midiOut->send(TAMidiMessage(0xe0|(c.chan&15),pitchBend&0x7f,pitchBend>>7)); + } + break; } - if (c.value!=DIV_NOTE_NULL) { - chan[c.chan].curMidiNote=c.value+12; - if (chan[c.chan].curMidiNote<0) chan[c.chan].curMidiNote=0; - if (chan[c.chan].curMidiNote>127) chan[c.chan].curMidiNote=127; + case DIV_CMD_PANNING: { + int pan=convertPanSplitToLinearLR(c.value,c.value2,127); + output->midiOut->send(TAMidiMessage(0xb0|(c.chan&15),0x0a,pan)); + break; } - output->midiOut->send(TAMidiMessage(0x90|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); - break; - case DIV_CMD_NOTE_OFF: - case DIV_CMD_NOTE_OFF_ENV: - if (chan[c.chan].curMidiNote>=0) { - output->midiOut->send(TAMidiMessage(0x80|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); + case DIV_CMD_HINT_PORTA: { + if (c.value2>0) { + if (c.value<=0 || c.value>=255) break; + //output->midiOut->send(TAMidiMessage(0x80|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); + int target=c.value+12; + if (target<0) target=0; + if (target>127) target=127; + + if (chan[c.chan].curMidiNote>=0) { + output->midiOut->send(TAMidiMessage(0xb0|(c.chan&15),0x54,chan[c.chan].curMidiNote)); + } + output->midiOut->send(TAMidiMessage(0xb0|(c.chan&15),0x05,1/*MIN(0x7f,c.value2/4)*/)); + output->midiOut->send(TAMidiMessage(0xb0|(c.chan&15),0x41,0x7f)); + + output->midiOut->send(TAMidiMessage(0x90|(c.chan&15),target,scaledVol)); + } else { + output->midiOut->send(TAMidiMessage(0xb0|(c.chan&15),0x41,0)); + } + break; } - chan[c.chan].curMidiNote=-1; - break; - case DIV_CMD_INSTRUMENT: - if (chan[c.chan].lastIns!=c.value) { - output->midiOut->send(TAMidiMessage(0xc0|(c.chan&15),c.value,0)); - } - break; - case DIV_CMD_VOLUME: - if (chan[c.chan].curMidiNote>=0 && chan[c.chan].midiAftertouch) { - chan[c.chan].midiAftertouch=false; - output->midiOut->send(TAMidiMessage(0xa0|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); - } - break; - case DIV_CMD_PITCH: { - int pitchBend=8192+(c.value<<5); - if (pitchBend<0) pitchBend=0; - if (pitchBend>16383) pitchBend=16383; - if (pitchBend!=chan[c.chan].midiPitch) { - chan[c.chan].midiPitch=pitchBend; - output->midiOut->send(TAMidiMessage(0xe0|(c.chan&15),pitchBend&0x7f,pitchBend>>7)); - } - break; + default: + break; } - default: - break; } } } @@ -1055,11 +1082,6 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { cycles++; } - // MIDI clock - if (output) if (!skipping && output->midiOut!=NULL) { - //output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0)); - } - if (!pendingNotes.empty()) { bool isOn[DIV_MAX_CHANS]; memset(isOn,0,DIV_MAX_CHANS*sizeof(bool)); @@ -1106,6 +1128,12 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { if (!freelance) { if (--subticks<=0) { subticks=tickMult; + + // MIDI clock + if (output) if (!skipping && output->midiOut!=NULL && midiOutClock) { + output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0)); + } + if (stepPlay!=1) { tempoAccum+=curSubSong->virtualTempoN; while (tempoAccum>=curSubSong->virtualTempoD) { diff --git a/src/gui/gui.h b/src/gui/gui.h index a873f843..76a25efd 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1195,6 +1195,8 @@ class FurnaceGUI { int channelFeedbackStyle; int channelFont; int channelTextCenter; + int midiOutClock; + int midiOutMode; int maxRecentFile; unsigned int maxUndoSteps; String mainFontPath; @@ -1318,6 +1320,8 @@ class FurnaceGUI { channelFeedbackStyle(1), channelFont(1), channelTextCenter(1), + midiOutClock(0), + midiOutMode(1), maxRecentFile(10), maxUndoSteps(100), mainFontPath(""), diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index cc3f044b..805072f1 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -955,6 +955,26 @@ void FurnaceGUI::drawSettings() { ImGui::EndTable(); } + ImGui::TreePop(); + } + if (ImGui::TreeNode("MIDI output settings")) { + ImGui::Text("Output mode:"); + if (ImGui::RadioButton("Off (use for TX81Z)",settings.midiOutMode==0)) { + settings.midiOutMode=0; + } + if (ImGui::RadioButton("Melodic",settings.midiOutMode==1)) { + settings.midiOutMode=1; + } + /* + if (ImGui::RadioButton("Light Show (use for Launchpad)",settings.midiOutMode==2)) { + settings.midiOutMode=2; + }*/ + + bool midiOutClockB=settings.midiOutClock; + if (ImGui::Checkbox("Send MIDI clock",&midiOutClockB)) { + settings.midiOutClock=midiOutClockB; + } + ImGui::TreePop(); } } @@ -2314,6 +2334,8 @@ void FurnaceGUI::syncSettings() { settings.channelFont=e->getConfInt("channelFont",1); settings.channelTextCenter=e->getConfInt("channelTextCenter",1); settings.maxRecentFile=e->getConfInt("maxRecentFile",10); + settings.midiOutClock=e->getConfInt("midiOutClock",0); + settings.midiOutMode=e->getConfInt("midiOutMode",1); clampSetting(settings.mainFontSize,2,96); clampSetting(settings.patFontSize,2,96); @@ -2415,6 +2437,8 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.channelFont,0,1); clampSetting(settings.channelTextCenter,0,1); clampSetting(settings.maxRecentFile,0,30); + clampSetting(settings.midiOutClock,0,1); + clampSetting(settings.midiOutMode,0,2); settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys","")); if (settings.initialSys.size()<4) { @@ -2572,6 +2596,8 @@ void FurnaceGUI::commitSettings() { e->setConf("channelFont",settings.channelFont); e->setConf("channelTextCenter",settings.channelTextCenter); e->setConf("maxRecentFile",settings.maxRecentFile); + e->setConf("midiOutClock",settings.midiOutClock); + e->setConf("midiOutMode",settings.midiOutMode); // colors for (int i=0; i Date: Mon, 26 Sep 2022 01:48:09 -0500 Subject: [PATCH 6/9] Game Boy: fix zombie mode and macro speed --- src/engine/platform/gb.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index fea89c71..7c1c5d25 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -432,7 +432,11 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].envVol=chan[c.chan].vol; chan[c.chan].soManyHacksToMakeItDefleCompatible=true; } else if (c.chan!=2) { - chan[c.chan].envVol=chan[c.chan].vol; + if (chan[c.chan].std.vol.will && !chan[c.chan].std.vol.finished) { + chan[c.chan].outVol=VOL_SCALE_LINEAR(chan[c.chan].vol&15,MIN(15,chan[c.chan].std.vol.val),15); + } + chan[c.chan].envVol=chan[c.chan].outVol; + if (!chan[c.chan].keyOn) chan[c.chan].killIt=true; chan[c.chan].freqChanged=true; } From 607e3c9339fc37b651c7d5b3f7d5315c03b03ab5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 26 Sep 2022 02:51:16 -0500 Subject: [PATCH 7/9] fix the crashes --- src/engine/platform/rf5c68.cpp | 11 ++++++----- src/engine/platform/snes.cpp | 7 +++++-- src/engine/platform/su.cpp | 2 +- src/engine/platform/ymz280b.cpp | 9 ++++++--- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/engine/platform/rf5c68.cpp b/src/engine/platform/rf5c68.cpp index e462e3d8..dccd0fd2 100644 --- a/src/engine/platform/rf5c68.cpp +++ b/src/engine/platform/rf5c68.cpp @@ -122,9 +122,6 @@ void DivPlatformRF5C68::tick(bool sysTick) { } else { chan[i].audPos=0; } - // TODO: BANG BANG BANG - // AAAAAAAAAAAAAAAAAAA - // ASGDJFJFSDGL;ASDHFKJLSHFLKAJSFHKLJVSJ if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { unsigned char keyon=regPool[8]&~(1<calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE)); if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].keyOn) { - unsigned int start=sampleOffRFC[chan[i].sample]; - unsigned int loop=start+s->length8; + unsigned int start=0; + unsigned int loop=0; + if (chan[i].sample>=0 && chan[i].samplesong.sampleLen) { + start=sampleOffRFC[chan[i].sample]; + loop=start+s->length8; + } if (chan[i].audPos>0) { start=start+MIN(chan[i].audPos,s->length8); } diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index 3686980f..b552cd4b 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -178,7 +178,6 @@ void DivPlatformSNES::tick(bool sysTick) { updateWave(i); } } - // TODO: THIS WILL CRASH IF THE SAMPLE IS INVALID!!! if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { DivSample* s=parent->getSample(chan[i].sample); double off=(s->centerRate>=1)?((double)s->centerRate/8363.0):1.0; @@ -191,7 +190,7 @@ void DivPlatformSNES::tick(bool sysTick) { if (chan[i].useWave) { start=waveTableAddr(i); loop=start; - } else { + } else if (chan[i].sample>=0 && chan[i].samplesong.sampleLen) { start=sampleOff[chan[i].sample]; end=MIN(start+MAX(s->lengthBRR,1),getSampleMemCapacity()); loop=MAX(start,end-1); @@ -201,6 +200,10 @@ void DivPlatformSNES::tick(bool sysTick) { if (s->loopStart>=0) { loop=start+s->loopStart/16*9; } + } else { + start=0; + end=0; + loop=0; } sampleMem[tabAddr+0]=start&0xff; sampleMem[tabAddr+1]=start>>8; diff --git a/src/engine/platform/su.cpp b/src/engine/platform/su.cpp index 25fefa20..cd0aea34 100644 --- a/src/engine/platform/su.cpp +++ b/src/engine/platform/su.cpp @@ -163,7 +163,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) { DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU); int sNum=ins->amiga.getSample(chan[i].note); DivSample* sample=parent->getSample(sNum); - if (sample!=NULL) { + if (sample!=NULL && sNum>=0 && sNumsong.sampleLen) { unsigned int sampleEnd=sampleOffSU[sNum]+(sample->getLoopEndPosition()); unsigned int off=sampleOffSU[sNum]+chan[i].hasOffset; chan[i].hasOffset=0; diff --git a/src/engine/platform/ymz280b.cpp b/src/engine/platform/ymz280b.cpp index 2e617c76..e89c3f9b 100644 --- a/src/engine/platform/ymz280b.cpp +++ b/src/engine/platform/ymz280b.cpp @@ -145,12 +145,15 @@ void DivPlatformYMZ280B::tick(bool sysTick) { // ADPCM has half the range if (s->depth==DIV_SAMPLE_DEPTH_YMZ_ADPCM && chan[i].freq>255) chan[i].freq=255; ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0)|(chan[i].freq>>8); - // TODO: AGAIN THIS WILL CRASH IF THE SAMPLE IS INVALID!!! if (chan[i].keyOn) { - unsigned int start=sampleOff[chan[i].sample]; + unsigned int start=0; unsigned int loopStart=0; unsigned int loopEnd=0; - unsigned int end=MIN(start+s->getCurBufLen(),getSampleMemCapacity()-1); + unsigned int end=0; + if (chan[i].sample>=0 && chan[i].samplesong.sampleLen) { + start=sampleOff[chan[i].sample]; + end=MIN(start+s->getCurBufLen(),getSampleMemCapacity()-1); + } if (chan[i].audPos>0) { switch (s->depth) { case DIV_SAMPLE_DEPTH_YMZ_ADPCM: start+=chan[i].audPos/2; break; From 5f91f0b09cbb91d18fc749cba03b23fe65ba0dd5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 26 Sep 2022 02:57:07 -0500 Subject: [PATCH 8/9] SegaPCM: what a mess --- src/engine/platform/segapcm.cpp | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/engine/platform/segapcm.cpp b/src/engine/platform/segapcm.cpp index 5cd4a8e8..8bec9f30 100644 --- a/src/engine/platform/segapcm.cpp +++ b/src/engine/platform/segapcm.cpp @@ -20,6 +20,7 @@ // TODO: new macro formula #include "segapcm.h" #include "../engine.h" +#include "../../ta-log.h" #include #include @@ -452,7 +453,36 @@ void DivPlatformSegaPCM::reset() { } void DivPlatformSegaPCM::renderSamples() { - // TODO: THIS MESS + size_t memPos=0; + + for (int i=0; isong.sampleLen; i++) { + DivSample* sample=parent->getSample(i); + unsigned int alignedSize=(sample->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)+0xff)&(~0xff); + if (alignedSize>65536) alignedSize=65536; + if ((memPos&0xff0000)!=((memPos+alignedSize)&0xff0000)) { + memPos=(memPos+0xffff)&0xff0000; + } + logV("- sample %d will be at %x with length %x",i,memPos,alignedSize); + if (memPos>=16777216) break; + sampleOffSegaPCM[i]=memPos; + unsigned int readPos=0; + for (unsigned int j=0; j=(unsigned int)sample->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)) { + if (sample->isLoopable()) { + readPos=sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT); + memPos++; + } else { + memPos++; + } + } else { + memPos++; + } + readPos++; + if (memPos>=16777216) break; + } + sample->loopOffP=readPos-sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT); + if (memPos>=16777216) break; + } } void DivPlatformSegaPCM::setFlags(unsigned int flags) { From e5b37db55a0ca3662ad1902010de29ee3dfd5118 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 26 Sep 2022 03:23:34 -0500 Subject: [PATCH 9/9] SNES: panning/wavetable fixes --- src/engine/platform/snes.cpp | 20 ++++++++++++-------- src/engine/platform/snes.h | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index b552cd4b..d8dcd374 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -83,7 +83,13 @@ void DivPlatformSNES::acquire(short* bufL, short* bufR, size_t start, size_t len bufL[h]=out[0]; bufR[h]=out[1]; for (int i=0; i<8; i++) { - oscBuf[i]->data[oscBuf[i]->needle++]=chOut[i*2]+chOut[i*2+1]; + int next=chOut[i*2]+chOut[i*2+1]; + if (next<-32768) next=-32768; + if (next>32767) next=32767; + next=(next*254)/MAX(1,globalVolL+globalVolR); + if (next<-32768) next=-32768; + if (next>32767) next=32767; + oscBuf[i]->data[oscBuf[i]->needle++]=next; } } } @@ -133,12 +139,10 @@ void DivPlatformSNES::tick(bool sysTick) { chan[i].freqChanged=true; } if (chan[i].std.panL.had) { - int val=chan[i].std.panL.val&0x7f; - chan[i].panL=(val<<1)|(val>>6); + chan[i].panL=chan[i].std.panL.val&0x7f; } if (chan[i].std.panR.had) { - int val=chan[i].std.panR.val&0x7f; - chan[i].panR=(val<<1)|(val>>6); + chan[i].panR=chan[i].std.panR.val&0x7f; } bool hasInverted=false; if (chan[i].std.ex1.had) { @@ -362,8 +366,8 @@ int DivPlatformSNES::dispatch(DivCommand c) { return chan[c.chan].vol; break; case DIV_CMD_PANNING: - chan[c.chan].panL=c.value; - chan[c.chan].panR=c.value2; + chan[c.chan].panL=c.value>>1; + chan[c.chan].panR=c.value2>>1; writeOutVol(c.chan); break; case DIV_CMD_PITCH: @@ -509,7 +513,7 @@ void DivPlatformSNES::reset() { chan[i]=Channel(); chan[i].std.setEngine(parent); chan[i].ws.setEngine(parent); - chan[i].ws.init(NULL,32,255); + chan[i].ws.init(NULL,32,15); writeOutVol(i); chWrite(i,4,i); // source number } diff --git a/src/engine/platform/snes.h b/src/engine/platform/snes.h index ad8048f3..4d05df83 100644 --- a/src/engine/platform/snes.h +++ b/src/engine/platform/snes.h @@ -75,7 +75,7 @@ class DivPlatformSNES: public DivDispatch { Channel chan[8]; DivDispatchOscBuffer* oscBuf[8]; bool isMuted[8]; - signed char globalVolL, globalVolR; + int globalVolL, globalVolR; unsigned char noiseFreq; size_t sampleTableBase; bool writeControl;