Merge branch 'master' of https://github.com/tildearrow/furnace into k053260
This commit is contained in:
commit
523e08ed5c
35 changed files with 677 additions and 193 deletions
|
|
@ -178,7 +178,7 @@ bool DivConfig::loadFromFile(const char* path, bool createOnFail, bool redundanc
|
|||
logD("config does not exist");
|
||||
if (createOnFail) {
|
||||
logI("creating default config.");
|
||||
reportError(fmt::sprintf("Creating default config: %s",strerror(errno)));
|
||||
//reportError(fmt::sprintf("Creating default config: %s",strerror(errno)));
|
||||
return save(path,redundancy);
|
||||
} else {
|
||||
reportError(fmt::sprintf("COULD NOT LOAD CONFIG %s",strerror(errno)));
|
||||
|
|
@ -191,7 +191,7 @@ bool DivConfig::loadFromFile(const char* path, bool createOnFail, bool redundanc
|
|||
logD("config does not exist");
|
||||
if (createOnFail) {
|
||||
logI("creating default config.");
|
||||
reportError(fmt::sprintf("Creating default config: %s",strerror(errno)));
|
||||
//reportError(fmt::sprintf("Creating default config: %s",strerror(errno)));
|
||||
return save(path);
|
||||
} else {
|
||||
reportError(fmt::sprintf("COULD NOT LOAD CONFIG %s",strerror(errno)));
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
|
|||
return "03xx: Portamento";
|
||||
case 0x04:
|
||||
return "04xy: Vibrato (x: speed; y: depth)";
|
||||
case 0x05:
|
||||
return "05xy: Volume slide + vibrato (compatibility only!)";
|
||||
case 0x06:
|
||||
return "06xy: Volume slide + portamento (compatibility only!)";
|
||||
case 0x07:
|
||||
return "07xy: Tremolo (x: speed; y: depth)";
|
||||
case 0x08:
|
||||
|
|
@ -2419,6 +2423,13 @@ void DivEngine::stepOne(int row) {
|
|||
void DivEngine::stop() {
|
||||
BUSY_BEGIN;
|
||||
freelance=false;
|
||||
if (!playing) {
|
||||
//Send midi panic
|
||||
if (output) if (output->midiOut!=NULL) {
|
||||
output->midiOut->send(TAMidiMessage(TA_MIDI_CONTROL,0x7B,0));
|
||||
logV("Midi panic sent");
|
||||
}
|
||||
}
|
||||
playing=false;
|
||||
extValuePresent=false;
|
||||
endOfSong=false; // what?
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ struct DivChannelState {
|
|||
int delayOrder, delayRow, retrigSpeed, retrigTick;
|
||||
int vibratoDepth, vibratoRate, vibratoPos, vibratoPosGiant, vibratoDir, vibratoFine;
|
||||
int tremoloDepth, tremoloRate, tremoloPos;
|
||||
unsigned char arp, arpStage, arpTicks, panL, panR, panRL, panRR;
|
||||
unsigned char arp, arpStage, arpTicks, panL, panR, panRL, panRR, lastVibrato, lastPorta;
|
||||
bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff;
|
||||
bool arpYield, delayLocked, inPorta, scheduledSlideReset, shorthandPorta, wasShorthandPorta, noteOnInhibit, resetArp;
|
||||
bool wentThroughNote, goneThroughNote;
|
||||
|
|
@ -146,6 +146,8 @@ struct DivChannelState {
|
|||
panR(255),
|
||||
panRL(0),
|
||||
panRR(0),
|
||||
lastVibrato(0),
|
||||
lastPorta(0),
|
||||
doNote(false),
|
||||
legato(false),
|
||||
portaStop(false),
|
||||
|
|
|
|||
|
|
@ -23,11 +23,7 @@
|
|||
static DivPattern emptyPat;
|
||||
|
||||
DivPattern::DivPattern() {
|
||||
memset(data,-1,DIV_MAX_ROWS*DIV_MAX_COLS*sizeof(short));
|
||||
for (int i=0; i<DIV_MAX_ROWS; i++) {
|
||||
data[i][0]=0;
|
||||
data[i][1]=0;
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
DivPattern* DivChannelData::getPattern(int index, bool create) {
|
||||
|
|
@ -93,6 +89,14 @@ void DivPattern::copyOn(DivPattern* dest) {
|
|||
memcpy(dest->data,data,sizeof(data));
|
||||
}
|
||||
|
||||
void DivPattern::clear() {
|
||||
memset(data,-1,DIV_MAX_ROWS*DIV_MAX_COLS*sizeof(short));
|
||||
for (int i=0; i<DIV_MAX_ROWS; i++) {
|
||||
data[i][0]=0;
|
||||
data[i][1]=0;
|
||||
}
|
||||
}
|
||||
|
||||
DivChannelData::DivChannelData():
|
||||
effectCols(1) {
|
||||
memset(data,0,DIV_MAX_PATTERNS*sizeof(void*));
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@ struct DivPattern {
|
|||
String name;
|
||||
short data[DIV_MAX_ROWS][DIV_MAX_COLS];
|
||||
|
||||
/**
|
||||
* clear the pattern.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* copy this pattern to another.
|
||||
* @param dest the destination pattern.
|
||||
|
|
|
|||
|
|
@ -687,6 +687,7 @@ void DivPlatformAY8910::muteChannel(int ch, bool mute) {
|
|||
void DivPlatformAY8910::forceIns() {
|
||||
for (int i=0; i<3; i++) {
|
||||
chan[i].insChanged=true;
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
immWrite(0x0b,ayEnvPeriod);
|
||||
immWrite(0x0c,ayEnvPeriod>>8);
|
||||
|
|
|
|||
|
|
@ -1558,7 +1558,7 @@ DivMacroInt* DivPlatformOPL::getChanMacroInt(int ch) {
|
|||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformOPL::getOscBuffer(int ch) {
|
||||
if (oplType==759) {
|
||||
if (oplType==759 || chipType==8950) {
|
||||
if (ch>=totalChans+1) return NULL;
|
||||
} else {
|
||||
if (ch>=totalChans) return NULL;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ const char* regCheatSheetPV1000[]={
|
|||
"CH1_Pitch", "00",
|
||||
"CH2_Pitch", "01",
|
||||
"CH3_Pitch", "02",
|
||||
"Control", "03",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -38,11 +39,10 @@ const char** DivPlatformPV1000::getRegisterSheet() {
|
|||
|
||||
void DivPlatformPV1000::acquire(short** buf, size_t len) {
|
||||
for (size_t h=0; h<len; h++) {
|
||||
short samp;
|
||||
samp=d65010g031_sound_tick(&d65010g031,1);
|
||||
short samp=d65010g031_sound_tick(&d65010g031,1);
|
||||
buf[0][h]=samp;
|
||||
for (int i=0; i<3; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(d65010g031.square[i].out<<12);
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(d65010g031.out[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -73,17 +73,17 @@ void DivPlatformPV1000::tick(bool sysTick) {
|
|||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
chan[i].freq=0x3f-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<1) chan[i].freq=1;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].freq>62) chan[i].freq=62;
|
||||
if (isMuted[i]) chan[i].keyOn=false;
|
||||
if (chan[i].keyOn) {
|
||||
rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0 : chan[i].freq);
|
||||
rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0x3f : chan[i].freq);
|
||||
chan[i].keyOn=false;
|
||||
} else if (chan[i].freqChanged && chan[i].active && !isMuted[i]) {
|
||||
rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0 : chan[i].freq);
|
||||
rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0x3f : chan[i].freq);
|
||||
}
|
||||
if (chan[i].keyOff) {
|
||||
rWrite(i,0);
|
||||
rWrite(i,0x3f);
|
||||
chan[i].keyOff=false;
|
||||
}
|
||||
chan[i].freqChanged=false;
|
||||
|
|
@ -137,6 +137,13 @@ int DivPlatformPV1000::dispatch(DivCommand c) {
|
|||
chan[c.chan].pitch=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
case DIV_CMD_STD_NOISE_MODE: // ring modulation
|
||||
if (c.value&1) {
|
||||
rWrite(3,3);
|
||||
} else {
|
||||
rWrite(3,2);
|
||||
}
|
||||
break;
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int destFreq=NOTE_PERIODIC(c.value2);
|
||||
bool return2=false;
|
||||
|
|
@ -224,16 +231,21 @@ unsigned char* DivPlatformPV1000::getRegisterPool() {
|
|||
}
|
||||
|
||||
int DivPlatformPV1000::getRegisterPoolSize() {
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
void DivPlatformPV1000::reset() {
|
||||
memset(regPool,0,3);
|
||||
memset(regPool,0,4);
|
||||
for (int i=0; i<3; i++) {
|
||||
chan[i]=Channel();
|
||||
chan[i].std.setEngine(parent);
|
||||
}
|
||||
d65010g031_reset(&d65010g031);
|
||||
// mute
|
||||
rWrite(0,0x3f);
|
||||
rWrite(1,0x3f);
|
||||
rWrite(2,0x3f);
|
||||
rWrite(3,2);
|
||||
}
|
||||
|
||||
int DivPlatformPV1000::getOutputCount() {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class DivPlatformPV1000: public DivDispatch {
|
|||
DivDispatchOscBuffer* oscBuf[3];
|
||||
bool isMuted[3];
|
||||
|
||||
unsigned char regPool[3];
|
||||
unsigned char regPool[4];
|
||||
d65010g031_t d65010g031;
|
||||
friend void putDispatchChip(void*,int);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
|
|
|||
|
|
@ -151,8 +151,8 @@ void DivPlatformRF5C68::tick(bool sysTick) {
|
|||
if (s->isLoopable()) {
|
||||
loop=start+s->loopStart;
|
||||
}
|
||||
start=MIN(start,getSampleMemCapacity()-31);
|
||||
loop=MIN(loop,getSampleMemCapacity()-31);
|
||||
start=MIN(start,getSampleMemCapacity()-32);
|
||||
loop=MIN(loop,getSampleMemCapacity()-32);
|
||||
rWrite(8,keyoff); // force keyoff first
|
||||
chWrite(i,6,start>>8);
|
||||
chWrite(i,4,loop&0xff);
|
||||
|
|
@ -425,7 +425,7 @@ void DivPlatformRF5C68::renderSamples(int sysID) {
|
|||
}
|
||||
|
||||
int length=s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT);
|
||||
int actualLength=MIN((int)(getSampleMemCapacity()-memPos)-31,length);
|
||||
int actualLength=MIN((int)(getSampleMemCapacity()-memPos)-32,length);
|
||||
if (actualLength>0) {
|
||||
sampleOffRFC[i]=memPos;
|
||||
for (int j=0; j<actualLength; j++) {
|
||||
|
|
@ -435,8 +435,8 @@ void DivPlatformRF5C68::renderSamples(int sysID) {
|
|||
sampleMem[memPos++]=(val>0)?(val|0x80):(0-val);
|
||||
}
|
||||
// write end of sample marker
|
||||
memset(&sampleMem[memPos],0xff,31);
|
||||
memPos+=31;
|
||||
memset(&sampleMem[memPos],0xff,32);
|
||||
memPos+=32;
|
||||
}
|
||||
if (actualLength<length) {
|
||||
logW("out of RF5C68 PCM memory for sample %d!",i);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle)
|
|||
{
|
||||
if (square->period > 0)
|
||||
{
|
||||
int period = d65010g031_max(1, (0x3f - square->period));
|
||||
const int period = square->period;
|
||||
square->counter += cycle;
|
||||
while (square->counter >= period)
|
||||
{
|
||||
|
|
@ -82,9 +82,9 @@ int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle)
|
|||
// this is the bit I altered
|
||||
// THIS IS **NOT** THE ORIGINAL SOFTWARE! I am plainly marking it as such!
|
||||
const int d65Volumes[3]={
|
||||
3840,
|
||||
5120,
|
||||
8192
|
||||
3840, // -6dB
|
||||
5120, // -3dB
|
||||
8192 // 0dB
|
||||
};
|
||||
|
||||
int d65010g031_sound_tick(struct d65010g031_t *d65010g031, const int cycle)
|
||||
|
|
@ -92,7 +92,29 @@ int d65010g031_sound_tick(struct d65010g031_t *d65010g031, const int cycle)
|
|||
int out = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
out += d65010g031_square_tick(&d65010g031->square[i], cycle)?d65Volumes[i]:-d65Volumes[i];
|
||||
d65010g031->out[i] = 0;
|
||||
}
|
||||
if (d65010g031->ctrl & 2)
|
||||
{
|
||||
if (d65010g031->ctrl & 1) // ring modulation
|
||||
{
|
||||
int sout[3] = {
|
||||
d65010g031_square_tick(&d65010g031->square[0], cycle),
|
||||
d65010g031_square_tick(&d65010g031->square[1], cycle),
|
||||
d65010g031_square_tick(&d65010g031->square[2], cycle),
|
||||
};
|
||||
d65010g031->out[0] = (sout[0] ^ sout[1]) ? d65Volumes[0] : -d65Volumes[0];
|
||||
d65010g031->out[1] = (sout[1] ^ sout[2]) ? d65Volumes[1] : -d65Volumes[1];
|
||||
d65010g031->out[2] = (sout[2] ? d65Volumes[2] : -d65Volumes[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
d65010g031->out[i] = d65010g031_square_tick(&d65010g031->square[i], cycle)?d65Volumes[i]:-d65Volumes[i];
|
||||
}
|
||||
}
|
||||
out = d65010g031->out[0] + d65010g031->out[1] + d65010g031->out[2];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
@ -105,12 +127,25 @@ void d65010g031_reset(struct d65010g031_t *d65010g031)
|
|||
d65010g031->square[i].counter = 0;
|
||||
d65010g031->square[i].out = 0;
|
||||
}
|
||||
d65010g031->ctrl = 0;
|
||||
}
|
||||
|
||||
void d65010g031_write(struct d65010g031_t *d65010g031, const unsigned char a, const unsigned char d)
|
||||
{
|
||||
if (a < 3)
|
||||
switch (a)
|
||||
{
|
||||
d65010g031->square[a].period = d & 0x3f;
|
||||
case 3:
|
||||
d65010g031->ctrl = d;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
const unsigned char per = (unsigned char)(~d) & 0x3f;
|
||||
if ((per == 0) && (d65010g031->square[a].period != 0))
|
||||
{
|
||||
d65010g031->square[a].out ^= 1;
|
||||
}
|
||||
d65010g031->square[a].period = per;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ struct d65010g031_square_t
|
|||
struct d65010g031_t
|
||||
{
|
||||
struct d65010g031_square_t square[3];
|
||||
signed short out[3];
|
||||
unsigned char ctrl;
|
||||
};
|
||||
|
||||
int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle);
|
||||
|
|
|
|||
|
|
@ -222,7 +222,8 @@ void DivPlatformX1_010::acquire(short** buf, size_t len) {
|
|||
if (stereo) buf[1][h]=tempR;
|
||||
|
||||
for (int i=0; i<16; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(x1_010.voice_out(i,0)+x1_010.voice_out(i,1))>>1;
|
||||
int vo=(x1_010.voice_out(i,0)+x1_010.voice_out(i,1))<<3;
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=CLAMP(vo,-32768,32767);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -680,6 +680,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
chan[i].inPorta=false;
|
||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||
} else {
|
||||
chan[i].lastPorta=effectVal;
|
||||
calledPorta=true;
|
||||
if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.buggyPortaAfterSlide) {
|
||||
chan[i].portaNote=chan[i].note;
|
||||
|
|
@ -700,11 +701,78 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
}
|
||||
break;
|
||||
case 0x04: // vibrato
|
||||
if (effectVal) chan[i].lastVibrato=effectVal;
|
||||
chan[i].vibratoDepth=effectVal&15;
|
||||
chan[i].vibratoRate=effectVal>>4;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate));
|
||||
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
|
||||
break;
|
||||
case 0x05: // vol slide + vibrato
|
||||
if (effectVal==0) {
|
||||
chan[i].vibratoDepth=0;
|
||||
chan[i].vibratoRate=0;
|
||||
} else {
|
||||
chan[i].vibratoDepth=chan[i].lastVibrato&15;
|
||||
chan[i].vibratoRate=chan[i].lastVibrato>>4;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate));
|
||||
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
|
||||
// TODO: non-0x-or-x0 value should be treated as 00
|
||||
if (effectVal!=0) {
|
||||
if ((effectVal&15)!=0) {
|
||||
chan[i].volSpeed=-(effectVal&15)*64;
|
||||
} else {
|
||||
chan[i].volSpeed=(effectVal>>4)*64;
|
||||
}
|
||||
// tremolo and vol slides are incompatible
|
||||
chan[i].tremoloDepth=0;
|
||||
chan[i].tremoloRate=0;
|
||||
} else {
|
||||
chan[i].volSpeed=0;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
|
||||
break;
|
||||
case 0x06: // vol slide + porta
|
||||
if (effectVal==0 || chan[i].lastPorta==0) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0)));
|
||||
chan[i].inPorta=false;
|
||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||
} else {
|
||||
calledPorta=true;
|
||||
if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.buggyPortaAfterSlide) {
|
||||
chan[i].portaNote=chan[i].note;
|
||||
chan[i].portaSpeed=-1;
|
||||
} else {
|
||||
chan[i].portaNote=chan[i].note;
|
||||
chan[i].portaSpeed=chan[i].lastPorta;
|
||||
chan[i].inPorta=true;
|
||||
chan[i].wasShorthandPorta=false;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0)));
|
||||
chan[i].portaStop=true;
|
||||
if (chan[i].keyOn) chan[i].doNote=false;
|
||||
chan[i].stopOnOff=song.stopPortaOnNoteOff; // what?!
|
||||
chan[i].scheduledSlideReset=false;
|
||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,1));
|
||||
lastSlide=0x1337; // i hate this so much
|
||||
}
|
||||
// TODO: non-0x-or-x0 value should be treated as 00
|
||||
if (effectVal!=0) {
|
||||
if ((effectVal&15)!=0) {
|
||||
chan[i].volSpeed=-(effectVal&15)*64;
|
||||
} else {
|
||||
chan[i].volSpeed=(effectVal>>4)*64;
|
||||
}
|
||||
// tremolo and vol slides are incompatible
|
||||
chan[i].tremoloDepth=0;
|
||||
chan[i].tremoloRate=0;
|
||||
} else {
|
||||
chan[i].volSpeed=0;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
|
||||
break;
|
||||
case 0x07: // tremolo
|
||||
// TODO
|
||||
// this effect is really weird. i thought it would alter the tremolo depth but turns out it's completely different
|
||||
|
|
@ -1125,25 +1193,47 @@ void DivEngine::nextRow() {
|
|||
bool wantPreNote=false;
|
||||
if (disCont[dispatchOfChan[i]].dispatch!=NULL) {
|
||||
wantPreNote=disCont[dispatchOfChan[i]].dispatch->getWantPreNote();
|
||||
if (wantPreNote) dispatchCmd(DivCommand(DIV_CMD_PRE_NOTE,i,ticks));
|
||||
if (wantPreNote) {
|
||||
int addition=0;
|
||||
for (int j=0; j<curPat[i].effectCols; j++) {
|
||||
if (pat->data[curRow][4+(j<<1)]==0xed) {
|
||||
if (pat->data[curRow][5+(j<<1)]>0) {
|
||||
addition=pat->data[curRow][5+(j<<1)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_PRE_NOTE,i,ticks+addition));
|
||||
}
|
||||
}
|
||||
|
||||
if (song.oneTickCut) {
|
||||
bool doPrepareCut=true;
|
||||
int addition=0;
|
||||
|
||||
for (int j=0; j<curPat[i].effectCols; j++) {
|
||||
if (pat->data[curRow][4+(j<<1)]==0x03) {
|
||||
doPrepareCut=false;
|
||||
break;
|
||||
}
|
||||
if (pat->data[curRow][4+(j<<1)]==0x06) {
|
||||
doPrepareCut=false;
|
||||
break;
|
||||
}
|
||||
if (pat->data[curRow][4+(j<<1)]==0xea) {
|
||||
if (pat->data[curRow][5+(j<<1)]>0) {
|
||||
doPrepareCut=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pat->data[curRow][4+(j<<1)]==0xed) {
|
||||
if (pat->data[curRow][5+(j<<1)]>0) {
|
||||
addition=pat->data[curRow][5+(j<<1)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (doPrepareCut && !wantPreNote && chan[i].cut<=0) chan[i].cut=ticks;
|
||||
if (doPrepareCut && !wantPreNote && chan[i].cut<=0) chan[i].cut=ticks+addition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -892,10 +892,10 @@ bool DivSample::resampleBlep(double r) {
|
|||
}
|
||||
}
|
||||
for (int i=0; i<finalCount; i++) {
|
||||
float result=floatData[i]+data16[i];
|
||||
float result=floatData[i]+data8[i];
|
||||
if (result<-128) result=-128;
|
||||
if (result>127) result=127;
|
||||
data16[i]=round(result);
|
||||
data8[i]=round(result);
|
||||
}
|
||||
}
|
||||
delete[] floatData;
|
||||
|
|
|
|||
|
|
@ -1839,7 +1839,11 @@ void DivEngine::registerSystems() {
|
|||
{"Square 1", "Square 2", "Square 3"},
|
||||
{"S1", "S2", "S3"},
|
||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
||||
{DIV_INS_PV1000, DIV_INS_PV1000, DIV_INS_PV1000}
|
||||
{DIV_INS_PV1000, DIV_INS_PV1000, DIV_INS_PV1000},
|
||||
{},
|
||||
{
|
||||
{0x10, {DIV_CMD_STD_NOISE_MODE, "10xx: Set ring modulation (0: disable, 1: enable)"}}
|
||||
}
|
||||
);
|
||||
|
||||
sysDefs[DIV_SYSTEM_SFX_BEEPER_QUADTONE]=new DivSysDef(
|
||||
|
|
|
|||
|
|
@ -1083,6 +1083,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
|
||||
bool trailing=false;
|
||||
bool beenOneLoopAlready=false;
|
||||
bool mayWriteRate=(fmod(curSubSong->hz,1.0)<0.00001 || fmod(curSubSong->hz,1.0)>0.99999);
|
||||
int countDown=MAX(0,trailingTicks)+1;
|
||||
|
||||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||
|
|
@ -2399,6 +2400,9 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
w->writeI(0);
|
||||
w->writeI(0);
|
||||
}
|
||||
if (mayWriteRate) {
|
||||
w->writeI(round(curSubSong->hz));
|
||||
}
|
||||
w->seek(0x34,SEEK_SET);
|
||||
w->writeI(songOff-0x34);
|
||||
if (version>=0x170) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue