Merge branch 'master' of https://github.com/tildearrow/furnace into k053260
This commit is contained in:
commit
ac8db58cbf
127 changed files with 2967 additions and 1338 deletions
|
|
@ -21,6 +21,7 @@
|
|||
#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);} }
|
||||
|
||||
|
|
@ -64,34 +65,45 @@ const char** DivPlatformC64::getRegisterSheet() {
|
|||
}
|
||||
|
||||
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++]=(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;
|
||||
}
|
||||
} 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++]=(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -106,7 +118,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 +193,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 +226,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 +264,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 +377,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 +463,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 +532,7 @@ bool DivPlatformC64::getWantPreNote() {
|
|||
}
|
||||
|
||||
float DivPlatformC64::getPostAmp() {
|
||||
return isFP?3.0f:1.0f;
|
||||
return (sidCore==1)?3.0f:1.0f;
|
||||
}
|
||||
|
||||
void DivPlatformC64::reset() {
|
||||
|
|
@ -510,10 +542,20 @@ void DivPlatformC64::reset() {
|
|||
chan[i].std.setEngine(parent);
|
||||
}
|
||||
|
||||
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 +566,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 +581,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,21 +606,58 @@ 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);
|
||||
}
|
||||
|
||||
int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||
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 +669,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() {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <queue>
|
||||
#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> {
|
||||
|
|
@ -64,11 +65,16 @@ class DivPlatformC64: public DivDispatch {
|
|||
|
||||
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);
|
||||
|
|
@ -101,7 +107,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();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#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);} }
|
||||
|
|
@ -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 {
|
||||
|
|
@ -664,9 +667,7 @@ 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;
|
||||
|
|
@ -675,6 +676,9 @@ int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, const DivConfig
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -423,7 +423,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 +465,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 +482,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 +491,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 +522,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();
|
||||
|
|
|
|||
19
src/engine/platform/sound/c64_d/LICENSE
Normal file
19
src/engine/platform/sound/c64_d/LICENSE
Normal 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.
|
||||
11
src/engine/platform/sound/c64_d/README.md
Normal file
11
src/engine/platform/sound/c64_d/README.md
Normal 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
|
||||
367
src/engine/platform/sound/c64_d/dsid.c
Normal file
367
src/engine/platform/sound/c64_d/dsid.c
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
double dSID_render(struct SID_chip* sid) {
|
||||
double flin = 0, output = 0;
|
||||
double wfout = 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;
|
||||
|
||||
static double step;
|
||||
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;
|
||||
static double fakeplp[3] = {0};
|
||||
static double fakepbp[3] = {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 + fakepbp[chn] * reso + fakeplp[chn];
|
||||
if (sid->M[0x18] & HP)
|
||||
fakeflout -= tmp;
|
||||
tmp = fakepbp[chn] - tmp * ctf;
|
||||
fakepbp[chn] = tmp;
|
||||
if (sid->M[0x18] & BP)
|
||||
fakeflout -= tmp;
|
||||
tmp = fakeplp[chn] + tmp * ctf;
|
||||
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;
|
||||
}
|
||||
97
src/engine/platform/sound/c64_d/dsid.h
Normal file
97
src/engine/platform/sound/c64_d/dsid.h
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#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 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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ public:
|
|||
counter_enabled(true),
|
||||
gate(false),
|
||||
resetLfsr(false),
|
||||
envelope_counter(0xaa),
|
||||
envelope_counter(0),
|
||||
attack(0),
|
||||
decay(0),
|
||||
sustain(0),
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "vera.h"
|
||||
#include "../engine.h"
|
||||
#include "../../ta-log.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
|
|
@ -32,10 +33,11 @@ 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",
|
||||
|
|
@ -45,6 +47,7 @@ const char* regCheatSheetVERA[]={
|
|||
"AUDIO_CTRL", "40",
|
||||
"AUDIO_RATE", "41",
|
||||
"AUDIO_DATA", "42",
|
||||
"ZSM_SYNC", "44",
|
||||
|
||||
NULL
|
||||
};
|
||||
|
|
@ -226,6 +229,49 @@ void DivPlatformVERA::tick(bool sysTick) {
|
|||
rWritePCMRate(chan[16].freq&0xff);
|
||||
chan[16].freqChanged=false;
|
||||
}
|
||||
|
||||
if (dumpWrites) {
|
||||
DivSample* s=parent->getSample(chan[16].pcm.sample);
|
||||
if (s->samples>0) {
|
||||
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.pos=s->loopStart;
|
||||
logI("VERA PCM export: treating looped sample as non-looped");
|
||||
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 +416,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 +490,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 +509,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue