diff --git a/src/engine/platform/dave.cpp b/src/engine/platform/dave.cpp index b84ebb61e..ea72629f9 100644 --- a/src/engine/platform/dave.cpp +++ b/src/engine/platform/dave.cpp @@ -468,6 +468,7 @@ int DivPlatformDave::dispatch(DivCommand c) { chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: + if (c.chan<4) break; chan[c.chan].dacPos=c.value; chan[c.chan].setPos=true; break; diff --git a/src/engine/platform/lynx.cpp b/src/engine/platform/lynx.cpp index 1ea439beb..568a45cdc 100644 --- a/src/engine/platform/lynx.cpp +++ b/src/engine/platform/lynx.cpp @@ -135,7 +135,11 @@ void DivPlatformLynx::acquire(short** buf, size_t len) { if (isMuted[i]) { WRITE_OUTPUT(i,0); } else { - WRITE_OUTPUT(i,CLAMP((s->data8[chan[i].samplePos]*chan[i].outVol)>>7,-128,127)); + if (chan[i].samplePos<0 || chan[i].samplePos>=(int)s->samples) { + WRITE_OUTPUT(i,0); + } else { + WRITE_OUTPUT(i,CLAMP((s->data8[chan[i].samplePos]*chan[i].outVol)>>7,-128,127)); + } } chan[i].samplePos++; @@ -209,7 +213,11 @@ void DivPlatformLynx::tick(bool sysTick) { if (chan[i].std.phaseReset.val==1) { if (chan[i].pcm && chan[i].sample>=0 && chan[i].samplesong.sampleLen) { chan[i].sampleAccum=0; - chan[i].samplePos=0; + if (chan[i].setPos) { + chan[i].setPos=false; + } else { + chan[i].samplePos=0; + } } WRITE_LFSR(i, 0); WRITE_OTHER(i, 0); @@ -294,7 +302,11 @@ int DivPlatformLynx::dispatch(DivCommand c) { c.value=ins->amiga.getFreq(chan[c.chan].sampleNote); } chan[c.chan].sampleAccum=0; - chan[c.chan].samplePos=0; + if (chan[c.chan].setPos) { + chan[c.chan].setPos=false; + } else { + chan[c.chan].samplePos=0; + } } if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); @@ -400,6 +412,10 @@ int DivPlatformLynx::dispatch(DivCommand c) { 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); chan[c.chan].inPorta=c.value; break; + case DIV_CMD_SAMPLE_POS: + chan[c.chan].samplePos=c.value; + chan[c.chan].setPos=true; + break; case DIV_CMD_GET_VOLMAX: return 127; break; diff --git a/src/engine/platform/mmc5.cpp b/src/engine/platform/mmc5.cpp index 49a19e8c8..71f7fd39a 100644 --- a/src/engine/platform/mmc5.cpp +++ b/src/engine/platform/mmc5.cpp @@ -49,7 +49,7 @@ void DivPlatformMMC5::acquire(short** buf, size_t len) { dacPeriod+=dacRate; if (dacPeriod>=rate) { DivSample* s=parent->getSample(dacSample); - if (s->samples>0) { + if (s->samples>0 && dacPossamples) { if (!isMuted[2]) { rWrite(0x5011,((unsigned char)s->data8[dacPos]+0x80)); } @@ -192,7 +192,11 @@ int DivPlatformMMC5::dispatch(DivCommand c) { } else { if (dumpWrites) addWrite(0xffff0000,dacSample); } - dacPos=0; + if (chan[c.chan].setPos) { + chan[c.chan].setPos=false; + } else { + dacPos=0; + } dacPeriod=0; if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false); @@ -214,7 +218,11 @@ int DivPlatformMMC5::dispatch(DivCommand c) { } else { if (dumpWrites) addWrite(0xffff0000,dacSample); } - dacPos=0; + if (chan[c.chan].setPos) { + chan[c.chan].setPos=false; + } else { + dacPos=0; + } dacPeriod=0; dacRate=parent->getSample(dacSample)->rate; if (dumpWrites) addWrite(0xffff0001,dacRate); @@ -307,6 +315,11 @@ int DivPlatformMMC5::dispatch(DivCommand c) { sampleBank=parent->song.sample.size()/12; } break; + case DIV_CMD_SAMPLE_POS: + if (c.chan!=2) break; + dacPos=c.value; + chan[c.chan].setPos=true; + break; case DIV_CMD_LEGATO: if (c.chan==2) { chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)),false); diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index d8c922cda..1156ad2a6 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -81,7 +81,7 @@ void DivPlatformNES::doWrite(unsigned short addr, unsigned char data) { dacPeriod+=dacRate; \ if (dacPeriod>=rate) { \ DivSample* s=parent->getSample(dacSample); \ - if (s->samples>0) { \ + if (s->samples>0 && dacPossamples) { \ if (!isMuted[4]) { \ unsigned char next=((unsigned char)s->data8[dacPos]+0x80)>>1; \ if (dacAntiClickOn && dacAntiClick=0 && dacSamplesong.sampleLen) { - unsigned int dpcmAddr=sampleOffDPCM[dacSample]; - unsigned int dpcmLen=parent->getSample(dacSample)->lengthDPCM>>4; + unsigned int dpcmAddr=sampleOffDPCM[dacSample]+(dacPos>>3); + int dpcmLen=(parent->getSample(dacSample)->lengthDPCM-(dacPos>>3))>>4; + if (dpcmLen<0) dpcmLen=0; if (dpcmLen>255) dpcmLen=255; goingToLoop=parent->getSample(dacSample)->isLoopable(); // write DPCM @@ -464,7 +465,11 @@ int DivPlatformNES::dispatch(DivCommand c) { } else { if (dumpWrites && !dpcmMode) addWrite(0xffff0000,dacSample); } - dacPos=0; + if (chan[c.chan].setPos) { + chan[c.chan].setPos=false; + } else { + dacPos=0; + } dacPeriod=0; if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false); @@ -486,14 +491,19 @@ int DivPlatformNES::dispatch(DivCommand c) { } else { if (dumpWrites && !dpcmMode) addWrite(0xffff0000,dacSample); } - dacPos=0; + if (chan[c.chan].setPos) { + chan[c.chan].setPos=false; + } else { + dacPos=0; + } dacPeriod=0; dacRate=parent->getSample(dacSample)->rate; if (dumpWrites && !dpcmMode) addWrite(0xffff0001,dacRate); chan[c.chan].furnaceDac=false; if (dpcmMode && !skipRegisterWrites) { - unsigned int dpcmAddr=sampleOffDPCM[dacSample]; - unsigned int dpcmLen=parent->getSample(dacSample)->lengthDPCM>>4; + unsigned int dpcmAddr=sampleOffDPCM[dacSample]+(dacPos>>3); + int dpcmLen=(parent->getSample(dacSample)->lengthDPCM-(dacPos>>3))>>4; + if (dpcmLen<0) dpcmLen=0; if (dpcmLen>255) dpcmLen=255; goingToLoop=parent->getSample(dacSample)->isLoopable(); // write DPCM @@ -682,6 +692,15 @@ int DivPlatformNES::dispatch(DivCommand c) { sampleBank=parent->song.sample.size()/12; } break; + case DIV_CMD_SAMPLE_POS: + if (c.chan!=4) break; + dacPos=c.value; + dpcmPos=c.value; + chan[c.chan].setPos=true; + if (chan[c.chan].active) { + chan[c.chan].keyOn=true; + } + break; case DIV_CMD_LEGATO: if (c.chan==3) break; if (c.chan==4) { @@ -777,6 +796,7 @@ void DivPlatformNES::reset() { dacPeriod=0; dacPos=0; + dpcmPos=0; dacRate=0; dacSample=-1; sampleBank=0; diff --git a/src/engine/platform/nes.h b/src/engine/platform/nes.h index d3b47f02c..cccbe0b18 100644 --- a/src/engine/platform/nes.h +++ b/src/engine/platform/nes.h @@ -44,7 +44,7 @@ class DivPlatformNES: public DivDispatch { Channel chan[5]; DivDispatchOscBuffer* oscBuf[5]; bool isMuted[5]; - int dacPeriod, dacRate; + int dacPeriod, dacRate, dpcmPos; unsigned int dacPos, dacAntiClick; int dacSample; unsigned char* dpcmMem; diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index 146b67ba5..dbc4fec46 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -62,7 +62,7 @@ void DivPlatformPCE::acquire(short** buf, size_t len) { chan[i].dacPeriod+=chan[i].dacRate; if (chan[i].dacPeriod>rate) { DivSample* s=parent->getSample(chan[i].dacSample); - if (s->samples<=0) { + if (s->samples<=0 || chan[i].dacPos>=s->samples) { chan[i].dacSample=-1; continue; } @@ -204,7 +204,11 @@ void DivPlatformPCE::tick(bool sysTick) { if (chan[i].std.phaseReset.had && chan[i].std.phaseReset.val==1) { if (chan[i].furnaceDac && chan[i].pcm) { if (chan[i].active && chan[i].dacSample>=0 && chan[i].dacSamplesong.sampleLen) { - chan[i].dacPos=0; + if (chan[i].setPos) { + chan[i].setPos=false; + } else { + chan[i].dacPos=0; + } chan[i].dacPeriod=0; chWrite(i,0x04,parent->song.disableSampleMacro?0xdf:(0xc0|chan[i].vol)); addWrite(0xffff0000+(i<<8),chan[i].dacSample); @@ -302,7 +306,11 @@ int DivPlatformPCE::dispatch(DivCommand c) { addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dacSample); } } - chan[c.chan].dacPos=0; + if (chan[c.chan].setPos) { + chan[c.chan].setPos=false; + } else { + chan[c.chan].dacPos=0; + } chan[c.chan].dacPeriod=0; if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); @@ -331,7 +339,11 @@ int DivPlatformPCE::dispatch(DivCommand c) { } else { if (dumpWrites) addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dacSample); } - chan[c.chan].dacPos=0; + if (chan[c.chan].setPos) { + chan[c.chan].setPos=false; + } else { + chan[c.chan].dacPos=0; + } chan[c.chan].dacPeriod=0; chan[c.chan].dacRate=parent->getSample(chan[c.chan].dacSample)->rate; if (dumpWrites) { @@ -457,6 +469,10 @@ int DivPlatformPCE::dispatch(DivCommand c) { sampleBank=parent->song.sample.size()/12; } break; + case DIV_CMD_SAMPLE_POS: + chan[c.chan].dacPos=c.value; + chan[c.chan].setPos=true; + break; case DIV_CMD_PANNING: { chan[c.chan].pan=(c.value&0xf0)|(c.value2>>4); chWrite(c.chan,0x05,isMuted[c.chan]?0:chan[c.chan].pan); diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index cdd8fc6b2..0b0401353 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -391,17 +391,23 @@ void DivPlatformQSound::tick(bool sysTick) { chan[i].freq=off*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,440.0,4096.0); if (chan[i].freq>0xefff) chan[i].freq=0xefff; if (chan[i].keyOn) { + if (chan[i].setPos) { + chan[i].setPos=false; + } else { + chan[i].audPos=0; + } + if (i<16) { rWrite(q1_reg_map[Q1V_BANK][i], qsound_bank); rWrite(q1_reg_map[Q1V_END][i], qsound_end); rWrite(q1_reg_map[Q1V_LOOP][i], qsound_loop); - rWrite(q1_reg_map[Q1V_START][i], qsound_addr); + rWrite(q1_reg_map[Q1V_START][i], qsound_addr+chan[i].audPos); rWrite(q1_reg_map[Q1V_PHASE][i], 0x8000); } else { rWrite(Q1A_KEYON+(i-16),0); rWrite(q1a_bank_map[i-16], qsound_bank); rWrite(q1a_end_map[i-16], qsound_end); - rWrite(q1a_start_map[i-16], qsound_addr); + rWrite(q1a_start_map[i-16], qsound_addr+chan[i].audPos); rWrite(Q1A_KEYON+(i-16),1); } //logV("ch %d bank=%04x, addr=%04x, end=%04x, loop=%04x!",i,qsound_bank,qsound_addr,qsound_end,qsound_loop); @@ -580,6 +586,13 @@ int DivPlatformQSound::dispatch(DivCommand c) { 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); chan[c.chan].inPorta=c.value; break; + case DIV_CMD_SAMPLE_POS: + chan[c.chan].audPos=c.value; + chan[c.chan].setPos=true; + if (chan[c.chan].active) { + chan[c.chan].keyOn=true; + } + break; case DIV_CMD_GET_VOLMAX: return 255; break; diff --git a/src/engine/platform/qsound.h b/src/engine/platform/qsound.h index be797bf77..ab4ae36af 100644 --- a/src/engine/platform/qsound.h +++ b/src/engine/platform/qsound.h @@ -29,6 +29,7 @@ class DivPlatformQSound: public DivDispatch { int sample, wave; int panning; int echo; + int audPos; bool useWave, surround, isNewQSound, setPos; Channel(): SharedChannel(255), @@ -37,6 +38,7 @@ class DivPlatformQSound: public DivDispatch { wave(-1), panning(0x10), echo(0), + audPos(0), useWave(false), surround(true), isNewQSound(false), diff --git a/src/engine/platform/segapcm.cpp b/src/engine/platform/segapcm.cpp index 3f8598c43..d3c8a99b0 100644 --- a/src/engine/platform/segapcm.cpp +++ b/src/engine/platform/segapcm.cpp @@ -128,41 +128,47 @@ void DivPlatformSegaPCM::tick(bool sysTick) { if (chan[i].keyOn || chan[i].keyOff) { if (chan[i].keyOn && !chan[i].keyOff) { rWrite(0x86+(i<<3),3); - chan[i].pcm.pos=0; + if (chan[i].setPos) { + chan[i].setPos=false; + } else { + chan[i].pcm.pos=0; + } if (chan[i].furnacePCM) { DivSample* s=parent->getSample(chan[i].pcm.sample); int loopStart=s->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT); int actualLength=(s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)); if (actualLength>0xfeff) actualLength=0xfeff; - rWrite(0x86+(i<<3),3+((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); - rWrite(0x84+(i<<3),(sampleOffSegaPCM[chan[i].pcm.sample])&0xff); - rWrite(0x85+(i<<3),(sampleOffSegaPCM[chan[i].pcm.sample]>>8)&0xff); + int actualPos=sampleOffSegaPCM[chan[i].pcm.sample]+chan[i].pcm.pos; + rWrite(0x86+(i<<3),3+((actualPos>>16)<<3)); + rWrite(0x84+(i<<3),(actualPos)&0xff); + rWrite(0x85+(i<<3),(actualPos>>8)&0xff); rWrite(6+(i<<3),sampleEndSegaPCM[chan[i].pcm.sample]); if (!s->isLoopable()) { - rWrite(0x86+(i<<3),2+((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); + rWrite(0x86+(i<<3),2+((actualPos>>16)<<3)); } else { - int loopPos=(sampleOffSegaPCM[chan[i].pcm.sample]&0xffff)+loopStart; - logV("sampleOff: %x loopPos: %x",sampleOffSegaPCM[chan[i].pcm.sample],loopPos); + int loopPos=(actualPos&0xffff)+loopStart; + logV("sampleOff: %x loopPos: %x",actualPos,loopPos); rWrite(4+(i<<3),loopPos&0xff); rWrite(5+(i<<3),(loopPos>>8)&0xff); - rWrite(0x86+(i<<3),((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); + rWrite(0x86+(i<<3),((actualPos>>16)<<3)); } } else { DivSample* s=parent->getSample(chan[i].pcm.sample); int loopStart=s->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT); int actualLength=(s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)); if (actualLength>0xfeff) actualLength=0xfeff; - rWrite(0x86+(i<<3),3+((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); - rWrite(0x84+(i<<3),(sampleOffSegaPCM[chan[i].pcm.sample])&0xff); - rWrite(0x85+(i<<3),(sampleOffSegaPCM[chan[i].pcm.sample]>>8)&0xff); + int actualPos=sampleOffSegaPCM[chan[i].pcm.sample]+chan[i].pcm.pos; + rWrite(0x86+(i<<3),3+((actualPos>>16)<<3)); + rWrite(0x84+(i<<3),(actualPos)&0xff); + rWrite(0x85+(i<<3),(actualPos>>8)&0xff); rWrite(6+(i<<3),sampleEndSegaPCM[chan[i].pcm.sample]); if (!s->isLoopable()) { - rWrite(0x86+(i<<3),2+((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); + rWrite(0x86+(i<<3),2+((actualPos>>16)<<3)); } else { - int loopPos=(sampleOffSegaPCM[chan[i].pcm.sample]&0xffff)+loopStart; + int loopPos=(actualPos&0xffff)+loopStart; rWrite(4+(i<<3),loopPos&0xff); rWrite(5+(i<<3),(loopPos>>8)&0xff); - rWrite(0x86+(i<<3),((sampleOffSegaPCM[chan[i].pcm.sample]>>16)<<3)); + rWrite(0x86+(i<<3),((actualPos>>16)<<3)); } rWrite(7+(i<<3),chan[i].pcm.freq); } @@ -335,6 +341,13 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) { sampleBank=parent->song.sample.size()/12; } break; + case DIV_CMD_SAMPLE_POS: + chan[c.chan].pcm.pos=c.value; + chan[c.chan].setPos=true; + if (chan[c.chan].active) { + chan[c.chan].keyOn=true; + } + break; case DIV_CMD_MACRO_OFF: chan[c.chan].std.mask(c.value,true); break; diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index 39089ae32..6aa44b3e5 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -60,7 +60,7 @@ void DivPlatformSwan::acquire(short** buf, size_t len) { dacPeriod+=dacRate; while (dacPeriod>rate) { DivSample* s=parent->getSample(dacSample); - if (s->samples<=0) { + if (s->samples<=0 || dacPos>=s->samples) { dacSample=-1; dacPeriod=0; break; @@ -262,7 +262,11 @@ int DivPlatformSwan::dispatch(DivCommand c) { } if (pcm) { if (skipRegisterWrites) break; - dacPos=0; + if (setPos) { + setPos=false; + } else { + dacPos=0; + } dacPeriod=0; if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) { if (c.value!=DIV_NOTE_NULL) { @@ -435,6 +439,10 @@ int DivPlatformSwan::dispatch(DivCommand c) { sampleBank=parent->song.sample.size()/12; } break; + case DIV_CMD_SAMPLE_POS: + dacPos=c.value; + setPos=true; + break; case DIV_CMD_PANNING: { chan[c.chan].pan=(c.value&0xf0)|(c.value2>>4); calcAndWriteOutVol(c.chan,chan[c.chan].std.vol.will?chan[c.chan].std.vol.val:15); diff --git a/src/engine/platform/vera.cpp b/src/engine/platform/vera.cpp index fcd13b8ed..2e6180a95 100644 --- a/src/engine/platform/vera.cpp +++ b/src/engine/platform/vera.cpp @@ -56,6 +56,7 @@ const char** DivPlatformVERA::getRegisterSheet() { return regCheatSheetVERA; } +// TODO: possible sample offset latency... void DivPlatformVERA::acquire(short** buf, size_t len) { // both PSG part and PCM part output a full 16-bit range, putting bufL/R // argument right into both could cause an overflow @@ -63,7 +64,7 @@ void DivPlatformVERA::acquire(short** buf, size_t len) { size_t pos=0; DivSample* s=parent->getSample(chan[16].pcm.sample); while (len>0) { - if (s->samples>0) { + if (s->samples>0 && chan[16].pcm.possamples) { while (pcm_is_fifo_almost_empty(pcm)) { short tmp_l=0; short tmp_r=0; @@ -312,7 +313,11 @@ int DivPlatformVERA::dispatch(DivCommand c) { if (chan[16].pcm.sample<0 || chan[16].pcm.sample>=parent->song.sampleLen) { chan[16].pcm.sample=-1; } - chan[16].pcm.pos=0; + if (chan[16].pcm.setPos) { + chan[16].pcm.setPos=false; + } else { + chan[16].pcm.pos=0; + } DivSample* s=parent->getSample(chan[16].pcm.sample); unsigned char ctrl=0x90|chan[16].vol; // always stereo if (s->depth==DIV_SAMPLE_DEPTH_16BIT) { @@ -426,8 +431,13 @@ int DivPlatformVERA::dispatch(DivCommand c) { } break; } + case DIV_CMD_SAMPLE_POS: + if (c.chan!=16) break; + chan[c.chan].pcm.pos=c.value; + chan[c.chan].pcm.setPos=true; + break; case DIV_CMD_GET_VOLMAX: - if(c.chan<16) { + if (c.chan<16) { return 63; } else { return 15; diff --git a/src/engine/platform/vrc6.cpp b/src/engine/platform/vrc6.cpp index c87a747db..c1d17fb8f 100644 --- a/src/engine/platform/vrc6.cpp +++ b/src/engine/platform/vrc6.cpp @@ -54,7 +54,7 @@ void DivPlatformVRC6::acquire(short** buf, size_t len) { chan[i].dacPeriod+=chan[i].dacRate; if (chan[i].dacPeriod>rate) { DivSample* s=parent->getSample(chan[i].dacSample); - if (s->samples<=0) { + if (s->samples<=0 || chan[i].dacPos>=s->samples) { chan[i].dacSample=-1; chWrite(i,0,0); continue; @@ -185,7 +185,11 @@ void DivPlatformVRC6::tick(bool sysTick) { chWrite(i,0,isMuted[i]?0:0x80); addWrite(0xffff0000+(i<<8),chan[i].dacSample); } - chan[i].dacPos=0; + if (chan[i].setPos) { + chan[i].setPos=false; + } else { + chan[i].dacPos=0; + } chan[i].dacPeriod=0; chan[i].keyOn=true; } @@ -262,7 +266,11 @@ int DivPlatformVRC6::dispatch(DivCommand c) { addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dacSample); } } - chan[c.chan].dacPos=0; + if (chan[c.chan].setPos) { + chan[c.chan].setPos=false; + } else { + chan[c.chan].dacPos=0; + } chan[c.chan].dacPeriod=0; if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); @@ -290,7 +298,11 @@ int DivPlatformVRC6::dispatch(DivCommand c) { } else { if (dumpWrites) addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dacSample); } - chan[c.chan].dacPos=0; + if (chan[c.chan].setPos) { + chan[c.chan].setPos=false; + } else { + chan[c.chan].dacPos=0; + } chan[c.chan].dacPeriod=0; chan[c.chan].dacRate=parent->getSample(chan[c.chan].dacSample)->rate; if (dumpWrites) { @@ -405,6 +417,10 @@ int DivPlatformVRC6::dispatch(DivCommand c) { sampleBank=parent->song.sample.size()/12; } break; + case DIV_CMD_SAMPLE_POS: + chan[c.chan].dacPos=c.value; + chan[c.chan].setPos=true; + break; case DIV_CMD_LEGATO: chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0))); chan[c.chan].freqChanged=true;