Merge branch 'master' of https://github.com/tildearrow/furnace into x1_010_bank
This commit is contained in:
commit
2a881c9f66
84 changed files with 3061 additions and 381 deletions
|
|
@ -37,6 +37,10 @@ DivMacroInt* DivDispatch::getChanMacroInt(int chan) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
DivSamplePos DivDispatch::getSamplePos(int chan) {
|
||||
return DivSamplePos();
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivDispatch::getOscBuffer(int chan) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,6 +213,10 @@ void DivPlatformAmiga::rWrite(unsigned short addr, unsigned short val) {
|
|||
//logV("%.3x = %.4x",addr,val);
|
||||
regPool[addr>>1]=val;
|
||||
|
||||
if (!skipRegisterWrites && dumpWrites) {
|
||||
addWrite(addr,val);
|
||||
}
|
||||
|
||||
switch (addr&0x1fe) {
|
||||
case 0x96: { // DMACON
|
||||
if (val&32768) {
|
||||
|
|
@ -400,6 +404,29 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
|||
chan[i].keyOn=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short dmaOff=0;
|
||||
unsigned short dmaOn=0;
|
||||
for (int i=0; i<4; i++) {
|
||||
if (chan[i].keyOn || chan[i].keyOff) {
|
||||
chWrite(i,6,1);
|
||||
dmaOff|=1<<i;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmaOff) rWrite(0x96,dmaOff);
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
double off=1.0;
|
||||
if (!chan[i].useWave && chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[i].sample);
|
||||
if (s->centerRate<1) {
|
||||
off=1.0;
|
||||
} else {
|
||||
off=8363.0/(double)s->centerRate;
|
||||
}
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
|
||||
chan[i].freq=off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
|
|
@ -409,13 +436,16 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
|||
chWrite(i,6,chan[i].freq);
|
||||
|
||||
if (chan[i].keyOn) {
|
||||
rWrite(0x96,1<<i);
|
||||
if (chan[i].useWave) {
|
||||
rWrite(0x9a,(128<<i));
|
||||
chWrite(i,0,0);
|
||||
chWrite(i,2,i<<8);
|
||||
chWrite(i,4,chan[i].audLen);
|
||||
rWrite(0x96,0x8000|(1<<i));
|
||||
if (dumpWrites) {
|
||||
addWrite(0x200+i,i<<8);
|
||||
addWrite(0x204+i,chan[i].audLen);
|
||||
}
|
||||
dmaOn|=1<<i;
|
||||
} else {
|
||||
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[i].sample);
|
||||
|
|
@ -432,13 +462,21 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
|||
chWrite(i,0,0);
|
||||
chWrite(i,2,0x400);
|
||||
chWrite(i,4,1);
|
||||
if (dumpWrites) {
|
||||
addWrite(0x200+i,0x400);
|
||||
addWrite(0x204+i,1);
|
||||
}
|
||||
} else {
|
||||
chWrite(i,0,start>>16);
|
||||
chWrite(i,2,start);
|
||||
chWrite(i,4,len);
|
||||
if (dumpWrites) {
|
||||
addWrite(0x200+i,start);
|
||||
addWrite(0x204+i,len);
|
||||
}
|
||||
}
|
||||
|
||||
rWrite(0x96,0x8000|(1<<i));
|
||||
dmaOn|=1<<i;
|
||||
if (s->isLoopable()) {
|
||||
int loopPos=(sampleOff[chan[i].sample]+s->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT))&(~1);
|
||||
int loopEnd=(s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)-s->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT))>>1;
|
||||
|
|
@ -455,19 +493,28 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
|||
chWrite(i,0,0);
|
||||
chWrite(i,2,0x400);
|
||||
chWrite(i,4,1);
|
||||
if (dumpWrites) {
|
||||
addWrite(0x200+i,0x400);
|
||||
addWrite(0x204+i,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chan[i].keyOff) {
|
||||
rWrite(0x96,1<<i);
|
||||
}
|
||||
if (chan[i].keyOn) chan[i].keyOn=false;
|
||||
if (chan[i].keyOff) chan[i].keyOff=false;
|
||||
chan[i].freqChanged=false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmaOn) rWrite(0x96,0x8000|dmaOn);
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
if ((dmaOn&(1<<i)) && !chan[i].useWave && dumpWrites) {
|
||||
addWrite(0x200+i,(chan[i].irLocH<<16)|chan[i].irLocL);
|
||||
addWrite(0x204+i,chan[i].irLen);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
if (chan[i].writeVol) {
|
||||
chan[i].writeVol=false;
|
||||
|
|
@ -718,6 +765,18 @@ DivMacroInt* DivPlatformAmiga::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformAmiga::getSamplePos(int ch) {
|
||||
if (ch>=4) return DivSamplePos();
|
||||
if (chan[ch].sample<0 || chan[ch].sample>=parent->song.sampleLen) return DivSamplePos();
|
||||
int audPer=amiga.audPer[ch];
|
||||
if (audPer<1) audPer=1;
|
||||
return DivSamplePos(
|
||||
chan[ch].sample,
|
||||
amiga.dmaLoc[ch]-sampleOff[chan[ch].sample],
|
||||
chipClock/audPer
|
||||
);
|
||||
}
|
||||
|
||||
void DivPlatformAmiga::notifyInsChange(int ins) {
|
||||
for (int i=0; i<4; i++) {
|
||||
if (chan[i].ins==ins) {
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ class DivPlatformAmiga: public DivDispatch {
|
|||
|
||||
friend void putDispatchChip(void*,int);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
friend class DivExportAmigaValidation;
|
||||
|
||||
void irq(int ch);
|
||||
void rWrite(unsigned short addr, unsigned short val);
|
||||
|
|
@ -136,6 +137,7 @@ class DivPlatformAmiga: public DivDispatch {
|
|||
int getOutputCount();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
void setFlags(const DivConfig& flags);
|
||||
void notifyInsChange(int ins);
|
||||
void notifyWaveChange(int wave);
|
||||
|
|
|
|||
|
|
@ -700,6 +700,15 @@ DivMacroInt* DivPlatformAY8910::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformAY8910::getSamplePos(int ch) {
|
||||
if (ch>=3) return DivSamplePos();
|
||||
return DivSamplePos(
|
||||
chan[ch].dac.sample,
|
||||
chan[ch].dac.pos,
|
||||
chan[ch].dac.rate
|
||||
);
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformAY8910::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ class DivPlatformAY8910: public DivDispatch {
|
|||
int getOutputCount();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
bool getDCOffRequired();
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
|
|
|
|||
|
|
@ -696,6 +696,15 @@ DivMacroInt* DivPlatformAY8930::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformAY8930::getSamplePos(int ch) {
|
||||
if (ch>=3) return DivSamplePos();
|
||||
return DivSamplePos(
|
||||
chan[ch].dac.sample,
|
||||
chan[ch].dac.pos,
|
||||
chan[ch].dac.rate
|
||||
);
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformAY8930::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ class DivPlatformAY8930: public DivDispatch {
|
|||
int getOutputCount();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
|
|
|
|||
|
|
@ -336,6 +336,18 @@ DivMacroInt* DivPlatformGA20::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformGA20::getSamplePos(int ch) {
|
||||
if (ch>=4) return DivSamplePos();
|
||||
if (chan[ch].sample<0 || chan[ch].sample>=parent->song.sampleLen) return DivSamplePos();
|
||||
if (!ga20.is_playing(ch)) return DivSamplePos();
|
||||
unsigned char f=chan[ch].freq;
|
||||
return DivSamplePos(
|
||||
chan[ch].sample,
|
||||
ga20.get_position(ch)-sampleOffGA20[chan[ch].sample],
|
||||
chipClock/(4*(0x100-(int)f))
|
||||
);
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformGA20::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ class DivPlatformGA20: public DivDispatch, public iremga20_intf {
|
|||
virtual int dispatch(DivCommand c) override;
|
||||
virtual void* getChanState(int chan) override;
|
||||
virtual DivMacroInt* getChanMacroInt(int ch) override;
|
||||
virtual DivSamplePos getSamplePos(int ch) override;
|
||||
virtual DivDispatchOscBuffer* getOscBuffer(int chan) override;
|
||||
virtual unsigned char* getRegisterPool() override;
|
||||
virtual int getRegisterPoolSize() override;
|
||||
|
|
|
|||
|
|
@ -172,7 +172,14 @@ void DivPlatformGenesis::acquire_nuked(short** buf, size_t len) {
|
|||
flushFirst=false;
|
||||
}
|
||||
|
||||
OPN2_Clock(&fm,o); os[0]+=o[0]; os[1]+=o[1];
|
||||
OPN2_Clock(&fm,o);
|
||||
if (chipType==2) {
|
||||
os[0]+=CLAMP(o[0],-8192,8191);
|
||||
os[1]+=CLAMP(o[1],-8192,8191);
|
||||
} else {
|
||||
os[0]+=o[0];
|
||||
os[1]+=o[1];
|
||||
}
|
||||
//OPN2_Write(&fm,0,0);
|
||||
if (i==5) {
|
||||
if (fm.dacen) {
|
||||
|
|
@ -1202,6 +1209,17 @@ DivMacroInt* DivPlatformGenesis::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformGenesis::getSamplePos(int ch) {
|
||||
if (!chan[5].dacMode) return DivSamplePos();
|
||||
if (ch<5) return DivSamplePos();
|
||||
if (ch>5 && !softPCM) return DivSamplePos();
|
||||
return DivSamplePos(
|
||||
chan[ch].dacSample,
|
||||
chan[ch].dacPos,
|
||||
chan[ch].dacRate
|
||||
);
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformGenesis::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
|
|||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
|
|
|
|||
|
|
@ -415,6 +415,16 @@ DivMacroInt* DivPlatformLynx::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformLynx::getSamplePos(int ch) {
|
||||
if (ch>=4) return DivSamplePos();
|
||||
if (!chan[ch].pcm) return DivSamplePos();
|
||||
return DivSamplePos(
|
||||
chan[ch].sample,
|
||||
chan[ch].samplePos,
|
||||
chan[ch].sampleFreq
|
||||
);
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformLynx::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class DivPlatformLynx: public DivDispatch {
|
|||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "n163.h"
|
||||
#include "../engine.h"
|
||||
#include "../../ta-log.h"
|
||||
#include <math.h>
|
||||
|
||||
#define rRead(a,v) n163.addr_w(a); n163.data_r(v);
|
||||
|
|
@ -166,6 +167,7 @@ void DivPlatformN163::updateWave(int ch, int wave, int pos, int len) {
|
|||
|
||||
void DivPlatformN163::updateWaveCh(int ch) {
|
||||
if (ch<=chanMax) {
|
||||
logV("updateWave with pos %d and len %d",chan[ch].wavePos,chan[ch].waveLen);
|
||||
updateWave(ch,-1,chan[ch].wavePos,chan[ch].waveLen);
|
||||
if (chan[ch].active && !isMuted[ch]) {
|
||||
chan[ch].volumeChanged=true;
|
||||
|
|
@ -337,15 +339,15 @@ int DivPlatformN163::dispatch(DivCommand c) {
|
|||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_N163);
|
||||
if (chan[c.chan].insChanged) {
|
||||
chan[c.chan].wave=ins->n163.wave;
|
||||
chan[c.chan].ws.changeWave1(chan[c.chan].wave);
|
||||
chan[c.chan].wavePos=ins->n163.wavePos;
|
||||
chan[c.chan].waveLen=ins->n163.waveLen;
|
||||
chan[c.chan].waveMode=ins->n163.waveMode;
|
||||
chan[c.chan].ws.init(NULL,chan[c.chan].waveLen,15,false);
|
||||
chan[c.chan].ws.changeWave1(chan[c.chan].wave);
|
||||
chan[c.chan].waveChanged=true;
|
||||
if (chan[c.chan].waveMode&0x3 || ins->ws.enabled) {
|
||||
chan[c.chan].waveUpdated=true;
|
||||
}
|
||||
chan[c.chan].insChanged=false;
|
||||
}
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
|
|
@ -360,6 +362,7 @@ int DivPlatformN163::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].macroInit(ins);
|
||||
chan[c.chan].ws.init(ins,chan[c.chan].waveLen,15,chan[c.chan].insChanged);
|
||||
chan[c.chan].insChanged=false;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_OFF:
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ void DivPlatformNamcoWSG::acquire(short** buf, size_t len) {
|
|||
}
|
||||
|
||||
void DivPlatformNamcoWSG::updateWave(int ch) {
|
||||
if (romMode) return;
|
||||
if (devType==30) {
|
||||
for (int i=0; i<32; i++) {
|
||||
((namco_cus30_device*)namco)->namcos1_cus30_w(i+ch*32,chan[ch].ws.output[i]);
|
||||
|
|
@ -291,9 +292,9 @@ void DivPlatformNamcoWSG::tick(bool sysTick) {
|
|||
rWrite(0x1d,(chan[2].freq>>12)&15);
|
||||
rWrite(0x1e,(chan[2].freq>>16)&15);
|
||||
|
||||
rWrite(0x05,0);
|
||||
rWrite(0x0a,1);
|
||||
rWrite(0x0f,2);
|
||||
rWrite(0x05,romMode?(chan[0].wave&7):0);
|
||||
rWrite(0x0a,romMode?(chan[1].wave&7):1);
|
||||
rWrite(0x0f,romMode?(chan[2].wave&7):2);
|
||||
break;
|
||||
case 15:
|
||||
for (int i=0; i<8; i++) {
|
||||
|
|
@ -304,7 +305,7 @@ void DivPlatformNamcoWSG::tick(bool sysTick) {
|
|||
}
|
||||
rWrite((i<<3)+0x04,chan[i].freq&0xff);
|
||||
rWrite((i<<3)+0x05,(chan[i].freq>>8)&0xff);
|
||||
rWrite((i<<3)+0x06,((chan[i].freq>>16)&15)|(i<<4));
|
||||
rWrite((i<<3)+0x06,((chan[i].freq>>16)&15)|((romMode?(chan[i].wave&7):i)<<4));
|
||||
}
|
||||
break;
|
||||
case 30:
|
||||
|
|
@ -496,10 +497,11 @@ void DivPlatformNamcoWSG::reset() {
|
|||
if (dumpWrites) {
|
||||
addWrite(0xffffffff,0);
|
||||
}
|
||||
// TODO: wave memory
|
||||
namco->set_voices(chans);
|
||||
namco->set_stereo((devType==2 || devType==30));
|
||||
namco->device_start(NULL);
|
||||
|
||||
updateROMWaves();
|
||||
}
|
||||
|
||||
int DivPlatformNamcoWSG::getOutputCount() {
|
||||
|
|
@ -510,6 +512,27 @@ bool DivPlatformNamcoWSG::keyOffAffectsArp(int ch) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void DivPlatformNamcoWSG::updateROMWaves() {
|
||||
if (romMode) {
|
||||
// copy wavetables
|
||||
for (int i=0; i<8; i++) {
|
||||
int data=0;
|
||||
DivWavetable* w=parent->getWave(i);
|
||||
|
||||
for (int j=0; j<32; j++) {
|
||||
if (w->max<1 || w->len<1) {
|
||||
data=0;
|
||||
} else {
|
||||
data=w->data[j*w->len/32]*15/w->max;
|
||||
if (data<0) data=0;
|
||||
if (data>15) data=15;
|
||||
}
|
||||
namco->update_namco_waveform(i*32+j,data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformNamcoWSG::notifyWaveChange(int wave) {
|
||||
for (int i=0; i<chans; i++) {
|
||||
if (chan[i].wave==wave) {
|
||||
|
|
@ -517,6 +540,7 @@ void DivPlatformNamcoWSG::notifyWaveChange(int wave) {
|
|||
updateWave(i);
|
||||
}
|
||||
}
|
||||
updateROMWaves();
|
||||
}
|
||||
|
||||
void DivPlatformNamcoWSG::notifyInsDeletion(void* ins) {
|
||||
|
|
@ -552,6 +576,8 @@ void DivPlatformNamcoWSG::setFlags(const DivConfig& flags) {
|
|||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
newNoise=flags.getBool("newNoise",true);
|
||||
romMode=flags.getBool("romMode",true);
|
||||
if (devType==30) romMode=false;
|
||||
}
|
||||
|
||||
void DivPlatformNamcoWSG::poke(unsigned int addr, unsigned short val) {
|
||||
|
|
|
|||
|
|
@ -50,8 +50,10 @@ class DivPlatformNamcoWSG: public DivDispatch {
|
|||
namco_audio_device* namco;
|
||||
int devType, chans;
|
||||
bool newNoise;
|
||||
bool romMode;
|
||||
unsigned char regPool[512];
|
||||
void updateWave(int ch);
|
||||
void updateROMWaves();
|
||||
friend void putDispatchChip(void*,int);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -505,6 +505,16 @@ DivMacroInt* DivPlatformPCE::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformPCE::getSamplePos(int ch) {
|
||||
if (ch>=6) return DivSamplePos();
|
||||
if (!chan[ch].pcm) return DivSamplePos();
|
||||
return DivSamplePos(
|
||||
chan[ch].dacSample,
|
||||
chan[ch].dacPos,
|
||||
chan[ch].dacRate
|
||||
);
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformPCE::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ class DivPlatformPCE: public DivDispatch {
|
|||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ void DivPlatformPCMDAC::acquire(short** buf, size_t len) {
|
|||
const int depthScale=(15-outDepth);
|
||||
int output=0;
|
||||
for (size_t h=0; h<len; h++) {
|
||||
if (!chan[0].active || isMuted) {
|
||||
if (!chan[0].active) {
|
||||
buf[0][h]=0;
|
||||
buf[1][h]=0;
|
||||
oscBuf->data[oscBuf->needle++]=0;
|
||||
|
|
@ -171,7 +171,11 @@ void DivPlatformPCMDAC::acquire(short** buf, size_t len) {
|
|||
}
|
||||
}
|
||||
}
|
||||
output=output*chan[0].vol*chan[0].envVol/16384;
|
||||
if (isMuted) {
|
||||
output=0;
|
||||
} else {
|
||||
output=output*chan[0].vol*chan[0].envVol/16384;
|
||||
}
|
||||
oscBuf->data[oscBuf->needle++]=output;
|
||||
if (outStereo) {
|
||||
buf[0][h]=((output*chan[0].panL)>>(depthScale+8))<<depthScale;
|
||||
|
|
@ -437,6 +441,15 @@ DivMacroInt* DivPlatformPCMDAC::getChanMacroInt(int ch) {
|
|||
return &chan[0].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformPCMDAC::getSamplePos(int ch) {
|
||||
if (ch>=1) return DivSamplePos();
|
||||
return DivSamplePos(
|
||||
chan[ch].sample,
|
||||
chan[ch].audPos,
|
||||
chan[ch].freq
|
||||
);
|
||||
}
|
||||
|
||||
void DivPlatformPCMDAC::notifyInsChange(int ins) {
|
||||
if (chan[0].ins==ins) {
|
||||
chan[0].insChanged=true;
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ class DivPlatformPCMDAC: public DivDispatch {
|
|||
void muteChannel(int ch, bool mute);
|
||||
int getOutputCount();
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
void setFlags(const DivConfig& flags);
|
||||
void notifyInsChange(int ins);
|
||||
void notifyWaveChange(int wave);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ void DivPlatformPV1000::acquire(short** buf, size_t len) {
|
|||
for (size_t h=0; h<len; h++) {
|
||||
short samp;
|
||||
samp=d65010g031_sound_tick(&d65010g031,1);
|
||||
buf[0][h]=samp<<12;
|
||||
buf[0][h]=samp;
|
||||
for (int i=0; i<3; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(d65010g031.square[i].out<<12);
|
||||
}
|
||||
|
|
@ -263,6 +263,10 @@ void DivPlatformPV1000::poke(std::vector<DivRegWrite>& wlist) {
|
|||
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
bool DivPlatformPV1000::getDCOffRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
int DivPlatformPV1000::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||
parent=p;
|
||||
dumpWrites=false;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#define _PV1000_H
|
||||
|
||||
#include "../dispatch.h"
|
||||
#include "sound/d65010g031.h"
|
||||
#include "sound/d65modified.h"
|
||||
#include <queue>
|
||||
|
||||
class DivPlatformPV1000: public DivDispatch {
|
||||
|
|
@ -55,6 +55,7 @@ class DivPlatformPV1000: public DivDispatch {
|
|||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
const char** getRegisterSheet();
|
||||
bool getDCOffRequired();
|
||||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void quit();
|
||||
~DivPlatformPV1000();
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ void DivPlatformRF5C68::forceIns() {
|
|||
chan[i].insChanged=true;
|
||||
chan[i].freqChanged=true;
|
||||
chan[i].sample=-1;
|
||||
chWrite(i,1,isMuted[i]?0:chan[i].panning);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -382,6 +382,17 @@ DivMacroInt* DivPlatformSegaPCM::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformSegaPCM::getSamplePos(int ch) {
|
||||
if (ch>=16) return DivSamplePos();
|
||||
if (chan[ch].pcm.sample<0 || chan[ch].pcm.sample>=parent->song.sampleLen) return DivSamplePos();
|
||||
if (!pcm.is_playing(ch)) return DivSamplePos();
|
||||
return DivSamplePos(
|
||||
chan[ch].pcm.sample,
|
||||
pcm.get_addr(ch)-sampleOffSegaPCM[chan[ch].pcm.sample],
|
||||
122*(chan[ch].pcm.freq+1)
|
||||
);
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformSegaPCM::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ class DivPlatformSegaPCM: public DivDispatch {
|
|||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
|
|
|
|||
|
|
@ -681,6 +681,20 @@ DivMacroInt* DivPlatformSNES::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformSNES::getSamplePos(int ch) {
|
||||
if (ch>=8) return DivSamplePos();
|
||||
if (!chan[ch].active) return DivSamplePos();
|
||||
if (chan[ch].sample<0 || chan[ch].sample>=parent->song.sampleLen) return DivSamplePos();
|
||||
const SPC_DSP::voice_t* v=dsp.get_voice(ch);
|
||||
// TODO: fix?
|
||||
if (sampleMem[v->brr_addr&0xffff]==0) return DivSamplePos();
|
||||
return DivSamplePos(
|
||||
chan[ch].sample,
|
||||
((v->brr_addr-sampleOff[chan[ch].sample])*16/9)+v->brr_offset,
|
||||
(chan[ch].freq*125)/16
|
||||
);
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformSNES::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ class DivPlatformSNES: public DivDispatch {
|
|||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
|
|
|
|||
|
|
@ -34,9 +34,31 @@ freely, subject to the following restrictions:
|
|||
TODO:
|
||||
- needs hardware test
|
||||
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
ALTERED VERSION!!!
|
||||
|
||||
|
||||
THIS IS **NOT** NOT NOT NOT!!!! THE ORIGINAL SOFTWARE
|
||||
IT ISN'T
|
||||
THE MODIFICATIONS THAT WERE MADE ARE:
|
||||
|
||||
1. FIX VOLUMES - APPARENTLY THE SQUARES HAVE DIFFERENT VOLUMES (thanks forple)
|
||||
|
||||
*/
|
||||
|
||||
#include "d65010g031.h"
|
||||
#include "d65modified.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static int d65010g031_max(int a, int b) { return (a > b) ? a : b; }
|
||||
|
|
@ -57,12 +79,20 @@ int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// this is the bit I altered
|
||||
// THIS IS **NOT** THE ORIGINAL SOFTWARE! I am plainly marking it as such!
|
||||
const int d65Volumes[3]={
|
||||
3840,
|
||||
5120,
|
||||
8192
|
||||
};
|
||||
|
||||
int d65010g031_sound_tick(struct d65010g031_t *d65010g031, const int cycle)
|
||||
{
|
||||
int out = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
out += d65010g031_square_tick(&d65010g031->square[i], cycle);
|
||||
out += d65010g031_square_tick(&d65010g031->square[i], cycle)?d65Volumes[i]:-d65Volumes[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
@ -39,12 +39,19 @@ public:
|
|||
u8 read(u32 offset);
|
||||
|
||||
inline void set_mute(const int ch, const bool mute) { m_channel[ch & 3].mute = mute; }
|
||||
inline unsigned int get_position(const int ch) {
|
||||
return m_channel[ch&3].pos;
|
||||
}
|
||||
inline bool is_playing(const int ch) {
|
||||
return m_channel[ch&3].play;
|
||||
}
|
||||
|
||||
// device-level overrides
|
||||
void device_reset();
|
||||
|
||||
// sound stream update overrides
|
||||
void sound_stream_update(short** outputs, int len);
|
||||
|
||||
|
||||
private:
|
||||
struct channel_def
|
||||
|
|
|
|||
|
|
@ -134,6 +134,18 @@ uint8_t* segapcm_device::get_ram() {
|
|||
return m_ram;
|
||||
}
|
||||
|
||||
unsigned int segapcm_device::get_addr(int ch) {
|
||||
uint8_t *regs = &m_ram[8*ch];
|
||||
int offset = (regs[0x86] & m_bankmask) << m_bankshift;
|
||||
uint32_t addr = (regs[0x85] << 8) | (regs[0x84]) | offset;
|
||||
return addr;
|
||||
}
|
||||
|
||||
bool segapcm_device::is_playing(int ch) {
|
||||
uint8_t *regs = &m_ram[8*ch];
|
||||
return !(regs[0x86]&1);
|
||||
}
|
||||
|
||||
void segapcm_device::mute(int ch, bool doMute) {
|
||||
m_muted[ch&15]=doMute;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ public:
|
|||
void write(unsigned int offset, uint8_t data);
|
||||
uint8_t read(unsigned int offset);
|
||||
uint8_t* get_ram();
|
||||
unsigned int get_addr(int ch);
|
||||
bool is_playing(int ch);
|
||||
void mute(int ch, bool doMute);
|
||||
|
||||
// device-level overrides
|
||||
|
|
|
|||
|
|
@ -123,6 +123,9 @@ public:
|
|||
uint8_t t_envx_out;
|
||||
sample_t out[2]; // Furnace addition, for per-channel oscilloscope
|
||||
};
|
||||
|
||||
// Furnace addition, gets a voice
|
||||
const voice_t* get_voice(int n);
|
||||
private:
|
||||
enum { brr_block_size = 9 };
|
||||
|
||||
|
|
@ -298,6 +301,10 @@ inline void SPC_DSP::get_voice_outputs( sample_t* outs )
|
|||
}
|
||||
}
|
||||
|
||||
inline const SPC_DSP::voice_t* SPC_DSP::get_voice(int n) {
|
||||
return &m.voices[n];
|
||||
}
|
||||
|
||||
#if !SPC_NO_COPY_STATE_FUNCS
|
||||
|
||||
class SPC_State_Copier {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "vic20.h"
|
||||
#include "../engine.h"
|
||||
#include "../../ta-log.h"
|
||||
#include <math.h>
|
||||
|
||||
#define rWrite(a,v) {regPool[(a)]=(v)&0xff; vic_sound_machine_store(vic,a,(v)&0xff);}
|
||||
|
|
@ -79,9 +80,7 @@ void DivPlatformVIC20::calcAndWriteOutVol(int ch, int env) {
|
|||
}
|
||||
|
||||
void DivPlatformVIC20::writeOutVol(int ch) {
|
||||
if (!isMuted[ch] && chan[ch].active) {
|
||||
rWrite(14,chan[ch].outVol);
|
||||
}
|
||||
rWrite(14,chan[ch].outVol);
|
||||
}
|
||||
|
||||
void DivPlatformVIC20::tick(bool sysTick) {
|
||||
|
|
@ -99,6 +98,20 @@ void DivPlatformVIC20::tick(bool sysTick) {
|
|||
}
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.duty.had) {
|
||||
if (chan[i].onOff!=(bool)chan[i].std.duty.val) {
|
||||
chan[i].onOff=(bool)chan[i].std.duty.val;
|
||||
if (chan[i].active) {
|
||||
if (chan[i].onOff) {
|
||||
chan[i].keyOn=true;
|
||||
chan[i].keyOff=false;
|
||||
} else {
|
||||
chan[i].keyOn=false;
|
||||
chan[i].keyOff=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].std.wave.had) {
|
||||
if (chan[i].wave!=chan[i].std.wave.val) {
|
||||
chan[i].wave=chan[i].std.wave.val&0x0f;
|
||||
|
|
@ -156,6 +169,7 @@ int DivPlatformVIC20::dispatch(DivCommand c) {
|
|||
chan[c.chan].freqChanged=true;
|
||||
chan[c.chan].note=c.value;
|
||||
}
|
||||
chan[c.chan].onOff=true;
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].macroInit(ins);
|
||||
|
|
|
|||
|
|
@ -27,10 +27,12 @@
|
|||
class DivPlatformVIC20: public DivDispatch {
|
||||
struct Channel: public SharedChannel<int> {
|
||||
int wave, waveWriteCycle;
|
||||
bool onOff;
|
||||
Channel():
|
||||
SharedChannel<int>(15),
|
||||
wave(0),
|
||||
waveWriteCycle(-1) {}
|
||||
waveWriteCycle(-1),
|
||||
onOff(true) {}
|
||||
};
|
||||
Channel chan[4];
|
||||
DivDispatchOscBuffer* oscBuf[4];
|
||||
|
|
|
|||
|
|
@ -448,6 +448,16 @@ DivMacroInt* DivPlatformVRC6::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformVRC6::getSamplePos(int ch) {
|
||||
if (ch>=2) return DivSamplePos();
|
||||
if (!chan[ch].pcm) return DivSamplePos();
|
||||
return DivSamplePos(
|
||||
chan[ch].dacSample,
|
||||
chan[ch].dacPos,
|
||||
chan[ch].dacRate
|
||||
);
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformVRC6::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ class DivPlatformVRC6: public DivDispatch, public vrcvi_intf {
|
|||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue