diff --git a/papers/format.md b/papers/format.md index 46bb4c1fa..9eef48522 100644 --- a/papers/format.md +++ b/papers/format.md @@ -219,6 +219,7 @@ size | description | - 0xcb: Casio PV-1000 - 3 channels | - 0xcc: K053260 - 4 channels | - 0xcd: TED - 2 channels + | - 0xce: Namco C140 - 24 channels | - 0xde: YM2610B extended - 19 channels | - 0xe0: QSound - 19 channels | - 0xfc: Pong - 1 channel diff --git a/src/engine/platform/c140.cpp b/src/engine/platform/c140.cpp index a7a3b162b..55f4983ad 100644 --- a/src/engine/platform/c140.cpp +++ b/src/engine/platform/c140.cpp @@ -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)); 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); + 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; @@ -174,7 +174,6 @@ void DivPlatformC140::tick(bool sysTick) { chan[i].volChangedL=true; chan[i].volChangedR=true; } - chan[i].keyOn=false; } if (chan[i].keyOff) { chan[i].keyOff=false; @@ -184,7 +183,10 @@ void DivPlatformC140::tick(bool sysTick) { rWrite(0x03+(i<<4),chan[i].freq&0xff); 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; } 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); } else { - memcpy(sampleMem+(memPos/sizeof(short)),s->data16,length); + if (s->depth==DIV_SAMPLE_DEPTH_MULAW) { + for (unsigned int i=0; idataMuLaw[i]<<8)^0xff00; + } + } else { + memcpy(sampleMem+(memPos/sizeof(short)),s->data16,length); + } } sampleOff[i]=memPos>>1; sampleLoaded[i]=true; diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 17cd235c1..127f3eff6 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -269,6 +269,9 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) { case DIV_SAMPLE_DEPTH_VOX: off=(offset+1)/2; break; + case DIV_SAMPLE_DEPTH_MULAW: + off=offset; + break; case DIV_SAMPLE_DEPTH_16BIT: off=offset*2; break; @@ -316,6 +319,10 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) { off=(offset+1)/2; len=(length+1)/2; break; + case DIV_SAMPLE_DEPTH_MULAW: + off=offset; + len=length; + break; case DIV_SAMPLE_DEPTH_16BIT: off=offset*2; len=length*2; @@ -365,6 +372,9 @@ int DivSample::getEndPosition(DivSampleDepth depth) { case DIV_SAMPLE_DEPTH_VOX: off=lengthVOX; break; + case DIV_SAMPLE_DEPTH_MULAW: + off=lengthMuLaw; + break; case DIV_SAMPLE_DEPTH_16BIT: off=length16; break; @@ -538,6 +548,12 @@ bool DivSample::initInternal(DivSampleDepth d, int count) { dataVOX=new unsigned char[lengthVOX]; memset(dataVOX,0,lengthVOX); 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 if (data16!=NULL) delete[] data16; length16=count*2; @@ -1155,6 +1171,13 @@ void DivSample::render(unsigned int formatMask) { case DIV_SAMPLE_DEPTH_VOX: // VOX oki_decode(dataVOX,data16,samples); break; + case DIV_SAMPLE_DEPTH_MULAW: // 8-bit µ-law PCM + for (unsigned int i=0; i>24)|((si&0x03f80000)>>19))^0xff; + } + } } void* DivSample::getCurBuf() { @@ -1255,6 +1288,8 @@ void* DivSample::getCurBuf() { return dataBRR; case DIV_SAMPLE_DEPTH_VOX: return dataVOX; + case DIV_SAMPLE_DEPTH_MULAW: + return dataMuLaw; case DIV_SAMPLE_DEPTH_16BIT: return data16; default: @@ -1283,6 +1318,8 @@ unsigned int DivSample::getCurBufLen() { return lengthBRR; case DIV_SAMPLE_DEPTH_VOX: return lengthVOX; + case DIV_SAMPLE_DEPTH_MULAW: + return lengthMuLaw; case DIV_SAMPLE_DEPTH_16BIT: return length16; default: @@ -1392,4 +1429,5 @@ DivSample::~DivSample() { if (dataB) delete[] dataB; if (dataBRR) delete[] dataBRR; if (dataVOX) delete[] dataVOX; + if (dataMuLaw) delete[] dataMuLaw; } diff --git a/src/engine/sample.h b/src/engine/sample.h index ce1bf1fa2..bbf90d4f5 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -43,6 +43,7 @@ enum DivSampleDepth: unsigned char { DIV_SAMPLE_DEPTH_8BIT=8, DIV_SAMPLE_DEPTH_BRR=9, DIV_SAMPLE_DEPTH_VOX=10, + DIV_SAMPLE_DEPTH_MULAW=11, DIV_SAMPLE_DEPTH_16BIT=16, DIV_SAMPLE_DEPTH_MAX // boundary for sample depth }; @@ -108,6 +109,7 @@ struct DivSample { // - 8: 8-bit PCM // - 9: BRR (SNES) // - 10: VOX ADPCM + // - 11: 8-bit µ-law PCM // - 16: 16-bit PCM DivSampleDepth depth; bool loop, brrEmphasis, dither; @@ -130,8 +132,9 @@ struct DivSample { unsigned char* dataB; // 6 unsigned char* dataBRR; // 9 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; @@ -337,6 +340,7 @@ struct DivSample { dataB(NULL), dataBRR(NULL), dataVOX(NULL), + dataMuLaw(NULL), length8(0), length16(0), length1(0), @@ -347,6 +351,7 @@ struct DivSample { lengthB(0), lengthBRR(0), lengthVOX(0), + lengthMuLaw(0), samples(0) { for (int i=0; idepth==DIV_SAMPLE_DEPTH_8BIT)?255:32767); if (posX>=0) { - statusBar2=fmt::sprintf("(%d, %d)",posX,posY); + statusBar2=fmt::sprintf("(%d, %d) $%.2x",posX,posY,((unsigned char*)sample->getCurBuf())[posX]); } }