void RareSnesScanner::SearchForRareSnesFromARAM (RawFile* file) { RareSnesVersion version = NONE; UINT ofsSongLoadASM; UINT ofsVCmdExecASM; UINT addrSeqHeader; UINT addrVCmdTable; wstring name = RawFile::removeExtFromPath(file->GetFileName()); if (file->SearchBytePattern(ptnSongLoadDKC2, ofsSongLoadASM)) { addrSeqHeader = file->GetShort(file->GetByte(ofsSongLoadASM + 8)); } else if (file->SearchBytePattern(ptnSongLoadDKC, ofsSongLoadASM) && file->GetShort(ofsSongLoadASM + 13) == file->GetShort(ofsSongLoadASM + 8) + 1) { addrSeqHeader = file->GetShort(ofsSongLoadASM + 8); } else { return; } if (file->SearchBytePattern(ptnVCmdExecDKC2, ofsVCmdExecASM)) { addrVCmdTable = file->GetShort(ofsVCmdExecASM + 10); if (file->GetShort(addrVCmdTable + (0x0c * 2)) != 0) { if (file->GetShort(addrVCmdTable + (0x11 * 2)) != 0) { version = WNRN; } else { version = DKC2; } } else { version = KI; } } else if (file->SearchBytePattern(ptnVCmdExecDKC, ofsVCmdExecASM)) { addrVCmdTable = file->GetShort(ofsVCmdExecASM + 12); version = DKC; } else { return; } RareSnesSeq* newSeq = new RareSnesSeq(file, version, addrSeqHeader, name); if (!newSeq->LoadVGMFile()) { delete newSeq; return; } }
void RareSnesScanner::SearchForRareSnesFromARAM(RawFile *file) { RareSnesVersion version = RARESNES_NONE; uint32_t ofsSongLoadASM; uint32_t ofsVCmdExecASM; uint32_t addrSeqHeader; uint32_t addrVCmdTable; wstring name = file->tag.HasTitle() ? file->tag.title : RawFile::removeExtFromPath(file->GetFileName()); // find a sequence if (file->SearchBytePattern(ptnSongLoadDKC2, ofsSongLoadASM)) { addrSeqHeader = file->GetShort(file->GetByte(ofsSongLoadASM + 8)); } else if (file->SearchBytePattern(ptnSongLoadDKC, ofsSongLoadASM) && file->GetShort(ofsSongLoadASM + 13) == file->GetShort(ofsSongLoadASM + 8) + 1) { addrSeqHeader = file->GetShort(ofsSongLoadASM + 8); } else { return; } // guess engine version if (file->SearchBytePattern(ptnVCmdExecDKC2, ofsVCmdExecASM)) { addrVCmdTable = file->GetShort(ofsVCmdExecASM + 10); if (file->GetShort(addrVCmdTable + (0x0c * 2)) != 0) { if (file->GetShort(addrVCmdTable + (0x11 * 2)) != 0) { version = RARESNES_WNRN; } else { version = RARESNES_DKC2; } } else { version = RARESNES_KI; } } else if (file->SearchBytePattern(ptnVCmdExecDKC, ofsVCmdExecASM)) { addrVCmdTable = file->GetShort(ofsVCmdExecASM + 12); version = RARESNES_DKC; } else { return; } // load sequence RareSnesSeq *newSeq = new RareSnesSeq(file, version, addrSeqHeader, name); if (!newSeq->LoadVGMFile()) { delete newSeq; return; } // Rare engine has a instrument # <--> SRCN # table, find it uint32_t ofsReadSRCNASM; if (!file->SearchBytePattern(ptnReadSRCNTable, ofsReadSRCNASM)) { return; } uint32_t addrSRCNTable = file->GetShort(ofsReadSRCNASM + 5); if (addrSRCNTable + 0x100 > 0x10000) { return; } // find DIR address uint32_t ofsSetDIRASM; if (!file->SearchBytePattern(ptnLoadDIR, ofsSetDIRASM)) { return; } uint32_t spcDirAddr = file->GetByte(ofsSetDIRASM + 4) << 8; // scan SRCN table RareSnesInstrSet *newInstrSet = new RareSnesInstrSet(file, addrSRCNTable, spcDirAddr, newSeq->instrUnityKeyHints, newSeq->instrPitchHints, newSeq->instrADSRHints); if (!newInstrSet->LoadVGMFile()) { delete newInstrSet; return; } // get SRCN # range uint8_t maxSRCN = 0; std::vector<uint8_t> usedSRCNs; const std::vector<uint8_t> &availInstruments = newInstrSet->GetAvailableInstruments(); for (std::vector<uint8_t>::const_iterator itr = availInstruments.begin(); itr != availInstruments.end(); ++itr) { uint8_t inst = (*itr); uint8_t srcn = file->GetByte(addrSRCNTable + inst); if (maxSRCN < srcn) { maxSRCN = srcn; } std::vector<uint8_t>::iterator itrSRCN = find(usedSRCNs.begin(), usedSRCNs.end(), srcn); if (itrSRCN == usedSRCNs.end()) { usedSRCNs.push_back(srcn); } } std::sort(usedSRCNs.begin(), usedSRCNs.end()); // load BRR samples SNESSampColl *newSampColl = new SNESSampColl(RareSnesFormat::name, file, spcDirAddr, usedSRCNs); if (!newSampColl->LoadVGMFile()) { delete newSampColl; return; } }
bool RareSnesTrack::ReadEvent(void) { RareSnesSeq* parentSeq = (RareSnesSeq*)this->parentSeq; uint32_t beginOffset = curOffset; if (curOffset >= 0x10000) { return false; } bool bWriteGenericEventAsTextEventTmp; uint8_t statusByte = GetByte(curOffset++); uint8_t newMidiVol, newMidiPan; bool bContinue = true; wstringstream desc; if (statusByte >= 0x80) { uint8_t noteByte = statusByte; // check for "reuse last key" if (noteByte == 0xe1) { noteByte = altNoteByte2; } else if (noteByte >= 0xe0) { noteByte = altNoteByte1; } uint8_t key = noteByte - 0x81; uint8_t spcKey = min(max(noteByte - 0x80 + 36 + spcTranspose, 0), 0x7f); uint16_t dur; if (defNoteDur != 0) { dur = defNoteDur; } else { if (useLongDur) { dur = GetShortBE(curOffset); curOffset += 2; } else { dur = GetByte(curOffset++); } } if (noteByte == 0x80) { //wostringstream ssTrace; //ssTrace << L"Rest: " << dur << L" " << defNoteDur << L" " << (useLongDur ? L"L" : L"S") << std::endl; //OutputDebugString(ssTrace.str().c_str()); AddRest(beginOffset, curOffset-beginOffset, dur); } else { // a note, add hints for instrument if (parentSeq->instrUnityKeyHints.find(spcInstr) == parentSeq->instrUnityKeyHints.end()) { parentSeq->instrUnityKeyHints[spcInstr] = spcTransposeAbs; parentSeq->instrPitchHints[spcInstr] = (int16_t) round(GetTuningInSemitones(spcTuning) * 100.0); } if (parentSeq->instrADSRHints.find(spcInstr) == parentSeq->instrADSRHints.end()) { parentSeq->instrADSRHints[spcInstr] = spcADSR; } spcNotePitch = RareSnesSeq::NOTE_PITCH_TABLE[spcKey]; spcNotePitch = (spcNotePitch * (1024 + spcTuning) + (spcTuning < 0 ? 1023 : 0)) / 1024; //wostringstream ssTrace; //ssTrace << L"Note: " << key << L" " << dur << L" " << defNoteDur << L" " << (useLongDur ? L"L" : L"S") << L" P=" << spcNotePitch << std::endl; //OutputDebugString(ssTrace.str().c_str()); uint8_t vel = 127; AddNoteByDur(beginOffset, curOffset-beginOffset, key, vel, dur); AddTime(dur); } } else { RareSnesSeqEventType eventType = (RareSnesSeqEventType)0; map<uint8_t, RareSnesSeqEventType>::iterator pEventType = parentSeq->EventMap.find(statusByte); if (pEventType != parentSeq->EventMap.end()) { eventType = pEventType->second; } switch (eventType) { case EVENT_UNKNOWN0: desc << L"Event: 0x" << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)statusByte; EVENT_WITH_MIDITEXT_START AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); EVENT_WITH_MIDITEXT_END break; case EVENT_UNKNOWN1: { uint8_t arg1 = GetByte(curOffset++); desc << L"Event: 0x" << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)statusByte << std::dec << std::setfill(L' ') << std::setw(0) << L" Arg1: " << (int)arg1; EVENT_WITH_MIDITEXT_START AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); EVENT_WITH_MIDITEXT_END break; } case EVENT_UNKNOWN2: { uint8_t arg1 = GetByte(curOffset++); uint8_t arg2 = GetByte(curOffset++); desc << L"Event: 0x" << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)statusByte << std::dec << std::setfill(L' ') << std::setw(0) << L" Arg1: " << (int)arg1 << L" Arg2: " << (int)arg2; EVENT_WITH_MIDITEXT_START AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); EVENT_WITH_MIDITEXT_END break; } case EVENT_UNKNOWN3: { uint8_t arg1 = GetByte(curOffset++); uint8_t arg2 = GetByte(curOffset++); uint8_t arg3 = GetByte(curOffset++); desc << L"Event: 0x" << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)statusByte << std::dec << std::setfill(L' ') << std::setw(0) << L" Arg1: " << (int)arg1 << L" Arg2: " << (int)arg2 << L" Arg3: " << (int)arg3; EVENT_WITH_MIDITEXT_START AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); EVENT_WITH_MIDITEXT_END break; } case EVENT_UNKNOWN4: { uint8_t arg1 = GetByte(curOffset++); uint8_t arg2 = GetByte(curOffset++); uint8_t arg3 = GetByte(curOffset++); uint8_t arg4 = GetByte(curOffset++); desc << L"Event: 0x" << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)statusByte << std::dec << std::setfill(L' ') << std::setw(0) << L" Arg1: " << (int)arg1 << L" Arg2: " << (int)arg2 << L" Arg3: " << (int)arg3 << L" Arg4: " << (int)arg4; EVENT_WITH_MIDITEXT_START AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); EVENT_WITH_MIDITEXT_END break; } case EVENT_END: AddEndOfTrack(beginOffset, curOffset-beginOffset); bContinue = false; //loaded = true; break; case EVENT_PROGCHANGE: { uint8_t newProg = GetByte(curOffset++); spcInstr = newProg; AddProgramChange(beginOffset, curOffset-beginOffset, newProg, true); break; } case EVENT_PROGCHANGEVOL: { uint8_t newProg = GetByte(curOffset++); int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); spcInstr = newProg; spcVolL = newVolL; spcVolR = newVolR; AddProgramChange(beginOffset, curOffset-beginOffset, newProg, true, L"Program Change, Volume"); AddVolLRNoItem(spcVolL, spcVolR); break; } case EVENT_VOLLR: { int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); spcVolL = newVolL; spcVolR = newVolR; AddVolLR(beginOffset, curOffset-beginOffset, spcVolL, spcVolR, L"Volume L/R"); break; } case EVENT_VOLCENTER: { int8_t newVol = (int8_t) GetByte(curOffset++); spcVolL = newVol; spcVolR = newVol; AddVolLR(beginOffset, curOffset-beginOffset, spcVolL, spcVolR, L"Volume"); break; } case EVENT_GOTO: { uint16_t dest = GetShort(curOffset); curOffset += 2; desc << L"Destination: $" << std::hex << std::setfill(L'0') << std::setw(4) << std::uppercase << (int)dest; uint32_t length = curOffset - beginOffset; curOffset = dest; if (!IsOffsetUsed(dest) || rptNestLevel != 0) // nest level check is required for Stickerbrush Symphony AddGenericEvent(beginOffset, length, L"Jump", desc.str().c_str(), CLR_LOOPFOREVER); else AddLoopForever(beginOffset, length, L"Jump"); break; } case EVENT_CALLNTIMES: { uint8_t times = GetByte(curOffset++); uint16_t dest = GetShort(curOffset); curOffset += 2; desc << L"Times: " << (int)times << L" Destination: $" << std::hex << std::setfill(L'0') << std::setw(4) << std::uppercase << (int)dest; AddGenericEvent(beginOffset, curOffset-beginOffset, (times == 1 ? L"Pattern Play" : L"Pattern Repeat"), desc.str().c_str(), CLR_LOOP, ICON_STARTREP); if (rptNestLevel == RARESNES_RPTNESTMAX) { pRoot->AddLogItem(new LogItem(L"Subroutine nest level overflow\n", LOG_LEVEL_ERR, L"RareSnesSeq")); bContinue = false; break; } rptRetnAddr[rptNestLevel] = curOffset; rptCount[rptNestLevel] = times; rptStart[rptNestLevel] = dest; rptNestLevel++; curOffset = dest; break; } case EVENT_CALLONCE: { uint16_t dest = GetShort(curOffset); curOffset += 2; desc << L"Destination: $" << std::hex << std::setfill(L'0') << std::setw(4) << std::uppercase << (int)dest; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Pattern Play", desc.str().c_str(), CLR_LOOP, ICON_STARTREP); if (rptNestLevel == RARESNES_RPTNESTMAX) { pRoot->AddLogItem(new LogItem(L"Subroutine nest level overflow\n", LOG_LEVEL_ERR, L"RareSnesSeq")); bContinue = false; break; } rptRetnAddr[rptNestLevel] = curOffset; rptCount[rptNestLevel] = 1; rptStart[rptNestLevel] = dest; rptNestLevel++; curOffset = dest; break; } case EVENT_RET: { AddGenericEvent(beginOffset, curOffset-beginOffset, L"End Pattern", desc.str().c_str(), CLR_TRACKEND, ICON_ENDREP); if (rptNestLevel == 0) { pRoot->AddLogItem(new LogItem(L"Subroutine nest level overflow\n", LOG_LEVEL_ERR, L"RareSnesSeq")); bContinue = false; break; } rptNestLevel--; rptCount[rptNestLevel] = (rptCount[rptNestLevel] - 1) & 0xff; if (rptCount[rptNestLevel] != 0) { // continue curOffset = rptStart[rptNestLevel]; rptNestLevel++; } else { // return curOffset = rptRetnAddr[rptNestLevel]; } break; } case EVENT_DEFDURON: { if (useLongDur) { defNoteDur = GetShortBE(curOffset); curOffset += 2; } else { defNoteDur = GetByte(curOffset++); } AddGenericEvent(beginOffset, curOffset-beginOffset, L"Default Duration On", desc.str().c_str(), CLR_DURNOTE, ICON_NOTE); break; } case EVENT_DEFDUROFF: defNoteDur = 0; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Default Duration Off", desc.str().c_str(), CLR_DURNOTE, ICON_NOTE); break; case EVENT_PITCHSLIDEUP: { curOffset += 5; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Pitch Slide Up", desc.str().c_str(), CLR_PITCHBEND, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_PITCHSLIDEDOWN: { curOffset += 5; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Pitch Slide Down", desc.str().c_str(), CLR_PITCHBEND, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_PITCHSLIDEOFF: EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Pitch Slide Off", desc.str().c_str(), CLR_PITCHBEND, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; case EVENT_TEMPO: { uint8_t newTempo = GetByte(curOffset++); parentSeq->tempo = newTempo; AddTempoBPM(beginOffset, curOffset-beginOffset, parentSeq->GetTempoInBPM()); break; } case EVENT_TEMPOADD: { int8_t deltaTempo = (int8_t) GetByte(curOffset++); parentSeq->tempo = (parentSeq->tempo + deltaTempo) & 0xff; AddTempoBPM(beginOffset, curOffset-beginOffset, parentSeq->GetTempoInBPM(), L"Tempo Add"); break; } case EVENT_VIBRATOSHORT: { curOffset += 3; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Vibrato (Short)", desc.str().c_str(), CLR_MODULATION, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_VIBRATOOFF: EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Vibrato Off", desc.str().c_str(), CLR_MODULATION, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; case EVENT_VIBRATO: { curOffset += 4; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Vibrato", desc.str().c_str(), CLR_MODULATION, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_TREMOLOOFF: EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Tremolo Off", desc.str().c_str(), CLR_MODULATION, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; case EVENT_TREMOLO: { curOffset += 4; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Tremolo", desc.str().c_str(), CLR_MODULATION, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_ADSR: { uint16_t newADSR = GetShortBE(curOffset); curOffset += 2; spcADSR = newADSR; desc << L"ADSR: " << std::hex << std::setfill(L'0') << std::setw(4) << std::uppercase << (int)newADSR; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"ADSR", desc.str().c_str(), CLR_ADSR, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_MASTVOL: { uint8_t newVol = GetByte(curOffset++); AddMasterVol(beginOffset, curOffset-beginOffset, newVol & 0x7f); break; } case EVENT_MASTVOLLR: { int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); int8_t newVol = min(abs(newVolL) + abs(newVolR), 255) / 2; // workaround: convert to mono AddMasterVol(beginOffset, curOffset-beginOffset, newVol, L"Master Volume L/R"); break; } case EVENT_TUNING: { int8_t newTuning = (int8_t) GetByte(curOffset++); spcTuning = newTuning; desc << L"Tuning: " << (int)newTuning << L" (" << (int)(GetTuningInSemitones(newTuning) * 100 + 0.5) << L" cents)"; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Tuning", desc.str().c_str(), CLR_PITCHBEND, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_TRANSPABS: // should be used for pitch correction of instrument { int8_t newTransp = (int8_t) GetByte(curOffset++); spcTranspose = spcTransposeAbs = newTransp; //AddTranspose(beginOffset, curOffset-beginOffset, 0, L"Transpose (Abs)"); // add event without MIDI event if (readMode == READMODE_ADD_TO_UI && !IsOffsetUsed(beginOffset)) AddEvent(new TransposeSeqEvent(this, newTransp, beginOffset, curOffset-beginOffset, L"Transpose (Abs)")); cKeyCorrection = SEQ_KEYOFS; break; } case EVENT_TRANSPREL: { int8_t deltaTransp = (int8_t) GetByte(curOffset++); spcTranspose = (spcTranspose + deltaTransp) & 0xff; //AddTranspose(beginOffset, curOffset-beginOffset, spcTransposeAbs - spcTranspose, L"Transpose (Rel)"); // add event without MIDI event if (readMode == READMODE_ADD_TO_UI && !IsOffsetUsed(beginOffset)) AddEvent(new TransposeSeqEvent(this, deltaTransp, beginOffset, curOffset-beginOffset, L"Transpose (Rel)")); cKeyCorrection += deltaTransp; break; } case EVENT_ECHOPARAM: { uint8_t newFeedback = GetByte(curOffset++); int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); parentSeq->midiReverb = min(abs(newVolL) + abs(newVolR), 255) / 2; // TODO: update MIDI reverb value for each tracks? desc << L"Feedback: " << (int)newFeedback << L" Volume: " << (int)newVolL << L", " << (int)newVolR; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Echo Param", desc.str().c_str(), CLR_REVERB, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_ECHOON: EVENT_WITH_MIDITEXT_START AddReverb(beginOffset, curOffset-beginOffset, parentSeq->midiReverb, L"Echo On"); EVENT_WITH_MIDITEXT_END break; case EVENT_ECHOOFF: EVENT_WITH_MIDITEXT_START AddReverb(beginOffset, curOffset-beginOffset, 0, L"Echo Off"); EVENT_WITH_MIDITEXT_END break; case EVENT_ECHOFIR: { uint8_t newFIR[8]; GetBytes(curOffset, 8, newFIR); curOffset += 8; desc << L"Filter: "; for (int iFIRIndex = 0; iFIRIndex < 8; iFIRIndex++) { if (iFIRIndex != 0) desc << L" "; desc << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)newFIR[iFIRIndex]; } EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Echo FIR", desc.str().c_str(), CLR_REVERB, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_NOISECLK: { uint8_t newCLK = GetByte(curOffset++); desc << L"CLK: " << (int)newCLK; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Noise Frequency", desc.str().c_str(), CLR_CHANGESTATE, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_NOISEON: EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Noise On", desc.str().c_str(), CLR_CHANGESTATE, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; case EVENT_NOISEOFF: EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Noise Off", desc.str().c_str(), CLR_CHANGESTATE, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; case EVENT_SETALTNOTE1: altNoteByte1 = GetByte(curOffset++); desc << L"Note: " << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)altNoteByte1; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Set Alt Note 1", desc.str().c_str(), CLR_CHANGESTATE, ICON_NOTE); break; case EVENT_SETALTNOTE2: altNoteByte2 = GetByte(curOffset++); desc << L"Note: " << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)altNoteByte2; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Set Alt Note 2", desc.str().c_str(), CLR_CHANGESTATE, ICON_NOTE); break; case EVENT_PITCHSLIDEDOWNSHORT: { curOffset += 4; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Pitch Slide Down (Short)", desc.str().c_str(), CLR_PITCHBEND, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_PITCHSLIDEUPSHORT: { curOffset += 4; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Pitch Slide Up (Short)", desc.str().c_str(), CLR_PITCHBEND, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_LONGDURON: useLongDur = true; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Long Duration On", desc.str().c_str(), CLR_DURNOTE, ICON_NOTE); break; case EVENT_LONGDUROFF: useLongDur = false; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Long Duration Off", desc.str().c_str(), CLR_DURNOTE, ICON_NOTE); break; case EVENT_SETVOLADSRPRESET1: { int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); uint16_t newADSR = GetShortBE(curOffset); curOffset += 2; parentSeq->presetVolL[0] = newVolL; parentSeq->presetVolR[0] = newVolR; parentSeq->presetADSR[0] = newADSR; // add event without MIDI events CalcVolPanFromVolLR(spcVolL, spcVolR, newMidiVol, newMidiPan); if (readMode == READMODE_ADD_TO_UI && !IsOffsetUsed(beginOffset)) AddEvent(new VolSeqEvent(this, newMidiVol, beginOffset, curOffset-beginOffset, L"Set Vol/ADSR Preset 1")); break; } case EVENT_SETVOLADSRPRESET2: { int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); uint16_t newADSR = GetShortBE(curOffset); curOffset += 2; parentSeq->presetVolL[1] = newVolL; parentSeq->presetVolR[1] = newVolR; parentSeq->presetADSR[1] = newADSR; // add event without MIDI events CalcVolPanFromVolLR(spcVolL, spcVolR, newMidiVol, newMidiPan); if (readMode == READMODE_ADD_TO_UI && !IsOffsetUsed(beginOffset)) AddEvent(new VolSeqEvent(this, newMidiVol, beginOffset, curOffset-beginOffset, L"Set Vol/ADSR Preset 2")); break; } case EVENT_SETVOLADSRPRESET3: { int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); uint16_t newADSR = GetShortBE(curOffset); curOffset += 2; parentSeq->presetVolL[2] = newVolL; parentSeq->presetVolR[2] = newVolR; parentSeq->presetADSR[2] = newADSR; // add event without MIDI events CalcVolPanFromVolLR(spcVolL, spcVolR, newMidiVol, newMidiPan); if (readMode == READMODE_ADD_TO_UI && !IsOffsetUsed(beginOffset)) AddEvent(new VolSeqEvent(this, newMidiVol, beginOffset, curOffset-beginOffset, L"Set Vol/ADSR Preset 3")); break; } case EVENT_SETVOLADSRPRESET4: { int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); uint16_t newADSR = GetShortBE(curOffset); curOffset += 2; parentSeq->presetVolL[3] = newVolL; parentSeq->presetVolR[3] = newVolR; parentSeq->presetADSR[3] = newADSR; // add event without MIDI events CalcVolPanFromVolLR(spcVolL, spcVolR, newMidiVol, newMidiPan); if (readMode == READMODE_ADD_TO_UI && !IsOffsetUsed(beginOffset)) AddEvent(new VolSeqEvent(this, newMidiVol, beginOffset, curOffset-beginOffset, L"Set Vol/ADSR Preset 4")); break; } case EVENT_SETVOLADSRPRESET5: { int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); uint16_t newADSR = GetShortBE(curOffset); curOffset += 2; parentSeq->presetVolL[4] = newVolL; parentSeq->presetVolR[4] = newVolR; parentSeq->presetADSR[4] = newADSR; // add event without MIDI events CalcVolPanFromVolLR(spcVolL, spcVolR, newMidiVol, newMidiPan); if (readMode == READMODE_ADD_TO_UI && !IsOffsetUsed(beginOffset)) AddEvent(new VolSeqEvent(this, newMidiVol, beginOffset, curOffset-beginOffset, L"Set Vol/ADSR Preset 5")); break; } case EVENT_GETVOLADSRPRESET1: spcVolL = parentSeq->presetVolL[0]; spcVolR = parentSeq->presetVolR[0]; EVENT_WITH_MIDITEXT_START AddVolLR(beginOffset, curOffset-beginOffset, spcVolL, spcVolR, L"Get Vol/ADSR Preset 1"); EVENT_WITH_MIDITEXT_END break; case EVENT_GETVOLADSRPRESET2: spcVolL = parentSeq->presetVolL[1]; spcVolR = parentSeq->presetVolR[1]; EVENT_WITH_MIDITEXT_START AddVolLR(beginOffset, curOffset-beginOffset, spcVolL, spcVolR, L"Get Vol/ADSR Preset 2"); EVENT_WITH_MIDITEXT_END break; case EVENT_GETVOLADSRPRESET3: spcVolL = parentSeq->presetVolL[2]; spcVolR = parentSeq->presetVolR[2]; EVENT_WITH_MIDITEXT_START AddVolLR(beginOffset, curOffset-beginOffset, spcVolL, spcVolR, L"Get Vol/ADSR Preset 3"); EVENT_WITH_MIDITEXT_END break; case EVENT_GETVOLADSRPRESET4: spcVolL = parentSeq->presetVolL[3]; spcVolR = parentSeq->presetVolR[3]; EVENT_WITH_MIDITEXT_START AddVolLR(beginOffset, curOffset-beginOffset, spcVolL, spcVolR, L"Get Vol/ADSR Preset 4"); EVENT_WITH_MIDITEXT_END break; case EVENT_GETVOLADSRPRESET5: spcVolL = parentSeq->presetVolL[4]; spcVolR = parentSeq->presetVolR[4]; EVENT_WITH_MIDITEXT_START AddVolLR(beginOffset, curOffset-beginOffset, spcVolL, spcVolR, L"Get Vol/ADSR Preset 5"); EVENT_WITH_MIDITEXT_END break; case EVENT_TIMERFREQ: { uint8_t newFreq = GetByte(curOffset++); parentSeq->timerFreq = newFreq; AddTempoBPM(beginOffset, curOffset-beginOffset, parentSeq->GetTempoInBPM(), L"Timer Frequency"); break; } //case EVENT_CONDJUMP: // break; //case EVENT_SETCONDJUMPPARAM: // break; case EVENT_RESETADSR: spcADSR = 0x8FE0; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reset ADSR", L"ADSR: 8FE0", CLR_ADSR, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; case EVENT_RESETADSRSOFT: spcADSR = 0x8EE0; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reset ADSR (Soft)", L"ADSR: 8EE0", CLR_ADSR, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; case EVENT_VOICEPARAMSHORT: { uint8_t newProg = GetByte(curOffset++); int8_t newTransp = (int8_t) GetByte(curOffset++); int8_t newTuning = (int8_t) GetByte(curOffset++); desc << L"Program Number: " << (int)newProg << L" Transpose: " << (int)newTransp << L" Tuning: " << (int)newTuning << L" (" << (int)(GetTuningInSemitones(newTuning) * 100 + 0.5) << L" cents)";; // instrument spcInstr = newProg; AddProgramChange(beginOffset, curOffset-beginOffset, newProg, true, L"Program Change, Transpose, Tuning"); // transpose spcTranspose = spcTransposeAbs = newTransp; cKeyCorrection = SEQ_KEYOFS; // tuning spcTuning = newTuning; break; } case EVENT_VOICEPARAM: { uint8_t newProg = GetByte(curOffset++); int8_t newTransp = (int8_t) GetByte(curOffset++); int8_t newTuning = (int8_t) GetByte(curOffset++); int8_t newVolL = (int8_t) GetByte(curOffset++); int8_t newVolR = (int8_t) GetByte(curOffset++); uint16_t newADSR = GetShortBE(curOffset); curOffset += 2; desc << L"Program Number: " << (int)newProg << L" Transpose: " << (int)newTransp << L" Tuning: " << (int)newTuning << L" (" << (int)(GetTuningInSemitones(newTuning) * 100 + 0.5) << L" cents)";; desc << L" Volume: " << (int)newVolL << L", " << (int)newVolR; desc << L" ADSR: " << std::hex << std::setfill(L'0') << std::setw(4) << std::uppercase << (int)newADSR; // instrument spcInstr = newProg; AddProgramChange(beginOffset, curOffset-beginOffset, newProg, true, L"Program Change, Transpose, Tuning, Volume L/R, ADSR"); // transpose spcTranspose = spcTransposeAbs = newTransp; cKeyCorrection = SEQ_KEYOFS; // tuning spcTuning = newTuning; // volume spcVolL = newVolL; spcVolR = newVolR; AddVolLRNoItem(spcVolL, spcVolR); // ADSR spcADSR = newADSR; break; } case EVENT_ECHODELAY: { uint8_t newEDL = GetByte(curOffset++); desc << L"Delay: " << (int)newEDL; EVENT_WITH_MIDITEXT_START AddGenericEvent(beginOffset, curOffset-beginOffset, L"Echo Delay", desc.str().c_str(), CLR_REVERB, ICON_CONTROL); EVENT_WITH_MIDITEXT_END break; } case EVENT_SETVOLPRESETS: { int8_t newVolL1 = (int8_t) GetByte(curOffset++); int8_t newVolR1 = (int8_t) GetByte(curOffset++); int8_t newVolL2 = (int8_t) GetByte(curOffset++); int8_t newVolR2 = (int8_t) GetByte(curOffset++); parentSeq->presetVolL[0] = newVolL1; parentSeq->presetVolR[0] = newVolR1; parentSeq->presetVolL[1] = newVolL2; parentSeq->presetVolR[1] = newVolR2; // add event without MIDI events CalcVolPanFromVolLR(parentSeq->presetVolL[0], parentSeq->presetVolR[0], newMidiVol, newMidiPan); if (readMode == READMODE_ADD_TO_UI && !IsOffsetUsed(beginOffset)) AddEvent(new VolSeqEvent(this, newMidiVol, beginOffset, curOffset-beginOffset, L"Set Volume Preset")); break; } case EVENT_GETVOLPRESET1: spcVolL = parentSeq->presetVolL[0]; spcVolR = parentSeq->presetVolR[0]; AddVolLR(beginOffset, curOffset-beginOffset, spcVolL, spcVolR, L"Get Volume Preset 1"); break; case EVENT_GETVOLPRESET2: spcVolL = parentSeq->presetVolL[1]; spcVolR = parentSeq->presetVolR[1]; AddVolLR(beginOffset, curOffset-beginOffset, spcVolL, spcVolR, L"Get Volume Preset 2"); break; case EVENT_LFOOFF: if (readMode == READMODE_ADD_TO_UI && !IsOffsetUsed(beginOffset)) AddEvent(new ModulationSeqEvent(this, 0, beginOffset, curOffset-beginOffset, L"Pitch Slide/Vibrato/Tremolo Off")); break; default: desc << L"Event: 0x" << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)statusByte; EVENT_WITH_MIDITEXT_START AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); EVENT_WITH_MIDITEXT_END pRoot->AddLogItem(new LogItem(wstring(L"Unknown Event - ") + desc.str(), LOG_LEVEL_ERR, wstring(L"RareSnesSeq"))); bContinue = false; break; } } //wostringstream ssTrace; //ssTrace << L"" << std::hex << std::setfill(L'0') << std::setw(8) << std::uppercase << beginOffset << L": " << std::setw(2) << (int)statusByte << L" -> " << std::setw(8) << curOffset << std::endl; //OutputDebugString(ssTrace.str().c_str()); return bContinue; }