Merge branch 'master' of github.com:tildearrow/furnace
This commit is contained in:
commit
9b91584d13
|
@ -605,7 +605,7 @@ class DivEngine {
|
|||
// - -2 to add a whole loop of trailing
|
||||
SafeWriter* saveVGM(bool* sysToExport=NULL, bool loop=true, int version=0x171, bool patternHints=false, bool directStream=false, int trailingTicks=-1);
|
||||
// dump to ZSM.
|
||||
SafeWriter* saveZSM(unsigned int zsmrate=60, bool loop=true);
|
||||
SafeWriter* saveZSM(unsigned int zsmrate=60, bool loop=true, bool optimize=true);
|
||||
// dump command stream.
|
||||
SafeWriter* saveCommand(bool binary=false);
|
||||
// export to an audio file
|
||||
|
|
|
@ -66,6 +66,8 @@ void DivZSM::init(unsigned int rate) {
|
|||
// Channel masks
|
||||
ymMask=0;
|
||||
psgMask=0;
|
||||
// Optimize writes
|
||||
optimize=true;
|
||||
}
|
||||
|
||||
int DivZSM::getoffset() {
|
||||
|
@ -121,9 +123,6 @@ void DivZSM::writeSync(unsigned char a, unsigned char v) {
|
|||
}
|
||||
|
||||
void DivZSM::writePSG(unsigned char a, unsigned char v) {
|
||||
// TODO: suppress writes to PSG voice that is not audible (volume=0)
|
||||
// ^ Let's leave these alone, ZSMKit has a feature that can benefit
|
||||
// from silent channels.
|
||||
if (a>=69) {
|
||||
logD("ZSM: ignoring VERA PSG write a=%02x v=%02x",a,v);
|
||||
return;
|
||||
|
@ -213,6 +212,10 @@ void DivZSM::setLoopPoint() {
|
|||
}
|
||||
}
|
||||
|
||||
void DivZSM::setOptimize(bool o) {
|
||||
optimize=o;
|
||||
}
|
||||
|
||||
SafeWriter* DivZSM::finish() {
|
||||
tick(0); // flush any pending writes / ticks
|
||||
flushTicks(); // flush ticks in case there were no writes pending
|
||||
|
@ -278,6 +281,11 @@ void DivZSM::flushWrites() {
|
|||
flushTicks(); // only flush ticks if there are writes pending.
|
||||
for (unsigned char i=0; i<64; i++) {
|
||||
if (psgState[psg_NEW][i]==psgState[psg_PREV][i]) continue;
|
||||
// if optimize=true, suppress writes to PSG voices that are not audible (volume=0 or R+L=0)
|
||||
// ZSMKit has a feature that can benefit from having silent channels
|
||||
// updated, so this is something that can be toggled off or on for export
|
||||
if (optimize && (i&3)!=2 && (psgState[psg_NEW][(i&0x3c)+2]&0x3f)==0) continue; // vol
|
||||
if (optimize && (i&3)!=2 && (psgState[psg_NEW][(i&0x3c)+2]&0xc0)==0) continue; // R+L
|
||||
psgState[psg_PREV][i]=psgState[psg_NEW][i];
|
||||
w->writeC(i);
|
||||
w->writeC(psgState[psg_NEW][i]);
|
||||
|
|
|
@ -70,6 +70,7 @@ class DivZSM {
|
|||
int tickRate;
|
||||
int ymMask;
|
||||
int psgMask;
|
||||
bool optimize;
|
||||
public:
|
||||
DivZSM();
|
||||
~DivZSM();
|
||||
|
@ -79,6 +80,7 @@ class DivZSM {
|
|||
void writePSG(unsigned char a, unsigned char v);
|
||||
void writePCM(unsigned char a, unsigned char v);
|
||||
void writeSync(unsigned char a, unsigned char v);
|
||||
void setOptimize(bool o);
|
||||
void tick(int numticks = 1);
|
||||
void setLoopPoint();
|
||||
SafeWriter* finish();
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0;
|
||||
constexpr int MASTER_CLOCK_MASK=(sizeof(void*)==8)?0xff:0;
|
||||
|
||||
SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
|
||||
SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop, bool optimize) {
|
||||
int VERA=-1;
|
||||
int YM=-1;
|
||||
int IGNORED=0;
|
||||
|
@ -118,6 +118,9 @@ SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
|
|||
// by nature of overflowing the signed char value
|
||||
signed char tuningoffset=(signed char)(round(3072*(log(song.tuning/440.0)/log(2))))&0xff;
|
||||
zsm.writeSync(0x01,tuningoffset);
|
||||
// Set optimize flag, which mainly buffers PSG writes
|
||||
// whenever the channel is silent
|
||||
zsm.setOptimize(optimize);
|
||||
|
||||
while (!done) {
|
||||
if (loopPos==-1) {
|
||||
|
|
|
@ -4108,6 +4108,8 @@ bool FurnaceGUI::loop() {
|
|||
}
|
||||
ImGui::Checkbox("loop",&zsmExportLoop);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("optimize size",&zsmExportOptimize);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Begin Export")) {
|
||||
openFileDialog(GUI_FILE_EXPORT_ZSM);
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
@ -5071,7 +5073,7 @@ bool FurnaceGUI::loop() {
|
|||
break;
|
||||
}
|
||||
case GUI_FILE_EXPORT_ZSM: {
|
||||
SafeWriter* w=e->saveZSM(zsmExportTickRate,zsmExportLoop);
|
||||
SafeWriter* w=e->saveZSM(zsmExportTickRate,zsmExportLoop,zsmExportOptimize);
|
||||
if (w!=NULL) {
|
||||
FILE* f=ps_fopen(copyOfName.c_str(),"wb");
|
||||
if (f!=NULL) {
|
||||
|
@ -6803,6 +6805,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
displayExporting(false),
|
||||
vgmExportLoop(true),
|
||||
zsmExportLoop(true),
|
||||
zsmExportOptimize(true),
|
||||
vgmExportPatternHints(false),
|
||||
vgmExportDirectStream(false),
|
||||
displayInsTypeList(false),
|
||||
|
|
|
@ -1324,7 +1324,7 @@ class FurnaceGUI {
|
|||
std::vector<String> availRenderDrivers;
|
||||
std::vector<String> availAudioDrivers;
|
||||
|
||||
bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, zsmExportLoop, vgmExportPatternHints;
|
||||
bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, zsmExportLoop, zsmExportOptimize, vgmExportPatternHints;
|
||||
bool vgmExportDirectStream, displayInsTypeList;
|
||||
bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed;
|
||||
bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu;
|
||||
|
|
Loading…
Reference in New Issue