Skip to content

Commit

Permalink
Add CV script
Browse files Browse the repository at this point in the history
  • Loading branch information
IntelOrca committed Dec 31, 2023
1 parent 1350c75 commit 913f7ab
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 48 deletions.
92 changes: 92 additions & 0 deletions src/IntelOrca.Biohazard/Room/CvScript.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

namespace IntelOrca.Biohazard.Room
{
public readonly struct CvScript
{
public ReadOnlyMemory<byte> Data { get; }

public CvScript(ReadOnlyMemory<byte> data)
{
Data = data;
}

public int Count
{
get
{
if (Data.Length < 4)
return 0;

return GetOffset(0) / 4;
}
}

public CvScriptRoutine this[int index]
{
get
{
var count = Count;
if (index < 0 || index >= count)
throw new ArgumentOutOfRangeException(nameof(index));

var offset = GetOffset(index);
var length = index < count - 1 ? GetOffset(index + 1) - offset : Data.Length - offset;
return new CvScriptRoutine(Data.Slice(offset, length));
}
}

public int GetOffset(int index)
{
var offsets = MemoryMarshal.Cast<byte, int>(Data.Span);
return offsets[index];
}

public Builder ToBuilder()
{
var builder = new Builder();
for (var i = 0; i < Count; i++)
builder.Routines.Add(this[i]);
return builder;
}

public class Builder
{
public List<CvScriptRoutine> Routines { get; } = new List<CvScriptRoutine>();

public CvScript ToScript()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);

var offset = Routines.Count * 4;
for (var i = 0; i < Routines.Count; i++)
{
bw.Write(offset);
offset += Routines[i].Data.Length;
}

foreach (var routine in Routines)
{
bw.Write(routine.Data);
}

var bytes = ms.ToArray();
return new CvScript(bytes);
}
}
}

public readonly struct CvScriptRoutine
{
public ReadOnlyMemory<byte> Data { get; }

public CvScriptRoutine(ReadOnlyMemory<byte> data)
{
Data = data;
}
}
}
15 changes: 14 additions & 1 deletion src/IntelOrca.Biohazard/Room/RdtCv.Builder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class Builder : IRdtBuilder

public List<Item> Items { get; } = new List<Item>();
public List<Aot> Aots { get; } = new List<Aot>();
public CvScript Script { get; set; } = new CvScript();

public Builder(byte[] data)
{
Expand All @@ -23,7 +24,13 @@ public RdtCv ToRdt()
var br = new BinaryReader(_ms);
var bw = new BinaryWriter(_ms);
_ms.Position = 16;
_ms.Position = br.ReadInt32();
var tableOffset = br.ReadInt32();
var modelOffset = br.ReadInt32();
var motionOffset = br.ReadInt32();
var scriptOffset = br.ReadInt32();
var textureOffset = br.ReadInt32();

_ms.Position = tableOffset;
br.ReadInt32();
br.ReadInt32();
br.ReadInt32();
Expand All @@ -49,6 +56,9 @@ public RdtCv ToRdt()
if (aotCount != Aots.Count)
throw new Exception("Changing number of doors is not supported");

if (textureOffset - scriptOffset != Script.Data.Length)
throw new Exception("Changing script length is not supported");

_ms.Position = items;
foreach (var item in Items)
{
Expand All @@ -61,6 +71,9 @@ public RdtCv ToRdt()
bw.Write(aot);
}

_ms.Position = scriptOffset;
bw.Write(Script.Data);

return new RdtCv(_ms.ToArray());
}

Expand Down
16 changes: 13 additions & 3 deletions src/IntelOrca.Biohazard/Room/RdtCv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ public Builder ToBuilder()
var builder = new Builder(Data.ToArray());
builder.Aots.AddRange(Aots.ToArray());
builder.Items.AddRange(Items.ToArray());
builder.Script = Script;
return builder;
}

public FileHeader Header => Data.GetSafeSpan<FileHeader>(0, 1)[0];
private ReadOnlySpan<int> ScriptOffsets => Data.GetSafeSpan<int>(Header.ScriptsOffset, 15);
private ReadOnlySpan<int> ScriptOffsets => Data.GetSafeSpan<int>(Header.TableOffset, 15);
private ReadOnlySpan<int> ScriptCounts => Data.GetSafeSpan<int>(256, 14);

public ReadOnlySpan<Item> Items => GetTable<Item>(4);
Expand All @@ -56,6 +57,15 @@ public ReadOnlySpan<Reaction> Reactions
}
}

public CvScript Script
{
get
{
var mem = Data[Header.ScriptOffset..Header.TextureOffset];
return new CvScript(mem);
}
}

