From 997a4f734d4c4740ec29847d31ac6cc79a07cb56 Mon Sep 17 00:00:00 2001 From: laqieer Date: Thu, 28 Apr 2022 22:33:58 +0800 Subject: [PATCH] add hacks to assist in gba midi extraction --- VG Music Studio/Core/GBA/MP2K/Player.cs | 66 ++++++++++++++++++++++--- VG Music Studio/Core/GBA/MP2K/Track.cs | 1 + 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/VG Music Studio/Core/GBA/MP2K/Player.cs b/VG Music Studio/Core/GBA/MP2K/Player.cs index e00bd21..4052a8e 100644 --- a/VG Music Studio/Core/GBA/MP2K/Player.cs +++ b/VG Music Studio/Core/GBA/MP2K/Player.cs @@ -86,7 +86,11 @@ private void SetTicks() SongEvent e = evs.Single(ev => ev.Offset == track.DataOffset); if (track.CallStackDepth == 0 && e.Ticks.Count > 0) { - break; + // HACK: this check ensure that we can't get into an infinite jump + // loop. We now ensure we can't jump backwards, so we don't need + // this break anymore, but there may be some things we could improve on here + + // break; } else { @@ -121,6 +125,7 @@ public void LoadSong(long index) } _tracks = null; } + Events = null; SongEntry entry = _config.Reader.ReadObject(_config.SongTableOffsets[0] + (index * 8)); SongHeader header = _config.Reader.ReadObject(entry.HeaderOffset - GBA.Utils.CartridgeOffset); @@ -256,6 +261,8 @@ void EmulateNote(byte key, byte velocity, byte addedDuration) { if (!EventExists(offset)) { + Debug.WriteLine(trackIndex.ToString()); + Debug.WriteLine("Loaded first voice command"); AddEvent(new VoiceCommand { Voice = cmd }); } break; @@ -264,6 +271,9 @@ void EmulateNote(byte key, byte velocity, byte addedDuration) { if (!EventExists(offset)) { + Debug.WriteLine(trackIndex.ToString()); + Debug.WriteLine("Loaded first volume command"); + AddEvent(new VolumeCommand { Volume = cmd }); } break; @@ -378,7 +388,10 @@ void EmulateNote(byte key, byte velocity, byte addedDuration) AddEvents(jumpOffset); } } - cont = false; + // HACK: It was previously assumed that a jump means there is no reasons to continue + // however there is some midis in GBA games which have instructions after the jump + // so don't breakout so we can continue to read those + // cont = false; break; } case 0xB3: @@ -458,7 +471,9 @@ void EmulateNote(byte key, byte velocity, byte addedDuration) sbyte transpose = _config.Reader.ReadSByte(); if (!EventExists(offset)) { - AddEvent(new TransposeCommand { Transpose = transpose }); + Debug.WriteLine(trackIndex.ToString()); + Debug.WriteLine("Loaded transpose command"); + AddEvent(new TransposeCommand { Transpose = transpose }); } break; } @@ -468,7 +483,9 @@ void EmulateNote(byte key, byte velocity, byte addedDuration) byte voice = _config.Reader.ReadByte(); if (!EventExists(offset)) { - AddEvent(new VoiceCommand { Voice = voice }); + Debug.WriteLine(trackIndex.ToString()); + Debug.WriteLine("Loaded second voice command"); + AddEvent(new VoiceCommand { Voice = voice }); } break; } @@ -477,7 +494,9 @@ void EmulateNote(byte key, byte velocity, byte addedDuration) byte volume = _config.Reader.ReadByte(); if (!EventExists(offset)) { - AddEvent(new VolumeCommand { Volume = volume }); + Debug.WriteLine(trackIndex.ToString()); + Debug.WriteLine("Loaded second volume command"); + AddEvent(new VolumeCommand { Volume = volume }); } break; } @@ -675,6 +694,7 @@ public void SaveAsMIDI(string fileName, MIDISaveArgs args) long startOfPatternTicks = 0, endOfPatternTicks = 0; sbyte transpose = 0; var playing = new List(); + for (int i = 0; i < Events[trackIndex].Count; i++) { SongEvent e = Events[trackIndex][i]; @@ -837,21 +857,38 @@ public void SaveAsMIDI(string fileName, MIDISaveArgs args) } case TransposeCommand keysh: { - transpose = keysh.Transpose; + Debug.WriteLine("Some transpose command"); + Debug.WriteLine(ticks); + transpose = keysh.Transpose; break; } case TuneCommand tune: { - track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, trackIndex, 24, tune.Tune)); + if (trackIndex == 8) + { + Debug.WriteLine("Write tune command"); + Debug.WriteLine(ticks); + } + track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, trackIndex, 24, tune.Tune)); break; } case VoiceCommand voice: { + if (trackIndex == 8) + { + Debug.WriteLine("Write voice command"); + Debug.WriteLine(ticks); + } track.Insert(ticks, new ChannelMessage(ChannelCommand.ProgramChange, trackIndex, voice.Voice)); break; } case VolumeCommand vol: { + if (trackIndex == 8) + { + Debug.WriteLine("Write volume command"); + Debug.WriteLine(ticks); + } double d = baseVolume / (double)0x7F; int volume = (int)(vol.Volume / d); // If there are rounding errors, fix them (happens if baseVolume is not 127 and baseVolume is not vol.Volume) @@ -1257,7 +1294,20 @@ private void ExecuteNext(Track track, ref bool update) } case 0xB2: { - track.DataOffset = (_config.ROM[track.DataOffset++] | (_config.ROM[track.DataOffset++] << 8) | (_config.ROM[track.DataOffset++] << 16) | (_config.ROM[track.DataOffset++] << 24)) - GBA.Utils.CartridgeOffset; + int jumpOffset = (_config.ROM[track.DataOffset++] | (_config.ROM[track.DataOffset++] << 8) | (_config.ROM[track.DataOffset++] << 16) | (_config.ROM[track.DataOffset++] << 24)) - GBA.Utils.CartridgeOffset; + // HACK: only do jumps if we are jumping forwards + // means we can't get into an infinite jump routine + if (jumpOffset > track.DataOffset) { + track.LastJumped = jumpOffset; + track.DataOffset = jumpOffset; + } + // HACK TODO: potentially use the Last Jumped value to allow us to jump backwards + // but ensure that we don't end up in an infinite loop + if (jumpOffset != track.LastJumped) + { + //track.LastJumped = jumpOffset; + //track.DataOffset = jumpOffset; + } break; } case 0xB3: diff --git a/VG Music Studio/Core/GBA/MP2K/Track.cs b/VG Music Studio/Core/GBA/MP2K/Track.cs index 1288008..70eac55 100644 --- a/VG Music Studio/Core/GBA/MP2K/Track.cs +++ b/VG Music Studio/Core/GBA/MP2K/Track.cs @@ -25,6 +25,7 @@ internal class Track public bool Stopped; public int DataOffset; public int[] CallStack = new int[3]; + public int LastJumped; public byte CallStackDepth; public byte RunCmd; public byte PrevKey;