Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt
* 'master' of https://github.com/tildearrow/furnace: dev90 - linear pitch macro option dev89 - C64: add test/gate macro YMU759: update system definition more changes to autoNoteOn SoundUnit: ring modulation GUI: improve the maximize auto-detection a bit GUI: possibly remember maximized state NES: fix audio resolution being too low update to-do list SoundUnit: more stuff SoundUnit: max cutoff 16383 effectRows -> effectCols GUI: rename Amiga/Sample to Sample This is not a sample properties table Define the compact wave editor Menu option, settings file # Conflicts: # src/gui/insEdit.cpp
This commit is contained in:
commit
3956b2cd30
1
TODO.md
1
TODO.md
|
@ -37,6 +37,7 @@
|
||||||
- volume commands should work on Game Boy
|
- volume commands should work on Game Boy
|
||||||
- macro editor menu
|
- macro editor menu
|
||||||
- refactor sysDef.cpp
|
- refactor sysDef.cpp
|
||||||
|
- effect/postEffect refactor
|
||||||
- add another FM editor layout
|
- add another FM editor layout
|
||||||
- try to find out why does VSlider not accept keyboard input
|
- try to find out why does VSlider not accept keyboard input
|
||||||
- finish lock layout
|
- finish lock layout
|
||||||
|
|
|
@ -29,6 +29,9 @@ furthermore, an `or reserved` indicates this field is always present, but is res
|
||||||
|
|
||||||
the format versions are:
|
the format versions are:
|
||||||
|
|
||||||
|
- 90: Furnace dev90
|
||||||
|
- 89: Furnace dev89
|
||||||
|
- 88: Furnace dev88
|
||||||
- 87: Furnace dev87
|
- 87: Furnace dev87
|
||||||
- 86: Furnace dev86
|
- 86: Furnace dev86
|
||||||
- 85: Furnace dev85
|
- 85: Furnace dev85
|
||||||
|
@ -280,7 +283,8 @@ size | description
|
||||||
1 | new Sega PCM (with macros and proper vol/pan) (>=84) or reserved
|
1 | new Sega PCM (with macros and proper vol/pan) (>=84) or reserved
|
||||||
1 | weird f-num/block-based chip pitch slides (>=85) or reserved
|
1 | weird f-num/block-based chip pitch slides (>=85) or reserved
|
||||||
1 | SN duty macro always resets phase (>=86) or reserved
|
1 | SN duty macro always resets phase (>=86) or reserved
|
||||||
20 | reserved
|
1 | pitch macro is linear (>=90) or reserved
|
||||||
|
19 | reserved
|
||||||
```
|
```
|
||||||
|
|
||||||
# instrument
|
# instrument
|
||||||
|
@ -669,6 +673,8 @@ size | description
|
||||||
1 | parameter 2
|
1 | parameter 2
|
||||||
1 | parameter 3
|
1 | parameter 3
|
||||||
1 | parameter 4
|
1 | parameter 4
|
||||||
|
--- | **extra C64 data** (>=89)
|
||||||
|
1 | don't test/gate before new note
|
||||||
```
|
```
|
||||||
|
|
||||||
# wavetable
|
# wavetable
|
||||||
|
|
|
@ -140,7 +140,7 @@ void DivEngine::walkSong(int& loopOrder, int& loopRow, int& loopEnd) {
|
||||||
for (int j=nextRow; j<song.patLen; j++) {
|
for (int j=nextRow; j<song.patLen; j++) {
|
||||||
nextRow=0;
|
nextRow=0;
|
||||||
for (int k=0; k<chans; k++) {
|
for (int k=0; k<chans; k++) {
|
||||||
for (int l=0; l<song.pat[k].effectRows; l++) {
|
for (int l=0; l<song.pat[k].effectCols; l++) {
|
||||||
effectVal=pat[k]->data[j][5+(l<<1)];
|
effectVal=pat[k]->data[j][5+(l<<1)];
|
||||||
if (effectVal<0) effectVal=0;
|
if (effectVal<0) effectVal=0;
|
||||||
if (pat[k]->data[j][4+(l<<1)]==0x0d) {
|
if (pat[k]->data[j][4+(l<<1)]==0x0d) {
|
||||||
|
@ -945,21 +945,28 @@ unsigned short DivEngine::calcBaseFreqFNumBlock(double clock, double divider, in
|
||||||
return bf|(block<<bits);
|
return bf|(block<<bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivEngine::calcFreq(int base, int pitch, bool period, int octave) {
|
int DivEngine::calcFreq(int base, int pitch, bool period, int octave, int pitch2) {
|
||||||
if (song.linearPitch) {
|
if (song.linearPitch) {
|
||||||
// global pitch multiplier
|
// global pitch multiplier
|
||||||
int whatTheFuck=(1024+(globalPitch<<6)-(globalPitch<0?globalPitch-6:0));
|
int whatTheFuck=(1024+(globalPitch<<6)-(globalPitch<0?globalPitch-6:0));
|
||||||
if (whatTheFuck<1) whatTheFuck=1; // avoids division by zero but please kill me
|
if (whatTheFuck<1) whatTheFuck=1; // avoids division by zero but please kill me
|
||||||
|
if (song.pitchMacroIsLinear) {
|
||||||
|
pitch+=pitch2;
|
||||||
|
}
|
||||||
pitch+=2048;
|
pitch+=2048;
|
||||||
if (pitch<0) pitch=0;
|
if (pitch<0) pitch=0;
|
||||||
if (pitch>4095) pitch=4095;
|
if (pitch>4095) pitch=4095;
|
||||||
return period?
|
int ret=period?
|
||||||
((base*(reversePitchTable[pitch]))/whatTheFuck):
|
((base*(reversePitchTable[pitch]))/whatTheFuck):
|
||||||
(((base*(pitchTable[pitch]))>>10)*whatTheFuck)/1024;
|
(((base*(pitchTable[pitch]))>>10)*whatTheFuck)/1024;
|
||||||
|
if (!song.pitchMacroIsLinear) {
|
||||||
|
ret+=period?(-pitch2):pitch2;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
return period?
|
return period?
|
||||||
base-pitch:
|
base-pitch-pitch2:
|
||||||
base+((pitch*octave)>>1);
|
base+((pitch*octave)>>1)+pitch2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivEngine::play() {
|
void DivEngine::play() {
|
||||||
|
@ -2103,7 +2110,7 @@ void DivEngine::autoNoteOn(int ch, int ins, int note, int vol) {
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if ((ins==-1 || ins>=song.insLen || getChannelType(finalChan)==4 || getPreferInsType(finalChan)==getIns(ins)->type || getIns(ins)->type==DIV_INS_AMIGA) && chan[finalChan].midiNote==-1) {
|
if ((ins==-1 || ins>=song.insLen || getPreferInsType(finalChan)==getIns(ins)->type || getPreferInsSecondType(finalChan)==getIns(ins)->type) && chan[finalChan].midiNote==-1) {
|
||||||
chan[finalChan].midiNote=note;
|
chan[finalChan].midiNote=note;
|
||||||
pendingNotes.push(DivNoteEvent(finalChan,ins,note,vol,true));
|
pendingNotes.push(DivNoteEvent(finalChan,ins,note,vol,true));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -44,8 +44,8 @@
|
||||||
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
||||||
#define BUSY_END isBusy.unlock(); softLocked=false;
|
#define BUSY_END isBusy.unlock(); softLocked=false;
|
||||||
|
|
||||||
#define DIV_VERSION "dev88"
|
#define DIV_VERSION "dev90"
|
||||||
#define DIV_ENGINE_VERSION 88
|
#define DIV_ENGINE_VERSION 90
|
||||||
|
|
||||||
// for imports
|
// for imports
|
||||||
#define DIV_VERSION_MOD 0xff01
|
#define DIV_VERSION_MOD 0xff01
|
||||||
|
@ -470,7 +470,7 @@ class DivEngine {
|
||||||
unsigned short calcBaseFreqFNumBlock(double clock, double divider, int note, int bits);
|
unsigned short calcBaseFreqFNumBlock(double clock, double divider, int note, int bits);
|
||||||
|
|
||||||
// calculate frequency/period
|
// calculate frequency/period
|
||||||
int calcFreq(int base, int pitch, bool period=false, int octave=0);
|
int calcFreq(int base, int pitch, bool period=false, int octave=0, int pitch2=0);
|
||||||
|
|
||||||
// find song loop position
|
// find song loop position
|
||||||
void walkSong(int& loopOrder, int& loopRow, int& loopEnd);
|
void walkSong(int& loopOrder, int& loopRow, int& loopEnd);
|
||||||
|
@ -525,6 +525,9 @@ class DivEngine {
|
||||||
// get preferred instrument type
|
// get preferred instrument type
|
||||||
DivInstrumentType getPreferInsType(int ch);
|
DivInstrumentType getPreferInsType(int ch);
|
||||||
|
|
||||||
|
// get alternate instrument type
|
||||||
|
DivInstrumentType getPreferInsSecondType(int ch);
|
||||||
|
|
||||||
// get song system name
|
// get song system name
|
||||||
const char* getSongSystemName();
|
const char* getSongSystemName();
|
||||||
|
|
||||||
|
|
|
@ -637,14 +637,14 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
for (int i=0; i<getChannelCount(ds.system[0]); i++) {
|
for (int i=0; i<getChannelCount(ds.system[0]); i++) {
|
||||||
DivChannelData& chan=ds.pat[i];
|
DivChannelData& chan=ds.pat[i];
|
||||||
if (ds.version<0x0a) {
|
if (ds.version<0x0a) {
|
||||||
chan.effectRows=1;
|
chan.effectCols=1;
|
||||||
} else {
|
} else {
|
||||||
chan.effectRows=reader.readC();
|
chan.effectCols=reader.readC();
|
||||||
}
|
}
|
||||||
logD("%d fx rows: %d",i,chan.effectRows);
|
logD("%d fx rows: %d",i,chan.effectCols);
|
||||||
if (chan.effectRows>4 || chan.effectRows<1) {
|
if (chan.effectCols>4 || chan.effectCols<1) {
|
||||||
logE("invalid effect row count %d. are you sure everything is ok?",chan.effectRows);
|
logE("invalid effect column count %d. are you sure everything is ok?",chan.effectCols);
|
||||||
lastError="file is corrupt or unreadable at effect rows";
|
lastError="file is corrupt or unreadable at effect columns";
|
||||||
delete[] file;
|
delete[] file;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -694,7 +694,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
pat->data[k][3]=(pat->data[k][3]&3)*5;
|
pat->data[k][3]=(pat->data[k][3]&3)*5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int l=0; l<chan.effectRows; l++) {
|
for (int l=0; l<chan.effectCols; l++) {
|
||||||
// effect
|
// effect
|
||||||
pat->data[k][4+(l<<1)]=reader.readS();
|
pat->data[k][4+(l<<1)]=reader.readS();
|
||||||
pat->data[k][5+(l<<1)]=reader.readS();
|
pat->data[k][5+(l<<1)]=reader.readS();
|
||||||
|
@ -1011,6 +1011,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
if (ds.version<86) {
|
if (ds.version<86) {
|
||||||
ds.snDutyReset=true;
|
ds.snDutyReset=true;
|
||||||
}
|
}
|
||||||
|
if (ds.version<90) {
|
||||||
|
ds.pitchMacroIsLinear=false;
|
||||||
|
}
|
||||||
ds.isDMF=false;
|
ds.isDMF=false;
|
||||||
|
|
||||||
reader.readS(); // reserved
|
reader.readS(); // reserved
|
||||||
|
@ -1291,10 +1294,10 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<tchans; i++) {
|
for (int i=0; i<tchans; i++) {
|
||||||
ds.pat[i].effectRows=reader.readC();
|
ds.pat[i].effectCols=reader.readC();
|
||||||
if (ds.pat[i].effectRows<1 || ds.pat[i].effectRows>8) {
|
if (ds.pat[i].effectCols<1 || ds.pat[i].effectCols>8) {
|
||||||
logE("channel %d has zero or too many effect columns! (%d)",i,ds.pat[i].effectRows);
|
logE("channel %d has zero or too many effect columns! (%d)",i,ds.pat[i].effectCols);
|
||||||
lastError=fmt::sprintf("channel %d has too many effect columns! (%d)",i,ds.pat[i].effectRows);
|
lastError=fmt::sprintf("channel %d has too many effect columns! (%d)",i,ds.pat[i].effectCols);
|
||||||
delete[] file;
|
delete[] file;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1372,7 +1375,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
} else {
|
} else {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
for (int i=0; i<20; i++) {
|
if (ds.version>=90) {
|
||||||
|
ds.pitchMacroIsLinear=reader.readC();
|
||||||
|
} else {
|
||||||
|
reader.readC();
|
||||||
|
}
|
||||||
|
for (int i=0; i<19; i++) {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1572,7 +1580,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
pat->data[j][1]=reader.readS();
|
pat->data[j][1]=reader.readS();
|
||||||
pat->data[j][2]=reader.readS();
|
pat->data[j][2]=reader.readS();
|
||||||
pat->data[j][3]=reader.readS();
|
pat->data[j][3]=reader.readS();
|
||||||
for (int k=0; k<ds.pat[chan].effectRows; k++) {
|
for (int k=0; k<ds.pat[chan].effectCols; k++) {
|
||||||
pat->data[j][4+(k<<1)]=reader.readS();
|
pat->data[j][4+(k<<1)]=reader.readS();
|
||||||
pat->data[j][5+(k<<1)]=reader.readS();
|
pat->data[j][5+(k<<1)]=reader.readS();
|
||||||
}
|
}
|
||||||
|
@ -1973,7 +1981,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ds.pat[ch].effectRows=fxCols;
|
ds.pat[ch].effectCols=fxCols;
|
||||||
}
|
}
|
||||||
|
|
||||||
ds.pal=false;
|
ds.pal=false;
|
||||||
|
@ -1990,7 +1998,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
|
||||||
ds.chanShortName[i]=fmt::sprintf("C%d",i+1);
|
ds.chanShortName[i]=fmt::sprintf("C%d",i+1);
|
||||||
}
|
}
|
||||||
for(int i=chCount; i<ds.systemLen*4; i++) {
|
for(int i=chCount; i<ds.systemLen*4; i++) {
|
||||||
ds.pat[i].effectRows=1;
|
ds.pat[i].effectCols=1;
|
||||||
ds.chanShow[i]=false;
|
ds.chanShow[i]=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2294,7 +2302,7 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
w->writeC(song.pat[i].effectRows);
|
w->writeC(song.pat[i].effectCols);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
|
@ -2330,7 +2338,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
||||||
w->writeC(song.newSegaPCM);
|
w->writeC(song.newSegaPCM);
|
||||||
w->writeC(song.fbPortaPause);
|
w->writeC(song.fbPortaPause);
|
||||||
w->writeC(song.snDutyReset);
|
w->writeC(song.snDutyReset);
|
||||||
for (int i=0; i<20; i++) {
|
w->writeC(song.pitchMacroIsLinear);
|
||||||
|
for (int i=0; i<19; i++) {
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2384,7 +2393,7 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
||||||
w->writeS(pat->data[j][1]); // octave
|
w->writeS(pat->data[j][1]); // octave
|
||||||
w->writeS(pat->data[j][2]); // instrument
|
w->writeS(pat->data[j][2]); // instrument
|
||||||
w->writeS(pat->data[j][3]); // volume
|
w->writeS(pat->data[j][3]); // volume
|
||||||
w->write(&pat->data[j][4],2*song.pat[i>>16].effectRows*2); // effects
|
w->write(&pat->data[j][4],2*song.pat[i>>16].effectCols*2); // effects
|
||||||
}
|
}
|
||||||
|
|
||||||
w->writeString(pat->name,false);
|
w->writeString(pat->name,false);
|
||||||
|
@ -2730,7 +2739,7 @@ SafeWriter* DivEngine::saveDMF(unsigned char version) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<getChannelCount(sys); i++) {
|
for (int i=0; i<getChannelCount(sys); i++) {
|
||||||
w->writeC(song.pat[i].effectRows);
|
w->writeC(song.pat[i].effectCols);
|
||||||
|
|
||||||
for (int j=0; j<song.ordersLen; j++) {
|
for (int j=0; j<song.ordersLen; j++) {
|
||||||
DivPattern* pat=song.pat[i].getPattern(song.orders.ord[i][j],false);
|
DivPattern* pat=song.pat[i].getPattern(song.orders.ord[i][j],false);
|
||||||
|
@ -2738,7 +2747,7 @@ SafeWriter* DivEngine::saveDMF(unsigned char version) {
|
||||||
w->writeS(pat->data[k][0]); // note
|
w->writeS(pat->data[k][0]); // note
|
||||||
w->writeS(pat->data[k][1]); // octave
|
w->writeS(pat->data[k][1]); // octave
|
||||||
w->writeS(pat->data[k][3]); // volume
|
w->writeS(pat->data[k][3]); // volume
|
||||||
w->write(&pat->data[k][4],2*song.pat[i].effectRows*2); // effects
|
w->write(&pat->data[k][4],2*song.pat[i].effectCols*2); // effects
|
||||||
w->writeS(pat->data[k][2]); // instrument
|
w->writeS(pat->data[k][2]); // instrument
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -507,6 +507,9 @@ void DivInstrument::putInsData(SafeWriter* w) {
|
||||||
w->writeC(std.ex6Macro.mode);
|
w->writeC(std.ex6Macro.mode);
|
||||||
w->writeC(std.ex7Macro.mode);
|
w->writeC(std.ex7Macro.mode);
|
||||||
w->writeC(std.ex8Macro.mode);
|
w->writeC(std.ex8Macro.mode);
|
||||||
|
|
||||||
|
// C64 no test
|
||||||
|
w->writeC(c64.noTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
||||||
|
@ -1014,6 +1017,11 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
||||||
std.ex8Macro.mode=reader.readC();
|
std.ex8Macro.mode=reader.readC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// C64 no test
|
||||||
|
if (version>=89) {
|
||||||
|
c64.noTest=reader.readC();
|
||||||
|
}
|
||||||
|
|
||||||
return DIV_DATA_SUCCESS;
|
return DIV_DATA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -265,7 +265,7 @@ struct DivInstrumentC64 {
|
||||||
unsigned char a, d, s, r;
|
unsigned char a, d, s, r;
|
||||||
unsigned short duty;
|
unsigned short duty;
|
||||||
unsigned char ringMod, oscSync;
|
unsigned char ringMod, oscSync;
|
||||||
bool toFilter, volIsCutoff, initFilter, dutyIsAbs, filterIsAbs;
|
bool toFilter, volIsCutoff, initFilter, dutyIsAbs, filterIsAbs, noTest;
|
||||||
unsigned char res;
|
unsigned char res;
|
||||||
unsigned short cut;
|
unsigned short cut;
|
||||||
bool hp, lp, bp, ch3off;
|
bool hp, lp, bp, ch3off;
|
||||||
|
@ -287,6 +287,7 @@ struct DivInstrumentC64 {
|
||||||
initFilter(false),
|
initFilter(false),
|
||||||
dutyIsAbs(false),
|
dutyIsAbs(false),
|
||||||
filterIsAbs(false),
|
filterIsAbs(false),
|
||||||
|
noTest(false),
|
||||||
res(0),
|
res(0),
|
||||||
cut(0),
|
cut(0),
|
||||||
hp(false),
|
hp(false),
|
||||||
|
|
|
@ -130,6 +130,6 @@ SafeReader* DivPattern::compile(int len, int fxRows) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DivChannelData::DivChannelData():
|
DivChannelData::DivChannelData():
|
||||||
effectRows(1) {
|
effectCols(1) {
|
||||||
memset(data,0,256*sizeof(void*));
|
memset(data,0,256*sizeof(void*));
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ struct DivPattern {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DivChannelData {
|
struct DivChannelData {
|
||||||
unsigned char effectRows;
|
unsigned char effectCols;
|
||||||
// data goes as follows: data[ROW][TYPE]
|
// data goes as follows: data[ROW][TYPE]
|
||||||
// TYPE is:
|
// TYPE is:
|
||||||
// 0: note
|
// 0: note
|
||||||
|
|
|
@ -207,7 +207,7 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
|
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
|
|
|
@ -239,7 +239,7 @@ void DivPlatformAY8910::tick(bool sysTick) {
|
||||||
if (!chan[i].std.ex3.will) chan[i].autoEnvNum=1;
|
if (!chan[i].std.ex3.will) chan[i].autoEnvNum=1;
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
//rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63)));
|
//rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63)));
|
||||||
|
|
|
@ -261,7 +261,7 @@ void DivPlatformAY8930::tick(bool sysTick) {
|
||||||
immWrite(0x1a,ayNoiseOr);
|
immWrite(0x1a,ayNoiseOr);
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
if (chan[i].insChanged) {
|
if (chan[i].insChanged) {
|
||||||
|
|
|
@ -170,16 +170,17 @@ void DivPlatformC64::tick(bool sysTick) {
|
||||||
if (chan[i].testWhen>0) {
|
if (chan[i].testWhen>0) {
|
||||||
if (--chan[i].testWhen<1) {
|
if (--chan[i].testWhen<1) {
|
||||||
if (!chan[i].resetMask && !chan[i].inPorta) {
|
if (!chan[i].resetMask && !chan[i].inPorta) {
|
||||||
|
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_C64);
|
||||||
rWrite(i*7+5,0);
|
rWrite(i*7+5,0);
|
||||||
rWrite(i*7+6,0);
|
rWrite(i*7+6,0);
|
||||||
rWrite(i*7+4,(chan[i].wave<<4)|8|(chan[i].ring<<2)|(chan[i].sync<<1));
|
rWrite(i*7+4,(chan[i].wave<<4)|(ins->c64.noTest?0:8)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chan[i].std.wave.had) {
|
if (chan[i].std.wave.had) {
|
||||||
chan[i].wave=chan[i].std.wave.val;
|
chan[i].wave=chan[i].std.wave.val;
|
||||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
|
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
|
||||||
}
|
}
|
||||||
if (chan[i].std.pitch.had) {
|
if (chan[i].std.pitch.had) {
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
|
@ -196,20 +197,25 @@ void DivPlatformC64::tick(bool sysTick) {
|
||||||
chan[i].sync=chan[i].std.ex3.val&1;
|
chan[i].sync=chan[i].std.ex3.val&1;
|
||||||
chan[i].ring=chan[i].std.ex3.val&2;
|
chan[i].ring=chan[i].std.ex3.val&2;
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
|
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
|
||||||
|
}
|
||||||
|
if (chan[i].std.ex4.had) {
|
||||||
|
chan[i].test=chan[i].std.ex4.val&1;
|
||||||
|
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>0xffff) chan[i].freq=0xffff;
|
if (chan[i].freq>0xffff) chan[i].freq=0xffff;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||||
rWrite(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
rWrite(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].ring<<2)|(chan[i].sync<<1)|1);
|
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|1);
|
||||||
}
|
}
|
||||||
if (chan[i].keyOff) {
|
if (chan[i].keyOff) {
|
||||||
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||||
rWrite(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
rWrite(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].ring<<2)|(chan[i].sync<<1)|0);
|
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|0);
|
||||||
}
|
}
|
||||||
rWrite(i*7,chan[i].freq&0xff);
|
rWrite(i*7,chan[i].freq&0xff);
|
||||||
rWrite(i*7+1,chan[i].freq>>8);
|
rWrite(i*7+1,chan[i].freq>>8);
|
||||||
|
@ -231,6 +237,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
chan[c.chan].active=true;
|
chan[c.chan].active=true;
|
||||||
chan[c.chan].keyOn=true;
|
chan[c.chan].keyOn=true;
|
||||||
|
chan[c.chan].test=false;
|
||||||
if (chan[c.chan].insChanged || chan[c.chan].resetDuty || ins->std.waveMacro.len>0) {
|
if (chan[c.chan].insChanged || chan[c.chan].resetDuty || ins->std.waveMacro.len>0) {
|
||||||
chan[c.chan].duty=ins->c64.duty;
|
chan[c.chan].duty=ins->c64.duty;
|
||||||
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||||
|
@ -335,7 +342,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_WAVE:
|
case DIV_CMD_WAVE:
|
||||||
chan[c.chan].wave=c.value;
|
chan[c.chan].wave=c.value;
|
||||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO:
|
case DIV_CMD_LEGATO:
|
||||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
|
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
|
||||||
|
@ -416,11 +423,11 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
chan[c.chan].ring=c.value;
|
chan[c.chan].ring=c.value;
|
||||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
chan[c.chan].sync=c.value;
|
chan[c.chan].sync=c.value;
|
||||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
filtControl&=7;
|
filtControl&=7;
|
||||||
|
|
|
@ -30,7 +30,7 @@ class DivPlatformC64: public DivDispatch {
|
||||||
unsigned char sweep, wave, attack, decay, sustain, release;
|
unsigned char sweep, wave, attack, decay, sustain, release;
|
||||||
short duty;
|
short duty;
|
||||||
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, filter;
|
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, filter;
|
||||||
bool resetMask, resetFilter, resetDuty, ring, sync;
|
bool resetMask, resetFilter, resetDuty, ring, sync, test;
|
||||||
signed char vol, outVol;
|
signed char vol, outVol;
|
||||||
DivMacroInt std;
|
DivMacroInt std;
|
||||||
Channel():
|
Channel():
|
||||||
|
@ -61,6 +61,7 @@ class DivPlatformC64: public DivDispatch {
|
||||||
resetDuty(false),
|
resetDuty(false),
|
||||||
ring(false),
|
ring(false),
|
||||||
sync(false),
|
sync(false),
|
||||||
|
test(false),
|
||||||
vol(15) {}
|
vol(15) {}
|
||||||
};
|
};
|
||||||
Channel chan[3];
|
Channel chan[3];
|
||||||
|
|
|
@ -436,7 +436,7 @@ void DivPlatformES5506::tick(bool sysTick) {
|
||||||
chan[i].envChanged.changed=0;
|
chan[i].envChanged.changed=0;
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].freq>0x1ffff) chan[i].freq=0x1ffff;
|
if (chan[i].freq>0x1ffff) chan[i].freq=0x1ffff;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
|
|
|
@ -177,7 +177,7 @@ void DivPlatformFDS::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
|
|
|
@ -227,7 +227,7 @@ void DivPlatformGB::tick(bool sysTick) {
|
||||||
if (ntPos>255) ntPos=255;
|
if (ntPos>255) ntPos=255;
|
||||||
chan[i].freq=noiseTable[ntPos];
|
chan[i].freq=noiseTable[ntPos];
|
||||||
} else {
|
} else {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>2047) chan[i].freq=2047;
|
if (chan[i].freq>2047) chan[i].freq=2047;
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -412,7 +412,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i<6; i++) {
|
||||||
if (i==2 && extMode) continue;
|
if (i==2 && extMode) continue;
|
||||||
if (chan[i].freqChanged) {
|
if (chan[i].freqChanged) {
|
||||||
int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4)+chan[i].std.pitch.val;
|
int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].std.pitch.val);
|
||||||
int block=(chan[i].baseFreq&0xf800)>>11;
|
int block=(chan[i].baseFreq&0xf800)>>11;
|
||||||
if (fNum<0) fNum=0;
|
if (fNum<0) fNum=0;
|
||||||
if (fNum>2047) {
|
if (fNum>2047) {
|
||||||
|
|
|
@ -307,7 +307,7 @@ void DivPlatformGenesisExt::tick(bool sysTick) {
|
||||||
unsigned char writeMask=2;
|
unsigned char writeMask=2;
|
||||||
if (extMode) for (int i=0; i<4; i++) {
|
if (extMode) for (int i=0; i<4; i++) {
|
||||||
if (opChan[i].freqChanged) {
|
if (opChan[i].freqChanged) {
|
||||||
int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4)+opChan[i].std.pitch.val;
|
int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].std.pitch.val);
|
||||||
int block=(opChan[i].baseFreq&0xf800)>>11;
|
int block=(opChan[i].baseFreq&0xf800)>>11;
|
||||||
if (fNum<0) fNum=0;
|
if (fNum<0) fNum=0;
|
||||||
if (fNum>2047) {
|
if (fNum>2047) {
|
||||||
|
|
|
@ -195,7 +195,7 @@ void DivPlatformLynx::tick(bool sysTick) {
|
||||||
WRITE_OTHER(i, ((chan[i].lfsr&0xf00)>>4));
|
WRITE_OTHER(i, ((chan[i].lfsr&0xf00)>>4));
|
||||||
chan[i].lfsr=-1;
|
chan[i].lfsr=-1;
|
||||||
}
|
}
|
||||||
chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (chan[i].std.duty.had) {
|
if (chan[i].std.duty.had) {
|
||||||
chan[i].duty=chan[i].std.duty.val;
|
chan[i].duty=chan[i].std.duty.val;
|
||||||
WRITE_FEEDBACK(i, chan[i].duty.feedback);
|
WRITE_FEEDBACK(i, chan[i].duty.feedback);
|
||||||
|
|
|
@ -134,7 +134,7 @@ void DivPlatformMMC5::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1;
|
||||||
if (chan[i].freq>2047) chan[i].freq=2047;
|
if (chan[i].freq>2047) chan[i].freq=2047;
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
|
|
|
@ -347,7 +347,7 @@ void DivPlatformN163::tick(bool sysTick) {
|
||||||
chan[i].waveUpdated=false;
|
chan[i].waveUpdated=false;
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq((((chan[i].baseFreq*chan[i].waveLen)*(chanMax+1))/16),chan[i].pitch,false,0)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq((((chan[i].baseFreq*chan[i].waveLen)*(chanMax+1))/16),chan[i].pitch,false,0,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].freq>0x3ffff) chan[i].freq=0x3ffff;
|
if (chan[i].freq>0x3ffff) chan[i].freq=0x3ffff;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
|
|
|
@ -109,7 +109,7 @@ void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
if (nes->apu.clocked) {
|
if (nes->apu.clocked) {
|
||||||
nes->apu.clocked=false;
|
nes->apu.clocked=false;
|
||||||
}
|
}
|
||||||
int sample=(pulse_output(nes)+tnd_output(nes));
|
int sample=(pulse_output(nes)+tnd_output(nes))<<6;
|
||||||
if (sample>32767) sample=32767;
|
if (sample>32767) sample=32767;
|
||||||
if (sample<-32768) sample=-32768;
|
if (sample<-32768) sample=-32768;
|
||||||
bufL[i]=sample;
|
bufL[i]=sample;
|
||||||
|
@ -218,7 +218,7 @@ void DivPlatformNES::tick(bool sysTick) {
|
||||||
if (ntPos>252) ntPos=252;
|
if (ntPos>252) ntPos=252;
|
||||||
chan[i].freq=(parent->song.properNoiseLayout)?(15-(chan[i].baseFreq&15)):(noiseTable[ntPos]);
|
chan[i].freq=(parent->song.properNoiseLayout)?(15-(chan[i].baseFreq&15)):(noiseTable[ntPos]);
|
||||||
} else {
|
} else {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1;
|
||||||
if (chan[i].freq>2047) chan[i].freq=2047;
|
if (chan[i].freq>2047) chan[i].freq=2047;
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
}
|
}
|
||||||
|
@ -472,7 +472,7 @@ int DivPlatformNES::getRegisterPoolSize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
float DivPlatformNES::getPostAmp() {
|
float DivPlatformNES::getPostAmp() {
|
||||||
return 128.0f;
|
return 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformNES::reset() {
|
void DivPlatformNES::reset() {
|
||||||
|
|
|
@ -417,7 +417,7 @@ void DivPlatformOPL::tick(bool sysTick) {
|
||||||
bool updateDrums=false;
|
bool updateDrums=false;
|
||||||
for (int i=0; i<totalChans; i++) {
|
for (int i=0; i<totalChans; i++) {
|
||||||
if (chan[i].freqChanged) {
|
if (chan[i].freqChanged) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq));
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>131071) chan[i].freq=131071;
|
if (chan[i].freq>131071) chan[i].freq=131071;
|
||||||
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val;
|
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val;
|
||||||
chan[i].freqH=freqt>>8;
|
chan[i].freqH=freqt>>8;
|
||||||
|
|
|
@ -261,7 +261,7 @@ void DivPlatformOPLL::tick(bool sysTick) {
|
||||||
|
|
||||||
for (int i=0; i<11; i++) {
|
for (int i=0; i<11; i++) {
|
||||||
if (chan[i].freqChanged) {
|
if (chan[i].freqChanged) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq));
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>262143) chan[i].freq=262143;
|
if (chan[i].freq>262143) chan[i].freq=262143;
|
||||||
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val;
|
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val;
|
||||||
chan[i].freqL=freqt&0xff;
|
chan[i].freqL=freqt&0xff;
|
||||||
|
|
|
@ -217,7 +217,7 @@ void DivPlatformPCE::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE);
|
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE);
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (chan[i].furnaceDac) {
|
if (chan[i].furnaceDac) {
|
||||||
double off=1.0;
|
double off=1.0;
|
||||||
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
|
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
|
||||||
|
|
|
@ -193,7 +193,7 @@ void DivPlatformPCSpeaker::tick(bool sysTick) {
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1;
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
|
|
|
@ -116,7 +116,7 @@ void DivPlatformPET::tick(bool sysTick) {
|
||||||
chan.freqChanged=true;
|
chan.freqChanged=true;
|
||||||
}
|
}
|
||||||
if (chan.freqChanged || chan.keyOn || chan.keyOff) {
|
if (chan.freqChanged || chan.keyOn || chan.keyOff) {
|
||||||
chan.freq=parent->calcFreq(chan.baseFreq,chan.pitch,true)+chan.std.pitch.val;
|
chan.freq=parent->calcFreq(chan.baseFreq,chan.pitch,true,0,chan.std.pitch.val);
|
||||||
if (chan.freq>257) chan.freq=257;
|
if (chan.freq>257) chan.freq=257;
|
||||||
if (chan.freq<2) chan.freq=2;
|
if (chan.freq<2) chan.freq=2;
|
||||||
rWrite(8,chan.freq-2);
|
rWrite(8,chan.freq-2);
|
||||||
|
|
|
@ -331,7 +331,7 @@ void DivPlatformQSound::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
|
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>0xffff) chan[i].freq=0xffff;
|
if (chan[i].freq>0xffff) chan[i].freq=0xffff;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
rWrite(q1_reg_map[Q1V_BANK][i], qsound_bank);
|
rWrite(q1_reg_map[Q1V_BANK][i], qsound_bank);
|
||||||
|
|
|
@ -194,7 +194,7 @@ void DivPlatformSAA1099::tick(bool sysTick) {
|
||||||
rWrite(0x18+(i/3),saaEnv[i/3]);
|
rWrite(0x18+(i/3),saaEnv[i/3]);
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||||
if (chan[i].freq>=32768) {
|
if (chan[i].freq>=32768) {
|
||||||
chan[i].freqH=7;
|
chan[i].freqH=7;
|
||||||
|
|
|
@ -106,7 +106,7 @@ void DivPlatformSMS::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
if (chan[i].freqChanged) {
|
if (chan[i].freqChanged) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>1023) chan[i].freq=1023;
|
if (chan[i].freq>1023) chan[i].freq=1023;
|
||||||
if (chan[i].freq<8) chan[i].freq=1;
|
if (chan[i].freq<8) chan[i].freq=1;
|
||||||
//if (chan[i].actualNote>0x5d) chan[i].freq=0x01;
|
//if (chan[i].actualNote>0x5d) chan[i].freq=0x01;
|
||||||
|
@ -121,7 +121,7 @@ void DivPlatformSMS::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chan[3].freqChanged || updateSNMode) {
|
if (chan[3].freqChanged || updateSNMode) {
|
||||||
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true)+chan[3].std.pitch.val;
|
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].std.pitch.val);
|
||||||
if (chan[3].freq>1023) chan[3].freq=1023;
|
if (chan[3].freq>1023) chan[3].freq=1023;
|
||||||
if (chan[3].actualNote>0x5d) chan[3].freq=0x01;
|
if (chan[3].actualNote>0x5d) chan[3].freq=0x01;
|
||||||
if (snNoiseMode&2) { // take period from channel 3
|
if (snNoiseMode&2) { // take period from channel 3
|
||||||
|
|
|
@ -34,6 +34,10 @@ void SoundUnit::NextSample(short* l, short* r) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chan[i].flags.ring) {
|
||||||
|
ns[i]=(ns[i]*ns[(i+1)&7])>>7;
|
||||||
|
}
|
||||||
|
|
||||||
if (chan[i].flags.pcm) {
|
if (chan[i].flags.pcm) {
|
||||||
if (chan[i].freq>0x8000) {
|
if (chan[i].freq>0x8000) {
|
||||||
pcmdec[i]+=0x8000;
|
pcmdec[i]+=0x8000;
|
||||||
|
|
|
@ -32,6 +32,62 @@ const char** DivPlatformSoundUnit::getRegisterSheet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* DivPlatformSoundUnit::getEffectName(unsigned char effect) {
|
const char* DivPlatformSoundUnit::getEffectName(unsigned char effect) {
|
||||||
|
switch (effect) {
|
||||||
|
case 0x10:
|
||||||
|
return "10xx: Set waveform (0 to 7)";
|
||||||
|
break;
|
||||||
|
case 0x12:
|
||||||
|
return "12xx: Set pulse width (0 to 7F)";
|
||||||
|
break;
|
||||||
|
case 0x13:
|
||||||
|
return "13xx: Set resonance (0 to F)";
|
||||||
|
break;
|
||||||
|
case 0x14:
|
||||||
|
return "14xx: Set filter mode (bit 0: ring mod; bit 1: low pass; bit 2: band pass; bit 3: high pass)";
|
||||||
|
break;
|
||||||
|
case 0x15:
|
||||||
|
return "15xx: Set frequency sweep period low byte";
|
||||||
|
break;
|
||||||
|
case 0x16:
|
||||||
|
return "16xx: Set frequency sweep period high byte";
|
||||||
|
break;
|
||||||
|
case 0x17:
|
||||||
|
return "17xx: Set volume sweep period low byte";
|
||||||
|
break;
|
||||||
|
case 0x18:
|
||||||
|
return "18xx: Set volume sweep period high byte";
|
||||||
|
break;
|
||||||
|
case 0x19:
|
||||||
|
return "19xx: Set cutoff sweep period low byte";
|
||||||
|
break;
|
||||||
|
case 0x1a:
|
||||||
|
return "1Axx: Set cutoff sweep period high byte";
|
||||||
|
break;
|
||||||
|
case 0x1b:
|
||||||
|
return "1Bxx: Set frequency sweep boundary";
|
||||||
|
break;
|
||||||
|
case 0x1c:
|
||||||
|
return "1Cxx: Set volume sweep boundary";
|
||||||
|
break;
|
||||||
|
case 0x1d:
|
||||||
|
return "1Dxx: Set cutoff sweep boundary";
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
return "20xx: Toggle frequency sweep (bit 0-6: speed; bit 7: direction is up)";
|
||||||
|
break;
|
||||||
|
case 0x21:
|
||||||
|
return "21xx: Toggle volume sweep (bit 0-4: speed; bit 5: direciton is up; bit 6: loop; bit 7: alternate)";
|
||||||
|
break;
|
||||||
|
case 0x22:
|
||||||
|
return "22xx: Toggle cutoff sweep (bit 0-6: speed; bit 7: direction is up)";
|
||||||
|
break;
|
||||||
|
case 0x40: case 0x41: case 0x42: case 0x43:
|
||||||
|
case 0x44: case 0x45: case 0x46: case 0x47:
|
||||||
|
case 0x48: case 0x49: case 0x4a: case 0x4b:
|
||||||
|
case 0x4c: case 0x4d: case 0x4e: case 0x4f:
|
||||||
|
return "4xxx: Set cutoff (0 to FFF)";
|
||||||
|
break;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +106,12 @@ void DivPlatformSoundUnit::writeControl(int ch) {
|
||||||
chWrite(ch,0x04,(chan[ch].wave&7)|(chan[ch].pcm<<3)|(chan[ch].control<<4));
|
chWrite(ch,0x04,(chan[ch].wave&7)|(chan[ch].pcm<<3)|(chan[ch].control<<4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformSoundUnit::writeControlUpper(int ch) {
|
||||||
|
chWrite(ch,0x05,((int)chan[ch].phaseReset)|(chan[ch].filterPhaseReset<<1)|(chan[ch].pcmLoop<<2)|(chan[ch].timerSync<<3)|(chan[ch].freqSweep<<4)|(chan[ch].volSweep<<5)|(chan[ch].cutSweep<<6));
|
||||||
|
chan[ch].phaseReset=false;
|
||||||
|
chan[ch].filterPhaseReset=false;
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformSoundUnit::tick(bool sysTick) {
|
void DivPlatformSoundUnit::tick(bool sysTick) {
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i<8; i++) {
|
||||||
chan[i].std.next();
|
chan[i].std.next();
|
||||||
|
@ -80,6 +142,10 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
|
||||||
chan[i].wave=chan[i].std.wave.val&7;
|
chan[i].wave=chan[i].std.wave.val&7;
|
||||||
writeControl(i);
|
writeControl(i);
|
||||||
}
|
}
|
||||||
|
if (chan[i].std.phaseReset.had) {
|
||||||
|
chan[i].phaseReset=chan[i].std.phaseReset.val;
|
||||||
|
writeControlUpper(i);
|
||||||
|
}
|
||||||
if (chan[i].std.panL.had) {
|
if (chan[i].std.panL.had) {
|
||||||
chan[i].pan=chan[i].std.panL.val;
|
chan[i].pan=chan[i].std.panL.val;
|
||||||
chWrite(i,0x03,chan[i].pan);
|
chWrite(i,0x03,chan[i].pan);
|
||||||
|
@ -88,7 +154,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
if (chan[i].std.ex1.had) {
|
if (chan[i].std.ex1.had) {
|
||||||
chan[i].cutoff=chan[i].std.ex1.val;
|
chan[i].cutoff=chan[i].std.ex1.val&16383;
|
||||||
chWrite(i,0x06,chan[i].cutoff&0xff);
|
chWrite(i,0x06,chan[i].cutoff&0xff);
|
||||||
chWrite(i,0x07,chan[i].cutoff>>8);
|
chWrite(i,0x07,chan[i].cutoff>>8);
|
||||||
}
|
}
|
||||||
|
@ -102,7 +168,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
|
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val);
|
||||||
chWrite(i,0x00,chan[i].freq&0xff);
|
chWrite(i,0x00,chan[i].freq&0xff);
|
||||||
chWrite(i,0x01,chan[i].freq>>8);
|
chWrite(i,0x01,chan[i].freq>>8);
|
||||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||||
|
|
|
@ -31,7 +31,8 @@ class DivPlatformSoundUnit: public DivDispatch {
|
||||||
int ins, cutoff, res, control;
|
int ins, cutoff, res, control;
|
||||||
signed char pan;
|
signed char pan;
|
||||||
unsigned char duty;
|
unsigned char duty;
|
||||||
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, noise, pcm;
|
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, noise, pcm, phaseReset, filterPhaseReset;
|
||||||
|
bool pcmLoop, timerSync, freqSweep, volSweep, cutSweep;
|
||||||
signed char vol, outVol, wave;
|
signed char vol, outVol, wave;
|
||||||
DivMacroInt std;
|
DivMacroInt std;
|
||||||
Channel():
|
Channel():
|
||||||
|
@ -53,9 +54,16 @@ class DivPlatformSoundUnit: public DivDispatch {
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
noise(false),
|
noise(false),
|
||||||
pcm(false),
|
pcm(false),
|
||||||
|
phaseReset(false),
|
||||||
|
filterPhaseReset(false),
|
||||||
|
pcmLoop(false),
|
||||||
|
timerSync(false),
|
||||||
|
freqSweep(false),
|
||||||
|
volSweep(false),
|
||||||
|
cutSweep(false),
|
||||||
vol(127),
|
vol(127),
|
||||||
outVol(127),
|
outVol(127),
|
||||||
wave(-1) {}
|
wave(0) {}
|
||||||
};
|
};
|
||||||
Channel chan[8];
|
Channel chan[8];
|
||||||
bool isMuted[8];
|
bool isMuted[8];
|
||||||
|
@ -74,6 +82,7 @@ class DivPlatformSoundUnit: public DivDispatch {
|
||||||
SoundUnit* su;
|
SoundUnit* su;
|
||||||
unsigned char regPool[128];
|
unsigned char regPool[128];
|
||||||
void writeControl(int ch);
|
void writeControl(int ch);
|
||||||
|
void writeControlUpper(int ch);
|
||||||
|
|
||||||
friend void putDispatchChan(void*,int,int);
|
friend void putDispatchChan(void*,int,int);
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -194,7 +194,7 @@ void DivPlatformSwan::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (i==1 && pcm && furnaceDac) {
|
if (i==1 && pcm && furnaceDac) {
|
||||||
double off=1.0;
|
double off=1.0;
|
||||||
if (dacSample>=0 && dacSample<parent->song.sampleLen) {
|
if (dacSample>=0 && dacSample<parent->song.sampleLen) {
|
||||||
|
|
|
@ -194,7 +194,7 @@ void DivPlatformVERA::tick(bool sysTick) {
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged) {
|
if (chan[i].freqChanged) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||||
rWrite(i,0,chan[i].freq&0xff);
|
rWrite(i,0,chan[i].freq&0xff);
|
||||||
rWrite(i,1,(chan[i].freq>>8)&0xff);
|
rWrite(i,1,(chan[i].freq>>8)&0xff);
|
||||||
|
|
|
@ -123,7 +123,7 @@ void DivPlatformVIC20::tick(bool sysTick) {
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val);
|
||||||
if (i<3) {
|
if (i<3) {
|
||||||
chan[i].freq>>=(2-i);
|
chan[i].freq>>=(2-i);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -183,9 +183,9 @@ void DivPlatformVRC6::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
if (i==2) { // sawtooth
|
if (i==2) { // sawtooth
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1;
|
||||||
} else { // pulse
|
} else { // pulse
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1;
|
||||||
if (chan[i].furnaceDac) {
|
if (chan[i].furnaceDac) {
|
||||||
double off=1.0;
|
double off=1.0;
|
||||||
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
|
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
|
||||||
|
|
|
@ -476,7 +476,7 @@ void DivPlatformX1_010::tick(bool sysTick) {
|
||||||
chan[i].envChanged=false;
|
chan[i].envChanged=false;
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val;
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val);
|
||||||
if (chan[i].pcm) {
|
if (chan[i].pcm) {
|
||||||
if (chan[i].freq<1) chan[i].freq=1;
|
if (chan[i].freq<1) chan[i].freq=1;
|
||||||
if (chan[i].freq>255) chan[i].freq=255;
|
if (chan[i].freq>255) chan[i].freq=255;
|
||||||
|
|
|
@ -572,7 +572,7 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
if (i==1 && extMode) continue;
|
if (i==1 && extMode) continue;
|
||||||
if (chan[i].freqChanged) {
|
if (chan[i].freqChanged) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq));
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>262143) chan[i].freq=262143;
|
if (chan[i].freq>262143) chan[i].freq=262143;
|
||||||
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val;
|
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val;
|
||||||
immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8);
|
immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8);
|
||||||
|
|
|
@ -635,7 +635,7 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i<6; i++) {
|
||||||
if (i==2 && extMode) continue;
|
if (i==2 && extMode) continue;
|
||||||
if (chan[i].freqChanged) {
|
if (chan[i].freqChanged) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq));
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val);
|
||||||
if (chan[i].freq>262143) chan[i].freq=262143;
|
if (chan[i].freq>262143) chan[i].freq=262143;
|
||||||
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val;
|
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val;
|
||||||
immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8);
|
immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8);
|
||||||
|
|
|
@ -955,7 +955,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
int whatRow=afterDelay?chan[i].delayRow:curRow;
|
int whatRow=afterDelay?chan[i].delayRow:curRow;
|
||||||
DivPattern* pat=song.pat[i].getPattern(song.orders.ord[i][whatOrder],false);
|
DivPattern* pat=song.pat[i].getPattern(song.orders.ord[i][whatOrder],false);
|
||||||
// pre effects
|
// pre effects
|
||||||
if (!afterDelay) for (int j=0; j<song.pat[i].effectRows; j++) {
|
if (!afterDelay) for (int j=0; j<song.pat[i].effectCols; j++) {
|
||||||
short effect=pat->data[whatRow][4+(j<<1)];
|
short effect=pat->data[whatRow][4+(j<<1)];
|
||||||
short effectVal=pat->data[whatRow][5+(j<<1)];
|
short effectVal=pat->data[whatRow][5+(j<<1)];
|
||||||
|
|
||||||
|
@ -1064,7 +1064,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
bool calledPorta=false;
|
bool calledPorta=false;
|
||||||
|
|
||||||
// effects
|
// effects
|
||||||
for (int j=0; j<song.pat[i].effectRows; j++) {
|
for (int j=0; j<song.pat[i].effectCols; j++) {
|
||||||
short effect=pat->data[whatRow][4+(j<<1)];
|
short effect=pat->data[whatRow][4+(j<<1)];
|
||||||
short effectVal=pat->data[whatRow][5+(j<<1)];
|
short effectVal=pat->data[whatRow][5+(j<<1)];
|
||||||
|
|
||||||
|
@ -1384,7 +1384,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].noteOnInhibit=false;
|
chan[i].noteOnInhibit=false;
|
||||||
|
|
||||||
// post effects
|
// post effects
|
||||||
for (int j=0; j<song.pat[i].effectRows; j++) {
|
for (int j=0; j<song.pat[i].effectCols; j++) {
|
||||||
short effect=pat->data[whatRow][4+(j<<1)];
|
short effect=pat->data[whatRow][4+(j<<1)];
|
||||||
short effectVal=pat->data[whatRow][5+(j<<1)];
|
short effectVal=pat->data[whatRow][5+(j<<1)];
|
||||||
|
|
||||||
|
@ -1421,7 +1421,7 @@ void DivEngine::nextRow() {
|
||||||
snprintf(pb2,4095,"\x1b[0;36m%.2x",pat->data[curRow][2]);
|
snprintf(pb2,4095,"\x1b[0;36m%.2x",pat->data[curRow][2]);
|
||||||
strcat(pb3,pb2);
|
strcat(pb3,pb2);
|
||||||
}
|
}
|
||||||
for (int j=0; j<song.pat[i].effectRows; j++) {
|
for (int j=0; j<song.pat[i].effectCols; j++) {
|
||||||
if (pat->data[curRow][4+(j<<1)]==-1) {
|
if (pat->data[curRow][4+(j<<1)]==-1) {
|
||||||
strcat(pb3,"\x1b[m--");
|
strcat(pb3,"\x1b[m--");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1495,7 +1495,7 @@ void DivEngine::nextRow() {
|
||||||
if (song.oneTickCut) {
|
if (song.oneTickCut) {
|
||||||
bool doPrepareCut=true;
|
bool doPrepareCut=true;
|
||||||
|
|
||||||
for (int j=0; j<song.pat[i].effectRows; j++) {
|
for (int j=0; j<song.pat[i].effectCols; j++) {
|
||||||
if (pat->data[curRow][4+(j<<1)]==0x03) {
|
if (pat->data[curRow][4+(j<<1)]==0x03) {
|
||||||
doPrepareCut=false;
|
doPrepareCut=false;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -336,6 +336,7 @@ struct DivSong {
|
||||||
bool newSegaPCM;
|
bool newSegaPCM;
|
||||||
bool fbPortaPause;
|
bool fbPortaPause;
|
||||||
bool snDutyReset;
|
bool snDutyReset;
|
||||||
|
bool pitchMacroIsLinear;
|
||||||
|
|
||||||
DivOrders orders;
|
DivOrders orders;
|
||||||
std::vector<DivInstrument*> ins;
|
std::vector<DivInstrument*> ins;
|
||||||
|
@ -441,7 +442,8 @@ struct DivSong {
|
||||||
e1e2AlsoTakePriority(false),
|
e1e2AlsoTakePriority(false),
|
||||||
newSegaPCM(true),
|
newSegaPCM(true),
|
||||||
fbPortaPause(false),
|
fbPortaPause(false),
|
||||||
snDutyReset(false) {
|
snDutyReset(false),
|
||||||
|
pitchMacroIsLinear(true) {
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<32; i++) {
|
||||||
system[i]=DIV_SYSTEM_NULL;
|
system[i]=DIV_SYSTEM_NULL;
|
||||||
systemVol[i]=64;
|
systemVol[i]=64;
|
||||||
|
|
|
@ -305,6 +305,12 @@ DivInstrumentType DivEngine::getPreferInsType(int chan) {
|
||||||
return sysDefs[sysOfChan[chan]]->chanInsType[dispatchChanOfChan[chan]][0];
|
return sysDefs[sysOfChan[chan]]->chanInsType[dispatchChanOfChan[chan]][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DivInstrumentType DivEngine::getPreferInsSecondType(int chan) {
|
||||||
|
if (chan<0 || chan>chans) return DIV_INS_NULL;
|
||||||
|
if (sysDefs[sysOfChan[chan]]==NULL) return DIV_INS_NULL;
|
||||||
|
return sysDefs[sysOfChan[chan]]->chanInsType[dispatchChanOfChan[chan]][1];
|
||||||
|
}
|
||||||
|
|
||||||
int DivEngine::minVGMVersion(DivSystem which) {
|
int DivEngine::minVGMVersion(DivSystem which) {
|
||||||
switch (which) {
|
switch (which) {
|
||||||
case DIV_SYSTEM_YM2612:
|
case DIV_SYSTEM_YM2612:
|
||||||
|
@ -367,8 +373,8 @@ void DivEngine::registerSystems() {
|
||||||
"Yamaha YMU759", NULL, 0x01, 0x01, 17, true, false, 0, false,
|
"Yamaha YMU759", NULL, 0x01, 0x01, 17, true, false, 0, false,
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "PCM" }, // name
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "PCM" }, // name
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "PCM" }, // short
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "PCM" }, // short
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM}, // type
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM }, // type
|
||||||
{DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM} // ins
|
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA} // ins
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_GENESIS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_GENESIS]=new DivSysDef(
|
||||||
|
|
|
@ -121,6 +121,10 @@ void FurnaceGUI::drawCompatFlags() {
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip("when enabled, duty macro will always reset phase, even if its value hasn't changed.");
|
ImGui::SetTooltip("when enabled, duty macro will always reset phase, even if its value hasn't changed.");
|
||||||
}
|
}
|
||||||
|
ImGui::Checkbox("Pitch macro is linear",&e->song.pitchMacroIsLinear);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("when enabled, the pitch macro of an instrument is in linear space.");
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Text("Loop modality:");
|
ImGui::Text("Loop modality:");
|
||||||
if (ImGui::RadioButton("Reset channels",e->song.loopModality==0)) {
|
if (ImGui::RadioButton("Reset channels",e->song.loopModality==0)) {
|
||||||
|
|
|
@ -87,7 +87,7 @@ void FurnaceGUI::finishSelection() {
|
||||||
selStart.xFine=0;
|
selStart.xFine=0;
|
||||||
}
|
}
|
||||||
if (e->song.chanCollapse[selEnd.xCoarse]) {
|
if (e->song.chanCollapse[selEnd.xCoarse]) {
|
||||||
selEnd.xFine=2+e->song.pat[cursor.xCoarse].effectRows*2;
|
selEnd.xFine=2+e->song.pat[cursor.xCoarse].effectCols*2;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->setMidiBaseChan(cursor.xCoarse);
|
e->setMidiBaseChan(cursor.xCoarse);
|
||||||
|
@ -105,7 +105,7 @@ void FurnaceGUI::moveCursor(int x, int y, bool select) {
|
||||||
demandScrollX=true;
|
demandScrollX=true;
|
||||||
if (x>0) {
|
if (x>0) {
|
||||||
for (int i=0; i<x; i++) {
|
for (int i=0; i<x; i++) {
|
||||||
if (++cursor.xFine>=(e->song.chanCollapse[cursor.xCoarse]?1:(3+e->song.pat[cursor.xCoarse].effectRows*2))) {
|
if (++cursor.xFine>=(e->song.chanCollapse[cursor.xCoarse]?1:(3+e->song.pat[cursor.xCoarse].effectCols*2))) {
|
||||||
cursor.xFine=0;
|
cursor.xFine=0;
|
||||||
if (++cursor.xCoarse>=lastChannel) {
|
if (++cursor.xCoarse>=lastChannel) {
|
||||||
if (settings.wrapHorizontal!=0 && !select) {
|
if (settings.wrapHorizontal!=0 && !select) {
|
||||||
|
@ -113,7 +113,7 @@ void FurnaceGUI::moveCursor(int x, int y, bool select) {
|
||||||
if (settings.wrapHorizontal==2) y++;
|
if (settings.wrapHorizontal==2) y++;
|
||||||
} else {
|
} else {
|
||||||
cursor.xCoarse=lastChannel-1;
|
cursor.xCoarse=lastChannel-1;
|
||||||
cursor.xFine=e->song.chanCollapse[cursor.xCoarse]?0:(2+e->song.pat[cursor.xCoarse].effectRows*2);
|
cursor.xFine=e->song.chanCollapse[cursor.xCoarse]?0:(2+e->song.pat[cursor.xCoarse].effectCols*2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (!e->song.chanShow[cursor.xCoarse]) {
|
while (!e->song.chanShow[cursor.xCoarse]) {
|
||||||
|
@ -129,7 +129,7 @@ void FurnaceGUI::moveCursor(int x, int y, bool select) {
|
||||||
if (--cursor.xCoarse<firstChannel) {
|
if (--cursor.xCoarse<firstChannel) {
|
||||||
if (settings.wrapHorizontal!=0 && !select) {
|
if (settings.wrapHorizontal!=0 && !select) {
|
||||||
cursor.xCoarse=lastChannel-1;
|
cursor.xCoarse=lastChannel-1;
|
||||||
cursor.xFine=2+e->song.pat[cursor.xCoarse].effectRows*2;
|
cursor.xFine=2+e->song.pat[cursor.xCoarse].effectCols*2;
|
||||||
if (settings.wrapHorizontal==2) y--;
|
if (settings.wrapHorizontal==2) y--;
|
||||||
} else {
|
} else {
|
||||||
cursor.xCoarse=firstChannel;
|
cursor.xCoarse=firstChannel;
|
||||||
|
@ -143,7 +143,7 @@ void FurnaceGUI::moveCursor(int x, int y, bool select) {
|
||||||
if (e->song.chanCollapse[cursor.xCoarse]) {
|
if (e->song.chanCollapse[cursor.xCoarse]) {
|
||||||
cursor.xFine=0;
|
cursor.xFine=0;
|
||||||
} else {
|
} else {
|
||||||
cursor.xFine=2+e->song.pat[cursor.xCoarse].effectRows*2;
|
cursor.xFine=2+e->song.pat[cursor.xCoarse].effectCols*2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ void FurnaceGUI::moveCursorBottom(bool select) {
|
||||||
DETERMINE_LAST;
|
DETERMINE_LAST;
|
||||||
cursor.xCoarse=lastChannel-1;
|
cursor.xCoarse=lastChannel-1;
|
||||||
if (cursor.xCoarse<0) cursor.xCoarse=0;
|
if (cursor.xCoarse<0) cursor.xCoarse=0;
|
||||||
cursor.xFine=2+e->song.pat[cursor.xCoarse].effectRows*2;
|
cursor.xFine=2+e->song.pat[cursor.xCoarse].effectCols*2;
|
||||||
demandScrollX=true;
|
demandScrollX=true;
|
||||||
} else {
|
} else {
|
||||||
cursor.y=e->song.patLen-1;
|
cursor.y=e->song.patLen-1;
|
||||||
|
|
|
@ -462,13 +462,13 @@ void FurnaceGUI::doAction(int what) {
|
||||||
break;
|
break;
|
||||||
case GUI_ACTION_PAT_INCREASE_COLUMNS:
|
case GUI_ACTION_PAT_INCREASE_COLUMNS:
|
||||||
if (cursor.xCoarse<0 || cursor.xCoarse>=e->getTotalChannelCount()) break;
|
if (cursor.xCoarse<0 || cursor.xCoarse>=e->getTotalChannelCount()) break;
|
||||||
e->song.pat[cursor.xCoarse].effectRows++;
|
e->song.pat[cursor.xCoarse].effectCols++;
|
||||||
if (e->song.pat[cursor.xCoarse].effectRows>8) e->song.pat[cursor.xCoarse].effectRows=8;
|
if (e->song.pat[cursor.xCoarse].effectCols>8) e->song.pat[cursor.xCoarse].effectCols=8;
|
||||||
break;
|
break;
|
||||||
case GUI_ACTION_PAT_DECREASE_COLUMNS:
|
case GUI_ACTION_PAT_DECREASE_COLUMNS:
|
||||||
if (cursor.xCoarse<0 || cursor.xCoarse>=e->getTotalChannelCount()) break;
|
if (cursor.xCoarse<0 || cursor.xCoarse>=e->getTotalChannelCount()) break;
|
||||||
e->song.pat[cursor.xCoarse].effectRows--;
|
e->song.pat[cursor.xCoarse].effectCols--;
|
||||||
if (e->song.pat[cursor.xCoarse].effectRows<1) e->song.pat[cursor.xCoarse].effectRows=1;
|
if (e->song.pat[cursor.xCoarse].effectCols<1) e->song.pat[cursor.xCoarse].effectCols=1;
|
||||||
break;
|
break;
|
||||||
case GUI_ACTION_PAT_INTERPOLATE:
|
case GUI_ACTION_PAT_INTERPOLATE:
|
||||||
doInterpolate();
|
doInterpolate();
|
||||||
|
|
|
@ -137,12 +137,12 @@ void FurnaceGUI::makeUndo(ActionType action) {
|
||||||
void FurnaceGUI::doSelectAll() {
|
void FurnaceGUI::doSelectAll() {
|
||||||
finishSelection();
|
finishSelection();
|
||||||
curNibble=false;
|
curNibble=false;
|
||||||
if (selStart.xFine==0 && selEnd.xFine==2+e->song.pat[selEnd.xCoarse].effectRows*2) {
|
if (selStart.xFine==0 && selEnd.xFine==2+e->song.pat[selEnd.xCoarse].effectCols*2) {
|
||||||
if (selStart.y==0 && selEnd.y==e->song.patLen-1) { // select entire pattern
|
if (selStart.y==0 && selEnd.y==e->song.patLen-1) { // select entire pattern
|
||||||
selStart.xCoarse=0;
|
selStart.xCoarse=0;
|
||||||
selStart.xFine=0;
|
selStart.xFine=0;
|
||||||
selEnd.xCoarse=e->getTotalChannelCount()-1;
|
selEnd.xCoarse=e->getTotalChannelCount()-1;
|
||||||
selEnd.xFine=2+e->song.pat[selEnd.xCoarse].effectRows*2;
|
selEnd.xFine=2+e->song.pat[selEnd.xCoarse].effectCols*2;
|
||||||
} else { // select entire column
|
} else { // select entire column
|
||||||
selStart.y=0;
|
selStart.y=0;
|
||||||
selEnd.y=e->song.patLen-1;
|
selEnd.y=e->song.patLen-1;
|
||||||
|
@ -153,14 +153,14 @@ void FurnaceGUI::doSelectAll() {
|
||||||
// find row position
|
// find row position
|
||||||
for (SelectionPoint i; i.xCoarse!=selStart.xCoarse || i.xFine!=selStart.xFine; selStartX++) {
|
for (SelectionPoint i; i.xCoarse!=selStart.xCoarse || i.xFine!=selStart.xFine; selStartX++) {
|
||||||
i.xFine++;
|
i.xFine++;
|
||||||
if (i.xFine>=3+e->song.pat[i.xCoarse].effectRows*2) {
|
if (i.xFine>=3+e->song.pat[i.xCoarse].effectCols*2) {
|
||||||
i.xFine=0;
|
i.xFine=0;
|
||||||
i.xCoarse++;
|
i.xCoarse++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (SelectionPoint i; i.xCoarse!=selEnd.xCoarse || i.xFine!=selEnd.xFine; selEndX++) {
|
for (SelectionPoint i; i.xCoarse!=selEnd.xCoarse || i.xFine!=selEnd.xFine; selEndX++) {
|
||||||
i.xFine++;
|
i.xFine++;
|
||||||
if (i.xFine>=3+e->song.pat[i.xCoarse].effectRows*2) {
|
if (i.xFine>=3+e->song.pat[i.xCoarse].effectCols*2) {
|
||||||
i.xFine=0;
|
i.xFine=0;
|
||||||
i.xCoarse++;
|
i.xCoarse++;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ void FurnaceGUI::doSelectAll() {
|
||||||
selEnd.y=e->song.patLen-1;
|
selEnd.y=e->song.patLen-1;
|
||||||
} else { // left-right
|
} else { // left-right
|
||||||
selStart.xFine=0;
|
selStart.xFine=0;
|
||||||
selEnd.xFine=2+e->song.pat[selEnd.xCoarse].effectRows*2;
|
selEnd.xFine=2+e->song.pat[selEnd.xCoarse].effectCols*2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ void FurnaceGUI::doDelete() {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskDelete,iFine);
|
maskOut(opMaskDelete,iFine);
|
||||||
for (int j=selStart.y; j<=selEnd.y; j++) {
|
for (int j=selStart.y; j<=selEnd.y; j++) {
|
||||||
if (iFine==0) {
|
if (iFine==0) {
|
||||||
|
@ -237,7 +237,7 @@ void FurnaceGUI::doPullDelete() {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskPullDelete,iFine);
|
maskOut(opMaskPullDelete,iFine);
|
||||||
for (int j=selStart.y; j<e->song.patLen; j++) {
|
for (int j=selStart.y; j<e->song.patLen; j++) {
|
||||||
if (j<e->song.patLen-1) {
|
if (j<e->song.patLen-1) {
|
||||||
|
@ -269,7 +269,7 @@ void FurnaceGUI::doInsert() {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskInsert,iFine);
|
maskOut(opMaskInsert,iFine);
|
||||||
for (int j=e->song.patLen-1; j>=selStart.y; j--) {
|
for (int j=e->song.patLen-1; j>=selStart.y; j--) {
|
||||||
if (j==selStart.y) {
|
if (j==selStart.y) {
|
||||||
|
@ -301,7 +301,7 @@ void FurnaceGUI::doTranspose(int amount, OperationMask& mask) {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(mask,iFine);
|
maskOut(mask,iFine);
|
||||||
for (int j=selStart.y; j<=selEnd.y; j++) {
|
for (int j=selStart.y; j<=selEnd.y; j++) {
|
||||||
if (iFine==0) {
|
if (iFine==0) {
|
||||||
|
@ -369,7 +369,7 @@ void FurnaceGUI::doCopy(bool cut) {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
if (iFine==0) {
|
if (iFine==0) {
|
||||||
clipboard+=noteNameNormal(pat->data[j][0],pat->data[j][1]);
|
clipboard+=noteNameNormal(pat->data[j][0],pat->data[j][1]);
|
||||||
if (cut) {
|
if (cut) {
|
||||||
|
@ -530,7 +530,7 @@ void FurnaceGUI::doPaste(PasteMode mode) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (mode!=GUI_PASTE_MODE_MIX_BG || pat->data[j][iFine+1]==-1) {
|
if (mode!=GUI_PASTE_MODE_MIX_BG || pat->data[j][iFine+1]==-1) {
|
||||||
if (iFine<(3+e->song.pat[iCoarse].effectRows*2)) pat->data[j][iFine+1]=val;
|
if (iFine<(3+e->song.pat[iCoarse].effectCols*2)) pat->data[j][iFine+1]=val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -589,7 +589,7 @@ void FurnaceGUI::doInterpolate() {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskInterpolate,iFine);
|
maskOut(opMaskInterpolate,iFine);
|
||||||
points.clear();
|
points.clear();
|
||||||
if (iFine!=0) {
|
if (iFine!=0) {
|
||||||
|
@ -648,7 +648,7 @@ void FurnaceGUI::doFade(int p0, int p1, bool mode) {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskFade,iFine);
|
maskOut(opMaskFade,iFine);
|
||||||
if (iFine!=0) {
|
if (iFine!=0) {
|
||||||
int absoluteTop=255;
|
int absoluteTop=255;
|
||||||
|
@ -686,7 +686,7 @@ void FurnaceGUI::doInvertValues() {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskInvertVal,iFine);
|
maskOut(opMaskInvertVal,iFine);
|
||||||
if (iFine!=0) {
|
if (iFine!=0) {
|
||||||
int top=255;
|
int top=255;
|
||||||
|
@ -717,7 +717,7 @@ void FurnaceGUI::doScale(float top) {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskScale,iFine);
|
maskOut(opMaskScale,iFine);
|
||||||
if (iFine!=0) {
|
if (iFine!=0) {
|
||||||
int absoluteTop=255;
|
int absoluteTop=255;
|
||||||
|
@ -748,7 +748,7 @@ void FurnaceGUI::doRandomize(int bottom, int top, bool mode) {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskRandomize,iFine);
|
maskOut(opMaskRandomize,iFine);
|
||||||
if (iFine!=0) {
|
if (iFine!=0) {
|
||||||
int absoluteTop=255;
|
int absoluteTop=255;
|
||||||
|
@ -794,7 +794,7 @@ void FurnaceGUI::doFlip() {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskFlip,iFine);
|
maskOut(opMaskFlip,iFine);
|
||||||
for (int j=selStart.y; j<=selEnd.y; j++) {
|
for (int j=selStart.y; j<=selEnd.y; j++) {
|
||||||
if (iFine==0) {
|
if (iFine==0) {
|
||||||
|
@ -825,7 +825,7 @@ void FurnaceGUI::doCollapse(int divider) {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskCollapseExpand,iFine);
|
maskOut(opMaskCollapseExpand,iFine);
|
||||||
for (int j=selStart.y; j<=selEnd.y; j++) {
|
for (int j=selStart.y; j<=selEnd.y; j++) {
|
||||||
if (iFine==0) {
|
if (iFine==0) {
|
||||||
|
@ -882,7 +882,7 @@ void FurnaceGUI::doExpand(int multiplier) {
|
||||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||||
if (!e->song.chanShow[iCoarse]) continue;
|
if (!e->song.chanShow[iCoarse]) continue;
|
||||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true);
|
||||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
for (; iFine<3+e->song.pat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||||
maskOut(opMaskCollapseExpand,iFine);
|
maskOut(opMaskCollapseExpand,iFine);
|
||||||
for (int j=selStart.y; j<=selEnd.y; j++) {
|
for (int j=selStart.y; j<=selEnd.y; j++) {
|
||||||
if (iFine==0) {
|
if (iFine==0) {
|
||||||
|
|
|
@ -1003,7 +1003,7 @@ void FurnaceGUI::valueInput(int num, bool direct, int target) {
|
||||||
editAdvance();
|
editAdvance();
|
||||||
} else {
|
} else {
|
||||||
if (settings.effectCursorDir==2) {
|
if (settings.effectCursorDir==2) {
|
||||||
if (++cursor.xFine>=(3+(e->song.pat[cursor.xCoarse].effectRows*2))) {
|
if (++cursor.xFine>=(3+(e->song.pat[cursor.xCoarse].effectCols*2))) {
|
||||||
cursor.xFine=3;
|
cursor.xFine=3;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3613,6 +3613,10 @@ bool FurnaceGUI::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(sdlWin),&displaySize)==0) {
|
if (SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(sdlWin),&displaySize)==0) {
|
||||||
|
if (scrW>((displaySize.w/dpiScale)-48) && scrH>((displaySize.h/dpiScale)-64)) {
|
||||||
|
// maximize
|
||||||
|
SDL_MaximizeWindow(sdlWin);
|
||||||
|
}
|
||||||
if (scrW>displaySize.w/dpiScale) scrW=(displaySize.w/dpiScale)-32;
|
if (scrW>displaySize.w/dpiScale) scrW=(displaySize.w/dpiScale)-32;
|
||||||
if (scrH>displaySize.h/dpiScale) scrH=(displaySize.h/dpiScale)-32;
|
if (scrH>displaySize.h/dpiScale) scrH=(displaySize.h/dpiScale)-32;
|
||||||
if (!fullScreen) {
|
if (!fullScreen) {
|
||||||
|
|
|
@ -825,6 +825,7 @@ class FurnaceGUI {
|
||||||
int loadJapanese;
|
int loadJapanese;
|
||||||
int fmLayout;
|
int fmLayout;
|
||||||
int sampleLayout;
|
int sampleLayout;
|
||||||
|
int waveLayout;
|
||||||
int susPosition;
|
int susPosition;
|
||||||
int effectCursorDir;
|
int effectCursorDir;
|
||||||
int cursorPastePos;
|
int cursorPastePos;
|
||||||
|
@ -903,6 +904,7 @@ class FurnaceGUI {
|
||||||
loadJapanese(0),
|
loadJapanese(0),
|
||||||
fmLayout(0),
|
fmLayout(0),
|
||||||
sampleLayout(0),
|
sampleLayout(0),
|
||||||
|
waveLayout(0),
|
||||||
susPosition(0),
|
susPosition(0),
|
||||||
effectCursorDir(1),
|
effectCursorDir(1),
|
||||||
cursorPastePos(1),
|
cursorPastePos(1),
|
||||||
|
|
|
@ -80,11 +80,11 @@ const int vgmVersions[6]={
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* insTypes[DIV_INS_MAX]={
|
const char* insTypes[DIV_INS_MAX]={
|
||||||
"Standard",
|
"Standard (SMS/NES)",
|
||||||
"FM (4-operator)",
|
"FM (4-operator)",
|
||||||
"Game Boy",
|
"Game Boy",
|
||||||
"C64",
|
"C64",
|
||||||
"Amiga/Sample",
|
"Sample",
|
||||||
"PC Engine",
|
"PC Engine",
|
||||||
"AY-3-8910/SSG",
|
"AY-3-8910/SSG",
|
||||||
"AY8930",
|
"AY8930",
|
||||||
|
|
|
@ -2465,9 +2465,10 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
P(ImGui::Checkbox("Volume Macro is Cutoff Macro",&ins->c64.volIsCutoff));
|
P(ImGui::Checkbox("Volume Macro is Cutoff Macro",&ins->c64.volIsCutoff));
|
||||||
P(ImGui::Checkbox("Absolute Cutoff Macro",&ins->c64.filterIsAbs));
|
P(ImGui::Checkbox("Absolute Cutoff Macro",&ins->c64.filterIsAbs));
|
||||||
P(ImGui::Checkbox("Absolute Duty Macro",&ins->c64.dutyIsAbs));
|
P(ImGui::Checkbox("Absolute Duty Macro",&ins->c64.dutyIsAbs));
|
||||||
|
P(ImGui::Checkbox("Don't test/gate before new note",&ins->c64.noTest));
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_ES5506) if (ImGui::BeginTabItem("Amiga/Sample")) {
|
if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_ES5506) if (ImGui::BeginTabItem("Sample")) {
|
||||||
String sName;
|
String sName;
|
||||||
if (ins->amiga.initSample<0 || ins->amiga.initSample>=e->song.sampleLen) {
|
if (ins->amiga.initSample<0 || ins->amiga.initSample>=e->song.sampleLen) {
|
||||||
sName="none selected";
|
sName="none selected";
|
||||||
|
@ -2920,7 +2921,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
ex2Max=4095;
|
ex2Max=4095;
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_SU) {
|
if (ins->type==DIV_INS_SU) {
|
||||||
ex1Max=65535;
|
ex1Max=16383;
|
||||||
ex2Max=255;
|
ex2Max=255;
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_SAA1099) ex1Max=8;
|
if (ins->type==DIV_INS_SAA1099) ex1Max=8;
|
||||||
|
@ -2985,7 +2986,8 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
ins->type==DIV_INS_AY ||
|
ins->type==DIV_INS_AY ||
|
||||||
ins->type==DIV_INS_AY8930 ||
|
ins->type==DIV_INS_AY8930 ||
|
||||||
ins->type==DIV_INS_SWAN ||
|
ins->type==DIV_INS_SWAN ||
|
||||||
ins->type==DIV_INS_ES5506) {
|
ins->type==DIV_INS_ES5506 ||
|
||||||
|
ins->type==DIV_INS_SU) {
|
||||||
NORMAL_MACRO(ins->std.phaseResetMacro,0,1,"phaseReset","Phase Reset",32,ins->std.phaseResetMacro.open,true,NULL,false,NULL,0,0,0,0,false,0,macroDummyMode,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[16],0,1,NULL,false);
|
NORMAL_MACRO(ins->std.phaseResetMacro,0,1,"phaseReset","Phase Reset",32,ins->std.phaseResetMacro.open,true,NULL,false,NULL,0,0,0,0,false,0,macroDummyMode,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[16],0,1,NULL,false);
|
||||||
}
|
}
|
||||||
if (ex1Max>0) {
|
if (ex1Max>0) {
|
||||||
|
@ -3024,6 +3026,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_C64) {
|
if (ins->type==DIV_INS_C64) {
|
||||||
NORMAL_MACRO(ins->std.ex3Macro,0,2,"ex3","Special",32,ins->std.ex3Macro.open,true,c64SpecialBits,false,NULL,0,0,0,0,false,0,macroDummyMode,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2,NULL,false);
|
NORMAL_MACRO(ins->std.ex3Macro,0,2,"ex3","Special",32,ins->std.ex3Macro.open,true,c64SpecialBits,false,NULL,0,0,0,0,false,0,macroDummyMode,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2,NULL,false);
|
||||||
|
NORMAL_MACRO(ins->std.ex4Macro,0,1,"ex4","Test/Gate",32,ins->std.ex4Macro.open,true,NULL,false,NULL,0,0,0,0,false,0,macroDummyMode,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[7],0,1,NULL,false);
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930 || ins->type==DIV_INS_X1_010) {
|
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930 || ins->type==DIV_INS_X1_010) {
|
||||||
NORMAL_MACRO(ins->std.ex3Macro,0,15,"ex3","AutoEnv Num",96,ins->std.ex3Macro.open,false,NULL,false,NULL,0,0,0,0,false,0,macroDummyMode,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15,NULL,false);
|
NORMAL_MACRO(ins->std.ex3Macro,0,15,"ex3","AutoEnv Num",96,ins->std.ex3Macro.open,false,NULL,false,NULL,0,0,0,0,false,0,macroDummyMode,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15,NULL,false);
|
||||||
|
|
|
@ -217,7 +217,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
// effects
|
// effects
|
||||||
for (int k=0; k<e->song.pat[j].effectRows; k++) {
|
for (int k=0; k<e->song.pat[j].effectCols; k++) {
|
||||||
int index=4+(k<<1);
|
int index=4+(k<<1);
|
||||||
bool selectedEffect=selectedRow && (j32+index-1>=sel1XSum && j32+index-1<=sel2XSum);
|
bool selectedEffect=selectedRow && (j32+index-1>=sel1XSum && j32+index-1<=sel2XSum);
|
||||||
bool selectedEffectVal=selectedRow && (j32+index>=sel1XSum && j32+index<=sel2XSum);
|
bool selectedEffectVal=selectedRow && (j32+index>=sel1XSum && j32+index<=sel2XSum);
|
||||||
|
@ -427,7 +427,7 @@ void FurnaceGUI::drawPattern() {
|
||||||
displayTooltip=true;
|
displayTooltip=true;
|
||||||
} else {
|
} else {
|
||||||
const char* chName=e->getChannelName(i);
|
const char* chName=e->getChannelName(i);
|
||||||
size_t chNameLimit=6+4*e->song.pat[i].effectRows;
|
size_t chNameLimit=6+4*e->song.pat[i].effectCols;
|
||||||
if (strlen(chName)>chNameLimit) {
|
if (strlen(chName)>chNameLimit) {
|
||||||
String shortChName=chName;
|
String shortChName=chName;
|
||||||
shortChName.resize(chNameLimit-3);
|
shortChName.resize(chNameLimit-3);
|
||||||
|
@ -524,18 +524,18 @@ void FurnaceGUI::drawPattern() {
|
||||||
if (!e->song.chanCollapse[i]) {
|
if (!e->song.chanCollapse[i]) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
snprintf(chanID,2048,"<##_LCH%d",i);
|
snprintf(chanID,2048,"<##_LCH%d",i);
|
||||||
ImGui::BeginDisabled(e->song.pat[i].effectRows<=1);
|
ImGui::BeginDisabled(e->song.pat[i].effectCols<=1);
|
||||||
if (ImGui::SmallButton(chanID)) {
|
if (ImGui::SmallButton(chanID)) {
|
||||||
e->song.pat[i].effectRows--;
|
e->song.pat[i].effectCols--;
|
||||||
if (e->song.pat[i].effectRows<1) e->song.pat[i].effectRows=1;
|
if (e->song.pat[i].effectCols<1) e->song.pat[i].effectCols=1;
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::BeginDisabled(e->song.pat[i].effectRows>=8);
|
ImGui::BeginDisabled(e->song.pat[i].effectCols>=8);
|
||||||
snprintf(chanID,2048,">##_RCH%d",i);
|
snprintf(chanID,2048,">##_RCH%d",i);
|
||||||
if (ImGui::SmallButton(chanID)) {
|
if (ImGui::SmallButton(chanID)) {
|
||||||
e->song.pat[i].effectRows++;
|
e->song.pat[i].effectCols++;
|
||||||
if (e->song.pat[i].effectRows>8) e->song.pat[i].effectRows=8;
|
if (e->song.pat[i].effectCols>8) e->song.pat[i].effectCols=8;
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
|
@ -990,6 +990,11 @@ void FurnaceGUI::drawSettings() {
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
bool waveLayoutB=settings.waveLayout;
|
||||||
|
if (ImGui::Checkbox("Use compact wave editor",&waveLayoutB)) {
|
||||||
|
settings.waveLayout=waveLayoutB;
|
||||||
|
}
|
||||||
|
|
||||||
bool sampleLayoutB=settings.sampleLayout;
|
bool sampleLayoutB=settings.sampleLayout;
|
||||||
if (ImGui::Checkbox("Use compact sample editor",&sampleLayoutB)) {
|
if (ImGui::Checkbox("Use compact sample editor",&sampleLayoutB)) {
|
||||||
settings.sampleLayout=sampleLayoutB;
|
settings.sampleLayout=sampleLayoutB;
|
||||||
|
@ -1656,6 +1661,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
settings.loadJapanese=e->getConfInt("loadJapanese",0);
|
settings.loadJapanese=e->getConfInt("loadJapanese",0);
|
||||||
settings.fmLayout=e->getConfInt("fmLayout",0);
|
settings.fmLayout=e->getConfInt("fmLayout",0);
|
||||||
settings.sampleLayout=e->getConfInt("sampleLayout",0);
|
settings.sampleLayout=e->getConfInt("sampleLayout",0);
|
||||||
|
settings.waveLayout=e->getConfInt("waveLayout",0);
|
||||||
settings.susPosition=e->getConfInt("susPosition",0);
|
settings.susPosition=e->getConfInt("susPosition",0);
|
||||||
settings.effectCursorDir=e->getConfInt("effectCursorDir",1);
|
settings.effectCursorDir=e->getConfInt("effectCursorDir",1);
|
||||||
settings.cursorPastePos=e->getConfInt("cursorPastePos",1);
|
settings.cursorPastePos=e->getConfInt("cursorPastePos",1);
|
||||||
|
@ -1733,6 +1739,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
clampSetting(settings.frameBorders,0,1);
|
clampSetting(settings.frameBorders,0,1);
|
||||||
clampSetting(settings.effectDeletionAltersValue,0,1);
|
clampSetting(settings.effectDeletionAltersValue,0,1);
|
||||||
clampSetting(settings.sampleLayout,0,1);
|
clampSetting(settings.sampleLayout,0,1);
|
||||||
|
clampSetting(settings.waveLayout,0,1);
|
||||||
clampSetting(settings.separateFMColors,0,1);
|
clampSetting(settings.separateFMColors,0,1);
|
||||||
clampSetting(settings.insEditColorize,0,1);
|
clampSetting(settings.insEditColorize,0,1);
|
||||||
clampSetting(settings.metroVol,0,200);
|
clampSetting(settings.metroVol,0,200);
|
||||||
|
@ -1817,6 +1824,7 @@ void FurnaceGUI::commitSettings() {
|
||||||
e->setConf("loadJapanese",settings.loadJapanese);
|
e->setConf("loadJapanese",settings.loadJapanese);
|
||||||
e->setConf("fmLayout",settings.fmLayout);
|
e->setConf("fmLayout",settings.fmLayout);
|
||||||
e->setConf("sampleLayout",settings.sampleLayout);
|
e->setConf("sampleLayout",settings.sampleLayout);
|
||||||
|
e->setConf("waveLayout",settings.waveLayout);
|
||||||
e->setConf("susPosition",settings.susPosition);
|
e->setConf("susPosition",settings.susPosition);
|
||||||
e->setConf("effectCursorDir",settings.effectCursorDir);
|
e->setConf("effectCursorDir",settings.effectCursorDir);
|
||||||
e->setConf("cursorPastePos",settings.cursorPastePos);
|
e->setConf("cursorPastePos",settings.cursorPastePos);
|
||||||
|
|
|
@ -31,7 +31,7 @@ void FurnaceGUI::drawWaveEdit() {
|
||||||
}
|
}
|
||||||
if (!waveEditOpen) return;
|
if (!waveEditOpen) return;
|
||||||
float wavePreview[256];
|
float wavePreview[256];
|
||||||
ImGui::SetNextWindowSizeConstraints(ImVec2(450.0f*dpiScale,300.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
|
ImGui::SetNextWindowSizeConstraints(ImVec2(300.0f*dpiScale,300.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
|
||||||
if (ImGui::Begin("Wavetable Editor",&waveEditOpen,settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking)) {
|
if (ImGui::Begin("Wavetable Editor",&waveEditOpen,settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking)) {
|
||||||
if (curWave<0 || curWave>=(int)e->song.wave.size()) {
|
if (curWave<0 || curWave>=(int)e->song.wave.size()) {
|
||||||
ImGui::Text("no wavetable selected");
|
ImGui::Text("no wavetable selected");
|
||||||
|
@ -53,6 +53,8 @@ void FurnaceGUI::drawWaveEdit() {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
DivWavetable* wave=e->song.wave[curWave];
|
DivWavetable* wave=e->song.wave[curWave];
|
||||||
|
|
||||||
|
if (!settings.waveLayout){
|
||||||
ImGui::Text("Width");
|
ImGui::Text("Width");
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip("use a width of:\n- any on Amiga/N163\n- 32 on Game Boy, PC Engine and WonderSwan\n- 64 on FDS\n- 128 on X1-010\nany other widths will be scaled during playback.");
|
ImGui::SetTooltip("use a width of:\n- any on Amiga/N163\n- 32 on Game Boy, PC Engine and WonderSwan\n- 64 on FDS\n- 128 on X1-010\nany other widths will be scaled during playback.");
|
||||||
|
@ -79,6 +81,7 @@ void FurnaceGUI::drawWaveEdit() {
|
||||||
e->notifyWaveChange(curWave);
|
e->notifyWaveChange(curWave);
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::RadioButton("Dec",!waveHex)) {
|
if (ImGui::RadioButton("Dec",!waveHex)) {
|
||||||
waveHex=false;
|
waveHex=false;
|
||||||
|
@ -87,6 +90,42 @@ void FurnaceGUI::drawWaveEdit() {
|
||||||
if (ImGui::RadioButton("Hex",waveHex)) {
|
if (ImGui::RadioButton("Hex",waveHex)) {
|
||||||
waveHex=true;
|
waveHex=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.waveLayout){
|
||||||
|
if (ImGui::BeginTable("WaveProps",2,ImGuiTableFlags_SizingStretchSame)) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("Width");
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("use a width of:\n- any on Amiga/N163\n- 32 on Game Boy, PC Engine and WonderSwan\n- 64 on FDS\n- 128 on X1-010\nany other widths will be scaled during playback.");
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
if (ImGui::InputInt("##_WTW",&wave->len,1,2)) {
|
||||||
|
if (wave->len>256) wave->len=256;
|
||||||
|
if (wave->len<1) wave->len=1;
|
||||||
|
e->notifyWaveChange(curWave);
|
||||||
|
if (wavePreviewOn) e->previewWave(curWave,wavePreviewNote);
|
||||||
|
MARK_MODIFIED;
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("Height");
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("use a height of:\n- 15 for Game Boy, WonderSwan, X1-010 Envelope shape and N163\n- 31 for PC Engine\n- 63 for FDS\n- 255 for X1-010\nany other heights will be scaled during playback.");
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
if (ImGui::InputInt("##_WTH",&wave->max,1,2)) {
|
||||||
|
if (wave->max>255) wave->max=255;
|
||||||
|
if (wave->max<1) wave->max=1;
|
||||||
|
e->notifyWaveChange(curWave);
|
||||||
|
MARK_MODIFIED;
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0; i<wave->len; i++) {
|
for (int i=0; i<wave->len; i++) {
|
||||||
if (wave->data[i]>wave->max) wave->data[i]=wave->max;
|
if (wave->data[i]>wave->max) wave->data[i]=wave->max;
|
||||||
wavePreview[i]=wave->data[i];
|
wavePreview[i]=wave->data[i];
|
||||||
|
|
Loading…
Reference in New Issue