private ReadOnlySpan<T> GetTable<T>(int index) where T : struct
{
var offset = ScriptOffsets[index];
Expand All @@ -72,10 +82,10 @@ public unsafe struct FileHeader
public int Unk04;
public int Unk08;
public int Unk0C;
public int ScriptsOffset;
public int TableOffset;
public int ModelOffset;
public int MotionOffset;
public int Flags;
public int ScriptOffset;
public int TextureOffset;
public int Unk24;
public int Unk28;
Expand Down
42 changes: 42 additions & 0 deletions test/IntelOrca.Biohazard.Tests/MemoryAssert.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.IO;
using IntelOrca.Biohazard.Extensions;
using Xunit;

namespace IntelOrca.Biohazard.Tests
{
internal static class MemoryAssert
{
public static void AssertAndCompareMemory(ReadOnlyMemory<byte> expected, ReadOnlyMemory<byte> actual)
{
try
{
AssertMemory(expected, actual);
}
catch
{
var path = @"M:\temp\rdt";
Directory.CreateDirectory(path);
expected.WriteToFile(Path.Combine(path, "expected.dat"));
actual.WriteToFile(Path.Combine(path, "actual.dat"));
throw;
}
}

public static void AssertMemory(ReadOnlyMemory<byte> expected, ReadOnlyMemory<byte> actual)
{
var spanExpected = expected.Span;
var spanActual = actual.Span;

var length = spanExpected.Length;
Assert.Equal(length, spanActual.Length);
for (var i = 0; i < length; i++)
{
if (spanExpected[i] != spanActual[i])
{
Assert.False(true, $"Memory did not match at index {i}");
}
}
}
}
}
14 changes: 8 additions & 6 deletions test/IntelOrca.Biohazard.Tests/TestCV.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.IO;
using IntelOrca.Biohazard.Room;
using Xunit;
using static IntelOrca.Biohazard.Tests.MemoryAssert;

namespace IntelOrca.Biohazard.Tests
{
public class TestCV
public class TestCv
{
[Fact]
public void RDT_000()
Expand Down Expand Up @@ -44,9 +45,7 @@ public void RDT_001_Rebuild()
{
var rdt = GetRdt(1);
var newRdt = rdt.ToBuilder().ToRdt();
var a = rdt.Data.CalculateFnv1a();
var b = newRdt.Data.CalculateFnv1a();
Assert.Equal(a, b);
AssertMemory(rdt.Data, newRdt.Data);
}

[Fact]
Expand Down Expand Up @@ -82,10 +81,13 @@ public void RDT_001_Rebuild_WithChange()
}

[Fact]
public void RDT_010()
public void RDT_010_Rebuild_Script()
{
var rdt = GetRdt(10);
var reactions = rdt.Reactions;
var s1 = rdt.Script;
var sb = s1.ToBuilder();
var s2 = sb.ToScript();
AssertMemory(s1.Data, s2.Data);
}

private RdtCv GetRdt(int index)
Expand Down
39 changes: 1 addition & 38 deletions test/IntelOrca.Biohazard.Tests/TestRdtFile.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using IntelOrca.Biohazard.Extensions;
using IntelOrca.Biohazard.Room;
using IntelOrca.Biohazard.Script;
using IntelOrca.Biohazard.Script.Opcodes;
using Xunit;
using Xunit.Abstractions;
using static IntelOrca.Biohazard.Tests.MemoryAssert;
using static IntelOrca.Biohazard.Tests.TestInfo;

namespace IntelOrca.Biohazard.Tests
Expand Down Expand Up @@ -349,37 +344,5 @@ private static void AssertRebuild(BioVersion version, string fileName)
var rebuiltRdt = rdt.ToBuilder().ToRdt();
AssertAndCompareMemory(rdt.Data, rebuiltRdt.Data);
}

private static void AssertAndCompareMemory(ReadOnlyMemory<byte> expected, ReadOnlyMemory<byte> actual)
{
try
{
AssertMemory(expected, actual);
}
catch
{
var path = @"M:\temp\rdt";
Directory.CreateDirectory(path);
expected.WriteToFile(Path.Combine(path, "expected.dat"));
actual.WriteToFile(Path.Combine(path, "actual.dat"));
throw;
}
}

private static void AssertMemory(ReadOnlyMemory<byte> expected, ReadOnlyMemory<byte> actual)
{
var spanExpected = expected.Span;
var spanActual = actual.Span;

var length = spanExpected.Length;
Assert.Equal(length, spanActual.Length);
for (var i = 0; i < length; i++)
{
if (spanExpected[i] != spanActual[i])
{
Assert.False(true, $"Memory did not match at index {i}");
}
}
}
}
}

0 comments on commit 913f7ab

Please sign in to comment.