Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare for NMK112 bankswitching support #1447

Merged
merged 23 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5aeeb09
Prepare for NMK112 bankswitching support
cam900 Aug 31, 2023
a2be46b
Casting
cam900 Aug 31, 2023
e839212
Merge branch 'master' into nmk112
tildearrow Sep 7, 2023
4a92bf0
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Sep 21, 2023
9db632b
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Sep 22, 2023
b12af42
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Oct 2, 2023
e76d96f
Fix length
cam900 Oct 3, 2023
d6d3bbc
Fix build
cam900 Oct 3, 2023
15bdb19
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Oct 21, 2023
31977ab
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Nov 2, 2023
fa95bea
Sync with master
cam900 Nov 2, 2023
7cf40f2
Merge branches 'master' and 'nmk112' of https://github.com/tildearrow…
cam900 Nov 4, 2023
f6849df
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Nov 15, 2023
b427bab
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Dec 1, 2023
32f0113
Fix VGM output
cam900 Dec 1, 2023
35f8a92
Reduce duplication
cam900 Dec 1, 2023
ea4d4a0
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Dec 11, 2023
7f706b9
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Dec 14, 2023
e5b6f0b
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Jan 19, 2024
6440b8c
Add warning for MSM6295 maximum bankswitched sample length
cam900 Jan 19, 2024
8e0b64c
Add preset variation with NMK112
cam900 Jan 19, 2024
6917c54
Byte to nibble
cam900 Jan 25, 2024
3922770
Merge branch 'master' of https://github.com/tildearrow/furnace into n…
cam900 Feb 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 125 additions & 38 deletions src/engine/platform/msm6295.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -304,6 +326,9 @@ void DivPlatformMSM6295::reset() {
sampleBank=0;
rateSel=rateSelInit;
rWrite(12,!rateSelInit);
if (isBanked) {
rWrite(14,1);
}

delay=0;
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
// 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++;
}
adpcmMemLen=memPos+256;

// 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=((unsigned int)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;
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;
}
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;
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;
}
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;
Expand Down Expand Up @@ -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;
Expand Down
12 changes: 10 additions & 2 deletions src/engine/platform/msm6295.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
22 changes: 22 additions & 0 deletions src/gui/debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions src/gui/sysConf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down