ZSM: code style
This commit is contained in:
parent
982678eff3
commit
6b89dec812
|
|
@ -23,7 +23,7 @@
|
||||||
#include "song.h"
|
#include "song.h"
|
||||||
|
|
||||||
DivZSM::DivZSM() {
|
DivZSM::DivZSM() {
|
||||||
w = NULL;
|
w=NULL;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,8 +31,8 @@ DivZSM::~DivZSM() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivZSM::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
|
||||||
|
|
@ -50,7 +50,7 @@ void DivZSM::init(unsigned int rate) {
|
||||||
w->writeS((unsigned short)rate);
|
w->writeS((unsigned short)rate);
|
||||||
// 2 reserved bytes (set to zero)
|
// 2 reserved bytes (set to zero)
|
||||||
w->writeS(0x00);
|
w->writeS(0x00);
|
||||||
tickRate = rate;
|
tickRate=rate;
|
||||||
loopOffset=-1;
|
loopOffset=-1;
|
||||||
numWrites=0;
|
numWrites=0;
|
||||||
memset(&ymState,-1,sizeof(ymState));
|
memset(&ymState,-1,sizeof(ymState));
|
||||||
|
|
@ -63,44 +63,43 @@ int DivZSM::getoffset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivZSM::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
|
||||||
if (a!=0x08) ymState[ym_NEW][a] = v; // cache the newly-written value
|
if (a!=0x08) ymState[ym_NEW][a]=v; // cache the newly-written value
|
||||||
bool writeit=false; // used to suppress spurious writes to unused channels
|
bool writeit=false; // used to suppress spurious writes to unused channels
|
||||||
if (a < 0x20) {
|
if (a<0x20) {
|
||||||
if (a == 0x08) {
|
if (a==0x08) {
|
||||||
// write keyUPDN messages if channel is active.
|
// write keyUPDN messages if channel is active.
|
||||||
writeit = (ymMask & (1 << (v & 0x07))) > 0;
|
writeit=(ymMask&(1<<(v&0x07)))>0;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// do not suppress global registers
|
// do not suppress global registers
|
||||||
writeit = true;
|
writeit=true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writeit = (ymMask & (1 << (a & 0x07))) > 0; // a&0x07 = chan ID for regs >=0x20
|
writeit=(ymMask&(1<<(a&0x07)))>0; // a&0x07 = chan ID for regs >=0x20
|
||||||
}
|
}
|
||||||
if (lastMask != ymMask) {
|
if (lastMask!=ymMask) {
|
||||||
// if the ymMask just changed, then the channel has become active.
|
// if the ymMask just changed, then the channel has become active.
|
||||||
// This can only happen on a KeyDN event, so voice = v & 0x07
|
// This can only happen on a KeyDN event, so voice=v&0x07
|
||||||
// insert a keyUP just to be safe.
|
// insert a keyUP just to be safe.
|
||||||
ymwrites.push_back(DivRegWrite(0x08,v&0x07));
|
ymwrites.push_back(DivRegWrite(0x08,v&0x07));
|
||||||
numWrites++;
|
numWrites++;
|
||||||
// flush the ym_NEW cached states for this channel into the ZSM....
|
// flush the ym_NEW cached states for this channel into the ZSM....
|
||||||
for ( int i=0x20 + (v&0x07); i <= 0xff ; i+=8) {
|
for (int i=0x20+(v&0x07); i<=0xff; i+=8) {
|
||||||
if (ymState[ym_NEW][i] != ymState[ym_PREV][i]) {
|
if (ymState[ym_NEW][i]!=ymState[ym_PREV][i]) {
|
||||||
ymwrites.push_back(DivRegWrite(i,ymState[ym_NEW][i]));
|
ymwrites.push_back(DivRegWrite(i,ymState[ym_NEW][i]));
|
||||||
numWrites++;
|
numWrites++;
|
||||||
// ...and update the shadow
|
// ...and update the shadow
|
||||||
ymState[ym_PREV][i] = ymState[ym_NEW][i];
|
ymState[ym_PREV][i]=ymState[ym_NEW][i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Handle the current write if channel is active
|
// Handle the current write if channel is active
|
||||||
if (writeit && ((ymState[ym_NEW][a] != ymState[ym_PREV][a])||a==0x08) ) {
|
if (writeit && ((ymState[ym_NEW][a]!=ymState[ym_PREV][a]) || a==0x08)) {
|
||||||
// update YM shadow if not the KeyUPDN register.
|
// update YM shadow if not the KeyUPDN register.
|
||||||
if (a!=0x008) ymState[ym_PREV][a] = ymState[ym_NEW][a];
|
if (a!=8) ymState[ym_PREV][a]=ymState[ym_NEW][a];
|
||||||
// if reg = PMD, then change back to real register 0x19
|
// if reg=PMD, then change back to real register 0x19
|
||||||
if (a==0x1a) a=0x19;
|
if (a==0x1a) a=0x19;
|
||||||
ymwrites.push_back(DivRegWrite(a,v));
|
ymwrites.push_back(DivRegWrite(a,v));
|
||||||
numWrites++;
|
numWrites++;
|
||||||
|
|
@ -109,24 +108,26 @@ void DivZSM::writeYM(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)
|
// 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);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(psgState[psg_PREV][a] == v) {
|
if (psgState[psg_PREV][a]==v) {
|
||||||
if (psgState[psg_NEW][a] != v)
|
if (psgState[psg_NEW][a]!=v) {
|
||||||
// NEW value is being reset to the same as PREV value
|
// NEW value is being reset to the same as PREV value
|
||||||
// so it is no longer a new write.
|
// so it is no longer a new write.
|
||||||
numWrites--;
|
numWrites--;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (psgState[psg_PREV][a] == psgState[psg_NEW][a])
|
if (psgState[psg_PREV][a]==psgState[psg_NEW][a]) {
|
||||||
// if this write changes the NEW cached value to something other
|
// if this write changes the NEW cached value to something other
|
||||||
// than the PREV value, then this is a new write.
|
// than the PREV value, then this is a new write.
|
||||||
numWrites++;
|
numWrites++;
|
||||||
}
|
}
|
||||||
psgState[psg_NEW][a] = v;
|
}
|
||||||
// mark channel as used in the psgMask if volume is set > 0.
|
psgState[psg_NEW][a]=v;
|
||||||
if ((a % 4 == 2) && (v & 0x3f)) psgMask |= (1 << (a>>2));
|
// mark channel as used in the psgMask if volume is set>0.
|
||||||
|
if ((a%4==2) && (v&0x3f)) psgMask|=(1<<(a>>2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivZSM::writePCM(unsigned char a, unsigned char v) {
|
void DivZSM::writePCM(unsigned char a, unsigned char v) {
|
||||||
|
|
@ -135,7 +136,7 @@ void DivZSM::writePCM(unsigned char a, unsigned char v) {
|
||||||
|
|
||||||
void DivZSM::tick(int numticks) {
|
void DivZSM::tick(int numticks) {
|
||||||
flushWrites();
|
flushWrites();
|
||||||
ticks += numticks;
|
ticks+=numticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivZSM::setLoopPoint() {
|
void DivZSM::setLoopPoint() {
|
||||||
|
|
@ -154,12 +155,14 @@ void DivZSM::setLoopPoint() {
|
||||||
memset(&ymState[ym_PREV],-1,sizeof(ymState[ym_PREV]));
|
memset(&ymState[ym_PREV],-1,sizeof(ymState[ym_PREV]));
|
||||||
// ... and cache (except for unused channels)
|
// ... and cache (except for unused channels)
|
||||||
memset(&ymState[ym_NEW],-1,0x20);
|
memset(&ymState[ym_NEW],-1,0x20);
|
||||||
for (int chan=0; chan<8 ; chan++) {
|
for (int chan=0; chan<8; chan++) {
|
||||||
// do not clear state for as-yet-unused channels
|
// do not clear state for as-yet-unused channels
|
||||||
if (!(ymMask & (1<<chan))) continue;
|
if (!(ymMask&(1<<chan))) continue;
|
||||||
// clear the state for channels in use so they match the unknown state
|
// clear the state for channels in use so they match the unknown state
|
||||||
// of the YM shadow.
|
// of the YM shadow.
|
||||||
for (int i=0x20+chan; i<=0xff; i+= 8) ymState[ym_NEW][i] = -1;
|
for (int i=0x20+chan; i<=0xff; i+=8) {
|
||||||
|
ymState[ym_NEW][i]=-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,8 +172,8 @@ SafeWriter* DivZSM::finish() {
|
||||||
w->writeC(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->writeC((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;
|
||||||
}
|
}
|
||||||
|
|
@ -179,16 +182,16 @@ 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->writeC(i);
|
w->writeC(i);
|
||||||
w->writeC(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->writeC((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 {
|
||||||
|
|
@ -205,10 +208,10 @@ void DivZSM::flushWrites() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivZSM::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->writeC((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);
|
||||||
|
|
|
||||||
|
|
@ -27,36 +27,42 @@ 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) {
|
||||||
|
int VERA=-1;
|
||||||
|
int YM=-1;
|
||||||
|
int IGNORED=0;
|
||||||
|
|
||||||
int VERA = -1;
|
|
||||||
int YM = -1;
|
|
||||||
int IGNORED = 0;
|
|
||||||
|
|
||||||
//loop = false;
|
|
||||||
// find indexes for YM and VERA. Ignore other systems.
|
// find indexes for YM and VERA. Ignore other systems.
|
||||||
for (int i=0; i<song.systemLen; i++) {
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
switch (song.system[i]) {
|
switch (song.system[i]) {
|
||||||
case DIV_SYSTEM_VERA:
|
case DIV_SYSTEM_VERA:
|
||||||
if (VERA >= 0) { IGNORED++;break; }
|
if (VERA>=0) {
|
||||||
VERA = i;
|
IGNORED++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
VERA=i;
|
||||||
logD("VERA detected as chip id %d",i);
|
logD("VERA detected as chip id %d",i);
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2151:
|
case DIV_SYSTEM_YM2151:
|
||||||
if (YM >= 0) { IGNORED++;break; }
|
if (YM>=0) {
|
||||||
YM = i;
|
IGNORED++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
YM=i;
|
||||||
logD("YM detected as chip id %d",i);
|
logD("YM detected as chip id %d",i);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
IGNORED++;
|
IGNORED++;
|
||||||
logD("Ignoring chip %d systemID %d",i,song.system[i]);
|
logD("Ignoring chip %d systemID %d",i,song.system[i]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (VERA < 0 && YM < 0) {
|
if (VERA<0 && YM<0) {
|
||||||
logE("No supported systems for ZSM");
|
logE("No supported systems for ZSM");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (IGNORED > 0)
|
if (IGNORED>0) {
|
||||||
logW("ZSM export ignoring %d unsupported system%c",IGNORED,IGNORED>1?'s':' ');
|
logW("ZSM export ignoring %d unsupported system%c",IGNORED,IGNORED>1?'s':' ');
|
||||||
|
}
|
||||||
|
|
||||||
stop();
|
stop();
|
||||||
repeatPattern=false;
|
repeatPattern=false;
|
||||||
|
|
@ -64,7 +70,7 @@ SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
|
||||||
BUSY_BEGIN_SOFT;
|
BUSY_BEGIN_SOFT;
|
||||||
|
|
||||||
double origRate=got.rate;
|
double origRate=got.rate;
|
||||||
got.rate=zsmrate & 0xffff;
|
got.rate=zsmrate&0xffff;
|
||||||
|
|
||||||
// determine loop point
|
// determine loop point
|
||||||
int loopOrder=0;
|
int loopOrder=0;
|
||||||
|
|
@ -91,13 +97,13 @@ SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
|
||||||
int loopPos=-1;
|
int loopPos=-1;
|
||||||
int writeCount=0;
|
int writeCount=0;
|
||||||
int fracWait=0; // accumulates fractional ticks
|
int fracWait=0; // accumulates fractional ticks
|
||||||
if (VERA >= 0) disCont[VERA].dispatch->toggleRegisterDump(true);
|
if (VERA>=0) disCont[VERA].dispatch->toggleRegisterDump(true);
|
||||||
if (YM >= 0) {
|
if (YM>=0) {
|
||||||
disCont[YM].dispatch->toggleRegisterDump(true);
|
disCont[YM].dispatch->toggleRegisterDump(true);
|
||||||
// emit LFO initialization commands
|
// emit LFO initialization commands
|
||||||
zsm.writeYM(0x18,0); // freq = 0
|
zsm.writeYM(0x18,0); // freq=0
|
||||||
zsm.writeYM(0x19,0x7F); // AMD = 7F
|
zsm.writeYM(0x19,0x7F); // AMD =7F
|
||||||
zsm.writeYM(0x19,0xFF); // PMD = 7F
|
zsm.writeYM(0x19,0xFF); // PMD =7F
|
||||||
// TODO: incorporate the Furnace meta-command for init data and filter
|
// TODO: incorporate the Furnace meta-command for init data and filter
|
||||||
// out writes to otherwise-unused channels.
|
// out writes to otherwise-unused channels.
|
||||||
}
|
}
|
||||||
|
|
@ -126,25 +132,26 @@ SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
|
||||||
int i=0;
|
int i=0;
|
||||||
// dump YM writes first
|
// dump YM writes first
|
||||||
if (j==0) {
|
if (j==0) {
|
||||||
if (YM < 0)
|
if (YM<0) {
|
||||||
continue;
|
continue;
|
||||||
else
|
} else {
|
||||||
i=YM;
|
i=YM;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// dump VERA writes second
|
// dump VERA writes second
|
||||||
if (j==1) {
|
if (j==1) {
|
||||||
if (VERA < 0)
|
if (VERA<0) {
|
||||||
continue;
|
continue;
|
||||||
else {
|
} else {
|
||||||
i=VERA;
|
i=VERA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<DivRegWrite>& writes=disCont[i].dispatch->getRegisterWrites();
|
std::vector<DivRegWrite>& writes=disCont[i].dispatch->getRegisterWrites();
|
||||||
if (writes.size() > 0)
|
if (writes.size()>0)
|
||||||
logD("zsmOps: Writing %d messages to chip %d",writes.size(), i);
|
logD("zsmOps: Writing %d messages to chip %d",writes.size(),i);
|
||||||
for (DivRegWrite& write: writes) {
|
for (DivRegWrite& write: writes) {
|
||||||
if (i==YM) zsm.writeYM(write.addr&0xff, write.val);
|
if (i==YM) zsm.writeYM(write.addr&0xff,write.val);
|
||||||
if (i==VERA) zsm.writePSG(write.addr&0xff, write.val);
|
if (i==VERA) zsm.writePSG(write.addr&0xff,write.val);
|
||||||
writeCount++;
|
writeCount++;
|
||||||
}
|
}
|
||||||
writes.clear();
|
writes.clear();
|
||||||
|
|
@ -152,9 +159,9 @@ SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
|
||||||
|
|
||||||
// write wait
|
// write wait
|
||||||
int totalWait=cycles>>MASTER_CLOCK_PREC;
|
int totalWait=cycles>>MASTER_CLOCK_PREC;
|
||||||
fracWait += cycles & MASTER_CLOCK_MASK;
|
fracWait+=cycles&MASTER_CLOCK_MASK;
|
||||||
totalWait += fracWait>>MASTER_CLOCK_PREC;
|
totalWait+=fracWait>>MASTER_CLOCK_PREC;
|
||||||
fracWait &= MASTER_CLOCK_MASK;
|
fracWait&=MASTER_CLOCK_MASK;
|
||||||
if (totalWait>0) {
|
if (totalWait>0) {
|
||||||
zsm.tick(totalWait);
|
zsm.tick(totalWait);
|
||||||
//tickCount+=totalWait;
|
//tickCount+=totalWait;
|
||||||
|
|
@ -163,9 +170,9 @@ SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
|
||||||
// end of song
|
// end of song
|
||||||
|
|
||||||
// done - close out.
|
// done - close out.
|
||||||
got.rate = origRate;
|
got.rate=origRate;
|
||||||
if (VERA >= 0) disCont[VERA].dispatch->toggleRegisterDump(false);
|
if (VERA>=0) disCont[VERA].dispatch->toggleRegisterDump(false);
|
||||||
if (YM >= 0) disCont[YM].dispatch->toggleRegisterDump(false);
|
if (YM>=0) disCont[YM].dispatch->toggleRegisterDump(false);
|
||||||
|
|
||||||
remainingLoops=-1;
|
remainingLoops=-1;
|
||||||
playing=false;
|
playing=false;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue