ZSM: add optimize for size toggle
This commit is contained in:
parent
fe8f94b2b2
commit
a1d74e7dc1
|
@ -605,7 +605,7 @@ class DivEngine {
|
||||||
// - -2 to add a whole loop of trailing
|
// - -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);
|
SafeWriter* saveVGM(bool* sysToExport=NULL, bool loop=true, int version=0x171, bool patternHints=false, bool directStream=false, int trailingTicks=-1);
|
||||||
// dump to ZSM.
|
// 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.
|
// dump command stream.
|
||||||
SafeWriter* saveCommand(bool binary=false);
|
SafeWriter* saveCommand(bool binary=false);
|
||||||
// export to an audio file
|
// export to an audio file
|
||||||
|
|
|
@ -66,6 +66,8 @@ void DivZSM::init(unsigned int rate) {
|
||||||
// Channel masks
|
// Channel masks
|
||||||
ymMask=0;
|
ymMask=0;
|
||||||
psgMask=0;
|
psgMask=0;
|
||||||
|
// Optimize writes
|
||||||
|
optimize=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivZSM::getoffset() {
|
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) {
|
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) {
|
if (a>=69) {
|
||||||
logD("ZSM: ignoring VERA PSG write a=%02x v=%02x",a,v);
|
logD("ZSM: ignoring VERA PSG write a=%02x v=%02x",a,v);
|
||||||
return;
|
return;
|
||||||
|
@ -213,6 +212,10 @@ void DivZSM::setLoopPoint() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivZSM::setOptimize(bool o) {
|
||||||
|
optimize = o;
|
||||||
|
}
|
||||||
|
|
||||||
SafeWriter* DivZSM::finish() {
|
SafeWriter* DivZSM::finish() {
|
||||||
tick(0); // flush any pending writes / ticks
|
tick(0); // flush any pending writes / ticks
|
||||||
flushTicks(); // flush ticks in case there were no writes pending
|
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.
|
flushTicks(); // only flush ticks if there are writes pending.
|
||||||
for (unsigned char i=0; i<64; i++) {
|
for (unsigned char i=0; i<64; i++) {
|
||||||
if (psgState[psg_NEW][i]==psgState[psg_PREV][i]) continue;
|
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%4!=2 && (psgState[psg_NEW][(i&0x3c)+2]&0x3f)==0) continue; // vol
|
||||||
|
if (optimize && i%4!=2 && (psgState[psg_NEW][(i&0x3c)+2]&0xc0)==0) continue; // R+L
|
||||||
psgState[psg_PREV][i]=psgState[psg_NEW][i];
|
psgState[psg_PREV][i]=psgState[psg_NEW][i];
|
||||||
w->writeC(i);
|
w->writeC(i);
|
||||||
w->writeC(psgState[psg_NEW][i]);
|
w->writeC(psgState[psg_NEW][i]);
|
||||||
|
|
|
@ -70,6 +70,7 @@ class DivZSM {
|
||||||
int tickRate;
|
int tickRate;
|
||||||
int ymMask;
|
int ymMask;
|
||||||
int psgMask;
|
int psgMask;
|
||||||
|
bool optimize;
|
||||||
public:
|
public:
|
||||||
DivZSM();
|
DivZSM();
|
||||||
~DivZSM();
|
~DivZSM();
|
||||||
|
@ -79,6 +80,7 @@ class DivZSM {
|
||||||
void writePSG(unsigned char a, unsigned char v);
|
void writePSG(unsigned char a, unsigned char v);
|
||||||
void writePCM(unsigned char a, unsigned char v);
|
void writePCM(unsigned char a, unsigned char v);
|
||||||
void writeSync(unsigned char a, unsigned char v);
|
void writeSync(unsigned char a, unsigned char v);
|
||||||
|
void setOptimize(bool o);
|
||||||
void tick(int numticks = 1);
|
void tick(int numticks = 1);
|
||||||
void setLoopPoint();
|
void setLoopPoint();
|
||||||
SafeWriter* finish();
|
SafeWriter* finish();
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0;
|
constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0;
|
||||||
constexpr int MASTER_CLOCK_MASK=(sizeof(void*)==8)?0xff: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 VERA=-1;
|
||||||
int YM=-1;
|
int YM=-1;
|
||||||
int IGNORED=0;
|
int IGNORED=0;
|
||||||
|
@ -118,6 +118,9 @@ SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
|
||||||
// by nature of overflowing the signed char value
|
// by nature of overflowing the signed char value
|
||||||
signed char tuningoffset=(signed char)(round(3072*(log(song.tuning/440.0)/log(2))))&0xff;
|
signed char tuningoffset=(signed char)(round(3072*(log(song.tuning/440.0)/log(2))))&0xff;
|
||||||
zsm.writeSync(0x01,tuningoffset);
|
zsm.writeSync(0x01,tuningoffset);
|
||||||
|
// Set optimize flag, which mainly buffers PSG writes
|
||||||
|
// whenever the channel is silent
|
||||||
|
zsm.setOptimize(optimize);
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
if (loopPos==-1) {
|
if (loopPos==-1) {
|
||||||
|
|
|
@ -4108,6 +4108,8 @@ bool FurnaceGUI::loop() {
|
||||||
}
|
}
|
||||||
ImGui::Checkbox("loop",&zsmExportLoop);
|
ImGui::Checkbox("loop",&zsmExportLoop);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
ImGui::Checkbox("optimize size",&zsmExportOptimize);
|
||||||
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Begin Export")) {
|
if (ImGui::Button("Begin Export")) {
|
||||||
openFileDialog(GUI_FILE_EXPORT_ZSM);
|
openFileDialog(GUI_FILE_EXPORT_ZSM);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
|
@ -5067,7 +5069,7 @@ bool FurnaceGUI::loop() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GUI_FILE_EXPORT_ZSM: {
|
case GUI_FILE_EXPORT_ZSM: {
|
||||||
SafeWriter* w=e->saveZSM(zsmExportTickRate,zsmExportLoop);
|
SafeWriter* w=e->saveZSM(zsmExportTickRate,zsmExportLoop,zsmExportOptimize);
|
||||||
if (w!=NULL) {
|
if (w!=NULL) {
|
||||||
FILE* f=ps_fopen(copyOfName.c_str(),"wb");
|
FILE* f=ps_fopen(copyOfName.c_str(),"wb");
|
||||||
if (f!=NULL) {
|
if (f!=NULL) {
|
||||||
|
@ -6799,6 +6801,7 @@ FurnaceGUI::FurnaceGUI():
|
||||||
displayExporting(false),
|
displayExporting(false),
|
||||||
vgmExportLoop(true),
|
vgmExportLoop(true),
|
||||||
zsmExportLoop(true),
|
zsmExportLoop(true),
|
||||||
|
zsmExportOptimize(true),
|
||||||
vgmExportPatternHints(false),
|
vgmExportPatternHints(false),
|
||||||
vgmExportDirectStream(false),
|
vgmExportDirectStream(false),
|
||||||
displayInsTypeList(false),
|
displayInsTypeList(false),
|
||||||
|
|
|
@ -1324,7 +1324,7 @@ class FurnaceGUI {
|
||||||
std::vector<String> availRenderDrivers;
|
std::vector<String> availRenderDrivers;
|
||||||
std::vector<String> availAudioDrivers;
|
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 vgmExportDirectStream, displayInsTypeList;
|
||||||
bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed;
|
bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed;
|
||||||
bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu;
|
bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu;
|
||||||
|
|
Loading…
Reference in a new issue