write millisecond length to audio files

This commit is contained in:
itsmattkc 2019-05-20 12:12:05 +10:00
parent 30b3f7db1e
commit 001e62fe4f
2 changed files with 98 additions and 4 deletions

View file

@ -634,6 +634,7 @@ namespace Rebuilder
out_stream.Write(b, 0, b.Length);
// Copy MxOb data
long mxob_output_start = out_stream.Position;
byte[] mxob_data = new byte[mxob_len];
in_stream.Read(mxob_data, 0, mxob_len);
out_stream.Write(mxob_data, 0, mxob_len);
@ -643,6 +644,7 @@ namespace Rebuilder
List<Int32> ids = new List<Int32>();
List<List<byte[]>> data = new List<List<byte[]>>();
Int32 wav_id = -1;
long wav_ms_pos = -1;
Int32 flc_id = -1;
int flc_write_count = 1;
@ -659,11 +661,16 @@ namespace Rebuilder
{
if (mxob_data[i] == 0)
{
id = BitConverter.ToInt32(mxob_data, i + 1);
i++;
id = BitConverter.ToInt32(mxob_data, i);
break;
}
}
i += 12;
int ms_pos = i;
// Find type
for (; i < mxob_len - 4; i++)
{
@ -673,6 +680,8 @@ namespace Rebuilder
if (here == " WAV")
{
wav_id = id;
wav_ms_pos = mxob_output_start + ms_pos;
}
else if (here == " FLC")
{
@ -836,6 +845,17 @@ namespace Rebuilder
out_stream.Write(data_size_bytes, 0, data_size_bytes.Length);
long wav_end = wav_str.Position + wav_data_size;
Int32 data_rate_per_second = BitConverter.ToInt32(wav_header, 8);
Int32 millisecond_length = (Int32) Math.Round((double)wav_data_size * 1000.0 / (double)data_rate_per_second);
// Write WAV's millisecond length (as a multiple of 1)
out_stream.Position = wav_ms_pos;
data_size_bytes = BitConverter.GetBytes(millisecond_length);
out_stream.Write(data_size_bytes, 0, data_size_bytes.Length);
data_size_bytes = BitConverter.GetBytes((Int32)1);
out_stream.Write(data_size_bytes, 0, data_size_bytes.Length);
// Re-skip latter 4 bytes of MxCh header
out_stream.Position = old_pos;

View file

@ -23,10 +23,13 @@ namespace Rebuilder
CheckBox override_resolution;
NumericUpDown res_width;
NumericUpDown res_height;
CheckBox upscale_bitmaps;
Button run_button;
CheckBox advanced_button;
CheckBox multiple_instances;
MusicInjector music_injector = new MusicInjector();
Button music_replacement_btn = new Button();
@ -137,6 +140,14 @@ namespace Rebuilder
row++;
multiple_instances = new CheckBox();
multiple_instances.Anchor = AnchorStyles.Left | AnchorStyles.Right;
multiple_instances.Text = "Allow multiple instances";
grid.Controls.Add(multiple_instances, 0, row);
grid.SetColumnSpan(multiple_instances, 2);
row++;
stay_active_when_window_is_defocused = new CheckBox();
stay_active_when_window_is_defocused.Checked = false;
stay_active_when_window_is_defocused.Anchor = AnchorStyles.Left | AnchorStyles.Right;
@ -228,6 +239,14 @@ namespace Rebuilder
row++;
upscale_bitmaps = new CheckBox();
upscale_bitmaps.Enabled = false;
upscale_bitmaps.Anchor = AnchorStyles.Left | AnchorStyles.Right;
upscale_bitmaps.Text = "Upscale Bitmaps";
advanced_grid.Controls.Add(upscale_bitmaps, 1, row);
row++;
Label advanced_warning_lbl = new Label();
advanced_warning_lbl.Text = "WARNING: These features are experimental and often incomplete. Use at your own risk.";
advanced_warning_lbl.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
@ -253,6 +272,7 @@ namespace Rebuilder
tip.SetToolTip(stay_active_when_window_is_defocused, "LEGO Island's default behavior is to pause all operations when defocused. " +
"This setting overrides that behavior and keeps LEGO Island active even when unfocused.\n\n" +
"NOTE: This currently only works in windowed mode.");
tip.SetToolTip(upscale_bitmaps, "WARNING: This doesn't upscale the bitmaps' hitboxes yet and can make 2D areas like the Information Center difficult to navigate");
Controls.Add(grid);
Controls.Add(advanced_grid);
@ -287,7 +307,18 @@ namespace Rebuilder
fs.WriteByte(b);
}
private void WriteManyBytes(FileStream fs, byte b, int count, long pos = -1)
{
if (pos > -1)
{
fs.Position = pos;
}
for (int i=0;i< count;i++)
fs.WriteByte(b);
}
private void WriteInt32(FileStream fs, Int32 integer, long pos = -1)
{
byte[] int_bytes = BitConverter.GetBytes(integer);
@ -350,6 +381,12 @@ namespace Rebuilder
WriteByte(lego1dll, 0x80, aug_build ? 0xAD7D3 : 0xADD43);
}
if (multiple_instances.Checked)
{
// LEGO Island uses FindWindowA in user32.dll to determine if it's already running, here we replace the call with moving 0x0 into EAX, simulating a NULL response from FindWindowA
WriteByte(isleexe, 0xEB, 0x10B5);
}
// Redirect JUKEBOX.SI if we're inserting music
if (music_injector.ReplaceCount() > 0)
{
@ -358,7 +395,6 @@ namespace Rebuilder
Uri uri2 = new Uri(source_dir + "/ISLE.EXE");
Uri relative = uri2.MakeRelativeUri(uri1);
string jukebox_path = "\\" + relative.ToString().Replace("/", "\\");
//Console.WriteLine(jukebox_path);
if (aug_build)
{
@ -388,6 +424,33 @@ namespace Rebuilder
// Changes D3D render size
WriteInt32(isleexe, (Int32)res_width.Value-1, 0x4D0);
WriteInt32(isleexe, (Int32)res_height.Value-1, 0x4D7);
// Write code to upscale the bitmaps
if (upscale_bitmaps.Checked)
{
Write(lego1dll, new byte[] { 0xE9, 0x2D, 0x01, 0x00, 0x00, 0x8B, 0x56, 0x1C, 0x6A, 0x00, 0x8D, 0x45, 0xE4, 0xF6, 0x42, 0x30, 0x08, 0x74, 0x07, 0x68, 0x00, 0x80, 0x00, 0x00, 0xEB, 0x02, 0x6A, 0x00, 0x8B, 0x3B, 0x50, 0x51, 0x8D, 0x4D, 0xD4, 0x51, 0x53, 0x53, 0x50, 0x68 }, 0xB20E9);
WriteFloat(lego1dll, (float) res_height.Value / 480.0f);
Int32 x_offset = (Int32)Math.Round((res_width.Value - (res_height.Value / 3 * 4))/2);
Write(lego1dll, new byte[] { 0xDB, 0x45, 0xD4, 0xD8, 0x0C, 0x24, 0xDB, 0x5D, 0xD4, 0xDB, 0x45, 0xD8, 0xD8, 0x0C, 0x24, 0xDB, 0x5D, 0xD8, 0xDB, 0x45, 0xDC, 0xD8, 0x0C, 0x24, 0xDB, 0x5D, 0xDC, 0xDB, 0x45, 0xE0, 0xD8, 0x0C, 0x24, 0xDB, 0x5D, 0xE0, 0x58, 0x8B, 0x45, 0xD4, 0x05 });
WriteInt32(lego1dll, x_offset);
Write(lego1dll, new byte[] { 0x89, 0x45, 0xD4, 0x8B, 0x45, 0xDC, 0x05 });
WriteInt32(lego1dll, x_offset);
Write(lego1dll, new byte[] { 0x89, 0x45, 0xDC });
// Frees up 143 bytes of NOPs
WriteManyBytes(lego1dll, 0x90, 143);
Write(lego1dll, new byte[] { 0x58, 0x5B });
Write(lego1dll, new byte[] { 0xE9, 0xF6, 0xFD, 0xFF, 0xFF }, 0xB22F3);
// Frees up 19 bytes of NOPs
WriteManyBytes(lego1dll, 0x90, 19);
}
}
if (aug_build && redirect_saves.Checked)
@ -470,6 +533,7 @@ namespace Rebuilder
{
res_width.Enabled = override_resolution.Checked;
res_height.Enabled = override_resolution.Checked;
upscale_bitmaps.Enabled = override_resolution.Checked;
}
private void CopyRegistryKey(RegistryKey src, RegistryKey dst)
@ -596,8 +660,9 @@ namespace Rebuilder
{
key.CreateSubKey(temp_path + "\\ISLE.EXE");
//string compat_string = "HIGHDPIAWARE";
string compat_string = "HIGHDPIAWARE DWM8And16BitMitigation";
if (!run_fullscreen.Checked)
{
compat_string += " 256COLOR";
@ -713,6 +778,11 @@ namespace Rebuilder
music_injector.LoadData(stream);
UpdateMusicInjectorBtnText();
}
else if (stream.Name == "upscalebitmaps")
{
stream.Read();
upscale_bitmaps.Checked = bool.Parse(stream.Value);
}
}
}
@ -768,6 +838,10 @@ namespace Rebuilder
stream.WriteString(res_height.Value.ToString());
stream.WriteEndElement(); // overrideresheight
stream.WriteStartElement("upscalebitmaps");
stream.WriteString(upscale_bitmaps.Checked.ToString());
stream.WriteEndElement();
stream.WriteStartElement("musicinjection");
music_injector.SaveData(stream);
stream.WriteEndElement(); // musicinjection