mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-30 16:33:01 +00:00
Merge branch 'master' of https://github.com/tildearrow/furnace into nmk112
This commit is contained in:
commit
b12af42b06
43 changed files with 160 additions and 70 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -307,7 +307,7 @@ jobs:
|
|||
cp -v -r ../instruments new/instruments
|
||||
cp -v -r ../wavetables new/wavetables
|
||||
cd new
|
||||
wget https://tildearrow.org/furproto/manual.pdf
|
||||
wget https://tildearrow.org/furnace/doc/latest/manual.pdf
|
||||
cd ..
|
||||
|
||||
hdiutil create -srcfolder new -volname Furnace -format UDZO furnace.dmg
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -27,6 +27,7 @@ CMakePresets.json
|
|||
extern/imgui_patched/examples/
|
||||
src/asm/68k/amigatest/*.bin
|
||||
src/asm/68k/amigatest/player
|
||||
src/check/calc_checksum
|
||||
res/binary_to_compressed_c
|
||||
res/binary_to_compressed_c.exe
|
||||
res/docpdf/manual.html
|
||||
|
|
|
@ -17,7 +17,7 @@ for other operating systems, you may [build the source](#developer-info).
|
|||
|
||||
## features
|
||||
|
||||
- over 50 sound chips - and counting:
|
||||
- a large selection of sound chips:
|
||||
- Yamaha FM chips:
|
||||
- YM2151 (OPM)
|
||||
- YM2203 (OPN)
|
||||
|
@ -103,7 +103,7 @@ for other operating systems, you may [build the source](#developer-info).
|
|||
- quality emulation cores (Nuked, MAME, SameBoy, Mednafen PCE, NSFplay, puNES, reSID, Stella, SAASound, vgsound_emu and ymfm)
|
||||
- wavetable synthesizer
|
||||
- available on wavetable chips
|
||||
- create complex sounds with ease - provide up to two wavetables, select and effect and let go!
|
||||
- create complex sounds with ease - provide up to two wavetables, select an effect and let go!
|
||||
- MIDI input support
|
||||
- additional features:
|
||||
- FM macros!
|
||||
|
@ -327,7 +327,7 @@ it is in [doc/](doc/README.md).
|
|||
|
||||
> is there a tutorial?
|
||||
|
||||
sadly, the in-program tutorial isn't ready yet. however, [a video tutorial is available on YouTube](https://youtube.com/playlist?list=PLCELB6AsTZUnwv0PC5AAGHjvg47F44YQ1), made by Spinning Square Waves.
|
||||
[a video tutorial (of a previous version) is available on YouTube](https://youtube.com/playlist?list=PLCELB6AsTZUnwv0PC5AAGHjvg47F44YQ1), made by Spinning Square Waves.
|
||||
|
||||
> I've lost my song!
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ android {
|
|||
}
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 26
|
||||
versionCode 178
|
||||
versionName "0.6pre16"
|
||||
versionCode 181
|
||||
versionName "0.6"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DANDROID_APP_PLATFORM=android-21", "-DANDROID_STL=c++_static", "-DWARNINGS_ARE_ERRORS=ON"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.tildearrow.furnace"
|
||||
android:versionCode="178"
|
||||
android:versionName="0.6pre16"
|
||||
android:versionCode="181"
|
||||
android:versionName="0.6"
|
||||
android:installLocation="auto">
|
||||
|
||||
<!-- OpenGL ES 2.0 -->
|
||||
|
|
BIN
demos/arcade/Hexionology.fur
Normal file
BIN
demos/arcade/Hexionology.fur
Normal file
Binary file not shown.
BIN
demos/ay8910/Drifting in Colour.fur
Normal file
BIN
demos/ay8910/Drifting in Colour.fur
Normal file
Binary file not shown.
BIN
demos/ay8910/cardboardmywater.fur
Normal file
BIN
demos/ay8910/cardboardmywater.fur
Normal file
Binary file not shown.
BIN
demos/genesis/All Good Times.fur
Normal file
BIN
demos/genesis/All Good Times.fur
Normal file
Binary file not shown.
BIN
demos/msx/attack_the_barbarian.fur
Normal file
BIN
demos/msx/attack_the_barbarian.fur
Normal file
Binary file not shown.
Binary file not shown.
BIN
demos/snes/IMU Café.fur
Normal file
BIN
demos/snes/IMU Café.fur
Normal file
Binary file not shown.
BIN
demos/snes/Sadness.fur
Normal file
BIN
demos/snes/Sadness.fur
Normal file
Binary file not shown.
|
@ -53,7 +53,7 @@ these apply to each operator:
|
|||
- does not apply for OP4.
|
||||
- **Reverb (REV)**: not a true reverb. extends release time, giving a slight reverb-like effect to the operator.
|
||||
- **Fine Detune (DT)**: shifts the pitch a little (0 to 7).
|
||||
- **Waveform Select (WS)**: changes the waveform of the operator (OPL2 and OPL3 only, 0-3 range on OPL2 and 0-7 on OPL3).
|
||||
- **Waveform Select (WS)**: changes the waveform of the operator.
|
||||
- **Coarse Detune (DT2)**: shifts the pitch by tens of cents (0 to 3).
|
||||
|
||||
#### I am familiar with Yamaha TX81Z. where's LS and KVS?
|
||||
|
|
|
@ -11,7 +11,7 @@ this allows you to enable and configure the Furnace wavetable synthesizer. see [
|
|||
- **Volume**: volume sequence.
|
||||
- **Arpeggio**: pitch sequence.
|
||||
- **Noise**: specifies noise pitch.
|
||||
- only applicable for Namco C30, and even so, only on the last 4 channels.
|
||||
- only applicable for Namco C30.
|
||||
- **Waveform**: specifies wavetable sequence.
|
||||
- **Panning (left)**: output level of left channel.
|
||||
- Namco C30 only.
|
||||
|
|
|
@ -39,6 +39,14 @@ the following sound chips have sample support:
|
|||
- Namco C140
|
||||
- Namco C219
|
||||
|
||||
## using samples
|
||||
|
||||
the simplest path to using a sample is:
|
||||
- in the sample list, use the "Open" button (folder icon) to load the sample.
|
||||
- double-click the sample in the list to open it in the sample editor.
|
||||
- click the "Create instrument from sample" button (upload icon, to the left of "Zoom").
|
||||
- use the created instrument in the track.
|
||||
|
||||
## compatible sample mode (LEGACY)
|
||||
|
||||
**use of this mode is discouraged in favor of Sample type instruments.**
|
||||
|
|
|
@ -16,11 +16,13 @@ the index follows.
|
|||
|
||||
## authors
|
||||
|
||||
- brickblock369
|
||||
- cam900
|
||||
- DeMOSic
|
||||
- Electric Keet
|
||||
- freq-mod
|
||||
- host12prog
|
||||
- Lunathir
|
||||
- nicco1690
|
||||
- tildearrow
|
||||
|
||||
|
|
2
extern/igfd/ImGuiFileDialog.cpp
vendored
2
extern/igfd/ImGuiFileDialog.cpp
vendored
|
@ -3859,7 +3859,7 @@ namespace IGFD
|
|||
}
|
||||
}
|
||||
#endif
|
||||
for (const char* i=n; *i; i++) {
|
||||
for (const unsigned char* i=(const unsigned char*)n; *i; i++) {
|
||||
#ifdef _WIN32
|
||||
if (*i<32) {
|
||||
return 3;
|
||||
|
|
|
@ -6,7 +6,7 @@ when copying pattern data from Furnace, it's stored in the clipboard as plain te
|
|||
org.tildearrow.furnace - Pattern Data (144)
|
||||
```
|
||||
|
||||
this top line of text is always the same except for the number in parentheses, which is the internal build number. for example, 0.6pre16 is `178`.
|
||||
this top line of text is always the same except for the number in parentheses, which is the internal build number. for example, 0.6 is `181`.
|
||||
|
||||
the second line is a number between 0 and 18 (decimal) which indicates which column the clip starts from.
|
||||
- `0`: note.
|
||||
|
|
|
@ -32,6 +32,9 @@ these fields are 0 in format versions prior to 100 (0.6pre1).
|
|||
|
||||
the format versions are:
|
||||
|
||||
- 181: Furnace 0.6
|
||||
- 180: Furnace 0.6pre18
|
||||
- 179: Furnace 0.6pre17
|
||||
- 178: Furnace 0.6pre16
|
||||
- 177: Furnace 0.6pre15
|
||||
- 175: Furnace 0.6pre14
|
||||
|
|
|
@ -15,17 +15,17 @@
|
|||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>0.6pre16</string>
|
||||
<string>0.6</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Furnace</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.6pre16</string>
|
||||
<string>0.6</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.6pre16</string>
|
||||
<string>0.6</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string></string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
|
|
|
@ -334,11 +334,13 @@ if __name__ == "__main__":
|
|||
<div>
|
||||
<h3>authors</h3>
|
||||
<ul>
|
||||
<li>brickblock369</li>
|
||||
<li>cam900</li>
|
||||
<li>DeMOSic</li>
|
||||
<li>Electric Keet</li>
|
||||
<li>freq-mod</li>
|
||||
<li>host12prog</li>
|
||||
<li>Lunathir</li>
|
||||
<li>nicco1690</li>
|
||||
<li>tildearrow</li>
|
||||
</ul>
|
||||
|
|
|
@ -52,7 +52,7 @@ cd ..
|
|||
cp ../../../LICENSE . || exit 1
|
||||
cp ../../../res/releaseReadme/stable-linux.txt README.md || exit 1
|
||||
cp -r ../../../papers papers || exit 1
|
||||
curl "https://tildearrow.org/furproto/manual.pdf" > manual.pdf
|
||||
curl "https://tildearrow.org/furnace/doc/latest/manual.pdf" > manual.pdf
|
||||
rmdir usr || exit 1
|
||||
|
||||
strip -s furnace
|
||||
|
|
|
@ -35,7 +35,7 @@ cp ../../res/docpdf/manual.pdf . || exit 1
|
|||
|
||||
i686-w64-mingw32-strip -s furnace.exe || exit 1
|
||||
|
||||
zip -r furnace.zip LICENSE.txt furnace.exe README.txt papers doc demos instruments wavetables
|
||||
zip -r furnace.zip LICENSE.txt furnace.exe README.txt manual.pdf papers demos instruments wavetables
|
||||
|
||||
furName=$(git describe --tags | sed "s/v0/0/")
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ cp ../../res/docpdf/manual.pdf . || exit 1
|
|||
|
||||
x86_64-w64-mingw32-strip -s furnace.exe || exit 1
|
||||
|
||||
zip -r furnace.zip LICENSE.txt furnace.exe README.txt papers doc demos instruments wavetables
|
||||
zip -r furnace.zip LICENSE.txt furnace.exe README.txt manual.pdf papers demos instruments wavetables
|
||||
|
||||
furName=$(git describe --tags | sed "s/v0/0/")
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ xxd -c 256 -ps furnace.exe | sed "s/4765745469636b436f756e743634/4765745469636b4
|
|||
rm furnace.exe
|
||||
mv furnace-patched.exe furnace.exe
|
||||
|
||||
zip -r furnace.zip LICENSE.txt furnace.exe README.txt papers doc demos instruments wavetables
|
||||
zip -r furnace.zip LICENSE.txt furnace.exe README.txt manual.pdf papers demos instruments wavetables
|
||||
|
||||
furName=$(git describe --tags | sed "s/v0/0/")
|
||||
|
||||
|
|
|
@ -52,10 +52,10 @@ class DivWorkPool;
|
|||
#define EXTERN_BUSY_BEGIN_SOFT e->softLocked=true; e->isBusy.lock();
|
||||
#define EXTERN_BUSY_END e->isBusy.unlock(); e->softLocked=false;
|
||||
|
||||
#define DIV_UNSTABLE
|
||||
//#define DIV_UNSTABLE
|
||||
|
||||
#define DIV_VERSION "0.6pre16"
|
||||
#define DIV_ENGINE_VERSION 178
|
||||
#define DIV_VERSION "0.6"
|
||||
#define DIV_ENGINE_VERSION 181
|
||||
// for imports
|
||||
#define DIV_VERSION_MOD 0xff01
|
||||
#define DIV_VERSION_FC 0xff02
|
||||
|
|
|
@ -464,6 +464,13 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth,
|
|||
accum/=channels;
|
||||
sample->data8[i]=accum;
|
||||
}
|
||||
if (bigEndian) {
|
||||
for (unsigned int i=0; (i+1)<samples; i+=2) {
|
||||
sample->data8[i]^=sample->data8[i^1];
|
||||
sample->data8[i^1]^=sample->data8[i];
|
||||
sample->data8[i]^=sample->data8[i^1];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memcpy(sample->getCurBuf(),buf,len);
|
||||
}
|
||||
|
|
|
@ -245,10 +245,10 @@ void DivPlatformC140::tick(bool sysTick) {
|
|||
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen && s->isLoopable()) {
|
||||
if (is219) {
|
||||
loop=MIN(start+(s->loopStart>>1),65535);
|
||||
end=MIN(start+(s->loopEnd>>1)-1,65535);
|
||||
end=MIN(start+(s->loopEnd>>1),65535);
|
||||
} else {
|
||||
loop=MIN(start+s->loopStart,65535);
|
||||
end=MIN(start+s->loopEnd-1,65535);
|
||||
loop=MIN(start+s->loopStart+1,65535);
|
||||
end=MIN(start+s->loopEnd+1,65535);
|
||||
}
|
||||
} else if (chan[i].noise && is219) {
|
||||
loop=0;
|
||||
|
@ -575,7 +575,7 @@ void DivPlatformC140::renderSamples(int sysID) {
|
|||
}
|
||||
|
||||
if (is219) { // C219 (8-bit)
|
||||
unsigned int length=s->length8;
|
||||
unsigned int length=s->length8+4;
|
||||
// fit sample size to single bank size
|
||||
if (length>131072) {
|
||||
length=131072;
|
||||
|
@ -594,27 +594,39 @@ void DivPlatformC140::renderSamples(int sysID) {
|
|||
logW("out of C219 memory for sample %d!",i);
|
||||
}
|
||||
if (s->depth==DIV_SAMPLE_DEPTH_C219) {
|
||||
unsigned char next=0;
|
||||
unsigned int sPos=0;
|
||||
for (unsigned int i=0; i<length; i++) {
|
||||
if (i>=s->lengthC219) {
|
||||
sampleMem[(memPos+i)^1]=0;
|
||||
} else {
|
||||
sampleMem[(memPos+i)^1]=s->dataC219[i];
|
||||
if (sPos<s->lengthC219) {
|
||||
next=s->dataC219[sPos++];
|
||||
if (s->isLoopable()) {
|
||||
if ((int)sPos>=s->loopEnd) {
|
||||
sPos=s->loopStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
sampleMem[(memPos+i)^1]=next;
|
||||
}
|
||||
} else {
|
||||
signed char next=0;
|
||||
unsigned int sPos=0;
|
||||
for (unsigned int i=0; i<length; i++) {
|
||||
if (i>=s->length8) {
|
||||
sampleMem[(memPos+i)^1]=0;
|
||||
} else {
|
||||
sampleMem[(memPos+i)^1]=s->data8[i];
|
||||
if (sPos<s->length8) {
|
||||
next=s->data8[sPos++];
|
||||
if (s->isLoopable()) {
|
||||
if ((int)sPos>=s->loopEnd) {
|
||||
sPos=s->loopStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
sampleMem[(memPos+i)^1]=next;
|
||||
}
|
||||
}
|
||||
sampleOff[i]=memPos>>1;
|
||||
sampleLoaded[i]=true;
|
||||
memPos+=length;
|
||||
} else { // C140 (16-bit)
|
||||
unsigned int length=s->length16;
|
||||
unsigned int length=s->length16+4;
|
||||
// fit sample size to single bank size
|
||||
if (length>(131072)) {
|
||||
length=131072;
|
||||
|
@ -641,7 +653,20 @@ void DivPlatformC140::renderSamples(int sysID) {
|
|||
sampleMem[1+i+memPos]=c140Mu;
|
||||
}
|
||||
} else {
|
||||
memcpy(sampleMem+memPos,s->data16,length);
|
||||
short next=0;
|
||||
unsigned int sPos=0;
|
||||
for (unsigned int i=0; i<length; i+=2) {
|
||||
if (sPos<s->samples) {
|
||||
next=s->data16[sPos++];
|
||||
if (s->isLoopable()) {
|
||||
if ((int)sPos>=s->loopEnd) {
|
||||
sPos=s->loopStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
sampleMem[memPos+i]=((unsigned short)next);
|
||||
sampleMem[memPos+i+1]=((unsigned short)next)>>8;
|
||||
}
|
||||
}
|
||||
sampleOff[i]=memPos>>1;
|
||||
sampleLoaded[i]=true;
|
||||
|
|
|
@ -431,7 +431,7 @@ DivMacroInt* DivPlatformK007232::getChanMacroInt(int ch) {
|
|||
}
|
||||
|
||||
unsigned short DivPlatformK007232::getPan(int ch) {
|
||||
return ((chan[ch].panning&15)<<8)|((chan[ch].panning&0xf0)>>4);
|
||||
return stereo?(((chan[ch].panning&15)<<8)|((chan[ch].panning&0xf0)>>4)):0;
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformK007232::getOscBuffer(int ch) {
|
||||
|
|
|
@ -201,7 +201,7 @@ void DivPlatformNamcoWSG::tick(bool sysTick) {
|
|||
if (chan[i].std.vol.had) {
|
||||
chan[i].outVol=((chan[i].vol&15)*MIN(15,chan[i].std.vol.val))>>4;
|
||||
}
|
||||
if (chan[i].std.duty.had && i>=4) {
|
||||
if (chan[i].std.duty.had) {
|
||||
chan[i].noise=chan[i].std.duty.val;
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
@ -418,6 +418,7 @@ int DivPlatformNamcoWSG::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_STD_NOISE_MODE:
|
||||
chan[c.chan].noise=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
case DIV_CMD_PANNING: {
|
||||
chan[c.chan].pan=(c.value&0xf0)|(c.value2>>4);
|
||||
|
|
|
@ -104,7 +104,7 @@ void c140_voice_tick(struct c140_t *c140, const unsigned char v, const int cycle
|
|||
if (!voice->muted)
|
||||
{
|
||||
// fetch 12 bit sample
|
||||
signed short s1 = c140->sample_mem[((unsigned int)(voice->bank) << 16) | voice->addr] & ~0xf;
|
||||
signed short s1 = c140->sample_mem[((unsigned int)(voice->bank) << 16) | (voice->addr & 0xffff)] & ~0xf;
|
||||
signed short s2 = c140->sample_mem[((unsigned int)(voice->bank) << 16) | ((voice->addr + 1) & 0xffff)] & ~0xf;
|
||||
if (voice->compressed)
|
||||
{
|
||||
|
@ -171,7 +171,7 @@ void c219_voice_tick(struct c219_t *c219, const unsigned char v, const int cycle
|
|||
else
|
||||
{
|
||||
// fetch 8 bit sample
|
||||
signed short s1 = c219->sample_mem[((unsigned int)(c219->bank[(v >> 2) & 3]) << 17) | (voice->addr^1)];
|
||||
signed short s1 = c219->sample_mem[((unsigned int)(c219->bank[(v >> 2) & 3]) << 17) | ((voice->addr^1) & 0x1ffff)];
|
||||
signed short s2 = c219->sample_mem[((unsigned int)(c219->bank[(v >> 2) & 3]) << 17) | (((voice->addr + 1) & 0x1ffff)^1)];
|
||||
if (voice->compressed)
|
||||
{
|
||||
|
|
|
@ -1708,6 +1708,10 @@ void DivEngine::registerSystems() {
|
|||
|
||||
EffectHandlerMap namcoEffectHandlerMap={
|
||||
{0x10, {DIV_CMD_WAVE, "10xx: Set waveform"}},
|
||||
};
|
||||
|
||||
EffectHandlerMap namcoC30EffectHandlerMap={
|
||||
{0x10, {DIV_CMD_WAVE, "10xx: Set waveform"}},
|
||||
{0x11, {DIV_CMD_STD_NOISE_MODE, "11xx: Toggle noise mode"}},
|
||||
};
|
||||
|
||||
|
@ -1741,7 +1745,7 @@ void DivEngine::registerSystems() {
|
|||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||
{DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO},
|
||||
{},
|
||||
namcoEffectHandlerMap
|
||||
namcoC30EffectHandlerMap
|
||||
);
|
||||
|
||||
sysDefs[DIV_SYSTEM_MSM5232]=new DivSysDef(
|
||||
|
|
|
@ -1747,13 +1747,13 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
if (!hasRFC1) {
|
||||
hasRFC1=disCont[i].dispatch->chipClock;
|
||||
isSecond[i]=true;
|
||||
CHIP_VOL(16,1.6);
|
||||
CHIP_VOL(16,0.8);
|
||||
willExport[i]=true;
|
||||
writeRF5C68[1]=disCont[i].dispatch;
|
||||
}
|
||||
} else if (!hasRFC) {
|
||||
hasRFC=disCont[i].dispatch->chipClock;
|
||||
CHIP_VOL(5,1.6);
|
||||
CHIP_VOL(5,1.1);
|
||||
willExport[i]=true;
|
||||
writeRF5C68[0]=disCont[i].dispatch;
|
||||
}
|
||||
|
@ -2418,8 +2418,10 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
}
|
||||
while (!done) {
|
||||
if (loopPos==-1) {
|
||||
if (loopOrder==curOrder && loopRow==curRow && ticks==1) {
|
||||
writeLoop=true;
|
||||
if (loopOrder==curOrder && loopRow==curRow) {
|
||||
if ((ticks-((tempoAccum+curSubSong->virtualTempoN)/curSubSong->virtualTempoD))<=0) {
|
||||
writeLoop=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
songTick++;
|
||||
|
|
|
@ -106,7 +106,6 @@ void DivEngine::runExportThread() {
|
|||
if (sfWrap.doClose()!=0) {
|
||||
logE("could not close audio file!");
|
||||
}
|
||||
exporting=false;
|
||||
|
||||
if (initAudioBackend()) {
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
|
@ -118,6 +117,7 @@ void DivEngine::runExportThread() {
|
|||
}
|
||||
}
|
||||
logI("done!");
|
||||
exporting=false;
|
||||
break;
|
||||
}
|
||||
case DIV_EXPORT_MODE_MANY_SYS: {
|
||||
|
@ -217,7 +217,6 @@ void DivEngine::runExportThread() {
|
|||
logE("could not close audio file!");
|
||||
}
|
||||
}
|
||||
exporting=false;
|
||||
|
||||
if (initAudioBackend()) {
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
|
@ -229,6 +228,7 @@ void DivEngine::runExportThread() {
|
|||
}
|
||||
}
|
||||
logI("done!");
|
||||
exporting=false;
|
||||
break;
|
||||
}
|
||||
case DIV_EXPORT_MODE_MANY_CHAN: {
|
||||
|
@ -336,7 +336,6 @@ void DivEngine::runExportThread() {
|
|||
|
||||
if (stopExport) break;
|
||||
}
|
||||
exporting=false;
|
||||
|
||||
delete[] outBuf[0];
|
||||
delete[] outBuf[1];
|
||||
|
@ -359,6 +358,7 @@ void DivEngine::runExportThread() {
|
|||
}
|
||||
}
|
||||
logI("done!");
|
||||
exporting=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,11 +101,11 @@ template <typename T, size_t items> bool FixedQueue<T,items>::pop() {
|
|||
|
||||
template <typename T, size_t items> bool FixedQueue<T,items>::push(const T& item) {
|
||||
if (writePos==(readPos-1)) {
|
||||
logW("queue overflow!");
|
||||
//logW("queue overflow!");
|
||||
return false;
|
||||
}
|
||||
if (writePos==items-1 && readPos==0) {
|
||||
logW("queue overflow!");
|
||||
//logW("queue overflow!");
|
||||
return false;
|
||||
}
|
||||
data[writePos]=item;
|
||||
|
@ -121,11 +121,11 @@ template <typename T, size_t items> bool FixedQueue<T,items>::pop_front() {
|
|||
|
||||
template <typename T, size_t items> bool FixedQueue<T,items>::push_back(const T& item) {
|
||||
if (writePos==(readPos-1)) {
|
||||
logW("queue overflow!");
|
||||
//logW("queue overflow!");
|
||||
return false;
|
||||
}
|
||||
if (writePos==items-1 && readPos==0) {
|
||||
logW("queue overflow!");
|
||||
//logW("queue overflow!");
|
||||
return false;
|
||||
}
|
||||
data[writePos]=item;
|
||||
|
@ -145,11 +145,11 @@ template <typename T, size_t items> bool FixedQueue<T,items>::pop_back() {
|
|||
|
||||
template <typename T, size_t items> bool FixedQueue<T,items>::push_front(const T& item) {
|
||||
if (readPos==(writePos+1)) {
|
||||
logW("stack overflow!");
|
||||
//logW("stack overflow!");
|
||||
return false;
|
||||
}
|
||||
if (readPos==0 && writePos==items-1) {
|
||||
logW("stack overflow!");
|
||||
//logW("stack overflow!");
|
||||
return false;
|
||||
}
|
||||
if (readPos>0) {
|
||||
|
|
|
@ -30,9 +30,6 @@ const char* aboutLine[]={
|
|||
"the biggest multi-system chiptune tracker!",
|
||||
"featuring DefleMask song compatibility.",
|
||||
"",
|
||||
"this is a version released during The Freeze.",
|
||||
"please report any issues you find!",
|
||||
"",
|
||||
"> CREDITS <",
|
||||
"",
|
||||
"-- program --",
|
||||
|
@ -57,20 +54,21 @@ const char* aboutLine[]={
|
|||
"Raijin",
|
||||
"",
|
||||
"-- documentation --",
|
||||
"tildearrow",
|
||||
"freq-mod",
|
||||
"nicco1690",
|
||||
"DeMOSic",
|
||||
"brickblock369",
|
||||
"cam900",
|
||||
"host12prog",
|
||||
"WindowxDeveloper",
|
||||
"polluks",
|
||||
"DeMOSic",
|
||||
"Electric Keet",
|
||||
"freq-mod",
|
||||
"host12prog",
|
||||
"Lunathir",
|
||||
"nicco1690",
|
||||
"tildearrow",
|
||||
"",
|
||||
"-- demo songs --",
|
||||
"0x5066",
|
||||
"Abstract 64",
|
||||
"ActualNK358",
|
||||
"airconmanws",
|
||||
"akumanatt",
|
||||
"AmigaX",
|
||||
"AURORA*FIELDS",
|
||||
|
@ -123,10 +121,12 @@ const char* aboutLine[]={
|
|||
"psxdominator",
|
||||
"Raijin",
|
||||
"railzen7",
|
||||
"RevvoBolt",
|
||||
"SnugglyBun",
|
||||
"SuperJet Spade",
|
||||
"SwapXFO",
|
||||
"TakuikaNinja",
|
||||
"tapekeep",
|
||||
"TCORPStudios",
|
||||
"Teuthida",
|
||||
"ThaCuber",
|
||||
|
|
|
@ -584,6 +584,10 @@ void FurnaceGUI::drawMobileControls() {
|
|||
if (ImGui::Button("Stats")) {
|
||||
statsOpen=!statsOpen;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Grooves")) {
|
||||
groovesOpen=!groovesOpen;
|
||||
}
|
||||
if (ImGui::Button("Compat Flags")) {
|
||||
compatFlagsOpen=!compatFlagsOpen;
|
||||
}
|
||||
|
|
|
@ -3584,6 +3584,9 @@ bool FurnaceGUI::loop() {
|
|||
SDL_free(ev.drop.file);
|
||||
}
|
||||
break;
|
||||
case SDL_USEREVENT:
|
||||
// used for MIDI wake up
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
if (modified) {
|
||||
showWarning("Unsaved changes! Save changes before quitting?",GUI_WARN_QUIT);
|
||||
|
@ -3647,6 +3650,7 @@ bool FurnaceGUI::loop() {
|
|||
|
||||
while (true) {
|
||||
midiLock.lock();
|
||||
midiWakeUp=true;
|
||||
if (midiQueue.empty()) {
|
||||
midiLock.unlock();
|
||||
break;
|
||||
|
@ -4542,6 +4546,7 @@ bool FurnaceGUI::loop() {
|
|||
MEASURE(readOsc,readOsc());
|
||||
MEASURE(osc,drawOsc());
|
||||
MEASURE(chanOsc,drawChanOsc());
|
||||
MEASURE(grooves,drawGrooves());
|
||||
MEASURE(regView,drawRegView());
|
||||
} else {
|
||||
globalWinFlags=0;
|
||||
|
@ -5870,8 +5875,6 @@ bool FurnaceGUI::loop() {
|
|||
|
||||
if (pendingRawSampleDepth!=DIV_SAMPLE_DEPTH_8BIT && pendingRawSampleDepth!=DIV_SAMPLE_DEPTH_16BIT) {
|
||||
pendingRawSampleChannels=1;
|
||||
}
|
||||
if (pendingRawSampleDepth!=DIV_SAMPLE_DEPTH_16BIT) {
|
||||
pendingRawSampleBigEndian=false;
|
||||
}
|
||||
|
||||
|
@ -5898,6 +5901,10 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::Checkbox("Swap nibbles",&pendingRawSampleSwapNibbles);
|
||||
}
|
||||
|
||||
if (pendingRawSampleDepth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||
ImGui::Checkbox("Swap words",&pendingRawSampleBigEndian);
|
||||
}
|
||||
|
||||
if (pendingRawSampleDepth==DIV_SAMPLE_DEPTH_MULAW) {
|
||||
ImGui::Text("Encoding:");
|
||||
ImGui::Indent();
|
||||
|
@ -6729,11 +6736,20 @@ bool FurnaceGUI::init() {
|
|||
|
||||
firstFrame=true;
|
||||
|
||||
// TODO: MIDI mapping time!
|
||||
userEvents=SDL_RegisterEvents(1);
|
||||
|
||||
e->setMidiCallback([this](const TAMidiMessage& msg) -> int {
|
||||
if (introPos<11.0) return -2;
|
||||
midiLock.lock();
|
||||
midiQueue.push(msg);
|
||||
if (userEvents!=0xffffffff && midiWakeUp) {
|
||||
midiWakeUp=false;
|
||||
userEvent.user.type=userEvents;
|
||||
userEvent.user.code=0;
|
||||
userEvent.user.data1=NULL;
|
||||
userEvent.user.data2=NULL;
|
||||
SDL_PushEvent(&userEvent);
|
||||
}
|
||||
midiLock.unlock();
|
||||
e->setMidiBaseChan(cursor.xCoarse);
|
||||
if (msg.type==TA_MIDI_SYSEX) return -2;
|
||||
|
@ -7013,6 +7029,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
displayEditString(false),
|
||||
mobileEdit(false),
|
||||
killGraphics(false),
|
||||
midiWakeUp(true),
|
||||
audioEngineChanged(false),
|
||||
settingsChanged(false),
|
||||
debugFFT(false),
|
||||
|
@ -7026,6 +7043,8 @@ FurnaceGUI::FurnaceGUI():
|
|||
mobileEditPage(0),
|
||||
wheelCalmDown(0),
|
||||
shallDetectScale(0),
|
||||
cpuCores(0),
|
||||
userEvents(0xffffffff),
|
||||
mobileMenuPos(0.0f),
|
||||
autoButtonSize(0.0f),
|
||||
mobileEditAnim(0.0f),
|
||||
|
|
|
@ -1345,6 +1345,7 @@ class FurnaceGUI {
|
|||
bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString;
|
||||
bool mobileEdit;
|
||||
bool killGraphics;
|
||||
bool midiWakeUp;
|
||||
bool audioEngineChanged, settingsChanged, debugFFT;
|
||||
bool willExport[DIV_MAX_CHIPS];
|
||||
int vgmExportVersion;
|
||||
|
@ -1358,6 +1359,7 @@ class FurnaceGUI {
|
|||
int wheelCalmDown;
|
||||
int shallDetectScale;
|
||||
int cpuCores;
|
||||
unsigned int userEvents;
|
||||
float mobileMenuPos, autoButtonSize, mobileEditAnim;
|
||||
ImVec2 mobileEditButtonPos, mobileEditButtonSize;
|
||||
const int* curSysSection;
|
||||
|
@ -1371,6 +1373,7 @@ class FurnaceGUI {
|
|||
void* fmPreviewOPZ;
|
||||
void* fmPreviewOPZInterface;
|
||||
String* editString;
|
||||
SDL_Event userEvent;
|
||||
|
||||
String pendingRawSample;
|
||||
int pendingRawSampleDepth, pendingRawSampleChannels;
|
||||
|
|
|
@ -120,8 +120,8 @@ const int vgmVersions[7]={
|
|||
|
||||
// name, icon, letter icon
|
||||
const char* insTypes[DIV_INS_MAX+1][3]={
|
||||
{"SN76489/Sega PSG",ICON_FA_AREA_CHART,ICON_FUR_INS_STD},
|
||||
{"FM (OPN)",ICON_FA_BAR_CHART,ICON_FUR_INS_FM},
|
||||
{"SN76489/Sega PSG",ICON_FA_BAR_CHART,ICON_FUR_INS_STD},
|
||||
{"FM (OPN)",ICON_FA_AREA_CHART,ICON_FUR_INS_FM},
|
||||
{"Game Boy",ICON_FA_GAMEPAD,ICON_FUR_INS_GB},
|
||||
{"C64",ICON_FA_KEYBOARD_O,ICON_FUR_INS_C64},
|
||||
{"Generic Sample",ICON_FA_VOLUME_UP,ICON_FUR_INS_AMIGA},
|
||||
|
|
|
@ -3093,6 +3093,7 @@ void FurnaceGUI::drawSettings() {
|
|||
// "42 63" - enables all instrument types
|
||||
// "4-bit FDS" - enables partial pitch linearity option
|
||||
// "Power of the Chip" - enables options for multi-threaded audio
|
||||
// "btcdbcb" - use modern UI padding
|
||||
// "????" - enables stuff
|
||||
CONFIG_SECTION("Cheat Codes") {
|
||||
// SUBSECTION ENTER CODE:
|
||||
|
@ -3131,6 +3132,14 @@ void FurnaceGUI::drawSettings() {
|
|||
mmlString[30]="unlocked audio multi-threading options!";
|
||||
settings.showPool=1;
|
||||
}
|
||||
if (checker==0x94222d83 && checker1==0x6600) {
|
||||
mmlString[30]="enabled \"comfortable\" mode";
|
||||
ImGuiStyle& sty=ImGui::GetStyle();
|
||||
sty.FramePadding=ImVec2(20.0f*dpiScale,20.0f*dpiScale);
|
||||
sty.ItemSpacing=ImVec2(10.0f*dpiScale,10.0f*dpiScale);
|
||||
sty.ItemInnerSpacing=ImVec2(10.0f*dpiScale,10.0f*dpiScale);
|
||||
settingsOpen=false;
|
||||
}
|
||||
|
||||
mmlString[31]="";
|
||||
}
|
||||
|
|
|
@ -273,7 +273,7 @@ void FurnaceGUI::drawTutorial() {
|
|||
|
||||
ImGui::TextWrapped(
|
||||
"if you need help, you may:\n"
|
||||
"- read the (incomplete) manual: https://github.com/tildearrow/furnace/blob/master/doc/README.md\n"
|
||||
"- read the manual (a file called manual.pdf)\n"
|
||||
"- ask for help in Discussions (https://github.com/tildearrow/furnace/discussions), the Furnace Discord (https://discord.gg/EfrwT2wq7z) or Furnace in Revolt (https://rvlt.gg/GRPS6tmc)"
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue