code optimization

This commit is contained in:
2024-06-05 19:21:19 +02:00
parent 04c965ca80
commit 547dfc95bd
225 changed files with 17925 additions and 18561 deletions

View File

@@ -1,151 +1,148 @@
using System; namespace SM64Lib.LIBMIO0;
namespace SM64Lib.LIBMIO0 public struct MIO0_Header
{ {
public struct MIO0_Header public uint dest_size;
public uint comp_offset;
public uint uncomp_offset;
public bool big_endian;
};
public class MIO0
{
private const int MIO0_HEADER_LENGTH = 16;
private static int GET_BIT(byte[] buf, int offset, int bit)
{ {
public uint dest_size; return buf[(bit / 8) + offset] & (1 << (7 - (bit % 8)));
public uint comp_offset; }
public uint uncomp_offset;
public bool big_endian;
};
public class MIO0 private static bool compareByteArrays(byte[] buf1, byte[] buf2, int length)
{ {
for (int i = 0; i < length; ++i)
if (buf1[i] != buf2[i]) return false;
return true;
}
private const int MIO0_HEADER_LENGTH = 16; private static uint read_u32_be(byte[] buf, int off)
{
return (uint)(((buf)[off + 0] << 24) + ((buf)[off + 1] << 16) +
((buf)[off + 2] << 8) + ((buf)[off + 3]));
}
private static int GET_BIT(byte[] buf, int offset, int bit) private static uint read_u32_le(byte[] buf, int off)
{
return (uint)(((buf)[off + 1] << 24) + ((buf)[off + 0] << 16) +
((buf)[off + 3] << 8) + ((buf)[off + 2]));
}
private static void write_u32_be(byte[] buf, uint val, int off)
{
buf[off + 0] = (byte)((val >> 24) & 0xFF);
buf[off + 1] = (byte)((val >> 16) & 0xFF);
buf[off + 2] = (byte)((val >> 8) & 0xFF);
buf[off + 3] = (byte)(val & 0xFF);
}
///<summary>
/// decode MIO0 header<para/>
/// returns true if valid header, false otherwise
///</summary>
public static bool decode_header(byte[] buf, ref MIO0_Header head)
{
byte[] mio0_ascii_be = new byte[] { 0x4D, 0x49, 0x4F, 0x30 };
byte[] mio0_ascii_le = new byte[] { 0x49, 0x4D, 0x30, 0x4F };
if (compareByteArrays(buf, mio0_ascii_be, 4))
{ {
return buf[(bit / 8) + offset] & (1 << (7 - (bit % 8))); head.dest_size = read_u32_be(buf, 4);
head.comp_offset = read_u32_be(buf, 8);
head.uncomp_offset = read_u32_be(buf, 12);
head.big_endian = true;
return true;
} }
else if (compareByteArrays(buf, mio0_ascii_le, 4))
private static bool compareByteArrays(byte[] buf1, byte[] buf2, int length)
{ {
for (int i = 0; i < length; ++i) head.dest_size = read_u32_le(buf, 4);
if (buf1[i] != buf2[i]) return false; head.comp_offset = read_u32_le(buf, 8);
head.uncomp_offset = read_u32_le(buf, 12);
head.big_endian = false;
return true; return true;
} }
private static uint read_u32_be(byte[] buf, int off) return false;
{
return (uint)(((buf)[off + 0] << 24) + ((buf)[off + 1] << 16) +
((buf)[off + 2] << 8) + ((buf)[off + 3]));
}
private static uint read_u32_le(byte[] buf, int off)
{
return (uint)(((buf)[off + 1] << 24) + ((buf)[off + 0] << 16) +
((buf)[off + 3] << 8) + ((buf)[off + 2]));
}
private static void write_u32_be(byte[] buf, uint val, int off)
{
buf[off + 0] = (byte)((val >> 24) & 0xFF);
buf[off + 1] = (byte)((val >> 16) & 0xFF);
buf[off + 2] = (byte)((val >> 8) & 0xFF);
buf[off + 3] = (byte)(val & 0xFF);
}
///<summary>
/// decode MIO0 header<para/>
/// returns true if valid header, false otherwise
///</summary>
public static bool decode_header(byte[] buf, ref MIO0_Header head)
{
byte[] mio0_ascii_be = new byte[] { 0x4D, 0x49, 0x4F, 0x30 };
byte[] mio0_ascii_le = new byte[] { 0x49, 0x4D, 0x30, 0x4F };
if (compareByteArrays(buf, mio0_ascii_be, 4))
{
head.dest_size = read_u32_be(buf, 4);
head.comp_offset = read_u32_be(buf, 8);
head.uncomp_offset = read_u32_be(buf, 12);
head.big_endian = true;
return true;
}
else if (compareByteArrays(buf, mio0_ascii_le, 4))
{
head.dest_size = read_u32_le(buf, 4);
head.comp_offset = read_u32_le(buf, 8);
head.uncomp_offset = read_u32_le(buf, 12);
head.big_endian = false;
return true;
}
return false;
}
///<summary>
/// encode MIO0 header from struct
///</summary>
public static void encode_header(byte[] buf, ref MIO0_Header head)
{
write_u32_be(buf, 0x4D494F30, 0); // write "MIO0" at start of buffer
write_u32_be(buf, head.dest_size, 4);
write_u32_be(buf, head.comp_offset, 8);
write_u32_be(buf, head.uncomp_offset, 12);
}
///<summary>
/// decode MIO0 data<para/>
/// mio0_buf: buffer containing MIO0 data<para/>
/// returns the raw data as a byte array
///</summary>
public static byte[] mio0_decode(byte[] mio0_buf)
{
MIO0_Header head = new MIO0_Header();
uint bytes_written = 0;
int bit_idx = 0;
int comp_idx = 0;
int uncomp_idx = 0;
bool valid;
// extract header
valid = decode_header(mio0_buf, ref head);
// verify MIO0 header
if (!valid)
{
return null;
}
if (!head.big_endian)
{
return null;
}
byte[] decoded = new byte[head.dest_size];
// decode data
while (bytes_written < head.dest_size)
{
if (GET_BIT(mio0_buf, MIO0_HEADER_LENGTH, bit_idx) > 0)
{
// 1 - pull uncompressed data
decoded[bytes_written] = mio0_buf[head.uncomp_offset + uncomp_idx];
bytes_written++;
uncomp_idx++;
}
else
{
// 0 - read compressed data
byte a = mio0_buf[head.comp_offset + comp_idx + 0];
byte b = mio0_buf[head.comp_offset + comp_idx + 1];
comp_idx += 2;
int length = ((a & 0xF0) >> 4) + 3;
int idx = ((a & 0x0F) << 8) + b + 1;
for (int i = 0; i < length; i++)
{
decoded[bytes_written] = decoded[bytes_written - idx];
bytes_written++;
}
}
bit_idx++;
}
return decoded;
}
} }
///<summary>
/// encode MIO0 header from struct
///</summary>
public static void encode_header(byte[] buf, ref MIO0_Header head)
{
write_u32_be(buf, 0x4D494F30, 0); // write "MIO0" at start of buffer
write_u32_be(buf, head.dest_size, 4);
write_u32_be(buf, head.comp_offset, 8);
write_u32_be(buf, head.uncomp_offset, 12);
}
///<summary>
/// decode MIO0 data<para/>
/// mio0_buf: buffer containing MIO0 data<para/>
/// returns the raw data as a byte array
///</summary>
public static byte[] mio0_decode(byte[] mio0_buf)
{
MIO0_Header head = new MIO0_Header();
uint bytes_written = 0;
int bit_idx = 0;
int comp_idx = 0;
int uncomp_idx = 0;
bool valid;
// extract header
valid = decode_header(mio0_buf, ref head);
// verify MIO0 header
if (!valid)
{
return null;
}
if (!head.big_endian)
{
return null;
}
byte[] decoded = new byte[head.dest_size];
// decode data
while (bytes_written < head.dest_size)
{
if (GET_BIT(mio0_buf, MIO0_HEADER_LENGTH, bit_idx) > 0)
{
// 1 - pull uncompressed data
decoded[bytes_written] = mio0_buf[head.uncomp_offset + uncomp_idx];
bytes_written++;
uncomp_idx++;
}
else
{
// 0 - read compressed data
byte a = mio0_buf[head.comp_offset + comp_idx + 0];
byte b = mio0_buf[head.comp_offset + comp_idx + 1];
comp_idx += 2;
int length = ((a & 0xF0) >> 4) + 3;
int idx = ((a & 0x0F) << 8) + b + 1;
for (int i = 0; i < length; i++)
{
decoded[bytes_written] = decoded[bytes_written - idx];
bytes_written++;
}
}
bit_idx++;
}
return decoded;
}
} }

View File

@@ -1,6 +1,4 @@
using System.Reflection; using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly // Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von // für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,4 @@
using System.Reflection; using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von

File diff suppressed because it is too large Load Diff

View File

@@ -1,102 +1,98 @@
using OfficeOpenXml; using OfficeOpenXml;
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SM64Lib.Text.Exporters namespace SM64Lib.Text.Exporters;
public class ExcelExporter
{ {
public class ExcelExporter public ExcelExporter()
{ {
public ExcelExporter() ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
}
public async Task Export(string destFilePath, TextGroup[] groups)
{
var pkg = new ExcelPackage();
foreach (var tg in groups)
{ {
ExcelPackage.LicenseContext = LicenseContext.NonCommercial; var ws = pkg.Workbook.Worksheets.Add(tg.TextGroupInfo.Name);
var hasDialogCells = false;
ws.Cells.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Top;
ws.Cells.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left;
ws.Row(1).Style.Font.Bold = true;
ws.Cells[1, 1].Value = "#";
ws.Cells[1, 2].Value = "Text";
for (int i = 0; i < tg.Count; i++)
{
var ti = tg[i];
var ri = i + 2;
ws.Cells[ri, 1].Value = i;
ws.Cells[ri, 2].Value = ti.Text;
if (ti is TextTableDialogItem)
hasDialogCells = true;
}
for (int ri = 1; ri <= ws.Cells.Rows; ri++)
{
var r = ws.Row(ri);
r.CustomHeight = false;
}
if (hasDialogCells)
{
var c = ws.Column(2);
c.Style.WrapText = true;
c.Width = 30;
}
for (int ci = 1; ci <= 2; ci++)
{
var c = ws.Column(ci);
if (!c.Style.WrapText)
c.AutoFit();
}
} }
public async Task Export(string destFilePath, TextGroup[] groups) await pkg.SaveAsAsync(new FileInfo(destFilePath));
pkg.Dispose();
}
public async Task Import(string filePath, TextGroup[] groups)
{
try
{ {
var pkg = new ExcelPackage(); var pkg = new ExcelPackage();
await pkg.LoadAsync(new FileInfo(filePath));
foreach (var tg in groups) foreach (var tg in groups)
{ {
var ws = pkg.Workbook.Worksheets.Add(tg.TextGroupInfo.Name); var ws = pkg.Workbook.Worksheets[tg.TextGroupInfo.Name];
var hasDialogCells = false; if (ws is not null)
ws.Cells.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Top;
ws.Cells.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left;
ws.Row(1).Style.Font.Bold = true;
ws.Cells[1, 1].Value = "#";
ws.Cells[1, 2].Value = "Text";
for (int i = 0; i < tg.Count; i++)
{ {
var ti = tg[i]; for (int iti = 0; iti < tg.Count; iti++)
var ri = i + 2;
ws.Cells[ri, 1].Value = i;
ws.Cells[ri, 2].Value = ti.Text;
if (ti is TextTableDialogItem)
hasDialogCells = true;
}
for (int ri = 1; ri <= ws.Cells.Rows; ri++)
{
var r = ws.Row(ri);
r.CustomHeight = false;
}
if (hasDialogCells)
{
var c = ws.Column(2);
c.Style.WrapText = true;
c.Width = 30;
}
for (int ci = 1; ci <= 2; ci++)
{
var c = ws.Column(ci);
if (!c.Style.WrapText)
c.AutoFit();
}
}
await pkg.SaveAsAsync(new FileInfo(destFilePath));
pkg.Dispose();
}
public async Task Import(string filePath, TextGroup[] groups)
{
try
{
var pkg = new ExcelPackage();
await pkg.LoadAsync(new FileInfo(filePath));
foreach (var tg in groups)
{
var ws = pkg.Workbook.Worksheets[tg.TextGroupInfo.Name];
if (ws is not null)
{ {
for (int iti = 0; iti < tg.Count; iti++) var ti = tg[iti];
{ var ri = iti + 2;
var ti = tg[iti]; var c = ws.Cells[ri, 2];
var ri = iti + 2;
var c = ws.Cells[ri, 2];
ti.Text = ((string)c.Value).Replace("\r\n", "\n").Replace("\n", "\r\n"); ti.Text = ((string)c.Value).Replace("\r\n", "\n").Replace("\n", "\r\n");
tg.NeedToSave = true; tg.NeedToSave = true;
}
} }
} }
}
pkg.Dispose(); pkg.Dispose();
} }
catch (Exception) catch (Exception)
{ {
}
} }
} }
} }

View File

@@ -1,6 +1,4 @@
using System.Reflection; using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly // Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von // für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von

View File

@@ -1,48 +1,43 @@
using System; using System.IO;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SM64Lib.Text.Exporters namespace SM64Lib.Text.Exporters;
public class TxtExporter
{ {
public class TxtExporter public async Task Export(string destFilePath, TextGroup[] groups)
{ {
public async Task Export(string destFilePath, TextGroup[] groups) var sw = new StreamWriter(destFilePath);
for (int itg = 0; itg < groups.Length; itg++)
{ {
var sw = new StreamWriter(destFilePath); var tg = groups[itg];
for (int itg = 0; itg < groups.Length; itg++) if (itg != 0)
{
var tg = groups[itg];
if (itg != 0)
await sw.WriteLineAsync("------------------------------\n");
await sw.WriteLineAsync($"Text Group - {tg.TextGroupInfo.Name}\n");
await sw.WriteLineAsync("------------------------------\n"); await sw.WriteLineAsync("------------------------------\n");
await sw.WriteLineAsync($"Text Group - {tg.TextGroupInfo.Name}\n");
await sw.WriteLineAsync("------------------------------\n");
for (int iti = 0; iti < tg.Count; iti++) for (int iti = 0; iti < tg.Count; iti++)
{
var ti = tg[iti];
if (ti is TextTableDialogItem)
{ {
var ti = tg[iti]; await sw.WriteLineAsync($"Dialog #{iti}\n");
await sw.WriteLineAsync(ti.Text);
if (ti is TextTableDialogItem) await sw.WriteLineAsync("\n\n");
{ }
await sw.WriteLineAsync($"Dialog #{iti}\n"); else
await sw.WriteLineAsync(ti.Text); {
await sw.WriteLineAsync("\n\n"); await sw.WriteLineAsync($"Text Item #{iti}");
} await sw.WriteLineAsync(ti.Text);
else await sw.WriteLineAsync();
{
await sw.WriteLineAsync($"Text Item #{iti}");
await sw.WriteLineAsync(ti.Text);
await sw.WriteLineAsync();
}
} }
} }
await sw.FlushAsync();
sw.Close();
} }
await sw.FlushAsync();
sw.Close();
} }
} }

View File

@@ -1,5 +1,4 @@
using global::System; using global::System;
using global::System.Reflection;
using global::System.Runtime.InteropServices; using global::System.Runtime.InteropServices;
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View File

@@ -1,89 +1,87 @@
using System; using System;
using Microsoft.VisualBasic.CompilerServices;
namespace SM64Lib.TextValueConverter namespace SM64Lib.TextValueConverter;
public static class TextValueConverter
{ {
public static class TextValueConverter public static event WantIntegerValueModeEventHandler WantIntegerValueMode;
public delegate void WantIntegerValueModeEventHandler(WantIntegerValueModeEventArgs e);
public static int ValueFromText(string Text, int DefaultValue = 0, int useIVM = -1)
{ {
public static event WantIntegerValueModeEventHandler WantIntegerValueMode; return Convert.ToInt32(LongFromText(Text, DefaultValue, useIVM));
public delegate void WantIntegerValueModeEventHandler(WantIntegerValueModeEventArgs e); }
public static int ValueFromText(string Text, int DefaultValue = 0, int useIVM = -1) public static long LongFromText(string Text, long DefaultValue = 0, int useIVM = -1)
{
try
{ {
return Convert.ToInt32(LongFromText(Text, DefaultValue, useIVM)); int IVM = useIVM > -1 ? useIVM : GetIntegerValueMode();
} Text = Text?.ToLower()?.Trim();
public static long LongFromText(string Text, long DefaultValue = 0, int useIVM = -1) if (string.IsNullOrWhiteSpace(Text))
{ return 0;
try
switch (true)
{ {
int IVM = useIVM > -1 ? useIVM : GetIntegerValueMode(); case object _ when Text.StartsWith("0x"):
Text = Text?.ToLower()?.Trim(); case object _ when Text.StartsWith("&h"):
return Convert.ToInt32(Text.Substring(2), 16);
if (string.IsNullOrWhiteSpace(Text)) case object _ when Text.StartsWith("$"):
return 0; return Convert.ToInt32(Text.Substring(1), 16);
case object _ when Text.StartsWith("0b"):
switch (true) case object _ when Text.StartsWith("&b"):
{ return Convert.ToInt32(Text.Substring(2), 2);
case object _ when Text.StartsWith("0x"):
case object _ when Text.StartsWith("&h"):
return Convert.ToInt32(Text.Substring(2), 16);
case object _ when Text.StartsWith("$"):
return Convert.ToInt32(Text.Substring(1), 16);
case object _ when Text.StartsWith("0b"):
case object _ when Text.StartsWith("&b"):
return Convert.ToInt32(Text.Substring(2), 2);
default:
return Convert.ToInt32(Text);
}
}
catch (Exception)
{
return DefaultValue;
}
}
public static string TextFromValue(long Value, int IVM = -1, int charCount = 0)
{
if (IVM == -1)
{
IVM = GetIntegerValueMode();
}
switch (IVM)
{
case 0:
return Value.ToString(GetCharCountAsZeroString(charCount));
case 1:
return "0x" + Value.ToString("X" + (charCount > 0 ? charCount.ToString() : ""));
case 2:
return "&H" + Value.ToString("X" + (charCount > 0 ? charCount.ToString() : ""));
case 3:
return "$" + Value.ToString("X" + (charCount > 0 ? charCount.ToString() : ""));
default: default:
return string.Empty; return Convert.ToInt32(Text);
} }
} }
catch (Exception)
private static string GetCharCountAsZeroString(int charCount)
{ {
string GetCharCountAsZeroStringRet = default; return DefaultValue;
GetCharCountAsZeroStringRet = "";
while (GetCharCountAsZeroStringRet.Length < charCount)
GetCharCountAsZeroStringRet += "0";
return GetCharCountAsZeroStringRet;
}
private static int GetIntegerValueMode()
{
var e = new WantIntegerValueModeEventArgs();
WantIntegerValueMode?.Invoke(e);
return e.IntegerValueMode;
} }
} }
public class WantIntegerValueModeEventArgs : EventArgs public static string TextFromValue(long Value, int IVM = -1, int charCount = 0)
{ {
public int IntegerValueMode { get; set; } if (IVM == -1)
{
IVM = GetIntegerValueMode();
}
switch (IVM)
{
case 0:
return Value.ToString(GetCharCountAsZeroString(charCount));
case 1:
return "0x" + Value.ToString("X" + (charCount > 0 ? charCount.ToString() : ""));
case 2:
return "&H" + Value.ToString("X" + (charCount > 0 ? charCount.ToString() : ""));
case 3:
return "$" + Value.ToString("X" + (charCount > 0 ? charCount.ToString() : ""));
default:
return string.Empty;
}
} }
private static string GetCharCountAsZeroString(int charCount)
{
string GetCharCountAsZeroStringRet = default;
GetCharCountAsZeroStringRet = "";
while (GetCharCountAsZeroStringRet.Length < charCount)
GetCharCountAsZeroStringRet += "0";
return GetCharCountAsZeroStringRet;
}
private static int GetIntegerValueMode()
{
var e = new WantIntegerValueModeEventArgs();
WantIntegerValueMode?.Invoke(e);
return e.IntegerValueMode;
}
}
public class WantIntegerValueModeEventArgs : EventArgs
{
public int IntegerValueMode { get; set; }
} }

View File

@@ -1,83 +1,77 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Data; using SM64Lib.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.ASM namespace SM64Lib.ASM;
public class CustomAsmArea
{ {
public class CustomAsmArea public byte[] AreaBytes { get; set; }
[JsonProperty(nameof(Config))]
private CustomAsmAreaConfig config;
[JsonIgnore]
public CustomAsmAreaConfig Config
{ {
public byte[] AreaBytes { get; set; } get
[JsonProperty(nameof(Config))]
private CustomAsmAreaConfig config;
[JsonIgnore]
public CustomAsmAreaConfig Config
{ {
get if (config == null)
{ config = new CustomAsmAreaConfig();
if (config == null) return config;
config = new CustomAsmAreaConfig();
return config;
}
}
[JsonConstructor]
private CustomAsmArea(JsonConstructorAttribute emptyObject)
{
}
public CustomAsmArea()
: this(true)
{
}
private CustomAsmArea(bool createEmptyAreaBytesArray)
: this(null, createEmptyAreaBytesArray)
{
}
public CustomAsmArea(CustomAsmAreaConfig config)
: this(config, false)
{
}
private CustomAsmArea(CustomAsmAreaConfig config, bool createEmptyAreaBytesArray)
{
this.config = config;
if (createEmptyAreaBytesArray)
AreaBytes = new byte[] { };
}
public void Load(BinaryData data, CustomAsmBankConfig bankConfig)
{
if (Config.RomAddress != -1 && Config.Length > 0)
{
data.Position = Config.RomAddress;
AreaBytes = data.Read(Config.Length);
}
else
AreaBytes = new byte[] { };
}
public int Save(BinaryData data, int address, CustomAsmBankConfig bankConfig)
{
data.Position = address;
data.Write(AreaBytes);
return UpdateAddresses(address, bankConfig);
}
internal int UpdateAddresses(int address, CustomAsmBankConfig bankConfig)
{
Config.RomAddress = address;
Config.Length = AreaBytes.Length;
Config.RamAddress = address - bankConfig.GetRomStartAddress() + bankConfig.GetRamStartAddress();
return Config.Length;
} }
} }
[JsonConstructor]
private CustomAsmArea(JsonConstructorAttribute emptyObject)
{
}
public CustomAsmArea()
: this(true)
{
}
private CustomAsmArea(bool createEmptyAreaBytesArray)
: this(null, createEmptyAreaBytesArray)
{
}
public CustomAsmArea(CustomAsmAreaConfig config)
: this(config, false)
{
}
private CustomAsmArea(CustomAsmAreaConfig config, bool createEmptyAreaBytesArray)
{
this.config = config;
if (createEmptyAreaBytesArray)
AreaBytes = new byte[] { };
}
public void Load(BinaryData data, CustomAsmBankConfig bankConfig)
{
if (Config.RomAddress != -1 && Config.Length > 0)
{
data.Position = Config.RomAddress;
AreaBytes = data.Read(Config.Length);
}
else
AreaBytes = new byte[] { };
}
public int Save(BinaryData data, int address, CustomAsmBankConfig bankConfig)
{
data.Position = address;
data.Write(AreaBytes);
return UpdateAddresses(address, bankConfig);
}
internal int UpdateAddresses(int address, CustomAsmBankConfig bankConfig)
{
Config.RomAddress = address;
Config.Length = AreaBytes.Length;
Config.RamAddress = address - bankConfig.GetRomStartAddress() + bankConfig.GetRamStartAddress();
return Config.Length;
}
} }

View File

@@ -1,39 +1,33 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Pilz.Cryptography; using Pilz.Cryptography;
using Pilz.Json.Converters; using Pilz.Json.Converters;
namespace SM64Lib.ASM namespace SM64Lib.ASM;
public class CustomAsmAreaConfig
{ {
public class CustomAsmAreaConfig internal delegate void RequestCustomAsmAreaEventHandler(CustomAsmAreaConfig config, RequestCustomAsmAreaEventArgs request);
internal static event RequestCustomAsmAreaEventHandler RequestCustomAsmArea;
[JsonConverter(typeof(UniquieIDStringJsonConverter))]
public UniquieID ID { get; set; } = new();
public string Name { get; set; }
[JsonProperty]
public int RamAddress { get; internal set; } = -1;
[JsonProperty]
public int RomAddress { get; internal set; } = -1;
[JsonProperty]
public int Length { get; internal set; } = 0;
public CustomAsmArea FindCustomAsmArea()
{ {
internal delegate void RequestCustomAsmAreaEventHandler(CustomAsmAreaConfig config, RequestCustomAsmAreaEventArgs request); var args = new RequestCustomAsmAreaEventArgs();
internal static event RequestCustomAsmAreaEventHandler RequestCustomAsmArea; RequestCustomAsmArea?.Invoke(this, args);
return args.CustomAsmArea;
}
[JsonConverter(typeof(UniquieIDStringJsonConverter))] internal class RequestCustomAsmAreaEventArgs
public UniquieID ID { get; set; } = new(); {
public string Name { get; set; } public CustomAsmArea CustomAsmArea { get; set; }
[JsonProperty]
public int RamAddress { get; internal set; } = -1;
[JsonProperty]
public int RomAddress { get; internal set; } = -1;
[JsonProperty]
public int Length { get; internal set; } = 0;
public CustomAsmArea FindCustomAsmArea()
{
var args = new RequestCustomAsmAreaEventArgs();
RequestCustomAsmArea?.Invoke(this, args);
return args.CustomAsmArea;
}
internal class RequestCustomAsmAreaEventArgs
{
public CustomAsmArea CustomAsmArea { get; set; }
}
} }
} }

View File

@@ -1,85 +1,81 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.ASM namespace SM64Lib.ASM;
public class CustomAsmBank
{ {
public class CustomAsmBank public CustomAsmBankConfig Config { get; }
[JsonIgnore]
public List<CustomAsmArea> Areas { get; } = new List<CustomAsmArea>();
public CustomAsmBank() : this(new CustomAsmBankConfig())
{ {
public CustomAsmBankConfig Config { get; } }
[JsonIgnore]
public List<CustomAsmArea> Areas { get; } = new List<CustomAsmArea>();
public CustomAsmBank() : this(new CustomAsmBankConfig()) public CustomAsmBank(CustomAsmBankConfig config)
{
Config = config;
}
public void Load(RomManager romManager)
{
Areas.Clear();
bool canLoadArea(CustomAsmAreaConfig areaConfig) =>
areaConfig.RomAddress != -1;
if (Config.Areas.Where(n => canLoadArea(n)).Any())
{ {
} var data = romManager.GetBinaryRom(System.IO.FileAccess.Read);
public CustomAsmBank(CustomAsmBankConfig config) foreach (var areaConfig in Config.Areas)
{
Config = config;
}
public void Load(RomManager romManager)
{
Areas.Clear();
bool canLoadArea(CustomAsmAreaConfig areaConfig) =>
areaConfig.RomAddress != -1;
if (Config.Areas.Where(n => canLoadArea(n)).Any())
{ {
var data = romManager.GetBinaryRom(System.IO.FileAccess.Read); var area = new CustomAsmArea(areaConfig);
area.Config.ID.GenerateIfNull();
foreach (var areaConfig in Config.Areas) area.Load(data, Config);
{ Areas.Add(area);
var area = new CustomAsmArea(areaConfig);
area.Config.ID.GenerateIfNull();
area.Load(data, Config);
Areas.Add(area);
}
data.Close();
} }
data.Close();
}
}
public void Save(RomManager romManager)
{
var startAddr = Config.GetRomStartAddress();
var curRomAddr = startAddr;
if (Areas.Any())
{
var data = romManager.GetBinaryRom(System.IO.FileAccess.ReadWrite);
foreach (var area in Areas)
curRomAddr += area.Save(data, curRomAddr, Config);
data.Close();
} }
public void Save(RomManager romManager) UpdateAreaConfigCollection();
Config.Length = curRomAddr - startAddr;
}
public void UpdateAddresses()
{
if (Areas.Any())
{ {
var startAddr = Config.GetRomStartAddress(); var startAddr = Config.GetRomStartAddress();
var curRomAddr = startAddr; var curRomAddr = startAddr;
foreach (var area in Areas)
if (Areas.Any()) curRomAddr += area.UpdateAddresses(curRomAddr, Config);
{
var data = romManager.GetBinaryRom(System.IO.FileAccess.ReadWrite);
foreach (var area in Areas)
curRomAddr += area.Save(data, curRomAddr, Config);
data.Close();
}
UpdateAreaConfigCollection();
Config.Length = curRomAddr - startAddr; Config.Length = curRomAddr - startAddr;
} }
}
public void UpdateAddresses() public void UpdateAreaConfigCollection()
{ {
if (Areas.Any()) Config.Areas.Clear();
{ Config.Areas.AddRange(Areas.Select(n => n.Config));
var startAddr = Config.GetRomStartAddress();
var curRomAddr = startAddr;
foreach (var area in Areas)
curRomAddr += area.UpdateAddresses(curRomAddr, Config);
Config.Length = curRomAddr - startAddr;
}
}
public void UpdateAreaConfigCollection()
{
Config.Areas.Clear();
Config.Areas.AddRange(Areas.Select(n => n.Config));
}
} }
} }

View File

@@ -1,50 +1,45 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.ASM namespace SM64Lib.ASM;
public class CustomAsmBankConfig
{ {
public class CustomAsmBankConfig public static int DefaultMaxLength { get; set; } = 0xA000;
public static int DefaultRomStartAddress { get; internal set; } = 0x1206000;
public static int DefaultRamStartAddress { get; internal set; } = 0x406000;
public List<CustomAsmAreaConfig> Areas { get; } = new List<CustomAsmAreaConfig>();
public int MaxLength { get; set; } = -1;
[JsonProperty]
public int Length { get; internal set; } = -1;
public int RomStartAddress { get; set; } = -1;
public int RamStartAddress { get; set; } = -1;
public int GetRomStartAddress()
=> GetRomStartAddressAdv().address;
public (int address, bool isDefault) GetRomStartAddressAdv()
{ {
public static int DefaultMaxLength { get; set; } = 0xA000; bool isDefault = RomStartAddress == -1;
public static int DefaultRomStartAddress { get; internal set; } = 0x1206000; return (isDefault ? DefaultRomStartAddress : RomStartAddress, isDefault);
public static int DefaultRamStartAddress { get; internal set; } = 0x406000; }
public List<CustomAsmAreaConfig> Areas { get; } = new List<CustomAsmAreaConfig>(); public int GetRamStartAddress()
public int MaxLength { get; set; } = -1; => GetRamStartAddressAdv().address;
[JsonProperty]
public int Length { get; internal set; } = -1;
public int RomStartAddress { get; set; } = -1;
public int RamStartAddress { get; set; } = -1;
public int GetRomStartAddress() public (int address, bool isDefault) GetRamStartAddressAdv()
=> GetRomStartAddressAdv().address; {
bool isDefault = RamStartAddress == -1;
return (isDefault ? DefaultRamStartAddress : RamStartAddress, isDefault);
}
public (int address, bool isDefault) GetRomStartAddressAdv() public int GetMaxLength()
{ => GetMaxLengthAdv().length;
bool isDefault = RomStartAddress == -1;
return (isDefault ? DefaultRomStartAddress : RomStartAddress, isDefault);
}
public int GetRamStartAddress() public (int length, bool isDefault) GetMaxLengthAdv()
=> GetRamStartAddressAdv().address; {
bool isDefault = RamStartAddress == -1;
public (int address, bool isDefault) GetRamStartAddressAdv() return (isDefault ? DefaultMaxLength : MaxLength, isDefault);
{
bool isDefault = RamStartAddress == -1;
return (isDefault ? DefaultRamStartAddress : RamStartAddress, isDefault);
}
public int GetMaxLength()
=> GetMaxLengthAdv().length;
public (int length, bool isDefault) GetMaxLengthAdv()
{
bool isDefault = RamStartAddress == -1;
return (isDefault ? DefaultMaxLength : MaxLength, isDefault);
}
} }
} }

View File

@@ -1,30 +1,25 @@
using SM64Lib.Patching; using SM64Lib.Patching;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib namespace SM64Lib;
public class BaseTweakScriptInfo
{ {
public class BaseTweakScriptInfo public PatchScript Script { get; private set; }
{ public int Priority { get; private set; }
public PatchScript Script { get; private set; } public bool IsReadOnly { get; private set; }
public int Priority { get; private set; } public string Name { get; private set; }
public bool IsReadOnly { get; private set; } public bool EnabledByDefault { get; private set; }
public string Name { get; private set; } public bool Enabled { get; set; }
public bool EnabledByDefault { get; private set; }
public bool Enabled { get; set; }
public BaseTweakScriptInfo(PatchScript script) public BaseTweakScriptInfo(PatchScript script)
{ {
var infos = script.Name.Split('#'); var infos = script.Name.Split('#');
Priority = Convert.ToInt32(infos[0]); Priority = Convert.ToInt32(infos[0]);
IsReadOnly = infos[1] == "w" ? true : false; IsReadOnly = infos[1] == "w" ? true : false;
EnabledByDefault = infos[2] == "y" ? true : false; EnabledByDefault = infos[2] == "y" ? true : false;
Enabled = EnabledByDefault; Enabled = EnabledByDefault;
Name = infos[3]; Name = infos[3];
Script = script; Script = script;
}
} }
} }

