mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 15:03:01 +00:00
Implemented changes requested by Tildearrow
This commit is contained in:
parent
c3654eb67c
commit
d7900c2390
6 changed files with 32 additions and 30 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue