void CompileSnesTrack::AddInitialMidiEvents(int trackNum) { SeqTrack::AddInitialMidiEvents(trackNum); double volumeScale; AddProgramChangeNoItem(spcSRCN, true); AddVolNoItem(Convert7bitPercentVolValToStdMidiVal(spcVolume / 2)); AddPanNoItem(Convert7bitLinearPercentPanValToStdMidiVal((uint8_t)(spcPan + 0x80) / 2, &volumeScale)); AddExpressionNoItem(ConvertPercentAmpToStdMidiVal(volumeScale)); AddReverbNoItem(0); }
bool WDInstr::LoadInstr() { wostringstream strStr; ULONG j=0; long startAddress = 0; BOOL notSampleStart = false; //Read region data bool bSecondToLastRgn = 0; bool bLastRgn = 0; unsigned int k = 0; while (k*0x20 < unLength) { if (bSecondToLastRgn) bLastRgn = true; WDRgn* rgn = new WDRgn(this, k*0x20 + dwOffset); aRgns.push_back(rgn); rgn->AddSimpleItem(k*0x20 + dwOffset, 1, L"Stereo Region Flag"); rgn->AddSimpleItem(k*0x20 + 1 + dwOffset, 1, L"First/Last Region Flags"); rgn->AddSimpleItem(k*0x20 + 2 + dwOffset, 2, L"Unknown Flag"); rgn->AddSimpleItem(k*0x20 + 0x4 + dwOffset, 4, L"Sample Offset"); rgn->AddSimpleItem(k*0x20 + 0x8 + dwOffset, 4, L"Loop Start"); rgn->AddSimpleItem(k*0x20 + 0xC + dwOffset, 2, L"ADSR1"); rgn->AddSimpleItem(k*0x20 + 0xE + dwOffset, 2, L"ADSR2"); rgn->AddSimpleItem(k*0x20 + 0x12 + dwOffset, 1, L"Finetune"); rgn->AddSimpleItem(k*0x20 + 0x13 + dwOffset, 1, L"UnityKey"); rgn->AddSimpleItem(k*0x20 + 0x14 + dwOffset, 1, L"Key High"); rgn->AddSimpleItem(k*0x20 + 0x15 + dwOffset, 1, L"Velocity High"); rgn->AddSimpleItem(k*0x20 + 0x16 + dwOffset, 1, L"Attenuation"); rgn->AddSimpleItem(k*0x20 + 0x17 + dwOffset, 1, L"Pan"); rgn->bStereoRegion = GetByte(k*0x20 + dwOffset) & 0x1; rgn->bUnknownFlag2 = GetByte(k*0x20 + 2 + dwOffset) & 0x1; rgn->bFirstRegion = GetByte(k*0x20 + 1 + dwOffset) & 0x1; rgn->bLastRegion = (GetByte(k*0x20 + 1 + dwOffset) & 0x2) >> 1; //rgn->sample_offset = GetWord(k*0x20 + 0x4 + dwOffset); rgn->sampOffset = GetWord(k*0x20 + 0x4 + dwOffset) & 0xFFFFFFF0; //The & is there because FFX points to 0x----C offsets for some very odd reason rgn->loop.loopStart = GetWord(k*0x20 + 0x8 + dwOffset); rgn->ADSR1 = GetShort(k*0x20 + 0xC + dwOffset); rgn->ADSR2 = GetShort(k*0x20 + 0xE + dwOffset); rgn->fineTune = GetByte(k*0x20 + 0x12 + dwOffset); rgn->unityKey = 0x3A - GetByte(k*0x20 + 0x13 + dwOffset); rgn->keyHigh = GetByte(k*0x20 + 0x14 + dwOffset); rgn->velHigh = Convert7bitPercentVolValToStdMidiVal( GetByte(k*0x20 + 0x15 + dwOffset) ); BYTE vol = GetByte(k*0x20 + 0x16 + dwOffset); rgn->SetVolume((double)vol / 127.0); rgn->pan = (double)GetByte(k*0x20 + 0x17 + dwOffset); //need to convert if (rgn->pan == 255) rgn->pan = 1.0; else if (rgn->pan == 128) rgn->pan = 0; else if (rgn->pan == 192) rgn->pan = 0.5; else if (rgn->pan > 127) rgn->pan = (double)(rgn->pan-128)/(double)127; else rgn->pan = 0.5; rgn->fineTune = (short)ceil(((finetune_table[rgn->fineTune] - 0x10000) * 0.025766555011594949755217727389848) - 50); PSXConvADSR<WDRgn>(rgn, rgn->ADSR1, rgn->ADSR2, true); if (rgn->bLastRegion) { if (rgn->bStereoRegion) bSecondToLastRgn = true; else bLastRgn = true; } k++; } //First, do key and velocity ranges BYTE prevKeyHigh = 0; BYTE prevVelHigh = 0; for (UINT k=0; k<aRgns.size(); k++) { // Key Ranges if (((WDRgn*)aRgns[k])->bFirstRegion) //&& !instrument[i].region[k].bLastRegion) //used in ffx2 0049 YRP battle 1. check out first instrument, flags are weird aRgns[k]->keyLow = 0; else if (k > 0) { if (aRgns[k]->keyHigh == aRgns[k-1]->keyHigh) aRgns[k]->keyLow = aRgns[k-1]->keyLow;//hDLSFile.aInstrs.back()->aRgns.back()->usKeyLow; else aRgns[k]->keyLow = aRgns[k-1]->keyHigh+1; } else aRgns[k]->keyLow = 0; if (((WDRgn*)aRgns[k])->bLastRegion) aRgns[k]->keyHigh = 0x7F; // Velocity ranges if (aRgns[k]->velHigh == prevVelHigh) aRgns[k]->velLow = aRgns[k-1]->velLow; else aRgns[k]->velLow = prevVelHigh + 1; prevVelHigh = aRgns[k]->velHigh; if (k == 0) //if it's the first region of the instrument aRgns[k]->velLow = 0; else if (aRgns[k]->velHigh == aRgns[k-1]->velHigh) { aRgns[k]->velLow = aRgns[k-1]->velLow; aRgns[k]->velHigh = 0x7F; //FFX 0022, aka sight of spira, was giving me problems, hence this aRgns[k-1]->velHigh = 0x7F; //hDLSFile.aInstrs.back()->aRgns.back()->usVelHigh = 0x7F; } else if (aRgns[k-1]->velHigh == 0x7F) aRgns[k]->velLow = 0; else aRgns[k]->velLow = aRgns[k-1]->velHigh+1; } return TRUE; }
bool CompileSnesTrack::ReadEvent(void) { CompileSnesSeq* parentSeq = (CompileSnesSeq*)this->parentSeq; uint32_t beginOffset = curOffset; if (curOffset >= 0x10000) { return false; } uint8_t statusByte = GetByte(curOffset++); bool bContinue = true; std::wstringstream desc; CompileSnesSeqEventType eventType = (CompileSnesSeqEventType)0; std::map<uint8_t, CompileSnesSeqEventType>::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; AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); 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; AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); 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; AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); 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; AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); 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; AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); break; } case EVENT_UNKNOWN5: { uint8_t arg1 = GetByte(curOffset++); uint8_t arg2 = GetByte(curOffset++); uint8_t arg3 = GetByte(curOffset++); uint8_t arg4 = GetByte(curOffset++); uint8_t arg5 = 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 << L" Arg5: " << (int)arg5; AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); 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)) { AddGenericEvent(beginOffset, length, L"Jump", desc.str().c_str(), CLR_LOOPFOREVER); } else { bContinue = AddLoopForever(beginOffset, length, L"Jump"); } break; } case EVENT_LOOP_END: { uint8_t repeatNest = GetByte(curOffset++); uint16_t dest = GetShort(curOffset); curOffset += 2; desc << L"Nest Level: " << (int)repeatNest << L" Destination: $" << std::hex << std::setfill(L'0') << std::setw(4) << std::uppercase << (int)dest; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Repeat End", desc.str().c_str(), CLR_LOOP, ICON_ENDREP); repeatCount[repeatNest]--; if (repeatCount[repeatNest] != 0) { curOffset = dest; } break; } case EVENT_END: { AddEndOfTrack(beginOffset, curOffset-beginOffset); bContinue = false; break; } case EVENT_VIBRATO: { uint8_t envelopeIndex = GetByte(curOffset++); desc << L"Envelope Index: " << (int)envelopeIndex; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Vibrato", desc.str().c_str(), CLR_MODULATION, ICON_CONTROL); break; } case EVENT_PORTAMENTO_TIME: { uint8_t rate = GetByte(curOffset++); desc << L"Rate: " << (int)rate; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Portamento Time", desc.str().c_str(), CLR_PORTAMENTOTIME, ICON_CONTROL); break; } case EVENT_VOLUME: { uint8_t newVolume = GetByte(curOffset++); spcVolume = newVolume; uint8_t midiVolume = Convert7bitPercentVolValToStdMidiVal(spcVolume / 2); AddVol(beginOffset, curOffset - beginOffset, midiVolume); break; } case EVENT_VOLUME_ENVELOPE: { uint8_t envelopeIndex = GetByte(curOffset++); desc << L"Envelope Index: " << (int)envelopeIndex; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Volume Envelope", desc.str().c_str(), CLR_VOLUME, ICON_CONTROL); break; } case EVENT_TRANSPOSE: { int8_t delta = (int8_t)GetByte(curOffset++); spcTranspose += delta; AddTranspose(beginOffset, curOffset - beginOffset, spcTranspose, L"Transpose (Relative)"); break; } case EVENT_VOLUME_REL: { int8_t delta = (int8_t)GetByte(curOffset++); spcVolume += delta; uint8_t midiVolume = Convert7bitPercentVolValToStdMidiVal(spcVolume / 2); AddVol(beginOffset, curOffset - beginOffset, midiVolume, L"Volume (Relative)"); break; } case EVENT_NOTE: { bool rest = (statusByte == 0x00); uint8_t duration; bool hasDuration = ReadDurationBytes(curOffset, duration); if (hasDuration) { spcNoteDuration = duration; desc << L"Duration: " << (int)duration; } if (rest) { AddRest(beginOffset, curOffset - beginOffset, spcNoteDuration); } else { uint8_t noteNumber = statusByte - 1; AddNoteByDur(beginOffset, curOffset - beginOffset, noteNumber, 100, spcNoteDuration, hasDuration ? L"Note with Duration" : L"Note"); AddTime(spcNoteDuration); } break; } case EVENT_LOOP_COUNT: { uint8_t repeatNest = GetByte(curOffset++); uint8_t times = GetByte(curOffset++); int actualTimes = (times == 0) ? 256 : times; desc << L"Nest Level: " << (int)repeatNest << L" Times: " << actualTimes; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Loop Count", desc.str().c_str(), CLR_LOOP, ICON_STARTREP); repeatCount[repeatNest] = times; break; } case EVENT_FLAGS: { uint8_t flags = GetByte(curOffset++); spcFlags = flags; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Flags", desc.str().c_str(), CLR_CHANGESTATE, ICON_CONTROL); break; } case EVENT_TEMPO: { uint8_t newTempo = GetByte(curOffset++); spcTempo = newTempo; AddTempoBPM(beginOffset, curOffset - beginOffset, parentSeq->GetTempoInBPM(newTempo)); break; } case EVENT_TUNING: { int16_t newTuning; if (parentSeq->version == COMPILESNES_ALESTE || parentSeq->version == COMPILESNES_JAKICRUSH) { newTuning = (int8_t)GetByte(curOffset++); } else { newTuning = (int16_t)GetShort(curOffset); curOffset += 2; } desc << L"Pitch Register Delta: " << (int)newTuning; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Tuning", desc.str().c_str(), CLR_CHANGESTATE, ICON_CONTROL); break; } case EVENT_CALL: { 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); subReturnAddress = curOffset; curOffset = dest; break; } case EVENT_RET: { AddGenericEvent(beginOffset, curOffset - beginOffset, L"End Pattern", desc.str().c_str(), CLR_TRACKEND, ICON_ENDREP); curOffset = subReturnAddress; break; } case EVENT_PROGCHANGE: { uint8_t newProg = GetByte(curOffset++); AddProgramChange(beginOffset, curOffset - beginOffset, newProg, true); break; } case EVENT_ADSR: { uint8_t envelopeIndex = GetByte(curOffset++); desc << L"Envelope Index: " << (int)envelopeIndex; AddGenericEvent(beginOffset, curOffset - beginOffset, L"ADSR", desc.str().c_str(), CLR_VOLUME, ICON_CONTROL); break; } case EVENT_PORTAMENTO_ON: { spcFlags |= COMPILESNES_FLAGS_PORTAMENTO; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Portamento On", desc.str().c_str(), CLR_PORTAMENTO, ICON_CONTROL); break; } case EVENT_PORTAMENTO_OFF: { spcFlags &= ~COMPILESNES_FLAGS_PORTAMENTO; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Portamento Off", desc.str().c_str(), CLR_PORTAMENTO, ICON_CONTROL); break; } case EVENT_PANPOT_ENVELOPE: { uint8_t envelopeIndex = GetByte(curOffset++); desc << L"Envelope Index: " << (int)envelopeIndex; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Panpot Envelope", desc.str().c_str(), CLR_PAN, ICON_CONTROL); break; } case EVENT_PAN: { int8_t newPan = GetByte(curOffset++); spcPan = newPan; double volumeScale; uint8_t midiPan = Convert7bitLinearPercentPanValToStdMidiVal((uint8_t)(newPan + 0x80) / 2, &volumeScale); AddExpressionNoItem(ConvertPercentAmpToStdMidiVal(volumeScale)); AddPan(beginOffset, curOffset - beginOffset, midiPan); break; } case EVENT_LOOP_BREAK: { uint8_t repeatNest = GetByte(curOffset++); uint16_t dest = GetShort(curOffset); curOffset += 2; desc << L"Nest Level: " << (int)repeatNest << L" Destination: $" << std::hex << std::setfill(L'0') << std::setw(4) << std::uppercase << (int)dest; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Repeat Break", desc.str().c_str(), CLR_LOOP, ICON_ENDREP); repeatCount[repeatNest]--; if (repeatCount[repeatNest] == 0) { curOffset = dest; } break; } case EVENT_DURATION_DIRECT: { uint8_t duration; if (!ReadDurationBytes(curOffset, duration)) { // address out of range return false; } spcNoteDuration = duration; desc << L"Duration: " << (int)duration; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Duration (Direct)", desc.str().c_str(), CLR_DURNOTE, ICON_CONTROL); break; } case EVENT_DURATION: { uint8_t duration; if (!ReadDurationBytes(curOffset, duration)) { // address out of range return false; } spcNoteDuration = duration; desc << L"Duration: " << (int)duration; AddGenericEvent(beginOffset, curOffset - beginOffset, L"Duration", desc.str().c_str(), CLR_DURNOTE, ICON_CONTROL); break; } case EVENT_PERCUSSION_NOTE: { uint8_t duration; bool hasDuration = ReadDurationBytes(curOffset, duration); if (hasDuration) { spcNoteDuration = duration; desc << L"Duration: " << (int)duration; } uint8_t percNoteNumber = statusByte - parentSeq->STATUS_PERCUSSION_NOTE_MIN; AddPercNoteByDur(beginOffset, curOffset - beginOffset, percNoteNumber, 100, spcNoteDuration, hasDuration ? L"Percussion Note with Duration" : L"Percussion Note"); AddTime(spcNoteDuration); break; } default: desc << L"Event: 0x" << std::hex << std::setfill(L'0') << std::setw(2) << std::uppercase << (int)statusByte; AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event", desc.str().c_str()); pRoot->AddLogItem(new LogItem((std::wstring(L"Unknown Event - ") + desc.str()).c_str(), LOG_LEVEL_ERR, L"CompileSnesSeq")); 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; }