Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt

This commit is contained in:
cam900 2022-11-30 17:39:43 +09:00
commit 7867b59580
85 changed files with 6024 additions and 3108 deletions

View file

@ -152,11 +152,20 @@ size_t DivDispatch::getSampleMemCapacity(int index) {
return 0;
}
const char* DivDispatch::getSampleMemName(int index) {
return NULL;
}
size_t DivDispatch::getSampleMemUsage(int index) {
return 0;
}
void DivDispatch::renderSamples() {
bool DivDispatch::isSampleLoaded(int index, int sample) {
printf("you are calling.\n");
return false;
}
void DivDispatch::renderSamples(int sysID) {
}

View file

@ -1191,13 +1191,25 @@ size_t DivPlatformES5506::getSampleMemUsage(int index) {
return index == 0 ? sampleMemLen : 0;
}
void DivPlatformES5506::renderSamples() {
bool DivPlatformES5506::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformES5506::renderSamples(int sysID) {
memset(sampleMem,0,getSampleMemCapacity());
memset(sampleOffES5506,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=128; // add silent at begin and end of each bank for reverse playback
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOffES5506[i]=0;
continue;
}
unsigned int length=s->length16;
// fit sample size to single bank size
if (length>(4194304-128)) {
@ -1217,6 +1229,7 @@ void DivPlatformES5506::renderSamples() {
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,length);
}
sampleOffES5506[i]=memPos;
sampleLoaded[i]=true;
memPos+=length;
}
sampleMemLen=memPos+256;

View file

@ -249,6 +249,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
signed short* sampleMem; // ES5506 uses 16 bit data bus for samples
size_t sampleMemLen;
unsigned int sampleOffES5506[256];
bool sampleLoaded[256];
struct QueuedHostIntf {
unsigned char state;
unsigned char step;
@ -335,7 +336,8 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
virtual const void* getSampleMem(int index = 0) override;
virtual size_t getSampleMemCapacity(int index = 0) override;
virtual size_t getSampleMemUsage(int index = 0) override;
virtual void renderSamples() override;
virtual bool isSampleLoaded(int index, int sample) override;
virtual void renderSamples(int sysID) override;
virtual const char** getRegisterSheet() override;
virtual int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags) override;
virtual void quit() override;

View file

@ -362,8 +362,15 @@ size_t DivPlatformMSM6258::getSampleMemUsage(int index) {
return index == 0 ? adpcmMemLen : 0;
}
void DivPlatformMSM6258::renderSamples() {
bool DivPlatformMSM6258::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformMSM6258::renderSamples(int sysID) {
memset(adpcmMem,0,getSampleMemCapacity(0));
memset(sampleLoaded,0,256*sizeof(bool));
// sample data
size_t memPos=0;
@ -371,6 +378,8 @@ void DivPlatformMSM6258::renderSamples() {
if (sampleCount>128) sampleCount=128;
for (int i=0; i<sampleCount; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) continue;
int paddedLen=s->lengthVOX;
if (memPos>=getSampleMemCapacity(0)) {
logW("out of ADPCM memory for sample %d!",i);
@ -381,6 +390,7 @@ void DivPlatformMSM6258::renderSamples() {
logW("out of ADPCM memory for sample %d!",i);
} else {
memcpy(adpcmMem+memPos,s->dataVOX,paddedLen);
sampleLoaded[i]=true;
}
memPos+=paddedLen;
}

View file

@ -81,6 +81,7 @@ class DivPlatformMSM6258: public DivDispatch {
unsigned char* adpcmMem;
size_t adpcmMemLen;
bool sampleLoaded[256];
unsigned char sampleBank, msmPan, msmDivider, rateSel, msmClock, clockSel;
signed char msmDividerCount, msmClockCount;
short msmOut;
@ -113,7 +114,8 @@ class DivPlatformMSM6258: public DivDispatch {
const void* getSampleMem(int index);
size_t getSampleMemCapacity(int index);
size_t getSampleMemUsage(int index);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();

View file

@ -335,11 +335,18 @@ size_t DivPlatformMSM6295::getSampleMemUsage(int index) {
return index == 0 ? adpcmMemLen : 0;
}
void DivPlatformMSM6295::renderSamples() {
bool DivPlatformMSM6295::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformMSM6295::renderSamples(int sysID) {
unsigned int sampleOffVOX[256];
memset(adpcmMem,0,getSampleMemCapacity(0));
memset(sampleOffVOX,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
// sample data
size_t memPos=128*8;
@ -347,6 +354,11 @@ void DivPlatformMSM6295::renderSamples() {
if (sampleCount>128) sampleCount=128;
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);
@ -357,6 +369,7 @@ void DivPlatformMSM6295::renderSamples() {
logW("out of ADPCM memory for sample %d!",i);
} else {
memcpy(adpcmMem+memPos,s->dataVOX,paddedLen);
sampleLoaded[i]=true;
}
sampleOffVOX[i]=memPos;
memPos+=paddedLen;

View file

@ -68,6 +68,7 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
unsigned char* adpcmMem;
size_t adpcmMemLen;
bool sampleLoaded[256];
unsigned char sampleBank;
int delay, updateOsc;
@ -101,7 +102,8 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
virtual const void* getSampleMem(int index) override;
virtual size_t getSampleMemCapacity(int index) override;
virtual size_t getSampleMemUsage(int index) override;
virtual void renderSamples() override;
virtual bool isSampleLoaded(int index, int sample) override;
virtual void renderSamples(int chipID) override;
virtual int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags) override;
virtual void quit() override;

View file

@ -721,12 +721,24 @@ size_t DivPlatformNES::getSampleMemUsage(int index) {
return index==0?dpcmMemLen:0;
}
void DivPlatformNES::renderSamples() {
memset(dpcmMem,0,getSampleMemCapacity(0));
bool DivPlatformNES::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformNES::renderSamples(int sysID) {
memset(dpcmMem,0,getSampleMemCapacity(0));\
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOffDPCM[i]=0;
continue;
}
unsigned int paddedLen=(s->lengthDPCM+63)&(~0x3f);
logV("%d padded length: %d",i,paddedLen);
if ((memPos&(~0x3fff))!=((memPos+paddedLen)&(~0x3fff))) {
@ -744,6 +756,7 @@ void DivPlatformNES::renderSamples() {
logW("out of DPCM memory for sample %d!",i);
} else {
memcpy(dpcmMem+memPos,s->dataDPCM,MIN(s->lengthDPCM,paddedLen));
sampleLoaded[i]=true;
}
sampleOffDPCM[i]=memPos;
memPos+=paddedLen;

View file

@ -68,6 +68,7 @@ class DivPlatformNES: public DivDispatch {
int dacSample;
unsigned char* dpcmMem;
size_t dpcmMemLen;
bool sampleLoaded[256];
unsigned char dpcmBank;
unsigned char sampleBank;
unsigned char writeOscBuf;
@ -115,7 +116,8 @@ class DivPlatformNES: public DivDispatch {
const void* getSampleMem(int index);
size_t getSampleMemCapacity(int index);
size_t getSampleMemUsage(int index);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
~DivPlatformNES();

View file

@ -1757,14 +1757,26 @@ size_t DivPlatformOPL::getSampleMemUsage(int index) {
return (index==0 && adpcmChan>=0) ? adpcmBMemLen : 0;
}
void DivPlatformOPL::renderSamples() {
bool DivPlatformOPL::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformOPL::renderSamples(int sysID) {
if (adpcmChan<0) return;
memset(adpcmBMem,0,getSampleMemCapacity(0));
memset(sampleOffB,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOffB[i]=0;
continue;
}
int paddedLen=(s->lengthB+255)&(~0xff);
if ((memPos&0xf00000)!=((memPos+paddedLen)&0xf00000)) {
memPos=(memPos+0xfffff)&0xf00000;
@ -1778,6 +1790,7 @@ void DivPlatformOPL::renderSamples() {
logW("out of ADPCM memory for sample %d!",i);
} else {
memcpy(adpcmBMem+memPos,s->dataB,paddedLen);
sampleLoaded[i]=true;
}
sampleOffB[i]=memPos;
memPos+=paddedLen;

View file

@ -91,6 +91,7 @@ class DivPlatformOPL: public DivDispatch {
size_t adpcmBMemLen;
DivOPLAInterface iface;
unsigned int sampleOffB[256];
bool sampleLoaded[256];
ymfm::adpcm_b_engine* adpcmB;
const unsigned char** slotsNonDrums;
@ -152,7 +153,8 @@ class DivPlatformOPL: public DivDispatch {
const void* getSampleMem(int index);
size_t getSampleMemCapacity(int index);
size_t getSampleMemUsage(int index);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
~DivPlatformOPL();

View file

@ -247,7 +247,7 @@ void DivPlatformOPLL::tick(bool sysTick) {
if (chan[i].freq>65535) chan[i].freq=65535;
int freqt=toFreq(chan[i].freq);
chan[i].freqL=freqt&0xff;
if (i>=6 && properDrums) {
if (i>=6 && properDrums && (i<9 || !noTopHatFreq)) {
immWrite(0x10+drumSlot[i],freqt&0xff);
immWrite(0x20+drumSlot[i],freqt>>8);
} else if (i<6 || !drums) {
@ -963,6 +963,7 @@ void DivPlatformOPLL::setFlags(const DivConfig& flags) {
for (int i=0; i<11; i++) {
oscBuf[i]->rate=rate/2;
}
noTopHatFreq=flags.getBool("noTopHatFreq",false);
}
int DivPlatformOPLL::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {

View file

@ -82,7 +82,7 @@ class DivPlatformOPLL: public DivDispatch {
bool useYMFM;
bool drums;
bool properDrums, properDrumsSys;
bool properDrums, properDrumsSys, noTopHatFreq;
bool vrc7;
unsigned char patchSet;

View file

@ -252,6 +252,11 @@ void DivPlatformPCE::tick(bool sysTick) {
chan[i].freqChanged=false;
}
}
if (updateLFO) {
rWrite(0x08,lfoSpeed);
rWrite(0x09,lfoMode);
updateLFO=false;
}
}
int DivPlatformPCE::dispatch(DivCommand c) {
@ -389,13 +394,11 @@ int DivPlatformPCE::dispatch(DivCommand c) {
} else {
lfoMode=c.value;
}
rWrite(0x08,lfoSpeed);
rWrite(0x09,lfoMode);
updateLFO=true;
break;
case DIV_CMD_PCE_LFO_SPEED:
lfoSpeed=255-c.value;
rWrite(0x08,lfoSpeed);
rWrite(0x09,lfoMode);
updateLFO=true;
break;
case DIV_CMD_NOTE_PORTA: {
int destFreq=NOTE_PERIODIC(c.value2);
@ -525,8 +528,7 @@ void DivPlatformPCE::reset() {
rWrite(0,0);
rWrite(0x01,0xff);
// set LFO
rWrite(0x08,lfoSpeed);
rWrite(0x09,lfoMode);
updateLFO=true;
// set per-channel initial panning
for (int i=0; i<6; i++) {
chWrite(i,0x05,isMuted[i]?0:chan[i].pan);
@ -588,6 +590,7 @@ int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, const DivConfi
parent=p;
dumpWrites=false;
skipRegisterWrites=false;
updateLFO=false;
for (int i=0; i<6; i++) {
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;

View file

@ -76,6 +76,7 @@ class DivPlatformPCE: public DivDispatch {
DivDispatchOscBuffer* oscBuf[6];
bool isMuted[6];
bool antiClickEnabled;
bool updateLFO;
struct QueuedWrite {
unsigned char addr;
unsigned char val;

View file

@ -644,13 +644,25 @@ size_t DivPlatformQSound::getSampleMemUsage(int index) {
return index == 0 ? sampleMemLen : 0;
}
bool DivPlatformQSound::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
// TODO: ADPCM... come on...
void DivPlatformQSound::renderSamples() {
void DivPlatformQSound::renderSamples(int sysID) {
memset(sampleMem,0,getSampleMemCapacity());
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
offPCM[i]=0;
continue;
}
int length=s->length8;
if (length>65536-16) {
length=65536-16;
@ -671,6 +683,7 @@ void DivPlatformQSound::renderSamples() {
for (int i=0; i<length; i++) {
sampleMem[(memPos+i)^0x8000]=s->data8[i];
}
sampleLoaded[i]=true;
}
offPCM[i]=memPos^0x8000;
memPos+=length+16;

View file

@ -69,6 +69,7 @@ class DivPlatformQSound: public DivDispatch {
unsigned char* sampleMem;
size_t sampleMemLen;
bool sampleLoaded[256];
struct qsound_chip chip;
unsigned short regPool[512];
@ -103,7 +104,8 @@ class DivPlatformQSound: public DivDispatch {
const void* getSampleMem(int index = 0);
size_t getSampleMemCapacity(int index = 0);
size_t getSampleMemUsage(int index = 0);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
};

View file

@ -385,13 +385,25 @@ size_t DivPlatformRF5C68::getSampleMemUsage(int index) {
return index == 0 ? sampleMemLen : 0;
}
void DivPlatformRF5C68::renderSamples() {
bool DivPlatformRF5C68::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformRF5C68::renderSamples(int sysID) {
memset(sampleMem,0,getSampleMemCapacity());
memset(sampleOffRFC,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOffRFC[i]=0;
continue;
}
int length=s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT);
int actualLength=MIN((int)(getSampleMemCapacity()-memPos)-31,length);
if (actualLength>0) {
@ -412,6 +424,7 @@ void DivPlatformRF5C68::renderSamples() {
}
// align memPos to 256-byte boundary
memPos=(memPos+0xff)&~0xff;
sampleLoaded[i]=true;
}
sampleMemLen=memPos;
}

View file

@ -67,6 +67,7 @@ class DivPlatformRF5C68: public DivDispatch {
int chipType;
unsigned char curChan;
unsigned int sampleOffRFC[256];
bool sampleLoaded[256];
unsigned char* sampleMem;
size_t sampleMemLen;
@ -99,7 +100,8 @@ class DivPlatformRF5C68: public DivDispatch {
const void* getSampleMem(int index = 0);
size_t getSampleMemCapacity(int index = 0);
size_t getSampleMemUsage(int index = 0);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
private:

View file

@ -71,10 +71,17 @@ void DivPlatformSAA1099::acquire_saaSound(short* bufL, short* bufR, size_t start
writes.pop();
}
saa_saaSound->GenerateMany((unsigned char*)saaBuf[0],len,oscBuf);
#ifdef TA_BIG_ENDIAN
for (size_t i=0; i<len; i++) {
bufL[i+start]=(short)((((unsigned short)saaBuf[0][1+(i<<1)])<<8)|(((unsigned short)saaBuf[0][1+(i<<1)])>>8));
bufR[i+start]=(short)((((unsigned short)saaBuf[0][i<<1])<<8)|(((unsigned short)saaBuf[0][i<<1])>>8));
}
#else
for (size_t i=0; i<len; i++) {
bufL[i+start]=saaBuf[0][i<<1];
bufR[i+start]=saaBuf[0][1+(i<<1)];
}
#endif
}
void DivPlatformSAA1099::acquire(short* bufL, short* bufR, size_t start, size_t len) {

View file

@ -451,7 +451,7 @@ void DivPlatformSegaPCM::reset() {
}
}
void DivPlatformSegaPCM::renderSamples() {
void DivPlatformSegaPCM::renderSamples(int sysID) {
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {

View file

@ -110,7 +110,7 @@ class DivPlatformSegaPCM: public DivDispatch {
void tick(bool sysTick=true);
void muteChannel(int ch, bool mute);
void notifyInsChange(int ins);
void renderSamples();
void renderSamples(int chipID);
void setFlags(const DivConfig& flags);
bool isStereo();
void poke(unsigned int addr, unsigned short val);

View file

@ -119,10 +119,29 @@ void DivPlatformSMS::acquire(short* bufL, short* bufR, size_t start, size_t len)
}
}
double DivPlatformSMS::NOTE_SN(int ch, int note) {
double CHIP_DIVIDER=toneDivider;
if (ch==3) CHIP_DIVIDER=noiseDivider;
if (parent->song.linearPitch==2 || !easyNoise) {
return NOTE_PERIODIC(note);
}
if (note>easyThreshold) {
return MAX(0,easyStartingPeriod-(note-easyThreshold));
}
return NOTE_PERIODIC(note);
}
int DivPlatformSMS::snCalcFreq(int ch) {
if (parent->song.linearPitch==2 && easyNoise && chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2>(easyThreshold<<7)) {
int ret=(((easyStartingPeriod<<7)+0x40)-(chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2-(easyThreshold<<7)))>>7;
if (ret<0) ret=0;
return ret;
}
return parent->calcFreq(chan[ch].baseFreq,chan[ch].pitch,true,0,chan[ch].pitch2,chipClock,ch==3?noiseDivider:toneDivider);
}
void DivPlatformSMS::tick(bool sysTick) {
for (int i=0; i<4; i++) {
double CHIP_DIVIDER=toneDivider;
if (i==3) CHIP_DIVIDER=noiseDivider;
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=VOL_SCALE_LOG_BROKEN(chan[i].std.vol.val,chan[i].vol,15);
@ -137,7 +156,7 @@ void DivPlatformSMS::tick(bool sysTick) {
// TODO: add compatibility flag. this is horrible.
int areYouSerious=parent->calcArp(chan[i].note,chan[i].std.arp.val);
while (areYouSerious>0x60) areYouSerious-=12;
chan[i].baseFreq=NOTE_PERIODIC(areYouSerious);
chan[i].baseFreq=NOTE_SN(i,areYouSerious);
chan[i].actualNote=areYouSerious;
chan[i].freqChanged=true;
}
@ -177,7 +196,7 @@ void DivPlatformSMS::tick(bool sysTick) {
}
for (int i=0; i<3; i++) {
if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,toneDivider);
chan[i].freq=snCalcFreq(i);
if (chan[i].freq>1023) chan[i].freq=1023;
if (parent->song.snNoLowPeriods) {
if (chan[i].freq<8) chan[i].freq=1;
@ -196,7 +215,8 @@ void DivPlatformSMS::tick(bool sysTick) {
}
}
if (chan[3].freqChanged || updateSNMode) {
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].pitch2,chipClock,noiseDivider);
chan[3].freq=snCalcFreq(3);
//parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].pitch2,chipClock,noiseDivider);
if (chan[3].freq>1023) chan[3].freq=1023;
if (parent->song.snNoLowPeriods) {
if (chan[3].actualNote>0x5d) chan[3].freq=0x01;
@ -244,12 +264,10 @@ void DivPlatformSMS::tick(bool sysTick) {
}
int DivPlatformSMS::dispatch(DivCommand c) {
double CHIP_DIVIDER=toneDivider;
if (c.chan==3) CHIP_DIVIDER=noiseDivider;
switch (c.cmd) {
case DIV_CMD_NOTE_ON:
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].baseFreq=NOTE_SN(c.chan,c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
chan[c.chan].actualNote=c.value;
@ -300,7 +318,7 @@ int DivPlatformSMS::dispatch(DivCommand c) {
chan[c.chan].freqChanged=true;
break;
case DIV_CMD_NOTE_PORTA: {
int destFreq=NOTE_PERIODIC(c.value2);
int destFreq=NOTE_SN(c.chan,c.value2);
bool return2=false;
if (destFreq>chan[c.chan].baseFreq) {
chan[c.chan].baseFreq+=c.value;
@ -340,7 +358,7 @@ int DivPlatformSMS::dispatch(DivCommand c) {
break;
}
case DIV_CMD_LEGATO:
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
chan[c.chan].baseFreq=NOTE_SN(c.chan,c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
chan[c.chan].actualNote=c.value;
@ -349,7 +367,7 @@ int DivPlatformSMS::dispatch(DivCommand c) {
if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
}
if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note);
if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will) chan[c.chan].baseFreq=NOTE_SN(c.chan,chan[c.chan].note);
chan[c.chan].inPorta=c.value;
break;
case DIV_CMD_GET_VOLMAX:
@ -446,27 +464,42 @@ void DivPlatformSMS::setFlags(const DivConfig& flags) {
switch (flags.getInt("clockSel",0)) {
case 1:
chipClock=COLOR_PAL*4.0/5.0;
easyThreshold=84;
easyStartingPeriod=13;
break;
case 2:
chipClock=4000000;
easyThreshold=86;
easyStartingPeriod=13;
break;
case 3:
chipClock=COLOR_NTSC/2.0;
easyThreshold=72;
easyStartingPeriod=13;
break;
case 4:
chipClock=3000000;
easyThreshold=81;
easyStartingPeriod=13;
break;
case 5:
chipClock=2000000;
easyThreshold=74;
easyStartingPeriod=13;
break;
case 6:
chipClock=COLOR_NTSC/8.0;
easyThreshold=48;
easyStartingPeriod=13;
break;
default:
chipClock=COLOR_NTSC;
easyThreshold=84;
easyStartingPeriod=13;
break;
}
resetPhase=!flags.getBool("noPhaseReset",false);
easyNoise=!flags.getBool("noEasyNoise",false);
divider=16;
toneDivider=64.0;
noiseDivider=64.0;

View file

@ -65,11 +65,14 @@ class DivPlatformSMS: public DivDispatch {
int divider=16;
double toneDivider=64.0;
double noiseDivider=64.0;
int easyThreshold;
int easyStartingPeriod;
bool updateSNMode;
bool resetPhase;
bool isRealSN;
bool stereo;
bool nuked;
bool easyNoise;
sn76496_base_device* sn;
ympsg_t sn_nuked;
struct QueuedWrite {
@ -82,6 +85,9 @@ class DivPlatformSMS: public DivDispatch {
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
double NOTE_SN(int ch, int note);
int snCalcFreq(int ch);
void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len);
void acquire_mame(short* bufL, short* bufR, size_t start, size_t len);
public:

View file

@ -797,14 +797,26 @@ size_t DivPlatformSNES::getSampleMemUsage(int index) {
return index == 0 ? sampleMemLen : 0;
}
void DivPlatformSNES::renderSamples() {
bool DivPlatformSNES::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformSNES::renderSamples(int sysID) {
memset(copyOfSampleMem,0,getSampleMemCapacity());
memset(sampleOff,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
// skip past sample table and wavetable buffer
size_t memPos=sampleTableBase+8*4+8*9*16;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOff[i]=0;
continue;
}
int length=s->lengthBRR;
int actualLength=MIN((int)(getSampleMemCapacity()-memPos)/9*9,length);
if (actualLength>0) {
@ -822,6 +834,7 @@ void DivPlatformSNES::renderSamples() {
logW("out of BRR memory for sample %d!",i);
break;
}
sampleLoaded[i]=true;
}
sampleMemLen=memPos;
memcpy(sampleMem,copyOfSampleMem,65536);

View file

@ -109,6 +109,7 @@ class DivPlatformSNES: public DivDispatch {
signed char copyOfSampleMem[65536];
size_t sampleMemLen;
unsigned int sampleOff[256];
bool sampleLoaded[256];
unsigned char regPool[0x80];
SPC_DSP dsp;
friend void putDispatchChan(void*,int,int);
@ -136,7 +137,8 @@ class DivPlatformSNES: public DivDispatch {
const void* getSampleMem(int index = 0);
size_t getSampleMemCapacity(int index = 0);
size_t getSampleMemUsage(int index = 0);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
private:

View file

@ -391,7 +391,18 @@ void SoundUnit::Reset() {
memset(chan,0,sizeof(SUChannel)*8);
}
#ifdef TA_BIG_ENDIAN
const unsigned char suBERemap[32]={
0x01, 0x00, 0x02, 0x03, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e,
0x11, 0x10, 0x12, 0x13, 0x15, 0x14, 0x16, 0x17, 0x19, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f, 0x1e
};
#endif
void SoundUnit::Write(unsigned char addr, unsigned char data) {
#ifdef TA_BIG_ENDIAN
// remap
addr=(addr&0xe0)|(suBERemap[addr&0x1f]);
#endif
((unsigned char*)chan)[addr]=data;
}

View file

@ -286,6 +286,8 @@ int ymz280b_device::generate_pcm8(struct YMZ280BVoice *voice, s16 *buffer, int s
***********************************************************************************************/
// according to this core, it should be little-endian.
// but it's big-endian in VGMPlay...
int ymz280b_device::generate_pcm16(struct YMZ280BVoice *voice, s16 *buffer, int samples)
{
u32 position = voice->position;
@ -298,7 +300,7 @@ int ymz280b_device::generate_pcm16(struct YMZ280BVoice *voice, s16 *buffer, int
while (samples)
{
/* fetch the current value */
val = (s16)((m_ext_mem[position / 2 + 1] << 8) + m_ext_mem[position / 2 + 0]);
val = (s16)((m_ext_mem[position / 2 + 0] << 8) + m_ext_mem[position / 2 + 1]);
/* output to the buffer, scaling by the volume */
*buffer++ = val;
@ -321,7 +323,7 @@ int ymz280b_device::generate_pcm16(struct YMZ280BVoice *voice, s16 *buffer, int
while (samples)
{
/* fetch the current value */
val = (s16)((m_ext_mem[position / 2 + 1] << 8) + m_ext_mem[position / 2 + 0]);
val = (s16)((m_ext_mem[position / 2 + 0] << 8) + m_ext_mem[position / 2 + 1]);
/* output to the buffer, scaling by the volume */
*buffer++ = val;

View file

@ -524,7 +524,7 @@ void DivPlatformSoundUnit::setFlags(const DivConfig& flags) {
sampleMemSize=flags.getInt("sampleMemSize",0);
su->Init(sampleMemSize?65536:8192,flags.getBool("pdm",false));
renderSamples();
renderSamples(sysIDCache);
}
void DivPlatformSoundUnit::poke(unsigned int addr, unsigned short val) {
@ -547,14 +547,26 @@ size_t DivPlatformSoundUnit::getSampleMemUsage(int index) {
return (index==0)?sampleMemLen:0;
}
void DivPlatformSoundUnit::renderSamples() {
bool DivPlatformSoundUnit::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformSoundUnit::renderSamples(int sysID) {
memset(su->pcm,0,getSampleMemCapacity(0));
memset(sampleOffSU,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (s->data8==NULL) continue;
if (!s->renderOn[0][sysID]) {
sampleOffSU[i]=0;
continue;
}
int paddedLen=s->length8;
if (memPos>=getSampleMemCapacity(0)) {
logW("out of PCM memory for sample %d!",i);
@ -565,12 +577,13 @@ void DivPlatformSoundUnit::renderSamples() {
logW("out of PCM memory for sample %d!",i);
} else {
memcpy(su->pcm+memPos,s->data8,paddedLen);
sampleLoaded[i]=true;
}
sampleOffSU[i]=memPos;
memPos+=paddedLen;
}
sampleMemLen=memPos;
sysIDCache=sysID;
}
int DivPlatformSoundUnit::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
@ -582,6 +595,7 @@ int DivPlatformSoundUnit::init(DivEngine* p, int channels, int sugRate, const Di
oscBuf[i]=new DivDispatchOscBuffer;
}
su=new SoundUnit();
sysIDCache=0;
setFlags(flags);
reset();
return 8;

View file

@ -102,8 +102,9 @@ class DivPlatformSoundUnit: public DivDispatch {
unsigned char initIlCtrl, initIlSize, initFil1;
signed char echoVol, initEchoVol;
unsigned int sampleOffSU[256];
bool sampleLoaded[256];
int cycles, curChan, delay;
int cycles, curChan, delay, sysIDCache;
short tempL;
short tempR;
unsigned char sampleBank, lfoMode, lfoSpeed;
@ -138,7 +139,8 @@ class DivPlatformSoundUnit: public DivDispatch {
const void* getSampleMem(int index);
size_t getSampleMemCapacity(int index);
size_t getSampleMemUsage(int index);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
~DivPlatformSoundUnit();

View file

@ -81,10 +81,29 @@ void DivPlatformT6W28::writeOutVol(int ch) {
}
}
double DivPlatformT6W28::NOTE_SN(int ch, int note) {
double CHIP_DIVIDER=16;
if (ch==3) CHIP_DIVIDER=15;
if (parent->song.linearPitch==2 || !easyNoise) {
return NOTE_PERIODIC(note);
}
if (note>107) {
return MAX(0,13-(note-107));
}
return NOTE_PERIODIC(note);
}
int DivPlatformT6W28::snCalcFreq(int ch) {
if (parent->song.linearPitch==2 && easyNoise && chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2>(107<<7)) {
int ret=(((13<<7)+0x40)-(chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2-(107<<7)))>>7;
if (ret<0) ret=0;
return ret;
}
return parent->calcFreq(chan[ch].baseFreq,chan[ch].pitch,true,0,chan[ch].pitch2,chipClock,ch==3?15:16);
}
void DivPlatformT6W28::tick(bool sysTick) {
for (int i=0; i<4; i++) {
double CHIP_DIVIDER=16;
if (i==3) CHIP_DIVIDER=15;
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=VOL_SCALE_LOG_BROKEN(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15);
@ -92,7 +111,7 @@ void DivPlatformT6W28::tick(bool sysTick) {
if (chan[i].std.arp.had) {
if (!chan[i].inPorta) {
int noiseSeek=parent->calcArp(chan[i].note,chan[i].std.arp.val);
chan[i].baseFreq=NOTE_PERIODIC(noiseSeek);
chan[i].baseFreq=NOTE_SN(i,noiseSeek);
}
chan[i].freqChanged=true;
}
@ -124,7 +143,7 @@ void DivPlatformT6W28::tick(bool sysTick) {
rWrite(1,0xe0+chan[i].duty);
}
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
chan[i].freq=snCalcFreq(i);
if (chan[i].freq>1023) chan[i].freq=1023;
if (i==3) {
rWrite(1,0x80|(2<<5)|(chan[3].freq&15));
@ -141,13 +160,11 @@ void DivPlatformT6W28::tick(bool sysTick) {
}
int DivPlatformT6W28::dispatch(DivCommand c) {
double CHIP_DIVIDER=16;
if (c.chan==3) CHIP_DIVIDER=15;
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_PCE);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].baseFreq=NOTE_SN(c.chan,c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
@ -197,7 +214,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
chan[c.chan].freqChanged=true;
break;
case DIV_CMD_NOTE_PORTA: {
int destFreq=NOTE_PERIODIC(c.value2);
int destFreq=NOTE_SN(c.chan,c.value2);
bool return2=false;
if (destFreq>chan[c.chan].baseFreq) {
chan[c.chan].baseFreq+=c.value;
@ -231,15 +248,15 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
break;
}
case DIV_CMD_LEGATO:
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
chan[c.chan].baseFreq=NOTE_SN(c.chan,c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
break;
case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE));
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_T6W28));
}
if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note);
if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will) chan[c.chan].baseFreq=NOTE_SN(c.chan,chan[c.chan].note);
chan[c.chan].inPorta=c.value;
break;
case DIV_CMD_GET_VOLMAX:
@ -330,6 +347,7 @@ void DivPlatformT6W28::setFlags(const DivConfig& flags) {
for (int i=0; i<4; i++) {
oscBuf[i]->rate=rate;
}
easyNoise=!flags.getBool("noEasyNoise",false);
if (t6w!=NULL) {
delete t6w;

View file

@ -60,6 +60,7 @@ class DivPlatformT6W28: public DivDispatch {
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4];
bool antiClickEnabled;
bool easyNoise;
struct QueuedWrite {
unsigned char addr;
unsigned char val;
@ -75,6 +76,10 @@ class DivPlatformT6W28: public DivDispatch {
unsigned char regPool[128];
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
double NOTE_SN(int ch, int note);
int snCalcFreq(int ch);
void writeOutVol(int ch);
public:
void acquire(short* bufL, short* bufR, size_t start, size_t len);

View file

@ -949,13 +949,25 @@ size_t DivPlatformX1_010::getSampleMemUsage(int index) {
return index >= 0 ? sampleMemLen : 0;
}
void DivPlatformX1_010::renderSamples() {
bool DivPlatformX1_010::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformX1_010::renderSamples(int sysID) {
memset(sampleMem,0,getSampleMemCapacity());
memset(sampleOffX1,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOffX1[i]=0;
continue;
}
int paddedLen=(s->length8+4095)&(~0xfff);
if (isBanked) {
// fit sample bank size to 128KB for Seta 2 external bankswitching logic (not emulated yet!)
@ -975,6 +987,7 @@ void DivPlatformX1_010::renderSamples() {
logW("out of X1-010 memory for sample %d!",i);
} else {
memcpy(sampleMem+memPos,s->data8,paddedLen);
sampleLoaded[i]=true;
}
sampleOffX1[i]=memPos;
memPos+=paddedLen;

View file

@ -116,6 +116,7 @@ class DivPlatformX1_010: public DivDispatch, public vgsound_emu_mem_intf {
bool isBanked=false;
unsigned int bankSlot[8];
unsigned int sampleOffX1[256];
bool sampleLoaded[256];
unsigned char regPool[0x2000];
double NoteX1_010(int ch, int note);
@ -146,7 +147,8 @@ class DivPlatformX1_010: public DivDispatch, public vgsound_emu_mem_intf {
const void* getSampleMem(int index = 0);
size_t getSampleMemCapacity(int index = 0);
size_t getSampleMemUsage(int index = 0);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
const char** getRegisterSheet();
void setBanked(bool banked);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);

View file

@ -1336,13 +1336,25 @@ size_t DivPlatformYM2608::getSampleMemUsage(int index) {
return index == 0 ? adpcmBMemLen : 0;
}
void DivPlatformYM2608::renderSamples() {
bool DivPlatformYM2608::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformYM2608::renderSamples(int sysID) {
memset(adpcmBMem,0,getSampleMemCapacity(0));
memset(sampleOffB,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOffB[i]=0;
continue;
}
int paddedLen=(s->lengthB+255)&(~0xff);
if ((memPos&0xf00000)!=((memPos+paddedLen)&0xf00000)) {
memPos=(memPos+0xfffff)&0xf00000;
@ -1356,6 +1368,7 @@ void DivPlatformYM2608::renderSamples() {
logW("out of ADPCM memory for sample %d!",i);
} else {
memcpy(adpcmBMem+memPos,s->dataB,paddedLen);
sampleLoaded[i]=true;
}
sampleOffB[i]=memPos;
memPos+=paddedLen;

View file

@ -100,6 +100,7 @@ class DivPlatformYM2608: public DivPlatformOPN {
size_t adpcmBMemLen;
DivYM2608Interface iface;
unsigned int sampleOffB[256];
bool sampleLoaded[256];
DivPlatformAY8910* ay;
unsigned char sampleBank;
@ -137,7 +138,8 @@ class DivPlatformYM2608: public DivPlatformOPN {
const void* getSampleMem(int index);
size_t getSampleMemCapacity(int index);
size_t getSampleMemUsage(int index);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
void setFlags(const DivConfig& flags);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();

View file

@ -142,6 +142,8 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
unsigned char sampleBank;
bool extMode, noExtMacros;
bool sampleLoaded[2][256];
unsigned char writeADPCMAOff, writeADPCMAOn;
int globalADPCMAVolume;
@ -204,18 +206,34 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
return index == 0 ? 16777216 : index == 1 ? 16777216 : 0;
}
const char* getSampleMemName(int index=0) {
return index == 0 ? "ADPCM-A" : index == 1 ? "ADPCM-B" : NULL;
}
size_t getSampleMemUsage(int index) {
return index == 0 ? adpcmAMemLen : index == 1 ? adpcmBMemLen : 0;
}
void renderSamples() {
bool isSampleLoaded(int index, int sample) {
if (index<0 || index>1) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[index][sample];
}
void renderSamples(int sysID) {
memset(adpcmAMem,0,getSampleMemCapacity(0));
memset(sampleOffA,0,256*sizeof(unsigned int));
memset(sampleOffB,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*2*sizeof(bool));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOffA[i]=0;
continue;
}
int paddedLen=(s->lengthA+255)&(~0xff);
if ((memPos&0xf00000)!=((memPos+paddedLen)&0xf00000)) {
memPos=(memPos+0xfffff)&0xf00000;
@ -229,6 +247,7 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
logW("out of ADPCM-A memory for sample %d!",i);
} else {
memcpy(adpcmAMem+memPos,s->dataA,paddedLen);
sampleLoaded[0][i]=true;
}
sampleOffA[i]=memPos;
memPos+=paddedLen;
@ -240,6 +259,11 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[1][sysID]) {
sampleOffB[i]=0;
continue;
}
int paddedLen=(s->lengthB+255)&(~0xff);
if ((memPos&0xf00000)!=((memPos+paddedLen)&0xf00000)) {
memPos=(memPos+0xfffff)&0xf00000;
@ -253,6 +277,7 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
logW("out of ADPCM-B memory for sample %d!",i);
} else {
memcpy(adpcmBMem+memPos,s->dataB,paddedLen);
sampleLoaded[1][i]=true;
}
sampleOffB[i]=memPos;
memPos+=paddedLen;

View file

@ -420,18 +420,40 @@ size_t DivPlatformYMZ280B::getSampleMemUsage(int index) {
return index == 0 ? sampleMemLen : 0;
}
void DivPlatformYMZ280B::renderSamples() {
bool DivPlatformYMZ280B::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformYMZ280B::renderSamples(int sysID) {
memset(sampleMem,0,getSampleMemCapacity());
memset(sampleOff,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOff[i]=0;
continue;
}
int length=s->getCurBufLen();
unsigned char* src=(unsigned char*)s->getCurBuf();
int actualLength=MIN((int)(getSampleMemCapacity()-memPos),length);
if (actualLength>0) {
#ifdef TA_BIG_ENDIAN
memcpy(&sampleMem[memPos],src,actualLength);
#else
if (s->depth==DIV_SAMPLE_DEPTH_16BIT) {
for (int i=0; i<actualLength; i++) {
sampleMem[memPos+i]=src[i^1];
}
} else {
memcpy(&sampleMem[memPos],src,actualLength);
}
#endif
sampleOff[i]=memPos;
memPos+=length;
}
@ -439,6 +461,7 @@ void DivPlatformYMZ280B::renderSamples() {
logW("out of YMZ280B PCM memory for sample %d!",i);
break;
}
sampleLoaded[i]=true;
}
sampleMemLen=memPos;
}

View file

@ -67,6 +67,7 @@ class DivPlatformYMZ280B: public DivDispatch {
bool isMuted[8];
int chipType;
unsigned int sampleOff[256];
bool sampleLoaded[256];
unsigned char* sampleMem;
size_t sampleMemLen;
@ -99,7 +100,8 @@ class DivPlatformYMZ280B: public DivDispatch {
const void* getSampleMem(int index = 0);
size_t getSampleMemCapacity(int index = 0);
size_t getSampleMemUsage(int index = 0);
void renderSamples();
bool isSampleLoaded(int index, int sample);
void renderSamples(int chipID);
void setFlags(const DivConfig& flags);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();