View File

@@ -5,237 +5,234 @@ using SM64Lib.Data;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Z.Collections.Extensions; using Z.Collections.Extensions;
using static SM64Lib.Extensions.ObjectExtensions; using static SM64Lib.Extensions.ObjectExtensions;
namespace SM64Lib.Behaviors namespace SM64Lib.Behaviors;
public class Behavior
{ {
public class Behavior private readonly Dictionary<CustomAsmAreaConfig, BehaviorscriptCommand> knownCustomAsmCommands = new Dictionary<CustomAsmAreaConfig, BehaviorscriptCommand>();
[JsonProperty]
public BehaviorConfig Config { get; private set; }
[JsonProperty]
public Behaviorscript Script { get; private set; }
public int CollisionPointer { get; set; }
public bool EnableCollisionPointer { get; set; }
public List<int> BehaviorAddressDestinations { get; set; } = new List<int>();
[JsonIgnore]
public long Length
{ {
private readonly Dictionary<CustomAsmAreaConfig, BehaviorscriptCommand> knownCustomAsmCommands = new Dictionary<CustomAsmAreaConfig, BehaviorscriptCommand>(); get
[JsonProperty]
public BehaviorConfig Config { get; private set; }
[JsonProperty]
public Behaviorscript Script { get; private set; }
public int CollisionPointer { get; set; }
public bool EnableCollisionPointer { get; set; }
public List<int> BehaviorAddressDestinations { get; set; } = new List<int>();
[JsonIgnore]
public long Length
{ {
get if (Config.FixedLength == -1)
return Script.Length;
else
return Config.FixedLength;
}
}
public Behavior() : this(new BehaviorConfig())
{
}
public Behavior(BehaviorConfig config)
{
CreateNewBehaviorscript();
Config = config;
}
public Behavior(BehaviorCreationTypes behaviorCreationType) : this()
{
Create(behaviorCreationType);
}
public void Create(BehaviorCreationTypes type)
{
CreateNewBehaviorscript();
switch (type)
{
case BehaviorCreationTypes.SolidObject:
Script.Add(new BehaviorscriptCommand("00 09 00 00"));
Script.Add(new BehaviorscriptCommand("11 01 00 01"));
Script.Add(new BehaviorscriptCommand("2a 00 00 00 00 00 00 00"));
Script.Add(new BehaviorscriptCommand("08 00 00 00"));
Script.Add(new BehaviorscriptCommand("0c 00 00 00 80 38 39 cc"));
Script.Add(new BehaviorscriptCommand("09 00 00 00"));
break;
}
ParseScript();
}
private void CreateNewBehaviorscript()
{
if (Script != null)
Script.Close();
Script = new Behaviorscript();
}
public bool Read(BinaryData data, int address)
{
CreateNewBehaviorscript();
var success = Script.Read(data, address, Config.IsVanilla, Config.ExpectedLength != -1, Config.ExpectedLength);
if (Config.IsVanilla)
Config.FixedLength = (int)Script.Length;
Config.ExpectedLength = (int)Script.Length;
ParseScript();
return success;
}
public void Write(BinaryData data, int address)
{
//if (!Config.IsVanilla)
TakeoverSettingsToScript();
var length = Script.Write(data, address);
if (Config.FixedLength != -1 && length != Config.FixedLength)
data.Position -= length - Config.FixedLength;
Config.ExpectedLength = length;
}
public void ParseScript()
{
var dicCustomAsmFuncs = new Dictionary<int, CustomAsmAreaLinkOptions>();
EnableCollisionPointer = false;
knownCustomAsmCommands.Clear();
foreach (var link in Config.CustomAsmLinks)
dicCustomAsmFuncs.AddOrUpdate(link.CustomAsmAreaConfig.RamAddress | unchecked((int)0x80000000), link);
foreach (BehaviorscriptCommand cmd in Script)
{
switch (cmd.CommandType)
{ {
if (Config.FixedLength == -1) case BehaviorscriptCommandTypes.x2A_SetCollision:
return Script.Length; CollisionPointer = BehaviorscriptCommandFunctions.X2A.GetCollisionPointer(cmd);
else EnableCollisionPointer = true;
return Config.FixedLength; break;
} case BehaviorscriptCommandTypes.x0C_CallFunction:
} var ptr = BehaviorscriptCommandFunctions.X0C.GetAsmPointer(cmd);
if (dicCustomAsmFuncs.ContainsKey(ptr))
public Behavior() : this(new BehaviorConfig()) knownCustomAsmCommands.AddOrUpdate(dicCustomAsmFuncs[ptr].CustomAsmAreaConfig, cmd);
{
}
public Behavior(BehaviorConfig config)
{
CreateNewBehaviorscript();
Config = config;
}
public Behavior(BehaviorCreationTypes behaviorCreationType) : this()
{
Create(behaviorCreationType);
}
public void Create(BehaviorCreationTypes type)
{
CreateNewBehaviorscript();
switch (type)
{
case BehaviorCreationTypes.SolidObject:
Script.Add(new BehaviorscriptCommand("00 09 00 00"));
Script.Add(new BehaviorscriptCommand("11 01 00 01"));
Script.Add(new BehaviorscriptCommand("2a 00 00 00 00 00 00 00"));
Script.Add(new BehaviorscriptCommand("08 00 00 00"));
Script.Add(new BehaviorscriptCommand("0c 00 00 00 80 38 39 cc"));
Script.Add(new BehaviorscriptCommand("09 00 00 00"));
break; break;
} }
ParseScript();
} }
}
private void CreateNewBehaviorscript() public void TakeoverSettingsToScript()
{
// Update collision pointer
AddUpdateRemoveCmd(
BehaviorscriptCommandTypes.x2A_SetCollision,
EnableCollisionPointer,
() => BehaviorscriptCommandFactory.Build_x2A(CollisionPointer),
(cmd) => BehaviorscriptCommandFunctions.X2A.SetCollisionPointer(cmd, CollisionPointer));
// Insert Custom Asm Links
{ {
if (Script != null)
Script.Close();
Script = new Behaviorscript();
}
public bool Read(BinaryData data, int address)
{
CreateNewBehaviorscript();
var success = Script.Read(data, address, Config.IsVanilla, Config.ExpectedLength != -1, Config.ExpectedLength);
if (Config.IsVanilla)
Config.FixedLength = (int)Script.Length;
Config.ExpectedLength = (int)Script.Length;
ParseScript();
return success;
}
public void Write(BinaryData data, int address)
{
//if (!Config.IsVanilla)
TakeoverSettingsToScript();
var length = Script.Write(data, address);
if (Config.FixedLength != -1 && length != Config.FixedLength)
data.Position -= length - Config.FixedLength;
Config.ExpectedLength = length;
}
public void ParseScript()
{
var dicCustomAsmFuncs = new Dictionary<int, CustomAsmAreaLinkOptions>();
EnableCollisionPointer = false;
knownCustomAsmCommands.Clear();
foreach (var link in Config.CustomAsmLinks) foreach (var link in Config.CustomAsmLinks)
dicCustomAsmFuncs.AddOrUpdate(link.CustomAsmAreaConfig.RamAddress | unchecked((int)0x80000000), link);
foreach (BehaviorscriptCommand cmd in Script)
{ {
switch (cmd.CommandType) var asmPointer = link.CustomAsmAreaConfig.RamAddress | unchecked((int)0x80000000);
var cmdStartLoop = Script.FirstOfType(BehaviorscriptCommandTypes.x08_LoopStart);
var cmdStartLoopIndex = Script.IndexOf(cmdStartLoop);
int iInsert;
if (link.Loop)
{ {
case BehaviorscriptCommandTypes.x2A_SetCollision: if (cmdStartLoop is not null)
CollisionPointer = BehaviorscriptCommandFunctions.X2A.GetCollisionPointer(cmd); iInsert = cmdStartLoopIndex + 1;
EnableCollisionPointer = true;
break;
case BehaviorscriptCommandTypes.x0C_CallFunction:
var ptr = BehaviorscriptCommandFunctions.X0C.GetAsmPointer(cmd);
if (dicCustomAsmFuncs.ContainsKey(ptr))
knownCustomAsmCommands.AddOrUpdate(dicCustomAsmFuncs[ptr].CustomAsmAreaConfig, cmd);
break;
}
}
}
public void TakeoverSettingsToScript()
{
// Update collision pointer
AddUpdateRemoveCmd(
BehaviorscriptCommandTypes.x2A_SetCollision,
EnableCollisionPointer,
() => BehaviorscriptCommandFactory.Build_x2A(CollisionPointer),
(cmd) => BehaviorscriptCommandFunctions.X2A.SetCollisionPointer(cmd, CollisionPointer));
// Insert Custom Asm Links
{
foreach (var link in Config.CustomAsmLinks)
{
var asmPointer = link.CustomAsmAreaConfig.RamAddress | unchecked((int)0x80000000);
var cmdStartLoop = Script.FirstOfType(BehaviorscriptCommandTypes.x08_LoopStart);
var cmdStartLoopIndex = Script.IndexOf(cmdStartLoop);
int iInsert;
if (link.Loop)
{
if (cmdStartLoop is not null)
iInsert = cmdStartLoopIndex + 1;
else
iInsert = -1;
}
else else
{ iInsert = -1;
if (cmdStartLoop is not null)
iInsert = cmdStartLoopIndex;
else
iInsert = (int)Script.Count - 2;
}
if (knownCustomAsmCommands.ContainsKey(link.CustomAsmAreaConfig))
{
var cmd = knownCustomAsmCommands[link.CustomAsmAreaConfig];
var cmdIndex = Script.IndexOf(cmd);
BehaviorscriptCommandFunctions.X0C.SetAsmPointer(cmd, asmPointer);
if (cmdIndex != -1)
{
var reinsert = false;
if (link.Loop && cmdIndex < cmdStartLoopIndex)
{
reinsert = true;
iInsert -= 1;
}
else if (!link.Loop && cmdIndex > cmdStartLoopIndex)
reinsert = true;
if (reinsert)
{
Script.Remove(cmd);
Script.Insert(iInsert, cmd);
}
}
}
else if (iInsert != -1)
{
var cmd = BehaviorscriptCommandFactory.Build_x0C(asmPointer);
Script.Insert(iInsert, cmd);
knownCustomAsmCommands.Add(link.CustomAsmAreaConfig, cmd);
}
} }
foreach (var kvp in knownCustomAsmCommands.ToArray())
{
if (!Config.CustomAsmLinks.Where(n => n.CustomAsmAreaConfig == kvp.Key).Any())
{
knownCustomAsmCommands.Remove(kvp.Key);
Script.RemoveIfContains(kvp.Value);
kvp.Value.Close();
}
}
}
}
private void AddUpdateRemoveCmd(BehaviorscriptCommandTypes cmdType, bool conditionAddUpdate, Func<BehaviorscriptCommand> createCmd, Action<BehaviorscriptCommand> updateCmd)
{
var cmd = Script.FirstOfType(cmdType);
if (cmd is not null)
{
if (conditionAddUpdate)
updateCmd(cmd);
else else
{ {
Script.Remove(cmd); if (cmdStartLoop is not null)
cmd.Close(); iInsert = cmdStartLoopIndex;
else
iInsert = (int)Script.Count - 2;
}
if (knownCustomAsmCommands.ContainsKey(link.CustomAsmAreaConfig))
{
var cmd = knownCustomAsmCommands[link.CustomAsmAreaConfig];
var cmdIndex = Script.IndexOf(cmd);
BehaviorscriptCommandFunctions.X0C.SetAsmPointer(cmd, asmPointer);
if (cmdIndex != -1)
{
var reinsert = false;
if (link.Loop && cmdIndex < cmdStartLoopIndex)
{
reinsert = true;
iInsert -= 1;
}
else if (!link.Loop && cmdIndex > cmdStartLoopIndex)
reinsert = true;
if (reinsert)
{
Script.Remove(cmd);
Script.Insert(iInsert, cmd);
}
}
}
else if (iInsert != -1)
{
var cmd = BehaviorscriptCommandFactory.Build_x0C(asmPointer);
Script.Insert(iInsert, cmd);
knownCustomAsmCommands.Add(link.CustomAsmAreaConfig, cmd);
} }
} }
else if (conditionAddUpdate)
foreach (var kvp in knownCustomAsmCommands.ToArray())
{ {
cmd = createCmd(); if (!Config.CustomAsmLinks.Where(n => n.CustomAsmAreaConfig == kvp.Key).Any())
Script.Insert(1, cmd); {
knownCustomAsmCommands.Remove(kvp.Key);
Script.RemoveIfContains(kvp.Value);
kvp.Value.Close();
}
} }
} }
public void CopyPropertiesTo(Behavior dest)
{
// Copy Script
TakeoverSettingsToScript();
dest.Script.Close();
dest.Script.AddRange(Script);
dest.ParseScript();
// Copy Configs
dest.Config.Name = Config.Name;
Config.ParamsInfo.CloneTo(dest.Config.ParamsInfo);
}
} }
private void AddUpdateRemoveCmd(BehaviorscriptCommandTypes cmdType, bool conditionAddUpdate, Func<BehaviorscriptCommand> createCmd, Action<BehaviorscriptCommand> updateCmd)
{
var cmd = Script.FirstOfType(cmdType);
if (cmd is not null)
{
if (conditionAddUpdate)
updateCmd(cmd);
else
{
Script.Remove(cmd);
cmd.Close();
}
}
else if (conditionAddUpdate)
{
cmd = createCmd();
Script.Insert(1, cmd);
}
}
public void CopyPropertiesTo(Behavior dest)
{
// Copy Script
TakeoverSettingsToScript();
dest.Script.Close();
dest.Script.AddRange(Script);
dest.ParseScript();
// Copy Configs
dest.Config.Name = Config.Name;
Config.ParamsInfo.CloneTo(dest.Config.ParamsInfo);
}
} }

View File

@@ -1,220 +1,216 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Data; using SM64Lib.Data;
using SM64Lib.SegmentedBanking; using SM64Lib.SegmentedBanking;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Z.Collections.Extensions; using Z.Collections.Extensions;
namespace SM64Lib.Behaviors namespace SM64Lib.Behaviors;
public class BehaviorBank
{ {
public class BehaviorBank public BehaviorBankConfig Config { get; private set; }
public List<Behavior> Behaviors { get; } = new List<Behavior>();
[JsonIgnore]
public long Length
{ {
public BehaviorBankConfig Config { get; private set; } get => Behaviors.Sum(n => n.Length);
public List<Behavior> Behaviors { get; } = new List<Behavior>(); }
[JsonIgnore] public BehaviorBank(BehaviorBankConfig config)
public long Length {
Config = config;
}
public void ReadBank(SegmentedBank seg, int offset)
{
ReadBank(seg, offset, false);
}
public void ReadVanillaBank(SegmentedBank seg)
{
ReadBank(seg, 0, true);
}
private void ReadBank(SegmentedBank seg, int offset, bool isVanilla)
{
var data = new BinaryStreamData(seg.Data);
data.Position = offset;
ReadBank(data, isVanilla, seg.Length, (sbyte)seg.BankID);
}
public void ReadBank(BinaryData data)
{
ReadBank(data, false, -1, -1);
}
private void ReadBank(BinaryData data, bool isVanilla, int endAddress, sbyte bankID)
{
// Clear current list
Behaviors.Clear();
if (isVanilla)
{ {
get => Behaviors.Sum(n => n.Length); while (data.Position <= endAddress - 0x10)
{
var conf = new BehaviorConfig();
Config.BehaviorConfigs.Add(conf);
readBehavior(conf);
}
}
else
{
foreach (var config in Config.BehaviorConfigs.OrderBy(n => n.BankAddress))
readBehavior(config);
} }
public BehaviorBank(BehaviorBankConfig config) void readBehavior(BehaviorConfig config)
{ {
Config = config; int bankOffset;
} Behavior behav = new Behavior(config);
public void ReadBank(SegmentedBank seg, int offset)
{
ReadBank(seg, offset, false);
}
public void ReadVanillaBank(SegmentedBank seg)
{
ReadBank(seg, 0, true);
}
private void ReadBank(SegmentedBank seg, int offset, bool isVanilla)
{
var data = new BinaryStreamData(seg.Data);
data.Position = offset;
ReadBank(data, isVanilla, seg.Length, (sbyte)seg.BankID);
}
public void ReadBank(BinaryData data)
{
ReadBank(data, false, -1, -1);
}
private void ReadBank(BinaryData data, bool isVanilla, int endAddress, sbyte bankID)
{
// Clear current list
Behaviors.Clear();
if (isVanilla) if (isVanilla)
{ {
while (data.Position <= endAddress - 0x10) bankOffset = (int)data.Position;
{ config.BankAddress = (bankID << 24) | bankOffset;
var conf = new BehaviorConfig(); behav.Config.IsVanilla = true;
Config.BehaviorConfigs.Add(conf);
readBehavior(conf);
}
} }
else else
{ {
foreach (var config in Config.BehaviorConfigs.OrderBy(n => n.BankAddress)) bankOffset = config.BankAddress & 0xffffff;
readBehavior(config); if (!behav.Config.IsVanilla && !config.ID.HasID) config.ID.Generate();
} }
void readBehavior(BehaviorConfig config) var lastBehav = Behaviors.LastOrDefault();
if (behav.Read(data, bankOffset))
{ {
int bankOffset; if (isVanilla && lastBehav is not null && lastBehav.Config.IsVanilla && lastBehav.Config.FixedLength != -1)
Behavior behav = new Behavior(config); lastBehav.Config.FixedLength = bankOffset - (lastBehav.Config.BankAddress & 0xffffff);
if (isVanilla) Behaviors.Add(behav);
}
}
}
public SegmentedBank WriteToSeg(byte bankID, int offset, RomManager rommgr)
{
var segStream = new MemoryStream();
var seg = new SegmentedBank(bankID, segStream);
int lastPos = WriteToSeg(seg, offset, rommgr);
seg.Length = General.HexRoundUp1(lastPos);
return seg;
}
public int WriteToSeg(SegmentedBank seg, int offset, RomManager rommgr)
{
var addressUpdates = new Dictionary<int, int>();
var segStartAddress = seg.BankAddress | offset;
var data = new BinaryStreamData(seg.Data);
data.Position = offset;
if (Behaviors.Any())
{
// Save Behaviors to ROM
foreach (var behav in Behaviors)
{
var address = (int)data.Position;
var newBankAddress = (int)data.Position - offset + segStartAddress;
if (newBankAddress != behav.Config.BankAddress)
{ {
bankOffset = (int)data.Position; if (behav.Config.BankAddress != -1)
config.BankAddress = (bankID << 24) | bankOffset; addressUpdates.AddOrUpdate(behav.Config.BankAddress, newBankAddress);
behav.Config.IsVanilla = true; behav.Config.BankAddress = newBankAddress;
}
else
{
bankOffset = config.BankAddress & 0xffffff;
if (!behav.Config.IsVanilla && !config.ID.HasID) config.ID.Generate();
}
var lastBehav = Behaviors.LastOrDefault();
if (behav.Read(data, bankOffset))
{
if (isVanilla && lastBehav is not null && lastBehav.Config.IsVanilla && lastBehav.Config.FixedLength != -1)
lastBehav.Config.FixedLength = bankOffset - (lastBehav.Config.BankAddress & 0xffffff);
Behaviors.Add(behav);
} }
behav.Write(data, (int)data.Position);
} }
} }
public SegmentedBank WriteToSeg(byte bankID, int offset, RomManager rommgr) // Delete unused configs / Add new configs
{ Config.BehaviorConfigs.Clear();
var segStream = new MemoryStream(); Config.BehaviorConfigs.AddRange(Behaviors.Select(n => n.Config));
var seg = new SegmentedBank(bankID, segStream);
int lastPos = WriteToSeg(seg, offset, rommgr);
seg.Length = General.HexRoundUp1(lastPos);
return seg;
}
public int WriteToSeg(SegmentedBank seg, int offset, RomManager rommgr) // Update addresses
{ UpdateBehaviorAddresses(rommgr, addressUpdates);
var addressUpdates = new Dictionary<int, int>();
var segStartAddress = seg.BankAddress | offset;
var data = new BinaryStreamData(seg.Data);
data.Position = offset;
if (Behaviors.Any()) return (int)data.Position;
}
private void UpdateBehaviorAddresses(RomManager rommgr, Dictionary<int, int> addressUpdates)
{
if (Behaviors.Any() && rommgr is not null)
{
foreach (var lvl in rommgr.Levels)
{ {
// Save Behaviors to ROM foreach (var area in lvl.Areas)
foreach (var behav in Behaviors)
{ {
var address = (int)data.Position; foreach (var obj in area.Objects)
var newBankAddress = (int)data.Position - offset + segStartAddress;
if (newBankAddress != behav.Config.BankAddress)
{ {
if (behav.Config.BankAddress != -1) var behavAddr = Levels.Script.Commands.clNormal3DObject.GetSegBehaviorAddr(obj);
addressUpdates.AddOrUpdate(behav.Config.BankAddress, newBankAddress); foreach (var kvp in addressUpdates)
behav.Config.BankAddress = newBankAddress;
}
behav.Write(data, (int)data.Position);
}
}
// Delete unused configs / Add new configs
Config.BehaviorConfigs.Clear();
Config.BehaviorConfigs.AddRange(Behaviors.Select(n => n.Config));
// Update addresses
UpdateBehaviorAddresses(rommgr, addressUpdates);
return (int)data.Position;
}
private void UpdateBehaviorAddresses(RomManager rommgr, Dictionary<int, int> addressUpdates)
{
if (Behaviors.Any() && rommgr is not null)
{
foreach (var lvl in rommgr.Levels)
{
foreach (var area in lvl.Areas)
{
foreach (var obj in area.Objects)
{ {
var behavAddr = Levels.Script.Commands.clNormal3DObject.GetSegBehaviorAddr(obj); if (behavAddr == kvp.Key)
foreach (var kvp in addressUpdates) Levels.Script.Commands.clNormal3DObject.SetSegBehaviorAddr(obj, (uint)kvp.Value);
{
if (behavAddr == kvp.Key)
Levels.Script.Commands.clNormal3DObject.SetSegBehaviorAddr(obj, (uint)kvp.Value);
}
} }
} }
} }
} }
} }
}
public void WriteBehaviorAddresss(RomManager rommgr) public void WriteBehaviorAddresss(RomManager rommgr)
{
var data = rommgr.GetBinaryRom(FileAccess.ReadWrite);
WriteBehaviorAddresss(data);
data.Close();
}
public void WriteBehaviorAddresss(BinaryData data)
{
if (Behaviors.Any())
{ {
var data = rommgr.GetBinaryRom(FileAccess.ReadWrite);
WriteBehaviorAddresss(data);
data.Close();
}
public void WriteBehaviorAddresss(BinaryData data)
{
if (Behaviors.Any())
{
foreach (var behav in Behaviors)
{
foreach (var dest in behav.BehaviorAddressDestinations)
{
data.Position = dest;
data.Write(behav.Config.BankAddress);
}
}
}
}
public Behavior GetBehaviorByID(string id)
{
return Behaviors.FirstOrDefault(n => n.Config.ID == id);
}
public Behavior GetBehaviorByBankAddress(int bankAddress)
{
return Behaviors.FirstOrDefault(n => n.Config.BankAddress == bankAddress);
}
public void CalculateBehaviorBankAddresses(int bankStartAddress, RomManager rommgr)
{
var length = 0;
var addressUpdates = new Dictionary<int, int>();
foreach (var behav in Behaviors) foreach (var behav in Behaviors)
{ {
if (behav.Config.IsVanilla) foreach (var dest in behav.BehaviorAddressDestinations)
length += behav.Config.FixedLength;
else
{ {
var newBankAddress = bankStartAddress + length; data.Position = dest;
addressUpdates.AddIfNotContainsKey(behav.Config.BankAddress, newBankAddress); data.Write(behav.Config.BankAddress);
behav.Config.BankAddress = newBankAddress;
length += (int)behav.Script.Length;
} }
} }
// Update addresses
UpdateBehaviorAddresses(rommgr, addressUpdates);
} }
} }
public Behavior GetBehaviorByID(string id)
{
return Behaviors.FirstOrDefault(n => n.Config.ID == id);
}
public Behavior GetBehaviorByBankAddress(int bankAddress)
{
return Behaviors.FirstOrDefault(n => n.Config.BankAddress == bankAddress);
}
public void CalculateBehaviorBankAddresses(int bankStartAddress, RomManager rommgr)
{
var length = 0;
var addressUpdates = new Dictionary<int, int>();
foreach (var behav in Behaviors)
{
if (behav.Config.IsVanilla)
length += behav.Config.FixedLength;
else
{
var newBankAddress = bankStartAddress + length;
addressUpdates.AddIfNotContainsKey(behav.Config.BankAddress, newBankAddress);
behav.Config.BankAddress = newBankAddress;
length += (int)behav.Script.Length;
}
}
// Update addresses
UpdateBehaviorAddresses(rommgr, addressUpdates);
}
} }

View File

@@ -1,36 +1,31 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Behaviors namespace SM64Lib.Behaviors;
public class BehaviorBankConfig
{ {
public class BehaviorBankConfig public bool IsVanilla { get; set; } = true;
public List<BehaviorConfig> BehaviorConfigs { get; } = new List<BehaviorConfig>();
[JsonProperty(nameof(Enabled))]
private bool enabled = false;
public void Enable() => enabled = true;
internal void Disable()
{ {
public bool IsVanilla { get; set; } = true; enabled = false;
public List<BehaviorConfig> BehaviorConfigs { get; } = new List<BehaviorConfig>(); IsVanilla = true;
BehaviorConfigs.Clear();
}
[JsonProperty(nameof(Enabled))] [JsonIgnore]
private bool enabled = false; public bool Enabled
public void Enable() => enabled = true; {
internal void Disable() get
{ {
enabled = false; if (!enabled && !IsVanilla)
IsVanilla = true; enabled = true;
BehaviorConfigs.Clear(); return enabled;
}
[JsonIgnore]
public bool Enabled
{
get
{
if (!enabled && !IsVanilla)
enabled = true;
return enabled;
}
} }
} }
} }

View File

@@ -1,39 +1,34 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Pilz.Cryptography; using Pilz.Cryptography;
using Pilz.Json.Converters; using Pilz.Json.Converters;
using System.Collections.Generic;
namespace SM64Lib.Behaviors namespace SM64Lib.Behaviors;
public class BehaviorConfig
{ {
public class BehaviorConfig internal delegate void RequestModelEventHandler(BehaviorConfig config, RequestBehaviorEventArgs request);
internal static event RequestModelEventHandler RequestBehavior;
[JsonConverter(typeof(UniquieIDStringJsonConverter))]
public UniquieID ID { get; set; } = new();
public int BankAddress { get; set; } = -1;
public bool IsVanilla { get; set; } = false;
public string Name { get; set; } = string.Empty;
public int FixedLength { get; set; } = -1;
public int ExpectedLength { get; set; } = -1;
public List<CustomAsmAreaLinkOptions> CustomAsmLinks { get; } = new List<CustomAsmAreaLinkOptions>();
public BehaviorParamsInfo ParamsInfo { get; } = new BehaviorParamsInfo();
public Behavior FindBehavior()
{ {
internal delegate void RequestModelEventHandler(BehaviorConfig config, RequestBehaviorEventArgs request); var args = new RequestBehaviorEventArgs();
internal static event RequestModelEventHandler RequestBehavior; RequestBehavior?.Invoke(this, args);
return args.Behavior;
}
[JsonConverter(typeof(UniquieIDStringJsonConverter))] internal class RequestBehaviorEventArgs
public UniquieID ID { get; set; } = new(); {
public int BankAddress { get; set; } = -1; public Behavior Behavior { get; set; }
public bool IsVanilla { get; set; } = false;
public string Name { get; set; } = string.Empty;
public int FixedLength { get; set; } = -1;
public int ExpectedLength { get; set; } = -1;
public List<CustomAsmAreaLinkOptions> CustomAsmLinks { get; } = new List<CustomAsmAreaLinkOptions>();
public BehaviorParamsInfo ParamsInfo { get; } = new BehaviorParamsInfo();
public Behavior FindBehavior()
{
var args = new RequestBehaviorEventArgs();
RequestBehavior?.Invoke(this, args);
return args.Behavior;
}
internal class RequestBehaviorEventArgs
{
public Behavior Behavior { get; set; }
}
} }
} }

View File

@@ -1,13 +1,6 @@
using System; namespace SM64Lib.Behaviors;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Behaviors public enum BehaviorCreationTypes
{ {
public enum BehaviorCreationTypes SolidObject
{
SolidObject
}
} }

View File

@@ -1,15 +1,10 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Behaviors namespace SM64Lib.Behaviors;
public class BehaviorParamInfo
{ {
public class BehaviorParamInfo public string Name { get; set; } = string.Empty;
{ public string Description { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty; public List<BehaviorParamValue> Values { get; } = new List<BehaviorParamValue>();
public string Description { get; set; } = string.Empty;
public List<BehaviorParamValue> Values { get; } = new List<BehaviorParamValue>();
}
} }

View File

@@ -1,14 +1,7 @@
using System; namespace SM64Lib.Behaviors;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Behaviors public class BehaviorParamValue
{ {
public class BehaviorParamValue public string Name { get; set; } = "";
{ public byte Value { get; set; } = 0;
public string Name { get; set; } = "";
public byte Value { get; set; } = 0;
}
} }

View File

@@ -1,16 +1,9 @@
using System; namespace SM64Lib.Behaviors;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Behaviors public class BehaviorParamsInfo
{ {
public class BehaviorParamsInfo public BehaviorParamInfo Param1 { get; } = new();
{ public BehaviorParamInfo Param2 { get; } = new();
public BehaviorParamInfo Param1 { get; } = new(); public BehaviorParamInfo Param3 { get; } = new();
public BehaviorParamInfo Param2 { get; } = new(); public BehaviorParamInfo Param4 { get; } = new();
public BehaviorParamInfo Param3 { get; } = new();
public BehaviorParamInfo Param4 { get; } = new();
}
} }

View File

@@ -1,25 +1,19 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.ASM; using SM64Lib.ASM;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Behaviors namespace SM64Lib.Behaviors;
public class CustomAsmAreaLinkOptions
{ {
public class CustomAsmAreaLinkOptions // Temporary fix - Remove custom property code and make it auto property in v1.?
private CustomAsmAreaConfig customAsmAreaConfig;
public CustomAsmAreaConfig CustomAsmAreaConfig
{ {
// Temporary fix - Remove custom property code and make it auto property in v1.? get => customAsmAreaConfig ?? CustomAsm?.Config;
private CustomAsmAreaConfig customAsmAreaConfig; set => customAsmAreaConfig = value;
public CustomAsmAreaConfig CustomAsmAreaConfig
{
get => customAsmAreaConfig ?? CustomAsm?.Config;
set => customAsmAreaConfig = value;
}
// Temporary fix for old files - Remove property in v1.?
[JsonProperty]
public CustomAsmArea CustomAsm { get; private set; }
public bool Loop { get; set; }
} }
// Temporary fix for old files - Remove property in v1.?
[JsonProperty]
public CustomAsmArea CustomAsm { get; private set; }
public bool Loop { get; set; }
} }

View File

@@ -1,106 +1,104 @@
using SM64Lib.Data; using SM64Lib.Data;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace SM64Lib.Behaviors.Script namespace SM64Lib.Behaviors.Script;
public class Behaviorscript : BehaviorscriptCommandCollection
{ {
public class Behaviorscript : BehaviorscriptCommandCollection public bool Read(BinaryData data, int address, bool detectJumpsAsEnd = false, bool ignoreEndCmds = false, int expectedLength = -1)
{ {
public bool Read(BinaryData data, int address, bool detectJumpsAsEnd = false, bool ignoreEndCmds = false, int expectedLength = -1) bool ende = false;
bool success = true;
var newCmds = new List<BehaviorscriptCommand>();
data.Position = address;
if (expectedLength < 0)
expectedLength = (int)data.Length;
else
expectedLength += address;
while (!ende)
{ {
bool ende = false; if (expectedLength - data.Position >= 4)
bool success = true;
var newCmds = new List<BehaviorscriptCommand>();
data.Position = address;
if (expectedLength < 0)
expectedLength = (int)data.Length;
else
expectedLength += address;
while (!ende)
{ {
if (expectedLength - data.Position >= 4) // Get command infos
var cmdType = (BehaviorscriptCommandTypes)data.ReadByte();
int cmdLength = BehaviorscriptCommand.GetCommandLength(cmdType);
var unknownCmd = cmdLength == -1;
bool isEndCmd = ignoreEndCmds ? false : (unknownCmd || BehaviorscriptCommand.IsEndCommand(cmdType, detectJumpsAsEnd));
if (!unknownCmd)
{ {
// Get command infos // Reset position
var cmdType = (BehaviorscriptCommandTypes)data.ReadByte(); data.Position -= 1;
int cmdLength = BehaviorscriptCommand.GetCommandLength(cmdType);
var unknownCmd = cmdLength == -1;
bool isEndCmd = ignoreEndCmds ? false : (unknownCmd || BehaviorscriptCommand.IsEndCommand(cmdType, detectJumpsAsEnd));
if (!unknownCmd) if (data.Position + cmdLength <= expectedLength)
{ {
// Reset position // Read full command
data.Position -= 1; byte[] buf = new byte[cmdLength];
data.Read(buf);
if (data.Position + cmdLength <= expectedLength) // Create & add command
try
{ {
// Read full command newCmds.Add(new BehaviorscriptCommand(buf));
byte[] buf = new byte[cmdLength];
data.Read(buf);
// Create & add command
try
{
newCmds.Add(new BehaviorscriptCommand(buf));
}
catch (Exception)
{
success = false;
}
ende = isEndCmd;
} }
else catch (Exception)
ende = true; {
} success = false;
else }
{
data.Position += 3;
ende = isEndCmd; ende = isEndCmd;
} }
else
ende = true;
} }
else else
ende = true; {
data.Position += 3;
ende = isEndCmd;
}
} }
else
// Add new Cmds ende = true;
if (success && newCmds.Any())
{
Close();
AddRange(newCmds.ToArray());
}
return success;
} }
public int Write(BinaryData data, int address) // Add new Cmds
if (success && newCmds.Any())
{ {
data.Position = address; Close();
AddRange(newCmds.ToArray());
foreach (BehaviorscriptCommand command in this)
{
var cmdLength = BehaviorscriptCommand.GetCommandLength(command.CommandType);
if (command.Length != cmdLength)
command.SetLength(cmdLength);
data.Write(command.ToArray());
}
return (int)data.Position - address;
}
public int IndexOfType(BehaviorscriptCommandTypes cmdType)
{
return IndexOf(this.FirstOrDefault(n => n.CommandType == cmdType));
}
public BehaviorscriptCommand FirstOfType(BehaviorscriptCommandTypes cmdType)
{
return (BehaviorscriptCommand)this.FirstOrDefault(n => n.CommandType == cmdType);
} }
return success;
} }
public int Write(BinaryData data, int address)
{
data.Position = address;
foreach (BehaviorscriptCommand command in this)
{
var cmdLength = BehaviorscriptCommand.GetCommandLength(command.CommandType);
if (command.Length != cmdLength)
command.SetLength(cmdLength);
data.Write(command.ToArray());
}
return (int)data.Position - address;
}
public int IndexOfType(BehaviorscriptCommandTypes cmdType)
{
return IndexOf(this.FirstOrDefault(n => n.CommandType == cmdType));
}
public BehaviorscriptCommand FirstOfType(BehaviorscriptCommandTypes cmdType)
{
return (BehaviorscriptCommand)this.FirstOrDefault(n => n.CommandType == cmdType);
}
} }

View File

@@ -2,119 +2,118 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Json; using SM64Lib.Json;
namespace SM64Lib.Behaviors.Script namespace SM64Lib.Behaviors.Script;
[JsonConverter(typeof(BehaviorscriptCommandJsonConverter))]
public class BehaviorscriptCommand : SM64Lib.Script.BaseCommand<BehaviorscriptCommandTypes>
{ {
[JsonConverter(typeof(BehaviorscriptCommandJsonConverter))]
public class BehaviorscriptCommand : SM64Lib.Script.BaseCommand<BehaviorscriptCommandTypes> public override BehaviorscriptCommandTypes CommandType
{ {
get
public override BehaviorscriptCommandTypes CommandType
{ {
get Position = 0;
{ return (BehaviorscriptCommandTypes)ReadByte();
Position = 0;
return (BehaviorscriptCommandTypes)ReadByte();
}
set
{
Position = 0;
WriteByte((byte)value);
}
} }
public BehaviorscriptCommand() : base() set
{ {
Position = 0;
WriteByte((byte)value);
} }
public BehaviorscriptCommand(byte[] cmd) : base(cmd)
{
}
public BehaviorscriptCommand(string cmd) : base(cmd, true)
{
}
public static int GetCommandLength(BehaviorscriptCommandTypes type)
{
switch (type)
{
case BehaviorscriptCommandTypes.x00_Start: return 4;
case BehaviorscriptCommandTypes.x01_StateLoop: return 4;
case BehaviorscriptCommandTypes.x02_JumpandLink: return 8;
case BehaviorscriptCommandTypes.x03_Return: return 4;
case BehaviorscriptCommandTypes.x04_Jump: return 8;
case BehaviorscriptCommandTypes.x05_LoopN: return 4;
case BehaviorscriptCommandTypes.x06_EndLoopN: return 4;
case BehaviorscriptCommandTypes.x07_InfiniteLoop: return 4;
case BehaviorscriptCommandTypes.x08_LoopStart: return 4;
case BehaviorscriptCommandTypes.x09_LoopEnd: return 4;
case BehaviorscriptCommandTypes.x0A_EndBehaviorscript: return 4;
case BehaviorscriptCommandTypes.x0B_EndBehaviorscript_Unused: return 4;
case BehaviorscriptCommandTypes.x0C_CallFunction: return 8;
case BehaviorscriptCommandTypes.x0D_OffsetbyFloat: return 4;
case BehaviorscriptCommandTypes.x0E_SettoFloat: return 4;
case BehaviorscriptCommandTypes.x0F_OffsetbyInteger: return 4;
case BehaviorscriptCommandTypes.x10_SettoInteger: return 4;
case BehaviorscriptCommandTypes.x11_BitSet: return 4;
case BehaviorscriptCommandTypes.x12_BitClear: return 4;
case BehaviorscriptCommandTypes.x13_AddRNG: return 8;
case BehaviorscriptCommandTypes.x14_ObjectType: return 8;
case BehaviorscriptCommandTypes.x15_FloatMultiply: return 8;
case BehaviorscriptCommandTypes.x16_FloatAdd: return 8;
case BehaviorscriptCommandTypes.x17_AddRNG2: return 8;
case BehaviorscriptCommandTypes.x18_NoOperation: return 4;
case BehaviorscriptCommandTypes.x19_NoOperation: return 4;
case BehaviorscriptCommandTypes.x1A_NoOperation: return 4;
case BehaviorscriptCommandTypes.x1B_ChangeModelID: return 4;
case BehaviorscriptCommandTypes.x1C_LoadChildObject: return 0xC;
case BehaviorscriptCommandTypes.x1D_Deactivate: return 4;
case BehaviorscriptCommandTypes.x1E_DroptoGround: return 4;
case BehaviorscriptCommandTypes.x1F_UsedforWaves: return 4;
case BehaviorscriptCommandTypes.x20_Unused: return 4;
case BehaviorscriptCommandTypes.x21_SetBillboarding: return 4;
case BehaviorscriptCommandTypes.x22_SetRenderInvisibleflag: return 4;
case BehaviorscriptCommandTypes.x23_Collisioncylindersize: return 8;
case BehaviorscriptCommandTypes.x24_Nothing: return 4;
case BehaviorscriptCommandTypes.x25_StateCycle: return 4;
case BehaviorscriptCommandTypes.x26_Loop: return 4;
case BehaviorscriptCommandTypes.x27_SetWord: return 8;
case BehaviorscriptCommandTypes.x28_Animates: return 4;
case BehaviorscriptCommandTypes.x29_LoadChildObject: return 0xC;
case BehaviorscriptCommandTypes.x2A_SetCollision: return 8;
case BehaviorscriptCommandTypes.x2B_SetCollisionSphere: return 0xC;
case BehaviorscriptCommandTypes.x2C_SpawnObject: return 0xC;
case BehaviorscriptCommandTypes.x2D_SetInitPosition: return 4;
case BehaviorscriptCommandTypes.x2E_SetHurtbox: return 8;
case BehaviorscriptCommandTypes.x2F_SetInteraction: return 8;
case BehaviorscriptCommandTypes.x30_SetGravity: return 0x14;
case BehaviorscriptCommandTypes.x31_SetInteractionSubType: return 8;
case BehaviorscriptCommandTypes.x32_ScaleObject: return 4;
case BehaviorscriptCommandTypes.x33_ChildObjectChange: return 8;
case BehaviorscriptCommandTypes.x34_TextureAnimateRate: return 4;
case BehaviorscriptCommandTypes.x35_ClearGraphFlag: return 4;
case BehaviorscriptCommandTypes.x36_SetValue: return 8;
case BehaviorscriptCommandTypes.x37_SpawnSomething: return 8;
default: return -1; //throw new System.Exception("Command type not found!");
}
}
public static bool IsEndCommand(BehaviorscriptCommandTypes type, bool detectJumpsAsEnd = true)
{
switch (type)
{
case BehaviorscriptCommandTypes.x02_JumpandLink:
case BehaviorscriptCommandTypes.x04_Jump:
return detectJumpsAsEnd;
case BehaviorscriptCommandTypes.x06_EndLoopN:
case BehaviorscriptCommandTypes.x0A_EndBehaviorscript:
case BehaviorscriptCommandTypes.x0B_EndBehaviorscript_Unused:
case BehaviorscriptCommandTypes.x09_LoopEnd:
return true;
default:
return false;
}
}
} }
public BehaviorscriptCommand() : base()
{
}
public BehaviorscriptCommand(byte[] cmd) : base(cmd)
{
}
public BehaviorscriptCommand(string cmd) : base(cmd, true)
{
}
public static int GetCommandLength(BehaviorscriptCommandTypes type)
{
switch (type)
{
case BehaviorscriptCommandTypes.x00_Start: return 4;
case BehaviorscriptCommandTypes.x01_StateLoop: return 4;
case BehaviorscriptCommandTypes.x02_JumpandLink: return 8;
case BehaviorscriptCommandTypes.x03_Return: return 4;
case BehaviorscriptCommandTypes.x04_Jump: return 8;
case BehaviorscriptCommandTypes.x05_LoopN: return 4;
case BehaviorscriptCommandTypes.x06_EndLoopN: return 4;
case BehaviorscriptCommandTypes.x07_InfiniteLoop: return 4;
case BehaviorscriptCommandTypes.x08_LoopStart: return 4;
case BehaviorscriptCommandTypes.x09_LoopEnd: return 4;
case BehaviorscriptCommandTypes.x0A_EndBehaviorscript: return 4;
case BehaviorscriptCommandTypes.x0B_EndBehaviorscript_Unused: return 4;
case BehaviorscriptCommandTypes.x0C_CallFunction: return 8;
case BehaviorscriptCommandTypes.x0D_OffsetbyFloat: return 4;
case BehaviorscriptCommandTypes.x0E_SettoFloat: return 4;
case BehaviorscriptCommandTypes.x0F_OffsetbyInteger: return 4;
case BehaviorscriptCommandTypes.x10_SettoInteger: return 4;
case BehaviorscriptCommandTypes.x11_BitSet: return 4;
case BehaviorscriptCommandTypes.x12_BitClear: return 4;
case BehaviorscriptCommandTypes.x13_AddRNG: return 8;
case BehaviorscriptCommandTypes.x14_ObjectType: return 8;
case BehaviorscriptCommandTypes.x15_FloatMultiply: return 8;
case BehaviorscriptCommandTypes.x16_FloatAdd: return 8;
case BehaviorscriptCommandTypes.x17_AddRNG2: return 8;
case BehaviorscriptCommandTypes.x18_NoOperation: return 4;
case BehaviorscriptCommandTypes.x19_NoOperation: return 4;
case BehaviorscriptCommandTypes.x1A_NoOperation: return 4;
case BehaviorscriptCommandTypes.x1B_ChangeModelID: return 4;
case BehaviorscriptCommandTypes.x1C_LoadChildObject: return 0xC;
case BehaviorscriptCommandTypes.x1D_Deactivate: return 4;
case BehaviorscriptCommandTypes.x1E_DroptoGround: return 4;
case BehaviorscriptCommandTypes.x1F_UsedforWaves: return 4;
case BehaviorscriptCommandTypes.x20_Unused: return 4;
case BehaviorscriptCommandTypes.x21_SetBillboarding: return 4;
case BehaviorscriptCommandTypes.x22_SetRenderInvisibleflag: return 4;
case BehaviorscriptCommandTypes.x23_Collisioncylindersize: return 8;
case BehaviorscriptCommandTypes.x24_Nothing: return 4;
case BehaviorscriptCommandTypes.x25_StateCycle: return 4;
case BehaviorscriptCommandTypes.x26_Loop: return 4;
case BehaviorscriptCommandTypes.x27_SetWord: return 8;
case BehaviorscriptCommandTypes.x28_Animates: return 4;
case BehaviorscriptCommandTypes.x29_LoadChildObject: return 0xC;
case BehaviorscriptCommandTypes.x2A_SetCollision: return 8;
case BehaviorscriptCommandTypes.x2B_SetCollisionSphere: return 0xC;
case BehaviorscriptCommandTypes.x2C_SpawnObject: return 0xC;
case BehaviorscriptCommandTypes.x2D_SetInitPosition: return 4;
case BehaviorscriptCommandTypes.x2E_SetHurtbox: return 8;
case BehaviorscriptCommandTypes.x2F_SetInteraction: return 8;
case BehaviorscriptCommandTypes.x30_SetGravity: return 0x14;
case BehaviorscriptCommandTypes.x31_SetInteractionSubType: return 8;
case BehaviorscriptCommandTypes.x32_ScaleObject: return 4;
case BehaviorscriptCommandTypes.x33_ChildObjectChange: return 8;
case BehaviorscriptCommandTypes.x34_TextureAnimateRate: return 4;
case BehaviorscriptCommandTypes.x35_ClearGraphFlag: return 4;
case BehaviorscriptCommandTypes.x36_SetValue: return 8;
case BehaviorscriptCommandTypes.x37_SpawnSomething: return 8;
default: return -1; //throw new System.Exception("Command type not found!");
}
}
public static bool IsEndCommand(BehaviorscriptCommandTypes type, bool detectJumpsAsEnd = true)
{
switch (type)
{
case BehaviorscriptCommandTypes.x02_JumpandLink:
case BehaviorscriptCommandTypes.x04_Jump:
return detectJumpsAsEnd;
case BehaviorscriptCommandTypes.x06_EndLoopN:
case BehaviorscriptCommandTypes.x0A_EndBehaviorscript:
case BehaviorscriptCommandTypes.x0B_EndBehaviorscript_Unused:
case BehaviorscriptCommandTypes.x09_LoopEnd:
return true;
default:
return false;
}
}
} }

View File

@@ -1,7 +1,6 @@
namespace SM64Lib.Behaviors.Script namespace SM64Lib.Behaviors.Script;
public class BehaviorscriptCommandCollection : SM64Lib.Script.BaseCommandCollection<BehaviorscriptCommand, BehaviorscriptCommandTypes>
{ {
public class BehaviorscriptCommandCollection : SM64Lib.Script.BaseCommandCollection<BehaviorscriptCommand, BehaviorscriptCommandTypes>
{
}
} }

View File

@@ -1,32 +1,25 @@
using System; namespace SM64Lib.Behaviors.Script;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Behaviors.Script public static class BehaviorscriptCommandFactory
{ {
public static class BehaviorscriptCommandFactory public static BehaviorscriptCommand Build_x2A(int collisionPointer = -1)
{ {
public static BehaviorscriptCommand Build_x2A(int collisionPointer = -1) var cmd = new BehaviorscriptCommand("2a 00 00 00 00 00 00 00");
{ if (collisionPointer != -1)
var cmd = new BehaviorscriptCommand("2a 00 00 00 00 00 00 00"); BehaviorscriptCommandFunctions.X2A.SetCollisionPointer(cmd, collisionPointer);
if (collisionPointer != -1) return cmd;
BehaviorscriptCommandFunctions.X2A.SetCollisionPointer(cmd, collisionPointer); }
return cmd;
}
public static BehaviorscriptCommand Build_x08() public static BehaviorscriptCommand Build_x08()
{ {
return new BehaviorscriptCommand("08 00 00 00"); return new BehaviorscriptCommand("08 00 00 00");
} }
public static BehaviorscriptCommand Build_x0C(int asmPointer = -1) public static BehaviorscriptCommand Build_x0C(int asmPointer = -1)
{ {
var cmd = new BehaviorscriptCommand("0C 00 00 00 00 00 00 00"); var cmd = new BehaviorscriptCommand("0C 00 00 00 00 00 00 00");
if (asmPointer != -1) if (asmPointer != -1)
BehaviorscriptCommandFunctions.X2A.SetCollisionPointer(cmd, asmPointer); BehaviorscriptCommandFunctions.X2A.SetCollisionPointer(cmd, asmPointer);
return cmd; return cmd;
}
} }
} }

View File

@@ -1,39 +1,31 @@
using SM64Lib.Data; namespace SM64Lib.Behaviors.Script;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Behaviors.Script public class BehaviorscriptCommandFunctions
{ {
public class BehaviorscriptCommandFunctions public class X2A
{ {
public class X2A public static int GetCollisionPointer(BehaviorscriptCommand cmd)
{ {
public static int GetCollisionPointer(BehaviorscriptCommand cmd) cmd.Position = 4;
{ return cmd.ReadInt32();
cmd.Position = 4;
return cmd.ReadInt32();
}
public static void SetCollisionPointer(BehaviorscriptCommand cmd, int pointer)
{
cmd.Position = 4;
cmd.Write(pointer);
}
} }
public class X0C public static void SetCollisionPointer(BehaviorscriptCommand cmd, int pointer)
{ {
public static int GetAsmPointer(BehaviorscriptCommand cmd) cmd.Position = 4;
{ cmd.Write(pointer);
cmd.Position = 4; }
return cmd.ReadInt32(); }
} public class X0C
public static void SetAsmPointer(BehaviorscriptCommand cmd, int pointer) {
{ public static int GetAsmPointer(BehaviorscriptCommand cmd)
cmd.Position = 4; {
cmd.Write(pointer); cmd.Position = 4;
} return cmd.ReadInt32();
}
public static void SetAsmPointer(BehaviorscriptCommand cmd, int pointer)
{
cmd.Position = 4;
cmd.Write(pointer);
} }
} }
} }

View File

@@ -1,62 +1,61 @@
namespace SM64Lib.Behaviors.Script namespace SM64Lib.Behaviors.Script;
public enum BehaviorscriptCommandTypes
{ {
public enum BehaviorscriptCommandTypes x00_Start,
{ x01_StateLoop,
x00_Start, x02_JumpandLink,
x01_StateLoop, x03_Return,
x02_JumpandLink, x04_Jump,
x03_Return, x05_LoopN,
x04_Jump, x06_EndLoopN,
x05_LoopN, x07_InfiniteLoop,
x06_EndLoopN, x08_LoopStart,
x07_InfiniteLoop, x09_LoopEnd,
x08_LoopStart, x0A_EndBehaviorscript,
x09_LoopEnd, x0B_EndBehaviorscript_Unused,
x0A_EndBehaviorscript, x0C_CallFunction,
x0B_EndBehaviorscript_Unused, x0D_OffsetbyFloat,
x0C_CallFunction, x0E_SettoFloat,
x0D_OffsetbyFloat, x0F_OffsetbyInteger,
x0E_SettoFloat, x10_SettoInteger,
x0F_OffsetbyInteger, x11_BitSet,
x10_SettoInteger, x12_BitClear,
x11_BitSet, x13_AddRNG,
x12_BitClear, x14_ObjectType,
x13_AddRNG, x15_FloatMultiply,
x14_ObjectType, x16_FloatAdd,
x15_FloatMultiply, x17_AddRNG2,
x16_FloatAdd, x18_NoOperation,
x17_AddRNG2, x19_NoOperation,
x18_NoOperation, x1A_NoOperation,
x19_NoOperation, x1B_ChangeModelID,
x1A_NoOperation, x1C_LoadChildObject,
x1B_ChangeModelID, x1D_Deactivate,
x1C_LoadChildObject, x1E_DroptoGround,
x1D_Deactivate, x1F_UsedforWaves,
x1E_DroptoGround, x20_Unused,
x1F_UsedforWaves, x21_SetBillboarding,
x20_Unused, x22_SetRenderInvisibleflag,
x21_SetBillboarding, x23_Collisioncylindersize,
x22_SetRenderInvisibleflag, x24_Nothing,
x23_Collisioncylindersize, x25_StateCycle,
x24_Nothing, x26_Loop,
x25_StateCycle, x27_SetWord,
x26_Loop, x28_Animates,
x27_SetWord, x29_LoadChildObject,
x28_Animates, x2A_SetCollision,
x29_LoadChildObject, x2B_SetCollisionSphere,
x2A_SetCollision, x2C_SpawnObject,
x2B_SetCollisionSphere, x2D_SetInitPosition,
x2C_SpawnObject, x2E_SetHurtbox,
x2D_SetInitPosition, x2F_SetInteraction,
x2E_SetHurtbox, x30_SetGravity,
x2F_SetInteraction, x31_SetInteractionSubType,
x30_SetGravity, x32_ScaleObject,
x31_SetInteractionSubType, x33_ChildObjectChange,
x32_ScaleObject, x34_TextureAnimateRate,
x33_ChildObjectChange, x35_ClearGraphFlag,
x34_TextureAnimateRate, x36_SetValue,
x35_ClearGraphFlag, x37_SpawnSomething
x36_SetValue,
x37_SpawnSomething
}
} }

View File

@@ -1,22 +1,18 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Configuration namespace SM64Lib.Configuration;
public class CollisionBasicConfig
{ {
public class CollisionBasicConfig private List<byte> collisionTypesWithParams = new List<byte>()
{ { 4, 14, 44, 36, 37, 39, 45 };
private List<byte> collisionTypesWithParams = new List<byte>()
{ 4, 14, 44, 36, 37, 39, 45 };
[JsonProperty("CollisionTypesWithParamsV2", ObjectCreationHandling = ObjectCreationHandling.Replace)] [JsonProperty("CollisionTypesWithParamsV2", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<byte> CollisionTypesWithParams public List<byte> CollisionTypesWithParams
{ {
get => collisionTypesWithParams; get => collisionTypesWithParams;
private set => collisionTypesWithParams = value.Distinct().ToList(); private set => collisionTypesWithParams = value.Distinct().ToList();
}
} }
} }

View File

@@ -1,31 +1,30 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Objects.ModelBanks;
using System.Collections.Generic;
using Pilz.Cryptography; using Pilz.Cryptography;
using Pilz.Json.Converters; using Pilz.Json.Converters;
using SM64Lib.Objects.ModelBanks;
using System.Collections.Generic;
namespace SM64Lib.Configuration namespace SM64Lib.Configuration;
public class CustomModelConfig
{ {
public class CustomModelConfig internal delegate void RequestModelEventHandler(CustomModelConfig config, RequestModelEventArgs request);
internal static event RequestModelEventHandler RequestModel;
[JsonConverter(typeof(UniquieIDStringJsonConverter))]
public UniquieID ID { get; set; } = new();
public string Name { get; set; } = string.Empty;
public List<int> CollisionPointerDestinations { get; private set; } = new List<int>();
public CustomModel FindModel()
{ {
internal delegate void RequestModelEventHandler(CustomModelConfig config, RequestModelEventArgs request); var args = new RequestModelEventArgs();
internal static event RequestModelEventHandler RequestModel; RequestModel?.Invoke(this, args);
return args.Model;
}
[JsonConverter(typeof(UniquieIDStringJsonConverter))] internal class RequestModelEventArgs
public UniquieID ID { get; set; } = new(); {
public string Name { get; set; } = string.Empty; public CustomModel Model { get; set; }
public List<int> CollisionPointerDestinations { get; private set; } = new List<int>();
public CustomModel FindModel()
{
var args = new RequestModelEventArgs();
RequestModel?.Invoke(this, args);
return args.Model;
}
internal class RequestModelEventArgs
{
public CustomModel Model { get; set; }
}
} }
} }

View File

@@ -1,10 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace SM64Lib.Configuration namespace SM64Lib.Configuration;
public class LevelAreaConfig
{ {
public class LevelAreaConfig public string AreaName { get; set; }
{ public Dictionary<short, string> ScrollingNames { get; set; } = new Dictionary<short, string>();
public string AreaName { get; set; }
public Dictionary<short, string> ScrollingNames { get; set; } = new Dictionary<short, string>();
}
} }

View File

@@ -1,26 +1,25 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace SM64Lib.Configuration namespace SM64Lib.Configuration;
{
public class LevelConfig
{
public string LevelName { get; set; }
public bool EnableLocalObjectBank { get; set; } = false;
public ObjectModelConfig LocalObjectBank { get; set; } = new ObjectModelConfig();
public Dictionary<byte, LevelAreaConfig> AreaConfigs { get; private set; } = new Dictionary<byte, LevelAreaConfig>();
public LevelAreaConfig GetLevelAreaConfig(byte areaID) public class LevelConfig
{
public string LevelName { get; set; }
public bool EnableLocalObjectBank { get; set; } = false;
public ObjectModelConfig LocalObjectBank { get; set; } = new ObjectModelConfig();
public Dictionary<byte, LevelAreaConfig> AreaConfigs { get; private set; } = new Dictionary<byte, LevelAreaConfig>();
public LevelAreaConfig GetLevelAreaConfig(byte areaID)
{
if (AreaConfigs.ContainsKey(areaID))
{ {
if (AreaConfigs.ContainsKey(areaID)) return AreaConfigs[areaID];
{ }
return AreaConfigs[areaID]; else
} {
else var conf = new LevelAreaConfig();
{ AreaConfigs.Add(areaID, conf);
var conf = new LevelAreaConfig(); return conf;
AreaConfigs.Add(areaID, conf);
return conf;
}
} }
} }
} }

View File

@@ -1,9 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace SM64Lib.Configuration namespace SM64Lib.Configuration;
public class MusicConfiguration
{ {
public class MusicConfiguration public List<string> SqeuenceNames { get; private set; } = new List<string>();
{
public List<string> SqeuenceNames { get; private set; } = new List<string>();
}
} }

View File

@@ -1,13 +1,6 @@
using System; namespace SM64Lib.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Configuration public class NPCConfig
{ {
public class NPCConfig public bool Enabled3DCoins { get; set; } = false;
{
public bool Enabled3DCoins { get; set; } = false;
}
} }

View File

@@ -1,20 +1,19 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace SM64Lib.Configuration namespace SM64Lib.Configuration;
public class ObjectModelConfig
{ {
public class ObjectModelConfig public Dictionary<int, CustomModelConfig> CustomObjectConfigs { get; private set; } = new Dictionary<int, CustomModelConfig>();
public CustomModelConfig GetCustomObjectConfig(int id)
{ {
public Dictionary<int, CustomModelConfig> CustomObjectConfigs { get; private set; } = new Dictionary<int, CustomModelConfig>(); CustomModelConfig conf = null;
if (!CustomObjectConfigs.TryGetValue(id, out conf))
public CustomModelConfig GetCustomObjectConfig(int id)
{ {
CustomModelConfig conf = null; conf = new CustomModelConfig();
if (!CustomObjectConfigs.TryGetValue(id, out conf))
{
conf = new CustomModelConfig();
}
return conf;
} }
return conf;
} }
} }

View File

@@ -1,15 +1,9 @@
using Pilz.IO; using Pilz.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Configuration namespace SM64Lib.Configuration;
public class PatchingConfig
{ {
public class PatchingConfig public EmbeddedFilesContainer TweakBackups { get; } = new EmbeddedFilesContainer();
{ public bool Patched2DCamera { get; set; } = false;
public EmbeddedFilesContainer TweakBackups { get; } = new EmbeddedFilesContainer();
public bool Patched2DCamera { get; set; } = false;
}
} }

View File

@@ -1,78 +1,76 @@
using System.Collections.Generic; using global::Newtonsoft.Json.Linq;
using global::System.IO; using global::System.IO;
using Microsoft.VisualBasic.CompilerServices;
using global::Newtonsoft.Json.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.ASM;
using SM64Lib.Behaviors; using SM64Lib.Behaviors;
using SM64Lib.Objects.ObjectBanks; using SM64Lib.Objects.ObjectBanks;
using SM64Lib.ASM;
using SM64Lib.Objects.ObjectBanks.Data; using SM64Lib.Objects.ObjectBanks.Data;
using System; using System;
using System.Collections.Generic;
namespace SM64Lib.Configuration namespace SM64Lib.Configuration;
public class RomConfig
{ {
public class RomConfig // Levels
public Dictionary<byte, LevelConfig> LevelConfigs { get; } = new Dictionary<byte, LevelConfig>();
// Global Banks
[JsonProperty("GlobalObjectBankConfig")]
public ObjectModelConfig GlobalModelBank { get; } = new ObjectModelConfig();
public CustomAsmBankConfig GlobalCustomAsmBank { get; } = new CustomAsmBankConfig();
public BehaviorBankConfig GlobalBehaviorBank { get; } = new BehaviorBankConfig();
public CustomObjectCollection GlobalObjectBank { get; } = new CustomObjectCollection();
// Music
public MusicConfiguration MusicConfig { get; } = new MusicConfiguration();
// Texts
public Text.Profiles.TextProfileInfo TextProfileInfo { get; set; } = null;
// Patching
public PatchingConfig PatchingConfig { get; set; } = new PatchingConfig();
// Other
public ScrollTexConfig ScrollTexConfig { get; set; } = new ScrollTexConfig();
public ObjectBankDataListCollection ObjectBankInfoData { get; } = new ObjectBankDataListCollection();
public NPCConfig NPCConfig { get; } = new NPCConfig();
public CollisionBasicConfig CollisionBaseConfig { get; } = new CollisionBasicConfig();
/// <summary>
/// Contains custom configuration that isn't used by SM64Lib. E.g. Extra Object Combos.
/// </summary>
public Dictionary<string, string> CustomConfigs { get; } = new Dictionary<string, string>();
// F e a t u r e s
public LevelConfig GetLevelConfig(ushort levelID)
{ {
// Levels if (LevelConfigs.ContainsKey(Convert.ToByte(levelID)))
public Dictionary<byte, LevelConfig> LevelConfigs { get; } = new Dictionary<byte, LevelConfig>();
// Global Banks
[JsonProperty("GlobalObjectBankConfig")]
public ObjectModelConfig GlobalModelBank { get; } = new ObjectModelConfig();
public CustomAsmBankConfig GlobalCustomAsmBank { get; } = new CustomAsmBankConfig();
public BehaviorBankConfig GlobalBehaviorBank { get; } = new BehaviorBankConfig();
public CustomObjectCollection GlobalObjectBank { get; } = new CustomObjectCollection();
// Music
public MusicConfiguration MusicConfig { get; } = new MusicConfiguration();
// Texts
public Text.Profiles.TextProfileInfo TextProfileInfo { get; set; } = null;
// Patching
public PatchingConfig PatchingConfig { get; set; } = new PatchingConfig();
// Other
public ScrollTexConfig ScrollTexConfig { get; set; } = new ScrollTexConfig();
public ObjectBankDataListCollection ObjectBankInfoData { get; } = new ObjectBankDataListCollection();
public NPCConfig NPCConfig { get; } = new NPCConfig();
public CollisionBasicConfig CollisionBaseConfig { get; } = new CollisionBasicConfig();
/// <summary>
/// Contains custom configuration that isn't used by SM64Lib. E.g. Extra Object Combos.
/// </summary>
public Dictionary<string, string> CustomConfigs { get; } = new Dictionary<string, string>();
// F e a t u r e s
public LevelConfig GetLevelConfig(ushort levelID)
{ {
if (LevelConfigs.ContainsKey(Convert.ToByte(levelID))) return LevelConfigs[Convert.ToByte(levelID)];
{
return LevelConfigs[Convert.ToByte(levelID)];
}
else
{
var conf = new LevelConfig();
LevelConfigs.Add(Convert.ToByte(levelID), conf);
return conf;
}
} }
else
// L o a d / S a v e
public static RomConfig Load(string filePath)
{ {
var serializer = JsonSerializer.CreateDefault(); var conf = new LevelConfig();
serializer.PreserveReferencesHandling = PreserveReferencesHandling.All; LevelConfigs.Add(Convert.ToByte(levelID), conf);
return JObject.Parse(File.ReadAllText(filePath)).ToObject<RomConfig>(serializer); return conf;
}
public void Save(string filePath)
{
var serializer = JsonSerializer.CreateDefault();
serializer.PreserveReferencesHandling = PreserveReferencesHandling.All;
File.WriteAllText(filePath, JObject.FromObject(this, serializer).ToString());
} }
} }
// L o a d / S a v e
public static RomConfig Load(string filePath)
{
var serializer = JsonSerializer.CreateDefault();
serializer.PreserveReferencesHandling = PreserveReferencesHandling.All;
return JObject.Parse(File.ReadAllText(filePath)).ToObject<RomConfig>(serializer);
}
public void Save(string filePath)
{
var serializer = JsonSerializer.CreateDefault();
serializer.PreserveReferencesHandling = PreserveReferencesHandling.All;
File.WriteAllText(filePath, JObject.FromObject(this, serializer).ToString());
}
} }

View File

@@ -1,14 +1,7 @@
using System; namespace SM64Lib.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Configuration public class ScrollTexConfig
{ {
public class ScrollTexConfig public bool UseCustomBehavior { get; set; } = false;
{ public int CustomBehaviorAddress { get; set; } = -1;
public bool UseCustomBehavior { get; set; } = false;
public int CustomBehaviorAddress { get; set; } = -1;
}
} }

View File

@@ -1,28 +1,27 @@
using global::System.IO; using global::System.IO;
namespace SM64Lib.Data namespace SM64Lib.Data;
public class BinaryArrayData : BinaryStreamData
{ {
public class BinaryArrayData : BinaryStreamData public FileAccess RomAccess { get; private set; } = FileAccess.Read;
public BinaryArrayData(byte[] buffer) : base(new MemoryStream(buffer))
{ {
public FileAccess RomAccess { get; private set; } = FileAccess.Read;
public BinaryArrayData(byte[] buffer) : base(new MemoryStream(buffer))
{
}
// Inherits BinaryData
// Private ReadOnly myBaseStream As Stream
// Public ReadOnly Property RomAccess As FileAccess = FileAccess.Read
// Public Sub New(buffer As Byte())
// myBaseStream = New MemoryStream(buffer)
// End Sub
// Protected Overrides Function GetBaseStream() As Stream
// Return myBaseStream
// End Function
} }
// Inherits BinaryData
// Private ReadOnly myBaseStream As Stream
// Public ReadOnly Property RomAccess As FileAccess = FileAccess.Read
// Public Sub New(buffer As Byte())
// myBaseStream = New MemoryStream(buffer)
// End Sub
// Protected Overrides Function GetBaseStream() As Stream
// Return myBaseStream
// End Function
} }

View File

@@ -2,279 +2,278 @@
using SM64Lib.Data.System; using SM64Lib.Data.System;
using System; using System;
namespace SM64Lib.Data namespace SM64Lib.Data;
public abstract class BinaryData : IDisposable
{ {
public abstract class BinaryData : IDisposable public delegate void AnyBinaryDataEventHandler(BinaryData data);
public static event AnyBinaryDataEventHandler AnyBinaryDataOpened;
public static event AnyBinaryDataEventHandler AnyBinaryDataClosing;
public static event AnyBinaryDataEventHandler AnyBinaryDataClosed;
public static event AnyBinaryDataDisposedEventHandler AnyBinaryDataDisposed;
public delegate void AnyBinaryDataDisposedEventHandler();
private Stream _BaseStream = null;
private BinaryWriter _writer = null;
private BinaryReader _reader = null;
public RomManager RomManager { get; private set; }
protected abstract Stream GetBaseStream();
protected BinaryWriter Writer
{ {
public delegate void AnyBinaryDataEventHandler(BinaryData data); get
public static event AnyBinaryDataEventHandler AnyBinaryDataOpened;
public static event AnyBinaryDataEventHandler AnyBinaryDataClosing;
public static event AnyBinaryDataEventHandler AnyBinaryDataClosed;
public static event AnyBinaryDataDisposedEventHandler AnyBinaryDataDisposed;
public delegate void AnyBinaryDataDisposedEventHandler();
private Stream _BaseStream = null;
private BinaryWriter _writer = null;
private BinaryReader _reader = null;
public RomManager RomManager { get; private set; }
protected abstract Stream GetBaseStream();
protected BinaryWriter Writer
{ {
get if (_writer is null)
{ {
if (_writer is null) _writer = new BinaryWriter(BaseStream);
{
_writer = new BinaryWriter(BaseStream);
}
return _writer;
}
}
protected BinaryReader Reader
{
get
{
if (_reader is null)
{
_reader = new BinaryReader(BaseStream);
}
return _reader;
}
}
public long Position
{
get
{
return BaseStream.Position;
} }
set return _writer;
{
BaseStream.Position = value;
}
}
public long Length
{
get
{
return BaseStream.Length;
}
}
public Stream BaseStream
{
get
{
if (_BaseStream is null)
{
_BaseStream = GetBaseStream();
RaiseAnyBinaryDataOpened(this);
}
return _BaseStream;
}
}
~BinaryData()
{
AnyBinaryDataDisposed?.Invoke();
}
public void RoundUpPosition()
{
Position = General.HexRoundUp1(Position);
}
public void RoundUpPosition(int add)
{
Position = General.HexRoundUp1(Position + add);
}
protected void SetRomManager(RomManager rommgr)
{
RomManager = rommgr;
}
public void Write(sbyte value)
{
Writer.Write(value);
}
public void Write(byte value)
{
Writer.Write(value);
}
public void WriteByte(byte value)
{
Write(value);
}
public void Write(short value)
{
Writer.Write(SwapInts.SwapInt16(value));
}
public void Write(ushort value)
{
Writer.Write(SwapInts.SwapUInt16(value));
}
public void Write(int value)
{
Writer.Write(SwapInts.SwapInt32(value));
}
public void Write(uint value)
{
Writer.Write(SwapInts.SwapUInt32(value));
}
public void Write(long value)
{
Writer.Write(SwapInts.SwapInt64(value));
}
public void Write(ulong value)
{
Writer.Write(SwapInts.SwapUInt64(value));
}
public void Write(float value, bool isHalf = false)
{
if (isHalf)
Writer.Write(SwapInts.SwapHalf(value));
else
Writer.Write(SwapInts.SwapFloat32(value));
}
public void Write(string value)
{
Writer.Write(value);
}
public void Write(byte[] buffer)
{
Write(buffer, 0, buffer.Length);
}
public void Write(byte[] buffer, int index, int count)
{
Writer.Write(buffer, index, count);
}
public byte ReadByte()
{
return Reader.ReadByte();
}
public sbyte ReadSByte()
{
return Reader.ReadSByte();
}
public short ReadInt16()
{
return SwapInts.SwapInt16(Reader.ReadInt16());
}
public ushort ReadUInt16()
{
return SwapInts.SwapUInt16(Reader.ReadUInt16());
}
public int ReadInt32()
{
return SwapInts.SwapInt32(Reader.ReadInt32());
}
public uint ReadUInt32()
{
return SwapInts.SwapUInt32(Reader.ReadUInt32());
}
public long ReadInt64()
{
return SwapInts.SwapInt64(Reader.ReadInt64());
}
public ulong ReadUInt64()
{
return SwapInts.SwapUInt64(Reader.ReadUInt64());
}
public float ReadSingle()
{
return SwapInts.SwapFloat32(Reader.ReadSingle());
}
public string ReadString()
{
return Reader.ReadString();
}
public void Read(byte[] buffer)
{
Read(buffer, 0, buffer.Length);
}
public void Read(byte[] buffer, int index, int count)
{
Reader.Read(buffer, index, count);
}
public byte[] Read(int count)
{
var buf = new byte[count];
Read(buf, 0, count);
return buf;
}
public void Close()
{
AnyBinaryDataClosing?.Invoke(this);
BaseStream.Close();
AnyBinaryDataClosed?.Invoke(this);
}
public bool CanRead
{
get
{
return BaseStream.CanRead;
}
}
public bool CanWrite
{
get
{
return BaseStream.CanWrite;
}
}
public void SetLength(long length)
{
BaseStream.SetLength(length);
}
internal static void RaiseAnyBinaryDataOpened(BinaryData data)
{
AnyBinaryDataOpened?.Invoke(data);
}
public void Dispose()
{
Close();
} }
} }
protected BinaryReader Reader
{
get
{
if (_reader is null)
{
_reader = new BinaryReader(BaseStream);
}
return _reader;
}
}
public long Position
{
get
{
return BaseStream.Position;
}
set
{
BaseStream.Position = value;
}
}
public long Length
{
get
{
return BaseStream.Length;
}
}
public Stream BaseStream
{
get
{
if (_BaseStream is null)
{
_BaseStream = GetBaseStream();
RaiseAnyBinaryDataOpened(this);
}
return _BaseStream;
}
}
~BinaryData()
{
AnyBinaryDataDisposed?.Invoke();
}
public void RoundUpPosition()
{
Position = General.HexRoundUp1(Position);
}
public void RoundUpPosition(int add)
{
Position = General.HexRoundUp1(Position + add);
}
protected void SetRomManager(RomManager rommgr)
{
RomManager = rommgr;
}
public void Write(sbyte value)
{
Writer.Write(value);
}
public void Write(byte value)
{
Writer.Write(value);
}
public void WriteByte(byte value)
{
Write(value);
}
public void Write(short value)
{
Writer.Write(SwapInts.SwapInt16(value));
}
public void Write(ushort value)
{
Writer.Write(SwapInts.SwapUInt16(value));
}
public void Write(int value)
{
Writer.Write(SwapInts.SwapInt32(value));
}
public void Write(uint value)
{
Writer.Write(SwapInts.SwapUInt32(value));
}
public void Write(long value)
{
Writer.Write(SwapInts.SwapInt64(value));
}
public void Write(ulong value)
{
Writer.Write(SwapInts.SwapUInt64(value));
}
public void Write(float value, bool isHalf = false)
{
if (isHalf)
Writer.Write(SwapInts.SwapHalf(value));
else
Writer.Write(SwapInts.SwapFloat32(value));
}
public void Write(string value)
{
Writer.Write(value);
}
public void Write(byte[] buffer)
{
Write(buffer, 0, buffer.Length);
}
public void Write(byte[] buffer, int index, int count)
{
Writer.Write(buffer, index, count);
}
public byte ReadByte()
{
return Reader.ReadByte();
}
public sbyte ReadSByte()
{
return Reader.ReadSByte();
}
public short ReadInt16()
{
return SwapInts.SwapInt16(Reader.ReadInt16());
}
public ushort ReadUInt16()
{
return SwapInts.SwapUInt16(Reader.ReadUInt16());
}
public int ReadInt32()
{
return SwapInts.SwapInt32(Reader.ReadInt32());
}
public uint ReadUInt32()
{
return SwapInts.SwapUInt32(Reader.ReadUInt32());
}
public long ReadInt64()
{
return SwapInts.SwapInt64(Reader.ReadInt64());
}
public ulong ReadUInt64()
{
return SwapInts.SwapUInt64(Reader.ReadUInt64());
}
public float ReadSingle()
{
return SwapInts.SwapFloat32(Reader.ReadSingle());
}
public string ReadString()
{
return Reader.ReadString();
}
public void Read(byte[] buffer)
{
Read(buffer, 0, buffer.Length);
}
public void Read(byte[] buffer, int index, int count)
{
Reader.Read(buffer, index, count);
}
public byte[] Read(int count)
{
var buf = new byte[count];
Read(buf, 0, count);
return buf;
}
public void Close()
{
AnyBinaryDataClosing?.Invoke(this);
BaseStream.Close();
AnyBinaryDataClosed?.Invoke(this);
}
public bool CanRead
{
get
{
return BaseStream.CanRead;
}
}
public bool CanWrite
{
get
{
return BaseStream.CanWrite;
}
}
public void SetLength(long length)
{
BaseStream.SetLength(length);
}
internal static void RaiseAnyBinaryDataOpened(BinaryData data)
{
AnyBinaryDataOpened?.Invoke(data);
}
public void Dispose()
{
Close();
}
} }

View File

@@ -1,11 +1,10 @@
using global::System.IO; using global::System.IO;
namespace SM64Lib.Data namespace SM64Lib.Data;
public class BinaryFile : BinaryStreamData
{ {
public class BinaryFile : BinaryStreamData public BinaryFile(string filePath, FileMode fileMode, FileAccess fileAccess) : base(new FileStream(filePath, fileMode, fileAccess))
{ {
public BinaryFile(string filePath, FileMode fileMode, FileAccess fileAccess) : base(new FileStream(filePath, fileMode, fileAccess))
{
}
} }
} }

View File

@@ -1,26 +1,25 @@
using global::System.IO; using global::System.IO;
namespace SM64Lib.Data namespace SM64Lib.Data;
public class BinaryRom : BinaryFile
{ {
public class BinaryRom : BinaryFile public BinaryRom(RomManager rommgr, FileAccess romAccess) : base(rommgr.RomFile, FileMode.Open, romAccess)
{ {
public BinaryRom(RomManager rommgr, FileAccess romAccess) : base(rommgr.RomFile, FileMode.Open, romAccess) SetRomManager(rommgr);
{
SetRomManager(rommgr);
}
// Inherits BinaryData
// Public ReadOnly Property RomAccess As FileAccess = FileAccess.Read
// Public Sub New(rommgr As RomManager, romAccess As FileAccess)
// SetRomManager(rommgr)
// Me.RomAccess = romAccess
// End Sub
// Protected Overrides Function GetBaseStream() As Stream
// Return RomManager.GetStream(RomAccess)
// End Function
} }
// Inherits BinaryData
// Public ReadOnly Property RomAccess As FileAccess = FileAccess.Read
// Public Sub New(rommgr As RomManager, romAccess As FileAccess)
// SetRomManager(rommgr)
// Me.RomAccess = romAccess
// End Sub
// Protected Overrides Function GetBaseStream() As Stream
// Return RomManager.GetStream(RomAccess)
// End Function
} }

View File

@@ -1,33 +1,32 @@
using global::System.IO; using global::SM64Lib.SegmentedBanking;
using global::SM64Lib.SegmentedBanking; using global::System.IO;
namespace SM64Lib.Data namespace SM64Lib.Data;
public class BinarySegBank : BinaryData
{ {
public class BinarySegBank : BinaryData public SegmentedBank SegBank { get; private set; }
public BinarySegBank(SegmentedBank segBank, RomManager rommgr)
{ {
public SegmentedBank SegBank { get; private set; } SegBank = segBank;
SetRomManager(rommgr);
}
public BinarySegBank(SegmentedBank segBank, RomManager rommgr) public BinarySegBank(SegmentedBank segBank)
{
SegBank = segBank;
}
protected override Stream GetBaseStream()
{
if (RomManager is not null)
{ {
SegBank = segBank; var s = RomManager.GetBinaryRom(FileAccess.Read);
SetRomManager(rommgr); SegBank.ReadDataIfNull(s.BaseStream);
s.Close();
} }
public BinarySegBank(SegmentedBank segBank) return SegBank.Data;
{
SegBank = segBank;
}
protected override Stream GetBaseStream()
{
if (RomManager is not null)
{
var s = RomManager.GetBinaryRom(FileAccess.Read);
SegBank.ReadDataIfNull(s.BaseStream);
s.Close();
}
return SegBank.Data;
}
} }
} }

View File

@@ -1,20 +1,19 @@
using global::System.IO; using global::System.IO;
namespace SM64Lib.Data namespace SM64Lib.Data;
public class BinaryStreamData : BinaryData
{ {
public class BinaryStreamData : BinaryData protected readonly Stream myBaseStream;
public BinaryStreamData(Stream stream)
{ {
protected readonly Stream myBaseStream; myBaseStream = stream;
//RaiseAnyBinaryDataOpened(this);
}
public BinaryStreamData(Stream stream) protected override Stream GetBaseStream()
{ {
myBaseStream = stream; return myBaseStream;
//RaiseAnyBinaryDataOpened(this);
}
protected override Stream GetBaseStream()
{
return myBaseStream;
}
} }
} }

View File

@@ -1,98 +1,96 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Linq; using System.Linq;
using Microsoft.VisualBasic.CompilerServices;
namespace SM64Lib.Data.System namespace SM64Lib.Data.System;
public class Bits
{ {
public class Bits public static byte[] ByteToBitArray(byte b)
{ {
public static byte[] ByteToBitArray(byte b) var bitarray = new BitArray(new[] { b });
var temp = new byte[bitarray.Length];
for (int i = 0, loopTo = bitarray.Length - 1; i <= loopTo; i++)
temp[i] = Convert.ToByte(bitarray[i]);
int tindex = 0;
var temp2 = new byte[(temp.Count())];
for (int i = temp.Length - 1; i >= 0; i += -1)
{ {
var bitarray = new BitArray(new[] { b }); temp2[tindex] = temp[i];
var temp = new byte[bitarray.Length]; tindex += 1;
for (int i = 0, loopTo = bitarray.Length - 1; i <= loopTo; i++)
temp[i] = Convert.ToByte(bitarray[i]);
int tindex = 0;
var temp2 = new byte[(temp.Count())];
for (int i = temp.Length - 1; i >= 0; i += -1)
{
temp2[tindex] = temp[i];
tindex += 1;
}
return temp2;
} }
public static bool[] ByteToBoolArray(byte b) return temp2;
{ }
var bitarray = new BitArray(new[] { b });
var temp = new bool[bitarray.Length];
for (int i = 0, loopTo = bitarray.Length - 1; i <= loopTo; i++)
temp[i] = Convert.ToBoolean(bitarray[i]);
int tindex = 0;
var temp2 = new bool[(temp.Count())];
for (int i = temp.Length - 1; i >= 0; i += -1)
{
temp2[tindex] = temp[i];
tindex += 1;
}
return temp2; public static bool[] ByteToBoolArray(byte b)
{
var bitarray = new BitArray(new[] { b });
var temp = new bool[bitarray.Length];
for (int i = 0, loopTo = bitarray.Length - 1; i <= loopTo; i++)
temp[i] = Convert.ToBoolean(bitarray[i]);
int tindex = 0;
var temp2 = new bool[(temp.Count())];
for (int i = temp.Length - 1; i >= 0; i += -1)
{
temp2[tindex] = temp[i];
tindex += 1;
} }
public static byte ArrayToByte(byte[] ba) return temp2;
}
public static byte ArrayToByte(byte[] ba)
{
// ODER: BitArray.ToByte()
byte endval = 0;
int index = ba.Count() - 1;
foreach (var bit in ba)
{ {
// ODER: BitArray.ToByte() endval += (byte)(bit * Math.Pow(2, index));
index -= 1;
byte endval = 0;
int index = ba.Count() - 1;
foreach (var bit in ba)
{
endval += (byte)(bit * Math.Pow(2, index));
index -= 1;
}
return endval;
} }
public static byte ArrayToByte(bool[] ba) return endval;
}
public static byte ArrayToByte(bool[] ba)
{
// ODER: BitArray.ToByte()
byte endval = 0;
int index = ba.Count() - 1;
foreach (var bit in ba)
{ {
// ODER: BitArray.ToByte() endval += (byte)((bit ? 1 : 0) * Math.Pow(2, index));
index -= 1;
byte endval = 0;
int index = ba.Count() - 1;
foreach (var bit in ba)
{
endval += (byte)((bit ? 1 : 0) * Math.Pow(2, index));
index -= 1;
}
return endval;
} }
public static byte SetInByte(byte b, int index, byte value) return endval;
{ }
var temp = ByteToBitArray(b);
temp[index] = value;
return ArrayToByte(temp);
}
public static byte SetInByte(byte b, int index, bool value) public static byte SetInByte(byte b, int index, byte value)
{ {
var temp = ByteToBoolArray(b); var temp = ByteToBitArray(b);
temp[index] = value; temp[index] = value;
return ArrayToByte(temp); return ArrayToByte(temp);
} }
public static byte GetBitOfByte(byte b, int index) public static byte SetInByte(byte b, int index, bool value)
{ {
return ByteToBitArray(b)[index]; var temp = ByteToBoolArray(b);
} temp[index] = value;
return ArrayToByte(temp);
}
public static bool GetBoolOfByte(byte b, int index) public static byte GetBitOfByte(byte b, int index)
{ {
return ByteToBoolArray(b)[index]; return ByteToBitArray(b)[index];
} }
public static bool GetBoolOfByte(byte b, int index)
{
return ByteToBoolArray(b)[index];
} }
} }

View File

@@ -1,62 +1,61 @@
using System; using System;
namespace SM64Lib.Data.System namespace SM64Lib.Data.System;
internal static class SwapInts
{ {
internal static class SwapInts public static short SwapInt16(short value)
{ {
public static short SwapInt16(short value) var bytes = BitConverter.GetBytes(value);
{ Array.Reverse(bytes);
var bytes = BitConverter.GetBytes(value); return BitConverter.ToInt16(bytes, 0);
Array.Reverse(bytes); }
return BitConverter.ToInt16(bytes, 0);
}
public static ushort SwapUInt16(ushort value) public static ushort SwapUInt16(ushort value)
{ {
var bytes = BitConverter.GetBytes(value); var bytes = BitConverter.GetBytes(value);
Array.Reverse(bytes); Array.Reverse(bytes);
return BitConverter.ToUInt16(bytes, 0); return BitConverter.ToUInt16(bytes, 0);
} }
public static int SwapInt32(int value) public static int SwapInt32(int value)
{ {
var bytes = BitConverter.GetBytes(value); var bytes = BitConverter.GetBytes(value);
Array.Reverse(bytes); Array.Reverse(bytes);
return BitConverter.ToInt32(bytes, 0); return BitConverter.ToInt32(bytes, 0);
} }
public static uint SwapUInt32(uint value) public static uint SwapUInt32(uint value)
{ {
var bytes = BitConverter.GetBytes(value); var bytes = BitConverter.GetBytes(value);
Array.Reverse(bytes); Array.Reverse(bytes);
return BitConverter.ToUInt32(bytes, 0); return BitConverter.ToUInt32(bytes, 0);
} }
public static long SwapInt64(long value) public static long SwapInt64(long value)
{ {
var bytes = BitConverter.GetBytes(value); var bytes = BitConverter.GetBytes(value);
Array.Reverse(bytes); Array.Reverse(bytes);
return BitConverter.ToInt64(bytes, 0); return BitConverter.ToInt64(bytes, 0);
} }
public static ulong SwapUInt64(ulong value) public static ulong SwapUInt64(ulong value)
{ {
var bytes = BitConverter.GetBytes(value); var bytes = BitConverter.GetBytes(value);
Array.Reverse(bytes); Array.Reverse(bytes);
return BitConverter.ToUInt64(bytes, 0); return BitConverter.ToUInt64(bytes, 0);
} }
public static short SwapHalf(float value) public static short SwapHalf(float value)
{ {
byte[] bytes = BitConverter.GetBytes(value); byte[] bytes = BitConverter.GetBytes(value);
return (short)(BitConverter.ToInt32(bytes, 0) >> 16); return (short)(BitConverter.ToInt32(bytes, 0) >> 16);
} }
public static float SwapFloat32(float value) public static float SwapFloat32(float value)
{ {
byte[] bytes = BitConverter.GetBytes(value); byte[] bytes = BitConverter.GetBytes(value);
Array.Reverse(bytes); Array.Reverse(bytes);
return BitConverter.ToSingle(bytes, 0); return BitConverter.ToSingle(bytes, 0);
}
} }
} }

View File

@@ -1,39 +1,38 @@
using global::System.Runtime.InteropServices; using global::System.Runtime.InteropServices;
namespace SM64Lib namespace SM64Lib;
static class Datatypecastes
{ {
static class Datatypecastes public static short LongToInt16(long value)
{ {
public static short LongToInt16(long value) var cast = default(CasterLongInt16);
{ cast.LongValue = value;
var cast = default(CasterLongInt16); return cast.Int16Value;
cast.LongValue = value; }
return cast.Int16Value;
}
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
private struct CasterLongInt16 private struct CasterLongInt16
{ {
[FieldOffset(0)] [FieldOffset(0)]
public long LongValue; public long LongValue;
[FieldOffset(0)] [FieldOffset(0)]
public short Int16Value; public short Int16Value;
} }
public static byte LongToByte(long value) public static byte LongToByte(long value)
{ {
var cast = default(CasterLongByte); var cast = default(CasterLongByte);
cast.LongValue = value; cast.LongValue = value;
return cast.ByteValue; return cast.ByteValue;
} }
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
private struct CasterLongByte private struct CasterLongByte
{ {
[FieldOffset(0)] [FieldOffset(0)]
public long LongValue; public long LongValue;
[FieldOffset(0)] [FieldOffset(0)]
public byte ByteValue; public byte ByteValue;
}
} }
} }

View File

@@ -1,13 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.EventArguments namespace SM64Lib.EventArguments;
public class GetTextProfileInfoEventArgs : EventArgs
{ {
public class GetTextProfileInfoEventArgs : EventArgs public Text.Profiles.TextProfileInfo ProfileInfo { get; set; }
{
public Text.Profiles.TextProfileInfo ProfileInfo { get; set; }
}
} }

View File

@@ -1,13 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.EventArguments namespace SM64Lib.EventArguments;
public class PrepairingRomEventArgs : EventArgs
{ {
public class PrepairingRomEventArgs : EventArgs public IEnumerable<BaseTweakScriptInfo> ScriptInfos { get; set; }
{
public IEnumerable<BaseTweakScriptInfo> ScriptInfos { get; set; }
}
} }

View File

@@ -1,14 +1,13 @@
using System; using System;
namespace SM64Lib.EventArguments namespace SM64Lib.EventArguments;
{
public class RomVersionEventArgs : EventArgs
{
public RomVersion RomVersion { get; set; }
internal RomVersionEventArgs(RomVersion romVersion) public class RomVersionEventArgs : EventArgs
{ {
RomVersion = romVersion; public RomVersion RomVersion { get; set; }
}
internal RomVersionEventArgs(RomVersion romVersion)
{
RomVersion = romVersion;
} }
} }

View File

@@ -1,8 +1,7 @@
using System; using System;
namespace SM64Lib.Exceptions namespace SM64Lib.Exceptions;
public class InvalidMD5HashException : Exception
{ {
public class InvalidMD5HashException : Exception
{
}
} }

View File

@@ -1,11 +1,10 @@
using System; using System;
namespace SM64Lib.Exceptions namespace SM64Lib.Exceptions;
public class RomCompatiblityException : Exception
{ {
public class RomCompatiblityException : Exception public RomCompatiblityException(string msg) : base(msg)
{ {
public RomCompatiblityException(string msg) : base(msg)
{
}
} }
} }

View File

@@ -2,32 +2,31 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace SM64Lib.Extensions namespace SM64Lib.Extensions;
public static class Int16Extensions
{ {
public static class Int16Extensions public static bool IsInRange(this short value, short min, short max)
{ {
public static bool IsInRange(this short value, short min, short max) return value >= min && value <= max;
{
return value >= min && value <= max;
}
} }
}
public static class ObjectExtensions public static class ObjectExtensions
{
public static void CloneTo<T>(this T source, T destination) where T : class
{ {
public static void CloneTo<T>(this T source, T destination) where T : class var json = JsonSerializer.CreateDefault();
{ var jobj = JObject.FromObject(source);
var json = JsonSerializer.CreateDefault(); jobj.Populate(destination);
var jobj = JObject.FromObject(source);
jobj.Populate(destination);
}
} }
}
public static class JsonExtensions public static class JsonExtensions
{
public static void Populate(this JToken value, object target)
{ {
public static void Populate(this JToken value, object target) using (var sr = value.CreateReader())
{ JsonSerializer.CreateDefault().Populate(sr, target);
using (var sr = value.CreateReader())
JsonSerializer.CreateDefault().Populate(sr, target);
}
} }
} }

View File

@@ -1,49 +1,48 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace SM64Lib namespace SM64Lib;
public class FilePathsConfiguration
{ {
public class FilePathsConfiguration
// S T A T I C M E M B E R S
public static FilePathsConfiguration DefaultConfiguration { get; private set; } = new FilePathsConfiguration();
public static string[] AllFileKeys
{ {
get
// S T A T I C M E M B E R S
public static FilePathsConfiguration DefaultConfiguration { get; private set; } = new FilePathsConfiguration();
public static string[] AllFileKeys
{ {
get return new[] { "rn64crc.exe", "ApplyPPF3.exe", "Level Tabel.json", "Update-Patches.json", "Update Patches Folder", "Text Profiles.json", "BaseTweak", "sm64extend.exe", "Original Level Pointers.bin", "armips.exe", "Flips.exe", "nconvert.exe" };
{
return new[] { "rn64crc.exe","ApplyPPF3.exe", "Level Tabel.json", "Update-Patches.json", "Update Patches Folder", "Text Profiles.json", "BaseTweak", "sm64extend.exe", "Original Level Pointers.bin", "armips.exe", "Flips.exe", "nconvert.exe" };
}
}
// F I E L D S
private readonly Dictionary<string, string> dic = new Dictionary<string, string>();
// P R O P E R T I E S
public IReadOnlyDictionary<string, string> Files
{
get
{
return dic;
}
}
// C O N S T R U C T O R
public FilePathsConfiguration()
{
foreach (string key in AllFileKeys)
dic.Add(key, string.Empty);
}
// M E T H O D S
public void SetFilePath(string key, string path)
{
dic[key] = path;
} }
} }
// F I E L D S
private readonly Dictionary<string, string> dic = new Dictionary<string, string>();
// P R O P E R T I E S
public IReadOnlyDictionary<string, string> Files
{
get
{
return dic;
}
}
// C O N S T R U C T O R
public FilePathsConfiguration()
{
foreach (string key in AllFileKeys)
dic.Add(key, string.Empty);
}
// M E T H O D S
public void SetFilePath(string key, string path)
{
dic[key] = path;
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,17 @@
namespace SM64Lib.Geolayout namespace SM64Lib.Geolayout;
public enum BackgroundIDs : byte
{ {
public enum BackgroundIDs : byte HauntedForest = 0x6,
{ SnowyMountains = 0x4,
HauntedForest = 0x6, Desert = 0x5,
SnowyMountains = 0x4, Ocean = 0x0,
Desert = 0x5, UnderwaterCity = 0x2,
Ocean = 0x0, BelowClouds = 0x8,
UnderwaterCity = 0x2, AboveClouds = 0x3,
BelowClouds = 0x8, Cavern = 0x7,
AboveClouds = 0x3, FlamingSky = 0x1,
Cavern = 0x7, PurpleClouds = 0x9,
FlamingSky = 0x1, Custom = 0xA
PurpleClouds = 0x9,
Custom = 0xA
}
} }

View File

@@ -1,27 +1,26 @@
namespace SM64Lib.Geolayout namespace SM64Lib.Geolayout;
public enum BackgroundPointers
{ {
public enum BackgroundPointers HauntedForestStart = 0xC3B030, // &HC3AFD5
{ HauntedForestEnd = 0xC4F970, // &HC4F915
HauntedForestStart = 0xC3B030, // &HC3AFD5 SnowyMountainsStart = 0xB5D8B0, // &HB5D855
HauntedForestEnd = 0xC4F970, // &HC4F915 SnowyMountainsEnd = 0xB7D9F0, // &HB7D995
SnowyMountainsStart = 0xB5D8B0, // &HB5D855 DesertStart = 0xC12EF0, // &HC12E95
SnowyMountainsEnd = 0xB7D9F0, // &HB7D995 DesertEnd = 0xC33030, // &HC32FD5
DesertStart = 0xC12EF0, // &HC12E95 OceanStart = 0xB35770, // &HB35715
DesertEnd = 0xC33030, // &HC32FD5 OceanEnd = 0xB558B0, // &HB55855
OceanStart = 0xB35770, // &HB35715 UnderwaterCityStart = 0xBC2C70, // &HBC2C15
OceanEnd = 0xB558B0, // &HB55855 UnderwaterCityEnd = 0xBE2DB0, // &HBE2D55
UnderwaterCityStart = 0xBC2C70, // &HBC2C15 BelowCloudsStart = 0xB859F0, // &HB85995
UnderwaterCityEnd = 0xBE2DB0, // &HBE2D55 BelowCloudsEnd = 0xB9A330, // &HB9A2D5
BelowCloudsStart = 0xB859F0, // &HB85995 AboveCloudsStart = 0xBEADB0, // &HBEAD55
BelowCloudsEnd = 0xB9A330, // &HB9A2D5 AboveCloudsEnd = 0xC0AEF0, // &HC0AE95
AboveCloudsStart = 0xBEADB0, // &HBEAD55 CavernStart = 0xC57970, // &HC57915
AboveCloudsEnd = 0xC0AEF0, // &HC0AE95 CavernEnd = 0xC77AB0, // &HC77A55
CavernStart = 0xC57970, // &HC57915 FlamingSkyStart = 0xBA2330, // &HBA22D5
CavernEnd = 0xC77AB0, // &HC77A55 FlamingSkyEnd = 0xBBAC70, // &HBBAC15
FlamingSkyStart = 0xBA2330, // &HBA22D5 PurpleCloudsStart = 0xC7FAB0, // &HC7FA55
FlamingSkyEnd = 0xBBAC70, // &HBBAC15 PurpleCloudsEnd = 0xC9FBF0 // &HC9FB95
PurpleCloudsStart = 0xC7FAB0, // &HC7FA55
PurpleCloudsEnd = 0xC9FBF0 // &HC9FB95
}
} }

View File

@@ -1,20 +1,13 @@
using System; namespace SM64Lib.Geolayout;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Geolayout public class CameraFrustrum
{ {
public class CameraFrustrum /// <summary>
{ /// This is essentially render distance of geometry.
/// <summary> /// </summary>
/// This is essentially render distance of geometry. public short CameraFar { get; set; } = 0x7530;
/// </summary> /// <summary>
public short CameraFar { get; set; } = 0x7530; /// Defines how close to the camera geometry will render.
/// <summary> /// </summary>
/// Defines how close to the camera geometry will render. public short CameraNear { get; set; } = 0x64;
/// </summary>
public short CameraNear { get; set; } = 0x64;
}
} }

View File

@@ -1,23 +1,22 @@
namespace SM64Lib.Geolayout namespace SM64Lib.Geolayout;
public enum CameraPresets
{ {
public enum CameraPresets OpenCamera = 0x1,
{ TickTockClock,
OpenCamera = 0x1, SecretAquarium,
TickTockClock, InsideCastle,
SecretAquarium, Unmoving,
InsideCastle, MarioFacingObject,
Unmoving, Unmoving1,
MarioFacingObject, UnderwaterCamera,
Unmoving1, PeachSlideCamera,
UnderwaterCamera, InsideCannon,
PeachSlideCamera, BowserFightsDistant,
InsideCannon, CloseCameraCrashes,
BowserFightsDistant, FixedReferencePoint,
CloseCameraCrashes, PlattfromLevels,
FixedReferencePoint, Unmoving2,
PlattfromLevels, FreeRoamCamera
Unmoving2,
FreeRoamCamera
}
} }

View File

@@ -1,15 +1,14 @@
namespace SM64Lib.Geolayout namespace SM64Lib.Geolayout;
public enum DefaultGeolayers
{ {
public enum DefaultGeolayers SolidNoAntiAlias,
{ Solid,
SolidNoAntiAlias, SolidDecal,
Solid, TranslucentDecal,
SolidDecal, Alpha,
TranslucentDecal, Translucent,
Alpha, TranslucentDecal2,
Translucent, TranslucentDecal3
TranslucentDecal2,
TranslucentDecal3
}
} }

View File

@@ -1,14 +1,13 @@
namespace SM64Lib.Geolayout namespace SM64Lib.Geolayout;
public enum EnvironmentEffects
{ {
public enum EnvironmentEffects NoEffect = 0x0,
{ Snow = 0x1,
NoEffect = 0x0, Bllizard = 0x3,
Snow = 0x1, BetaFlower = 0xB,
Bllizard = 0x3, Lava = 0xC,
BetaFlower = 0xB, WaterRelated1 = 0xD,
Lava = 0xC, WaterRelated2 = 0x2
WaterRelated1 = 0xD,
WaterRelated2 = 0x2
}
} }

View File

@@ -1,10 +1,9 @@
namespace SM64Lib.Geolayout namespace SM64Lib.Geolayout;
public enum GeoAsmPointer : uint
{ {
public enum GeoAsmPointer : uint EnvironmentEffect = 0x802761D0,
{ Water = 0x802D104C,
EnvironmentEffect = 0x802761D0, Unknown = 0x802CD1E8
Water = 0x802D104C,
Unknown = 0x802CD1E8
}
} }

View File

@@ -1,380 +1,378 @@
using System.Collections.Generic; using global::SM64Lib.Geolayout.Script;
using global::SM64Lib.Geolayout.Script.Commands;
using global::System.IO; using global::System.IO;
using Microsoft.VisualBasic; using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using global::SM64Lib.Geolayout.Script;
using global::SM64Lib.Geolayout.Script.Commands;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic;
namespace SM64Lib.Geolayout namespace SM64Lib.Geolayout;
public class Geolayout
{ {
public class Geolayout [JsonProperty]
private int IndexForGeopointers = -1;
public Geolayoutscript Geolayoutscript { get; set; } = new Geolayoutscript();
public CameraPresets CameraPreset { get; set; } = CameraPresets.OpenCamera;
public EnvironmentEffects EnvironmentEffect { get; set; } = default;
public List<int> GeopointerOffsets { get; set; } = new List<int>();
public List<Geopointer> Geopointers { get; set; } = new List<Geopointer>();
public int NewGeoOffset { get; set; } = 0;
public bool Closed { get; set; } = false;
public ObjectShadow ObjectShadow { get; set; } = new ObjectShadow();
public CameraFrustrum CameraFrustrum { get; set; } = new CameraFrustrum();
public int Length
{ {
[JsonProperty] get
private int IndexForGeopointers = -1;
public Geolayoutscript Geolayoutscript { get; set; } = new Geolayoutscript();
public CameraPresets CameraPreset { get; set; } = CameraPresets.OpenCamera;
public EnvironmentEffects EnvironmentEffect { get; set; } = default;
public List<int> GeopointerOffsets { get; set; } = new List<int>();
public List<Geopointer> Geopointers { get; set; } = new List<Geopointer>();
public int NewGeoOffset { get; set; } = 0;
public bool Closed { get; set; } = false;
public ObjectShadow ObjectShadow { get; set; } = new ObjectShadow();
public CameraFrustrum CameraFrustrum { get; set; } = new CameraFrustrum();
public int Length
{
get
{
int tLength = Geopointers.Count * 8;
foreach (var c in Geolayoutscript)
tLength += (int)c.Length;
return tLength;
}
}
private void RemoveOldGeopointerCommands()
{
var ToRemove = new List<GeolayoutCommand>();
foreach (GeolayoutCommand c in Geolayoutscript)
{
if (c.CommandType == GeolayoutCommandTypes.LoadDisplaylist)
{
ToRemove.Add(c);
}
}
foreach (GeolayoutCommand cmd in ToRemove)
{
Geolayoutscript.Remove(cmd);
cmd.Close();
}
}
private List<Geopointer> GetGeopointersFromGeolayoutScript(Geolayoutscript script)
{
List<Geopointer> geopointers = new List<Geopointer>();
int geolayoutCommandIndex = 0;
var curMdlScale = System.Numerics.Vector3.One;
var curMdlOffset = System.Numerics.Vector3.Zero;
foreach (GeolayoutCommand geolayoutCommand in script)
{
var referenceCommand = geolayoutCommand;
if (geolayoutCommand.CommandType == GeolayoutCommandTypes.LoadDisplaylist)
{
geopointers.Add(new Geopointer(
cgLoadDisplayList.GetDrawingLayer(ref referenceCommand),
cgLoadDisplayList.GetSegGeopointer(ref referenceCommand),
curMdlScale,
curMdlOffset,
geolayoutCommandIndex
));
}
geolayoutCommandIndex += 1;
}
return geopointers;
}
public Geolayout(NewScriptCreationMode mode)
{
switch (mode)
{
case NewScriptCreationMode.Level:
{
{
var withBlock = Geolayoutscript;
withBlock.Add(new GeolayoutCommand(new byte[] { 0x8, 0x0, 0x0, 0xA, 0x0, 0xA0, 0x0, 0x78, 0x0, 0xA0, 0x0, 0x78 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0xC, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x9, 0x0, 0x0, 0x64 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x19, 0x0, 0x0, 0x0, 0x80, 0x27, 0x63, 0xD4 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0xC, 0x1, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0xA, 0x1, 0x0, 0x2D, 0x0, 0x64, 0x75, 0x30, 0x80, 0x29, 0xAA, 0x3C }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand("0F 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 80 28 7D 30"));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
IndexForGeopointers = 15;
// .Add(New GeolayoutCommand({&H15, &H1, &H0, &H0, &H0, &H0, &H0, &H0}))
withBlock.Add(new GeolayoutCommand(new byte[] { 0x17, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x0, 0x0, 0x80, 0x27, 0x61, 0xD0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x50, 0x0, 0x80, 0x2D, 0x10, 0x4C })); // Water
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x50, 0x1, 0x80, 0x2D, 0x10, 0x4C })); // Toxic Haze
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x50, 0x2, 0x80, 0x2D, 0x10, 0x4C })); // Mist
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0xC, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x0, 0x0, 0x80, 0x2C, 0xD1, 0xE8 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x1, 0x0, 0x0, 0x0 }));
}
break;
}
case NewScriptCreationMode.Object:
{
{
var withBlock1 = Geolayoutscript;
withBlock1.Add(new GeolayoutCommand("20 00 0F A0"));
withBlock1.Add(new GeolayoutCommand("04 00 00 00"));
IndexForGeopointers = 2;
withBlock1.Add(new GeolayoutCommand("05 00 00 00"));
withBlock1.Add(new GeolayoutCommand("01 00 00 00"));
}
break;
}
}
}
public void Read(byte[] data, byte bankID)
{
RenewGeolayout();
Geolayoutscript.Read(data, bankID);
ParseGeolayout();
}
public void Read(RomManager rommgr, int segAddress)
{
RenewGeolayout();
Geolayoutscript.Read(rommgr, segAddress);
ParseGeolayout();
}
private void RenewGeolayout()
{
if (!Closed) Close();
Closed = false;
Geolayoutscript.Clear();
Geopointers.Clear();
GeopointerOffsets.Clear();
Geolayoutscript = new Geolayoutscript();
ObjectShadow = new ObjectShadow();
CameraFrustrum = new CameraFrustrum();
}
public void ParseGeolayout()
{
var ToRemove = new List<GeolayoutCommand>();
int cIndex = 0;
var curMdlScale = System.Numerics.Vector3.One;
var curMdlOffset = System.Numerics.Vector3.Zero;
foreach (GeolayoutCommand fec in Geolayoutscript)
{
var c = fec;
var switchExpr = c.CommandType;
switch (switchExpr)
{
case GeolayoutCommandTypes.CameraPreset:
CameraPreset = (CameraPresets)cgCameraPreset.GetCameraPreset(ref c);
break;
case GeolayoutCommandTypes.x18:
var switchExpr1 = (uint)cgx18.GetAsmPointer(ref c);
switch (switchExpr1)
{
case 0x802761D0:
EnvironmentEffect = (EnvironmentEffects)cgx18.GetParam1(ref c);
break;
}
break;
case GeolayoutCommandTypes.LoadDisplaylist:
if (Geopointers.Count == 0)
IndexForGeopointers = cIndex;
Geopointers.Add(new Geopointer(cgLoadDisplayList.GetDrawingLayer(ref c), cgLoadDisplayList.GetSegGeopointer(ref c), curMdlScale, curMdlOffset, cIndex));
break;
case GeolayoutCommandTypes.ObjectShadown:
cgObjectShadow.GetShadow(c, ObjectShadow);
ObjectShadow.Enabled = true;
break;
case GeolayoutCommandTypes.DrawingDistance:
ObjectShadow.Enabled = false;
break;
case GeolayoutCommandTypes.CameraFrustrum:
cgCameraFrustrum.GetCameraFrustrum(c, CameraFrustrum);
break;
}
cIndex += 1;
}
// Remove Geopointercommands
RemoveOldGeopointerCommands();
}
public void Write(Stream s, int StartOffset)
{
NewGeoOffset = StartOffset;
var commandsToRemove = new List<GeolayoutCommand>();
GeolayoutCommand cmdObjectShadow = null;
GeolayoutCommand cmdDrawingDistance = null;
int tIndexForGeoPointer = IndexForGeopointers;
var isForLevel = false;
// Einstellungen übernehmen
int currentPosition = 0;
foreach (GeolayoutCommand fec in Geolayoutscript)
{
var c = fec;
var switchExpr = c.CommandType;
switch (switchExpr)
{
case GeolayoutCommandTypes.CameraPreset:
cgCameraPreset.SetCameraPreset(ref c, Convert.ToByte(CameraPreset));
break;
case GeolayoutCommandTypes.x18:
var switchExpr1 = cgx18.GetAsmPointer(ref c);
switch ((GeoAsmPointer)switchExpr1)
{
case GeoAsmPointer.EnvironmentEffect:
cgx18.SetParam1(ref c, (ushort)EnvironmentEffect);
break;
}
break;
case GeolayoutCommandTypes.ObjectShadown:
if (ObjectShadow.Enabled)
cmdObjectShadow = c;
else
commandsToRemove.Add(c);
break;
case GeolayoutCommandTypes.DrawingDistance:
if (ObjectShadow.Enabled)
commandsToRemove.Add(c);
else
cmdDrawingDistance = c;
break;
case GeolayoutCommandTypes.CameraFrustrum:
cgCameraFrustrum.SetCameraFrustrum(c, CameraFrustrum);
isForLevel = true;
break;
case GeolayoutCommandTypes.SetScreenRenderArea:
isForLevel = true;
break;
}
currentPosition += (int)c.Length;
}
// Insert Geopointers
foreach (Geopointer g in Geopointers)
{
var tcommand = new GeolayoutCommand(new byte[] { 0x15, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 });
cgLoadDisplayList.SetDrawingLayer(ref tcommand, g.Layer);
cgLoadDisplayList.SetSegGeopointer(ref tcommand, g.SegPointer);
if (g.Index == -1)
{
Geolayoutscript.Insert(tIndexForGeoPointer, tcommand);
}
else
{
Geolayoutscript.Insert(g.Index, tcommand);
}
tIndexForGeoPointer += 1;
}
// Remove all other commands to remove
foreach (var cmd in commandsToRemove)
{
Geolayoutscript.Remove(cmd);
cmd.Close();
}
// Add Geolayout Start command for non-level geolayouts
if (!isForLevel)
{
if (ObjectShadow.Enabled)
{
// Add Object Shadow
if (cmdObjectShadow is null)
{
cmdObjectShadow = new GeolayoutCommand("16 00 00 00 00 00 00 00");
Geolayoutscript.Insert(0, cmdObjectShadow);
}
cgObjectShadow.SetShadow(cmdObjectShadow, ObjectShadow);
}
else
{
if (cmdDrawingDistance == null)
Geolayoutscript.Insert(0, new GeolayoutCommand("20 00 0F A0"));
}
}
// Update Geopointer indexes after adding and removing other commands
Geopointers = GetGeopointersFromGeolayoutScript(Geolayoutscript);
// Write Geolayout to ROM
Geolayoutscript.Write(s, StartOffset);
// Remove Geopointercommands again
RemoveOldGeopointerCommands();
}
public void Close()
{ {
int tLength = Geopointers.Count * 8;
foreach (var c in Geolayoutscript) foreach (var c in Geolayoutscript)
c.Close(); tLength += (int)c.Length;
} return tLength;
public override string ToString()
{
string output = "";
foreach (var cmd in Geolayoutscript)
{
string tbytelist = "";
foreach (byte b in cmd.ToArray())
{
if (tbytelist != string.Empty)
tbytelist += " ";
tbytelist += Conversion.Hex(b);
}
if (output != string.Empty)
output += Environment.NewLine;
output += tbytelist;
}
return output;
}
public string ToString(GeolayoutCommandCollection Geolayoutscript)
{
string output = "";
foreach (var cmd in Geolayoutscript)
{
string tbytelist = "";
foreach (byte b in cmd.ToArray())
{
if (tbytelist != string.Empty)
tbytelist += " ";
tbytelist += Conversion.Hex(b);
}
if (output != string.Empty)
output += Environment.NewLine;
output += tbytelist;
}
return output;
}
public enum NewScriptCreationMode
{
None,
Level,
Object
} }
} }
private void RemoveOldGeopointerCommands()
{
var ToRemove = new List<GeolayoutCommand>();
foreach (GeolayoutCommand c in Geolayoutscript)
{
if (c.CommandType == GeolayoutCommandTypes.LoadDisplaylist)
{
ToRemove.Add(c);
}
}
foreach (GeolayoutCommand cmd in ToRemove)
{
Geolayoutscript.Remove(cmd);
cmd.Close();
}
}
private List<Geopointer> GetGeopointersFromGeolayoutScript(Geolayoutscript script)
{
List<Geopointer> geopointers = new List<Geopointer>();
int geolayoutCommandIndex = 0;
var curMdlScale = System.Numerics.Vector3.One;
var curMdlOffset = System.Numerics.Vector3.Zero;
foreach (GeolayoutCommand geolayoutCommand in script)
{
var referenceCommand = geolayoutCommand;
if (geolayoutCommand.CommandType == GeolayoutCommandTypes.LoadDisplaylist)
{
geopointers.Add(new Geopointer(
cgLoadDisplayList.GetDrawingLayer(ref referenceCommand),
cgLoadDisplayList.GetSegGeopointer(ref referenceCommand),
curMdlScale,
curMdlOffset,
geolayoutCommandIndex
));
}
geolayoutCommandIndex += 1;
}
return geopointers;
}
public Geolayout(NewScriptCreationMode mode)
{
switch (mode)
{
case NewScriptCreationMode.Level:
{
{
var withBlock = Geolayoutscript;
withBlock.Add(new GeolayoutCommand(new byte[] { 0x8, 0x0, 0x0, 0xA, 0x0, 0xA0, 0x0, 0x78, 0x0, 0xA0, 0x0, 0x78 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0xC, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x9, 0x0, 0x0, 0x64 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x19, 0x0, 0x0, 0x0, 0x80, 0x27, 0x63, 0xD4 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0xC, 0x1, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0xA, 0x1, 0x0, 0x2D, 0x0, 0x64, 0x75, 0x30, 0x80, 0x29, 0xAA, 0x3C }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand("0F 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 80 28 7D 30"));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
IndexForGeopointers = 15;
// .Add(New GeolayoutCommand({&H15, &H1, &H0, &H0, &H0, &H0, &H0, &H0}))
withBlock.Add(new GeolayoutCommand(new byte[] { 0x17, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x0, 0x0, 0x80, 0x27, 0x61, 0xD0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x50, 0x0, 0x80, 0x2D, 0x10, 0x4C })); // Water
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x50, 0x1, 0x80, 0x2D, 0x10, 0x4C })); // Toxic Haze
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x50, 0x2, 0x80, 0x2D, 0x10, 0x4C })); // Mist
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0xC, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x4, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x18, 0x0, 0x0, 0x0, 0x80, 0x2C, 0xD1, 0xE8 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x5, 0x0, 0x0, 0x0 }));
withBlock.Add(new GeolayoutCommand(new byte[] { 0x1, 0x0, 0x0, 0x0 }));
}
break;
}
case NewScriptCreationMode.Object:
{
{
var withBlock1 = Geolayoutscript;
withBlock1.Add(new GeolayoutCommand("20 00 0F A0"));
withBlock1.Add(new GeolayoutCommand("04 00 00 00"));
IndexForGeopointers = 2;
withBlock1.Add(new GeolayoutCommand("05 00 00 00"));
withBlock1.Add(new GeolayoutCommand("01 00 00 00"));
}
break;
}
}
}
public void Read(byte[] data, byte bankID)
{
RenewGeolayout();
Geolayoutscript.Read(data, bankID);
ParseGeolayout();
}
public void Read(RomManager rommgr, int segAddress)
{
RenewGeolayout();
Geolayoutscript.Read(rommgr, segAddress);
ParseGeolayout();
}
private void RenewGeolayout()
{
if (!Closed) Close();
Closed = false;
Geolayoutscript.Clear();
Geopointers.Clear();
GeopointerOffsets.Clear();
Geolayoutscript = new Geolayoutscript();
ObjectShadow = new ObjectShadow();
CameraFrustrum = new CameraFrustrum();
}
public void ParseGeolayout()
{
var ToRemove = new List<GeolayoutCommand>();
int cIndex = 0;
var curMdlScale = System.Numerics.Vector3.One;
var curMdlOffset = System.Numerics.Vector3.Zero;
foreach (GeolayoutCommand fec in Geolayoutscript)
{
var c = fec;
var switchExpr = c.CommandType;
switch (switchExpr)
{
case GeolayoutCommandTypes.CameraPreset:
CameraPreset = (CameraPresets)cgCameraPreset.GetCameraPreset(ref c);
break;
case GeolayoutCommandTypes.x18:
var switchExpr1 = (uint)cgx18.GetAsmPointer(ref c);
switch (switchExpr1)
{
case 0x802761D0:
EnvironmentEffect = (EnvironmentEffects)cgx18.GetParam1(ref c);
break;
}
break;
case GeolayoutCommandTypes.LoadDisplaylist:
if (Geopointers.Count == 0)
IndexForGeopointers = cIndex;
Geopointers.Add(new Geopointer(cgLoadDisplayList.GetDrawingLayer(ref c), cgLoadDisplayList.GetSegGeopointer(ref c), curMdlScale, curMdlOffset, cIndex));
break;
case GeolayoutCommandTypes.ObjectShadown:
cgObjectShadow.GetShadow(c, ObjectShadow);
ObjectShadow.Enabled = true;
break;
case GeolayoutCommandTypes.DrawingDistance:
ObjectShadow.Enabled = false;
break;
case GeolayoutCommandTypes.CameraFrustrum:
cgCameraFrustrum.GetCameraFrustrum(c, CameraFrustrum);
break;
}
cIndex += 1;
}
// Remove Geopointercommands
RemoveOldGeopointerCommands();
}
public void Write(Stream s, int StartOffset)
{
NewGeoOffset = StartOffset;
var commandsToRemove = new List<GeolayoutCommand>();
GeolayoutCommand cmdObjectShadow = null;
GeolayoutCommand cmdDrawingDistance = null;
int tIndexForGeoPointer = IndexForGeopointers;
var isForLevel = false;
// Einstellungen übernehmen
int currentPosition = 0;
foreach (GeolayoutCommand fec in Geolayoutscript)
{
var c = fec;
var switchExpr = c.CommandType;
switch (switchExpr)
{
case GeolayoutCommandTypes.CameraPreset:
cgCameraPreset.SetCameraPreset(ref c, Convert.ToByte(CameraPreset));
break;
case GeolayoutCommandTypes.x18:
var switchExpr1 = cgx18.GetAsmPointer(ref c);
switch ((GeoAsmPointer)switchExpr1)
{
case GeoAsmPointer.EnvironmentEffect:
cgx18.SetParam1(ref c, (ushort)EnvironmentEffect);
break;
}
break;
case GeolayoutCommandTypes.ObjectShadown:
if (ObjectShadow.Enabled)
cmdObjectShadow = c;
else
commandsToRemove.Add(c);
break;
case GeolayoutCommandTypes.DrawingDistance:
if (ObjectShadow.Enabled)
commandsToRemove.Add(c);
else
cmdDrawingDistance = c;
break;
case GeolayoutCommandTypes.CameraFrustrum:
cgCameraFrustrum.SetCameraFrustrum(c, CameraFrustrum);
isForLevel = true;
break;
case GeolayoutCommandTypes.SetScreenRenderArea:
isForLevel = true;
break;
}
currentPosition += (int)c.Length;
}
// Insert Geopointers
foreach (Geopointer g in Geopointers)
{
var tcommand = new GeolayoutCommand(new byte[] { 0x15, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 });
cgLoadDisplayList.SetDrawingLayer(ref tcommand, g.Layer);
cgLoadDisplayList.SetSegGeopointer(ref tcommand, g.SegPointer);
if (g.Index == -1)
{
Geolayoutscript.Insert(tIndexForGeoPointer, tcommand);
}
else
{
Geolayoutscript.Insert(g.Index, tcommand);
}
tIndexForGeoPointer += 1;
}
// Remove all other commands to remove
foreach (var cmd in commandsToRemove)
{
Geolayoutscript.Remove(cmd);
cmd.Close();
}
// Add Geolayout Start command for non-level geolayouts
if (!isForLevel)
{
if (ObjectShadow.Enabled)
{
// Add Object Shadow
if (cmdObjectShadow is null)
{
cmdObjectShadow = new GeolayoutCommand("16 00 00 00 00 00 00 00");
Geolayoutscript.Insert(0, cmdObjectShadow);
}
cgObjectShadow.SetShadow(cmdObjectShadow, ObjectShadow);
}
else
{
if (cmdDrawingDistance == null)
Geolayoutscript.Insert(0, new GeolayoutCommand("20 00 0F A0"));
}
}
// Update Geopointer indexes after adding and removing other commands
Geopointers = GetGeopointersFromGeolayoutScript(Geolayoutscript);
// Write Geolayout to ROM
Geolayoutscript.Write(s, StartOffset);
// Remove Geopointercommands again
RemoveOldGeopointerCommands();
}
public void Close()
{
foreach (var c in Geolayoutscript)
c.Close();
}
public override string ToString()
{
string output = "";
foreach (var cmd in Geolayoutscript)
{
string tbytelist = "";
foreach (byte b in cmd.ToArray())
{
if (tbytelist != string.Empty)
tbytelist += " ";
tbytelist += Conversion.Hex(b);
}
if (output != string.Empty)
output += Environment.NewLine;
output += tbytelist;
}
return output;
}
public string ToString(GeolayoutCommandCollection Geolayoutscript)
{
string output = "";
foreach (var cmd in Geolayoutscript)
{
string tbytelist = "";
foreach (byte b in cmd.ToArray())
{
if (tbytelist != string.Empty)
tbytelist += " ";
tbytelist += Conversion.Hex(b);
}
if (output != string.Empty)
output += Environment.NewLine;
output += tbytelist;
}
return output;
}
public enum NewScriptCreationMode
{
None,
Level,
Object
}
} }

