Fix some ES5506 VGM write feature (but still incomplete)

8 bit addWrite because ES5506 host interface is 8 bit width.
This commit is contained in:
cam900 2025-06-01 19:19:42 +09:00
parent 4d7945f778
commit 205e2124b6
4 changed files with 162 additions and 70 deletions

View file

@ -27,29 +27,124 @@
#define rWrite(a,...) {if(!skipRegisterWrites) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__)); }}
#define immWrite(a,...) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__));}
#define pageWrite(p,a,...) \
#define pageWrite(p,a,d) \
if (!skipRegisterWrites) { \
if (curPage!=(p)) { \
curPage=(p); \
rWrite(0xf,curPage); \
rWrite(0xf,curPage) \
if (dumpWrites) { \
addWrite(0x3c,0) \
addWrite(0x3d,0) \
addWrite(0x3e,0) \
addWrite(0x3f,curPage) \
} \
} \
rWrite((a),(d)) \
if (dumpWrites) { \
addWrite(((a)<<2)|0,((d)>>24)&0xff) \
addWrite(((a)<<2)|1,((d)>>16)&0xff) \
addWrite(((a)<<2)|2,((d)>>8)&0xff) \
addWrite(((a)<<2)|3,((d)>>0)&0xff) \
} \
rWrite((a),__VA_ARGS__); \
}
#define pageWriteMask(p,pm,a,...) \
#define pageWriteDelayed(p,a,d,dl) \
if (!skipRegisterWrites) { \
if (curPage!=(p)) { \
curPage=(p); \
rWrite(0xf,curPage) \
if (dumpWrites) { \
addWrite(0x3c,0) \
addWrite(0x3d,0) \
addWrite(0x3e,0) \
addWrite(0x3f,curPage) \
} \
} \
rWrite((a),(d),(dl)) \
if (dumpWrites) { \
addWrite(((a)<<2)|0,((d)>>24)&0xff) \
addWrite(((a)<<2)|1,((d)>>16)&0xff) \
addWrite(((a)<<2)|2,((d)>>8)&0xff) \
addWrite(((a)<<2)|3,((d)>>0)&0xff) \
} \
}
#define pageWriteMask(p,pm,a,d) \
if (!skipRegisterWrites) { \
if ((curPage&(pm))!=((p)&(pm))) { \
curPage=(curPage&~(pm))|((p)&(pm)); \
rWrite(0xf,curPage,(pm)); \
rWrite(0xf,curPage,(pm)) \
if (dumpWrites) { \
addWrite(0x3c,0) \
addWrite(0x3d,0) \
addWrite(0x3e,0) \
addWrite(0x3f,curPage) \
} \
} \
rWrite((a),(d)) \
if (dumpWrites) { \
addWrite(((a)<<2)|0,((d)>>24)&0xff) \
addWrite(((a)<<2)|1,((d)>>16)&0xff) \
addWrite(((a)<<2)|2,((d)>>8)&0xff) \
addWrite(((a)<<2)|3,((d)>>0)&0xff) \
} \
}
#define crWrite(c,d) \
if (!skipRegisterWrites) { \
if ((curPage&0x5f)!=((c)&0x5f)) { \
curPage=(curPage&~0x5f)|((c)&0x5f); \
rWrite(0xf,curPage,0x5f) \
if (dumpWrites) { \
addWrite(0x3c,0) \
addWrite(0x3d,0) \
addWrite(0x3e,0) \
addWrite(0x3f,curPage) \
} \
} \
chan[c].cr=(d); \
rWrite(0,chan[c].cr) \
if (dumpWrites) { \
addWrite(0x0,0) \
addWrite(0x1,0) \
addWrite(0x2,(chan[c].cr>>8)&0xff) \
addWrite(0x3,(chan[c].cr>>0)&0xff) \
} \
}
#define crWriteMask(c,d,m) \
if (!skipRegisterWrites) { \
if ((curPage&0x5f)!=((c)&0x5f)) { \
curPage=(curPage&~0x5f)|((c)&0x5f); \
rWrite(0xf,curPage,0x5f) \
if (dumpWrites) { \
addWrite(0x3c,0) \
addWrite(0x3d,0) \
addWrite(0x3e,0) \
addWrite(0x3f,curPage); \
} \
} \
chan[c].cr=(chan[c].cr&~(m))|((d)&(m)); \
rWrite(0,chan[c].cr,(m)) \
if (dumpWrites) { \
addWrite(0x0,0) \
addWrite(0x1,0) \
addWrite(0x2,(chan[c].cr>>8)&0xff) \
addWrite(0x3,(chan[c].cr>>0)&0xff) \
} \
rWrite((a),__VA_ARGS__); \
}
#define pageReadMask(p,pm,a,st,...) \
if (!skipRegisterWrites) { \
if ((curPage&(pm))!=((p)&(pm))) { \
curPage=(curPage&~(pm))|((p)&(pm)); \
rWrite(0xf,curPage,(pm)); \
rWrite(0xf,curPage,(pm)) \
if (dumpWrites) { \
addWrite(0x3c,0) \
addWrite(0x3d,0) \
addWrite(0x3e,0) \
addWrite(0x3f,curPage) \
} \
} \
rRead(st,(a),__VA_ARGS__); \
}
@ -119,15 +214,15 @@ void DivPlatformES5506::acquire(short** buf, size_t len) {
while (!hostIntf32.empty()) {
QueuedHostIntf w=hostIntf32.front();
if (w.isRead && (w.read!=NULL)) {
hostIntf8.push(QueuedHostIntf(w.state,0,w.addr,w.read,w.mask));
hostIntf8.push(QueuedHostIntf(w.state,1,w.addr,w.read,w.mask));
hostIntf8.push(QueuedHostIntf(w.state,2,w.addr,w.read,w.mask));
hostIntf8.push(QueuedHostIntf(w.state,3,w.addr,w.read,w.mask,w.delay));
hostIntf8.push(QueuedHostIntf(w.state,0,w.addr,w.read));
hostIntf8.push(QueuedHostIntf(w.state,1,w.addr,w.read));
hostIntf8.push(QueuedHostIntf(w.state,2,w.addr,w.read));
hostIntf8.push(QueuedHostIntf(w.state,3,w.addr,w.read,w.delay));
} else {
hostIntf8.push(QueuedHostIntf(0,w.addr,w.val,w.mask));
hostIntf8.push(QueuedHostIntf(1,w.addr,w.val,w.mask));
hostIntf8.push(QueuedHostIntf(2,w.addr,w.val,w.mask));
hostIntf8.push(QueuedHostIntf(3,w.addr,w.val,w.mask,w.delay));
hostIntf8.push(QueuedHostIntf(0,w.addr,w.val));
hostIntf8.push(QueuedHostIntf(1,w.addr,w.val));
hostIntf8.push(QueuedHostIntf(2,w.addr,w.val));
hostIntf8.push(QueuedHostIntf(3,w.addr,w.val,w.delay));
}
hostIntf32.pop();
}
@ -142,24 +237,11 @@ void DivPlatformES5506::acquire(short** buf, size_t len) {
logE("READING?!");
hostIntf8.pop();
} else {
unsigned int mask=(w.mask>>shift)&0xff;
if ((mask==0xff) || isMasked) {
if (mask==0xff) {
maskedVal=(w.val>>shift)&0xff;
}
es5506.host_w((w.addr<<2)+w.step,maskedVal);
if(dumpWrites) {
addWrite((w.addr<<2)+w.step,maskedVal);
}
isMasked=false;
es5506.host_w((w.addr<<2)+w.step,(w.val>>shift)&0xff);
if ((w.step==3) && (w.delay>0)) {
cycle+=w.delay;
}
hostIntf8.pop();
} else if (!isMasked) {
maskedVal=((w.val>>shift)&mask)|(es5506.host_r((w.addr<<2)+w.step)&~mask);
isMasked=true;
}
if (cycle>0) break;
}
}
@ -429,13 +511,13 @@ void DivPlatformES5506::tick(bool sysTick) {
if (chan[i].pcm.pause!=(bool)(chan[i].std.alg.val&1)) {
chan[i].pcm.pause=chan[i].std.alg.val&1;
if (!chan[i].keyOn) {
pageWriteMask(0x00|i,0x5f,0x00,chan[i].pcm.pause?0x0002:0x0000,0x0002);
crWriteMask(0x00|i,chan[i].pcm.pause?0x0002:0x0000,0x0002);
}
}
if (chan[i].pcm.direction!=(bool)(chan[i].std.alg.val&2)) {
chan[i].pcm.direction=chan[i].std.alg.val&2;
if (!chan[i].keyOn) {
pageWriteMask(0x00|i,0x5f,0x00,chan[i].pcm.direction?0x0040:0x0000,0x0040);
crWriteMask(0x00|i,chan[i].pcm.direction?0x0040:0x0000,0x0040);
}
}
}
@ -469,7 +551,7 @@ void DivPlatformES5506::tick(bool sysTick) {
}
}
if (chan[i].volChanged.ca) {
pageWriteMask(0x00|i,0x5f,0x00,(chan[i].ca<<10),0x1c00);
crWriteMask(0x00|i,(chan[i].ca<<10),0x1c00);
}
chan[i].volChanged.changed=0;
}
@ -578,7 +660,7 @@ void DivPlatformES5506::tick(bool sysTick) {
break;
}
// Set loop mode & Bank
pageWriteMask(0x00|i,0x5f,0x00,loopFlag,0xe0fd);
crWriteMask(0x00|i,loopFlag,0xe0fd);
}
chan[i].pcmChanged.loopBank=0;
}
@ -587,7 +669,7 @@ void DivPlatformES5506::tick(bool sysTick) {
if (chan[i].filterChanged.changed) {
if (!chan[i].keyOn) {
if (chan[i].filterChanged.mode) {
pageWriteMask(0x00|i,0x5f,0x00,(chan[i].filter.mode<<8),0x0300);
crWriteMask(0x00|i,(chan[i].filter.mode<<8),0x0300);
}
if (chan[i].filterChanged.k2) {
if (chan[i].std.ex2.mode!=0) { // Relative
@ -675,11 +757,11 @@ void DivPlatformES5506::tick(bool sysTick) {
}
chan[i].k1Prev=0xffff;
chan[i].k2Prev=0xffff;
pageWriteMask(0x00|i,0x5f,0x00,0x0303); // Wipeout CR
crWrite(0x00|i,0x0303); // Wipeout CR
pageWrite(0x00|i,0x06,0); // Clear ECOUNT
pageWrite(0x20|i,0x03,startPos); // Set ACCUM to start address
pageWrite(0x00|i,0x07,0xffff); // Set K1 and K2 to 0xffff
pageWrite(0x00|i,0x09,0xffff,~0,(chanMax+1)*4*2); // needs to 4 sample period delay
pageWriteDelayed(0x00|i,0x09,0xffff,(chanMax+1)*4*2); // needs to 4 sample period delay
pageWrite(0x00|i,0x01,chan[i].freq);
pageWrite(0x20|i,0x01,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.start:chan[i].pcm.loopStart);
pageWrite(0x20|i,0x02,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.end:chan[i].pcm.loopEnd);
@ -721,7 +803,7 @@ void DivPlatformES5506::tick(bool sysTick) {
pageWrite(0x00|i,0x0a,((unsigned char)(chan[i].envelope.k1Ramp)<<8)|(chan[i].envelope.k1Slow?1:0));
pageWrite(0x00|i,0x08,((unsigned char)(chan[i].envelope.k2Ramp)<<8)|(chan[i].envelope.k2Slow?1:0));
// initialize filter
pageWriteMask(0x00|i,0x5f,0x00,(chan[i].pcm.bank<<14)|(chan[i].filter.mode<<8),0xc300);
crWriteMask(0x00|i,(chan[i].pcm.bank<<14)|(chan[i].filter.mode<<8),0xc300);
if ((chan[i].std.ex2.mode!=0) && (chan[i].std.ex2.had)) {
k2=CLAMP(chan[i].filter.k2+chan[i].k2Offs,0,65535);
} else {
@ -762,11 +844,11 @@ void DivPlatformES5506::tick(bool sysTick) {
}
// Run sample
pageWrite(0x00|i,0x06,chan[i].envelope.ecount); // Clear ECOUNT
pageWriteMask(0x00|i,0x5f,0x00,loopFlag,0x3cff);
crWriteMask(0x00|i,loopFlag,0x3cff);
}
}
if (chan[i].keyOff) {
pageWriteMask(0x00|i,0x5f,0x00,0x0303); // Wipeout CR
crWrite(0x00|i,0x0303); // Wipeout CR
} else if (!chan[i].keyOn && chan[i].active) {
pageWrite(0x00|i,0x01,chan[i].freq);
}
@ -1085,7 +1167,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
if (chan[c.chan].active) {
if (chan[c.chan].pcm.pause!=(bool)(c.value&1)) {
chan[c.chan].pcm.pause=c.value&1;
pageWriteMask(0x00|c.chan,0x5f,0x00,chan[c.chan].pcm.pause?0x0002:0x0000,0x0002);
crWriteMask(0x00|c.chan,chan[c.chan].pcm.pause?0x0002:0x0000,0x0002);
}
}
break;
@ -1141,7 +1223,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
case DIV_CMD_SAMPLE_DIR: {
if (chan[c.chan].pcm.direction!=(bool)(c.value&1)) {
chan[c.chan].pcm.direction=c.value&1;
pageWriteMask(0x00|c.chan,0x5f,0x00,chan[c.chan].pcm.direction?0x0040:0x0000,0x0040);
crWriteMask(0x00|c.chan,chan[c.chan].pcm.direction?0x0040:0x0000,0x0040);
}
break;
}
@ -1212,12 +1294,14 @@ void DivPlatformES5506::reset() {
cycle=0;
curPage=0;
maskedVal=0;
irqv=0x80;
isMasked=false;
irqTrigger=false;
chanMax=initChanMax;
if (dumpWrites) {
addWrite(0xffffffff,0);
}
pageWriteMask(0x00,0x60,0x0b,chanMax);
pageWriteMask(0x00,0x60,0x0b,0x1f);
// set serial output to I2S-ish, 16 bit
@ -1286,6 +1370,10 @@ unsigned char* DivPlatformES5506::getRegisterPool() {
for (unsigned char p=0; p<128; p++) {
for (unsigned char r=0; r<16; r++) {
unsigned int reg=es5506.regs_r(p,r,false);
// Sync CR register with register pool
if (((p&0x40)==0) && (r==0)) {
chan[p&0x1f].cr=reg&0xffff;
}
for (int b=0; b<4; b++) {
*regPoolPtr++ = reg>>(24-(b<<3));
}

View file

@ -234,7 +234,6 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
unsigned char step;
unsigned char addr;
unsigned int val;
unsigned int mask;
unsigned int* read;
unsigned short delay;
bool isRead;
@ -243,25 +242,22 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
step(0),
addr(0),
val(0),
mask(0),
read(NULL),
delay(0),
isRead(false) {}
QueuedHostIntf(unsigned char s, unsigned char a, unsigned int v, unsigned int m=(unsigned int)(~0), unsigned short d=0):
QueuedHostIntf(unsigned char s, unsigned char a, unsigned int v, unsigned short d=0):
state(0),
step(s),
addr(a),
val(v),
mask(m),
read(NULL),
delay(0),
isRead(false) {}
QueuedHostIntf(unsigned char st, unsigned char s, unsigned char a, unsigned int* r, unsigned int m=(unsigned int)(~0), unsigned short d=0):
QueuedHostIntf(unsigned char st, unsigned char s, unsigned char a, unsigned int* r, unsigned short d=0):
state(st),
step(s),
addr(a),
val(0),
mask(m),
read(r),
delay(d),
isRead(true) {}
@ -269,9 +265,8 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
FixedQueue<QueuedHostIntf,2048> hostIntf32;
FixedQueue<QueuedHostIntf,2048> hostIntf8;
int cycle, curPage, volScale;
unsigned char maskedVal;
unsigned int irqv;
bool isMasked, isReaded;
bool isReaded;
bool irqTrigger, amigaVol, amigaPitch;
unsigned int curCR;

View file

@ -389,31 +389,31 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
for (int i=0; i<32; i++) {
for (int b=0; b<4; b++) {
w->writeC(0xbe);
w->writeC((0xf<<2)+b);
w->writeC(i);
w->writeC(baseAddr2|((0xf<<2)+b));
w->writeC((b==3)?i:0);
}
unsigned int init_cr=0x0303;
for (int b=0; b<4; b++) {
w->writeC(0xbe);
w->writeC(b);
w->writeC(baseAddr2|b);
w->writeC(init_cr>>(24-(b<<3)));
}
for (int r=1; r<11; r++) {
for (int b=0; b<4; b++) {
w->writeC(0xbe);
w->writeC((r<<2)+b);
w->writeC(baseAddr2|((r<<2)+b));
w->writeC(((r==7 || r==9) && b&2)?0xff:0);
}
}
for (int b=0; b<4; b++) {
w->writeC(0xbe);
w->writeC((0xf<<2)+b);
w->writeC(baseAddr2|((0xf<<2)+b));
w->writeC(0x20|i);
}
for (int r=1; r<10; r++) {
for (int b=0; b<4; b++) {
w->writeC(0xbe);
w->writeC((r<<2)+b);
w->writeC(baseAddr2|((r<<2)+b));
w->writeC(0);
}
}
@ -1059,7 +1059,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
break;
case DIV_SYSTEM_ES5506:
w->writeC(0xbe);
w->writeC(write.addr&0xff);
w->writeC(baseAddr2|(write.addr&0x7f));
w->writeC(write.val&0xff);
break;
case DIV_SYSTEM_VBOY:
@ -2446,13 +2446,23 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
// TODO
for (int i=0; i<2; i++) {
if (writeES5506[i]!=NULL && writeES5506[i]->getSampleMemUsage()>0) {
// split sample data into 4 areas
unsigned short* mem=(unsigned short*)writeES5506[i]->getSampleMem();
for (int b=0; b<4; b++) {
int offs=b<<22;
int memLen=CLAMP((int)writeES5506[i]->getSampleMemUsage()-offs,0,0x400000);
if (memLen>0) {
w->writeC(0x67);
w->writeC(0x66);
w->writeC(0x8F);
w->writeI((writeES5506[i]->getSampleMemUsage()+8)|(i*0x80000000));
w->writeI(writeES5506[i]->getSampleMemCapacity());
w->writeI(0);
w->write(writeES5506[i]->getSampleMem(),writeES5506[i]->getSampleMemUsage());
w->writeC(0x90);
w->writeI((memLen+8)|(i*0x80000000));
w->writeI(MIN(writeES5506[i]->getSampleMemCapacity(),0x400000));
w->writeI(b<<28);
for (int i=0; i<(memLen>>1); i++) {
w->writeS(mem[(offs>>1)+i]);
}
}
}
}
if (writeC140[i]!=NULL && writeC140[i]->getSampleMemUsage()>0) {
w->writeC(0x67);

View file

@ -494,13 +494,11 @@ void putDispatchChip(void* data, int type) {
ImGui::Text("- cycle: %d",ch->cycle);
ImGui::Text("- curPage: %d",ch->curPage);
ImGui::Text("- volScale: %d",ch->volScale);
ImGui::Text("- maskedVal: %.2x",ch->maskedVal);
ImGui::Text("- irqv: %.2x",ch->irqv);
ImGui::Text("- curCR: %.8x",ch->curCR);
ImGui::Text("- initChanMax: %d",ch->initChanMax);
ImGui::Text("- chanMax: %d",ch->chanMax);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->isMasked?colorOn:colorOff,">> IsMasked");
ImGui::TextColored(ch->isReaded?colorOn:colorOff,">> isReaded");
ImGui::TextColored(ch->irqTrigger?colorOn:colorOff,">> IrqTrigger");
break;
@ -885,6 +883,7 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text("- wave: %d",ch->wave);
ImGui::Text("- VolMacroMax: %d",ch->volMacroMax);
ImGui::Text("- PanMacroMax: %d",ch->panMacroMax);
ImGui::Text("- CR: %.4x",ch->cr);
ImGui::Text("* PCM:");
ImGui::Text(" * index: %d",ch->pcm.index);
ImGui::Text(" - next: %d",ch->pcm.next);