239 lines
7.6 KiB
C#
239 lines
7.6 KiB
C#
using global::SM64Lib.Data;
|
|
using global::System.IO;
|
|
using SM64Lib.SegmentedBanking;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace SM64Lib.Geolayout.Script;
|
|
|
|
public class Geolayoutscript : GeolayoutCommandCollection
|
|
{
|
|
public List<int> GeopointerOffsets = [];
|
|
|
|
public Geolayoutscript()
|
|
{
|
|
}
|
|
|
|
public Task ReadAsync(RomManager rommgr, int segAddress)
|
|
{
|
|
var t = new Task(() => Read(rommgr, segAddress));
|
|
t.Start();
|
|
return t;
|
|
}
|
|
|
|
public void Read(byte[] data, byte bankID)
|
|
{
|
|
var ms = new MemoryStream(data);
|
|
var segBank = new SegmentedBank(bankID, ms);
|
|
Read(segBank, 0);
|
|
}
|
|
|
|
public void Read(RomManager rommgr, int segAddress)
|
|
{
|
|
var segBank = rommgr.GetSegBank(Convert.ToByte(segAddress >> 24));
|
|
segBank.ReadDataIfNull(rommgr.RomFile);
|
|
Read(segBank, segAddress & 0x00ffffff);
|
|
}
|
|
|
|
public void Read(SegmentedBank segBank, int offset)
|
|
{
|
|
Close();
|
|
Clear();
|
|
GeopointerOffsets.Clear();
|
|
if (segBank is null)
|
|
return;
|
|
var data = new BinaryStreamData(segBank.Data)
|
|
{
|
|
Position = offset
|
|
};
|
|
var tb = new List<byte>();
|
|
GeolayoutCommandTypes cb = default;
|
|
int subNodeIndex = 0;
|
|
bool ende = false;
|
|
while (!ende)
|
|
{
|
|
if (data.Position >= data.Length)
|
|
break;
|
|
cb = (GeolayoutCommandTypes)data.ReadByte();
|
|
byte lenth = 0;
|
|
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;
|
|
|
|
for (int i = 1, loopTo = lenth; i <= loopTo; i++)
|
|
tb.Add(data.ReadByte());
|
|
|
|
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)
|
|
{
|
|
case GeolayoutCommandTypes.EndOfGeolayout:
|
|
ende = true;
|
|
break;
|
|
case GeolayoutCommandTypes.EndOfNode:
|
|
subNodeIndex -= 1;
|
|
break;
|
|
case GeolayoutCommandTypes.StartOfNode:
|
|
subNodeIndex += 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Write(Stream s, int GeolayoutStart)
|
|
{
|
|
var bw = new BinaryWriter(s);
|
|
|
|
// Write new Levelscript
|
|
s.Position = GeolayoutStart;
|
|
foreach (GeolayoutCommand c in this)
|
|
{
|
|
if (c.CommandType == GeolayoutCommandTypes.LoadDisplaylist)
|
|
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;
|
|
}
|
|
} |