C219: initial work
This commit is contained in:
parent
80961354f7
commit
859182bb08
13 changed files with 207 additions and 69 deletions
|
|
@ -587,6 +587,11 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
|||
break;
|
||||
case DIV_SYSTEM_C140:
|
||||
dispatch=new DivPlatformC140;
|
||||
((DivPlatformC140*)dispatch)->set219(false);
|
||||
break;
|
||||
case DIV_SYSTEM_C219:
|
||||
dispatch=new DivPlatformC140;
|
||||
((DivPlatformC140*)dispatch)->set219(true);
|
||||
break;
|
||||
case DIV_SYSTEM_PCM_DAC:
|
||||
dispatch=new DivPlatformPCMDAC;
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@
|
|||
#define EXTERN_BUSY_BEGIN_SOFT e->softLocked=true; e->isBusy.lock();
|
||||
#define EXTERN_BUSY_END e->isBusy.unlock(); e->softLocked=false;
|
||||
|
||||
//#define DIV_UNSTABLE
|
||||
#define DIV_UNSTABLE
|
||||
|
||||
#define DIV_VERSION "0.6pre9"
|
||||
#define DIV_VERSION "dev169"
|
||||
#define DIV_ENGINE_VERSION 169
|
||||
// for imports
|
||||
#define DIV_VERSION_MOD 0xff01
|
||||
|
|
|
|||
|
|
@ -967,6 +967,10 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song) {
|
|||
featureSM=true;
|
||||
featureSL=true;
|
||||
break;
|
||||
case DIV_INS_C219:
|
||||
featureSM=true;
|
||||
featureSL=true;
|
||||
break;
|
||||
|
||||
case DIV_INS_MAX:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ enum DivInstrumentType: unsigned short {
|
|||
// DIV_INS_YMF292=51,
|
||||
DIV_INS_TED=52,
|
||||
DIV_INS_C140=53,
|
||||
DIV_INS_C219=54,
|
||||
DIV_INS_MAX,
|
||||
DIV_INS_NULL
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,11 +49,40 @@ const char** DivPlatformC140::getRegisterSheet() {
|
|||
return regCheatSheetC140;
|
||||
}
|
||||
|
||||
void DivPlatformC140::acquire(short** buf, size_t len) {
|
||||
void DivPlatformC140::acquire_219(short** buf, size_t len) {
|
||||
for (size_t h=0; h<len; h++) {
|
||||
while (!writes.empty()) {
|
||||
QueuedWrite w=writes.front();
|
||||
c140_write(&c140, w.addr,w.val);
|
||||
c219_write(&c219,w.addr,w.val);
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop();
|
||||
}
|
||||
|
||||
c219_tick(&c219, 1);
|
||||
// scale as 16bit
|
||||
c219.lout >>= 10;
|
||||
c219.rout >>= 10;
|
||||
|
||||
if (c219.lout<-32768) c219.lout=-32768;
|
||||
if (c219.lout>32767) c219.lout=32767;
|
||||
|
||||
if (c219.rout<-32768) c219.rout=-32768;
|
||||
if (c219.rout>32767) c219.rout=32767;
|
||||
|
||||
buf[0][h]=c219.lout;
|
||||
buf[1][h]=c219.rout;
|
||||
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(c219.voice[i].lout+c219.voice[i].rout)>>10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformC140::acquire_140(short** buf, size_t len) {
|
||||
for (size_t h=0; h<len; h++) {
|
||||
while (!writes.empty()) {
|
||||
QueuedWrite w=writes.front();
|
||||
c140_write(&c140,w.addr,w.val);
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop();
|
||||
}
|
||||
|
|
@ -72,14 +101,22 @@ void DivPlatformC140::acquire(short** buf, size_t len) {
|
|||
buf[0][h]=c140.lout;
|
||||
buf[1][h]=c140.rout;
|
||||
|
||||
for (int i=0; i<24; i++) {
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(c140.voice[i].lout+c140.voice[i].rout)>>10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformC140::acquire(short** buf, size_t len) {
|
||||
if (is219) {
|
||||
acquire_219(buf,len);
|
||||
} else {
|
||||
acquire_140(buf,len);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformC140::tick(bool sysTick) {
|
||||
for (int i=0; i<24; i++) {
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
chan[i].outVol=(chan[i].vol*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul;
|
||||
|
|
@ -144,26 +181,47 @@ void DivPlatformC140::tick(bool sysTick) {
|
|||
chan[i].freq=(int)(off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE));
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||
ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0)|((s->depth==DIV_SAMPLE_DEPTH_MULAW)?0x08:0);
|
||||
if (is219) {
|
||||
ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0)|((s->depth==DIV_SAMPLE_DEPTH_MULAW)?1:0);
|
||||
} else {
|
||||
ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0)|((s->depth==DIV_SAMPLE_DEPTH_MULAW)?0x08:0);
|
||||
}
|
||||
if (chan[i].keyOn) {
|
||||
unsigned int bank=0;
|
||||
unsigned int start=0;
|
||||
unsigned int loop=0;
|
||||
unsigned int end=0;
|
||||
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||
bank=(sampleOff[chan[i].sample]>>16)&0xff;
|
||||
start=sampleOff[chan[i].sample]&0xffff;
|
||||
end=MIN(start+s->length8-1,65535);
|
||||
if (is219) {
|
||||
bank=(sampleOff[chan[i].sample]>>16)&0xff;
|
||||
start=sampleOff[chan[i].sample]&0xffff;
|
||||
end=MIN(start+(s->length8>>1)-1,65535);
|
||||
logV("sampleOff[%d]=%d",chan[i].sample,sampleOff[chan[i].sample]);
|
||||
} else {
|
||||
bank=(sampleOff[chan[i].sample]>>16)&0xff;
|
||||
start=sampleOff[chan[i].sample]&0xffff;
|
||||
end=MIN(start+s->length8-1,65535);
|
||||
}
|
||||
}
|
||||
if (chan[i].audPos>0) {
|
||||
start=MIN(start+MIN(chan[i].audPos,s->length8),65535);
|
||||
start=MIN(start+(MIN(chan[i].audPos,s->length8)>>1),65535);
|
||||
}
|
||||
if (s->isLoopable()) {
|
||||
loop=MIN(start+s->loopStart,65535);
|
||||
end=MIN(start+s->loopEnd-1,65535);
|
||||
if (is219) {
|
||||
loop=MIN(start+(s->loopStart>>1),65535);
|
||||
end=MIN(start+(s->loopEnd>>1)-1,65535);
|
||||
} else {
|
||||
loop=MIN(start+s->loopStart,65535);
|
||||
end=MIN(start+s->loopEnd-1,65535);
|
||||
}
|
||||
}
|
||||
rWrite(0x05+(i<<4),0); // force keyoff first
|
||||
rWrite(0x04+(i<<4),bank);
|
||||
if (is219) {
|
||||
// TODO; group banking
|
||||
|
||||
} else {
|
||||
rWrite(0x04+(i<<4),bank);
|
||||
}
|
||||
rWrite(0x06+(i<<4),(start>>8)&0xff);
|
||||
rWrite(0x07+(i<<4),start&0xff);
|
||||
rWrite(0x08+(i<<4),(end>>8)&0xff);
|
||||
|
|
@ -323,11 +381,15 @@ int DivPlatformC140::dispatch(DivCommand c) {
|
|||
|
||||
void DivPlatformC140::muteChannel(int ch, bool mute) {
|
||||
isMuted[ch]=mute;
|
||||
c140.voice[ch].muted=mute;
|
||||
if (is219) {
|
||||
c219.voice[ch].muted=mute;
|
||||
} else {
|
||||
c140.voice[ch].muted=mute;
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformC140::forceIns() {
|
||||
for (int i=0; i<24; i++) {
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
chan[i].insChanged=true;
|
||||
chan[i].freqChanged=true;
|
||||
chan[i].volChangedL=true;
|
||||
|
|
@ -355,8 +417,12 @@ DivDispatchOscBuffer* DivPlatformC140::getOscBuffer(int ch) {
|
|||
void DivPlatformC140::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
memset(regPool,0,512);
|
||||
c140_reset(&c140);
|
||||
for (int i=0; i<24; i++) {
|
||||
if (is219) {
|
||||
c219_reset(&c219);
|
||||
} else {
|
||||
c140_reset(&c140);
|
||||
}
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
chan[i]=DivPlatformC140::Channel();
|
||||
chan[i].std.setEngine(parent);
|
||||
rWrite(0x05+(i<<4),0);
|
||||
|
|
@ -368,7 +434,7 @@ int DivPlatformC140::getOutputCount() {
|
|||
}
|
||||
|
||||
void DivPlatformC140::notifyInsChange(int ins) {
|
||||
for (int i=0; i<24; i++) {
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
if (chan[i].ins==ins) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
|
|
@ -381,7 +447,7 @@ void DivPlatformC140::notifyWaveChange(int wave) {
|
|||
}
|
||||
|
||||
void DivPlatformC140::notifyInsDeletion(void* ins) {
|
||||
for (int i=0; i<24; i++) {
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
chan[i].std.notifyInsDeletion((DivInstrument*)ins);
|
||||
}
|
||||
}
|
||||
|
|
@ -437,53 +503,84 @@ void DivPlatformC140::renderSamples(int sysID) {
|
|||
continue;
|
||||
}
|
||||
|
||||
unsigned int length=s->length16;
|
||||
// fit sample size to single bank size
|
||||
if (length>(131072)) {
|
||||
length=131072;
|
||||
}
|
||||
if ((memPos&0xfe0000)!=((memPos+length)&0xfe0000)) {
|
||||
memPos=((memPos+0x1ffff)&0xfe0000);
|
||||
}
|
||||
if (memPos>=(getSampleMemCapacity())) {
|
||||
logW("out of C140 memory for sample %d!",i);
|
||||
break;
|
||||
}
|
||||
// why is C140 not G.711-compliant? this weird bit mangling had me puzzled for 3 hours...
|
||||
if (memPos+length>=(getSampleMemCapacity())) {
|
||||
if (s->depth==DIV_SAMPLE_DEPTH_MULAW) {
|
||||
for (unsigned int i=0; i<(getSampleMemCapacity())-memPos; i++) {
|
||||
if (i>=s->lengthMuLaw) break;
|
||||
unsigned char x=s->dataMuLaw[i]^0xff;
|
||||
if (x&0x80) x^=15;
|
||||
unsigned char c140Mu=(x&0x80)|((x&15)<<3)|((x&0x70)>>4);
|
||||
sampleMem[i+(memPos/sizeof(short))]=((c140Mu)<<8);
|
||||
}
|
||||
} else {
|
||||
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,(getSampleMemCapacity())-memPos);
|
||||
if (is219) { // C219 (8-bit)
|
||||
unsigned int length=s->length8;
|
||||
// fit sample size to single bank size
|
||||
if (length>131072) {
|
||||
length=131072;
|
||||
}
|
||||
if (length&1) length++;
|
||||
if ((memPos&0xfe0000)!=((memPos+length)&0xfe0000)) {
|
||||
memPos=((memPos+0x1ffff)&0xfe0000);
|
||||
}
|
||||
if (memPos>=(getSampleMemCapacity())) {
|
||||
logW("out of C219 memory for sample %d!",i);
|
||||
break;
|
||||
}
|
||||
if (memPos+length>=(getSampleMemCapacity())) {
|
||||
length=getSampleMemCapacity()-memPos;
|
||||
logW("out of C219 memory for sample %d!",i);
|
||||
}
|
||||
logW("out of C140 memory for sample %d!",i);
|
||||
} else {
|
||||
if (s->depth==DIV_SAMPLE_DEPTH_MULAW) {
|
||||
for (unsigned int i=0; i<length; i++) {
|
||||
if (i>=s->lengthMuLaw) break;
|
||||
unsigned char x=s->dataMuLaw[i]^0xff;
|
||||
if (x&0x80) x^=15;
|
||||
unsigned char c140Mu=(x&0x80)|((x&15)<<3)|((x&0x70)>>4);
|
||||
sampleMem[i+(memPos/sizeof(short))]=((c140Mu)<<8);
|
||||
if (i>=s->lengthMuLaw) {
|
||||
sampleMem[i+memPos]=0;
|
||||
} else {
|
||||
unsigned char x=s->dataMuLaw[i]^0xff;
|
||||
sampleMem[i+memPos]=x;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,length);
|
||||
for (unsigned int i=0; i<length; i++) {
|
||||
if (i>=s->length8) {
|
||||
sampleMem[memPos+i]=0;
|
||||
} else {
|
||||
sampleMem[memPos+i]=s->data8[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
sampleOff[i]=memPos>>1;
|
||||
sampleLoaded[i]=true;
|
||||
memPos+=length;
|
||||
} else { // C140 (16-bit)
|
||||
unsigned int length=s->length16;
|
||||
// fit sample size to single bank size
|
||||
if (length>(131072)) {
|
||||
length=131072;
|
||||
}
|
||||
if ((memPos&0xfe0000)!=((memPos+length)&0xfe0000)) {
|
||||
memPos=((memPos+0x1ffff)&0xfe0000);
|
||||
}
|
||||
if (memPos>=(getSampleMemCapacity())) {
|
||||
logW("out of C140 memory for sample %d!",i);
|
||||
break;
|
||||
}
|
||||
// why is C140 not G.711-compliant? this weird bit mangling had me puzzled for 3 hours...
|
||||
if (memPos+length>=(getSampleMemCapacity())) {
|
||||
length=getSampleMemCapacity()-memPos;
|
||||
logW("out of C140 memory for sample %d!",i);
|
||||
}
|
||||
if (s->depth==DIV_SAMPLE_DEPTH_MULAW) {
|
||||
for (unsigned int i=0; i<length; i+=2) {
|
||||
if ((i>>1)>=s->lengthMuLaw) break;
|
||||
unsigned char x=s->dataMuLaw[i>>1]^0xff;
|
||||
if (x&0x80) x^=15;
|
||||
unsigned char c140Mu=(x&0x80)|((x&15)<<3)|((x&0x70)>>4);
|
||||
sampleMem[i+memPos]=0;
|
||||
sampleMem[1+i+memPos]=c140Mu;
|
||||
}
|
||||
} else {
|
||||
memcpy(sampleMem+memPos,s->data16,length);
|
||||
}
|
||||
sampleOff[i]=memPos>>1;
|
||||
sampleLoaded[i]=true;
|
||||
memPos+=length;
|
||||
}
|
||||
sampleOff[i]=memPos>>1;
|
||||
sampleLoaded[i]=true;
|
||||
memPos+=length;
|
||||
}
|
||||
sampleMemLen=memPos+256;
|
||||
}
|
||||
|
||||
void DivPlatformC219::set219(bool is_219) {
|
||||
void DivPlatformC140::set219(bool is_219) {
|
||||
is219=is_219;
|
||||
totalChans=is219?16:24;
|
||||
}
|
||||
|
|
@ -492,7 +589,7 @@ void DivPlatformC140::setFlags(const DivConfig& flags) {
|
|||
chipClock=32000*256; // 8.192MHz and 12.288MHz input, verified from Assault Schematics
|
||||
CHECK_CUSTOM_CLOCK;
|
||||
rate=chipClock/192;
|
||||
for (int i=0; i<24; i++) {
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
}
|
||||
|
|
@ -502,23 +599,28 @@ int DivPlatformC140::init(DivEngine* p, int channels, int sugRate, const DivConf
|
|||
dumpWrites=false;
|
||||
skipRegisterWrites=false;
|
||||
|
||||
for (int i=0; i<24; i++) {
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
isMuted[i]=false;
|
||||
oscBuf[i]=new DivDispatchOscBuffer;
|
||||
}
|
||||
sampleMem=new short[getSampleMemCapacity()>>1];
|
||||
sampleMem=new unsigned char[getSampleMemCapacity()];
|
||||
sampleMemLen=0;
|
||||
c140_init(&c140);
|
||||
c140.sample_mem=sampleMem;
|
||||
if (is219) {
|
||||
c219_init(&c219);
|
||||
c219.sample_mem=(signed char*)sampleMem;
|
||||
} else {
|
||||
c140_init(&c140);
|
||||
c140.sample_mem=(short*)sampleMem;
|
||||
}
|
||||
setFlags(flags);
|
||||
reset();
|
||||
|
||||
return 24;
|
||||
return totalChans;
|
||||
}
|
||||
|
||||
void DivPlatformC140::quit() {
|
||||
delete[] sampleMem;
|
||||
for (int i=0; i<24; i++) {
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
delete oscBuf[i];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class DivPlatformC140: public DivDispatch {
|
|||
bool is219;
|
||||
int totalChans;
|
||||
|
||||
signed short* sampleMem;
|
||||
unsigned char* sampleMem;
|
||||
size_t sampleMemLen;
|
||||
struct QueuedWrite {
|
||||
unsigned short addr;
|
||||
|
|
@ -67,10 +67,14 @@ class DivPlatformC140: public DivDispatch {
|
|||
};
|
||||
FixedQueue<QueuedWrite,2048> writes;
|
||||
struct c140_t c140;
|
||||
struct c219_t c219;
|
||||
unsigned char regPool[512];
|
||||
friend void putDispatchChip(void*,int);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
||||
void acquire_219(short** buf, size_t len);
|
||||
void acquire_140(short** buf, size_t len);
|
||||
|
||||
public:
|
||||
void acquire(short** buf, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
|
|
|
|||
|
|
@ -130,7 +130,8 @@ enum DivSystem {
|
|||
DIV_SYSTEM_PV1000,
|
||||
DIV_SYSTEM_K053260,
|
||||
DIV_SYSTEM_TED,
|
||||
DIV_SYSTEM_C140
|
||||
DIV_SYSTEM_C140,
|
||||
DIV_SYSTEM_C219
|
||||
};
|
||||
|
||||
enum DivEffectType: unsigned short {
|
||||
|
|
|
|||
|
|
@ -1887,6 +1887,20 @@ void DivEngine::registerSystems() {
|
|||
{}
|
||||
);
|
||||
|
||||
sysDefs[DIV_SYSTEM_C219]=new DivSysDef(
|
||||
"Namco C219", NULL, 0xcf, 0, 16, false, true, 0x161, false, (1U<<DIV_SAMPLE_DEPTH_MULAW)|(1U<<DIV_SAMPLE_DEPTH_8BIT),
|
||||
"Namco's PCM chip used in their NA1/2 hardware.",
|
||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16"},
|
||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"},
|
||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||
{DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219, DIV_INS_C219},
|
||||
{DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA},
|
||||
{},
|
||||
{
|
||||
{0x10, {DIV_CMD_STD_NOISE_MODE, "10xx: Set noise/invert mode (bit 0: noise; bit 1: invert left output; bit 2: invert output)"}}
|
||||
}
|
||||
);
|
||||
|
||||
sysDefs[DIV_SYSTEM_DUMMY]=new DivSysDef(
|
||||
"Dummy System", NULL, 0xfd, 0, 8, false, true, 0, false, 0,
|
||||
"this is a system designed for testing purposes.",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue