mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-30 16:33:01 +00:00
Prepare for NMK112 bankswitching support
This commit is contained in:
parent
65cd433ac7
commit
5aeeb09616
4 changed files with 164 additions and 41 deletions
|
@ -34,6 +34,12 @@ u8 DivPlatformMSM6295::read_byte(u32 address) {
|
|||
if (adpcmMem==NULL || address>=getSampleMemCapacity(0)) {
|
||||
return 0;
|
||||
}
|
||||
if (isBanked) {
|
||||
if (address<0x400) {
|
||||
return adpcmMem[(bank[(address>>8)&0x3]<<16)|(address&0x3ff)];
|
||||
}
|
||||
return adpcmMem[(bank[(address>>16)&0x3]<<16)|(address&0xffff)];
|
||||
}
|
||||
return adpcmMem[address&0x3ffff];
|
||||
}
|
||||
|
||||
|
@ -62,6 +68,7 @@ void DivPlatformMSM6295::acquire(short** buf, size_t len) {
|
|||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
bank[w.addr-16]=w.val;
|
||||
break;
|
||||
}
|
||||
writes.pop();
|
||||
|
@ -109,7 +116,12 @@ void DivPlatformMSM6295::tick(bool sysTick) {
|
|||
rWriteDelay(0,(8<<i),60); // turn off
|
||||
if (chan[i].active && !chan[i].keyOff) {
|
||||
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||
rWrite(0,0x80|chan[i].sample); // set phrase
|
||||
if (isBanked) {
|
||||
rWrite(16+i,bankedPhrase[chan[i].sample].bank);
|
||||
rWrite(0,0x80|(i<<5)|bankedPhrase[chan[i].sample].phrase);
|
||||
} else {
|
||||
rWrite(0,0x80|chan[i].sample); // set phrase
|
||||
}
|
||||
rWrite(0,(16<<i)|(8-chan[i].outVol)); // turn on
|
||||
} else {
|
||||
chan[i].sample=-1;
|
||||
|
@ -147,7 +159,12 @@ int DivPlatformMSM6295::dispatch(DivCommand c) {
|
|||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
rWriteDelay(0,(8<<c.chan),180); // turn off
|
||||
rWrite(0,0x80|chan[c.chan].sample); // set phrase
|
||||
if (isBanked) {
|
||||
rWrite(16+c.chan,bankedPhrase[chan[c.chan].sample].bank);
|
||||
rWrite(0,0x80|(c.chan<<5)|bankedPhrase[chan[c.chan].sample].phrase);
|
||||
} else {
|
||||
rWrite(0,0x80|chan[c.chan].sample); // set phrase
|
||||
}
|
||||
rWrite(0,(16<<c.chan)|(8-chan[c.chan].outVol)); // turn on
|
||||
} else {
|
||||
break;
|
||||
|
@ -162,7 +179,12 @@ int DivPlatformMSM6295::dispatch(DivCommand c) {
|
|||
//DivSample* s=parent->getSample(12*sampleBank+c.value%12);
|
||||
chan[c.chan].sample=12*sampleBank+c.value%12;
|
||||
rWriteDelay(0,(8<<c.chan),180); // turn off
|
||||
rWrite(0,0x80|chan[c.chan].sample); // set phrase
|
||||
if (isBanked) {
|
||||
rWrite(16+c.chan,bankedPhrase[chan[c.chan].sample].bank);
|
||||
rWrite(0,0x80|(c.chan<<5)|bankedPhrase[chan[c.chan].sample].phrase);
|
||||
} else {
|
||||
rWrite(0,0x80|chan[c.chan].sample); // set phrase
|
||||
}
|
||||
rWrite(0,(16<<c.chan)|(8-chan[c.chan].outVol)); // turn on
|
||||
}
|
||||
break;
|
||||
|
@ -304,6 +326,9 @@ void DivPlatformMSM6295::reset() {
|
|||
sampleBank=0;
|
||||
rateSel=rateSelInit;
|
||||
rWrite(12,!rateSelInit);
|
||||
if (isBanked) {
|
||||
rWrite(14,1);
|
||||
}
|
||||
|
||||
delay=0;
|
||||
}
|
||||
|
@ -335,7 +360,7 @@ const void* DivPlatformMSM6295::getSampleMem(int index) {
|
|||
}
|
||||
|
||||
size_t DivPlatformMSM6295::getSampleMemCapacity(int index) {
|
||||
return index == 0 ? 262144 : 0;
|
||||
return index == 0 ? (isBanked?16777216:262144) : 0;
|
||||
}
|
||||
|
||||
size_t DivPlatformMSM6295::getSampleMemUsage(int index) {
|
||||
|
@ -351,53 +376,114 @@ bool DivPlatformMSM6295::isSampleLoaded(int index, int sample) {
|
|||
void DivPlatformMSM6295::renderSamples(int sysID) {
|
||||
unsigned int sampleOffVOX[256];
|
||||
|
||||
memset(adpcmMem,0,getSampleMemCapacity(0));
|
||||
memset(adpcmMem,0,16777216);
|
||||
memset(sampleOffVOX,0,256*sizeof(unsigned int));
|
||||
memset(sampleLoaded,0,256*sizeof(bool));
|
||||
for (int i=0; i<256; i++) {
|
||||
bankedPhrase[i].bank=0;
|
||||
bankedPhrase[i].phrase=0;
|
||||
}
|
||||
|
||||
// sample data
|
||||
size_t memPos=128*8;
|
||||
int sampleCount=parent->song.sampleLen;
|
||||
if (sampleCount>127) sampleCount=127;
|
||||
for (int i=0; i<sampleCount; i++) {
|
||||
DivSample* s=parent->song.sample[i];
|
||||
if (!s->renderOn[0][sysID]) {
|
||||
sampleOffVOX[i]=0;
|
||||
continue;
|
||||
}
|
||||
if (isBanked) {
|
||||
int bankInd=0;
|
||||
int phraseInd=0;
|
||||
for (int i=0; i<parent->song.sampleLen; i++) {
|
||||
DivSample* s=parent->song.sample[i];
|
||||
if (!s->renderOn[0][sysID]) {
|
||||
sampleOffVOX[i]=0;
|
||||
continue;
|
||||
}
|
||||
|
||||
int paddedLen=s->lengthVOX;
|
||||
if (memPos>=getSampleMemCapacity(0)) {
|
||||
logW("out of ADPCM memory for sample %d!",i);
|
||||
break;
|
||||
int paddedLen=s->lengthVOX;
|
||||
// fit to single bank size
|
||||
if (paddedLen>65536-0x400) {
|
||||
paddedLen=65536-0x400;
|
||||
}
|
||||
// 32 phrase per bank
|
||||
if ((phraseInd>=32)||((memPos&0xff0000)!=((memPos+paddedLen)&0xff0000))) {
|
||||
memPos=((memPos+0xffff)&0xff0000)+0x400;
|
||||
bankInd++;
|
||||
phraseInd=0;
|
||||
}
|
||||
if (memPos>=getSampleMemCapacity(0)) {
|
||||
logW("out of ADPCM memory for sample %d!",i);
|
||||
break;
|
||||
}
|
||||
if (memPos+paddedLen>=getSampleMemCapacity(0)) {
|
||||
memcpy(adpcmMem+memPos,s->dataVOX,getSampleMemCapacity(0)-memPos);
|
||||
logW("out of ADPCM memory for sample %d!",i);
|
||||
} else {
|
||||
memcpy(adpcmMem+memPos,s->dataVOX,paddedLen);
|
||||
sampleLoaded[i]=true;
|
||||
}
|
||||
sampleOffVOX[i]=memPos;
|
||||
bankedPhrase[i].bank=bankInd;
|
||||
bankedPhrase[i].phrase=phraseInd;
|
||||
memPos+=paddedLen;
|
||||
phraseInd++;
|
||||
}
|
||||
if (memPos+paddedLen>=getSampleMemCapacity(0)) {
|
||||
memcpy(adpcmMem+memPos,s->dataVOX,getSampleMemCapacity(0)-memPos);
|
||||
logW("out of ADPCM memory for sample %d!",i);
|
||||
} else {
|
||||
memcpy(adpcmMem+memPos,s->dataVOX,paddedLen);
|
||||
sampleLoaded[i]=true;
|
||||
}
|
||||
sampleOffVOX[i]=memPos;
|
||||
memPos+=paddedLen;
|
||||
}
|
||||
adpcmMemLen=memPos+256;
|
||||
adpcmMemLen=memPos+256;
|
||||
|
||||
// phrase book
|
||||
for (int i=0; i<sampleCount; i++) {
|
||||
DivSample* s=parent->song.sample[i];
|
||||
int endPos=sampleOffVOX[i]+s->lengthVOX;
|
||||
adpcmMem[i*8]=(sampleOffVOX[i]>>16)&0xff;
|
||||
adpcmMem[1+i*8]=(sampleOffVOX[i]>>8)&0xff;
|
||||
adpcmMem[2+i*8]=(sampleOffVOX[i])&0xff;
|
||||
adpcmMem[3+i*8]=(endPos>>16)&0xff;
|
||||
adpcmMem[4+i*8]=(endPos>>8)&0xff;
|
||||
adpcmMem[5+i*8]=(endPos)&0xff;
|
||||
// phrase book
|
||||
for (int i=0; i<parent->song.sampleLen; i++) {
|
||||
DivSample* s=parent->song.sample[i];
|
||||
int endPos=sampleOffVOX[i]+s->lengthVOX;
|
||||
for (int b=0; b<4; b++) {
|
||||
unsigned int bankedAddr=(bankedPhrase[i].bank<<16)+(b<<8)+(bankedPhrase[i].phrase*8);
|
||||
adpcmMem[bankedAddr]=b;
|
||||
adpcmMem[bankedAddr+1]=(sampleOffVOX[i]>>8)&0xff;
|
||||
adpcmMem[bankedAddr+2]=(sampleOffVOX[i])&0xff;
|
||||
adpcmMem[bankedAddr+3]=b;
|
||||
adpcmMem[bankedAddr+4]=(endPos>>8)&0xff;
|
||||
adpcmMem[bankedAddr+5]=(endPos)&0xff;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int sampleCount=parent->song.sampleLen;
|
||||
if (sampleCount>127) sampleCount=127;
|
||||
for (int i=0; i<sampleCount; i++) {
|
||||
DivSample* s=parent->song.sample[i];
|
||||
if (!s->renderOn[0][sysID]) {
|
||||
sampleOffVOX[i]=0;
|
||||
continue;
|
||||
}
|
||||
|
||||
int paddedLen=s->lengthVOX;
|
||||
if (memPos>=getSampleMemCapacity(0)) {
|
||||
logW("out of ADPCM memory for sample %d!",i);
|
||||
break;
|
||||
}
|
||||
if (memPos+paddedLen>=getSampleMemCapacity(0)) {
|
||||
memcpy(adpcmMem+memPos,s->dataVOX,getSampleMemCapacity(0)-memPos);
|
||||
logW("out of ADPCM memory for sample %d!",i);
|
||||
} else {
|
||||
memcpy(adpcmMem+memPos,s->dataVOX,paddedLen);
|
||||
sampleLoaded[i]=true;
|
||||
}
|
||||
sampleOffVOX[i]=memPos;
|
||||
memPos+=paddedLen;
|
||||
}
|
||||
adpcmMemLen=memPos+256;
|
||||
|
||||
// phrase book
|
||||
for (int i=0; i<sampleCount; i++) {
|
||||
DivSample* s=parent->song.sample[i];
|
||||
int endPos=sampleOffVOX[i]+s->lengthVOX;
|
||||
adpcmMem[i*8]=(sampleOffVOX[i]>>16)&0xff;
|
||||
adpcmMem[1+i*8]=(sampleOffVOX[i]>>8)&0xff;
|
||||
adpcmMem[2+i*8]=(sampleOffVOX[i])&0xff;
|
||||
adpcmMem[3+i*8]=(endPos>>16)&0xff;
|
||||
adpcmMem[4+i*8]=(endPos>>8)&0xff;
|
||||
adpcmMem[5+i*8]=(endPos)&0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformMSM6295::setFlags(const DivConfig& flags) {
|
||||
rateSelInit=flags.getBool("rateSel",false);
|
||||
isBanked=flags.getBool("isBanked",false);
|
||||
switch (flags.getInt("clockSel",0)) {
|
||||
case 1:
|
||||
chipClock=4224000/4;
|
||||
|
@ -454,11 +540,12 @@ void DivPlatformMSM6295::setFlags(const DivConfig& flags) {
|
|||
rWrite(12,!rateSelInit);
|
||||
rateSel=rateSelInit;
|
||||
}
|
||||
rWrite(14,isBanked);
|
||||
}
|
||||
|
||||
int DivPlatformMSM6295::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||
parent=p;
|
||||
adpcmMem=new unsigned char[getSampleMemCapacity(0)];
|
||||
adpcmMem=new unsigned char[16777216];
|
||||
adpcmMemLen=0;
|
||||
dumpWrites=false;
|
||||
skipRegisterWrites=false;
|
||||
|
|
|
@ -49,7 +49,6 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
|
|||
};
|
||||
FixedQueue<QueuedWrite,256> writes;
|
||||
msm6295_core msm;
|
||||
unsigned char lastBusy;
|
||||
|
||||
unsigned char* adpcmMem;
|
||||
size_t adpcmMemLen;
|
||||
|
@ -58,7 +57,16 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
|
|||
|
||||
int delay, updateOsc;
|
||||
|
||||
bool rateSel=false, rateSelInit=false;
|
||||
bool rateSel=false, rateSelInit=false, isBanked=false;
|
||||
|
||||
unsigned int bank[4];
|
||||
struct BankedPhrase {
|
||||
unsigned char bank=0;
|
||||
unsigned char phrase=0;
|
||||
BankedPhrase():
|
||||
bank(0),
|
||||
phrase(0) {}
|
||||
} bankedPhrase[256];
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "../engine/platform/pv1000.h"
|
||||
#include "../engine/platform/k053260.h"
|
||||
#include "../engine/platform/c140.h"
|
||||
#include "../engine/platform/msm6295.h"
|
||||
#include "../engine/platform/dummy.h"
|
||||
|
||||
#define COMMON_CHIP_DEBUG \
|
||||
|
@ -554,6 +555,18 @@ void putDispatchChip(void* data, int type) {
|
|||
COMMON_CHIP_DEBUG_BOOL;
|
||||
break;
|
||||
}
|
||||
case DIV_SYSTEM_MSM6295: {
|
||||
DivPlatformMSM6295* ch=(DivPlatformMSM6295*)data;
|
||||
ImGui::Text("> MSM6295");
|
||||
COMMON_CHIP_DEBUG;
|
||||
ImGui::Text("- delay: %d",ch->delay);
|
||||
ImGui::Text("- updateOsc: %d",ch->updateOsc);
|
||||
COMMON_CHIP_DEBUG_BOOL;
|
||||
ImGui::TextColored(ch->rateSel?colorOn:colorOff,">> RateSel");
|
||||
ImGui::TextColored(ch->rateSelInit?colorOn:colorOff,">> rateSelInit");
|
||||
ImGui::TextColored(ch->isBanked?colorOn:colorOff,">> IsBanked");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ImGui::Text("Unimplemented chip! Help!");
|
||||
break;
|
||||
|
@ -1092,6 +1105,15 @@ void putDispatchChan(void* data, int chanNum, int type) {
|
|||
ImGui::TextColored(ch->setPos?colorOn:colorOff,">> SetPos");
|
||||
break;
|
||||
}
|
||||
case DIV_SYSTEM_MSM6295: {
|
||||
DivPlatformMSM6295::Channel* ch=(DivPlatformMSM6295::Channel*)data;
|
||||
ImGui::Text("> MSM6295");
|
||||
COMMON_CHAN_DEBUG;
|
||||
ImGui::Text("* Sample: %d",ch->sample);
|
||||
COMMON_CHAN_DEBUG_BOOL;
|
||||
ImGui::TextColored(ch->furnacePCM?colorOn:colorOff,">> FurnacePCM");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ImGui::Text("Unimplemented chip! Help!");
|
||||
break;
|
||||
|
|
|
@ -1349,6 +1349,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
case DIV_SYSTEM_MSM6295: {
|
||||
int clockSel=flags.getInt("clockSel",0);
|
||||
bool rateSel=flags.getBool("rateSel",false);
|
||||
bool isBanked=flags.getBool("isBanked",false);
|
||||
|
||||
ImGui::Text("Clock rate:");
|
||||
ImGui::Indent();
|
||||
|
@ -1425,10 +1426,15 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
}
|
||||
ImGui::Unindent();
|
||||
|
||||
if (ImGui::Checkbox("Bankswitched (NMK112)",&isBanked)) {
|
||||
altered=true;
|
||||
}
|
||||
|
||||
if (altered) {
|
||||
e->lockSave([&]() {
|
||||
flags.set("clockSel",clockSel);
|
||||
flags.set("rateSel",rateSel);
|
||||
flags.set("isBanked",isBanked);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue