C140: help µ-law ISN'T WORKING

This commit is contained in:
tildearrow 2023-08-12 01:54:12 -05:00
parent 0311d712b1
commit 27e454e7aa
7 changed files with 66 additions and 11 deletions

View file

@ -219,6 +219,7 @@ size | description
| - 0xcb: Casio PV-1000 - 3 channels | - 0xcb: Casio PV-1000 - 3 channels
| - 0xcc: K053260 - 4 channels | - 0xcc: K053260 - 4 channels
| - 0xcd: TED - 2 channels | - 0xcd: TED - 2 channels
| - 0xce: Namco C140 - 24 channels
| - 0xde: YM2610B extended - 19 channels | - 0xde: YM2610B extended - 19 channels
| - 0xe0: QSound - 19 channels | - 0xe0: QSound - 19 channels
| - 0xfc: Pong - 1 channel | - 0xfc: Pong - 1 channel

View file

@ -143,7 +143,7 @@ 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)); 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<0) chan[i].freq=0;
if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].freq>65535) chan[i].freq=65535;
ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0); ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0)|((s->depth==DIV_SAMPLE_DEPTH_MULAW)?0x08:0);
if (chan[i].keyOn) { if (chan[i].keyOn) {
unsigned int bank=0; unsigned int bank=0;
unsigned int start=0; unsigned int start=0;
@ -174,7 +174,6 @@ void DivPlatformC140::tick(bool sysTick) {
chan[i].volChangedL=true; chan[i].volChangedL=true;
chan[i].volChangedR=true; chan[i].volChangedR=true;
} }
chan[i].keyOn=false;
} }
if (chan[i].keyOff) { if (chan[i].keyOff) {
chan[i].keyOff=false; chan[i].keyOff=false;
@ -184,7 +183,10 @@ void DivPlatformC140::tick(bool sysTick) {
rWrite(0x03+(i<<4),chan[i].freq&0xff); rWrite(0x03+(i<<4),chan[i].freq&0xff);
chan[i].freqChanged=false; chan[i].freqChanged=false;
} }
rWrite(0x05+(i<<4),ctrl); if (chan[i].keyOn) {
rWrite(0x05+(i<<4),ctrl);
chan[i].keyOn=false;
}
} }
} }
} }
@ -437,10 +439,20 @@ void DivPlatformC140::renderSamples(int sysID) {
break; break;
} }
if (memPos+length>=(getSampleMemCapacity())) { if (memPos+length>=(getSampleMemCapacity())) {
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,(getSampleMemCapacity())-memPos); if (s->depth==DIV_SAMPLE_DEPTH_MULAW) {
} else {
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,(getSampleMemCapacity())-memPos);
}
logW("out of C140 memory for sample %d!",i); logW("out of C140 memory for sample %d!",i);
} else { } else {
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,length); if (s->depth==DIV_SAMPLE_DEPTH_MULAW) {
for (unsigned int i=0; i<length; i++) {
sampleMem[i+(memPos/sizeof(short))]=(s->dataMuLaw[i]<<8)^0xff00;
}
} else {
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,length);
}
} }
sampleOff[i]=memPos>>1; sampleOff[i]=memPos>>1;
sampleLoaded[i]=true; sampleLoaded[i]=true;

View file

