Implemented changes requested by Tildearrow

This commit is contained in:
ZeroByteOrg 2022-09-23 23:23:03 -05:00
parent c3654eb67c
commit d7900c2390
6 changed files with 32 additions and 30 deletions

View file

@ -77,9 +77,11 @@ int SafeWriter::writeC(signed char val) {
return write(&val,1); return write(&val,1);
} }
/*
int SafeWriter::writeUC(unsigned char val) { int SafeWriter::writeUC(unsigned char val) {
return write(&val,1); return write(&val,1);
} }
*/
#ifdef TA_BIG_ENDIAN #ifdef TA_BIG_ENDIAN
int SafeWriter::writeS_BE(short val) { int SafeWriter::writeS_BE(short val) {

View file

@ -45,7 +45,7 @@ class SafeWriter {
int write(const void* what, size_t count); int write(const void* what, size_t count);
int writeC(signed char val); int writeC(signed char val);
int writeUC(unsigned char val); //int writeUC(unsigned char val);
int writeS(short val); int writeS(short val);
int writeS_BE(short val); int writeS_BE(short val);
int writeI(int val); int writeI(int val);

View file

@ -22,21 +22,21 @@
#include "../utfutils.h" #include "../utfutils.h"
#include "song.h" #include "song.h"
ZSM::ZSM() { DivZSM::DivZSM() {
w = NULL; w = NULL;
init(); init();
} }
ZSM::~ZSM() { DivZSM::~DivZSM() {
} }
void ZSM::init(unsigned int rate) { void DivZSM::init(unsigned int rate) {
if (w != NULL) delete w; if (w != NULL) delete w;
w = new SafeWriter; w = new SafeWriter;
w->init(); w->init();
// write default ZSM data header // write default ZSM data header
w->write("zm",2); // magic header w->write("zm",2); // magic header
w->writeUC(ZSM_VERSION); w->writeC(ZSM_VERSION);
// no loop offset // no loop offset
w->writeS(0); w->writeS(0);
w->writeC(0); w->writeC(0);
@ -58,11 +58,11 @@ void ZSM::init(unsigned int rate) {
ticks=0; ticks=0;
} }
int ZSM::getoffset() { int DivZSM::getoffset() {
return w->tell(); return w->tell();
} }
void ZSM::writeYM(unsigned char a, unsigned char v) { void DivZSM::writeYM(unsigned char a, unsigned char v) {
int lastMask = ymMask; int lastMask = ymMask;
if (a==0x19 && v>=0x80) a=0x1a; // AMD/PSD use same reg addr. store PMD as 0x1a if (a==0x19 && v>=0x80) a=0x1a; // AMD/PSD use same reg addr. store PMD as 0x1a
if (a==0x08 && (v&0xf8)) ymMask |= (1 << (v & 0x07)); // mark chan as in-use if keyDN if (a==0x08 && (v&0xf8)) ymMask |= (1 << (v & 0x07)); // mark chan as in-use if keyDN
@ -107,7 +107,7 @@ void ZSM::writeYM(unsigned char a, unsigned char v) {
} }
} }
void ZSM::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) // TODO: suppress writes to PSG voice that is not audible (volume=0)
if (a >= 64) { if (a >= 64) {
logD ("ZSM: ignoring VERA PSG write a=%02x v=%02x",a,v); logD ("ZSM: ignoring VERA PSG write a=%02x v=%02x",a,v);
@ -129,16 +129,16 @@ void ZSM::writePSG(unsigned char a, unsigned char v) {
if ((a % 4 == 2) && (v & 0x3f)) psgMask |= (1 << (a>>2)); if ((a % 4 == 2) && (v & 0x3f)) psgMask |= (1 << (a>>2));
} }
void ZSM::writePCM(unsigned char a, unsigned char v) { void DivZSM::writePCM(unsigned char a, unsigned char v) {
// ZSM standard for PCM playback has not been established yet. // ZSM standard for PCM playback has not been established yet.
} }
void ZSM::tick(int numticks) { void DivZSM::tick(int numticks) {
flushWrites(); flushWrites();
ticks += numticks; ticks += numticks;
} }
void ZSM::setLoopPoint() { void DivZSM::setLoopPoint() {
tick(0); // flush any ticks+writes tick(0); // flush any ticks+writes
flushTicks(); // flush ticks incase no writes were pending flushTicks(); // flush ticks incase no writes were pending
logI("ZSM: loop at file offset %d bytes",w->tell()); logI("ZSM: loop at file offset %d bytes",w->tell());
@ -146,7 +146,7 @@ void ZSM::setLoopPoint() {
//update the ZSM header's loop offset value //update the ZSM header's loop offset value
w->seek(0x03,SEEK_SET); w->seek(0x03,SEEK_SET);
w->writeS((short)(loopOffset&0xffff)); w->writeS((short)(loopOffset&0xffff));
w->writeUC((short)((loopOffset>>16)&0xff)); w->writeC((unsigned char)((loopOffset>>16)&0xff));
w->seek(loopOffset,SEEK_SET); w->seek(loopOffset,SEEK_SET);
// reset the PSG shadow and write cache // reset the PSG shadow and write cache
memset(&psgState,-1,sizeof(psgState)); memset(&psgState,-1,sizeof(psgState));
@ -163,56 +163,56 @@ void ZSM::setLoopPoint() {
} }
} }
SafeWriter* ZSM::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
w->writeUC(ZSM_EOF); w->writeC(ZSM_EOF);
// update channel use masks. // update channel use masks.
w->seek(0x09,SEEK_SET); w->seek(0x09,SEEK_SET);
w->writeUC((unsigned char)(ymMask & 0xff)); w->writeC((unsigned char)(ymMask & 0xff));
w->writeS((short)(psgMask & 0xffff)); w->writeS((short)(psgMask & 0xffff));
// todo: put PCM offset/data writes here once defined in ZSM standard. // todo: put PCM offset/data writes here once defined in ZSM standard.
return w; return w;
} }
void ZSM::flushWrites() { void DivZSM::flushWrites() {
logD("ZSM: flushWrites.... numwrites=%d ticks=%d ymwrites=%d",numWrites,ticks,ymwrites.size()); logD("ZSM: flushWrites.... numwrites=%d ticks=%d ymwrites=%d",numWrites,ticks,ymwrites.size());
if (numWrites==0) return; if (numWrites==0) return;
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;
psgState[psg_PREV][i]=psgState[psg_NEW][i]; psgState[psg_PREV][i]=psgState[psg_NEW][i];
w->writeUC(i); w->writeC(i);
w->writeUC(psgState[psg_NEW][i]); w->writeC(psgState[psg_NEW][i]);
} }
int n=0; // n = completed YM writes. used to determine when to write the CMD byte... int n=0; // n = completed YM writes. used to determine when to write the CMD byte...
for (DivRegWrite& write: ymwrites) { for (DivRegWrite& write: ymwrites) {
if (n%ZSM_YM_MAX_WRITES == 0) { if (n%ZSM_YM_MAX_WRITES == 0) {
if(ymwrites.size()-n > ZSM_YM_MAX_WRITES) { if(ymwrites.size()-n > ZSM_YM_MAX_WRITES) {
w->writeUC((unsigned char)(ZSM_YM_CMD+ZSM_YM_MAX_WRITES)); w->writeC((unsigned char)(ZSM_YM_CMD+ZSM_YM_MAX_WRITES));
logD("ZSM: YM-write: %d (%02x) [max]",ZSM_YM_MAX_WRITES,ZSM_YM_MAX_WRITES+ZSM_YM_CMD); logD("ZSM: YM-write: %d (%02x) [max]",ZSM_YM_MAX_WRITES,ZSM_YM_MAX_WRITES+ZSM_YM_CMD);
} else { } else {
w->writeUC((unsigned char)(ZSM_YM_CMD+ymwrites.size()-n)); w->writeC((unsigned char)(ZSM_YM_CMD+ymwrites.size()-n));
logD("ZSM: YM-write: %d (%02x)",ymwrites.size()-n,ZSM_YM_CMD+ymwrites.size()-n); logD("ZSM: YM-write: %d (%02x)",ymwrites.size()-n,ZSM_YM_CMD+ymwrites.size()-n);
} }
} }
n++; n++;
w->writeUC(write.addr); w->writeC(write.addr);
w->writeUC(write.val); w->writeC(write.val);
} }
ymwrites.clear(); ymwrites.clear();
numWrites=0; numWrites=0;
} }
void ZSM::flushTicks() { void DivZSM::flushTicks() {
while (ticks > ZSM_DELAY_MAX) { while (ticks > ZSM_DELAY_MAX) {
logD("ZSM: write delay %d (max)",ZSM_DELAY_MAX); logD("ZSM: write delay %d (max)",ZSM_DELAY_MAX);
w->writeUC((unsigned char)(ZSM_DELAY_CMD+ZSM_DELAY_MAX)); w->writeC((unsigned char)(ZSM_DELAY_CMD+ZSM_DELAY_MAX));
ticks -= ZSM_DELAY_MAX; ticks -= ZSM_DELAY_MAX;
} }
if (ticks>0) { if (ticks>0) {
logD("ZSM: write delay %d",ticks); logD("ZSM: write delay %d",ticks);
w->writeUC(ZSM_DELAY_CMD+ticks); w->writeC(ZSM_DELAY_CMD+ticks);
} }
ticks=0; ticks=0;
} }

View file

@ -36,7 +36,7 @@
enum YM_STATE { ym_PREV, ym_NEW, ym_STATES }; enum YM_STATE { ym_PREV, ym_NEW, ym_STATES };
enum PSG_STATE { psg_PREV, psg_NEW, psg_STATES }; enum PSG_STATE { psg_PREV, psg_NEW, psg_STATES };
class ZSM { class DivZSM {
private: private:
SafeWriter* w; SafeWriter* w;
int ymState[ym_STATES][256]; int ymState[ym_STATES][256];
@ -49,8 +49,8 @@ class ZSM {
int ymMask = 0; int ymMask = 0;
int psgMask = 0; int psgMask = 0;
public: public:
ZSM(); DivZSM();
~ZSM(); ~DivZSM();
void init(unsigned int rate = 60); void init(unsigned int rate = 60);
int getoffset(); int getoffset();
void writeYM(unsigned char a, unsigned char v); void writeYM(unsigned char a, unsigned char v);

View file

@ -74,7 +74,7 @@ SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
logI("loop point: %d %d",loopOrder,loopRow); logI("loop point: %d %d",loopOrder,loopRow);
warnings=""; warnings="";
ZSM zsm; DivZSM zsm;
zsm.init(zsmrate); zsm.init(zsmrate);
// reset the playback state // reset the playback state

View file

@ -3400,7 +3400,7 @@ bool FurnaceGUI::loop() {
} }
ImGui::Checkbox("loop",&zsmExportLoop); ImGui::Checkbox("loop",&zsmExportLoop);
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button(" Go ")) { if (ImGui::Button("Begin Export")) {
openFileDialog(GUI_FILE_EXPORT_ZSM); openFileDialog(GUI_FILE_EXPORT_ZSM);
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }