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

This commit is contained in:
cam900 2023-07-18 20:17:28 +09:00
commit 1873a2a708
272 changed files with 6234 additions and 1974 deletions

View file

@ -21,7 +21,6 @@
#define _AMIGA_H
#include "../dispatch.h"
#include <queue>
#include "../waveSynth.h"
class DivPlatformAmiga: public DivDispatch {

View file

@ -878,7 +878,7 @@ void DivPlatformArcade::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformArcade::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,256);
if (useYMFM) {
fm_ymfm->reset();

View file

@ -20,7 +20,6 @@
#ifndef _ARCADE_H
#define _ARCADE_H
#include "fmshared_OPM.h"
#include <queue>
#include "../../../extern/opm/opm.h"
#include "sound/ymfm/ymfm_opm.h"

View file

@ -25,7 +25,7 @@
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(regRemap(a),v); if (dumpWrites) {addWrite(regRemap(a),v);} }
#define immWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(regRemap(a),v)); if (dumpWrites) {addWrite(regRemap(a),v);} }
#define CHIP_DIVIDER (extMode?extDiv:((sunsoft||clockSel)?16:8))

View file

@ -20,7 +20,7 @@
#ifndef _AY_H
#define _AY_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/ay8910.h"
class DivPlatformAY8910: public DivDispatch {
@ -89,9 +89,10 @@ class DivPlatformAY8910: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
ay8910_device* ay;
DivDispatchOscBuffer* oscBuf[3];
unsigned char regPool[16];

View file

@ -25,7 +25,7 @@
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
#define immWrite2(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define immWrite2(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER (clockSel?8:4)

View file

@ -20,7 +20,7 @@
#ifndef _AY8930_H
#define _AY8930_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/ay8910.h"
class DivPlatformAY8930: public DivDispatch {
@ -99,9 +99,10 @@ class DivPlatformAY8930: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
ay8930_device* ay;
DivDispatchOscBuffer* oscBuf[3];
unsigned char regPool[32];

View file

@ -21,7 +21,6 @@
#define _K005289_H
#include "../dispatch.h"
#include <queue>
#include "../waveSynth.h"
#include "vgsound_emu/src/k005289/k005289.hpp"

View file

@ -21,8 +21,9 @@
#include "../engine.h"
#include "sound/c64_fp/siddefs-fp.h"
#include <math.h>
#include "../../ta-log.h"
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_FREQBASE 524288
@ -63,35 +64,81 @@ const char** DivPlatformC64::getRegisterSheet() {
return regCheatSheetSID;
}
short DivPlatformC64::runFakeFilter(unsigned char ch, int in) {
if (!(regPool[0x17]&(1<<ch))) {
if (regPool[0x18]&0x80 && ch==2) return 0;
float fin=in;
fin*=(float)(regPool[0x18]&15)/20.0f;
return CLAMP(fin,-32768,32767);
}
// taken from dSID
float fin=in;
float fout=0;
float ctf=fakeCutTable[((regPool[0x15]&7)|(regPool[0x16]<<3))&0x7ff];
float reso=(sidIs6581?
((regPool[0x17]>0x5F)?8.0/(float)(regPool[0x17]>>4):1.41):
(pow(2,((float)(4-(float)(regPool[0x17]>>4))/8)))
);
float tmp=fin+fakeBand[ch]*reso+fakeLow[ch];
if (regPool[0x18]&0x40) {
fout-=tmp;
}
tmp=fakeBand[ch]-tmp*ctf;
fakeBand[ch]=tmp;
if (regPool[0x18]&0x20) {
fout-=tmp;
}
tmp=fakeLow[ch]+tmp*ctf;
fakeLow[ch]=tmp;
if (regPool[0x18]&0x10) {
fout+=tmp;
}
fout*=(float)(regPool[0x18]&15)/20.0f;
return CLAMP(fout,-32768,32767);
}
void DivPlatformC64::acquire(short** buf, size_t len) {
int dcOff=isFP?0:sid.get_dc(0);
int dcOff=(sidCore)?0:sid->get_dc(0);
for (size_t i=0; i<len; i++) {
if (!writes.empty()) {
QueuedWrite w=writes.front();
if (isFP) {
sid_fp.write(w.addr,w.val);
if (sidCore==2) {
dSID_write(sid_d,w.addr,w.val);
} else if (sidCore==1) {
sid_fp->write(w.addr,w.val);
} else {
sid.write(w.addr,w.val);
};
sid->write(w.addr,w.val);
}
regPool[w.addr&0x1f]=w.val;
writes.pop();
}
if (isFP) {
sid_fp.clock(4,&buf[0][i]);
if (sidCore==2) {
double o=dSID_render(sid_d);
buf[0][i]=32767*CLAMP(o,-1.0,1.0);
if (++writeOscBuf>=4) {
writeOscBuf=0;
oscBuf[0]->data[oscBuf[0]->needle++]=(sid_fp.lastChanOut[0]-dcOff)>>5;
oscBuf[1]->data[oscBuf[1]->needle++]=(sid_fp.lastChanOut[1]-dcOff)>>5;
oscBuf[2]->data[oscBuf[2]->needle++]=(sid_fp.lastChanOut[2]-dcOff)>>5;
oscBuf[0]->data[oscBuf[0]->needle++]=sid_d->lastOut[0];
oscBuf[1]->data[oscBuf[1]->needle++]=sid_d->lastOut[1];
oscBuf[2]->data[oscBuf[2]->needle++]=sid_d->lastOut[2];
}
} else if (sidCore==1) {
sid_fp->clock(4,&buf[0][i]);
if (++writeOscBuf>=4) {
writeOscBuf=0;
oscBuf[0]->data[oscBuf[0]->needle++]=runFakeFilter(0,(sid_fp->lastChanOut[0]-dcOff)>>5);
oscBuf[1]->data[oscBuf[1]->needle++]=runFakeFilter(1,(sid_fp->lastChanOut[1]-dcOff)>>5);
oscBuf[2]->data[oscBuf[2]->needle++]=runFakeFilter(2,(sid_fp->lastChanOut[2]-dcOff)>>5);
}
} else {
sid.clock();
buf[0][i]=sid.output();
sid->clock();
buf[0][i]=sid->output();
if (++writeOscBuf>=16) {
writeOscBuf=0;
oscBuf[0]->data[oscBuf[0]->needle++]=(sid.last_chan_out[0]-dcOff)>>5;
oscBuf[1]->data[oscBuf[1]->needle++]=(sid.last_chan_out[1]-dcOff)>>5;
oscBuf[2]->data[oscBuf[2]->needle++]=(sid.last_chan_out[2]-dcOff)>>5;
oscBuf[0]->data[oscBuf[0]->needle++]=runFakeFilter(0,(sid->last_chan_out[0]-dcOff)>>5);
oscBuf[1]->data[oscBuf[1]->needle++]=runFakeFilter(1,(sid->last_chan_out[1]-dcOff)>>5);
oscBuf[2]->data[oscBuf[2]->needle++]=runFakeFilter(2,(sid->last_chan_out[2]-dcOff)>>5);
}
}
}
@ -106,7 +153,9 @@ void DivPlatformC64::updateFilter() {
void DivPlatformC64::tick(bool sysTick) {
bool willUpdateFilter=false;
for (int i=0; i<3; i++) {
for (int _i=0; _i<3; _i++) {
int i=chanOrder[_i];
chan[i].std.next();
if (chan[i].std.vol.had) {
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_C64);
@ -179,8 +228,8 @@ void DivPlatformC64::tick(bool sysTick) {
if (--chan[i].testWhen<1) {
if (!chan[i].resetMask && !chan[i].inPorta) {
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_C64);
rWrite(i*7+5,0);
rWrite(i*7+6,0);
rWrite(i*7+5,testAD);
rWrite(i*7+6,testSR);
rWrite(i*7+4,(chan[i].wave<<4)|(ins->c64.noTest?0:8)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1));
}
}
@ -212,6 +261,7 @@ void DivPlatformC64::tick(bool sysTick) {
}
int DivPlatformC64::dispatch(DivCommand c) {
if (c.chan>2) return 0;
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
@ -249,6 +299,16 @@ int DivPlatformC64::dispatch(DivCommand c) {
if (chan[c.chan].insChanged) {
chan[c.chan].insChanged=false;
}
if (keyPriority) {
if (chanOrder[1]==c.chan) {
chanOrder[1]=chanOrder[2];
chanOrder[2]=c.chan;
} else if (chanOrder[0]==c.chan) {
chanOrder[0]=chanOrder[1];
chanOrder[1]=chanOrder[2];
chanOrder[2]=c.chan;
}
}
chan[c.chan].macroInit(ins);
break;
}
@ -352,7 +412,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
break;
case DIV_CMD_C64_CUTOFF:
if (c.value>100) c.value=100;
filtCut=c.value*2047/100;
filtCut=(c.value+2)*2047/102;
updateFilter();
break;
case DIV_CMD_C64_FINE_CUTOFF:
@ -438,10 +498,17 @@ int DivPlatformC64::dispatch(DivCommand c) {
void DivPlatformC64::muteChannel(int ch, bool mute) {
isMuted[ch]=mute;
if (isFP) {
sid_fp.mute(ch,mute);
if (sidCore==2) {
dSID_setMuteMask(
sid_d,
(isMuted[0]?0:1)|
(isMuted[1]?0:2)|
(isMuted[2]?0:4)
);
} else if (sidCore==1) {
sid_fp->mute(ch,mute);
} else {
sid.set_is_muted(ch,mute);
sid->set_is_muted(ch,mute);
}
}
@ -500,7 +567,7 @@ bool DivPlatformC64::getWantPreNote() {
}
float DivPlatformC64::getPostAmp() {
return isFP?3.0f:1.0f;
return (sidCore==1)?3.0f:1.0f;
}
void DivPlatformC64::reset() {
@ -508,12 +575,24 @@ void DivPlatformC64::reset() {
for (int i=0; i<3; i++) {
chan[i]=DivPlatformC64::Channel();
chan[i].std.setEngine(parent);
fakeLow[i]=0;
fakeBand[i]=0;
}
if (isFP) {
sid_fp.reset();
if (sidCore==2) {
dSID_init(sid_d,chipClock,rate,sidIs6581?6581:8580,needInitTables);
dSID_setMuteMask(
sid_d,
(isMuted[0]?0:1)|
(isMuted[1]?0:2)|
(isMuted[2]?0:4)
);
needInitTables=false;
} else if (sidCore==1) {
sid_fp->reset();
sid_fp->clockSilent(16000);
} else {
sid.reset();
sid->reset();
}
memset(regPool,0,32);
@ -524,6 +603,10 @@ void DivPlatformC64::reset() {
filtCut=2047;
resetTime=1;
vol=15;
chanOrder[0]=0;
chanOrder[1]=1;
chanOrder[2]=2;
}
void DivPlatformC64::poke(unsigned int addr, unsigned short val) {
@ -535,23 +618,11 @@ void DivPlatformC64::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformC64::setChipModel(bool is6581) {
if (is6581) {
if (isFP) {
sid_fp.setChipModel(reSIDfp::MOS6581);
} else {
sid.set_chip_model(MOS6581);
}
} else {
if (isFP) {
sid_fp.setChipModel(reSIDfp::MOS8580);
} else {
sid.set_chip_model(MOS8580);
}
}
sidIs6581=is6581;
}
void DivPlatformC64::setFP(bool fp) {
isFP=fp;
void DivPlatformC64::setCore(unsigned char which) {
sidCore=which;
}
void DivPlatformC64::setFlags(const DivConfig& flags) {
@ -572,9 +643,30 @@ void DivPlatformC64::setFlags(const DivConfig& flags) {
for (int i=0; i<3; i++) {
oscBuf[i]->rate=rate/16;
}
if (isFP) {
if (sidCore>0) {
rate/=4;
sid_fp.setSamplingParameters(chipClock,reSIDfp::DECIMATE,rate,0);
if (sidCore==1) sid_fp->setSamplingParameters(chipClock,reSIDfp::DECIMATE,rate,0);
}
keyPriority=flags.getBool("keyPriority",true);
testAD=((flags.getInt("testAttack",0)&15)<<4)|(flags.getInt("testDecay",0)&15);
testSR=((flags.getInt("testSustain",0)&15)<<4)|(flags.getInt("testRelease",0)&15);
// init fake filter table
// taken from dSID
double cutRatio=-2.0*3.14*(sidIs6581?(((double)oscBuf[0]->rate/44100.0)*(20000.0/256.0)):(12500.0/256.0))/(double)oscBuf[0]->rate;
for (int i=0; i<2048; i++) {
double c=(double)i/8.0+0.2;
if (sidIs6581) {
if (c<24) {
c=2.0*sin(771.78/(double)oscBuf[0]->rate);
} else {
c=(44100.0/(double)oscBuf[0]->rate)-1.263*(44100.0/(double)oscBuf[0]->rate)*exp(c*cutRatio);
}
} else {
c=1-exp(c*cutRatio);
}
fakeCutTable[i]=c;
}
}
@ -582,11 +674,45 @@ int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, const DivConfi
parent=p;
dumpWrites=false;
skipRegisterWrites=false;
needInitTables=true;
writeOscBuf=0;
for (int i=0; i<3; i++) {
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
}
if (sidCore==2) {
sid=NULL;
sid_fp=NULL;
sid_d=new struct SID_chip;
} else if (sidCore==1) {
sid=NULL;
sid_fp=new reSIDfp::SID;
sid_d=NULL;
} else {
sid=new SID;
sid_fp=NULL;
sid_d=NULL;
}
if (sidIs6581) {
if (sidCore==2) {
// do nothing
} else if (sidCore==1) {
sid_fp->setChipModel(reSIDfp::MOS6581);
} else {
sid->set_chip_model(MOS6581);
}
} else {
if (sidCore==2) {
// do nothing
} else if (sidCore==1) {
sid_fp->setChipModel(reSIDfp::MOS8580);
} else {
sid->set_chip_model(MOS8580);
}
}
setFlags(flags);
reset();
@ -598,6 +724,9 @@ void DivPlatformC64::quit() {
for (int i=0; i<3; i++) {
delete oscBuf[i];
}
if (sid!=NULL) delete sid;
if (sid_fp!=NULL) delete sid_fp;
if (sid_d!=NULL) delete sid_d;
}
DivPlatformC64::~DivPlatformC64() {

View file

@ -21,9 +21,10 @@
#define _C64_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/c64/sid.h"
#include "sound/c64_fp/SID.h"
#include "sound/c64_d/dsid.h"
class DivPlatformC64: public DivDispatch {
struct Channel: public SharedChannel<signed char> {
@ -55,25 +56,36 @@ class DivPlatformC64: public DivDispatch {
Channel chan[3];
DivDispatchOscBuffer* oscBuf[3];
bool isMuted[3];
float fakeLow[3];
float fakeBand[3];
float fakeCutTable[2048];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
unsigned char filtControl, filtRes, vol;
unsigned char writeOscBuf;
unsigned char sidCore;
int filtCut, resetTime;
bool isFP;
SID sid;
reSIDfp::SID sid_fp;
bool keyPriority, sidIs6581, needInitTables;
unsigned char chanOrder[3];
unsigned char testAD, testSR;
SID* sid;
reSIDfp::SID* sid_fp;
struct SID_chip* sid_d;
unsigned char regPool[32];
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
inline short runFakeFilter(unsigned char ch, int in);
void acquire_classic(short* bufL, short* bufR, size_t start, size_t len);
void acquire_fp(short* bufL, short* bufR, size_t start, size_t len);
@ -101,7 +113,7 @@ class DivPlatformC64: public DivDispatch {
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void setChipModel(bool is6581);
void setFP(bool fp);
void setCore(unsigned char which);
void quit();
~DivPlatformC64();
};

View file

@ -26,9 +26,8 @@
#define PITCH_OFFSET ((double)(16*2048*(chanMax+1)))
#define NOTE_ES5506(c,note) (parent->calcBaseFreq(chipClock,chan[c].pcm.freqOffs,note,false))
#define rWrite(a,...) {if(!skipRegisterWrites) {hostIntf32.emplace(4,(a),__VA_ARGS__); }}
//#define rRead(a,st,...) {hostIntf32.emplace(st,4,(a),__VA_ARGS__);}
#define immWrite(a,...) {hostIntf32.emplace(4,(a),__VA_ARGS__);}
#define rWrite(a,...) {if(!skipRegisterWrites) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__)); }}
#define immWrite(a,...) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__));}
#define pageWrite(p,a,...) \
if (!skipRegisterWrites) { \
if (curPage!=(p)) { \
@ -118,15 +117,15 @@ void DivPlatformES5506::acquire(short** buf, size_t len) {
while (!hostIntf32.empty()) {
QueuedHostIntf w=hostIntf32.front();
if (w.isRead && (w.read!=NULL)) {
hostIntf8.emplace(w.state,0,w.addr,w.read,w.mask);
hostIntf8.emplace(w.state,1,w.addr,w.read,w.mask);
hostIntf8.emplace(w.state,2,w.addr,w.read,w.mask);
hostIntf8.emplace(w.state,3,w.addr,w.read,w.mask,w.delay);
hostIntf8.push(QueuedHostIntf(w.state,0,w.addr,w.read,w.mask));
hostIntf8.push(QueuedHostIntf(w.state,1,w.addr,w.read,w.mask));
hostIntf8.push(QueuedHostIntf(w.state,2,w.addr,w.read,w.mask));
hostIntf8.push(QueuedHostIntf(w.state,3,w.addr,w.read,w.mask,w.delay));
} else {
hostIntf8.emplace(0,w.addr,w.val,w.mask);
hostIntf8.emplace(1,w.addr,w.val,w.mask);
hostIntf8.emplace(2,w.addr,w.val,w.mask);
hostIntf8.emplace(3,w.addr,w.val,w.mask,w.delay);
hostIntf8.push(QueuedHostIntf(0,w.addr,w.val,w.mask));
hostIntf8.push(QueuedHostIntf(1,w.addr,w.val,w.mask));
hostIntf8.push(QueuedHostIntf(2,w.addr,w.val,w.mask));
hostIntf8.push(QueuedHostIntf(3,w.addr,w.val,w.mask,w.delay));
}
hostIntf32.pop();
}
@ -1095,8 +1094,6 @@ DivMacroInt* DivPlatformES5506::getChanMacroInt(int ch) {
void DivPlatformES5506::reset() {
while (!hostIntf32.empty()) hostIntf32.pop();
while (!hostIntf8.empty()) hostIntf8.pop();
while (!queuedRead.empty()) queuedRead.pop();
while (!queuedReadState.empty()) queuedReadState.pop();
for (int i=0; i<32; i++) {
chan[i]=DivPlatformES5506::Channel();
chan[i].std.setEngine(parent);

View file

@ -22,7 +22,7 @@
#include "../dispatch.h"
#include "../engine.h"
#include <queue>
#include "../fixedQueue.h"
#include "../macroInt.h"
#include "../sample.h"
#include "vgsound_emu/src/es550x/es5506.hpp"
@ -238,6 +238,15 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
unsigned int* read;
unsigned short delay;
bool isRead;
QueuedHostIntf():
state(0),
step(0),
addr(0),
val(0),
mask(0),
read(NULL),
delay(0),
isRead(false) {}
QueuedHostIntf(unsigned char s, unsigned char a, unsigned int v, unsigned int m=(unsigned int)(~0), unsigned short d=0):
state(0),
step(s),
@ -257,17 +266,8 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
delay(d),
isRead(true) {}
};
struct QueuedReadState {
unsigned int* read;
unsigned char state;
QueuedReadState(unsigned int* r, unsigned char s):
read(r),
state(s) {}
};
std::queue<QueuedHostIntf> hostIntf32;
std::queue<QueuedHostIntf> hostIntf8;
std::queue<unsigned char> queuedRead;
std::queue<QueuedReadState> queuedReadState;
FixedQueue<QueuedHostIntf,2048> hostIntf32;
FixedQueue<QueuedHostIntf,2048> hostIntf8;
int cycle, curPage, volScale;
unsigned char maskedVal;
unsigned int irqv;

View file

@ -130,14 +130,15 @@ class DivPlatformOPN: public DivPlatformFMBase {
unsigned char freqH, freqL;
int portaPauseFreq;
signed char konCycles;
bool mask;
bool mask, hardReset;
OPNOpChannel():
SharedChannel<int>(0),
freqH(0),
freqL(0),
portaPauseFreq(0),
konCycles(0),
mask(true) {}
mask(true),
hardReset(false) {}
};
struct OPNOpChannelStereo: public OPNOpChannel {

View file

@ -22,7 +22,7 @@
#include "../dispatch.h"
#include "../instrument.h"
#include <deque>
#include "../fixedQueue.h"
#define KVS(x,y) ((chan[x].state.op[y].kvs==2 && isOutput[chan[x].state.alg][y]) || chan[x].state.op[y].kvs==1)
@ -79,9 +79,10 @@ class DivPlatformFMBase: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::deque<QueuedWrite> writes;
FixedQueue<QueuedWrite,2048> writes;
unsigned char lastBusy;
int delay;

View file

@ -22,7 +22,7 @@
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) {if(!skipRegisterWrites) {writes.emplace(a,v); if(dumpWrites) addWrite(a,v);}}
#define rWrite(a,v) {if(!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if(dumpWrites) addWrite(a,v);}}
#define CHIP_DIVIDER 64
@ -68,7 +68,7 @@ void DivPlatformGA20::acquire(short** buf, size_t len) {
ga20.write(w.addr,w.val);
regPool[w.addr]=w.val;
writes.pop();
delay=w.delay;
delay=1;
}
}
short *buffer[4]={
@ -361,9 +361,7 @@ DivDispatchOscBuffer* DivPlatformGA20::getOscBuffer(int ch) {
}
void DivPlatformGA20::reset() {
while (!writes.empty()) {
writes.pop();
}
writes.clear();
memset(regPool,0,32);
ga20.device_reset();
delay=0;

View file

@ -21,7 +21,7 @@
#define _GA20_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../macroInt.h"
#include "sound/ga20/iremga20.h"
@ -47,15 +47,14 @@ class DivPlatformGA20: public DivDispatch, public iremga20_intf {
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4];
struct QueuedWrite {
unsigned short addr;
unsigned char addr;
unsigned char val;
unsigned short delay;
QueuedWrite(unsigned short a, unsigned char v, unsigned short d=1):
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v):
addr(a),
val(v),
delay(d) {}
val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
unsigned int sampleOffGA20[256];
bool sampleLoaded[256];

View file

@ -19,10 +19,11 @@
#include "gb.h"
#include "../engine.h"
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
#define immWrite(a,v) {writes.emplace(a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
#define immWrite(a,v) {writes.push(QueuedWrite(a,v)); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 16
@ -80,6 +81,7 @@ void DivPlatformGB::acquire(short** buf, size_t len) {
}
void DivPlatformGB::updateWave() {
logV("WAVE UPDATE");
rWrite(0x1a,0);
for (int i=0; i<16; i++) {
int nibble1=ws.output[((i<<1)+antiClickWavePos)&31];
@ -299,6 +301,7 @@ void DivPlatformGB::tick(bool sysTick) {
}
if (chan[i].keyOn) {
if (i==2) { // wave
rWrite(16+i*5,0x00);
rWrite(16+i*5,0x80);
rWrite(16+i*5+2,gbVolMap[chan[i].outVol]);
} else {
@ -319,7 +322,7 @@ void DivPlatformGB::tick(bool sysTick) {
rWrite(16+i*5+4,((chan[i].keyOn||chan[i].keyOff)?0x80:0x00)|((chan[i].soundLen<64)<<6));
} else {
rWrite(16+i*5+3,(2048-chan[i].freq)&0xff);
rWrite(16+i*5+4,(((2048-chan[i].freq)>>8)&7)|((chan[i].keyOn||chan[i].keyOff)?0x80:0x00)|((chan[i].soundLen<63)<<6));
rWrite(16+i*5+4,(((2048-chan[i].freq)>>8)&7)|((chan[i].keyOn||(chan[i].keyOff && i!=2))?0x80:0x00)|((chan[i].soundLen<63)<<6));
}
if (enoughAlready) { // more compat garbage
rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(chan[i].soundLen&63)));
@ -394,6 +397,14 @@ int DivPlatformGB::dispatch(DivCommand c) {
chan[c.chan].vol=chan[c.chan].envVol;
chan[c.chan].outVol=chan[c.chan].envVol;
}
} else if (chan[c.chan].softEnv && c.chan!=2) {
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
chan[c.chan].envVol=chan[c.chan].outVol;
}
chan[c.chan].envLen=0;
chan[c.chan].envDir=1;
chan[c.chan].soundLen=64;
}
if (c.chan==2 && chan[c.chan].softEnv) {
chan[c.chan].soundLen=64;
@ -463,7 +474,9 @@ int DivPlatformGB::dispatch(DivCommand c) {
if (c.chan!=2) break;
chan[c.chan].wave=c.value;
ws.changeWave1(chan[c.chan].wave);
chan[c.chan].keyOn=true;
if (chan[c.chan].active) {
chan[c.chan].keyOn=true;
}
break;
case DIV_CMD_NOTE_PORTA: {
int destFreq=NOTE_PERIODIC(c.value2);
@ -664,22 +677,27 @@ void DivPlatformGB::setFlags(const DivConfig& flags) {
}
invertWave=flags.getBool("invertWave",true);
enoughAlready=flags.getBool("enoughAlready",false);
}
int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
chipClock=4194304;
CHECK_CUSTOM_CLOCK;
rate=chipClock/16;
for (int i=0; i<4; i++) {
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
oscBuf[i]->rate=rate;
}
}
int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
parent=p;
dumpWrites=false;
skipRegisterWrites=false;
model=GB_MODEL_DMG_B;
gb=new GB_gameboy_t;
for (int i=0; i<4; i++) {
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
}
setFlags(flags);
reset();
return 4;

View file

@ -23,7 +23,7 @@
#include "../dispatch.h"
#include "../waveSynth.h"
#include "sound/gb/gb.h"
#include <queue>
#include "../fixedQueue.h"
class DivPlatformGB: public DivDispatch {
struct Channel: public SharedChannel<signed char> {
@ -62,11 +62,12 @@ class DivPlatformGB: public DivDispatch {
unsigned char lastPan;
DivWaveSynth ws;
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
int antiClickPeriodCount, antiClickWavePos;

View file

@ -63,7 +63,7 @@ void DivPlatformGenesis::processDAC(int iRate) {
for (int i=5; i<7; i++) {
if (chan[i].dacSample!=-1) {
DivSample* s=parent->getSample(chan[i].dacSample);
if (!isMuted[i] && s->samples>0) {
if (!isMuted[i] && s->samples>0 && chan[i].dacPos<s->samples) {
if (parent->song.noOPN2Vol) {
chan[i].dacOutput=s->data8[chan[i].dacDirection?(s->samples-chan[i].dacPos-1):chan[i].dacPos];
} else {
@ -110,7 +110,7 @@ void DivPlatformGenesis::processDAC(int iRate) {
chan[5].dacPeriod+=chan[5].dacRate;
if (chan[5].dacPeriod>=iRate) {
DivSample* s=parent->getSample(chan[5].dacSample);
if (s->samples>0) {
if (s->samples>0 && chan[5].dacPos<s->samples) {
if (!isMuted[5]) {
if (chan[5].dacReady && writes.size()<16) {
int sample;
@ -122,8 +122,6 @@ void DivPlatformGenesis::processDAC(int iRate) {
urgentWrite(0x2a,(unsigned char)sample+0x80);
chan[5].dacReady=false;
}
} else {
urgentWrite(0x2a,0x80);
}
chan[5].dacPos++;
if (!chan[5].dacDirection && (s->isLoopable() && chan[5].dacPos>=(unsigned int)s->loopEnd)) {
@ -286,7 +284,7 @@ void DivPlatformGenesis::acquire(short** buf, size_t len) {
}
void DivPlatformGenesis::fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len) {
while (!writes.empty()) writes.pop_front();
writes.clear();
for (size_t i=0; i<len; i++) {
processDAC(sRate);
@ -595,6 +593,7 @@ void DivPlatformGenesis::muteChannel(int ch, bool mute) {
isMuted[ch]=mute;
if (ch>6) return;
if (ch<6) {
if (ch==5) immWrite(0x2a,0x80);
for (int j=0; j<4; j++) {
unsigned short baseAddr=chanOffs[ch]|opOffs[j];
DivInstrumentFM::Operator& op=chan[ch].state.op[j];
@ -702,7 +701,11 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
addWrite(0xffff0003,chan[c.chan].dacDirection);
}
}
chan[c.chan].dacPos=0;
if (chan[c.chan].setPos) {
chan[c.chan].setPos=false;
} else {
chan[c.chan].dacPos=0;
}
chan[c.chan].dacPeriod=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
@ -925,6 +928,12 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
if (dumpWrites) addWrite(0xffff0003,chan[c.chan].dacDirection);
break;
}
case DIV_CMD_SAMPLE_POS:
if (c.chan<5) c.chan=5;
chan[c.chan].dacPos=c.value;
chan[c.chan].setPos=true;
if (dumpWrites) addWrite(0xffff0005,chan[c.chan].dacPos);
break;
case DIV_CMD_LEGATO: {
if (c.chan==csmChan) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
@ -1273,7 +1282,7 @@ float DivPlatformGenesis::getPostAmp() {
}
void DivPlatformGenesis::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,512);
if (useYMFM) {
fm_ymfm->reset();

View file

@ -57,6 +57,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
int dacDelay;
bool dacReady;
bool dacDirection;
bool setPos;
unsigned char sampleBank;
signed char dacOutput;
Channel():
@ -70,6 +71,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
dacDelay(0),
dacReady(true),
dacDirection(false),
setPos(false),
sampleBank(0),
dacOutput(0) {}
};

View file

@ -396,6 +396,9 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
}
break;
}
case DIV_CMD_FM_HARD_RESET:
opChan[ch].hardReset=c.value;
break;
case DIV_CMD_GET_VOLMAX:
return 127;
break;
@ -449,6 +452,9 @@ static int opChanOffsH[4]={
};
void DivPlatformGenesisExt::tick(bool sysTick) {
int hardResetElapsed=0;
bool mustHardReset=false;
if (extMode) {
bool writeSomething=false;
unsigned char writeMask=2;
@ -459,6 +465,12 @@ void DivPlatformGenesisExt::tick(bool sysTick) {
writeMask&=~(1<<(4+i));
opChan[i].keyOff=false;
}
if (opChan[i].hardReset && opChan[i].keyOn) {
mustHardReset=true;
unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i];
immWrite(baseAddr+ADDR_SL_RR,0x0f);
hardResetElapsed++;
}
}
if (writeSomething) {
if (chan[csmChan].active) { // CSM
@ -627,6 +639,22 @@ void DivPlatformGenesisExt::tick(bool sysTick) {
(writeMask&0x80)?'4':'-'
);*/
immWrite(0x28,writeMask);
// hard reset handling
if (mustHardReset) {
for (unsigned int i=hardResetElapsed; i<hardResetCycles; i++) {
immWrite(0xf0,i&0xff);
}
for (int i=0; i<4; i++) {
if (opChan[i].keyOn && opChan[i].hardReset) {
// restore SL/RR
unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i];
DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i];
immWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
}
}
immWrite(0x28,writeMask);
}
}
if (extMode) {

View file

@ -22,7 +22,7 @@
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) {if(!skipRegisterWrites) {writes.emplace(a,v); if(dumpWrites) addWrite(a,v);}}
#define rWrite(a,v) {if(!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if(dumpWrites) addWrite(a,v);}}
#define CHIP_DIVIDER 64

View file

@ -21,7 +21,7 @@
#define _K007232_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../macroInt.h"
#include "vgsound_emu/src/k007232/k007232.hpp"
@ -57,12 +57,13 @@ class DivPlatformK007232: public DivDispatch, public k007232_intf {
unsigned short addr;
unsigned char val;
unsigned short delay;
QueuedWrite(): addr(0), val(0), delay(1) {}
QueuedWrite(unsigned short a, unsigned char v, unsigned short d=1):
addr(a),
val(v),
delay(d) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
unsigned int sampleOffK007232[256];
bool sampleLoaded[256];

View file

@ -0,0 +1,513 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "k053260.h"
#include "../engine.h"
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) {if(!skipRegisterWrites) {k053260.write(a,v); regPool[a]=v; if(dumpWrites) addWrite(a,v);}}
#define CHIP_DIVIDER 16
#define TICK_DIVIDER 64 // for match to YM3012 output rate
const char* regCheatSheetK053260[]={
"MainToSub0", "00",
"MainToSub1", "01",
"SubToMain0", "02",
"SubToMain1", "03",
"CHx_FreqL", "08+x*8",
"CHx_FreqH", "09+x*8",
"CHx_LengthL", "0A+x*8",
"CHx_LengthH", "0B+x*8",
"CHx_StartL", "0C+x*8",
"CHx_StartM", "0D+x*8",
"CHx_StartH", "0E+x*8",
"CHx_Volume", "0F+x*8",
"KeyOn", "28",
"Status", "29",
"LoopFormat", "2A",
"Test", "2B",
"CH01_Pan", "2C",
"CH23_Pan", "2D",
"ROMReadback", "2E",
"Control", "2F",
NULL
};
const char** DivPlatformK053260::getRegisterSheet() {
return regCheatSheetK053260;
}
inline void DivPlatformK053260::chWrite(unsigned char ch, unsigned int addr, unsigned char val) {
if (!skipRegisterWrites) {
rWrite(8+((ch<<3)|(addr&7)),val);
}
}
u8 DivPlatformK053260::read_sample(u32 address) {
if ((sampleMem!=NULL) && (address<getSampleMemCapacity())) {
return sampleMem[address&0x1fffff];
}
return 0;
}
void DivPlatformK053260::acquire(short** buf, size_t len) {
for (size_t i=0; i<len; i++) {
k053260.tick(TICK_DIVIDER);
int lout=(k053260.output(0)); // scale to 16 bit
int rout=(k053260.output(1)); // scale to 16 bit
if (lout>32767) lout=32767;
if (lout<-32768) lout=-32768;
if (rout>32767) rout=32767;
if (rout<-32768) rout=-32768;
buf[0][i]=lout;
buf[1][i]=rout;
for (int i=0; i<4; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=(k053260.voice_out(i,0)+k053260.voice_out(i,1))>>2;
}
}
}
void DivPlatformK053260::tick(bool sysTick) {
unsigned char panMask=0;
for (int i=0; i<4; i++) {
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=((chan[i].vol&0x7f)*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul;
chWrite(i,7,chan[i].outVol);
}
if (NEW_ARP_STRAT) {
chan[i].handleArp();
} else if (chan[i].std.arp.had) {
if (!chan[i].inPorta) {
chan[i].baseFreq=NOTE_PERIODIC(parent->calcArp(chan[i].note,chan[i].std.arp.val));
}
chan[i].freqChanged=true;
}
if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-32768,32767);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true;
}
if (chan[i].std.panL.had) { // panning
chan[i].panning=4+chan[i].std.panL.val;
if (!isMuted[i]) {
panMask|=1<<i;
}
}
if (chan[i].std.phaseReset.had) {
if (chan[i].std.phaseReset.val==1 && chan[i].active) {
chan[i].audPos=0;
chan[i].setPos=true;
}
}
if (chan[i].setPos) {
// force keyon
chan[i].keyOn=true;
chan[i].setPos=false;
} else {
chan[i].audPos=0;
}
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
unsigned char keyon=regPool[0x28]|(1<<i);
unsigned char keyoff=keyon&~(17<<i);
unsigned char loopon=regPool[0x2a]|(1<<i);
unsigned char loopoff=loopon&~(1<<i);
double off=1.0;
int sample=chan[i].sample;
if (sample>=0 && sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(sample);
if (s->centerRate<1) {
off=1.0;
} else {
off=8363.0/s->centerRate;
}
}
DivSample* s=parent->getSample(chan[i].sample);
chan[i].freq=0x1000-(int)(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));
if (chan[i].freq>4095) chan[i].freq=4095;
if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].keyOn) {
unsigned int start=0;
unsigned int length=0;
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
start=sampleOffK053260[chan[i].sample];
length=s->length8;
if (chan[i].reverse) {
start+=length;
keyon|=(16<<i);
}
}
if (chan[i].audPos>0) {
if (chan[i].reverse) {
start=start-MIN(chan[i].audPos,s->length8);
}
else {
start=start+MIN(chan[i].audPos,s->length8);
}
length=MAX(1,length-chan[i].audPos);
}
start=MIN(start,getSampleMemCapacity());
length=MIN(65535,MIN(length,getSampleMemCapacity()));
rWrite(0x28,keyoff); // force keyoff first
rWrite(0x2a,loopoff);
chWrite(i,2,length&0xff);
chWrite(i,3,length>>8);
chWrite(i,4,start&0xff);
chWrite(i,5,start>>8);
chWrite(i,6,start>>16);
if (!chan[i].std.vol.had) {
chan[i].outVol=chan[i].vol;
chWrite(i,7,chan[i].outVol);
}
rWrite(0x28,keyon);
if (s->isLoopable()) {
rWrite(0x2a,loopon);
}
chan[i].keyOn=false;
}
if (chan[i].keyOff) {
rWrite(0x28,keyoff);
rWrite(0x2a,loopoff);
chan[i].keyOff=false;
}
if (chan[i].freqChanged) {
chWrite(i,0,chan[i].freq&0xff);
chWrite(i,1,chan[i].freq>>8);
chan[i].freqChanged=false;
}
}
}
if (panMask) {
updatePanning(panMask);
}
}
void DivPlatformK053260::updatePanning(unsigned char mask) {
if (mask&3) {
rWrite(0x2c,
(isMuted[0]?0:chan[0].panning)|
(isMuted[1]?0:chan[1].panning<<3));
}
if (mask&0xc) {
rWrite(0x2d,
(isMuted[2]?0:chan[2].panning)|
(isMuted[3]?0:chan[3].panning<<3));
}
}
int DivPlatformK053260::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:127;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].sample=ins->amiga.getSample(c.value);
c.value=ins->amiga.getFreq(c.value);
}
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
}
if (chan[c.chan].sample<0 || chan[c.chan].sample>=parent->song.sampleLen) {
chan[c.chan].sample=-1;
}
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
break;
}
case DIV_CMD_NOTE_OFF:
chan[c.chan].sample=-1;
chan[c.chan].active=false;
chan[c.chan].keyOff=true;
chan[c.chan].macroInit(NULL);
break;
case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE:
chan[c.chan].std.release();
break;
case DIV_CMD_INSTRUMENT:
if (chan[c.chan].ins!=c.value || c.value2==1) {
chan[c.chan].ins=c.value;
}
break;
case DIV_CMD_VOLUME:
if (chan[c.chan].vol!=c.value) {
chan[c.chan].vol=c.value;
if (!chan[c.chan].std.vol.has) {
chan[c.chan].outVol=c.value;
chWrite(c.chan,7,chan[c.chan].outVol);
}
}
break;
case DIV_CMD_GET_VOLUME:
if (chan[c.chan].std.vol.has) {
return chan[c.chan].vol;
}
return chan[c.chan].outVol;
break;
case DIV_CMD_PANNING:
chan[c.chan].panning=MIN(parent->convertPanSplitToLinearLR(c.value,c.value2,7)+1,7);
if (!isMuted[c.chan]) {
updatePanning(1<<c.chan);
}
break;
case DIV_CMD_PITCH:
chan[c.chan].pitch=c.value;
chan[c.chan].freqChanged=true;
break;
case DIV_CMD_NOTE_PORTA: {
int destFreq=NOTE_PERIODIC(c.value2);
bool return2=false;
if (destFreq>chan[c.chan].baseFreq) {
chan[c.chan].baseFreq+=c.value;
if (chan[c.chan].baseFreq>=destFreq) {
chan[c.chan].baseFreq=destFreq;
return2=true;
}
} else {
chan[c.chan].baseFreq-=c.value;
if (chan[c.chan].baseFreq<=destFreq) {
chan[c.chan].baseFreq=destFreq;
return2=true;
}
}
chan[c.chan].freqChanged=true;
if (return2) {
chan[c.chan].inPorta=false;
return 2;
}
break;
}
case DIV_CMD_LEGATO: {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(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_AMIGA));
}
if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note);
chan[c.chan].inPorta=c.value;
break;
case DIV_CMD_SAMPLE_POS:
chan[c.chan].audPos=c.value;
chan[c.chan].setPos=true;
break;
case DIV_CMD_SAMPLE_DIR: {
if (chan[c.chan].reverse!=(bool)(c.value&1)) {
chan[c.chan].reverse=c.value&1;
}
break;
}
case DIV_CMD_GET_VOLMAX:
return 127;
break;
case DIV_CMD_MACRO_OFF:
chan[c.chan].std.mask(c.value,true);
break;
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
break;
default:
break;
}
return 1;
}
void DivPlatformK053260::muteChannel(int ch, bool mute) {
isMuted[ch]=mute;
updatePanning(1<<ch);
}
void DivPlatformK053260::forceIns() {
for (int i=0; i<4; i++) {
chan[i].insChanged=true;
chan[i].freqChanged=true;
chan[i].sample=-1;
chWrite(i,1,isMuted[i]?0:chan[i].panning);
}
}
void* DivPlatformK053260::getChanState(int ch) {
return &chan[ch];
}
DivMacroInt* DivPlatformK053260::getChanMacroInt(int ch) {
return &chan[ch].std;
}
DivDispatchOscBuffer* DivPlatformK053260::getOscBuffer(int ch) {
return oscBuf[ch];
}
void DivPlatformK053260::reset() {
memset(regPool,0,64);
k053260.reset();
rWrite(0x28,0); // keyoff all channels
for (int i=0; i<4; i++) {
chan[i]=DivPlatformK053260::Channel();
chan[i].std.setEngine(parent);
}
updatePanning(0xf);
rWrite(0x2f,2); // sound enable
}
int DivPlatformK053260::getOutputCount() {
return 2;
}
void DivPlatformK053260::notifyInsChange(int ins) {
for (int i=0; i<4; i++) {
if (chan[i].ins==ins) {
chan[i].insChanged=true;
}
}
}
void DivPlatformK053260::notifyWaveChange(int wave) {
// TODO when wavetables are added
// TODO they probably won't be added unless the samples reside in RAM
}
void DivPlatformK053260::notifyInsDeletion(void* ins) {
for (int i=0; i<4; i++) {
chan[i].std.notifyInsDeletion((DivInstrument*)ins);
}
}
void DivPlatformK053260::setFlags(const DivConfig& flags) {
switch (flags.getInt("clockSel",0)) {
case 1: chipClock=4000000; break;
default: chipClock=COLOR_NTSC; break;
}
CHECK_CUSTOM_CLOCK;
rate=chipClock/TICK_DIVIDER;
for (int i=0; i<4; i++) {
oscBuf[i]->rate=rate;
}
}
void DivPlatformK053260::poke(unsigned int addr, unsigned short val) {
rWrite(addr&0x3f,val);
}
void DivPlatformK053260::poke(std::vector<DivRegWrite>& wlist) {
for (DivRegWrite& i: wlist) rWrite(i.addr&0x3f,i.val);
}
unsigned char* DivPlatformK053260::getRegisterPool() {
regPool[0x29]=k053260.read(0x29); // dynamically updated
return regPool;
}
int DivPlatformK053260::getRegisterPoolSize() {
return 64;
}
const void* DivPlatformK053260::getSampleMem(int index) {
return index == 0 ? sampleMem : NULL;
}
size_t DivPlatformK053260::getSampleMemCapacity(int index) {
return index == 0 ? 2097152 : 0;
}
size_t DivPlatformK053260::getSampleMemUsage(int index) {
return index == 0 ? sampleMemLen : 0;
}
bool DivPlatformK053260::isSampleLoaded(int index, int sample) {
if (index!=0) return false;
if (sample<0 || sample>255) return false;
return sampleLoaded[sample];
}
void DivPlatformK053260::renderSamples(int sysID) {
memset(sampleMem,0,getSampleMemCapacity());
memset(sampleOffK053260,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
size_t memPos=1; // for avoid silence
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (!s->renderOn[0][sysID]) {
sampleOffK053260[i]=0;
continue;
}
int length=MIN(65535,s->getEndPosition(DIV_SAMPLE_DEPTH_8BIT));
int actualLength=MIN((int)(getSampleMemCapacity()-memPos-1),length);
if (actualLength>0) {
sampleOffK053260[i]=memPos-1;
for (int j=0; j<actualLength; j++) {
sampleMem[memPos++]=s->data8[j];
}
sampleMem[memPos++]=0; // Silence for avoid popping noise
}
if (actualLength<length) {
logW("out of K053260 PCM memory for sample %d!",i);
break;
}
sampleLoaded[i]=true;
}
sampleMemLen=memPos;
}
int DivPlatformK053260::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
parent=p;
dumpWrites=false;
skipRegisterWrites=false;
for (int i=0; i<4; i++) {
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
}
sampleMem=new unsigned char[getSampleMemCapacity()];
sampleMemLen=0;
setFlags(flags);
reset();
return 4;
}
void DivPlatformK053260::quit() {
delete[] sampleMem;
for (int i=0; i<4; i++) {
delete oscBuf[i];
}
}

View file

@ -0,0 +1,97 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _K053260_H
#define _K053260_H
#include "../dispatch.h"
#include <queue>
#include "vgsound_emu/src/k053260/k053260.hpp"
class DivPlatformK053260: public DivDispatch, public k053260_intf {
struct Channel: public SharedChannel<int> {
unsigned int audPos;
int sample, wave;
int panning;
bool setPos, reverse;
int macroVolMul;
Channel():
SharedChannel<int>(127),
audPos(0),
sample(-1),
wave(-1),
panning(4),
setPos(false),
reverse(false),
macroVolMul(64) {}
};
Channel chan[4];
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4];
int chipType;
unsigned char curChan;
unsigned int sampleOffK053260[256];
bool sampleLoaded[256];
unsigned char* sampleMem;
size_t sampleMemLen;
k053260_core k053260;
unsigned char regPool[64];
void updatePanning(unsigned char mask);
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
public:
virtual u8 read_sample(u32 address) override;
virtual void acquire(short** buf, size_t len) override;
virtual int dispatch(DivCommand c) override;
virtual void* getChanState(int chan) override;
virtual DivMacroInt* getChanMacroInt(int ch) override;
virtual DivDispatchOscBuffer* getOscBuffer(int chan) override;
virtual unsigned char* getRegisterPool() override;
virtual int getRegisterPoolSize() override;
virtual void reset() override;
virtual void forceIns() override;
virtual void tick(bool sysTick=true) override;
virtual void muteChannel(int ch, bool mute) override;
virtual int getOutputCount() override;
virtual void notifyInsChange(int ins) override;
virtual void notifyWaveChange(int wave) override;
virtual void notifyInsDeletion(void* ins) override;
virtual void setFlags(const DivConfig& flags) override;
virtual void poke(unsigned int addr, unsigned short val) override;
virtual void poke(std::vector<DivRegWrite>& wlist) override;
virtual const char** getRegisterSheet() override;
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 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;
DivPlatformK053260():
DivDispatch(),
k053260_intf(),
k053260(*this) {}
private:
void chWrite(unsigned char ch, unsigned int addr, unsigned char val);
};
#endif

View file

@ -23,7 +23,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define NOTE_LINEAR(x) ((x)<<7)

View file

@ -21,7 +21,7 @@
#define _MSM5232_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/oki/msm5232.h"
class DivPlatformMSM5232: public DivDispatch {
@ -46,11 +46,12 @@ class DivPlatformMSM5232: public DivDispatch {
unsigned char groupAR[2];
unsigned char groupDR[2];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
int cycles, curChan, delay, detune, clockDriftAccum;
unsigned int clockDriftLFOPos, clockDriftLFOSpeed;

View file

@ -24,7 +24,7 @@
#include <string.h>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
const char** DivPlatformMSM6258::getRegisterSheet() {
return NULL;

View file

@ -21,7 +21,7 @@
#define _MSM6258_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/oki/okim6258.h"
class DivPlatformMSM6258: public DivDispatch {
@ -42,9 +42,10 @@ class DivPlatformMSM6258: public DivDispatch {
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
okim6258_device* msm;
unsigned char lastBusy;

View file

@ -23,8 +23,8 @@
#include <string.h>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWriteDelay(a,v,d) if (!skipRegisterWrites) {writes.emplace(a,v,d); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define rWriteDelay(a,v,d) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v,d)); if (dumpWrites) {addWrite(a,v);} }
const char** DivPlatformMSM6295::getRegisterSheet() {
return NULL;

View file

@ -21,7 +21,7 @@
#define _MSM6295_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "vgsound_emu/src/msm6295/msm6295.hpp"
class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
@ -41,12 +41,13 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
unsigned short addr;
unsigned char val;
unsigned short delay;
QueuedWrite(): addr(0), val(0), delay(96) {}
QueuedWrite(unsigned short a, unsigned char v, unsigned short d=96):
addr(a),
val(v),
delay(d) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
msm6295_core msm;
unsigned char lastBusy;

View file

@ -23,8 +23,8 @@
#include <math.h>
#define rRead(a,v) n163.addr_w(a); n163.data_r(v);
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWriteMask(a,v,m) if (!skipRegisterWrites) {writes.emplace(a,v,m); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define rWriteMask(a,v,m) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v,m)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) \
if (c<=chanMax) { \
rWrite(0x78-(c<<3)+(a&7),v) \
@ -207,7 +207,7 @@ void DivPlatformN163::tick(bool sysTick) {
}
}
if (chan[i].std.wave.had) {
if (chan[i].wave!=chan[i].std.wave.val) {
if (chan[i].wave!=chan[i].std.wave.val || chan[i].ws.activeChanged()) {
chan[i].wave=chan[i].std.wave.val;
chan[i].ws.changeWave1(chan[i].wave);
if (chan[i].waveMode&0x2) {

View file

@ -21,7 +21,7 @@
#define _N163_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "vgsound_emu/src/n163/n163.hpp"
@ -54,12 +54,13 @@ class DivPlatformN163: public DivDispatch {
DivDispatchOscBuffer* oscBuf[8];
bool isMuted[8];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
unsigned char mask;
QueuedWrite(unsigned char a, unsigned char v, unsigned char m=~0): addr(a), val(v), mask(m) {}
unsigned char addr;
unsigned char val;
unsigned char mask;
QueuedWrite(): addr(0), val(0), mask(~0) {}
QueuedWrite(unsigned char a, unsigned char v, unsigned char m=~0): addr(a), val(v), mask(m) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,2048> writes;
unsigned char initChanMax;
unsigned char chanMax;
short loadWave, loadPos, loadLen;

View file

@ -22,7 +22,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_FREQBASE 4194304

View file

@ -21,7 +21,7 @@
#define _NAMCOWSG_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "sound/namco.h"
@ -41,11 +41,12 @@ class DivPlatformNamcoWSG: public DivDispatch {
DivDispatchOscBuffer* oscBuf[8];
bool isMuted[8];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
namco_audio_device* namco;
int devType, chans;

View file

@ -24,7 +24,7 @@
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define immWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define KVSL(x,y) ((chan[x].state.op[orderedOpsL1[ops==4][y]].kvs==2 && isOutputL[ops==4][chan[x].state.alg][y]) || chan[x].state.op[orderedOpsL1[ops==4][y]].kvs==1)

View file

@ -21,7 +21,7 @@
#define _OPL_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../../../extern/opl/opl3.h"
#include "sound/ymfm/ymfm_adpcm.h"
@ -64,9 +64,10 @@ class DivPlatformOPL: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,2048> writes;
opl3_chip fm;
unsigned char* adpcmBMem;
size_t adpcmBMemLen;

View file

@ -24,7 +24,7 @@
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define immWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_FREQBASE 1180068

View file

@ -21,7 +21,7 @@
#define _OPLL_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
extern "C" {
#include "../../../extern/Nuked-OPLL/opll.h"
@ -50,9 +50,10 @@ class DivPlatformOPLL: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,512> writes;
opll_t fm;
int delay, lastCustomMemory;
unsigned char lastBusy;

View file

@ -22,7 +22,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) \
if (!skipRegisterWrites) { \
if (curChan!=c) { \
@ -531,7 +531,7 @@ int DivPlatformPCE::getRegisterPoolSize() {
}
void DivPlatformPCE::reset() {
while (!writes.empty()) writes.pop();
writes.clear();
memset(regPool,0,128);
for (int i=0; i<6; i++) {
chan[i]=DivPlatformPCE::Channel();

View file

@ -21,7 +21,7 @@
#define _PCE_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "sound/pce_psg.h"
@ -60,11 +60,12 @@ class DivPlatformPCE: public DivDispatch {
bool antiClickEnabled;
bool updateLFO;
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(9) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,512> writes;
unsigned char lastPan;
int cycles, curChan, delay;

View file

@ -21,7 +21,6 @@
#define _PCM_DAC_H
#include "../dispatch.h"
#include <queue>
#include "../waveSynth.h"
class DivPlatformPCMDAC: public DivDispatch {

View file

@ -21,7 +21,7 @@
#define _PCSPKR_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include <thread>
#include <mutex>
#include <condition_variable>
@ -40,12 +40,16 @@ class DivPlatformPCSpeaker: public DivDispatch {
struct RealQueueVal {
int tv_sec, tv_nsec;
unsigned short val;
RealQueueVal():
tv_sec(0),
tv_nsec(0),
val(0) {}
RealQueueVal(int sec, int nsec, unsigned short v):
tv_sec(sec),
tv_nsec(nsec),
val(v) {}
};
std::queue<RealQueueVal> realQueue;
FixedQueue<RealQueueVal,2048> realQueue;
std::mutex realQueueLock;
bool isMuted[1];
bool on, flip, lastOn, realOutEnabled;

View file

@ -21,7 +21,7 @@
#include "../engine.h"
#include "../../ta-log.h"
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 1

View file

@ -21,7 +21,7 @@
#define _POKEY_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
extern "C" {
#include "sound/pokey/mzpokeysnd.h"
@ -43,11 +43,12 @@ class DivPlatformPOKEY: public DivDispatch {
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
unsigned char audctl, skctl;
bool audctlChanged, skctlChanged;
unsigned char oscBufDelay;

View file

@ -42,7 +42,7 @@ void DivPlatformPV1000::acquire(short** buf, size_t len) {
short samp=d65010g031_sound_tick(&d65010g031,1);
buf[0][h]=samp;
for (int i=0; i<3; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=d65010g031.out[i]<<1;
oscBuf[i]->data[oscBuf[i]->needle++]=MAX(d65010g031.out[i]<<2,0);
}
}
}

View file

@ -22,7 +22,6 @@
#include "../dispatch.h"
#include "sound/d65modified.h"
#include <queue>
class DivPlatformPV1000: public DivDispatch {
struct Channel: public SharedChannel<int> {

View file

@ -21,7 +21,6 @@
#define _QSOUND_H
#include "../dispatch.h"
#include <queue>
#include "sound/qsound.h"
class DivPlatformQSound: public DivDispatch {

View file

@ -21,7 +21,6 @@
#define _RF5C68_H
#include "../dispatch.h"
#include <queue>
#include "sound/rf5c68.h"
class DivPlatformRF5C68: public DivDispatch {

View file

@ -23,7 +23,7 @@
#include <string.h>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 2

View file

@ -21,7 +21,7 @@
#define _SAA_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../../../extern/SAASound/src/SAASound.h"
class DivPlatformSAA1099: public DivDispatch {
@ -44,9 +44,10 @@ class DivPlatformSAA1099: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
CSAASound* saa_saaSound;
unsigned char regPool[32];
unsigned char lastBusy;

View file

@ -21,7 +21,6 @@
#define _SCC_H
#include "../dispatch.h"
#include <queue>
#include "../waveSynth.h"
#include "vgsound_emu/src/scc/scc.hpp"

View file

@ -23,7 +23,7 @@
#include <string.h>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) rWrite(((c)<<3)+(a),v)
void DivPlatformSegaPCM::acquire(short** buf, size_t len) {
@ -195,9 +195,6 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
chan[c.chan].pcm.sample=-1;
rWrite(0x86+(c.chan<<3),3);
chan[c.chan].macroInit(NULL);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
break;
}
if (c.value!=DIV_NOTE_NULL) {
@ -207,6 +204,16 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
}
chan[c.chan].furnacePCM=true;
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
if (parent->song.newSegaPCM) {
chan[c.chan].chVolL=(chan[c.chan].outVol*chan[c.chan].chPanL)/127;
chan[c.chan].chVolR=(chan[c.chan].outVol*chan[c.chan].chPanR)/127;
rWrite(2+(c.chan<<3),chan[c.chan].chVolL);
rWrite(3+(c.chan<<3),chan[c.chan].chVolR);
}
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
@ -423,7 +430,7 @@ const void* DivPlatformSegaPCM::getSampleMem(int index) {
}
size_t DivPlatformSegaPCM::getSampleMemCapacity(int index) {
return index == 0 ? 16777216 : 0;
return index == 0 ? 2097152 : 0;
}
size_t DivPlatformSegaPCM::getSampleMemUsage(int index) {
@ -465,7 +472,7 @@ void DivPlatformSegaPCM::reset() {
void DivPlatformSegaPCM::renderSamples(int sysID) {
size_t memPos=0;
memset(sampleMem,0,16777216);
memset(sampleMem,0,2097152);
memset(sampleLoaded,0,256*sizeof(bool));
memset(sampleOffSegaPCM,0,256*sizeof(unsigned int));
memset(sampleEndSegaPCM,0,256);
@ -482,7 +489,7 @@ void DivPlatformSegaPCM::renderSamples(int sysID) {
}
logV("- sample %d will be at %x with length %x",i,memPos,alignedSize);
sampleLoaded[i]=true;
if (memPos>=16777216) break;
if (memPos>=2097152) break;
sampleOffSegaPCM[i]=memPos;
for (unsigned int j=0; j<alignedSize; j++) {
if (j>=sample->samples) {
@ -491,10 +498,10 @@ void DivPlatformSegaPCM::renderSamples(int sysID) {
sampleMem[memPos++]=((unsigned char)sample->data8[j]+0x80);
}
sampleEndSegaPCM[i]=((memPos+0xff)>>8)-1;
if (memPos>=16777216) break;
if (memPos>=2097152) break;
}
logV(" and it ends in %d",sampleEndSegaPCM[i]);
if (memPos>=16777216) break;
if (memPos>=2097152) break;
}
sampleMemLen=memPos;
}
@ -522,10 +529,10 @@ int DivPlatformSegaPCM::init(DivEngine* p, int channels, int sugRate, const DivC
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
}
sampleMem=new unsigned char[16777216];
sampleMem=new unsigned char[2097152];
pcm.set_bank(segapcm_device::BANK_12M|segapcm_device::BANK_MASKF8);
pcm.set_read([this](unsigned int addr) -> unsigned char {
return sampleMem[addr&0xffffff];
return sampleMem[addr&0x1fffff];
});
setFlags(flags);
reset();

View file

@ -23,7 +23,7 @@
#include "../dispatch.h"
#include "../instrument.h"
#include "sound/segapcm.h"
#include <queue>
#include "../fixedQueue.h"
class DivPlatformSegaPCM: public DivDispatch {
protected:
@ -59,9 +59,10 @@ class DivPlatformSegaPCM: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,1024> writes;
segapcm_device pcm;
int delay;
int pcmL, pcmR, pcmCycles;

View file

@ -22,7 +22,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 64

View file

@ -21,7 +21,7 @@
#define _SM8521_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "sound/sm8521.h"
@ -46,11 +46,12 @@ class DivPlatformSM8521: public DivDispatch {
DivDispatchOscBuffer* oscBuf[3];
bool isMuted[3];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
bool antiClickEnabled;
struct sm8521_t sm8521;

View file

@ -22,7 +22,7 @@
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) {if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);}}}
#define rWrite(a,v) {if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);}}}
const char* regCheatSheetSN[]={
"DATA", "0",

View file

@ -25,7 +25,7 @@
extern "C" {
#include "../../../extern/Nuked-PSG/ympsg.h"
}
#include <queue>
#include "../fixedQueue.h"
class DivPlatformSMS: public DivDispatch {
struct Channel: public SharedChannel<signed char> {
@ -59,9 +59,10 @@ class DivPlatformSMS: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);

View file

@ -22,7 +22,7 @@
#include "../dispatch.h"
#include "../waveSynth.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/snes/SPC_DSP.h"
class DivPlatformSNES: public DivDispatch {
@ -81,9 +81,10 @@ class DivPlatformSNES: public DivDispatch {
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
signed char sampleMem[65536];
signed char copyOfSampleMem[65536];

View file

@ -0,0 +1,19 @@
Copyright (c) 2021 DefleMask Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,11 @@
dSID
===
This is the SID core used in DefleMask.
The project started as a very careful port from jsSID, comparing the wave
output from both, ensuring they were exactly the same.
## License
MIT License

View file

@ -0,0 +1,370 @@
#include "dsid.h"
#include <stdio.h>
#include <math.h> // INFINITY
#include <stdlib.h>
#include <string.h> // memset, memcpy
#define SID_OUT_SCALE (0x10000 * 3 * 16)
// CONTROL
#define GAT 0x01
#define SYN 0x02
#define RNG 0x04
#define TST 0x08
#define TRI 0x10
#define SAW 0x20
#define PUL 0x40
#define NOI 0x80
#define _HZ 0x10
#define DECSUS 0x40
#define ATK 0x80
// filter mode (high)
#define LP 0x10
#define BP 0x20
#define HP 0x40
#define OFF3 0x80
#define waveforms_add_sample(_id,_s) \
sid->lastOut[_id]=(_s);
const int Aexp[256] = {
1, 30, 30, 30, 30, 30, 30, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
double cmbWF(int chn, int *wfa, int index, int differ6581, struct SID_globals *g) {
if (differ6581 && g->model == 6581)
index &= 0x7FF;
return wfa[index];
}
void cCmbWF(int *wfa, double bitmul, double bstr, double trh) {
for (int i = 0; i < 4096; i++) {
wfa[i] = 0;
for (int j = 0; j < 12; j++) {
double blvl = 0;
for (int k = 0; k < 12; k++) {
blvl += (bitmul / pow(bstr, abs(k - j))) * (((i >> k) & 1) - 0.5);
}
wfa[i] += (blvl >= trh) ? pow(2, j) : 0;
}
wfa[i] *= 12;
}
}
void dSID_init(struct SID_chip* sid, double clockRate, double samplingRate, int model, unsigned char init_wf) {
if (model == 6581) {
sid->g.model = 6581;
} else {
sid->g.model = 8580;
}
memset(sid->M,0,MemLen);
memset(sid->SIDct, 0, sizeof(sid->SIDct));
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
sid->SIDct[i].ch[j].Ast = _HZ;
sid->SIDct[i].ch[j].nLFSR = 0x7FFFF8;
sid->SIDct[i].ch[j].prevwfout = 0;
}
sid->SIDct[i].ch[0].FSW = 1;
sid->SIDct[i].ch[1].FSW = 2;
sid->SIDct[i].ch[2].FSW = 4;
}
sid->g.ctfr = -2.0 * 3.14 * (12500.0 / 256.0) / samplingRate,
sid->g.ctf_ratio_6581 = -2.0 * 3.14 * (samplingRate / 44100.0) * (20000.0 / 256.0) / samplingRate;
sid->g.ckr = clockRate / samplingRate;
const double bAprd[16] = {9, 32 * 1, 63 * 1, 95 * 1, 149 * 1, 220 * 1,
267 * 1, 313 * 1, 392 * 1, 977 * 1, 1954 * 1, 3126 * 1,
3907 * 1, 11720 * 1, 19532 * 1, 31251 * 1};
const int bAstp[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
memcpy(&sid->g.Aprd, &bAprd, sizeof(bAprd));
memcpy(&sid->g.Astp, &bAstp, sizeof(bAstp));
if (init_wf) {
cCmbWF(sid->g.trsaw, 0.8, 2.4, 0.64);
cCmbWF(sid->g.pusaw, 1.4, 1.9, 0.68);
cCmbWF(sid->g.Pulsetrsaw, 0.8, 2.5, 0.64);
for (int i = 0; i < 2048; i++) {
double ctf = (double) i / 8.0 + 0.2;
if (model == 8580) {
ctf = 1 - exp(ctf * sid->g.ctfr);
} else {
if (ctf < 24) {
ctf = 2.0 * sin(771.78 / samplingRate);
} else {
ctf = (44100.0 / samplingRate) - 1.263 * (44100.0 / samplingRate) * exp(ctf * sid->g.ctf_ratio_6581);
}
}
sid->g.ctf_table[i] = ctf;
}
}
double prd0 = sid->g.ckr > 9 ? sid->g.ckr : 9;
sid->g.Aprd[0] = prd0;
sid->g.Astp[0] = ceil(prd0 / 9);
for (int i=0; i<3; i++) {
sid->fakeplp[i]=0;
sid->fakepbp[i]=0;
}
}
double dSID_render(struct SID_chip* sid) {
double flin = 0, output = 0;
double wfout = 0;
double step = 0;
for (int chn = 0; chn < 3; chn++) {
struct SIDVOICE *voic = &((struct SIDMEM *) (sid->M))->v[chn];
double pgt = (sid->SIDct->ch[chn].Ast & GAT);
uint8_t ctrl = voic->control;
uint8_t wf = ctrl & 0xF0;
uint8_t test = ctrl & TST;
uint8_t SR = voic->susres;
double tmp = 0;
if (pgt != (ctrl & GAT)) {
if (pgt) {
sid->SIDct->ch[chn].Ast &= 0xFF - (GAT | ATK | DECSUS);
} else {
sid->SIDct->ch[chn].Ast = (GAT | ATK | DECSUS);
if ((SR & 0xF) > (sid->SIDct->ch[chn].pSR & 0xF))
tmp = 1;
}
}
sid->SIDct->ch[chn].pSR = SR;
sid->SIDct->ch[chn].rcnt += sid->g.ckr;
if (sid->SIDct->ch[chn].rcnt >= 0x8000)
sid->SIDct->ch[chn].rcnt -= 0x8000;
double prd;
if (sid->SIDct->ch[chn].Ast & ATK) {
step = voic->attack;
prd = sid->g.Aprd[(int) step];
} else if (sid->SIDct->ch[chn].Ast & DECSUS) {
step = voic->decay;
prd = sid->g.Aprd[(int) step];
} else {
step = SR & 0xF;
prd = sid->g.Aprd[(int) step];
}
step = sid->g.Astp[(int) step];
if (sid->SIDct->ch[chn].rcnt >= prd && sid->SIDct->ch[chn].rcnt < prd + sid->g.ckr &&
tmp == 0) {
sid->SIDct->ch[chn].rcnt -= prd;
if ((sid->SIDct->ch[chn].Ast & ATK) ||
++sid->SIDct->ch[chn].expcnt == Aexp[(int) sid->SIDct->ch[chn].envcnt]) {
if (!(sid->SIDct->ch[chn].Ast & _HZ)) {
if (sid->SIDct->ch[chn].Ast & ATK) {
sid->SIDct->ch[chn].envcnt += step;
if (sid->SIDct->ch[chn].envcnt >= 0xFF) {
sid->SIDct->ch[chn].envcnt = 0xFF;
sid->SIDct->ch[chn].Ast &= 0xFF - ATK;
}
} else if (!(sid->SIDct->ch[chn].Ast & DECSUS) ||
sid->SIDct->ch[chn].envcnt > (SR >> 4) + (SR & 0xF0)) {
sid->SIDct->ch[chn].envcnt -= step;
if (sid->SIDct->ch[chn].envcnt <= 0 &&
sid->SIDct->ch[chn].envcnt + step != 0) {
sid->SIDct->ch[chn].envcnt = 0;
sid->SIDct->ch[chn].Ast |= _HZ;
}
}
}
sid->SIDct->ch[chn].expcnt = 0;
} else {
}
}
sid->SIDct->ch[chn].envcnt = (int) sid->SIDct->ch[chn].envcnt & 0xFF;
double aAdd = (voic->freq_low + voic->freq_high * 256) * sid->g.ckr;
if (test || ((ctrl & SYN) && sid->SIDct->sMSBrise)) {
sid->SIDct->ch[chn].pacc = 0;
} else {
sid->SIDct->ch[chn].pacc += aAdd;
if (sid->SIDct->ch[chn].pacc > 0xFFFFFF)
sid->SIDct->ch[chn].pacc -= 0x1000000;
}
double MSB = (int) sid->SIDct->ch[chn].pacc & 0x800000;
sid->SIDct->sMSBrise = (MSB > ((int) sid->SIDct->ch[chn].pracc & 0x800000)) ? 1 : 0;
if (wf & NOI) {
tmp = sid->SIDct->ch[chn].nLFSR;
if ((((int) sid->SIDct->ch[chn].pacc & 0x100000) !=
((int) sid->SIDct->ch[chn].pracc & 0x100000)) ||
aAdd >= 0x100000) {
step = ((int) tmp & 0x400000) ^ (((int) tmp & 0x20000) << 5);
tmp = (((int) tmp << 1) + (step > 0 || test)) & 0x7FFFFF;
sid->SIDct->ch[chn].nLFSR = tmp;
}
wfout = (wf & 0x70) ? 0
: (((int) tmp & 0x100000) >> 5) + (((int) tmp & 0x40000) >> 4) +
(((int) tmp & 0x4000) >> 1) + (((int) tmp & 0x800) << 1) +
(((int) tmp & 0x200) << 2) + (((int) tmp & 0x20) << 5) +
(((int) tmp & 0x04) << 7) + (((int) tmp & 0x01) << 8);
} else if (wf & PUL) {
double pw = (voic->pw_low + (voic->pw_high) * 256) * 16;
tmp = (int) aAdd >> 9;
if (0 < pw && pw < tmp)
pw = tmp;
tmp = (int) tmp ^ 0xFFFF;
if (pw > tmp)
pw = tmp;
tmp = (int) sid->SIDct->ch[chn].pacc >> 8;
if (wf == PUL) {
int lel = ((int) aAdd >> 16);
if (lel > 0) {
step = 256.0 / (double) lel;
} else {
step = INFINITY;
}
if (test)
wfout = 0xFFFF;
else if (tmp < pw) {
double lim = (0xFFFF - pw) * step;
if (lim > 0xFFFF)
lim = 0xFFFF;
wfout = lim - (pw - tmp) * step;
if (wfout < 0)
wfout = 0;
} else {
double lim = pw * step;
if (lim > 0xFFFF)
lim = 0xFFFF;
wfout = (0xFFFF - tmp) * step - lim;
if (wfout >= 0)
wfout = 0xFFFF;
wfout = (int) wfout & 0xFFFF;
}
} else {
wfout = (tmp >= pw || test) ? 0xFFFF : 0;
if (wf & TRI) {
if (wf & SAW) {
wfout =
(wfout) ? cmbWF(chn, sid->g.Pulsetrsaw, (int) tmp >> 4, 1, &sid->g) : 0;
} else {
tmp = (int) sid->SIDct->ch[chn].pacc ^ (ctrl & RNG ? sid->SIDct->sMSB : 0);
wfout =
(wfout)
? cmbWF(chn, sid->g.pusaw,
((int) tmp ^ ((int) tmp & 0x800000 ? 0xFFFFFF : 0)) >> 11,
0, &sid->g)
: 0;
}
} else if (wf & SAW)
wfout = (wfout) ? cmbWF(chn, sid->g.pusaw, (int) tmp >> 4, 1, &sid->g) : 0;
}
} else if (wf & SAW) {
wfout = (int) sid->SIDct->ch[chn].pacc >> 8;
if (wf & TRI)
wfout = cmbWF(chn, sid->g.trsaw, (int) wfout >> 4, 1, &sid->g);
else {
step = aAdd / 0x1200000;
wfout += wfout * step;
if (wfout > 0xFFFF)
wfout = 0xFFFF - (wfout - 0x10000) / step;
}
} else if (wf & TRI) {
tmp = (int) sid->SIDct->ch[chn].pacc ^ (ctrl & RNG ? sid->SIDct->sMSB : 0);
wfout = ((int) tmp ^ ((int) tmp & 0x800000 ? 0xFFFFFF : 0)) >> 7;
}
if (wf)
sid->SIDct->ch[chn].prevwfout = wfout;
else {
wfout = sid->SIDct->ch[chn].prevwfout;
}
sid->SIDct->ch[chn].pracc = sid->SIDct->ch[chn].pacc;
sid->SIDct->sMSB = MSB;
// double preflin = flin;
if ((sid->mute_mask & (1 << chn))) {
if (sid->M[0x17] & sid->SIDct->ch[chn].FSW) {
double chnout = (wfout - 0x8000) * (sid->SIDct->ch[chn].envcnt / 256);
flin += chnout;
// fake filter for solo waveform ahead
// mostly copypasted from below
double fakeflin = chnout;
double fakeflout = 0;
double ctf = sid->g.ctf_table[((sid->M[0x15]&7)|(sid->M[0x16]<<3))&0x7ff];
double reso;
if (sid->g.model == 8580) {
reso = pow(2, ((double) (4 - (double) (sid->M[0x17] >> 4)) / 8));
} else {
reso = (sid->M[0x17] > 0x5F) ? 8.0 / (double) (sid->M[0x17] >> 4) : 1.41;
}
double tmp = fakeflin + sid->fakepbp[chn] * reso + sid->fakeplp[chn];
if (sid->M[0x18] & HP)
fakeflout -= tmp;
tmp = sid->fakepbp[chn] - tmp * ctf;
sid->fakepbp[chn] = tmp;
if (sid->M[0x18] & BP)
fakeflout -= tmp;
tmp = sid->fakeplp[chn] + tmp * ctf;
sid->fakeplp[chn] = tmp;
if (sid->M[0x18] & LP)
fakeflout += tmp;
double wf_out = (fakeflout / SID_OUT_SCALE) * (sid->M[0x18] & 0xF) * 65535;
waveforms_add_sample(chn, wf_out);
} else if ((chn % 3) != 2 || !(sid->M[0x18] & OFF3)) {
double chnout = (wfout - 0x8000) * (sid->SIDct->ch[chn].envcnt / 256);
output += chnout;
double wf_out = (chnout / SID_OUT_SCALE) * (sid->M[0x18] & 0xF) * 65535;
waveforms_add_sample(chn, wf_out);
}
} else {
waveforms_add_sample(chn, 0);
}
}
int M1 = 0;
if (M1 & 3)
sid->M[0x1B] = (int) wfout >> 8;
sid->M[0x1C] = sid->SIDct->ch[2].envcnt;
double ctf = sid->g.ctf_table[((sid->M[0x15]&7)|(sid->M[0x16]<<3))&0x7ff];
double reso;
if (sid->g.model == 8580) {
reso = pow(2, ((double) (4 - (double) (sid->M[0x17] >> 4)) / 8));
} else {
reso = (sid->M[0x17] > 0x5F) ? 8.0 / (double) (sid->M[0x17] >> 4) : 1.41;
}
double tmp = flin + sid->SIDct->pbp * reso + sid->SIDct->plp;
if (sid->M[0x18] & HP)
output -= tmp;
tmp = sid->SIDct->pbp - tmp * ctf;
sid->SIDct->pbp = tmp;
if (sid->M[0x18] & BP)
output -= tmp;
tmp = sid->SIDct->plp + tmp * ctf;
sid->SIDct->plp = tmp;
if (sid->M[0x18] & LP)
output += tmp;
return (output / SID_OUT_SCALE) * (sid->M[0x18] & 0xF);
}
void dSID_setMuteMask(struct SID_chip* sid, int mute_mask) {
sid->mute_mask = mute_mask;
}
float dSID_getVolume(struct SID_chip* sid, int channel) {
if ((sid->M[0x18] & 0xF) == 0)
return 0;
return sid->SIDct[0].ch[channel].envcnt / 256.0f;
}
void dSID_write(struct SID_chip* sid, unsigned char addr, unsigned char val) {
sid->M[addr&0x1f]=val;
}

View file

@ -0,0 +1,99 @@
#ifndef DSID_H
#define DSID_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
struct SID_ctx_chan {
double rcnt;
double envcnt;
double expcnt;
double pacc;
double pracc;
int FSW;
int nLFSR;
double prevwfout;
uint8_t pSR;
int Ast;
};
struct SID_ctx {
int sMSBrise;
int sMSB;
double plp;
double pbp;
struct SID_ctx_chan ch[3];
};
struct SIDVOICE {
uint8_t freq_low;
uint8_t freq_high;
uint8_t pw_low;
uint8_t pw_high : 4;
uint8_t UNUSED : 4;
uint8_t control;
uint8_t decay : 4;
uint8_t attack : 4;
uint8_t susres;
// uint8_t release : 4;
// uint8_t sustain : 4;
};
struct SIDMEM {
struct SIDVOICE v[3];
uint8_t UNUSED : 4;
uint8_t cutoff_low : 4;
uint8_t cutoff_high;
uint8_t reso_rt : 4;
uint8_t reso : 4;
uint8_t volume : 4;
uint8_t filter_mode : 4;
uint8_t paddlex;
uint8_t paddley;
uint8_t osc3;
uint8_t env3;
};
struct SID_globals {
double ckr;
double ctfr;
double ctf_ratio_6581;
double ctf_table[2048];
int trsaw[4096];
int pusaw[4096];
int Pulsetrsaw[4096];
double Aprd[16];
int Astp[16];
int model;
};
#define MemLen 65536
struct SID_chip {
struct SID_globals g;
struct SID_ctx SIDct[3];
uint8_t M[MemLen];
int16_t lastOut[3];
int mute_mask;
double fakeplp[3];
double fakepbp[3];
};
double dSID_render(struct SID_chip* sid);
void dSID_init(struct SID_chip* sid, double clockRate, double samplingRate, int model, unsigned char init_wf);
float dSID_getVolume(struct SID_chip* sid, int channel);
void dSID_setMuteMask(struct SID_chip* sid, int mute_mask);
void dSID_write(struct SID_chip* sid, unsigned char addr, unsigned char val);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -61,7 +61,6 @@ const unsigned int EnvelopeGenerator::adsrtable[16] =
void EnvelopeGenerator::reset()
{
// counter is not changed on reset
envelope_pipeline = 0;
state_pipeline = 0;
@ -73,7 +72,7 @@ void EnvelopeGenerator::reset()
gate = false;
resetLfsr = true;
resetLfsr = false;
exponential_counter = 0;
exponential_counter_period = 1;
@ -81,7 +80,11 @@ void EnvelopeGenerator::reset()
state = RELEASE;
counter_enabled = true;
rate = adsrtable[release];
rate = 0;
envelope_counter = 0;
env3 = 0;
lfsr = 0x7fff;
}
void EnvelopeGenerator::writeCONTROL_REG(unsigned char control)

View file

@ -146,7 +146,7 @@ public:
counter_enabled(true),
gate(false),
resetLfsr(false),
envelope_counter(0xaa),
envelope_counter(0),
attack(0),
decay(0),
sustain(0),

View file

@ -351,7 +351,7 @@ void SID::write(int offset, unsigned char value)
break;
case 0x04: // Voice #1 control register
voice[0]->writeCONTROL_REG(muted[0] ? 0 : value);
voice[0]->writeCONTROL_REG(value);
break;
case 0x05: // Voice #1 Attack and Decay length
@ -379,7 +379,7 @@ void SID::write(int offset, unsigned char value)
break;
case 0x0b: // Voice #2 control register
voice[1]->writeCONTROL_REG(muted[1] ? 0 : value);
voice[1]->writeCONTROL_REG(value);
break;
case 0x0c: // Voice #2 Attack and Decay length
@ -407,7 +407,7 @@ void SID::write(int offset, unsigned char value)
break;
case 0x12: // Voice #3 control register
voice[2]->writeCONTROL_REG(muted[2] ? 0 : value);
voice[2]->writeCONTROL_REG(value);
break;
case 0x13: // Voice #3 Attack and Decay length

View file

@ -320,11 +320,11 @@ int SID::output()
const int v2 = voice[1]->output(voice[0]->wave());
const int v3 = voice[2]->output(voice[1]->wave());
lastChanOut[0]=v1;
lastChanOut[1]=v2;
lastChanOut[2]=v3;
lastChanOut[0]=muted[0]?0:v1;
lastChanOut[1]=muted[1]?0:v2;
lastChanOut[2]=muted[2]?0:v3;
return externalFilter->clock(filter->clock(v1, v2, v3));
return externalFilter->clock(filter->clock(muted[0]?0:v1, muted[1]?0:v2, muted[2]?0:v3));
}

View file

@ -137,7 +137,7 @@ void okim6258_device::device_reset()
void okim6258_device::sound_stream_update(short** outputs, int len)
{
auto &buffer = outputs[0];
short* buffer = outputs[0];
if (m_status & STATUS_PLAYING)
{

View file

@ -141,6 +141,7 @@ template<bool IsOpnA>
bool opn_registers_base<IsOpnA>::write(uint16_t index, uint8_t data, uint32_t &channel, uint32_t &opmask)
{
assert(index < REGISTERS);
if (index >= REGISTERS) return false;
// writes in the 0xa0-af/0x1a0-af region are handled as latched pairs
// borrow unused registers 0xb8-bf/0x1b8-bf as temporary holding locations

View file

@ -23,7 +23,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) rWrite(((c)<<5)|(a),v);
#define CHIP_DIVIDER 2

View file

@ -21,7 +21,7 @@
#define _SU_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/su.h"
class DivPlatformSoundUnit: public DivDispatch {
@ -72,11 +72,12 @@ class DivPlatformSoundUnit: public DivDispatch {
DivDispatchOscBuffer* oscBuf[8];
bool isMuted[8];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,512> writes;
unsigned char lastPan;
bool sampleMemSize;
unsigned char ilCtrl, ilSize, fil1;

View file

@ -21,8 +21,8 @@
#include "../engine.h"
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);}}
#define postWrite(a,v) postDACWrites.emplace(a,v);
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);}}
#define postWrite(a,v) postDACWrites.push(DivRegWrite(a,v));
#define CHIP_DIVIDER 32
@ -548,19 +548,25 @@ void DivPlatformSwan::poke(std::vector<DivRegWrite>& wlist) {
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
}
int DivPlatformSwan::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
parent=p;
dumpWrites=false;
skipRegisterWrites=false;
void DivPlatformSwan::setFlags(const DivConfig& flags) {
chipClock=3072000;
CHECK_CUSTOM_CLOCK;
rate=chipClock/16; // = 192000kHz, should be enough
for (int i=0; i<4; i++) {
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
oscBuf[i]->rate=rate;
}
}
int DivPlatformSwan::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
parent=p;
dumpWrites=false;
skipRegisterWrites=false;
for (int i=0; i<4; i++) {
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
}
ws=new WSwan();
setFlags(flags);
reset();
return 4;
}

View file

@ -23,7 +23,7 @@
#include "../dispatch.h"
#include "../waveSynth.h"
#include "sound/swan.h"
#include <queue>
#include "../fixedQueue.h"
class DivPlatformSwan: public DivDispatch {
struct Channel: public SharedChannel<int> {
@ -46,12 +46,13 @@ class DivPlatformSwan: public DivDispatch {
unsigned char regPool[0x80];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
std::queue<DivRegWrite> postDACWrites;
FixedQueue<QueuedWrite,256> writes;
FixedQueue<DivRegWrite,2048> postDACWrites;
WSwan* ws;
void updateWave(int ch);
friend void putDispatchChip(void*,int);
@ -68,6 +69,7 @@ class DivPlatformSwan: public DivDispatch {
void forceIns();
void tick(bool sysTick=true);
void muteChannel(int ch, bool mute);
void setFlags(const DivConfig& flags);
void notifyWaveChange(int wave);
void notifyInsDeletion(void* ins);
int getOutputCount();

View file

@ -23,7 +23,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
const char* regCheatSheetT6W28[]={
"Data0", "0",

View file

@ -21,7 +21,7 @@
#define _T6W28_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/t6w28/T6W28_Apu.h"
class DivPlatformT6W28: public DivDispatch {
@ -38,11 +38,12 @@ class DivPlatformT6W28: public DivDispatch {
bool isMuted[4];
bool easyNoise;
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
unsigned char lastPan;
int cycles, curChan, delay;

View file

@ -21,7 +21,6 @@
#define _TIA_H
#include "../dispatch.h"
#include <queue>
#include "sound/tia/Audio.h"
class DivPlatformTIA: public DivDispatch {

View file

@ -986,7 +986,7 @@ void DivPlatformTX81Z::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformTX81Z::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,330);
fm_ymfm->reset();
if (dumpWrites) {

View file

@ -21,7 +21,7 @@
#define _TX81Z_H
#include "fmshared_OPM.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/ymfm/ymfm_opz.h"
class DivTXInterface: public ymfm::ymfm_interface {

View file

@ -22,7 +22,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) rWrite(0x400+((c)<<6)+((a)<<2),v);
#define CHIP_DIVIDER 16

View file

@ -21,7 +21,7 @@
#define _PLATFORM_VB_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "sound/vsu.h"
@ -44,11 +44,12 @@ class DivPlatformVB: public DivDispatch {
DivDispatchOscBuffer* oscBuf[6];
bool isMuted[6];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,2048> writes;
unsigned char lastPan;
int cycles, curChan, delay;

View file

@ -32,19 +32,22 @@ extern "C" {
#define rWrite(c,a,d) {regPool[(c)*4+(a)]=(d); psg_writereg(psg,((c)*4+(a)),(d));if (dumpWrites) {addWrite(((c)*4+(a)),(d));}}
#define rWriteLo(c,a,d) rWrite(c,a,(regPool[(c)*4+(a)]&(~0x3f))|((d)&0x3f))
#define rWriteHi(c,a,d) rWrite(c,a,(regPool[(c)*4+(a)]&(~0xc0))|(((d)<<6)&0xc0))
#define rWritePCMCtrl(d) {regPool[64]=(d); pcm_write_ctrl(pcm,d);}
#define rWritePCMRate(d) {regPool[65]=(d); pcm_write_rate(pcm,d);}
#define rWritePCMCtrl(d) {regPool[64]=(d); pcm_write_ctrl(pcm,d);if (dumpWrites) addWrite(64,(d));}
#define rWritePCMRate(d) {regPool[65]=(d); pcm_write_rate(pcm,d);if (dumpWrites) addWrite(65,(d));}
#define rWritePCMData(d) {regPool[66]=(d); pcm_write_fifo(pcm,d);}
#define rWritePCMVol(d) rWritePCMCtrl((regPool[64]&(~0x8f))|((d)&15))
#define rWriteZSMSync(d) {if (dumpWrites) addWrite(68,(d));}
const char* regCheatSheetVERA[]={
"CHxFreq", "00+x*4",
"CHxVol", "02+x*4",
"CHxWave", "03+x*4",
"CHxFreq", "00+x*4",
"CHxVol", "02+x*4",
"CHxWave", "03+x*4",
"AUDIO_CTRL", "40",
"AUDIO_RATE", "41",
"AUDIO_DATA", "42",
"AUDIO_CTRL", "40",
"AUDIO_RATE", "41",
"AUDIO_DATA", "42",
"ZSM_PCM_LOOP_POINT", "43",
"ZSM_SYNC", "44",
NULL
};
@ -226,6 +229,57 @@ void DivPlatformVERA::tick(bool sysTick) {
rWritePCMRate(chan[16].freq&0xff);
chan[16].freqChanged=false;
}
// For export, output the entire sample that starts on this tick
if (dumpWrites) {
DivSample* s=parent->getSample(chan[16].pcm.sample);
if (s->samples>0) {
if (s->isLoopable()) {
// Inform the export process of the loop point for this sample
int tmp_ls=(s->loopStart<<1); // for stereo
if (chan[16].pcm.depth16)
tmp_ls<<=1; // for 16 bit
addWrite(67,tmp_ls&0xff);
addWrite(67,(tmp_ls>>8)&0xff);
addWrite(67,(tmp_ls>>16)&0xff);
}
while (true) {
short tmp_l=0;
short tmp_r=0;
if (!isMuted[16]) {
if (chan[16].pcm.depth16) {
tmp_l=s->data16[chan[16].pcm.pos];
tmp_r=tmp_l;
} else {
tmp_l=s->data8[chan[16].pcm.pos];
tmp_r=tmp_l;
}
if (!(chan[16].pan&1)) tmp_l=0;
if (!(chan[16].pan&2)) tmp_r=0;
}
if (chan[16].pcm.depth16) {
addWrite(66,tmp_l&0xff);
addWrite(66,(tmp_l>>8)&0xff);
addWrite(66,tmp_r&0xff);
addWrite(66,(tmp_r>>8)&0xff);
} else {
addWrite(66,tmp_l&0xff);
addWrite(66,tmp_r&0xff);
}
chan[16].pcm.pos++;
if (s->isLoopable() && chan[16].pcm.pos>=(unsigned int)s->loopEnd) {
chan[16].pcm.sample=-1;
break;
}
if (chan[16].pcm.pos>=s->samples) {
chan[16].pcm.sample=-1;
break;
}
}
} else {
chan[16].pcm.sample=-1;
}
}
}
int DivPlatformVERA::dispatch(DivCommand c) {
@ -370,6 +424,9 @@ int DivPlatformVERA::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_CMD_EXTERNAL:
rWriteZSMSync(c.value);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
break;
@ -441,6 +498,15 @@ void DivPlatformVERA::poke(std::vector<DivRegWrite>& wlist) {
for (auto &i: wlist) poke(i.addr,i.val);
}
void DivPlatformVERA::setFlags(const DivConfig& flags) {
chipClock=25000000;
CHECK_CUSTOM_CLOCK;
rate=chipClock/512;
for (int i=0; i<17; i++) {
oscBuf[i]->rate=rate;
}
}
int DivPlatformVERA::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
for (int i=0; i<17; i++) {
isMuted[i]=false;
@ -451,12 +517,7 @@ int DivPlatformVERA::init(DivEngine* p, int channels, int sugRate, const DivConf
pcm=new struct VERA_PCM;
dumpWrites=false;
skipRegisterWrites=false;
chipClock=25000000;
CHECK_CUSTOM_CLOCK;
rate=chipClock/512;
for (int i=0; i<17; i++) {
oscBuf[i]->rate=rate;
}
setFlags(flags);
reset();
return 17;
}

View file

@ -51,7 +51,7 @@ class DivPlatformVERA: public DivDispatch {
Channel chan[17];
DivDispatchOscBuffer* oscBuf[17];
bool isMuted[17];
unsigned char regPool[67];
unsigned char regPool[69];
struct VERA_PSG* psg;
struct VERA_PCM* pcm;
@ -70,6 +70,7 @@ class DivPlatformVERA: public DivDispatch {
void reset();
void tick(bool sysTick=true);
void muteChannel(int ch, bool mute);
void setFlags(const DivConfig& flags);
void notifyInsDeletion(void* ins);
float getPostAmp();
int getOutputCount();

View file

@ -22,7 +22,6 @@
#include "../dispatch.h"
#include "sound/vic20sound.h"
#include <queue>
class DivPlatformVIC20: public DivDispatch {
struct Channel: public SharedChannel<int> {

View file

@ -22,7 +22,7 @@
#include <cstddef>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) rWrite(0x9000+(c<<12)+(a&3),v)
const char* regCheatSheetVRC6[]={

View file

@ -20,7 +20,7 @@
#ifndef _VRC6_H
#define _VRC6_H
#include <queue>
#include "../fixedQueue.h"
#include "../dispatch.h"
#include "vgsound_emu/src/vrcvi/vrcvi.hpp"
@ -47,11 +47,12 @@ class DivPlatformVRC6: public DivDispatch, public vrcvi_intf {
DivDispatchOscBuffer* oscBuf[3];
bool isMuted[3];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,64> writes;
unsigned char sampleBank;
unsigned char writeOscBuf;
vrcvi_core vrc6;

View file

@ -974,7 +974,7 @@ void DivPlatformYM2203::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformYM2203::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,256);
if (dumpWrites) {
addWrite(0xffffffff,0);

View file

@ -1481,7 +1481,7 @@ void DivPlatformYM2608::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformYM2608::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,512);
if (dumpWrites) {
addWrite(0xffffffff,0);

View file

@ -1441,7 +1441,7 @@ void DivPlatformYM2610::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformYM2610::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,512);
if (dumpWrites) {
addWrite(0xffffffff,0);

View file

@ -1508,7 +1508,7 @@ void DivPlatformYM2610B::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformYM2610B::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,512);
if (dumpWrites) {
addWrite(0xffffffff,0);

View file

@ -21,7 +21,6 @@
#define _YMZ280B_H
#include "../dispatch.h"
#include <queue>
#include "sound/ymz280b.h"
class DivPlatformYMZ280B: public DivDispatch {

View file

@ -260,7 +260,6 @@ int DivPlatformZXBeeper::getRegisterPoolSize() {
}
void DivPlatformZXBeeper::reset() {
while (!writes.empty()) writes.pop();
memset(regPool,0,128);
for (int i=0; i<6; i++) {
chan[i]=DivPlatformZXBeeper::Channel();

View file

@ -21,7 +21,6 @@
#define _ZXBEEPER_H
#include "../dispatch.h"
#include <queue>
class DivPlatformZXBeeper: public DivDispatch {
struct Channel: public SharedChannel<signed char> {
@ -35,12 +34,6 @@ class DivPlatformZXBeeper: public DivDispatch {
Channel chan[6];
DivDispatchOscBuffer* oscBuf[6];
bool isMuted[6];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
unsigned char lastPan, ulaOut;
int cycles, curChan, sOffTimer, delay, curSample, curSamplePeriod;