View File

@@ -1,42 +1,41 @@
using Newtonsoft.Json; using Newtonsoft.Json;
namespace SM64Lib.Geolayout namespace SM64Lib.Geolayout;
public class Geopointer
{ {
public class Geopointer public byte Layer { get; set; } = default;
public int SegPointer { get; set; } = 0;
public int Index { get; set; } = -1;
public System.Numerics.Vector3 ModelScale { get; set; } = System.Numerics.Vector3.One;
public System.Numerics.Vector3 ModelOffset { get; set; } = System.Numerics.Vector3.Zero;
[JsonConstructor]
private Geopointer()
{ {
public byte Layer { get; set; } = default; }
public int SegPointer { get; set; } = 0;
public int Index { get; set; } = -1;
public System.Numerics.Vector3 ModelScale { get; set; } = System.Numerics.Vector3.One;
public System.Numerics.Vector3 ModelOffset { get; set; } = System.Numerics.Vector3.Zero;
[JsonConstructor] public Geopointer(byte Layer) : this()
private Geopointer() {
{ this.Layer = Layer;
} }
public Geopointer(byte Layer) : this() public Geopointer(byte Layer, int SegPointer) : this(Layer)
{ {
this.Layer = Layer; this.SegPointer = SegPointer;
} }
public Geopointer(byte Layer, int SegPointer) : this(Layer) public Geopointer(byte Layer, int SegPointer, System.Numerics.Vector3 mdlscale, System.Numerics.Vector3 mdloffset) : this(Layer, SegPointer)
{ {
this.SegPointer = SegPointer; ModelScale = mdlscale;
} ModelOffset = mdloffset;
}
public Geopointer(byte Layer, int SegPointer, System.Numerics.Vector3 mdlscale, System.Numerics.Vector3 mdloffset) : this(Layer, SegPointer) public Geopointer(byte Layer, int SegPointer, System.Numerics.Vector3 mdlscale, System.Numerics.Vector3 mdloffset, int index) : this(Layer, SegPointer)
{ {
ModelScale = mdlscale; ModelScale = mdlscale;
ModelOffset = mdloffset; ModelOffset = mdloffset;
} Index = index;
public Geopointer(byte Layer, int SegPointer, System.Numerics.Vector3 mdlscale, System.Numerics.Vector3 mdloffset, int index) : this(Layer, SegPointer)
{
ModelScale = mdlscale;
ModelOffset = mdloffset;
Index = index;
}
} }
} }

View File

@@ -1,16 +1,9 @@
using System; namespace SM64Lib.Geolayout;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Geolayout public class ObjectShadow
{ {
public class ObjectShadow public bool Enabled { get; set; } = false;
{ public ObjectShadowType Type { get; set; } = ObjectShadowType.Circle_9Verts;
public bool Enabled { get; set; } = false; public short Scale { get; set; }
public ObjectShadowType Type { get; set; } = ObjectShadowType.Circle_9Verts; public byte Solidity { get; set; } = 0xFF;
public short Scale { get; set; }
public byte Solidity { get; set; } = 0xFF;
}
} }

View File

@@ -1,24 +1,17 @@
using System; namespace SM64Lib.Geolayout;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Geolayout public enum ObjectShadowType
{ {
public enum ObjectShadowType Circle_9Verts = 0,
{ Circle_4Verts = 1,
Circle_9Verts = 0, Circle_4Verts_Flat_Unused = 2,
Circle_4Verts = 1, SquarePermanent = 10,
Circle_4Verts_Flat_Unused = 2, SquareScaleable = 11,
SquarePermanent = 10, SquareTooglable = 12,
SquareScaleable = 11, /**
SquareTooglable = 12, * This defines an offset after which rectangular shadows with custom
/** * widths and heights can be defined.
* This defines an offset after which rectangular shadows with custom */
* widths and heights can be defined. RectangleHardcodedOffset = 50,
*/ CirclePlayer = 99
RectangleHardcodedOffset = 50,
CirclePlayer = 99
}
} }

View File

@@ -2,39 +2,38 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Json; using SM64Lib.Json;
namespace SM64Lib.Geolayout.Script namespace SM64Lib.Geolayout.Script;
[JsonConverter(typeof(GeolayoutscriptCommandJsonConverter))]
public class GeolayoutCommand : BaseCommand<GeolayoutCommandTypes>
{ {
[JsonConverter(typeof(GeolayoutscriptCommandJsonConverter))] public GeolayoutCommand(byte[] bytes) : base(bytes)
public class GeolayoutCommand : BaseCommand<GeolayoutCommandTypes>
{ {
public GeolayoutCommand(byte[] bytes) : base(bytes) }
public GeolayoutCommand() : base()
{
}
public GeolayoutCommand(string bytes, bool enabledHex = true) : base(bytes, enabledHex)
{
}
public override GeolayoutCommandTypes CommandType
{
get
{ {
Position = 0;
GeolayoutCommandTypes t = (GeolayoutCommandTypes)ReadByte();
Position = 0;
return t;
} }
public GeolayoutCommand() : base() set
{ {
} Position = 0;
WriteByte((byte)value);
public GeolayoutCommand(string bytes, bool enabledHex = true) : base(bytes, enabledHex) Position = 0;
{
}
public override GeolayoutCommandTypes CommandType
{
get
{
Position = 0;
GeolayoutCommandTypes t = (GeolayoutCommandTypes)ReadByte();
Position = 0;
return t;
}
set
{
Position = 0;
WriteByte((byte)value);
Position = 0;
}
} }
} }
} }

View File

@@ -1,18 +1,17 @@
using global::SM64Lib.Script; using global::SM64Lib.Script;
namespace SM64Lib.Geolayout.Script namespace SM64Lib.Geolayout.Script;
{
public class GeolayoutCommandCollection : BaseCommandCollection<GeolayoutCommand, GeolayoutCommandTypes>
{
public int IndexOfFirst(GeolayoutCommandTypes cmdType)
{
for (int index = 0, loopTo = Count - 1; index <= loopTo; index++)
{
if (this[index].CommandType == cmdType)
return index;
}
return -1; public class GeolayoutCommandCollection : BaseCommandCollection<GeolayoutCommand, GeolayoutCommandTypes>
{
public int IndexOfFirst(GeolayoutCommandTypes cmdType)
{
for (int index = 0, loopTo = Count - 1; index <= loopTo; index++)
{
if (this[index].CommandType == cmdType)
return index;
} }
return -1;
} }
} }

View File

@@ -1,5 +1,4 @@
using global::System.Numerics; using global::System.Numerics;
using Microsoft.VisualBasic.CompilerServices;
using System; using System;
namespace SM64Lib.Geolayout.Script namespace SM64Lib.Geolayout.Script

View File

@@ -1,37 +1,36 @@
namespace SM64Lib.Geolayout.Script namespace SM64Lib.Geolayout.Script;
public enum GeolayoutCommandTypes
{ {
public enum GeolayoutCommandTypes BranchAndStore = 0x0,
{ EndOfGeolayout = 0x1,
BranchAndStore = 0x0, JumpToSegAddr = 0x2,
EndOfGeolayout = 0x1, JumpBack = 0x3,
JumpToSegAddr = 0x2, StartOfNode = 0x4,
JumpBack = 0x3, EndOfNode = 0x5,
StartOfNode = 0x4, SetScreenRenderArea = 0x8,
EndOfNode = 0x5, Scale1 = 0x9,
SetScreenRenderArea = 0x8, CameraFrustrum = 0xA,
Scale1 = 0x9, x0B = 0xB,
CameraFrustrum = 0xA, x0C = 0xC,
x0B = 0xB, x0D = 0xD,
x0C = 0xC, x0E = 0xE,
x0D = 0xD, CameraPreset = 0xF,
x0E = 0xE, x10 = 0x10,
CameraPreset = 0xF, x11 = 0x11,
x10 = 0x10, x12 = 0x12,
x11 = 0x11, LoadDisplaylistWithOffset = 0x13,
x12 = 0x12, BillboardModel = 0x14,
LoadDisplaylistWithOffset = 0x13, LoadDisplaylist = 0x15,
BillboardModel = 0x14, ObjectShadown = 0x16,
LoadDisplaylist = 0x15, x17 = 0x17,
ObjectShadown = 0x16, x18 = 0x18,
x17 = 0x17, Background = 0x19,
x18 = 0x18, x1A = 0x1A,
Background = 0x19, x1C = 0x1C,
x1A = 0x1A, Scale2 = 0x1D,
x1C = 0x1C, x1E = 0xE,
Scale2 = 0x1D, x1f = 0xF,
x1E = 0xE, DrawingDistance = 0x20
x1f = 0xF,
DrawingDistance = 0x20
}
} }

View File

@@ -1,239 +1,237 @@
using System.Collections.Generic; using global::SM64Lib.Data;
using global::System.IO; using global::System.IO;
using System.Threading.Tasks;
using Microsoft.VisualBasic.CompilerServices;
using global::SM64Lib.Data;
using SM64Lib.SegmentedBanking; using SM64Lib.SegmentedBanking;
using System; using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SM64Lib.Geolayout.Script namespace SM64Lib.Geolayout.Script;
public class Geolayoutscript : GeolayoutCommandCollection
{ {
public class Geolayoutscript : GeolayoutCommandCollection public List<int> GeopointerOffsets = new List<int>();
public Geolayoutscript()
{ {
public List<int> GeopointerOffsets = new List<int>(); }
public Geolayoutscript() public Task ReadAsync(RomManager rommgr, int segAddress)
{ {
} var t = new Task(() => Read(rommgr, segAddress));
t.Start();
return t;
}
public Task ReadAsync(RomManager rommgr, int segAddress) public void Read(byte[] data, byte bankID)
{ {
var t = new Task(() => Read(rommgr, segAddress)); var ms = new MemoryStream(data);
t.Start(); var segBank = new SegmentedBank(bankID, ms);
return t; Read(segBank, 0);
} }
public void Read(byte[] data, byte bankID) public void Read(RomManager rommgr, int segAddress)
{ {
var ms = new MemoryStream(data); var segBank = rommgr.GetSegBank(Convert.ToByte(segAddress >> 24));
var segBank = new SegmentedBank(bankID, ms); segBank.ReadDataIfNull(rommgr.RomFile);
Read(segBank, 0); Read(segBank, segAddress & 0x00ffffff);
} }
public void Read(RomManager rommgr, int segAddress) public void Read(SegmentedBank segBank, int offset)
{
Close();
Clear();
GeopointerOffsets.Clear();
if (segBank is null)
return;
var data = new BinaryStreamData(segBank.Data);
data.Position = offset;
var tb = new List<byte>();
GeolayoutCommandTypes cb = default;
int subNodeIndex = 0;
bool ende = false;
while (!ende)
{ {
var segBank = rommgr.GetSegBank(Convert.ToByte(segAddress >> 24)); if (data.Position >= data.Length)
segBank.ReadDataIfNull(rommgr.RomFile); break;
Read(segBank, segAddress & 0x00ffffff); cb = (GeolayoutCommandTypes)data.ReadByte();
} byte lenth = 0;
switch (cb)
public void Read(SegmentedBank segBank, int offset)
{
Close();
Clear();
GeopointerOffsets.Clear();
if (segBank is null)
return;
var data = new BinaryStreamData(segBank.Data);
data.Position = offset;
var tb = new List<byte>();
GeolayoutCommandTypes cb = default;
int subNodeIndex = 0;
bool ende = false;
while (!ende)
{ {
if (data.Position >= data.Length) case GeolayoutCommandTypes.Background:
lenth = 0x8;
break; break;
cb = (GeolayoutCommandTypes)data.ReadByte(); case GeolayoutCommandTypes.CameraPreset:
byte lenth = 0; lenth = 0x14;
switch (cb)
{
case GeolayoutCommandTypes.Background:
lenth = 0x8;
break;
case GeolayoutCommandTypes.CameraPreset:
lenth = 0x14;
break;
case GeolayoutCommandTypes.DrawingDistance:
lenth = 0x4;
break;
case GeolayoutCommandTypes.EndOfGeolayout:
lenth = 0x4;
break;
case GeolayoutCommandTypes.EndOfNode:
lenth = 0x4;
break;
case GeolayoutCommandTypes.JumpBack:
lenth = 0x4;
break;
case GeolayoutCommandTypes.JumpToSegAddr:
lenth = 0x8;
break;
case GeolayoutCommandTypes.LoadDisplaylist:
lenth = 0x8;
break;
case GeolayoutCommandTypes.LoadDisplaylistWithOffset:
lenth = 0xC;
break;
case GeolayoutCommandTypes.ObjectShadown:
lenth = 0x8;
break;
case GeolayoutCommandTypes.Scale1:
lenth = 0x4;
break;
case GeolayoutCommandTypes.Scale2:
lenth = 0x8;
break;
case GeolayoutCommandTypes.StartOfNode:
lenth = 0x4;
break;
case GeolayoutCommandTypes.SetScreenRenderArea:
lenth = 0xC;
break;
case GeolayoutCommandTypes.BillboardModel:
lenth = 0x8;
break;
case GeolayoutCommandTypes.BranchAndStore:
lenth = 0x8;
break;
case GeolayoutCommandTypes.CameraFrustrum:
{
var switchExpr = data.ReadByte();
switch (switchExpr)
{
case 0x1:
lenth = 0xC;
break;
default:
lenth = 0x8;
break;
}
segBank.Data.Position -= 1;
break;
}
case GeolayoutCommandTypes.x0B:
lenth = 0x4;
break;
case GeolayoutCommandTypes.x0C:
lenth = 0x4;
break;
case GeolayoutCommandTypes.x0D:
lenth = 0x8;
break;
case GeolayoutCommandTypes.x0E:
lenth = 0x8;
break;
case GeolayoutCommandTypes.x10:
lenth = 0x10;
break;
case GeolayoutCommandTypes.x11:
lenth = 0x8;
break;
case GeolayoutCommandTypes.x12:
{
var switchExpr = data.ReadByte() >> 4;
switch (switchExpr)
{
case 0x8:
lenth = 0xC;
break;
default:
lenth = 0x8;
break;
}
segBank.Data.Position -= 1;
break;
}
case GeolayoutCommandTypes.x17:
lenth = 0x4;
break;
case GeolayoutCommandTypes.x18:
lenth = 0x8;
break;
case GeolayoutCommandTypes.x1A:
lenth = 0x8;
break;
case GeolayoutCommandTypes.x1C:
lenth = 0xC;
break;
case var @case when @case == GeolayoutCommandTypes.x1E:
lenth = 0x8;
break;
case var case1 when case1 == GeolayoutCommandTypes.x1f:
lenth = 0x10;
break;
default:
break;
}
segBank.Data.Position -= 1;
if (lenth == 0 || segBank.Data.Position + lenth > segBank.Data.Length)
break; break;
case GeolayoutCommandTypes.DrawingDistance:
lenth = 0x4;
break;
case GeolayoutCommandTypes.EndOfGeolayout:
lenth = 0x4;
break;
case GeolayoutCommandTypes.EndOfNode:
lenth = 0x4;
break;
case GeolayoutCommandTypes.JumpBack:
lenth = 0x4;
break;
case GeolayoutCommandTypes.JumpToSegAddr:
lenth = 0x8;
break;
case GeolayoutCommandTypes.LoadDisplaylist:
lenth = 0x8;
break;
case GeolayoutCommandTypes.LoadDisplaylistWithOffset:
lenth = 0xC;
break;
case GeolayoutCommandTypes.ObjectShadown:
lenth = 0x8;
break;
case GeolayoutCommandTypes.Scale1:
lenth = 0x4;
break;
case GeolayoutCommandTypes.Scale2:
lenth = 0x8;
break;
case GeolayoutCommandTypes.StartOfNode:
lenth = 0x4;
break;
case GeolayoutCommandTypes.SetScreenRenderArea:
lenth = 0xC;
break;
case GeolayoutCommandTypes.BillboardModel:
lenth = 0x8;
break;
case GeolayoutCommandTypes.BranchAndStore:
lenth = 0x8;
break;
case GeolayoutCommandTypes.CameraFrustrum:
{
var switchExpr = data.ReadByte();
switch (switchExpr)
{
case 0x1:
lenth = 0xC;
break;
default:
lenth = 0x8;
break;
}
for (int i = 1, loopTo = lenth; i <= loopTo; i++) segBank.Data.Position -= 1;
tb.Add(data.ReadByte()); break;
}
case GeolayoutCommandTypes.x0B:
lenth = 0x4;
break;
case GeolayoutCommandTypes.x0C:
lenth = 0x4;
break;
case GeolayoutCommandTypes.x0D:
lenth = 0x8;
break;
case GeolayoutCommandTypes.x0E:
lenth = 0x8;
break;
case GeolayoutCommandTypes.x10:
lenth = 0x10;
break;
case GeolayoutCommandTypes.x11:
lenth = 0x8;
break;
case GeolayoutCommandTypes.x12:
{
var switchExpr = data.ReadByte() >> 4;
switch (switchExpr)
{
case 0x8:
lenth = 0xC;
break;
default:
lenth = 0x8;
break;
}
var tCommand = new GeolayoutCommand(tb.ToArray()); segBank.Data.Position -= 1;
int bankOffset = (int)(segBank.Data.Position - lenth);
tCommand.RomAddress = segBank.RomStart + bankOffset;
tCommand.BankAddress = segBank.BankAddress + bankOffset;
Add(tCommand);
tb.Clear();
var switchExpr1 = tCommand.CommandType;
switch (switchExpr1)
{
case GeolayoutCommandTypes.EndOfGeolayout:
ende = true;
break; break;
case GeolayoutCommandTypes.EndOfNode: }
subNodeIndex -= 1; case GeolayoutCommandTypes.x17:
break; lenth = 0x4;
case GeolayoutCommandTypes.StartOfNode: break;
subNodeIndex += 1; case GeolayoutCommandTypes.x18:
break; lenth = 0x8;
} break;
case GeolayoutCommandTypes.x1A:
lenth = 0x8;
break;
case GeolayoutCommandTypes.x1C:
lenth = 0xC;
break;
case var @case when @case == GeolayoutCommandTypes.x1E:
lenth = 0x8;
break;
case var case1 when case1 == GeolayoutCommandTypes.x1f:
lenth = 0x10;
break;
default:
break;
} }
}
public void Write(Stream s, int GeolayoutStart) segBank.Data.Position -= 1;
{ if (lenth == 0 || segBank.Data.Position + lenth > segBank.Data.Length)
var bw = new BinaryWriter(s); break;
// Write new Levelscript for (int i = 1, loopTo = lenth; i <= loopTo; i++)
s.Position = GeolayoutStart; tb.Add(data.ReadByte());
foreach (GeolayoutCommand c in this)
var tCommand = new GeolayoutCommand(tb.ToArray());
int bankOffset = (int)(segBank.Data.Position - lenth);
tCommand.RomAddress = segBank.RomStart + bankOffset;
tCommand.BankAddress = segBank.BankAddress + bankOffset;
Add(tCommand);
tb.Clear();
var switchExpr1 = tCommand.CommandType;
switch (switchExpr1)
{ {
if (c.CommandType == GeolayoutCommandTypes.LoadDisplaylist) case GeolayoutCommandTypes.EndOfGeolayout:
GeopointerOffsets.Add((int)(s.Position + 0x4)); ende = true;
foreach (byte b in c.ToArray()) break;
bw.Write(b); case GeolayoutCommandTypes.EndOfNode:
subNodeIndex -= 1;
break;
case GeolayoutCommandTypes.StartOfNode:
subNodeIndex += 1;
break;
} }
} }
}
public GeolayoutCommand GetFirst(GeolayoutCommandTypes cmdType)
{ public void Write(Stream s, int GeolayoutStart)
foreach (GeolayoutCommand cmd in this) {
{ var bw = new BinaryWriter(s);
if (cmd.CommandType == cmdType)
{ // Write new Levelscript
return cmd; s.Position = GeolayoutStart;
} foreach (GeolayoutCommand c in this)
} {
if (c.CommandType == GeolayoutCommandTypes.LoadDisplaylist)
return null; GeopointerOffsets.Add((int)(s.Position + 0x4));
} foreach (byte b in c.ToArray())
bw.Write(b);
}
}
public GeolayoutCommand GetFirst(GeolayoutCommandTypes cmdType)
{
foreach (GeolayoutCommand cmd in this)
{
if (cmd.CommandType == cmdType)
{
return cmd;
}
}
return null;
} }
} }

View File

@@ -1,14 +1,13 @@
namespace SM64Lib.Geolayout namespace SM64Lib.Geolayout;
public enum TerrainTypes
{ {
public enum TerrainTypes NoramlA = 0x0,
{ NoramlB,
NoramlA = 0x0, SnowTerrain,
NoramlB, SandTerrain,
SnowTerrain, BigBoosHount,
SandTerrain, WaterLevels,
BigBoosHount, SlipperySlide
WaterLevels,
SlipperySlide
}
} }

View File

@@ -1,87 +1,83 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
namespace SM64Lib.Json namespace SM64Lib.Json;
public class ArrayReferencePreservngConverter : JsonConverter
{ {
public class ArrayReferencePreservngConverter : JsonConverter const string refProperty = "$ref";
const string idProperty = "$id";
const string valuesProperty = "$values";
public override bool CanConvert(Type objectType)
{ {
const string refProperty = "$ref"; return objectType.IsArray;
const string idProperty = "$id"; }
const string valuesProperty = "$values";
public override bool CanConvert(Type objectType) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
else if (reader.TokenType == JsonToken.StartArray)
{ {
return objectType.IsArray; // No $ref. Deserialize as a List<T> to avoid infinite recursion and return as an array.
} var elementType = objectType.GetElementType();
var listType = typeof(List<>).MakeGenericType(elementType);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) var list = (IList)serializer.Deserialize(reader, listType);
{ if (list == null)
if (reader.TokenType == JsonToken.Null)
return null; return null;
else if (reader.TokenType == JsonToken.StartArray) var array = Array.CreateInstance(elementType, list.Count);
{ list.CopyTo(array, 0);
// No $ref. Deserialize as a List<T> to avoid infinite recursion and return as an array. return array;
var elementType = objectType.GetElementType();
var listType = typeof(List<>).MakeGenericType(elementType);
var list = (IList)serializer.Deserialize(reader, listType);
if (list == null)
return null;
var array = Array.CreateInstance(elementType, list.Count);
list.CopyTo(array, 0);
return array;
}
else
{
var obj = JObject.Load(reader);
var refId = (string)obj[refProperty];
if (refId != null)
{
var reference = serializer.ReferenceResolver.ResolveReference(serializer, refId);
if (reference != null)
return reference;
}
var values = obj[valuesProperty];
if (values == null || values.Type == JTokenType.Null)
return null;
if (!(values is JArray))
{
throw new JsonSerializationException(string.Format("{0} was not an array", values));
}
var count = ((JArray)values).Count;
var elementType = objectType.GetElementType();
var array = Array.CreateInstance(elementType, count);
var objId = (string)obj[idProperty];
if (objId != null)
{
// Add the empty array into the reference table BEFORE poppulating it,
// to handle recursive references.
serializer.ReferenceResolver.AddReference(serializer, objId, array);
}
var listType = typeof(List<>).MakeGenericType(elementType);
using (var subReader = values.CreateReader())
{
var list = (IList)serializer.Deserialize(subReader, listType);
list.CopyTo(array, 0);
}
return array;
}
} }
else
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
throw new NotImplementedException(); var obj = JObject.Load(reader);
var refId = (string)obj[refProperty];
if (refId != null)
{
var reference = serializer.ReferenceResolver.ResolveReference(serializer, refId);
if (reference != null)
return reference;
}
var values = obj[valuesProperty];
if (values == null || values.Type == JTokenType.Null)
return null;
if (!(values is JArray))
{
throw new JsonSerializationException(string.Format("{0} was not an array", values));
}
var count = ((JArray)values).Count;
var elementType = objectType.GetElementType();
var array = Array.CreateInstance(elementType, count);
var objId = (string)obj[idProperty];
if (objId != null)
{
// Add the empty array into the reference table BEFORE poppulating it,
// to handle recursive references.
serializer.ReferenceResolver.AddReference(serializer, objId, array);
}
var listType = typeof(List<>).MakeGenericType(elementType);
using (var subReader = values.CreateReader())
{
var list = (IList)serializer.Deserialize(subReader, listType);
list.CopyTo(array, 0);
}
return array;
} }
} }
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
} }

View File

@@ -1,61 +1,54 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Behaviors.Script;
using SM64Lib.Geolayout.Script; using SM64Lib.Geolayout.Script;
using SM64Lib.Model.Fast3D;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Json namespace SM64Lib.Json;
internal class BaseCommandJsonConverter : JsonConverter
{ {
internal class BaseCommandJsonConverter : JsonConverter public override bool CanConvert(Type objectType)
{ {
public override bool CanConvert(Type objectType) return typeof(GeolayoutscriptCommandJsonConverter).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var export = serializer.Deserialize<CmdExport>(reader);
GeolayoutCommand c;
if (existingValue is not null)
c = (GeolayoutCommand)existingValue;
else
c = new GeolayoutCommand();
if (export?.Buffer is not null)
{ {
return typeof(GeolayoutscriptCommandJsonConverter).IsAssignableFrom(objectType); c.Position = 0;
c.Write(export.Buffer, 0, export.Buffer.Length);
c.Position = 0;
} }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) c.BankAddress = export.BankAddress;
return c;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var cmd = (GeolayoutCommand)value;
var export = new CmdExport
{ {
var export = serializer.Deserialize<CmdExport>(reader); Buffer = cmd.ToArray(),
GeolayoutCommand c; BankAddress = cmd.BankAddress
};
if (existingValue is not null) serializer.Serialize(writer, export);
c = (GeolayoutCommand)existingValue; }
else
c = new GeolayoutCommand();
if (export?.Buffer is not null) private class CmdExport
{ {
c.Position = 0; public byte[] Buffer { get; set; }
c.Write(export.Buffer, 0, export.Buffer.Length); public int BankAddress { get; set; }
c.Position = 0;
}
c.BankAddress = export.BankAddress;
return c;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var cmd = (GeolayoutCommand)value;
var export = new CmdExport
{
Buffer = cmd.ToArray(),
BankAddress = cmd.BankAddress
};
serializer.Serialize(writer, export);
}
private class CmdExport
{
public byte[] Buffer { get; set; }
public int BankAddress { get; set; }
}
} }
} }

View File

@@ -1,60 +1,54 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Behaviors.Script; using SM64Lib.Behaviors.Script;
using SM64Lib.Model.Fast3D;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Json namespace SM64Lib.Json;
internal class BehaviorscriptCommandJsonConverter : JsonConverter
{ {
internal class BehaviorscriptCommandJsonConverter : JsonConverter public override bool CanConvert(Type objectType)
{ {
public override bool CanConvert(Type objectType) return typeof(BehaviorscriptCommand).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var export = serializer.Deserialize<CmdExport>(reader);
BehaviorscriptCommand c;
if (existingValue is not null)
c = (BehaviorscriptCommand)existingValue;
else
c = new BehaviorscriptCommand();
if (export?.Buffer is not null)
{ {
return typeof(BehaviorscriptCommand).IsAssignableFrom(objectType); c.Position = 0;
c.Write(export.Buffer, 0, export.Buffer.Length);
c.Position = 0;
} }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) c.BankAddress = export.BankAddress;
return c;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var cmd = (BehaviorscriptCommand)value;
var export = new CmdExport
{ {
var export = serializer.Deserialize<CmdExport>(reader); Buffer = cmd.ToArray(),
BehaviorscriptCommand c; BankAddress = cmd.BankAddress
};
if (existingValue is not null) serializer.Serialize(writer, export);
c = (BehaviorscriptCommand)existingValue; }
else
c = new BehaviorscriptCommand();
if (export?.Buffer is not null) private class CmdExport
{ {
c.Position = 0; public byte[] Buffer { get; set; }
c.Write(export.Buffer, 0, export.Buffer.Length); public int BankAddress { get; set; }
c.Position = 0;
}
c.BankAddress = export.BankAddress;
return c;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var cmd = (BehaviorscriptCommand)value;
var export = new CmdExport
{
Buffer = cmd.ToArray(),
BankAddress = cmd.BankAddress
};
serializer.Serialize(writer, export);
}
private class CmdExport
{
public byte[] Buffer { get; set; }
public int BankAddress { get; set; }
}
} }
} }

View File

@@ -1,35 +1,30 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Model.Fast3D;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Z.Collections.Extensions; using Z.Collections.Extensions;
namespace SM64Lib.Json namespace SM64Lib.Json;
internal class ComplexDictionarJsonConverter<TKey, TValue> : JsonConverter
{ {
internal class ComplexDictionarJsonConverter<TKey, TValue> : JsonConverter public override bool CanConvert(Type objectType)
{ {
public override bool CanConvert(Type objectType) return typeof(List<KeyValuePair<TKey, TValue>>).IsAssignableFrom(objectType);
{ }
return typeof(List<KeyValuePair<TKey, TValue>>).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
var list = serializer.Deserialize<List<KeyValuePair<TKey, TValue>>>(reader); var list = serializer.Deserialize<List<KeyValuePair<TKey, TValue>>>(reader);
var dic = new Dictionary<TKey, TValue>(); var dic = new Dictionary<TKey, TValue>();
dic.AddRange(list.ToArray()); dic.AddRange(list.ToArray());
return dic; return dic;
} }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value is Dictionary<TKey, TValue>) if (value is Dictionary<TKey, TValue>)
serializer.Serialize(writer, ((Dictionary<TKey, TValue>)value).ToArray()); serializer.Serialize(writer, ((Dictionary<TKey, TValue>)value).ToArray());
}
} }
} }

View File

@@ -2,70 +2,66 @@
using SM64Lib.Model.Fast3D; using SM64Lib.Model.Fast3D;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Json namespace SM64Lib.Json;
internal class Fast3DBufferJsonConverter : JsonConverter
{ {
internal class Fast3DBufferJsonConverter : JsonConverter public override bool CanConvert(Type objectType)
{ {
public override bool CanConvert(Type objectType) return typeof(Fast3DBuffer).IsAssignableFrom(objectType);
{ }
return typeof(Fast3DBuffer).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
var export = serializer.Deserialize<Fast3DBufferExport>(reader); var export = serializer.Deserialize<Fast3DBufferExport>(reader);
Fast3DBuffer c; Fast3DBuffer c;
if (existingValue is not null) if (existingValue is not null)
c = (Fast3DBuffer)existingValue; c = (Fast3DBuffer)existingValue;
else
c = new Fast3DBuffer();
if (export?.Buffer is not null)
{
c.Position = 0;
if (export.IsDeflateStream)
General.DecompressData(export.Buffer, c);
else else
c = new Fast3DBuffer(); c.Write(export.Buffer, 0, export.Buffer.Length);
if (export?.Buffer is not null) c.Position = 0;
{
c.Position = 0;
if (export.IsDeflateStream)
General.DecompressData(export.Buffer, c);
else
c.Write(export.Buffer, 0, export.Buffer.Length);
c.Position = 0;
}
c.Fast3DBankStart = export.Fast3DBankStart;
c.DLPointers = export.DLPointers.ToArray();
return c;
} }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) c.Fast3DBankStart = export.Fast3DBankStart;
c.DLPointers = export.DLPointers.ToArray();
return c;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var buffer = (Fast3DBuffer)value;
var export = new Fast3DBufferExport
{ {
var buffer = (Fast3DBuffer)value; Buffer = General.CompressData(buffer, CompressionLevel.Fastest),
var export = new Fast3DBufferExport Fast3DBankStart = buffer.Fast3DBankStart,
{ DLPointers = buffer.DLPointers.ToList(),
Buffer = General.CompressData(buffer, CompressionLevel.Fastest), IsDeflateStream = true
Fast3DBankStart = buffer.Fast3DBankStart, };
DLPointers = buffer.DLPointers.ToList(), buffer.Position = 0;
IsDeflateStream = true
};
buffer.Position = 0;
serializer.Serialize(writer, export); serializer.Serialize(writer, export);
} }
private class Fast3DBufferExport private class Fast3DBufferExport
{ {
public byte[] Buffer { get; set; } public byte[] Buffer { get; set; }
public int Fast3DBankStart { get; set; } public int Fast3DBankStart { get; set; }
public List<Geolayout.Geopointer> DLPointers { get; set; } public List<Geolayout.Geopointer> DLPointers { get; set; }
public bool IsDeflateStream { get; set; } = false; public bool IsDeflateStream { get; set; } = false;
}
} }
} }

View File

@@ -1,61 +1,54 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Behaviors.Script;
using SM64Lib.Geolayout.Script; using SM64Lib.Geolayout.Script;
using SM64Lib.Model.Fast3D;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Json namespace SM64Lib.Json;
internal class GeolayoutscriptCommandJsonConverter : JsonConverter
{ {
internal class GeolayoutscriptCommandJsonConverter : JsonConverter public override bool CanConvert(Type objectType)
{ {
public override bool CanConvert(Type objectType) return typeof(GeolayoutCommand).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var export = serializer.Deserialize<CmdExport>(reader);
GeolayoutCommand c;
if (existingValue is not null)
c = (GeolayoutCommand)existingValue;
else
c = new GeolayoutCommand();
if (export?.Buffer is not null)
{ {
return typeof(GeolayoutCommand).IsAssignableFrom(objectType); c.Position = 0;
c.Write(export.Buffer, 0, export.Buffer.Length);
c.Position = 0;
} }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) c.BankAddress = export.BankAddress;
return c;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var cmd = (GeolayoutCommand)value;
var export = new CmdExport
{ {
var export = serializer.Deserialize<CmdExport>(reader); Buffer = cmd.ToArray(),
GeolayoutCommand c; BankAddress = cmd.BankAddress
};
if (existingValue is not null) serializer.Serialize(writer, export);
c = (GeolayoutCommand)existingValue; }
else
c = new GeolayoutCommand();
if (export?.Buffer is not null) private class CmdExport
{ {
c.Position = 0; public byte[] Buffer { get; set; }
c.Write(export.Buffer, 0, export.Buffer.Length); public int BankAddress { get; set; }
c.Position = 0;
}
c.BankAddress = export.BankAddress;
return c;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var cmd = (GeolayoutCommand)value;
var export = new CmdExport
{
Buffer = cmd.ToArray(),
BankAddress = cmd.BankAddress
};
serializer.Serialize(writer, export);
}
private class CmdExport
{
public byte[] Buffer { get; set; }
public int BankAddress { get; set; }
}
} }
} }

View File

@@ -1,36 +1,30 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Json namespace SM64Lib.Json;
internal class JsonHelper
{ {
internal class JsonHelper public static JsonSerializer CreateJsonSerializer(
bool allowReferences = false,
bool rememberTypeNames = false,
bool enableIndentedFormatting = true)
{ {
public static JsonSerializer CreateJsonSerializer( var serializer = JsonSerializer.CreateDefault();
bool allowReferences = false,
bool rememberTypeNames = false, if (enableIndentedFormatting)
bool enableIndentedFormatting = true) serializer.Formatting = Formatting.Indented;
if (rememberTypeNames)
serializer.TypeNameHandling = TypeNameHandling.Auto;
if (allowReferences)
{ {
var serializer = JsonSerializer.CreateDefault(); serializer.PreserveReferencesHandling = PreserveReferencesHandling.All;
serializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
if (enableIndentedFormatting)
serializer.Formatting = Formatting.Indented;
if (rememberTypeNames)
serializer.TypeNameHandling = TypeNameHandling.Auto;
if (allowReferences)
{
serializer.PreserveReferencesHandling = PreserveReferencesHandling.All;
serializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
}
serializer.Converters.Add(new MemoryStreamJsonConverter());
return serializer;
} }
serializer.Converters.Add(new MemoryStreamJsonConverter());
return serializer;
} }
} }

View File

@@ -1,62 +1,54 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Behaviors.Script;
using SM64Lib.Geolayout.Script;
using SM64Lib.Levels.Script; using SM64Lib.Levels.Script;
using SM64Lib.Model.Fast3D;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Json namespace SM64Lib.Json;
internal class LevelscriptCommandJsonConverter : JsonConverter
{ {
internal class LevelscriptCommandJsonConverter : JsonConverter public override bool CanConvert(Type objectType)
{ {
public override bool CanConvert(Type objectType) return typeof(LevelscriptCommand).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var export = serializer.Deserialize<CmdExport>(reader);
LevelscriptCommand c;
if (existingValue is not null)
c = (LevelscriptCommand)existingValue;
else
c = new LevelscriptCommand();
if (export?.Buffer is not null)
{ {
return typeof(LevelscriptCommand).IsAssignableFrom(objectType); c.Position = 0;
c.Write(export.Buffer, 0, export.Buffer.Length);
c.Position = 0;
} }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) c.BankAddress = export.BankAddress;
return c;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var cmd = (LevelscriptCommand)value;
var export = new CmdExport
{ {
var export = serializer.Deserialize<CmdExport>(reader); Buffer = cmd.ToArray(),
LevelscriptCommand c; BankAddress = cmd.BankAddress
};
if (existingValue is not null) serializer.Serialize(writer, export);
c = (LevelscriptCommand)existingValue; }
else
c = new LevelscriptCommand();
if (export?.Buffer is not null) private class CmdExport
{ {
c.Position = 0; public byte[] Buffer { get; set; }
c.Write(export.Buffer, 0, export.Buffer.Length); public int BankAddress { get; set; }
c.Position = 0;
}
c.BankAddress = export.BankAddress;
return c;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var cmd = (LevelscriptCommand)value;
var export = new CmdExport
{
Buffer = cmd.ToArray(),
BankAddress = cmd.BankAddress
};
serializer.Serialize(writer, export);
}
private class CmdExport
{
public byte[] Buffer { get; set; }
public int BankAddress { get; set; }
}
} }
} }

View File

@@ -1,37 +1,28 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Behaviors.Script;
using SM64Lib.Geolayout.Script;
using SM64Lib.Levels.Script;
using SM64Lib.Model.Fast3D;
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Json namespace SM64Lib.Json;
internal class MemoryStreamJsonConverter : JsonConverter
{ {
internal class MemoryStreamJsonConverter : JsonConverter public override bool CanConvert(Type objectType)
{ {
public override bool CanConvert(Type objectType) return typeof(MemoryStream).IsAssignableFrom(objectType);
{ }
return typeof(MemoryStream).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
var msData = serializer.Deserialize<byte[]>(reader); var msData = serializer.Deserialize<byte[]>(reader);
var ms = new MemoryStream(); var ms = new MemoryStream();
ms.Write(msData, 0, msData.Length); ms.Write(msData, 0, msData.Length);
ms.Position = 0; ms.Position = 0;
return ms; return ms;
} }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
var ms = (MemoryStream)value; var ms = (MemoryStream)value;
serializer.Serialize(writer, ms.ToArray()); serializer.Serialize(writer, ms.ToArray());
}
} }
} }

View File

@@ -1,16 +1,15 @@
using global::System.Drawing; using global::System.Drawing;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
{
public class AreaBG
{
public AreaBGs Type { get; set; } = AreaBGs.Levelbackground;
public Color Color { get; set; } = Color.Black;
}
public enum AreaBGs public class AreaBG
{ {
Levelbackground, public AreaBGs Type { get; set; } = AreaBGs.Levelbackground;
Color public Color Color { get; set; } = Color.Black;
} }
public enum AreaBGs
{
Levelbackground,
Color
} }

View File

@@ -1,23 +1,16 @@
using System; namespace SM64Lib.Levels;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Levels public enum AreaReverbLevel : byte
{ {
public enum AreaReverbLevel : byte None,
{ Level01 = 0x8,
None, Level02 = 0xC,
Level01 = 0x8, Level03 = 0x10,
Level02 = 0xC, Level04 = 0x18,
Level03 = 0x10, Level05 = 0x20,
Level04 = 0x18, Level06 = 0x28,
Level05 = 0x20, Level07 = 0x30,
Level06 = 0x28, Level08 = 0x38,
Level07 = 0x30, Level09 = 0x40,
Level08 = 0x38, Level10 = 0x70
Level09 = 0x40,
Level10 = 0x70
}
} }

View File

@@ -1,123 +1,122 @@
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public enum ObjectBank0x0C
{ {
public enum ObjectBank0x0C Disabled,
{ HauntedObjects,
Disabled, SnowObjects,
HauntedObjects, AssortedEnemies1,
SnowObjects, DesertObjects,
AssortedEnemies1, BigBobOmbBoss,
DesertObjects, AssortedEnemies2,
BigBobOmbBoss, WaterObjects,
AssortedEnemies2, AssortedEnemies3,
WaterObjects, PeachYoshi,
AssortedEnemies3, Switches,
PeachYoshi, LavaObjects
Switches, }
LavaObjects
}
public enum ObjectBank0x0D public enum ObjectBank0x0D
{ {
Disabled, Disabled,
AssortedEnemies4, AssortedEnemies4,
Moneybags, Moneybags,
CastleObjects, CastleObjects,
GroundEnemies, GroundEnemies,
WaterObjects2, WaterObjects2,
Bowser Bowser
} }
public enum ObjectBank0x0E public enum ObjectBank0x0E
{ {
Disabled, Disabled,
HaundetHouse, HaundetHouse,
CoolCoolMountain, CoolCoolMountain,
InsideCastle, InsideCastle,
HazyMazeCave, HazyMazeCave,
ShiftingSandLand, ShiftingSandLand,
BobOmbBattlefield, BobOmbBattlefield,
SnowandsLand, SnowandsLand,
WetDryWorld, WetDryWorld,
JollyRogerBay, JollyRogerBay,
TinyHugeIsland, TinyHugeIsland,
TickTockClock, TickTockClock,
RainbowRide, RainbowRide,
CastleGrounds, CastleGrounds,
Bowser1Course, Bowser1Course,
VanishCap, VanishCap,
Bowser2Course, Bowser2Course,
Bowser3Course, Bowser3Course,
LethalLavaLand, LethalLavaLand,
DireDireDocks, DireDireDocks,
WhompsFortress, WhompsFortress,
CastleCourtyard, CastleCourtyard,
WingCap, WingCap,
Bowser2Battle, Bowser2Battle,
Bowser3Battle, Bowser3Battle,
TallTallMountain TallTallMountain
} }
public enum ObjectBanks public enum ObjectBanks
{ {
Bank0x0C, Bank0x0C,
Bank0x0D, Bank0x0D,
Bank0x0E Bank0x0E
} }
public enum Levels : byte public enum Levels : byte
{ {
HaundetHouse = 0x4, HaundetHouse = 0x4,
CoolCoolMountain, CoolCoolMountain,
InsideCastle, InsideCastle,
HazyMazeCave, HazyMazeCave,
ShiftingSandLand, ShiftingSandLand,
BobOmbsBattlefield, BobOmbsBattlefield,
SnowManLand, SnowManLand,
WetDryWorld, WetDryWorld,
JollyRogerBay, JollyRogerBay,
TinyHugeIsland, TinyHugeIsland,
TickTockClock, TickTockClock,
RainbowRide, RainbowRide,
CastleGrounds, CastleGrounds,
Bowser1Course, Bowser1Course,
VanishCap, VanishCap,
Bowser2Course, Bowser2Course,
SecretAquarium, SecretAquarium,
Bowser3Course, Bowser3Course,
LethalLavaLand, LethalLavaLand,
DireDireDocks, DireDireDocks,
WhompsFortress, WhompsFortress,
EndCakePicture, EndCakePicture,
CastleCourtyard, CastleCourtyard,
PeachsSecretSlide, PeachsSecretSlide,
MetalCap, MetalCap,
WingCap, WingCap,
Bowser1Battle, Bowser1Battle,
RainbowClouds, RainbowClouds,
Bowser2Battle = 0x21, Bowser2Battle = 0x21,
Bowser3Battle, Bowser3Battle,
TallTallMountain = 0x24 TallTallMountain = 0x24
} }
public enum ScrollingTextureAxis public enum ScrollingTextureAxis
{ {
X, X,
Y Y
} }
public enum SpecialBoxType public enum SpecialBoxType
{ {
Water, Water,
ToxicHaze, ToxicHaze,
Mist Mist
} }
public enum WaterType public enum WaterType
{ {
Default = 0x0, Default = 0x0,
JRBWater = 0x20000, JRBWater = 0x20000,
GreenWater = 0x30000, GreenWater = 0x30000,
LavaWater = 0x40000 LavaWater = 0x40000
}
} }

View File

@@ -1,10 +1,9 @@
using global::SM64Lib.Data; using global::SM64Lib.Data;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public interface ILevelManager
{ {
public interface ILevelManager void LoadLevel(Level lvl, RomManager rommgr, ushort LevelID, uint segAddress);
{ LevelSaveResult SaveLevel(Level lvl, RomManager rommgr, BinaryData output, ref uint curOff);
void LoadLevel(Level lvl, RomManager rommgr, ushort LevelID, uint segAddress);
LevelSaveResult SaveLevel(Level lvl, RomManager rommgr, BinaryData output, ref uint curOff);
}
} }

View File

@@ -1,329 +1,326 @@
using System.Collections.Generic; using global::SM64Lib.Levels.Script;
using System.Data;
using global::System.IO;
using System.Linq;
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using global::SM64Lib.Levels.Script;
using global::SM64Lib.Levels.Script.Commands; using global::SM64Lib.Levels.Script.Commands;
using global::SM64Lib.Objects.ObjectBanks.Data; using global::SM64Lib.Objects.ObjectBanks.Data;
using global::SM64Lib.SegmentedBanking; using global::SM64Lib.SegmentedBanking;
using SM64Lib.Objects.ModelBanks; using Microsoft.VisualBasic;
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Objects.ModelBanks;
using System; using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public abstract class Level
{ {
public abstract class Level
// S h a r e d M e m b e r s
internal static readonly byte[] LevelscriptStart = new byte[] { 0x80, 0x8, 0x0, 0x0, 0x19, 0x0, 0x0, 0x1C, 0x8, 0x0, 0x0, 0xA, 0x0, 0xA0, 0x0, 0x78, 0x0, 0xA0, 0x0, 0x78, 0x4, 0x0, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0 };
// F i e l d s
protected SegmentedBank _Bank0x19 = null;
// A u t o P r o p e r t i e s
internal LevelscriptCommand LastGobCmdSegLoad { get; set; } = null;
internal LevelscriptCommand LastLobCmdSegLoad { get; set; } = null;
[JsonIgnore]
internal Dictionary<byte, ObjectBankData> MyObjectBanks { get; private set; } = new Dictionary<byte, ObjectBankData>();
public Levelscript Levelscript { get; set; } = new Levelscript();
public List<LevelArea> Areas { get; private set; } = new List<LevelArea>();
public ushort LevelID { get; set; } = 0;
public LevelBG Background { get; private set; } = new LevelBG();
public bool ActSelector { get; set; } = false;
public bool HardcodedCameraSettings { get; set; } = false;
public bool Closed { get; set; } = false;
public int LastRomOffset { get; set; } = -1;
public bool NeedToSaveLevelscript { get; set; } = false;
public bool NeedToSaveBanks0E { get; set; } = false;
public bool OneBank0xESystemEnabled { get; set; } = true;
public bool EnableGlobalObjectBank { get; set; } = false;
public bool EnableLocalObjectBank { get; set; } = false;
public CustomModelBank LocalObjectBank { get; private set; } = new CustomModelBank();
[JsonIgnore]
public RomManager RomManager { get; set; }
// O t h e r P r o p e r t i e s
[JsonIgnore]
public IReadOnlyDictionary<byte, ObjectBankData> LoadedObjectBanks
{ {
get
// S h a r e d M e m b e r s
internal static readonly byte[] LevelscriptStart = new byte[] { 0x80, 0x8, 0x0, 0x0, 0x19, 0x0, 0x0, 0x1C, 0x8, 0x0, 0x0, 0xA, 0x0, 0xA0, 0x0, 0x78, 0x0, 0xA0, 0x0, 0x78, 0x4, 0x0, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0 };
// F i e l d s
protected SegmentedBank _Bank0x19 = null;
// A u t o P r o p e r t i e s
internal LevelscriptCommand LastGobCmdSegLoad { get; set; } = null;
internal LevelscriptCommand LastLobCmdSegLoad { get; set; } = null;
[JsonIgnore]
internal Dictionary<byte, ObjectBankData> MyObjectBanks { get; private set; } = new Dictionary<byte, ObjectBankData>();
public Levelscript Levelscript { get; set; } = new Levelscript();
public List<LevelArea> Areas { get; private set; } = new List<LevelArea>();
public ushort LevelID { get; set; } = 0;
public LevelBG Background { get; private set; } = new LevelBG();
public bool ActSelector { get; set; } = false;
public bool HardcodedCameraSettings { get; set; } = false;
public bool Closed { get; set; } = false;
public int LastRomOffset { get; set; } = -1;
public bool NeedToSaveLevelscript { get; set; } = false;
public bool NeedToSaveBanks0E { get; set; } = false;
public bool OneBank0xESystemEnabled { get; set; } = true;
public bool EnableGlobalObjectBank { get; set; } = false;
public bool EnableLocalObjectBank { get; set; } = false;
public CustomModelBank LocalObjectBank { get; private set; } = new CustomModelBank();
[JsonIgnore]
public RomManager RomManager { get; set; }
// O t h e r P r o p e r t i e s
[JsonIgnore]
public IReadOnlyDictionary<byte, ObjectBankData> LoadedObjectBanks
{ {
get return MyObjectBanks;
{
return MyObjectBanks;
}
}
[JsonIgnore]
public SegmentedBank Bank0x19
{
get
{
return _Bank0x19;
}
internal set
{
_Bank0x19 = value;
}
}
[JsonIgnore]
public int ObjectsCount
{
get
{
int tcount = 0;
foreach (var a in Areas)
tcount += a.Objects.Count;
return tcount;
}
}
[JsonIgnore]
public int WarpsCount
{
get
{
int tcount = 0;
foreach (var a in Areas)
tcount += a.Warps.Count;
return tcount;
}
}
[JsonIgnore]
public long Length
{
get
{
long length = 0;
if (Bank0x19 is not null)
length += Bank0x19.Length;
else
length += RomManagerSettings.DefaultLevelscriptSize;
if (LocalObjectBank is not null)
length += LocalObjectBank.Length;
foreach (var area in Areas)
{
length += area.AreaModel.Length;
if (OneBank0xESystemEnabled)
length += area.Levelscript.Length;
}
return length;
}
}
// C o n s t r u c t o r s
[JsonConstructor]
protected Level(JsonConstructorAttribute attr)
{
}
protected Level(ushort LevelID, int LevelIndex, RomManager rommgr) : this(rommgr)
{
this.LevelID = LevelID;
CreateNewLevelscript();
HardcodedCameraSettings = false;
ActSelector = General.ActSelectorDefaultValues[LevelIndex];
}
protected Level(RomManager rommgr)
{
RomManager = rommgr;
}
// M e t h o d s
public void CreateNewLevelscript()
{
{
var withBlock = Levelscript;
withBlock.Close();
withBlock.Clear();
// Start Loading Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1B, 0x4, 0x0, 0x0 }));
// Loading Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x17, 0xC, 0x1, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }));
// Start Model Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1D, 0x4, 0x0, 0x0 }));
// Load Marios Model
withBlock.Add(new LevelscriptCommand(new byte[] { 0x25, 0xC, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x13, 0x0, 0x2E, 0xC0 }));
// Start End-Of-Level Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1E, 0x4, 0x0, 0x0 }));
// End-Of-Level Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x2B, 0xC, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x11, 0x8, 0x0, 0x0, 0x80, 0x24, 0xBC, 0xD8 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x12, 0x8, 0x0, 0x1, 0x80, 0x24, 0xBC, 0xD8 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1C, 0x4, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x4, 0x4, 0x0, 0x1 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x2, 0x4, 0x0, 0x0 }));
// Add the general object bank
ChangeObjectBank(null, RomManager.RomConfig.ObjectBankInfoData[Convert.ToByte(0xB)]?.FirstOrDefault());
}
foreach (LevelscriptCommand c in Levelscript)
{
if (c.CommandType != LevelscriptCommandTypes.LoadRomToRam)
continue;
if (clLoadRomToRam.GetSegmentedID(c) != 0xE)
continue;
}
}
public void SetSegmentedBanks(RomManager rommgr)
{
foreach (LevelscriptCommand cmd in Levelscript)
{
var switchExpr = cmd.CommandType;
switch (switchExpr)
{
case LevelscriptCommandTypes.LoadRomToRam:
case LevelscriptCommandTypes.x1A:
case LevelscriptCommandTypes.x18:
{
cmd.Position = 0;
byte bankID = clLoadRomToRam.GetSegmentedID(cmd);
int startAddr = clLoadRomToRam.GetRomStart(cmd);
int endAddr = clLoadRomToRam.GetRomEnd(cmd);
var seg = rommgr.SetSegBank(bankID, startAddr, endAddr);
if (cmd.CommandType == LevelscriptCommandTypes.x1A)
seg.MakeAsMIO0();
break;
}
}
}
if (Bank0x19 is not null)
{
rommgr.SetSegBank(Bank0x19);
}
}
public LevelscriptCommand GetDefaultPositionCmd()
{
return (LevelscriptCommand)Levelscript.FirstOrDefault(n => n.CommandType == LevelscriptCommandTypes.DefaultPosition);
}
public void ChangeObjectBankData(byte bankID, ObjectBankData newObd)
{
ChangeObjectBank(GetObjectBankData(bankID), newObd);
MyObjectBanks[bankID] = newObd;
}
public ObjectBankData GetObjectBankData(byte bankID)
{
if (MyObjectBanks.ContainsKey(bankID))
{
return MyObjectBanks[bankID];
}
else
{
var obd = FindObjectBankData(bankID);
MyObjectBanks.Add(bankID, obd);
return obd;
}
}
protected void ChangeObjectBank(ObjectBankData oldObd, ObjectBankData newObd)
{
// Remove old commands
if (oldObd is not null)
{
foreach (ObjectBankDataCommand obdCmd in oldObd.Commands)
{
foreach (var cmd in Levelscript.Where(n => General.CompareTwoByteArrays(n.ToArray(), obdCmd.Command)).ToArray())
{
cmd.Close();
Levelscript.Remove(cmd);
}
}
}
// Add new commands
if (newObd is not null)
{
foreach (ObjectBankDataCommand obdCmd in newObd.Commands)
{
int startIndex = Levelscript.IndexOfFirst(LevelscriptCommandTypes.x1D);
if (!(obdCmd.CommandType == 0x1A || obdCmd.CommandType == 0x17))
{
startIndex += 1;
}
var cmd = new LevelscriptCommand(obdCmd.Command);
Levelscript.Insert(startIndex, cmd);
startIndex += 1;
}
}
}
protected ObjectBankData FindObjectBankData(byte bankID)
{
var list = RomManager.RomConfig.ObjectBankInfoData[bankID];
var Found = new List<bool>();
foreach (ObjectBankData obd in list)
{
foreach (ObjectBankDataCommand obdCmd in obd.Commands)
Found.Add(Levelscript.Where(n => General.CompareTwoByteArrays(n.ToArray(), obdCmd.Command)).Any());
if (!Found.Contains(false))
{
return obd;
}
Found.Clear();
}
return null;
}
public void Close()
{
foreach (var c in Levelscript)
c.Close();
Levelscript.Clear();
foreach (var a in Areas)
a.Close();
Areas.Clear();
Closed = true;
}
public override string ToString()
{
string output = "";
foreach (var cmd in Levelscript)
{
string tbytelist = "";
foreach (byte b in cmd.ToArray())
{
if (tbytelist != string.Empty)
tbytelist += " ";
tbytelist += Conversion.Hex(b);
}
if (output != string.Empty)
output += Environment.NewLine;
output += tbytelist;
}
return output;
} }
} }
[JsonIgnore]
public SegmentedBank Bank0x19
{
get
{
return _Bank0x19;
}
internal set
{
_Bank0x19 = value;
}
}
[JsonIgnore]
public int ObjectsCount
{
get
{
int tcount = 0;
foreach (var a in Areas)
tcount += a.Objects.Count;
return tcount;
}
}
[JsonIgnore]
public int WarpsCount
{
get
{
int tcount = 0;
foreach (var a in Areas)
tcount += a.Warps.Count;
return tcount;
}
}
[JsonIgnore]
public long Length
{
get
{
long length = 0;
if (Bank0x19 is not null)
length += Bank0x19.Length;
else
length += RomManagerSettings.DefaultLevelscriptSize;
if (LocalObjectBank is not null)
length += LocalObjectBank.Length;
foreach (var area in Areas)
{
length += area.AreaModel.Length;
if (OneBank0xESystemEnabled)
length += area.Levelscript.Length;
}
return length;
}
}
// C o n s t r u c t o r s
[JsonConstructor]
protected Level(JsonConstructorAttribute attr)
{
}
protected Level(ushort LevelID, int LevelIndex, RomManager rommgr) : this(rommgr)
{
this.LevelID = LevelID;
CreateNewLevelscript();
HardcodedCameraSettings = false;
ActSelector = General.ActSelectorDefaultValues[LevelIndex];
}
protected Level(RomManager rommgr)
{
RomManager = rommgr;
}
// M e t h o d s
public void CreateNewLevelscript()
{
{
var withBlock = Levelscript;
withBlock.Close();
withBlock.Clear();
// Start Loading Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1B, 0x4, 0x0, 0x0 }));
// Loading Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x17, 0xC, 0x1, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }));
// Start Model Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1D, 0x4, 0x0, 0x0 }));
// Load Marios Model
withBlock.Add(new LevelscriptCommand(new byte[] { 0x25, 0xC, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x13, 0x0, 0x2E, 0xC0 }));
// Start End-Of-Level Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1E, 0x4, 0x0, 0x0 }));
// End-Of-Level Commands
withBlock.Add(new LevelscriptCommand(new byte[] { 0x2B, 0xC, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x11, 0x8, 0x0, 0x0, 0x80, 0x24, 0xBC, 0xD8 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x12, 0x8, 0x0, 0x1, 0x80, 0x24, 0xBC, 0xD8 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1C, 0x4, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x4, 0x4, 0x0, 0x1 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x2, 0x4, 0x0, 0x0 }));
// Add the general object bank
ChangeObjectBank(null, RomManager.RomConfig.ObjectBankInfoData[Convert.ToByte(0xB)]?.FirstOrDefault());
}
foreach (LevelscriptCommand c in Levelscript)
{
if (c.CommandType != LevelscriptCommandTypes.LoadRomToRam)
continue;
if (clLoadRomToRam.GetSegmentedID(c) != 0xE)
continue;
}
}
public void SetSegmentedBanks(RomManager rommgr)
{
foreach (LevelscriptCommand cmd in Levelscript)
{
var switchExpr = cmd.CommandType;
switch (switchExpr)
{
case LevelscriptCommandTypes.LoadRomToRam:
case LevelscriptCommandTypes.x1A:
case LevelscriptCommandTypes.x18:
{
cmd.Position = 0;
byte bankID = clLoadRomToRam.GetSegmentedID(cmd);
int startAddr = clLoadRomToRam.GetRomStart(cmd);
int endAddr = clLoadRomToRam.GetRomEnd(cmd);
var seg = rommgr.SetSegBank(bankID, startAddr, endAddr);
if (cmd.CommandType == LevelscriptCommandTypes.x1A)
seg.MakeAsMIO0();
break;
}
}
}
if (Bank0x19 is not null)
{
rommgr.SetSegBank(Bank0x19);
}
}
public LevelscriptCommand GetDefaultPositionCmd()
{
return (LevelscriptCommand)Levelscript.FirstOrDefault(n => n.CommandType == LevelscriptCommandTypes.DefaultPosition);
}
public void ChangeObjectBankData(byte bankID, ObjectBankData newObd)
{
ChangeObjectBank(GetObjectBankData(bankID), newObd);
MyObjectBanks[bankID] = newObd;
}
public ObjectBankData GetObjectBankData(byte bankID)
{
if (MyObjectBanks.ContainsKey(bankID))
{
return MyObjectBanks[bankID];
}
else
{
var obd = FindObjectBankData(bankID);
MyObjectBanks.Add(bankID, obd);
return obd;
}
}
protected void ChangeObjectBank(ObjectBankData oldObd, ObjectBankData newObd)
{
// Remove old commands
if (oldObd is not null)
{
foreach (ObjectBankDataCommand obdCmd in oldObd.Commands)
{
foreach (var cmd in Levelscript.Where(n => General.CompareTwoByteArrays(n.ToArray(), obdCmd.Command)).ToArray())
{
cmd.Close();
Levelscript.Remove(cmd);
}
}
}
// Add new commands
if (newObd is not null)
{
foreach (ObjectBankDataCommand obdCmd in newObd.Commands)
{
int startIndex = Levelscript.IndexOfFirst(LevelscriptCommandTypes.x1D);
if (!(obdCmd.CommandType == 0x1A || obdCmd.CommandType == 0x17))
{
startIndex += 1;
}
var cmd = new LevelscriptCommand(obdCmd.Command);
Levelscript.Insert(startIndex, cmd);
startIndex += 1;
}
}
}
protected ObjectBankData FindObjectBankData(byte bankID)
{
var list = RomManager.RomConfig.ObjectBankInfoData[bankID];
var Found = new List<bool>();
foreach (ObjectBankData obd in list)
{
foreach (ObjectBankDataCommand obdCmd in obd.Commands)
Found.Add(Levelscript.Where(n => General.CompareTwoByteArrays(n.ToArray(), obdCmd.Command)).Any());
if (!Found.Contains(false))
{
return obd;
}
Found.Clear();
}
return null;
}
public void Close()
{
foreach (var c in Levelscript)
c.Close();
Levelscript.Clear();
foreach (var a in Areas)
a.Close();
Areas.Clear();
Closed = true;
}
public override string ToString()
{
string output = "";
foreach (var cmd in Levelscript)
{
string tbytelist = "";
foreach (byte b in cmd.ToArray())
{
if (tbytelist != string.Empty)
tbytelist += " ";
tbytelist += Conversion.Hex(b);
}
if (output != string.Empty)
output += Environment.NewLine;
output += tbytelist;
}
return output;
}
} }

View File

@@ -1,178 +1,175 @@
using System.Collections.Generic; using global::SM64Lib.Levels.Script;
using System.Linq;
using Microsoft.VisualBasic.CompilerServices;
using global::SM64Lib.Levels.Script;
using global::SM64Lib.Levels.Script.Commands; using global::SM64Lib.Levels.Script.Commands;
using global::SM64Lib.Levels.ScrolTex; using global::SM64Lib.Levels.ScrolTex;
using global::SM64Lib.Model; using global::SM64Lib.Model;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public abstract class LevelArea
{ {
public abstract class LevelArea
// S h a r e d M e m b e r s
public static readonly byte[] DefaultNormal3DObject = new byte[] { 0x24, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0 };
// F i e l d s
protected bool _GettingAreaCollision = false;
// A u t o P r o p e r t i e s
public SpecialBoxList SpecialBoxes { get; private set; } = new SpecialBoxList();
public List<ManagedScrollingTexture> ScrollingTextures { get; private set; } = new List<ManagedScrollingTexture>();
public List<LevelscriptCommand> Objects { get; private set; } = new List<LevelscriptCommand>();
public List<LevelscriptCommand> MacroObjects { get; private set; } = new List<LevelscriptCommand>();
public List<LevelscriptCommand> Warps { get; private set; } = new List<LevelscriptCommand>();
public List<LevelscriptCommand> WarpsForGame { get; private set; } = new List<LevelscriptCommand>();
public ShowMessage ShowMessage { get; private set; } = new ShowMessage();
public AreaBG Background { get; private set; } = new AreaBG();
public LevelscriptCommandCollection Levelscript { get; set; } = new LevelscriptCommandCollection();
public Geolayout.Geolayout Geolayout { get; set; } = new Geolayout.Geolayout(SM64Lib.Geolayout.Geolayout.NewScriptCreationMode.None);
public Geolayout.TerrainTypes TerrainType { get; set; } = SM64Lib.Geolayout.TerrainTypes.NoramlA;
public byte BGMusic { get; set; } = 0;
public byte AreaID { get; set; } = 0;
public uint GeolayoutOffset { get; set; } = 0;
public ObjectModel AreaModel { get; set; } = new ObjectModel();
public bool Enable2DCamera { get; set; } = false;
public uint Bank0x0EOffset { get; set; } = 0;
public int Bank0xELength { get; set; }
// O t h e r P r o p e r t i e s
[JsonIgnore]
public int Fast3DBankRomStart
{ {
get
// S h a r e d M e m b e r s
public static readonly byte[] DefaultNormal3DObject = new byte[] { 0x24, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0 };
// F i e l d s
protected bool _GettingAreaCollision = false;
// A u t o P r o p e r t i e s
public SpecialBoxList SpecialBoxes { get; private set; } = new SpecialBoxList();
public List<ManagedScrollingTexture> ScrollingTextures { get; private set; } = new List<ManagedScrollingTexture>();
public List<LevelscriptCommand> Objects { get; private set; } = new List<LevelscriptCommand>();
public List<LevelscriptCommand> MacroObjects { get; private set; } = new List<LevelscriptCommand>();
public List<LevelscriptCommand> Warps { get; private set; } = new List<LevelscriptCommand>();
public List<LevelscriptCommand> WarpsForGame { get; private set; } = new List<LevelscriptCommand>();
public ShowMessage ShowMessage { get; private set; } = new ShowMessage();
public AreaBG Background { get; private set; } = new AreaBG();
public LevelscriptCommandCollection Levelscript { get; set; } = new LevelscriptCommandCollection();
public Geolayout.Geolayout Geolayout { get; set; } = new Geolayout.Geolayout(SM64Lib.Geolayout.Geolayout.NewScriptCreationMode.None);
public Geolayout.TerrainTypes TerrainType { get; set; } = SM64Lib.Geolayout.TerrainTypes.NoramlA;
public byte BGMusic { get; set; } = 0;
public byte AreaID { get; set; } = 0;
public uint GeolayoutOffset { get; set; } = 0;
public ObjectModel AreaModel { get; set; } = new ObjectModel();
public bool Enable2DCamera { get; set; } = false;
public uint Bank0x0EOffset { get; set; } = 0;
public int Bank0xELength { get; set; }
// O t h e r P r o p e r t i e s
[JsonIgnore]
public int Fast3DBankRomStart
{
get
{
return Convert.ToInt32(Bank0x0EOffset);
}
}
[JsonIgnore]
public int Fast3DLength
{
get
{
return CollisionPointer - 0xE000000;
}
}
[JsonIgnore]
public bool IsCamera2D
{
get
{
return Enable2DCamera && Geolayout.CameraPreset == SM64Lib.Geolayout.CameraPresets.PlattfromLevels;
}
}
[JsonIgnore]
public int CollisionPointer
{
get
{
int CollisionPointerRet = default;
_GettingAreaCollision = true;
foreach (var cmd in Levelscript)
{
if (cmd.CommandType == LevelscriptCommandTypes.AreaCollision)
{
CollisionPointerRet = Convert.ToInt32(clAreaCollision.GetAreaCollision((LevelscriptCommand)cmd));
}
}
_GettingAreaCollision = false;
return CollisionPointerRet;
}
set
{
if (_GettingAreaCollision)
return;
foreach (var cmd in Levelscript)
{
if (cmd.CommandType == LevelscriptCommandTypes.AreaCollision)
{
clAreaCollision.SetAreaCollision((LevelscriptCommand)cmd, Convert.ToUInt32(value));
}
}
}
}
// M e t h o d s
public void SetSegmentedBanks(RomManager rommgr)
{
var bank0xE = rommgr.SetSegBank(0xE, Convert.ToInt32(Bank0x0EOffset), (int)(Bank0x0EOffset + Bank0xELength), AreaID);
bank0xE.Data = AreaModel.Fast3DBuffer;
}
internal void UpdateScrollingTextureVertexPointer(int offset)
{
foreach (ManagedScrollingTexture scrollText in ScrollingTextures)
scrollText.VertexPointer += offset;
}
public void Close()
{
Levelscript.Close();
Geolayout.Close();
}
// C o n s t r u c t o r s
protected LevelArea(byte AreaID) : this(AreaID, 9)
{
}
protected LevelArea(byte AreaID, byte LevelID) : this(AreaID, LevelID, true, true)
{
}
protected LevelArea(byte AreaID, byte LevelID, bool AddWarps, bool AddObjects)
{
Geolayout = new Geolayout.Geolayout(SM64Lib.Geolayout.Geolayout.NewScriptCreationMode.Level);
this.AreaID = AreaID;
{
var withBlock = Levelscript;
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1F, 0x8, AreaID, 0x0, 0x0, 0x0, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x2E, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x36, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x31, 0x4, 0x0, 0x2 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x20, 0x4, 0x0, 0x0 }));
}
if (AddWarps)
{
Objects.Add(new LevelscriptCommand(new byte[] { 0x24, 0x18, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA, 0x0, 0x0, 0x13, 0x0, 0x2F, 0x74 }));
Warps.Add(new LevelscriptCommand(new byte[] { 0x26, 0x8, 0xA, LevelID, AreaID, 0x0, 0x0, 0x0 }));
WarpsForGame.Add(new LevelscriptCommand(new byte[] { 0x26, 0x8, 0xF0, 0x6, 0x1, 0x32, 0x0, 0x0 }));
WarpsForGame.Add(new LevelscriptCommand(new byte[] { 0x26, 0x8, 0xF1, 0x6, 0x1, 0x64, 0x0, 0x0 }));
}
if (AddObjects)
{
//for (int i = 1; i <= 15; i++)
//{
// var newObj = new LevelscriptCommand(DefaultNormal3DObject);
// Objects.Add(newObj);
//}
}
}
protected LevelArea()
{
Geolayout = new Geolayout.Geolayout(SM64Lib.Geolayout.Geolayout.NewScriptCreationMode.Level);
}
[JsonConstructor]
protected LevelArea(JsonConstructorAttribute attr)
{ {
return Convert.ToInt32(Bank0x0EOffset);
} }
} }
[JsonIgnore]
public int Fast3DLength
{
get
{
return CollisionPointer - 0xE000000;
}
}
[JsonIgnore]
public bool IsCamera2D
{
get
{
return Enable2DCamera && Geolayout.CameraPreset == SM64Lib.Geolayout.CameraPresets.PlattfromLevels;
}
}
[JsonIgnore]
public int CollisionPointer
{
get
{
int CollisionPointerRet = default;
_GettingAreaCollision = true;
foreach (var cmd in Levelscript)
{
if (cmd.CommandType == LevelscriptCommandTypes.AreaCollision)
{
CollisionPointerRet = Convert.ToInt32(clAreaCollision.GetAreaCollision((LevelscriptCommand)cmd));
}
}
_GettingAreaCollision = false;
return CollisionPointerRet;
}
set
{
if (_GettingAreaCollision)
return;
foreach (var cmd in Levelscript)
{
if (cmd.CommandType == LevelscriptCommandTypes.AreaCollision)
{
clAreaCollision.SetAreaCollision((LevelscriptCommand)cmd, Convert.ToUInt32(value));
}
}
}
}
// M e t h o d s
public void SetSegmentedBanks(RomManager rommgr)
{
var bank0xE = rommgr.SetSegBank(0xE, Convert.ToInt32(Bank0x0EOffset), (int)(Bank0x0EOffset + Bank0xELength), AreaID);
bank0xE.Data = AreaModel.Fast3DBuffer;
}
internal void UpdateScrollingTextureVertexPointer(int offset)
{
foreach (ManagedScrollingTexture scrollText in ScrollingTextures)
scrollText.VertexPointer += offset;
}
public void Close()
{
Levelscript.Close();
Geolayout.Close();
}
// C o n s t r u c t o r s
protected LevelArea(byte AreaID) : this(AreaID, 9)
{
}
protected LevelArea(byte AreaID, byte LevelID) : this(AreaID, LevelID, true, true)
{
}
protected LevelArea(byte AreaID, byte LevelID, bool AddWarps, bool AddObjects)
{
Geolayout = new Geolayout.Geolayout(SM64Lib.Geolayout.Geolayout.NewScriptCreationMode.Level);
this.AreaID = AreaID;
{
var withBlock = Levelscript;
withBlock.Add(new LevelscriptCommand(new byte[] { 0x1F, 0x8, AreaID, 0x0, 0x0, 0x0, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x2E, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x36, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x31, 0x4, 0x0, 0x2 }));
withBlock.Add(new LevelscriptCommand(new byte[] { 0x20, 0x4, 0x0, 0x0 }));
}
if (AddWarps)
{
Objects.Add(new LevelscriptCommand(new byte[] { 0x24, 0x18, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA, 0x0, 0x0, 0x13, 0x0, 0x2F, 0x74 }));
Warps.Add(new LevelscriptCommand(new byte[] { 0x26, 0x8, 0xA, LevelID, AreaID, 0x0, 0x0, 0x0 }));
WarpsForGame.Add(new LevelscriptCommand(new byte[] { 0x26, 0x8, 0xF0, 0x6, 0x1, 0x32, 0x0, 0x0 }));
WarpsForGame.Add(new LevelscriptCommand(new byte[] { 0x26, 0x8, 0xF1, 0x6, 0x1, 0x64, 0x0, 0x0 }));
}
if (AddObjects)
{
//for (int i = 1; i <= 15; i++)
//{
// var newObj = new LevelscriptCommand(DefaultNormal3DObject);
// Objects.Add(newObj);
//}
}
}
protected LevelArea()
{
Geolayout = new Geolayout.Geolayout(SM64Lib.Geolayout.Geolayout.NewScriptCreationMode.Level);
}
[JsonConstructor]
protected LevelArea(JsonConstructorAttribute attr)
{
}
} }

View File

@@ -1,234 +1,232 @@
using global::System.Drawing; using global::SM64Lib.Model.Fast3D;
using global::System.Drawing;
using global::System.IO; using global::System.IO;
using Microsoft.VisualBasic.CompilerServices;
using SM64Lib.Data.System;
using global::SM64Lib.Model.Fast3D;
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Data.System;
using System; using System;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public class LevelBG
{ {
public class LevelBG private Bitmap _Image = null;
// A u t o P r o p e r t i e s
public byte[] ImageData { get; set; } = null;
public bool Enabled { get; set; } = true;
public bool IsCustom { get; set; } = false;
public Geolayout.BackgroundIDs ID { get; set; } = Geolayout.BackgroundIDs.Ocean;
// A u t o P r o p e r t i e s
[JsonIgnore]
public Bitmap Image
{ {
private Bitmap _Image = null; get
// A u t o P r o p e r t i e s
public byte[] ImageData { get; set; } = null;
public bool Enabled { get; set; } = true;
public bool IsCustom { get; set; } = false;
public Geolayout.BackgroundIDs ID { get; set; } = Geolayout.BackgroundIDs.Ocean;
// A u t o P r o p e r t i e s
[JsonIgnore]
public Bitmap Image
{ {
get if (_Image is not null)
{ {
if (_Image is not null) return _Image;
{
return _Image;
}
else
{
var img = GetImage();
_Image = (Bitmap)img;
return (Bitmap)img;
}
}
}
[JsonIgnore]
public int ImageLength
{
get
{
return ImageData?.Length ?? 0;
}
}
[JsonIgnore]
public bool HasImage
{
get
{
return ImageData is object;
}
}
// C o n s t r c u t o r s
public LevelBG()
{
}
public LevelBG(Geolayout.BackgroundIDs ID)
{
this.ID = ID;
}
public LevelBG(Image Image)
{
ID = Geolayout.BackgroundIDs.Custom;
SetImage(Image);
}
// M e t h o d s
public void WriteImage(Stream s, int offset)
{
// Write Image Data
s.Position = offset;
if (ImageData is not null)
{
s.Write(ImageData, 0, ImageData.Length);
}
}
public void ReadImage(Stream s, int offset)
{
// Read Image Data
ImageData = new byte[131072];
s.Position = offset;
s.Read(ImageData, 0, ImageData.Length);
_Image = null;
}
public void SetImage(Image image)
{
SetImage(new Bitmap(image));
}
public void SetImage(Bitmap bmp)
{
var s = new Size(248, 248); // ((&H20140 - &H140) / 256 / 2 / 32) * 31)
if (bmp.Size != s)
{
bmp = (Bitmap)TextureManager.ResizeImage(bmp, s, false);
}
ImageData = BackgroundImageConverter.GetBytes(bmp);
_Image = null;
}
public Image GetImage()
{
if (ImageData is not null)
{
var s = new Size(248, 248); // ((_ImageByts.Length - &H140) / 256 / 2 / 32) * 31)
var img = BackgroundImageConverter.GetImage(ImageData, s);
_Image = img;
return img;
} }
else else
{ {
return null; var img = GetImage();
_Image = (Bitmap)img;
return (Bitmap)img;
}
}
}
[JsonIgnore]
public int ImageLength
{
get
{
return ImageData?.Length ?? 0;
}
}
[JsonIgnore]
public bool HasImage
{
get
{
return ImageData is object;
}
}
// C o n s t r c u t o r s
public LevelBG()
{
}
public LevelBG(Geolayout.BackgroundIDs ID)
{
this.ID = ID;
}
public LevelBG(Image Image)
{
ID = Geolayout.BackgroundIDs.Custom;
SetImage(Image);
}
// M e t h o d s
public void WriteImage(Stream s, int offset)
{
// Write Image Data
s.Position = offset;
if (ImageData is not null)
{
s.Write(ImageData, 0, ImageData.Length);
}
}
public void ReadImage(Stream s, int offset)
{
// Read Image Data
ImageData = new byte[131072];
s.Position = offset;
s.Read(ImageData, 0, ImageData.Length);
_Image = null;
}
public void SetImage(Image image)
{
SetImage(new Bitmap(image));
}
public void SetImage(Bitmap bmp)
{
var s = new Size(248, 248); // ((&H20140 - &H140) / 256 / 2 / 32) * 31)
if (bmp.Size != s)
{
bmp = (Bitmap)TextureManager.ResizeImage(bmp, s, false);
}
ImageData = BackgroundImageConverter.GetBytes(bmp);
_Image = null;
}
public Image GetImage()
{
if (ImageData is not null)
{
var s = new Size(248, 248); // ((_ImageByts.Length - &H140) / 256 / 2 / 32) * 31)
var img = BackgroundImageConverter.GetImage(ImageData, s);
_Image = img;
return img;
}
else
{
return null;
}
}
public static byte[] GetBackgroundPointerTable()
{
return new byte[] { 0xA, 0x0, 0x0, 0x0, 0xA, 0x0, 0x8, 0x0, 0xA, 0x0, 0x10, 0x0, 0xA, 0x0, 0x18, 0x0, 0xA, 0x0, 0x20, 0x0, 0xA, 0x0, 0x28, 0x0, 0xA, 0x0, 0x30, 0x0, 0xA, 0x0, 0x38, 0x0, 0xA, 0x0, 0x0, 0x0, 0xA, 0x0, 0x8, 0x0, 0xA, 0x0, 0x40, 0x0, 0xA, 0x0, 0x48, 0x0, 0xA, 0x0, 0x50, 0x0, 0xA, 0x0, 0x58, 0x0, 0xA, 0x0, 0x60, 0x0, 0xA, 0x0, 0x68, 0x0, 0xA, 0x0, 0x70, 0x0, 0xA, 0x0, 0x78, 0x0, 0xA, 0x0, 0x40, 0x0, 0xA, 0x0, 0x48, 0x0, 0xA, 0x0, 0x80, 0x0, 0xA, 0x0, 0x88, 0x0, 0xA, 0x0, 0x90, 0x0, 0xA, 0x0, 0x98, 0x0, 0xA, 0x0, 0xA0, 0x0, 0xA, 0x0, 0xA8, 0x0, 0xA, 0x0, 0xB0, 0x0, 0xA, 0x0, 0xB8, 0x0, 0xA, 0x0, 0x80, 0x0, 0xA, 0x0, 0x88, 0x0, 0xA, 0x0, 0xC0, 0x0, 0xA, 0x0, 0xC8, 0x0, 0xA, 0x0, 0xD0, 0x0, 0xA, 0x0, 0xD8, 0x0, 0xA, 0x0, 0xE0, 0x0, 0xA, 0x0, 0xE8, 0x0, 0xA, 0x0, 0xF0, 0x0, 0xA, 0x0, 0xF8, 0x0, 0xA, 0x0, 0xC0, 0x0, 0xA, 0x0, 0xC8, 0x0, 0xA, 0x1, 0x0, 0x0, 0xA, 0x1, 0x8, 0x0, 0xA, 0x1, 0x10, 0x0, 0xA, 0x1, 0x18, 0x0, 0xA, 0x1, 0x20, 0x0, 0xA, 0x1, 0x28, 0x0, 0xA, 0x1, 0x30, 0x0, 0xA, 0x1, 0x38, 0x0, 0xA, 0x1, 0x0, 0x0, 0xA, 0x1, 0x8, 0x0, 0xA, 0x1, 0x40, 0x0, 0xA, 0x1, 0x48, 0x0, 0xA, 0x1, 0x50, 0x0, 0xA, 0x1, 0x58, 0x0, 0xA, 0x1, 0x60, 0x0, 0xA, 0x1, 0x68, 0x0, 0xA, 0x1, 0x70, 0x0, 0xA, 0x1, 0x78, 0x0, 0xA, 0x1, 0x40, 0x0, 0xA, 0x1, 0x48, 0x0, 0xA, 0x1, 0x80, 0x0, 0xA, 0x1, 0x88, 0x0, 0xA, 0x1, 0x90, 0x0, 0xA, 0x1, 0x98, 0x0, 0xA, 0x1, 0xA0, 0x0, 0xA, 0x1, 0xA8, 0x0, 0xA, 0x1, 0xB0, 0x0, 0xA, 0x1, 0xB8, 0x0, 0xA, 0x1, 0x80, 0x0, 0xA, 0x1, 0x88, 0x0, 0xA, 0x1, 0xC0, 0x0, 0xA, 0x1, 0xC8, 0x0, 0xA, 0x1, 0xD0, 0x0, 0xA, 0x1, 0xD8, 0x0, 0xA, 0x1, 0xE0, 0x0, 0xA, 0x1, 0xE8, 0x0, 0xA, 0x1, 0xF0, 0x0, 0xA, 0x1, 0xF8, 0x0, 0xA, 0x1, 0xC0, 0x0, 0xA, 0x1, 0xC8, 0x0 };
}
// C l a s s e s
private class BackgroundImageConverter
{
public static Bitmap GetImage(byte[] data, Size size)
{
var ms = new MemoryStream(data);
var br = new BinaryReader(ms);
var img = new Bitmap(size.Width, size.Height);
uint current_address = 0;
for (int y = 0, loopTo = (int)(size.Height / (double)31 - 1); y <= loopTo; y++)
{
for (int x = 0, loopTo1 = (int)(size.Width / (double)31 - 1); x <= loopTo1; x++)
{
ParseBlock(br, img, current_address, new Rectangle(x * 31, y * 31, 31, 31));
current_address += 2048;
}
}
ms.Close();
return img;
}
private static void ParseBlock(BinaryReader br, Bitmap map, uint address, Rectangle rect)
{
for (int yy = 0, loopTo = rect.Height - 1; yy <= loopTo; yy++)
{
for (int xx = 0, loopTo1 = rect.Width - 1; xx <= loopTo1; xx++)
{
int offset = (int)(address + (yy * (rect.Width + 1) + xx) * 2);
br.BaseStream.Position = offset;
ushort pixel = SwapInts.SwapUInt16(br.ReadUInt16());
byte red = Convert.ToByte((pixel >> 11 & 0x1F) * 8);
byte green = Convert.ToByte((pixel >> 6 & 0x1F) * 8);
byte blue = Convert.ToByte((pixel >> 1 & 0x1F) * 8);
byte alpha = Convert.ToByte((pixel & 1) > 0 ? 0xFF : 0);
var pixcol = Color.FromArgb(alpha, red, green, blue);
map.SetPixel(rect.X + xx, rect.Y + yy, pixcol);
}
} }
} }
public static byte[] GetBackgroundPointerTable() public static byte[] GetBytes(Bitmap img)
{ {
return new byte[] { 0xA, 0x0, 0x0, 0x0, 0xA, 0x0, 0x8, 0x0, 0xA, 0x0, 0x10, 0x0, 0xA, 0x0, 0x18, 0x0, 0xA, 0x0, 0x20, 0x0, 0xA, 0x0, 0x28, 0x0, 0xA, 0x0, 0x30, 0x0, 0xA, 0x0, 0x38, 0x0, 0xA, 0x0, 0x0, 0x0, 0xA, 0x0, 0x8, 0x0, 0xA, 0x0, 0x40, 0x0, 0xA, 0x0, 0x48, 0x0, 0xA, 0x0, 0x50, 0x0, 0xA, 0x0, 0x58, 0x0, 0xA, 0x0, 0x60, 0x0, 0xA, 0x0, 0x68, 0x0, 0xA, 0x0, 0x70, 0x0, 0xA, 0x0, 0x78, 0x0, 0xA, 0x0, 0x40, 0x0, 0xA, 0x0, 0x48, 0x0, 0xA, 0x0, 0x80, 0x0, 0xA, 0x0, 0x88, 0x0, 0xA, 0x0, 0x90, 0x0, 0xA, 0x0, 0x98, 0x0, 0xA, 0x0, 0xA0, 0x0, 0xA, 0x0, 0xA8, 0x0, 0xA, 0x0, 0xB0, 0x0, 0xA, 0x0, 0xB8, 0x0, 0xA, 0x0, 0x80, 0x0, 0xA, 0x0, 0x88, 0x0, 0xA, 0x0, 0xC0, 0x0, 0xA, 0x0, 0xC8, 0x0, 0xA, 0x0, 0xD0, 0x0, 0xA, 0x0, 0xD8, 0x0, 0xA, 0x0, 0xE0, 0x0, 0xA, 0x0, 0xE8, 0x0, 0xA, 0x0, 0xF0, 0x0, 0xA, 0x0, 0xF8, 0x0, 0xA, 0x0, 0xC0, 0x0, 0xA, 0x0, 0xC8, 0x0, 0xA, 0x1, 0x0, 0x0, 0xA, 0x1, 0x8, 0x0, 0xA, 0x1, 0x10, 0x0, 0xA, 0x1, 0x18, 0x0, 0xA, 0x1, 0x20, 0x0, 0xA, 0x1, 0x28, 0x0, 0xA, 0x1, 0x30, 0x0, 0xA, 0x1, 0x38, 0x0, 0xA, 0x1, 0x0, 0x0, 0xA, 0x1, 0x8, 0x0, 0xA, 0x1, 0x40, 0x0, 0xA, 0x1, 0x48, 0x0, 0xA, 0x1, 0x50, 0x0, 0xA, 0x1, 0x58, 0x0, 0xA, 0x1, 0x60, 0x0, 0xA, 0x1, 0x68, 0x0, 0xA, 0x1, 0x70, 0x0, 0xA, 0x1, 0x78, 0x0, 0xA, 0x1, 0x40, 0x0, 0xA, 0x1, 0x48, 0x0, 0xA, 0x1, 0x80, 0x0, 0xA, 0x1, 0x88, 0x0, 0xA, 0x1, 0x90, 0x0, 0xA, 0x1, 0x98, 0x0, 0xA, 0x1, 0xA0, 0x0, 0xA, 0x1, 0xA8, 0x0, 0xA, 0x1, 0xB0, 0x0, 0xA, 0x1, 0xB8, 0x0, 0xA, 0x1, 0x80, 0x0, 0xA, 0x1, 0x88, 0x0, 0xA, 0x1, 0xC0, 0x0, 0xA, 0x1, 0xC8, 0x0, 0xA, 0x1, 0xD0, 0x0, 0xA, 0x1, 0xD8, 0x0, 0xA, 0x1, 0xE0, 0x0, 0xA, 0x1, 0xE8, 0x0, 0xA, 0x1, 0xF0, 0x0, 0xA, 0x1, 0xF8, 0x0, 0xA, 0x1, 0xC0, 0x0, 0xA, 0x1, 0xC8, 0x0 }; var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
int wTiles = (int)(img.Width / (double)31);
int hTiles = (int)(img.Height / (double)31);
int current_address = 0;
for (int y = 0, loopTo = hTiles - 1; y <= loopTo; y++)
{
for (int x = 0, loopTo1 = wTiles - 1; x <= loopTo1; x++)
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), x * 31, y * 31, 0, 0, 0, 0, 31, 31, 32);
if (x < wTiles - 1)
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), (x + 1) * 31 - 30, y * 31, 30, 0, 1, 0, 31, 31, 32);
ConvertBlock(bw, img, Convert.ToUInt32(current_address), (x + 1) * 31 - 30, y * 31, 30, 30, 1, 1, 31, 31, 32);
}
else
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), -30, y * 31, 30, 0, 1, 0, 31, 31, 32);
ConvertBlock(bw, img, Convert.ToUInt32(current_address), -30, y * 31, 30, 30, 1, 1, 31, 31, 32);
}
if (y < hTiles - 1)
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), x * 31, (y + 1) * 31 - 30, 0, 30, 0, 1, 31, 31, 32);
}
else
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), x * 31, -30, 0, 30, 0, 1, 31, 31, 32);
}
current_address += 2048;
}
}
var temp = ms.ToArray();
ms.Close();
return temp;
} }
// C l a s s e s private static void ConvertBlock(BinaryWriter bw, Bitmap map, uint address, int src_x, int src_y, int start_x, int start_y, int offset_x, int offset_y, int w, int h, int lineWidth)
private class BackgroundImageConverter
{ {
public static Bitmap GetImage(byte[] data, Size size) for (int yy = start_y, loopTo = h - 1; yy <= loopTo; yy++)
{ {
var ms = new MemoryStream(data); for (int xx = start_x, loopTo1 = w - 1; xx <= loopTo1; xx++)
var br = new BinaryReader(ms);
var img = new Bitmap(size.Width, size.Height);
uint current_address = 0;
for (int y = 0, loopTo = (int)(size.Height / (double)31 - 1); y <= loopTo; y++)
{ {
for (int x = 0, loopTo1 = (int)(size.Width / (double)31 - 1); x <= loopTo1; x++) var pixel = map.GetPixel(src_x + xx, src_y + yy);
{ int r = pixel.R / 8;
ParseBlock(br, img, current_address, new Rectangle(x * 31, y * 31, 31, 31)); int g = pixel.G / 8;
current_address += 2048; int b = pixel.B / 8;
} int a = pixel.A == 0xFF ? 1 : 0;
} bw.BaseStream.Position = address + ((yy + offset_y) * lineWidth + xx + offset_x) * 2;
bw.Write(SwapInts.SwapUInt16(Convert.ToUInt16(r << 11 | g << 6 | b << 1 | a)));
ms.Close();
return img;
}
private static void ParseBlock(BinaryReader br, Bitmap map, uint address, Rectangle rect)
{
for (int yy = 0, loopTo = rect.Height - 1; yy <= loopTo; yy++)
{
for (int xx = 0, loopTo1 = rect.Width - 1; xx <= loopTo1; xx++)
{
int offset = (int)(address + (yy * (rect.Width + 1) + xx) * 2);
br.BaseStream.Position = offset;
ushort pixel = SwapInts.SwapUInt16(br.ReadUInt16());
byte red = Convert.ToByte((pixel >> 11 & 0x1F) * 8);
byte green = Convert.ToByte((pixel >> 6 & 0x1F) * 8);
byte blue = Convert.ToByte((pixel >> 1 & 0x1F) * 8);
byte alpha = Convert.ToByte((pixel & 1) > 0 ? 0xFF : 0);
var pixcol = Color.FromArgb(alpha, red, green, blue);
map.SetPixel(rect.X + xx, rect.Y + yy, pixcol);
}
}
}
public static byte[] GetBytes(Bitmap img)
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
int wTiles = (int)(img.Width / (double)31);
int hTiles = (int)(img.Height / (double)31);
int current_address = 0;
for (int y = 0, loopTo = hTiles - 1; y <= loopTo; y++)
{
for (int x = 0, loopTo1 = wTiles - 1; x <= loopTo1; x++)
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), x * 31, y * 31, 0, 0, 0, 0, 31, 31, 32);
if (x < wTiles - 1)
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), (x + 1) * 31 - 30, y * 31, 30, 0, 1, 0, 31, 31, 32);
ConvertBlock(bw, img, Convert.ToUInt32(current_address), (x + 1) * 31 - 30, y * 31, 30, 30, 1, 1, 31, 31, 32);
}
else
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), -30, y * 31, 30, 0, 1, 0, 31, 31, 32);
ConvertBlock(bw, img, Convert.ToUInt32(current_address), -30, y * 31, 30, 30, 1, 1, 31, 31, 32);
}
if (y < hTiles - 1)
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), x * 31, (y + 1) * 31 - 30, 0, 30, 0, 1, 31, 31, 32);
}
else
{
ConvertBlock(bw, img, Convert.ToUInt32(current_address), x * 31, -30, 0, 30, 0, 1, 31, 31, 32);
}
current_address += 2048;
}
}
var temp = ms.ToArray();
ms.Close();
return temp;
}
private static void ConvertBlock(BinaryWriter bw, Bitmap map, uint address, int src_x, int src_y, int start_x, int start_y, int offset_x, int offset_y, int w, int h, int lineWidth)
{
for (int yy = start_y, loopTo = h - 1; yy <= loopTo; yy++)
{
for (int xx = start_x, loopTo1 = w - 1; xx <= loopTo1; xx++)
{
var pixel = map.GetPixel(src_x + xx, src_y + yy);
int r = pixel.R / 8;
int g = pixel.G / 8;
int b = pixel.B / 8;
int a = pixel.A == 0xFF ? 1 : 0;
bw.BaseStream.Position = address + ((yy + offset_y) * lineWidth + xx + offset_x) * 2;
bw.Write(SwapInts.SwapUInt16(Convert.ToUInt16(r << 11 | g << 6 | b << 1 | a)));
}
} }
} }
} }

View File

@@ -1,79 +1,74 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using SM64Lib.Levels.Script; using SM64Lib.Levels.Script;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public class LevelExport
{ {
public class LevelExport // P r o p e r t i e s
[JsonProperty]
public object Content { get; protected set; }
[JsonProperty]
public LevelExportContentType ContentType { get; set; }
// C o n s t r u c t o r s
private LevelExport(object content, LevelExportContentType type) : this()
{ {
// P r o p e r t i e s Content = content;
ContentType = type;
}
[JsonProperty] public LevelExport(Level level) : this(new List<Level> { level }) { }
public object Content { get; protected set; } public LevelExport(List<Level> levels) : this(levels, LevelExportContentType.Level) { }
[JsonProperty] public LevelExport(LevelArea area) : this(new List<LevelArea> { area }) { }
public LevelExportContentType ContentType { get; set; } public LevelExport(List<LevelArea> areas) : this(areas, LevelExportContentType.Area) { }
public LevelExport(List<LevelscriptCommand> cmds, LevelExportContentType contentType) : this((object)cmds, contentType) { }
// C o n s t r u c t o r s [JsonConstructor]
private LevelExport() { }
private LevelExport(object content, LevelExportContentType type) : this() // F e a t u r e s
{
Content = content;
ContentType = type;
}
public LevelExport(Level level) : this(new List<Level> { level }) { } public void WriteToFile(string filePath, CompressionLevel compressionLevel)
public LevelExport(List<Level> levels) : this(levels, LevelExportContentType.Level) { } {
public LevelExport(LevelArea area) : this(new List<LevelArea> { area }) { } var plainText = compressionLevel == CompressionLevel.NoCompression;
public LevelExport(List<LevelArea> areas) : this(areas, LevelExportContentType.Area) { }
public LevelExport(List<LevelscriptCommand> cmds, LevelExportContentType contentType) : this((object)cmds, contentType) { }
[JsonConstructor] // Open streams
private LevelExport() { } var fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
var output = new DeflateStream(fs, compressionLevel, true);
var sw = new StreamWriter(output);
// F e a t u r e s // Create serializer
var serializer = Json.JsonHelper.CreateJsonSerializer(true, true, plainText);
public void WriteToFile(string filePath, CompressionLevel compressionLevel) // Serialize
{ serializer.Serialize(sw, this);
var plainText = compressionLevel == CompressionLevel.NoCompression;
// Open streams sw.Flush();
var fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite); output.Close();
var output = new DeflateStream(fs, compressionLevel, true); fs.Close();
var sw = new StreamWriter(output); }
// Create serializer public static LevelExport ReadFromFile(string filePath)
var serializer = Json.JsonHelper.CreateJsonSerializer(true, true, plainText); {
// Open streams
var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var input = new DeflateStream(fs, CompressionMode.Decompress);
var sr = new StreamReader(input);
// Serialize // Create serializer
serializer.Serialize(sw, this); var serializer = Json.JsonHelper.CreateJsonSerializer(true, true);
sw.Flush(); // Deserialize
output.Close(); var export = (LevelExport)serializer.Deserialize(sr, typeof(LevelExport));
fs.Close();
}
public static LevelExport ReadFromFile(string filePath) fs.Close();
{
// Open streams
var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var input = new DeflateStream(fs, CompressionMode.Decompress);
var sr = new StreamReader(input);
// Create serializer
var serializer = Json.JsonHelper.CreateJsonSerializer(true, true);
// Deserialize return export;
var export = (LevelExport)serializer.Deserialize(sr, typeof(LevelExport));
fs.Close();
return export;
}
} }
} }

View File

@@ -1,17 +1,10 @@
using System; namespace SM64Lib.Levels;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Levels public enum LevelExportContentType
{ {
public enum LevelExportContentType Unknown,
{ Level,
Unknown, Area,
Level, Objects,
Area, Warps
Objects,
Warps
}
} }

View File

@@ -1,14 +1,7 @@
using System; namespace SM64Lib.Levels;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Levels public enum LevelExportFileFormat
{ {
public enum LevelExportFileFormat JSON,
{ PlainText
JSON,
PlainText
}
} }

View File

@@ -2,74 +2,71 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public static class LevelExportImporter
{ {
public static class LevelExportImporter public static void ImportLevel(LevelExport export, RomManager destRomManager, KeyValuePair<Level, short>[] levelIDs)
{ {
public static void ImportLevel(LevelExport export, RomManager destRomManager, KeyValuePair<Level, short>[] levelIDs) var levels = export.Content as Level[];
if (levels != null)
{ {
var levels = export.Content as Level[]; foreach (var level in levels)
if (levels != null)
{ {
foreach (var level in levels) var id = (ushort?)levelIDs.FirstOrDefault(n => n.Key == level).Value;
if (id is not null)
{ {
var id = (ushort?)levelIDs.FirstOrDefault(n => n.Key == level).Value; level.LevelID = (ushort)id;
if (id is not null) destRomManager.Levels.Add(level);
{
level.LevelID = (ushort)id;
destRomManager.Levels.Add(level);
}
} }
} }
else
throw new NotSupportedException();
} }
else
throw new NotSupportedException();
}
public static void ImportArea(LevelExport export, Level destLevel, KeyValuePair<LevelArea, byte>[] areaIDs) public static void ImportArea(LevelExport export, Level destLevel, KeyValuePair<LevelArea, byte>[] areaIDs)
{
var areas = export.Content as LevelArea[];
if (areas != null)
{ {
var areas = export.Content as LevelArea[]; foreach (var area in areas)
if (areas != null)
{ {
foreach (var area in areas) var id = (byte?)areaIDs.FirstOrDefault(n => n.Key == area).Value;
if (id is not null)
{ {
var id = (byte?)areaIDs.FirstOrDefault(n => n.Key == area).Value; area.AreaID = (byte)id;
if (id is not null) destLevel.Areas.Add(area);
{
area.AreaID = (byte)id;
destLevel.Areas.Add(area);
}
} }
} }
else
throw new NotSupportedException();
} }
else
throw new NotSupportedException();
}
public static void ImportScript(LevelExport export, LevelArea destArea, List<LevelscriptCommand> allowedCommands) public static void ImportScript(LevelExport export, LevelArea destArea, List<LevelscriptCommand> allowedCommands)
{
var cmds = export.Content as List<LevelscriptCommand>;
if (cmds is not null)
{ {
var cmds = export.Content as List<LevelscriptCommand>; foreach (var cmd in cmds)
if (cmds is not null)
{ {
foreach (var cmd in cmds) if (allowedCommands.Contains(cmd))
{ {
if (allowedCommands.Contains(cmd)) switch (export.ContentType)
{ {
switch (export.ContentType) case LevelExportContentType.Objects:
{ destArea.Objects.Add(cmd);
case LevelExportContentType.Objects: break;
destArea.Objects.Add(cmd); case LevelExportContentType.Warps:
break; destArea.Warps.Add(cmd);
case LevelExportContentType.Warps: break;
destArea.Warps.Add(cmd);
break;
}
} }
} }
} }
else
throw new NotSupportedException();
} }
else
throw new NotSupportedException();
} }
} }

View File

@@ -1,143 +1,142 @@
using System.Collections.Generic; using global::Newtonsoft.Json.Linq;
using global::System.IO; using global::System.IO;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using global::Newtonsoft.Json.Linq;
using static SM64Lib.TextValueConverter.TextValueConverter; using static SM64Lib.TextValueConverter.TextValueConverter;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public class LevelInfoDataTabelList : List<LevelInfoDataTabelList.Level>
{ {
public class LevelInfoDataTabelList : List<LevelInfoDataTabelList.Level> public void ReadFromFile(string FileName)
{ {
public void ReadFromFile(string FileName) var jobj = JObject.Parse(File.ReadAllText(FileName));
if (jobj["Levels"] is not null)
{ {
var jobj = JObject.Parse(File.ReadAllText(FileName)); foreach (JObject entry in (JArray)jobj["Levels"])
if (jobj["Levels"] is not null)
{ {
foreach (JObject entry in (JArray)jobj["Levels"]) Add(new Level
{ {
Add(new Level Name = entry?["Name"].ToString(),
{ Number = entry?["Number"].ToString(),
Name = entry?["Name"].ToString(), TypeString = entry?["Type"].ToString(),
Number = entry?["Number"].ToString(), ID = (ushort)ValueFromText(entry?["ID"].ToString()),
TypeString = entry?["Type"].ToString(), Pointer = (uint)ValueFromText(entry?["Pointer"].ToString()),
ID = (ushort)ValueFromText(entry?["ID"].ToString()), Index = entry["Index"].Value<int>()
Pointer = (uint)ValueFromText(entry?["Pointer"].ToString()), });
Index = entry["Index"].Value<int>()
});
}
} }
} }
}
public Level GetByLevelID(ushort ID)
{ public Level GetByLevelID(ushort ID)
return this.FirstOrDefault(n => n.ID == ID); {
} return this.FirstOrDefault(n => n.ID == ID);
}
public class Level
{ public class Level
public ushort ID { get; set; } = 0; {
public uint Pointer { get; set; } = 0; public ushort ID { get; set; } = 0;
public string Name { get; set; } = ""; public uint Pointer { get; set; } = 0;
public string Number { get; set; } = ""; public string Name { get; set; } = "";
public LevelTypes Type { get; set; } = LevelTypes.Level; public string Number { get; set; } = "";
public int Index { get; set; } = -1; public LevelTypes Type { get; set; } = LevelTypes.Level;
public int Index { get; set; } = -1;
public string TypeString
{ public string TypeString
get {
{ get
var switchExpr = Type; {
switch (switchExpr) var switchExpr = Type;
{ switch (switchExpr)
case LevelTypes.Level: {
{ case LevelTypes.Level:
return "Level"; {
} return "Level";
}
case LevelTypes.Sidelevel:
{ case LevelTypes.Sidelevel:
return "Side"; {
} return "Side";
}
case LevelTypes.Overworld:
{ case LevelTypes.Overworld:
return "OW"; {
} return "OW";
}
case LevelTypes.Bowsercourse:
{ case LevelTypes.Bowsercourse:
return "BC"; {
} return "BC";
}
case LevelTypes.Bowserbattle:
{ case LevelTypes.Bowserbattle:
return "BB"; {
} return "BB";
}
case LevelTypes.Switchpalace:
{ case LevelTypes.Switchpalace:
return "Switch"; {
} return "Switch";
}
default:
{ default:
return ""; {
} return "";
} }
} }
}
set
{ set
switch (value) {
{ switch (value)
case "Level": {
{ case "Level":
Type = LevelTypes.Level; {
break; Type = LevelTypes.Level;
} break;
}
case "Side":
{ case "Side":
Type = LevelTypes.Sidelevel; {
break; Type = LevelTypes.Sidelevel;
} break;
}
case "OW":
{ case "OW":
Type = LevelTypes.Overworld; {
break; Type = LevelTypes.Overworld;
} break;
}
case "BC":
{ case "BC":
Type = LevelTypes.Bowsercourse; {
break; Type = LevelTypes.Bowsercourse;
} break;
}
case "BB":
{ case "BB":
Type = LevelTypes.Bowserbattle; {
break; Type = LevelTypes.Bowserbattle;
} break;
}
case "Switch":
{ case "Switch":
Type = LevelTypes.Switchpalace; {
break; Type = LevelTypes.Switchpalace;
} break;
} }
} }
} }
} }
}
public enum LevelTypes
{ public enum LevelTypes
Level, {
Sidelevel, Level,
Overworld, Sidelevel,
Switchpalace, Overworld,
Bowsercourse, Switchpalace,
Bowserbattle Bowsercourse,
} Bowserbattle
} }
} }

View File

@@ -2,21 +2,20 @@
using System.Data; using System.Data;
using System.Linq; using System.Linq;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
{
public class LevelList : List<Level>
{
public bool NeedToSave
{
get
{
return this.Where(n => n.NeedToSaveLevelscript || n.NeedToSaveBanks0E).Count() > 0;
}
}
public long Length public class LevelList : List<Level>
{
public bool NeedToSave
{
get
{ {
get => this.Sum(n => n.Length); return this.Where(n => n.NeedToSaveLevelscript || n.NeedToSaveBanks0E).Count() > 0;
} }
} }
public long Length
{
get => this.Sum(n => n.Length);
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,25 @@
using System; using global::System.IO;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using global::System.IO;
using Microsoft.VisualBasic.CompilerServices;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public class LevelNumberTable : List<byte>
{ {
public class LevelNumberTable : List<byte> public void ReadFromROM(string Romfile, int Address = 0xE8D98)
{ {
public void ReadFromROM(string Romfile, int Address = 0xE8D98) var fs = new FileStream(Romfile, FileMode.Open, FileAccess.Read);
{ ReadFromROM(ref fs);
var fs = new FileStream(Romfile, FileMode.Open, FileAccess.Read); fs.Close();
ReadFromROM(ref fs); }
fs.Close();
}
public void ReadFromROM(ref FileStream fs, int Address = 0xE8D98) public void ReadFromROM(ref FileStream fs, int Address = 0xE8D98)
{
Clear();
for (int i = 0; i <= 30; i++)
{ {
Clear(); fs.Position = Address + General.GetLevelIDFromIndex(Convert.ToByte(i));
for (int i = 0; i <= 30; i++) Add(Convert.ToByte(fs.ReadByte()));
{
fs.Position = Address + General.GetLevelIDFromIndex(Convert.ToByte(i));
Add(Convert.ToByte(fs.ReadByte()));
}
} }
} }
} }

View File

@@ -1,9 +1,8 @@
using global::SM64Lib.SegmentedBanking; using global::SM64Lib.SegmentedBanking;
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public class LevelSaveResult
{ {
public class LevelSaveResult public SegmentedBank Bank0x19 { get; set; } = null;
{
public SegmentedBank Bank0x19 { get; set; } = null;
}
} }

View File

@@ -1,10 +1,9 @@
namespace SM64Lib.Levels namespace SM64Lib.Levels;
public enum LevelType
{ {
public enum LevelType Original,
{ SM64RomManager,
Original, SM64Editor
SM64RomManager,
SM64Editor
}
} }

Some files were not shown because too many files have changed in this diff Show More