code optimization
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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)
|
||||||
{
|
{
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SM64Lib.Exceptions
|
namespace SM64Lib.Exceptions;
|
||||||
|
|
||||||
|
public class InvalidMD5HashException : Exception
|
||||||
{
|
{
|
||||||
public class InvalidMD5HashException : Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
1137
SM64Lib/General.cs
1137
SM64Lib/General.cs
File diff suppressed because it is too large
Load Diff
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
@@ -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()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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
Reference in New Issue
Block a user