bool OrgTrack::LoadTrack(uint32_t trackNum, uint32_t stopOffset, long stopDelta) { pMidiTrack = parentSeq->midi->AddTrack(); //SetChannelAndGroupFromTrkNum(trackNum); if (realTrkNum > 7) channel = 9; //all tracks above 8 are drum tracks (channel 10) else channel = trackNum; channelGroup = 0; pMidiTrack->SetChannelGroup(channelGroup); if (trackNum == 0) { AddTempo(0, 0, ((OrgSeq *) parentSeq)->waitTime * 4000); AddTimeSig(0, 0, 4, 4, (uint8_t) parentSeq->GetPPQN()); } if (channel == 10) AddProgramChange(0, 0, waveNum); bInLoop = false; curOffset = dwOffset; //start at beginning of track curNote = 0; for (uint16_t i = 0; i < numNotes; i++) ReadEvent(); return true; }
bool PS1Seq::ReadEvent(void) { uint32_t beginOffset = curOffset; uint32_t delta = ReadVarLen(curOffset); if (curOffset >= rawfile->size()) return false; AddTime(delta); uint8_t status_byte = GetByte(curOffset++); //if (status_byte == 0) //Jump Relative //{ // short relOffset = (short)GetShortBE(curOffset); // AddGenericEvent(beginOffset, 4, L"Jump Relative", NULL, BG_CLR_PINK); // curOffset += relOffset; // curOffset += 4; //skip the first 4 bytes (no idea) // SetPPQN(GetShortBE(curOffset)); // curOffset += 2; // AddTempo(curOffset, 3, GetWordBE(curOffset-1) & 0xFFFFFF); // curOffset += 3; // uint8_t numer = GetByte(curOffset++); // uint8_t denom = GetByte(curOffset++); // if (numer == 0 || numer > 32) //sanity check // return false; // AddTimeSig(curOffset-2, 2, numer, 1<<denom, GetPPQN()); // SetEventsOffset(offset() + 0x0F); //} // else if (status_byte <= 0x7F) // Running Status { if (status_byte == 0) // some games were ripped to PSF with the EndTrack event missing, so { if (GetWord(curOffset) == 0) //if we read a sequence of four 0 bytes, then just treat that return false; //as the end of the track } status_byte = runningStatus; curOffset--; } else runningStatus = status_byte; channel = status_byte&0x0F; SetCurTrack(channel); switch (status_byte & 0xF0) { case 0x90 : //note event key = GetByte(curOffset++); vel = GetByte(curOffset++); if (vel > 0) //if the velocity is > 0, it's a note on AddNoteOn(beginOffset, curOffset-beginOffset, key, vel); else //otherwise it's a note off AddNoteOff(beginOffset, curOffset-beginOffset, key); break; case 0xB0 : { uint8_t controlNum = GetByte(curOffset++); uint8_t value = GetByte(curOffset++); switch (controlNum) //control number { case 0 : //bank select AddGenericEvent(beginOffset, curOffset-beginOffset, L"Bank Select", L"", CLR_MISC); AddBankSelectNoItem(value); break; case 6 : //data entry AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN Data Entry", L"", CLR_MISC); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 7 : //volume AddVol(beginOffset, curOffset-beginOffset, value); break; case 10 : //pan AddPan(beginOffset, curOffset-beginOffset, value); break; case 11 : //expression AddExpression(beginOffset, curOffset-beginOffset, value); break; case 64 : //damper (hold) AddSustainEvent(beginOffset, curOffset-beginOffset, value); break; case 91 : //reverb depth (_SsContExternal) AddReverb(beginOffset, curOffset-beginOffset, value); break; case 98 : //(0x62) NRPN 1 (LSB) switch (value) { case 20 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN 1 #20", L"", CLR_MISC); break; case 30 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN 1 #30", L"", CLR_MISC); break; default: AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN 1", L"", CLR_MISC); break; } if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 99 : //(0x63) NRPN 2 (MSB) switch (value) { case 20 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Loop Start", L"", CLR_LOOP); break; case 30 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Loop End", L"", CLR_LOOP); break; default: AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN 2", L"", CLR_MISC); break; } if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 100 : //(0x64) RPN 1 (LSB), no effect? AddGenericEvent(beginOffset, curOffset-beginOffset, L"RPN 1", L"", CLR_MISC); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 101 : //(0x65) RPN 2 (MSB), no effect? AddGenericEvent(beginOffset, curOffset-beginOffset, L"RPN 2", L"", CLR_MISC); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 121 : //reset all controllers AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reset All Controllers", L"", CLR_MISC); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; default: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control Event", L"", CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; } } break; case 0xC0 : { uint8_t progNum = GetByte(curOffset++); AddProgramChange(beginOffset, curOffset-beginOffset, progNum); } break; case 0xE0 : { uint8_t hi = GetByte(curOffset++); uint8_t lo = GetByte(curOffset++); AddPitchBendMidiFormat(beginOffset, curOffset-beginOffset, hi, lo); } break; case 0xF0 : { if (status_byte == 0xFF) { switch (GetByte(curOffset++)) { case 0x51 : //tempo. This is different from SMF, where we'd expect a 51 then 03. Also, supports //a string of tempo events AddTempo(beginOffset, curOffset+3-beginOffset, (GetShortBE(curOffset) << 8) | GetByte(curOffset + 2)); curOffset += 3; break; case 0x2F : AddEndOfTrack(beginOffset, curOffset-beginOffset); return false; default : AddUnknown(beginOffset, curOffset-beginOffset, L"Meta Event"); return false; } } else { AddUnknown(beginOffset, curOffset-beginOffset); return false; } } break; default: AddUnknown(beginOffset, curOffset-beginOffset); return false; } return true; }
// I'm going to try to follow closely to the original Salamander 2 code at 0x30C6 bool KonamiGXTrack::ReadEvent(void) { ULONG beginOffset = curOffset; ULONG deltatest = GetTime(); //AddDelta(ReadVarLen(curOffset)); BYTE status_byte = GetByte(curOffset++); if (status_byte == 0xFF) { if (bInJump) { bInJump = false; curOffset = jump_return_offset; } else { AddEndOfTrack(beginOffset, curOffset-beginOffset); return 0; } } else if (status_byte == 0x60) { return 1; } else if (status_byte == 0x61) { return 1; } else if (status_byte < 0xC0) //note event { BYTE note, delta; if (status_byte < 0x62) { delta = GetByte(curOffset++); note = status_byte; prevDelta = delta; } else { delta = prevDelta; note = status_byte - 0x62; } BYTE nextDataByte = GetByte(curOffset++); BYTE dur, vel; if (nextDataByte < 0x80) { dur = nextDataByte; prevDur = dur; vel = GetByte(curOffset++); } else { dur = prevDur; vel = nextDataByte - 0x80; } //AddNoteOn(beginOffset, curOffset-beginOffset, note, vel); //AddDelta(dur); //AddNoteOffNoItem(note); UINT newdur = (delta*dur)/0x64; if (newdur == 0) newdur = 1; AddNoteByDur(beginOffset, curOffset-beginOffset, note, vel, newdur); AddTime(delta); if (newdur > delta) ATLTRACE("newdur > delta. %X > %X. occurring at %X\n", newdur, delta, beginOffset); //AddDelta(dur); } else switch (status_byte) { case 0xC0: curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xCE: curOffset+=2; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xD0: curOffset+=3; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xD1: case 0xD2: case 0xD3: case 0xD4: case 0xD5: case 0xD6: curOffset+=2; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xDE: curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xE0: //Rest { BYTE delta = GetByte(curOffset++); AddTime(delta); } break; case 0xE1: //Hold { BYTE delta = GetByte(curOffset++); BYTE dur = GetByte(curOffset++); UINT newdur = (delta*dur)/0x64; AddTime(newdur); this->MakePrevDurNoteEnd(); AddTime(delta-newdur); } break; case 0xE2: //program change { BYTE progNum = GetByte(curOffset++); AddProgramChange(beginOffset, curOffset-beginOffset, progNum); } break; case 0xE3: //stereo related curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xE4: case 0xE5: curOffset+=3; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xE6: AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xE7: curOffset+=3; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xE8: AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xE9: curOffset+=3; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xEA: //tempo { BYTE bpm = GetByte(curOffset++); AddTempoBPM(beginOffset, curOffset-beginOffset, bpm); } break; case 0xEC: curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xEE: //master vol { BYTE vol = GetByte(curOffset++); //AddMasterVol(beginOffset, curOffset-beginOffset, vol); } break; case 0xEF: curOffset+=2; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xF0: curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xF1: curOffset+=3; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xF2: curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xF3: curOffset+=3; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xF6: case 0xF7: AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xF8: curOffset+=2; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xFA: //release rate curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xFD: curOffset += 4; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Loop", NULL, CLR_LOOP); break; case 0xFE: bInJump = true; jump_return_offset = curOffset+4; AddGenericEvent(beginOffset, jump_return_offset-beginOffset, L"Jump", NULL, CLR_LOOP); curOffset = GetWordBE(curOffset); //if (curOffset > 0x100000) // return 0; break; default: AddEndOfTrack(beginOffset, curOffset-beginOffset); return false; } return true; }
bool TriAcePS1Track::ReadEvent(void) { uint32_t beginOffset = curOffset; uint8_t status_byte = GetByte(curOffset++); uint8_t event_dur = 0; //0-0x7F is a note event if (status_byte <= 0x7F) { event_dur = GetByte(curOffset++); //Delta time from "Note on" to "Next command(op-code)". uint8_t note_dur; uint8_t velocity; if (!impliedNoteDur) note_dur = GetByte(curOffset++); //Delta time from "Note on" to "Note off". else note_dur = impliedNoteDur; if (!impliedVelocity) velocity = GetByte(curOffset++); else velocity = impliedVelocity; AddNoteByDur_Extend(beginOffset, curOffset-beginOffset, status_byte, velocity, note_dur); } else switch (status_byte) { case 0x80 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Score Pattern End", NULL, CLR_TRACKEND); return false; case 0x81 : //unknown event_dur = GetByte(curOffset++); curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x82 : //unknown event_dur = GetByte(curOffset++); curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x83 : //program change { event_dur = GetByte(curOffset++); uint8_t progNum = GetByte(curOffset++); uint8_t bankNum = GetByte(curOffset++); //ATLTRACE("PROGRAM CHANGE ProgNum: %X BankNum: %X", progNum, bankNum); uint8_t bank = (bankNum*2) + ((progNum > 0x7F) ? 1 : 0); if (progNum > 0x7F) progNum -= 0x80; //ATLTRACE(" SELECTING: prog %X bank %X\n", progNum, bank); AddBankSelectNoItem(bank); AddProgramChange(beginOffset, curOffset-beginOffset, progNum); } break; case 0x84 : //pitch bend { event_dur = GetByte(curOffset++); short bend = ((char)GetByte(curOffset++)) << 7; AddPitchBend(beginOffset, curOffset-beginOffset, bend); } break; case 0x85 : //volume { event_dur = GetByte(curOffset++); uint8_t val = GetByte(curOffset++); AddVol(beginOffset, curOffset-beginOffset, val); } break; case 0x86 : //expression { event_dur = GetByte(curOffset++); uint8_t val = GetByte(curOffset++); AddExpression(beginOffset, curOffset-beginOffset, val); } break; case 0x87 : //pan { event_dur = GetByte(curOffset++); uint8_t pan = GetByte(curOffset++); AddPan(beginOffset, curOffset-beginOffset, pan); } break; case 0x88 : //unknown event_dur = GetByte(curOffset++); curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x89 : //damper pedal { event_dur = GetByte(curOffset++); uint8_t val = GetByte(curOffset++); AddSustainEvent(beginOffset, curOffset-beginOffset, val); } break; case 0x8A : //unknown (tempo?) { event_dur = GetByte(curOffset++); uint8_t val = GetByte(curOffset++); AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event (tempo?)"); } break; case 0x8D : //Dal Segno: start point AddGenericEvent(beginOffset, curOffset-beginOffset, L"Dal Segno: start point", NULL, CLR_UNKNOWN); break; case 0x8E : //Dal Segno: end point curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Dal Segno: end point", NULL, CLR_UNKNOWN); break; case 0x8F : //rest { uint8_t rest = GetByte(curOffset++); AddRest(beginOffset, curOffset-beginOffset, rest); } break; case 0x90 : //unknown event_dur = GetByte(curOffset++); curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x92 : //unknown event_dur = GetByte(curOffset++); curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x93 : //unknown event_dur = GetByte(curOffset++); curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x94 : //unknown event_dur = GetByte(curOffset++); curOffset += 3; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x95 : //unknown event_dur = GetByte(curOffset++); curOffset++; AddUnknown(beginOffset, curOffset-beginOffset, L"Unknown Event (Tie?)"); break; case 0x96 : //Pitch Bend Range { event_dur = GetByte(curOffset++); uint8_t semitones = GetByte(curOffset++); AddPitchBendRange(beginOffset, curOffset-beginOffset, semitones); } break; case 0x97 : //unknown event_dur = GetByte(curOffset++); curOffset += 4; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x99 : //unknown event_dur = GetByte(curOffset++); curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x9A : //unknown event_dur = GetByte(curOffset++); curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x9B : //unknown event_dur = GetByte(curOffset++); curOffset += 5; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x9E : //imply note params impliedNoteDur = GetByte(curOffset++); impliedVelocity = GetByte(curOffset++); AddGenericEvent(beginOffset, curOffset-beginOffset, L"Imply Note Params", NULL, CLR_CHANGESTATE); break; default : Alert(L"Unknown event opcode %X at %X", status_byte, beginOffset); AddUnknown(beginOffset, curOffset-beginOffset); return false; } if (event_dur) AddTime(event_dur); return true; }
bool HeartBeatPS1Seq::ReadEvent(void) { uint32_t beginOffset = curOffset; // in this format, end of track (FF 2F 00) comes without delta-time. // so handle that crazy sequence the first. if (curOffset + 3 <= rawfile->size()) { if (GetByte(curOffset) == 0xff && GetByte(curOffset + 1) == 0x2f && GetByte(curOffset + 2) == 0x00) { curOffset += 3; AddEndOfTrack(beginOffset, curOffset-beginOffset); return false; } } uint32_t delta = ReadVarLen(curOffset); if (curOffset >= rawfile->size()) return false; AddTime(delta); uint8_t status_byte = GetByte(curOffset++); if (status_byte <= 0x7F) // Running Status { status_byte = runningStatus; curOffset--; } else runningStatus = status_byte; channel = status_byte&0x0F; SetCurTrack(channel); switch (status_byte & 0xF0) { case 0x80 : //note off key = GetByte(curOffset++); vel = GetByte(curOffset++); AddNoteOff(beginOffset, curOffset-beginOffset, key); break; case 0x90 : //note event key = GetByte(curOffset++); vel = GetByte(curOffset++); if (vel > 0) //if the velocity is > 0, it's a note on AddNoteOn(beginOffset, curOffset-beginOffset, key, vel); else //otherwise it's a note off AddNoteOff(beginOffset, curOffset-beginOffset, key); break; case 0xA0 : AddUnknown(beginOffset, curOffset-beginOffset); return false; case 0xB0 : { uint8_t controlNum = GetByte(curOffset++); uint8_t value = GetByte(curOffset++); switch (controlNum) //control number { case 1: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Modulation", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 2: // identical to CC#11? AddGenericEvent(beginOffset, curOffset-beginOffset, L"Breath Controller?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 4: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Foot Controller?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 5: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Portamento Time?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 6 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN Data Entry", NULL, CLR_MISC); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 7 : //volume AddVol(beginOffset, curOffset-beginOffset, value); break; case 9: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 9", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 10 : //pan AddPan(beginOffset, curOffset-beginOffset, value); break; case 11 : //expression AddExpression(beginOffset, curOffset-beginOffset, value); break; case 20: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 20", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 21: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 21", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 22: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 22", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 23: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 23", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 32: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Bank LSB?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 52: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 52", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 53: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 53", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 54: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 54", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 55: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 55", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 56: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 56", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 64: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Hold 1?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 69: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Hold 2?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 71: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Resonance?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 72: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Release Time?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 73: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Attack Time?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 74: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Cut Off Frequency?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 75: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Decay Time?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 76: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Vibrato Rate?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 77: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Vibrato Depth?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 78: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Vibrato Delay?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 79: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control 79", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 91: AddReverb(beginOffset, curOffset-beginOffset, value); break; case 92: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Tremolo Depth?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 98: switch (value) { case 20 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN 1 #20", NULL, CLR_MISC); break; case 30 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN 1 #30", NULL, CLR_MISC); break; default: AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN 1", NULL, CLR_MISC); break; } if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 99 : //(0x63) nrpn msb switch (value) { case 20 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Loop Start", NULL, CLR_LOOP); break; case 30 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Loop End", NULL, CLR_LOOP); break; default: AddGenericEvent(beginOffset, curOffset-beginOffset, L"NRPN 2", NULL, CLR_MISC); break; } if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 121: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reset All Controllers", NULL, CLR_MISC); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 126: AddGenericEvent(beginOffset, curOffset-beginOffset, L"MONO?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; case 127: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Poly?", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; default: AddGenericEvent(beginOffset, curOffset-beginOffset, L"Control Event", NULL, CLR_UNKNOWN); if (VGMSeq::readMode == READMODE_CONVERT_TO_MIDI) { pMidiTrack->AddControllerEvent(channel, controlNum, value); } break; } } break; case 0xC0 : { uint8_t progNum = GetByte(curOffset++); AddProgramChange(beginOffset, curOffset-beginOffset, progNum); } break; case 0xD0 : AddUnknown(beginOffset, curOffset-beginOffset); return false; case 0xE0 : { uint8_t hi = GetByte(curOffset++); uint8_t lo = GetByte(curOffset++); AddPitchBendMidiFormat(beginOffset, curOffset-beginOffset, hi, lo); } break; case 0xF0 : { if (status_byte == 0xFF) { if (curOffset + 1 > rawfile->size()) return false; uint8_t metaNum = GetByte(curOffset++); uint32_t metaLen = ReadVarLen(curOffset); if (curOffset + metaLen > rawfile->size()) return false; switch (metaNum) { case 0x51 : AddTempo(beginOffset, curOffset+metaLen-beginOffset, (GetShortBE(curOffset) << 8) | GetByte(curOffset + 2)); curOffset += metaLen; break; case 0x58 : { uint8_t numer = GetByte(curOffset); uint8_t denom = GetByte(curOffset + 1); AddTimeSig(beginOffset, curOffset+metaLen-beginOffset, numer, 1<<denom, (uint8_t)GetPPQN()); curOffset += metaLen; break; } case 0x2F : // apparently not used, but just in case. AddEndOfTrack(beginOffset, curOffset+metaLen-beginOffset); curOffset += metaLen; return false; default : AddUnknown(beginOffset, curOffset+metaLen-beginOffset); curOffset += metaLen; break; } } else { AddUnknown(beginOffset, curOffset-beginOffset); return false; } } break; } return true; }
//-------------------------------------------------- //Revisions: // 2009. 6.17(Wed.) : Re-make by "Sound tester 774" in "内蔵音源をMIDI変換するスレ(in http://www.2ch.net)" // Add un-known command(op-code). //-------------------------------------------------- bool AkaoTrack::ReadEvent(void) { ULONG beginOffset = curOffset; BYTE status_byte = GetByte(curOffset++); int i, k; if (status_byte < 0x9A) //it's either a note-on message, a tie message, or a rest message { //looking at offset 8005E5C8 in the FFO FF2 exe for this delta time table code 4294967296 0x100000000/0xBA2E8BA3 = 1.374999... = 11/8 //0x68 after eq = 9 /*i = ((status_byte * 0xBA2E8BA3) & 0xFF00000000) >> 32; // emulating multu and mfhi instruction //i >>= 3; //srl 3 */ i = status_byte / 11; k = i*2; //sll 1 - aka multiply by 2 k += i; //addu $v0, $v1 k *= 4; //sll 2 - aka multiply by 4 k -= i; //subu $v0, $v1 k = status_byte - k; //subu $v0, $s1, $v0 //k now equals the table index value //relative key calculation found at 8005E6F8 in FFO FF2 exe if (status_byte < 0x83) // it's a note-on message { relative_key = status_byte / 11; base_key = octave*12; if (bNotePlaying) { AddNoteOffNoItem(prevKey); bNotePlaying = false; } //if (bAssociatedWithSSTable) // FindNoteInstrAssoc(hFile, base_key + relative_key); AddNoteOn(beginOffset, curOffset-beginOffset, base_key + relative_key, vel); bNotePlaying = true; AddTime(delta_time_table[k]); } else if (status_byte < 0x8F) //if it's between 0x83 and 0x8E it is a tie event { AddTime(delta_time_table[k]); if (loop_counter[loop_layer] == 0 && loop_layer == 0) //do this so we don't repeat this for every single time it loops AddGenericEvent(beginOffset, curOffset-beginOffset, L"Tie", NULL, CLR_TIE); } else //otherwise, it's between 0x8F and 0x99 and it's a rest message { if (bNotePlaying) { AddNoteOff(beginOffset, curOffset-beginOffset, prevKey); bNotePlaying = false; } AddRest(beginOffset, curOffset-beginOffset, delta_time_table[k]); } } else if ((status_byte >= 0xF0) && (status_byte <= 0xFB)) { relative_key = status_byte-0xF0; base_key = octave*12; if (bNotePlaying) { AddNoteOffNoItem(prevKey); bNotePlaying = false; } bNotePlaying = true; AddNoteOn(beginOffset, curOffset-beginOffset+1, base_key + relative_key, vel); AddTime(GetByte(curOffset++)); } else switch (status_byte) { case 0xA0 : // ----[ 2009. 6.12 change ]----- // AddUnknown(beginOffset, curOffset-beginOffset); // break; AddEndOfTrack(beginOffset, curOffset-beginOffset); return false; case 0xA1 : // change program to articulation number { ((AkaoSeq*)parentSeq)->bUsesIndividualArts = true; BYTE artNum = GetByte(curOffset++); BYTE progNum = ((AkaoSeq*)parentSeq)->instrset->aInstrs.size() + artNum; AddProgramChange(beginOffset, curOffset-beginOffset, progNum); } break; case 0xA2 : // set next note length [ticks] curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Next note length", NULL, CLR_CHANGESTATE); break; case 0xA3 : //set track volume vol = GetByte(curOffset++); //expression value AddVol(beginOffset, curOffset-beginOffset, vol); break; case 0xA4: // pitch slide half steps. (Portamento) { BYTE dur = GetByte(curOffset++); //first byte is duration of slide BYTE steps = GetByte(curOffset++); //second byte is number of halfsteps to slide... not sure if signed or not, only seen positive //AddPitchBendSlide( AddGenericEvent(beginOffset, curOffset-beginOffset, L"Portamento", NULL, CLR_PORTAMENTO); } break; case 0xA5 : //set octave octave = GetByte(curOffset++); AddSetOctave(beginOffset, curOffset-beginOffset, octave); break; case 0xA6 : //set octave + 1 AddIncrementOctave(beginOffset, curOffset-beginOffset); break; case 0xA7 : //set octave - 1 AddDecrementOctave(beginOffset, curOffset-beginOffset); break; case 0xA8 : //set expression (USED TO BE VELOCITY, may go back after testing, as this is messy) { //vel = GetByte(curOffset++); //vel = Convert7bitPercentVolValToStdMidiVal(vel); //I THINK THIS APPLIES, BUT NOT POSITIVE //AddGenericEvent(beginOffset, curOffset-beginOffset, L"Set Velocity", NULL, BG_CLR_CYAN); BYTE cExpression = GetByte(curOffset++); //// こっちのlog演算は要らない //// vel = Convert7bitPercentVolValToStdMidiVal(vel); //I THINK THIS APPLIES, BUT NOT POSITIVE vel = 127; //とりあえず 127 にしておく AddExpression(beginOffset, curOffset-beginOffset, cExpression); } break; case 0xA9 : //set Expression fade { BYTE dur = GetByte(curOffset++); BYTE targExpr = GetByte(curOffset++); //reads the target velocity value - the velocity value we are fading toward AddExpressionSlide(beginOffset, curOffset-beginOffset, dur, targExpr); } break; case 0xAA : //set pan { BYTE pan = GetByte(curOffset++); AddPan(beginOffset, curOffset-beginOffset, pan); } break; case 0xAB : //set pan fade { BYTE dur = GetByte(curOffset++); BYTE targPan = GetByte(curOffset++); //reads the target velocity value - the velocity value we are fading toward AddPanSlide(beginOffset, curOffset-beginOffset, dur, targPan); } break; case 0xAC : //unknown curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; /*AD = set attack AE = set decay AF = set sustain level B0 = AE then AF <CBongo> B1 = set sustain release B2 = set release B7 might be set A,D,S,R values all at once B3 appears to be "reset ADSR to the initial values from the instrument/sample data"*/ case 0xAD : curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"ADSR", NULL, CLR_ADSR); break; case 0xAE : curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"ADSR", NULL, CLR_ADSR); break; case 0xAF : curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"ADSR", NULL, CLR_ADSR); break; case 0xB0 : curOffset++; curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"ADSR", NULL, CLR_ADSR); break; case 0xB1 : curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"ADSR", NULL, CLR_ADSR); break; case 0xB2 : curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"ADSR", NULL, CLR_ADSR); break; case 0xB3 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"ADSR", NULL, CLR_ADSR); break; // // 0xB4 to 0xB7 LFO Pitch bend // 0xB8 to 0xBC LFO Expression // 0xBC to 0xBF LFO Panpot // case 0xB4 : //unknown curOffset += 3; AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Pitch bend) Length, cycle", NULL, CLR_LFO); break; case 0xB5 : curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Pitch bend) Depth", NULL, CLR_LFO); break; case 0xB6 : //unknown AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Pitch bend) off", NULL, CLR_LFO); break; case 0xB7 : curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xB8 : //unknown curOffset += 3; AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Expression) Length, cycle", NULL, CLR_LFO); break; case 0xB9 : curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Expression) Depth", NULL, CLR_LFO); break; case 0xBA : //unknown AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Expression) off", NULL, CLR_LFO); break; case 0xBB : curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xBC : //unknown curOffset += 2; AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Panpot) Length, cycle", NULL, CLR_LFO); break; case 0xBD : curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Panpot) Depth", NULL, CLR_LFO); break; case 0xBE : //unknown AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Panpot) off", NULL, CLR_LFO); break; case 0xBF : curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xC0 : { char cTranspose = GetByte(curOffset++); AddTranspose(beginOffset, curOffset-beginOffset,cTranspose); } break; case 0xC1 : { BYTE cTranspose = GetByte(curOffset++); AddGenericEvent(beginOffset, curOffset-beginOffset, L"Transpose move", NULL, CLR_TRANSPOSE); } break; case 0xC2 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reverb On", NULL, CLR_REVERB); break; case 0xC3 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reverb Off", NULL, CLR_REVERB); break; case 0xC4 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Noise On", NULL, CLR_UNKNOWN); break; case 0xC5 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Noise Off", NULL, CLR_UNKNOWN); break; case 0xC6 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"FM Modulation On", NULL, CLR_UNKNOWN); break; case 0xC7 : AddGenericEvent(beginOffset, curOffset-beginOffset, L"FM Modulation Off", NULL, CLR_UNKNOWN); break; case 0xC8 : // set loop begin marker AddGenericEvent(beginOffset, curOffset-beginOffset, L"Repeat Start", NULL, CLR_LOOP); loop_begin_layer++; loop_begin_loc[loop_begin_layer] = curOffset; //bInLoop = true; break; case 0xC9 : { BYTE value1 = GetByte(curOffset++); AddGenericEvent(beginOffset, curOffset-beginOffset, L"Repeat End", NULL, CLR_LOOP); if (loop_begin_layer == 0) //if loop_begin_layer == 0, then there was never a matching loop begin event! this is seen in ff9 402 and ff9 hunter's chance break; if (loopID[loop_layer] != curOffset) { loop_layer++; loopID[loop_layer] = curOffset; curOffset = loop_begin_loc[loop_begin_layer]; loop_counter[loop_layer] = value1-2; bInLoop = true; } else if (loop_counter[loop_layer] > 0) { loop_counter[loop_layer]--; curOffset = loop_begin_loc[loop_begin_layer]; //if (loop_counter[loop_layer] == 0 && loop_layer == 1) // bInLoop = false; } else { loopID[loop_layer]=0; loop_layer--; loop_begin_layer--; if (loop_layer == 0) bInLoop = false; } } break; case 0xCA : { BYTE value1 = 2; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Repeat End", NULL, CLR_LOOP); if (loop_begin_layer == 0) break; if (loopID[loop_layer] != curOffset) { loop_layer++; loopID[loop_layer] = curOffset; curOffset = loop_begin_loc[loop_begin_layer]; loop_counter[loop_layer] = value1-2; bInLoop = true; } else if (loop_counter[loop_layer] > 0) { loop_counter[loop_layer]--; curOffset = loop_begin_loc[loop_begin_layer]; //if (loop_counter[loop_layer] == 0 && loop_layer == 1) // bInLoop = false; } else { loopID[loop_layer]=0; loop_layer--; loop_begin_layer--; if (loop_layer == 0) bInLoop = false; } } break; case 0xCC : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Slur On", NULL, CLR_PORTAMENTO); break; case 0xCD : AddGenericEvent(beginOffset, curOffset-beginOffset, L"Slur Off", NULL, CLR_PORTAMENTO); break; case 0xD0 : AddNoteOff(beginOffset, curOffset-beginOffset, prevKey); break; case 0xD1 : // unknown AddGenericEvent(beginOffset, curOffset-beginOffset, L"Deactivate Notes?", NULL, CLR_UNKNOWN); break; case 0xD2 : curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xD3 : curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xD8 : //pitch bend { BYTE cValue = GetByte(curOffset++); //signed data byte. range of 1 octave (0x7F = +1 octave 0x80 = -1 octave) int fullValue = (int)(cValue * 64.503937007874015748031496062992); fullValue += 0x2000; BYTE lo = fullValue & 0x7F; BYTE hi = (fullValue & 0x3F80) >> 7; AddPitchBendMidiFormat(beginOffset, curOffset-beginOffset, lo, hi); } break; case 0xD9 : curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Pitch bend move", NULL, CLR_UNKNOWN); break; case 0xDA : curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xDC : curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xDD : curOffset += 2; AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Pitch bend) times", NULL, CLR_UNKNOWN); break; case 0xDE : curOffset += 2; AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Expression) times", NULL, CLR_UNKNOWN); break; case 0xDF : curOffset += 2; AddGenericEvent(beginOffset, curOffset-beginOffset, L"LFO(Panpot) times", NULL, CLR_UNKNOWN); break; case 0xE1 : curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xE6 : curOffset += 2; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0xFC : //tie time //if (nVersion == VERSION_1 || nVersion == VERSION_2) // goto MetaEvent; //rest_time += pDoc->GetByte(j++); AddTime(GetByte(curOffset++)); AddGenericEvent(beginOffset, curOffset-beginOffset, L"Tie (custom)", NULL, CLR_TIE); break; case 0xFD : { if (bNotePlaying) { AddNoteOffNoItem(prevKey); bNotePlaying = false; } BYTE restTime = GetByte(curOffset++); AddRest(beginOffset, curOffset-beginOffset, restTime); } break; case 0xFE : //meta event //MetaEvent: switch (GetByte(curOffset++)) { case 0x00 : //tempo { BYTE value1 = GetByte(curOffset++); BYTE value2 = GetByte(curOffset++); double dValue1 = ((value2<<8) + value1)/218.4555555555555555555555555; //no clue how this magic number is properly derived AddTempoBPM(beginOffset, curOffset-beginOffset, dValue1); } break; case 0x01 : //tempo slide { BYTE value1 = GetByte(curOffset++); //NEED TO ADDRESS value 1 BYTE value2 = GetByte(curOffset++); //AddTempoSlide( //RecordMidiSetTempo(current_delta_time, value2); } break; case 0x02 : //reverb curOffset++; curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reverb Level", NULL, CLR_REVERB); break; case 0x03 : //reverb curOffset++; curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reverb Fade", NULL, CLR_REVERB); break; case 0x04 : //signals this track uses the drum kit AddProgramChange(beginOffset, curOffset-beginOffset, 127, L"Drum kit On"); //channel = 9; break; case 0x05 : //reverb AddGenericEvent(beginOffset, curOffset-beginOffset, L"Drum kit Off", NULL, CLR_UNKNOWN); break; case 0x06 : //Branch Relative { ULONG dest = (S16)GetShort(curOffset) + curOffset; curOffset += 2; ULONG eventLength = curOffset - beginOffset; bool bContinue = false; curOffset = dest; // Check the remaining area that will be processed by CPU-controlled jump. for (vector<ULONG>::iterator itAddr = vCondJumpAddr.begin(); itAddr != vCondJumpAddr.end(); ++itAddr) { if (!IsOffsetUsed(*itAddr)) { // There is an area not visited yet, VGMTrans must try to go there. bContinue = true; break; } } if (readMode == READMODE_FIND_DELTA_LENGTH) deltaLength = GetTime(); AddGenericEvent(beginOffset, eventLength, L"Dal Segno.(Loop)", NULL, CLR_LOOP); return bContinue; /*USHORT siValue = GetShort(pDoc, j); if (nScanMode == MODE_CONVERT_MIDI) //if we are converting the midi, the actually branch { if (seq_repeat_counter-- > 0) curOffset += siValue; else curOffset += 2; } else curOffset += 2; //otherwise, just skip over the relative branch offset*/ } break; case 0x07 : //Permanence Loop break with conditional. { BYTE condValue = GetByte(curOffset++); ULONG dest = (S16)GetShort(curOffset) + curOffset; curOffset += 2; ULONG eventLength = curOffset - beginOffset; // This event performs conditional jump if certain CPU variable matches to the condValue. // VGMTrans will simply try to parse all events as far as possible, instead. // (Test case: FF9 416 Final Battle) if (!IsOffsetUsed(beginOffset)) { // For the first time, VGMTrans just skips the event, // but remembers the destination address for future jump. vCondJumpAddr.push_back(dest); } else { // For the second time, VGMTrans jumps to the destination address. curOffset = dest; } AddGenericEvent(beginOffset, eventLength, L"Dal Segno (Loop) Break", NULL, CLR_LOOP); } break; case 0x09 : //Repeat break with conditional. curOffset++; curOffset++; curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Repeat Break", NULL, CLR_LOOP); break; //case 0x0E : //call subroutine //case 0x0F : //return from subroutine case 0x10 : //unknown curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; case 0x14 : //program change { BYTE curProgram = GetByte(curOffset++); //if (!bAssociatedWithSSTable) // RecordMidiProgramChange(current_delta_time, curProgram, hFile); AddProgramChange(beginOffset, curOffset-beginOffset, curProgram); } break; case 0x15 : //Time Signature { BYTE denom = 4; curOffset++;//(192 / GetByte(curOffset++)); BYTE numer = GetByte(curOffset++); //AddTimeSig(beginOffset, curOffset-beginOffset, numer, denom, parentSeq->GetPPQN()); } break; case 0x16 : //Maker curOffset += 2; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Maker", NULL, CLR_UNKNOWN); break; case 0x1C : //unknown curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; default : AddGenericEvent(beginOffset, curOffset-beginOffset, L"UNKNOWN META EVENT", NULL, CLR_UNRECOGNIZED); break; } break; default : AddGenericEvent(beginOffset, curOffset-beginOffset, L"UNKNOWN EVENT", NULL, CLR_UNRECOGNIZED); break; } return true; }
//============================================================== // Process of 1 Event //-------------------------------------------------------------- // Input // Nothing // Output // Nothing // Memo // SeqTrack::LoadTrack() から call される。 //============================================================== bool HOSATrack::ReadEvent(void) { //================================== // [ Local 変数 ] //---------------------------------- const ULONG beginOffset = curOffset; //start offset point const BYTE cCommand = GetByte(curOffset++); //command (op-code) const BYTE cCom_bit0 = (cCommand & 0x1F); //length / contents const BYTE cCom_bit5 = (cCommand & 0x60) >> 5; //Delta times const BYTE cCom_bit7 = (cCommand & 0x80) >> 7; //0=Notes / 1=Controls // unsigned int iMinLengthCounter; //デルタタイム最小値 // int i; //general // vector<char>::iterator it_note; // vector<int unsigned >::iterator it_Length; //================================== // [ Process of "Delta time" and "Note off Event" ] //---------------------------------- //Command用の(DeltaCounter==0)まで繰り返し。 //while(iDeltaTimeCounter!=0){ // //Search the minimum length time [ticks] // iMinLengthCounter = iDeltaTimeCounter; // for(i=0;i<listLength.size();i++){ // if(iMinLengthCounter > listLength[i]){ // iMinLengthCounter = listLength[i]; // } // } // //Writing delta time. // AddDelta(iMinLengthCounter); // // //Subtract the minimum length time from "Delta time" and "Length times" // iDeltaTimeCounter -= iMinLengthCounter; // for(i=0;i<listNote.size();i++){ // listLength[i] -= iMinLengthCounter; // } // //Search the ("Length times" == 0) // it_note = listNote.begin(); // it_Length = listLength.begin(); // while(it_Length != listLength.end()){ // if(*it_Length==0){ // //Write "Note-off Event" // AddNoteOffNoItem(*it_note); // //Erase note-information from vector. // it_note = listNote.erase(it_note); // it_Length = listLength.erase(it_Length); // } else { // it_note++; // it_Length++; // } // } //} //================================== // [ Process of command (note / control) ] //---------------------------------- //---------------------------------- // Command: Notes (cCommand == 0x00 - 0x7F) if(cCom_bit7==0){ //-------- //[2]Update the default Note Number cNoteNum = GetByte(curOffset++); //-------- //[3]Update the default Delta time ReadDeltaTime(cCom_bit5, &iDeltaTimeCom); //-------- //[4]Update the default Length iLengthTimeNote = GetShort(parentSeq->dwOffset + 0x10 + cCom_bit0*2); if(iLengthTimeNote==0){ // iLengthTimeNote = ReadVarLen(curOffset); //No count curOffset iLengthTimeNote = DecodeVariable(); }; //-------- //[5]Update the default Velocity if(cNoteNum & 0x80){ cNoteNum &= 0x7F; cVelocity = GetByte(curOffset++); }; //-------- //[3]Update the default Delta time (continuation) if(cCom_bit5==1){ iDeltaTimeCom = iLengthTimeNote; //Delta time is the same as note length. }; iDeltaTimeNote = iDeltaTimeCom; //Default delta time for Note. //-------- //Write Note-On Event AddNoteByDur(beginOffset, curOffset-beginOffset, cNoteNum, cVelocity, iLengthTimeNote); //---------------------------------- // Command: Controls (cCommand == 0x80 - 0x9F, 0xC0 - 0xFF) } else { if(cCom_bit5!=1){ switch(cCom_bit0){ //------------ //End of Track case(0x00): AddEndOfTrack(beginOffset, curOffset-beginOffset); return false; break; //------------ //Tempo case(0x01): cTempo = GetByte(curOffset++); AddTempoBPM(beginOffset, curOffset-beginOffset, cTempo); break; //------------ //Reverb case(0x02): curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reverb Depth", NULL, CLR_REVERB); break; //------------ //Instrument case(0x03): cInstrument = GetByte(curOffset++); AddProgramChange(beginOffset, curOffset-beginOffset, cInstrument); break; //------------ //Volume case(0x04): cVolume = GetByte(curOffset++); AddVol(beginOffset, curOffset-beginOffset, cVolume); break; //------------ //Panpot case(0x05): cPanpot = GetByte(curOffset++); AddPan(beginOffset, curOffset-beginOffset, cPanpot); break; //------------ //Expression case(0x06): cExpression = GetByte(curOffset++); AddExpression(beginOffset, curOffset-beginOffset, cExpression); break; //------------ //Unknown case(0x07): curOffset++; curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; //------------ //Dal Segno. (Loop) case(0x09): curOffset++; AddGenericEvent(beginOffset, curOffset-beginOffset, L"Dal Segno.(Loop)", NULL, CLR_LOOP); break; //------------ //Unknown case(0x0F): AddUnknown(beginOffset, curOffset-beginOffset); break; //------------ //Unknowns default: curOffset++; AddUnknown(beginOffset, curOffset-beginOffset); break; } //-------- //[3]Delta time ULONG beginOffset2 = curOffset; ReadDeltaTime(cCom_bit5, &iDeltaTimeCom); if(curOffset != beginOffset2){ AddGenericEvent(beginOffset2,curOffset-beginOffset2, L"Delta time", NULL, CLR_CHANGESTATE); }; //---------------------------------- // Command: Notes (cCommand == 0xA0 - 0xBF) } else { if(cCom_bit0 & 0x10){ //Add (Command = 0xB0 - 0xBF) cNoteNum+=(cCom_bit0 & 0x0F); }else{ //Sub (Command = 0xA0 - 0xAF) cNoteNum-=(cCom_bit0 & 0x0F); }; //-------- //Write Note-On Event AddNoteByDur(beginOffset, curOffset-beginOffset, cNoteNum, cVelocity, iLengthTimeNote); iDeltaTimeCom = iDeltaTimeNote; } } //================================== // [ Process of "Note" with note length ] //---------------------------------- //if(fNoteOutput!=0){ // //Write "Note-on Event" // AddNoteOn(beginOffset, curOffset-beginOffset, fNoteOutput, cVelocity); // //Add note-information to vector. // listNote.push_back(fNoteOutput); //Note Number // listLength.push_back(iLengthTimeNote); //Length // //Next delta time // iDeltaTimeCom = iDeltaTimeNote; //} //================================== // [ Process of "Setting Delta time" ] //---------------------------------- //iDeltaTimeCounter = iDeltaTimeCom; AddTime(iDeltaTimeCom); 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; }