@ -269,6 +269,9 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) {
case DIV_SAMPLE_DEPTH_VOX: case DIV_SAMPLE_DEPTH_VOX:
off=(offset+1)/2; off=(offset+1)/2;
break; break;
case DIV_SAMPLE_DEPTH_MULAW:
off=offset;
break;
case DIV_SAMPLE_DEPTH_16BIT: case DIV_SAMPLE_DEPTH_16BIT:
off=offset*2; off=offset*2;
break; break;
@ -316,6 +319,10 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) {
off=(offset+1)/2; off=(offset+1)/2;
len=(length+1)/2; len=(length+1)/2;
break; break;
case DIV_SAMPLE_DEPTH_MULAW:
off=offset;
len=length;
break;
case DIV_SAMPLE_DEPTH_16BIT: case DIV_SAMPLE_DEPTH_16BIT:
off=offset*2; off=offset*2;
len=length*2; len=length*2;
@ -365,6 +372,9 @@ int DivSample::getEndPosition(DivSampleDepth depth) {
case DIV_SAMPLE_DEPTH_VOX: case DIV_SAMPLE_DEPTH_VOX:
off=lengthVOX; off=lengthVOX;
break; break;
case DIV_SAMPLE_DEPTH_MULAW:
off=lengthMuLaw;
break;
case DIV_SAMPLE_DEPTH_16BIT: case DIV_SAMPLE_DEPTH_16BIT:
off=length16; off=length16;
break; break;
@ -538,6 +548,12 @@ bool DivSample::initInternal(DivSampleDepth d, int count) {
dataVOX=new unsigned char[lengthVOX]; dataVOX=new unsigned char[lengthVOX];
memset(dataVOX,0,lengthVOX); memset(dataVOX,0,lengthVOX);
break; break;
case DIV_SAMPLE_DEPTH_MULAW: // 8-bit µ-law
if (dataMuLaw!=NULL) delete[] dataMuLaw;
lengthMuLaw=count;
dataMuLaw=new unsigned char[(count+4095)&(~0xfff)];
memset(dataMuLaw,0,(count+4095)&(~0xfff));
break;
case DIV_SAMPLE_DEPTH_16BIT: // 16-bit case DIV_SAMPLE_DEPTH_16BIT: // 16-bit
if (data16!=NULL) delete[] data16; if (data16!=NULL) delete[] data16;
length16=count*2; length16=count*2;
@ -1155,6 +1171,13 @@ void DivSample::render(unsigned int formatMask) {
case DIV_SAMPLE_DEPTH_VOX: // VOX case DIV_SAMPLE_DEPTH_VOX: // VOX
oki_decode(dataVOX,data16,samples); oki_decode(dataVOX,data16,samples);
break; break;
case DIV_SAMPLE_DEPTH_MULAW: // 8-bit µ-law PCM
for (unsigned int i=0; i<samples; i++) {
unsigned int s=(dataMuLaw[i]^0xff);
s=0x3f800000+(((s<<24)&0x80000000)|((s&0x7f)<<19));
data16[i]=(short)((*(float*)&s)*128.0f);
}
break;
default: default:
return; return;
} }
@ -1233,6 +1256,16 @@ void DivSample::render(unsigned int formatMask) {
if (!initInternal(DIV_SAMPLE_DEPTH_VOX,samples)) return; if (!initInternal(DIV_SAMPLE_DEPTH_VOX,samples)) return;
oki_encode(data16,dataVOX,samples); oki_encode(data16,dataVOX,samples);
} }
if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_MULAW)) { // µ-law
if (!initInternal(DIV_SAMPLE_DEPTH_MULAW,samples)) return;
for (unsigned int i=0; i<samples; i++) {
float s=(float)-data16[i];
s/=32768.0f;
unsigned int si=*(unsigned int*)&s;
si-=0x3f800000;
dataMuLaw[i]=(((si&0x80000000)>>24)|((si&0x03f80000)>>19))^0xff;
}
}
} }
void* DivSample::getCurBuf() { void* DivSample::getCurBuf() {
@ -1255,6 +1288,8 @@ void* DivSample::getCurBuf() {
return dataBRR; return dataBRR;
case DIV_SAMPLE_DEPTH_VOX: case DIV_SAMPLE_DEPTH_VOX:
return dataVOX; return dataVOX;
case DIV_SAMPLE_DEPTH_MULAW:
return dataMuLaw;
case DIV_SAMPLE_DEPTH_16BIT: case DIV_SAMPLE_DEPTH_16BIT:
return data16; return data16;
default: default:
@ -1283,6 +1318,8 @@ unsigned int DivSample::getCurBufLen() {
return lengthBRR; return lengthBRR;
case DIV_SAMPLE_DEPTH_VOX: case DIV_SAMPLE_DEPTH_VOX:
return lengthVOX; return lengthVOX;
case DIV_SAMPLE_DEPTH_MULAW:
return lengthMuLaw;
case DIV_SAMPLE_DEPTH_16BIT: case DIV_SAMPLE_DEPTH_16BIT:
return length16; return length16;
default: default:
@ -1392,4 +1429,5 @@ DivSample::~DivSample() {
if (dataB) delete[] dataB; if (dataB) delete[] dataB;
if (dataBRR) delete[] dataBRR; if (dataBRR) delete[] dataBRR;
if (dataVOX) delete[] dataVOX; if (dataVOX) delete[] dataVOX;
if (dataMuLaw) delete[] dataMuLaw;
} }

View file

@ -43,6 +43,7 @@ enum DivSampleDepth: unsigned char {
DIV_SAMPLE_DEPTH_8BIT=8, DIV_SAMPLE_DEPTH_8BIT=8,
DIV_SAMPLE_DEPTH_BRR=9, DIV_SAMPLE_DEPTH_BRR=9,
DIV_SAMPLE_DEPTH_VOX=10, DIV_SAMPLE_DEPTH_VOX=10,
DIV_SAMPLE_DEPTH_MULAW=11,
DIV_SAMPLE_DEPTH_16BIT=16, DIV_SAMPLE_DEPTH_16BIT=16,
DIV_SAMPLE_DEPTH_MAX // boundary for sample depth DIV_SAMPLE_DEPTH_MAX // boundary for sample depth
}; };
@ -108,6 +109,7 @@ struct DivSample {
// - 8: 8-bit PCM // - 8: 8-bit PCM
// - 9: BRR (SNES) // - 9: BRR (SNES)
// - 10: VOX ADPCM // - 10: VOX ADPCM
// - 11: 8-bit µ-law PCM
// - 16: 16-bit PCM // - 16: 16-bit PCM
DivSampleDepth depth; DivSampleDepth depth;
bool loop, brrEmphasis, dither; bool loop, brrEmphasis, dither;
@ -130,8 +132,9 @@ struct DivSample {
unsigned char* dataB; // 6 unsigned char* dataB; // 6
unsigned char* dataBRR; // 9 unsigned char* dataBRR; // 9
unsigned char* dataVOX; // 10 unsigned char* dataVOX; // 10
unsigned char* dataMuLaw; // 11
unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthBRR, lengthVOX; unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthBRR, lengthVOX, lengthMuLaw;
unsigned int samples; unsigned int samples;
@ -337,6 +340,7 @@ struct DivSample {
dataB(NULL), dataB(NULL),
dataBRR(NULL), dataBRR(NULL),
dataVOX(NULL), dataVOX(NULL),
dataMuLaw(NULL),
length8(0), length8(0),
length16(0), length16(0),
length1(0), length1(0),
@ -347,6 +351,7 @@ struct DivSample {
lengthB(0), lengthB(0),
lengthBRR(0), lengthBRR(0),
lengthVOX(0), lengthVOX(0),
lengthMuLaw(0),
samples(0) { samples(0) {
for (int i=0; i<DIV_MAX_CHIPS; i++) { for (int i=0; i<DIV_MAX_CHIPS; i++) {
for (int j=0; j<DIV_MAX_SAMPLE_TYPE; j++) { for (int j=0; j<DIV_MAX_SAMPLE_TYPE; j++) {

View file

@ -1872,10 +1872,9 @@ void DivEngine::registerSystems() {
{} {}
); );
// TODO: Custom sample format
sysDefs[DIV_SYSTEM_C140]=new DivSysDef( sysDefs[DIV_SYSTEM_C140]=new DivSysDef(
"Namco C140", NULL, 0xfe/*Placeholder*/, 0, 24, false, true, 0x161, false, 1U<<DIV_SAMPLE_DEPTH_8BIT, "Namco C140", NULL, 0xce, 0, 24, false, true, 0x161, false, (1U<<DIV_SAMPLE_DEPTH_MULAW)|(1U<<DIV_SAMPLE_DEPTH_8BIT),
"Namco's first PCM chip arrived from 1987.", "Namco's first PCM chip from 1987.",
{"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", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24"}, {"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", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24"},
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"}, {"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_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_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},

View file

@ -192,7 +192,7 @@ const char* sampleDepths[DIV_SAMPLE_DEPTH_MAX]={
"8-bit PCM", "8-bit PCM",
"BRR", "BRR",
"VOX", "VOX",
NULL, "8-bit µ-law PCM",
NULL, NULL,
NULL, NULL,
NULL, NULL,

View file

@ -1608,7 +1608,7 @@ void FurnaceGUI::drawSampleEdit() {
} }
posY=(0.5-pos.y/rectSize.y)*((sample->depth==DIV_SAMPLE_DEPTH_8BIT)?255:32767); posY=(0.5-pos.y/rectSize.y)*((sample->depth==DIV_SAMPLE_DEPTH_8BIT)?255:32767);
if (posX>=0) { if (posX>=0) {
statusBar2=fmt::sprintf("(%d, %d)",posX,posY); statusBar2=fmt::sprintf("(%d, %d) $%.2x",posX,posY,((unsigned char*)sample->getCurBuf())[posX]);
} }
} }