diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index accdf6e3..d70f3a0b 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1314,7 +1314,7 @@ void DivEngine::registerSystems() { ); sysDefs[DIV_SYSTEM_PC98]=new DivSysDef( - "Yamaha YM2608 (OPNA)", NULL, 0x8e, 0, 16, true, true, 0, false, + "Yamaha YM2608 (OPNA)", NULL, 0x8e, 0, 16, true, true, 0x151, false, "OPN but twice the FM channels, stereo makes a come-back and has rhythm and ADPCM channels.", {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Square 1", "Square 2", "Square 3", "Kick", "Snare", "Top", "HiHat", "Tom", "Rim", "ADPCM"}, {"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "BD", "SD", "TP", "HH", "TM", "RM", "P"}, @@ -1326,7 +1326,7 @@ void DivEngine::registerSystems() { ); sysDefs[DIV_SYSTEM_PC98_EXT]=new DivSysDef( - "Yamaha YM2608 (OPNA) Extended Channel 3", NULL, 0xb7, 0, 19, true, true, 0, false, + "Yamaha YM2608 (OPNA) Extended Channel 3", NULL, 0xb7, 0, 19, true, true, 0x151, false, "OPN but twice the FM channels, stereo makes a come-back and has rhythm and ADPCM channels.\nthis one is in Extended Channel mode, which turns the second FM channel into four operators with independent notes/frequencies", {"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6", "Square 1", "Square 2", "Square 3", "Kick", "Snare", "Top", "HiHat", "Tom", "Rim", "ADPCM"}, {"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6", "S1", "S2", "S3", "BD", "SD", "TP", "HH", "TM", "RM", "P"}, @@ -1836,7 +1836,7 @@ void DivEngine::registerSystems() { ); sysDefs[DIV_SYSTEM_Y8950]=new DivSysDef( - "Yamaha Y8950", NULL, 0xb2, 0, 10, true, false, 0, false, + "Yamaha Y8950", NULL, 0xb2, 0, 10, true, false, 0x151, false, "like OPL but with an ADPCM channel.", {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9", "PCM"}, {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "PCM"}, @@ -1848,7 +1848,7 @@ void DivEngine::registerSystems() { ); sysDefs[DIV_SYSTEM_Y8950_DRUMS]=new DivSysDef( - "Yamaha Y8950 with drums", NULL, 0xb3, 0, 12, true, false, 0, false, + "Yamaha Y8950 with drums", NULL, 0xb3, 0, 12, true, false, 0x151, false, "the Y8950 chip, in drums mode.", {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM"}, {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH", "PCM"}, diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index dc6f8b8f..0941b6f9 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -167,6 +167,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write case DIV_SYSTEM_YM2610_EXT: case DIV_SYSTEM_YM2610_FULL_EXT: case DIV_SYSTEM_YM2610B_EXT: + // TODO: YM2610B channels 1 and 4 and ADPCM-B for (int i=0; i<2; i++) { // set SL and RR to highest w->writeC(8|baseAddr1); w->writeC(0x81+i); @@ -356,7 +357,6 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(0xd6+i); } break; - // TODO: it's 3:35am case DIV_SYSTEM_OPL: case DIV_SYSTEM_OPL_DRUMS: // disable envelope @@ -381,6 +381,31 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(0); } break; + case DIV_SYSTEM_Y8950: + case DIV_SYSTEM_Y8950_DRUMS: + // disable envelope + for (int i=0; i<6; i++) { + w->writeC(0x0b|baseAddr1); + w->writeC(0x80+i); + w->writeC(0x0f); + w->writeC(0x0b|baseAddr1); + w->writeC(0x88+i); + w->writeC(0x0f); + w->writeC(0x0b|baseAddr1); + w->writeC(0x90+i); + w->writeC(0x0f); + } + // key off + freq reset + for (int i=0; i<9; i++) { + w->writeC(0x0b|baseAddr1); + w->writeC(0xa0+i); + w->writeC(0); + w->writeC(0x0b|baseAddr1); + w->writeC(0xb0+i); + w->writeC(0); + } + // TODO: ADPCM + break; case DIV_SYSTEM_OPL2: case DIV_SYSTEM_OPL2_DRUMS: // disable envelope @@ -582,6 +607,21 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(write.addr&0xff); w->writeC(write.val); break; + case DIV_SYSTEM_PC98: + case DIV_SYSTEM_PC98_EXT: + switch (write.addr>>8) { + case 0: // port 0 + w->writeC(6|baseAddr1); + w->writeC(write.addr&0xff); + w->writeC(write.val); + break; + case 1: // port 1 + w->writeC(7|baseAddr1); + w->writeC(write.addr&0xff); + w->writeC(write.val); + break; + } + break; case DIV_SYSTEM_OPLL: case DIV_SYSTEM_OPLL_DRUMS: case DIV_SYSTEM_VRC7: @@ -629,6 +669,12 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(write.addr&0xff); w->writeC(write.val); break; + case DIV_SYSTEM_Y8950: + case DIV_SYSTEM_Y8950_DRUMS: + w->writeC(0x0c|baseAddr1); + w->writeC(write.addr&0xff); + w->writeC(write.val); + break; case DIV_SYSTEM_OPL2: case DIV_SYSTEM_OPL2_DRUMS: w->writeC(0x0a|baseAddr1); @@ -830,7 +876,9 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version) { bool writeDACSamples=false; bool writeNESSamples=false; bool writePCESamples=false; - DivDispatch* writeADPCM[2]={NULL,NULL}; + DivDispatch* writeADPCM_OPNA[2]={NULL,NULL}; + DivDispatch* writeADPCM_OPNB[2]={NULL,NULL}; + DivDispatch* writeADPCM_Y8950[2]={NULL,NULL}; int writeSegaPCM=0; DivDispatch* writeX1010[2]={NULL,NULL}; DivDispatch* writeQSound[2]={NULL,NULL}; @@ -940,11 +988,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version) { if (!hasOPNB) { hasOPNB=disCont[i].dispatch->chipClock; willExport[i]=true; - writeADPCM[0]=disCont[i].dispatch; + writeADPCM_OPNB[0]=disCont[i].dispatch; } else if (!(hasOPNB&0x40000000)) { isSecond[i]=true; willExport[i]=true; - writeADPCM[1]=disCont[i].dispatch; + writeADPCM_OPNB[1]=disCont[i].dispatch; hasOPNB|=0x40000000; howManyChips++; } @@ -1045,6 +1093,20 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version) { howManyChips++; } break; + case DIV_SYSTEM_PC98: + case DIV_SYSTEM_PC98_EXT: + if (!hasOPNA) { + hasOPNA=disCont[i].dispatch->chipClock; + willExport[i]=true; + writeADPCM_OPNA[0]=disCont[i].dispatch; + } else if (!(hasOPNA&0x40000000)) { + isSecond[i]=true; + willExport[i]=true; + writeADPCM_OPNA[1]=disCont[i].dispatch; + hasOPNA|=0x40000000; + howManyChips++; + } + break; case DIV_SYSTEM_OPLL: case DIV_SYSTEM_OPLL_DRUMS: case DIV_SYSTEM_VRC7: @@ -1125,6 +1187,20 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version) { howManyChips++; } break; + case DIV_SYSTEM_Y8950: + case DIV_SYSTEM_Y8950_DRUMS: + if (!hasY8950) { + hasY8950=disCont[i].dispatch->chipClock; + willExport[i]=true; + writeADPCM_Y8950[0]=disCont[i].dispatch; + } else if (!(hasY8950&0x40000000)) { + isSecond[i]=true; + willExport[i]=true; + writeADPCM_Y8950[1]=disCont[i].dispatch; + hasY8950|=0x40000000; + howManyChips++; + } + break; case DIV_SYSTEM_OPL2: case DIV_SYSTEM_OPL2_DRUMS: if (!hasOPL2) { @@ -1429,27 +1505,55 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version) { delete[] pcmMem; } + // ADPCM (OPNA) for (int i=0; i<2; i++) { - if (writeADPCM[i]!=NULL && writeADPCM[i]->getSampleMemUsage(0)>0) { + if (writeADPCM_OPNA[i]!=NULL && writeADPCM_OPNA[i]->getSampleMemUsage(0)>0) { w->writeC(0x67); w->writeC(0x66); - w->writeC(0x82); - w->writeI((writeADPCM[i]->getSampleMemUsage(0)+8)|(i*0x80000000)); - w->writeI(writeADPCM[i]->getSampleMemCapacity(0)); + w->writeC(0x81); + w->writeI((writeADPCM_OPNA[i]->getSampleMemUsage(0)+8)|(i*0x80000000)); + w->writeI(writeADPCM_OPNA[i]->getSampleMemCapacity(0)); w->writeI(0); - w->write(writeADPCM[i]->getSampleMem(0),writeADPCM[i]->getSampleMemUsage(0)); + w->write(writeADPCM_OPNA[i]->getSampleMem(0),writeADPCM_OPNA[i]->getSampleMemUsage(0)); } } + // ADPCM-A (OPNB) for (int i=0; i<2; i++) { - if (writeADPCM[i]!=NULL && writeADPCM[i]->getSampleMemUsage(1)>0) { + if (writeADPCM_OPNB[i]!=NULL && writeADPCM_OPNB[i]->getSampleMemUsage(0)>0) { + w->writeC(0x67); + w->writeC(0x66); + w->writeC(0x82); + w->writeI((writeADPCM_OPNB[i]->getSampleMemUsage(0)+8)|(i*0x80000000)); + w->writeI(writeADPCM_OPNB[i]->getSampleMemCapacity(0)); + w->writeI(0); + w->write(writeADPCM_OPNB[i]->getSampleMem(0),writeADPCM_OPNB[i]->getSampleMemUsage(0)); + } + } + + // ADPCM-B (OPNB) + for (int i=0; i<2; i++) { + if (writeADPCM_OPNB[i]!=NULL && writeADPCM_OPNB[i]->getSampleMemUsage(1)>0) { w->writeC(0x67); w->writeC(0x66); w->writeC(0x83); - w->writeI((writeADPCM[i]->getSampleMemUsage(1)+8)|(i*0x80000000)); - w->writeI(writeADPCM[i]->getSampleMemCapacity(1)); + w->writeI((writeADPCM_OPNB[i]->getSampleMemUsage(1)+8)|(i*0x80000000)); + w->writeI(writeADPCM_OPNB[i]->getSampleMemCapacity(1)); w->writeI(0); - w->write(writeADPCM[i]->getSampleMem(1),writeADPCM[i]->getSampleMemUsage(1)); + w->write(writeADPCM_OPNB[i]->getSampleMem(1),writeADPCM_OPNB[i]->getSampleMemUsage(1)); + } + } + + // ADPCM (Y8950) + for (int i=0; i<2; i++) { + if (writeADPCM_Y8950[i]!=NULL && writeADPCM_Y8950[i]->getSampleMemUsage(0)>0) { + w->writeC(0x67); + w->writeC(0x66); + w->writeC(0x88); + w->writeI((writeADPCM_Y8950[i]->getSampleMemUsage(0)+8)|(i*0x80000000)); + w->writeI(writeADPCM_Y8950[i]->getSampleMemCapacity(0)); + w->writeI(0); + w->write(writeADPCM_Y8950[i]->getSampleMem(0),writeADPCM_Y8950[i]->getSampleMemUsage(0)); } }