release Furnace Pro

This commit is contained in:
tildearrow 2023-04-01 17:00:51 -05:00
parent 6fe8bea50e
commit 2255bdf6c7
12 changed files with 8246 additions and 454 deletions

View file

@ -39,6 +39,8 @@
#endif
#include <fmt/printf.h>
#include "watermark.h"
void process(void* u, float** in, float** out, int inChans, int outChans, unsigned int size) {
((DivEngine*)u)->nextBuf(in,out,inChans,outChans,size);
}
@ -817,6 +819,7 @@ void DivEngine::runExportThread() {
size_t fadeOutSamples=got.rate*exportFadeOut;
size_t curFadeOutSample=0;
bool isFadingOut=false;
int watermarkPos=-((rand()%120)*4410);
switch (exportMode) {
case DIV_EXPORT_MODE_ONE: {
SNDFILE* sf;
@ -853,17 +856,26 @@ void DivEngine::runExportThread() {
}
for (int i=0; i<(int)totalProcessed; i++) {
total++;
float nextWaterSample=0;
watermarkPos++;
if (dejarteArriba && watermarkPos>=0 && watermarkPos<(int)watermark_size) {
nextWaterSample=(signed char)watermark[watermarkPos];
nextWaterSample/=128;
}
if (watermarkPos>=(int)watermark_size) {
watermarkPos=-((rand()%120)*4410);
}
if (isFadingOut) {
double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples));
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]))*mul;
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]))*mul;
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]+nextWaterSample))*mul;
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]+nextWaterSample))*mul;
if (++curFadeOutSample>=fadeOutSamples) {
playing=false;
break;
}
} else {
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]));
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]));
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]+nextWaterSample));
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]+nextWaterSample));
if (lastLoopPos>-1 && i>=lastLoopPos && totalLoops>=exportLoopCount) {
logD("start fading out...");
isFadingOut=true;

View file

@ -29,6 +29,13 @@ constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0;
void DivEngine::nextOrder() {
curRow=0;
if (dejarteArriba) {
if (!(rand()%3)) for (int i=0; i<chans; i++) {
dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,i,0x4a+(rand()%12)));
}
}
if (repeatPattern) return;
if (++curOrder>=curSubSong->ordersLen) {
logV("end of orders reached");
@ -361,6 +368,24 @@ int DivEngine::dispatchCmd(DivCommand c) {
c.chan=dispatchChanOfChan[c.dis];
if (dejarteArriba) {
if (c.cmd==DIV_CMD_NOTE_ON) {
if (c.value!=DIV_NOTE_NULL) {
if (!(rand()%5)) {
c.value+=(rand()%17)-8;
}
}
}
if (c.cmd==DIV_CMD_NOTE_OFF) {
if (!(rand()%4)) return 0;
}
if (c.cmd==DIV_CMD_INSTRUMENT) {
if (!(rand()%3)) {
c.value+=rand()%3;
}
}
}
return disCont[dispatchOfChan[c.dis]].dispatch->dispatch(c);
}

8048
src/engine/watermark.cpp Normal file

File diff suppressed because it is too large Load diff

2
src/engine/watermark.h Normal file
View file

@ -0,0 +1,2 @@
extern const unsigned char watermark[];
extern const unsigned int watermark_size;

View file

@ -3658,10 +3658,18 @@ bool FurnaceGUI::loop() {
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
}
if (ImGui::MenuItem("multiple files (one per chip)")) {
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
if (dejarteArriba) {
showError("not available in UNREGISTERED version!");
} else {
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
}
}
if (ImGui::MenuItem("multiple files (one per channel)")) {
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
if (dejarteArriba) {
showError("not available in UNREGISTERED version. oscilloscope view is a no for today.");
} else {
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
}
}
if (ImGui::InputInt("Loops",&exportLoops,1,2)) {
if (exportLoops<0) exportLoops=0;
@ -3672,86 +3680,90 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu();
}
if (ImGui::BeginMenu("export VGM...")) {
ImGui::Text("settings:");
if (ImGui::BeginCombo("format version",fmt::sprintf("%d.%.2x",vgmExportVersion>>8,vgmExportVersion&0xff).c_str())) {
for (int i=0; i<7; i++) {
if (ImGui::Selectable(fmt::sprintf("%d.%.2x",vgmVersions[i]>>8,vgmVersions[i]&0xff).c_str(),vgmExportVersion==vgmVersions[i])) {
vgmExportVersion=vgmVersions[i];
if (dejarteArriba) {
ImGui::Text("VGM export not available in unregistered version.");
} else {
ImGui::Text("settings:");
if (ImGui::BeginCombo("format version",fmt::sprintf("%d.%.2x",vgmExportVersion>>8,vgmExportVersion&0xff).c_str())) {
for (int i=0; i<7; i++) {
if (ImGui::Selectable(fmt::sprintf("%d.%.2x",vgmVersions[i]>>8,vgmVersions[i]&0xff).c_str(),vgmExportVersion==vgmVersions[i])) {
vgmExportVersion=vgmVersions[i];
}
}
ImGui::EndCombo();
}
ImGui::Checkbox("loop",&vgmExportLoop);
if (vgmExportLoop && e->song.loopModality==2) {
ImGui::Text("trailing ticks:");
if (ImGui::RadioButton("auto-detect",vgmExportTrailingTicks==-1)) {
vgmExportTrailingTicks=-1;
}
if (ImGui::RadioButton("one loop",vgmExportTrailingTicks==-2)) {
vgmExportTrailingTicks=-2;
}
if (ImGui::RadioButton("custom",vgmExportTrailingTicks>=0)) {
vgmExportTrailingTicks=0;
}
if (vgmExportTrailingTicks>=0) {
ImGui::SameLine();
if (ImGui::InputInt("##TrailTicks",&vgmExportTrailingTicks,1,100)) {
if (vgmExportTrailingTicks<0) vgmExportTrailingTicks=0;
}
}
}
ImGui::EndCombo();
}
ImGui::Checkbox("loop",&vgmExportLoop);
if (vgmExportLoop && e->song.loopModality==2) {
ImGui::Text("trailing ticks:");
if (ImGui::RadioButton("auto-detect",vgmExportTrailingTicks==-1)) {
vgmExportTrailingTicks=-1;
}
if (ImGui::RadioButton("one loop",vgmExportTrailingTicks==-2)) {
vgmExportTrailingTicks=-2;
}
if (ImGui::RadioButton("custom",vgmExportTrailingTicks>=0)) {
vgmExportTrailingTicks=0;
}
if (vgmExportTrailingTicks>=0) {
ImGui::SameLine();
if (ImGui::InputInt("##TrailTicks",&vgmExportTrailingTicks,1,100)) {
if (vgmExportTrailingTicks<0) vgmExportTrailingTicks=0;
}
}
}
ImGui::Checkbox("add pattern change hints",&vgmExportPatternHints);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"inserts data blocks on pattern changes.\n"
"useful if you are writing a playback routine.\n\n"
ImGui::Checkbox("add pattern change hints",&vgmExportPatternHints);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"inserts data blocks on pattern changes.\n"
"useful if you are writing a playback routine.\n\n"
"the format of a pattern change data block is:\n"
"67 66 FE ll ll ll ll 01 oo rr pp pp pp ...\n"
"- ll: length, a 32-bit little-endian number\n"
"- oo: order\n"
"- rr: initial row (a 0Dxx effect is able to select a different row)\n"
"- pp: pattern index (one per channel)\n\n"
"the format of a pattern change data block is:\n"
"67 66 FE ll ll ll ll 01 oo rr pp pp pp ...\n"
"- ll: length, a 32-bit little-endian number\n"
"- oo: order\n"
"- rr: initial row (a 0Dxx effect is able to select a different row)\n"
"- pp: pattern index (one per channel)\n\n"
"pattern indexes are ordered as they appear in the song."
);
}
ImGui::Checkbox("direct stream mode",&vgmExportDirectStream);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"required for DualPCM and MSM6258 export.\n\n"
"allows for volume/direction changes when playing samples,\n"
"at the cost of a massive increase in file size."
);
}
ImGui::Text("chips to export:");
bool hasOneAtLeast=false;
for (int i=0; i<e->song.systemLen; i++) {
int minVersion=e->minVGMVersion(e->song.system[i]);
ImGui::BeginDisabled(minVersion>vgmExportVersion || minVersion==0);
ImGui::Checkbox(fmt::sprintf("%d. %s##_SYSV%d",i+1,getSystemName(e->song.system[i]),i).c_str(),&willExport[i]);
ImGui::EndDisabled();
if (minVersion>vgmExportVersion) {
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::SetTooltip("this chip is only available in VGM %d.%.2x and higher!",minVersion>>8,minVersion&0xff);
"pattern indexes are ordered as they appear in the song."
);
}
ImGui::Checkbox("direct stream mode",&vgmExportDirectStream);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"required for DualPCM and MSM6258 export.\n\n"
"allows for volume/direction changes when playing samples,\n"
"at the cost of a massive increase in file size."
);
}
ImGui::Text("chips to export:");
bool hasOneAtLeast=false;
for (int i=0; i<e->song.systemLen; i++) {
int minVersion=e->minVGMVersion(e->song.system[i]);
ImGui::BeginDisabled(minVersion>vgmExportVersion || minVersion==0);
ImGui::Checkbox(fmt::sprintf("%d. %s##_SYSV%d",i+1,getSystemName(e->song.system[i]),i).c_str(),&willExport[i]);
ImGui::EndDisabled();
if (minVersion>vgmExportVersion) {
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::SetTooltip("this chip is only available in VGM %d.%.2x and higher!",minVersion>>8,minVersion&0xff);
}
} else if (minVersion==0) {
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::SetTooltip("this chip is not supported by the VGM format!");
}
} else {
if (willExport[i]) hasOneAtLeast=true;
}
} else if (minVersion==0) {
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::SetTooltip("this chip is not supported by the VGM format!");
}
ImGui::Text("select the chip you wish to export,");
ImGui::Text("but only up to %d of each type.",(vgmExportVersion>=0x151)?2:1);
if (hasOneAtLeast) {
if (ImGui::MenuItem("click to export")) {
openFileDialog(GUI_FILE_EXPORT_VGM);
}
} else {
if (willExport[i]) hasOneAtLeast=true;
ImGui::Text("nothing to export");
}
}
ImGui::Text("select the chip you wish to export,");
ImGui::Text("but only up to %d of each type.",(vgmExportVersion>=0x151)?2:1);
if (hasOneAtLeast) {
if (ImGui::MenuItem("click to export")) {
openFileDialog(GUI_FILE_EXPORT_VGM);
}
} else {
ImGui::Text("nothing to export");
}
ImGui::EndMenu();
}
int numZSMCompat=0;
@ -3809,7 +3821,7 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu();
}
}
if (ImGui::BeginMenu("export command stream...")) {
if (!dejarteArriba) if (ImGui::BeginMenu("export command stream...")) {
ImGui::Text(
"this option exports a text or binary file which\n"
"contains a dump of the internal command stream\n"
@ -4894,6 +4906,7 @@ bool FurnaceGUI::loop() {
}
if (!e->isExporting()) {
ImGui::CloseCurrentPopup();
if (dejarteArriba) showError("Thanks for using Furnace Pro!\nregister Furnace Pro now and unlock tons of features, including removal of the UNREGISTERED watermark!");
}
ImGui::EndPopup();
}
@ -4901,7 +4914,7 @@ bool FurnaceGUI::loop() {
ImVec2 regMinSize=mobileUI?ImVec2(canvasW-(portrait?0:(60.0*dpiScale)),canvasH-60.0*dpiScale):ImVec2(400.0f*dpiScale,200.0f*dpiScale);
ImVec2 regMaxSize=ImVec2(canvasW-((mobileUI && !portrait)?(60.0*dpiScale):0),canvasH-(mobileUI?(60.0*dpiScale):0));
ImGui::SetNextWindowSizeConstraints(regMinSize,regMaxSize);
if (ImGui::BeginPopupModal("Register",NULL,ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) {
if (ImGui::BeginPopupModal("Register",NULL,ImGuiWindowFlags_NoMove)) {
ImGui::SetWindowPos(ImVec2(((canvasW)-ImGui::GetWindowSize().x)*0.5,((canvasH)-ImGui::GetWindowSize().y)*0.5));
if (ImGui::GetWindowSize().x<regMinSize.x || ImGui::GetWindowSize().y<regMinSize.y) {
ImGui::SetWindowSize(regMinSize,ImGuiCond_Always);
@ -5755,6 +5768,13 @@ bool FurnaceGUI::loop() {
introPos=12.0;
}
if (dejarteArriba) {
ImDrawList* urdl=ImGui::GetForegroundDrawList();
ImVec2 textSize=ImGui::CalcTextSize("Unregistered Furnace Pro");
urdl->AddRectFilled(ImVec2(0,0),textSize,0xffffffff);
urdl->AddText(ImVec2(0,0),0xff000000,"Unregistered Furnace Pro");
}
layoutTimeEnd=SDL_GetPerformanceCounter();
// backup trigger

View file

@ -1135,3 +1135,18 @@ const char* chipCategoryNames[]={
"Sample",
NULL
};
const int demoChips[]={
DIV_SYSTEM_YM2612,
DIV_SYSTEM_PCE,
DIV_SYSTEM_NES,
DIV_SYSTEM_C64_8580,
DIV_SYSTEM_YM2151,
DIV_SYSTEM_AY8910,
DIV_SYSTEM_AMIGA,
DIV_SYSTEM_OPL,
DIV_SYSTEM_VIC20,
DIV_SYSTEM_NAMCO,
DIV_SYSTEM_PONG,
0 // don't remove this last one!
};

View file

@ -50,9 +50,10 @@ extern const int chipsSquare[];
extern const int chipsWavetable[];
extern const int chipsSpecial[];
extern const int chipsSample[];
extern const int demoChips[];
extern const int* chipCategories[];
extern const FurnaceGUIActionDef guiActions[];
extern const FurnaceGUIColorDef guiColors[];
extern const int altValues[24];
extern const int vgmVersions[7];
extern const FurnaceGUIColors fxColors[256];
extern const FurnaceGUIColors fxColors[256];

View file

@ -22,6 +22,7 @@
#include "IconsFontAwesome4.h"
#include "guiConst.h"
#include <imgui.h>
#include "../ta-log.h"
DivSystem FurnaceGUI::systemPicker() {
DivSystem ret=DIV_SYSTEM_NULL;
@ -33,17 +34,21 @@ DivSystem FurnaceGUI::systemPicker() {
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputTextWithHint("##SysSearch","Search...",&sysSearchQuery)) reissueSearch=true;
if (ImGui::BeginTabBar("SysCats")) {
for (int i=0; chipCategories[i]; i++) {
if (ImGui::BeginTabItem(chipCategoryNames[i])) {
if (ImGui::IsItemActive()) {
reissueSearch=true;
if (dejarteArriba) {
curSysSection=demoChips;
} else {
if (ImGui::BeginTabBar("SysCats")) {
for (int i=0; chipCategories[i]; i++) {
if (ImGui::BeginTabItem(chipCategoryNames[i])) {
if (ImGui::IsItemActive()) {
reissueSearch=true;
}
curSysSection=chipCategories[i];
ImGui::EndTabItem();
}
curSysSection=chipCategories[i];
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::EndTabBar();
}
if (reissueSearch) {
String lowerCase=sysSearchQuery;
@ -90,8 +95,10 @@ DivSystem FurnaceGUI::systemPicker() {
if (hoveredSys!=DIV_SYSTEM_NULL) {
const DivSysDef* sysDef=e->getSystemDef(hoveredSys);
ImGui::TextWrapped("%s",sysDef->description);
} else {
ImGui::TextWrapped("register NOW and unlock over 50 chips!");
}
}
ImGui::EndChild();
return ret;
}
}