Commit 40f14d73 authored by Spencer Alves's avatar Spencer Alves

Reference resolution finally working on a small jam game.

Also some preliminary support for some of the extra stuff in said game (extra room instance information)
parent 460c8a7c
......@@ -43,7 +43,7 @@ namespace Altar
{
public uint NameOffset;
public int InstanceType;
public uint _pad1; // unknown
public int _pad1; // unknown
public uint Occurrences;
public uint FirstAddress;
}
......@@ -261,8 +261,8 @@ namespace Altar
public Point Origin;
// unknown stuff
fixed int _pad2[3];
float funk;
public fixed int _pad2[3];
public float funk;
uint _pad3;
public CountOffsetsPair Textures;
......@@ -363,6 +363,18 @@ namespace Altar
public float MetresPerPixel;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct RoomObjInstEntry
{
public uint Name;
public uint Index;
public uint Unk1;
public uint Unk2;
fixed uint _pad1[4];
public uint Unk3;
public uint InstCount;
public uint Instances;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct TexPageEntry
{
public Rectangle16 Source, Dest;
......
......@@ -609,6 +609,9 @@ namespace Altar
case SectionHeaders.Sounds:
chunkStringOffsetOffsets = SectionWriter.WriteSounds(chunk, f.Sound, stringOffsets, f.AudioGroups);
break;
case SectionHeaders.AudioGroup:
chunkStringOffsetOffsets = SectionWriter.WriteAudioGroups(chunk, f.AudioGroups, stringOffsets);
break;
case SectionHeaders.Sprites:
SectionWriter.WriteSprites(chunk, f.Sprites, stringOffsets, texPagOffsets,
out chunkStringOffsetOffsets, out chunkTexpOffsetOffsets);
......@@ -656,7 +659,7 @@ namespace Altar
break;
case SectionHeaders.Strings:
// for Textures chunk up next
SectionWriter.Pad(stringsChunk, 0x100, writer.Buffer.Position + 8);
SectionWriter.Pad(stringsChunk, 0x80, writer.Buffer.Position + 8);
chunk = stringsChunk;
stringsChunkPosition = writer.Buffer.Position + 12;
break;
......
......@@ -149,6 +149,17 @@ namespace Altar.Repack
return r;
}
static RoomObjInst DeserializeRoomObjInst(JsonData j)
{
return new RoomObjInst
{
Index = (uint)j["index"],
Instances = DeserializeArray(j["instances"], i => (uint)i),
ObjName = (string)j["obj"],
Unk2 = (uint)j["unk2"]
};
}
static RoomView DeserializeRoomView(JsonData j, ObjectInfo[] objs)
{
var r = new RoomView
......@@ -288,7 +299,9 @@ namespace Altar.Repack
Bounding = DeserializeBBox2(j["bounding"]),
Origin = DeserializePoint(j["origin"]),
TextureIndices = j.Has("textures") ? DeserializeArray(j["textures"], (Func<dynamic, uint>)(jd => (uint)jd)) : null,
CollisionMasks = j.Has("colmasks") ? DeserializeArray(j["colmasks"], (Func<JsonData, bool[,]>)DeserializeColMask) : null
CollisionMasks = j.Has("colmasks") ? DeserializeArray(j["colmasks"], (Func<JsonData, bool[,]>)DeserializeColMask) : null,
Version = j.Has("unknown1") ? 2 : 1,
UnknownFloat = j.Has("unknown1") ? (float)j["unknown1"] : 0.0f
};
#endregion
#region public static BackgroundInfo DeserializeBg (JsonData j)
......@@ -373,7 +386,8 @@ namespace Altar.Repack
Backgrounds = DeserializeArray(j["bgs"], (Func<dynamic, RoomBackground>)(d => DeserializeRoomBg(d, bgs))),
Views = DeserializeArray(j["views"], (Func<dynamic, RoomView>)(d => DeserializeRoomView(d, objs))),
Objects = DeserializeArray(j["objs"], (Func<dynamic, RoomObject>)(d => DeserializeRoomObj(d, objs))),
Tiles = DeserializeArray(j["tiles"], (Func<dynamic, RoomTile>)(d => DeserializeRoomTile(d, bgs)))
Tiles = DeserializeArray(j["tiles"], (Func<dynamic, RoomTile>)(d => DeserializeRoomTile(d, bgs))),
ObjInst = j.Has("objinst") ? DeserializeArray(j["objinst"], DeserializeRoomObjInst) : null
};
#endregion
#region public static TexturePageInfo DeserializeTPag(JsonData j)
......@@ -400,7 +414,7 @@ namespace Altar.Repack
FirstOffset = j.Has("firstoffset") ? (uint)j["firstoffset"] : 0xFFFFFFFF,
HasExtra = j.Has("instancetype") || j.Has("unknown"),
InstanceType = j.Has("instancetype") ? (InstanceType)(int)j["instancetype"] : InstanceType.StackTopOrGlobal,
unknown2 = j.Has("unknown") ? (uint)j["unknown"] : 0
unknown2 = j.Has("unknown") ? (int)j["unknown"] : 0
};
private static CodeInfo DeserializeCodeFromFile(string filename, uint bcv,
......@@ -421,21 +435,10 @@ namespace Altar.Repack
{
throw new InvalidDataException("Unknown code format for '" + filename + "'");
}
return DeserializeAssembly(instructions, bcv,
return DeserializeAssembly(Path.GetFileNameWithoutExtension(filename), instructions, bcv,
stringIndices, objectIndices);
}
private static void AddReference(IDictionary<Tuple<string, InstanceType>, IList<uint>> references, Tuple<string, InstanceType> name, uint index)
{
IList<uint> reflist;
if (!references.TryGetValue(name, out reflist))
{
reflist = new List<uint>(1);
references[name] = reflist;
}
reflist.Add(index);
}
private static InstanceType GetInstanceType(InstanceType instanceType, string objName, IDictionary<string, uint> objectIndices)
{
if (instanceType <= 0)
......@@ -452,11 +455,11 @@ namespace Altar.Repack
}
}
private static CodeInfo DeserializeAssembly(IEnumerable<Instruction> instructions, uint bcv,
private static CodeInfo DeserializeAssembly(string name, IEnumerable<Instruction> instructions, uint bcv,
IDictionary<string, uint> stringIndices, IDictionary<string, uint> objectIndices)
{
IDictionary<Tuple<string, InstanceType>, IList<uint>> functionReferences = new Dictionary<Tuple<string, InstanceType>, IList<uint>>();
IDictionary<Tuple<string, InstanceType>, IList<uint>> variableReferences = new Dictionary<Tuple<string, InstanceType>, IList<uint>>();
IList<Tuple<ReferenceSignature, uint>> functionReferences = new List<Tuple<ReferenceSignature, uint>>();
IList<Tuple<ReferenceSignature, uint>> variableReferences = new List<Tuple<ReferenceSignature, uint>>();
var binaryInstructions = new List<AnyInstruction>();
uint size = 0;
......@@ -480,8 +483,12 @@ namespace Altar.Repack
OpCode = op,
Types = new TypePair(setinst.Type1, setinst.Type2)
};
AddReference(variableReferences, new Tuple<string, InstanceType>(setinst.TargetVariable,
setinst.InstanceType), size);
variableReferences.Add(new Tuple<ReferenceSignature, uint>(new ReferenceSignature
{
Name = setinst.TargetVariable,
InstanceType = setinst.InstanceType,
Instance = setinst.InstanceType == InstanceType.Local ? name : null
}, size));
break;
case InstructionKind.Push:
var bp = new PushInstruction
......@@ -494,8 +501,12 @@ namespace Altar.Repack
var p = (PushVariable)inst;
bp.Value = (short)GetInstanceType(p.InstanceType, p.InstanceName, objectIndices);
bp.ValueRest = new Reference(p.VariableType, 0).val;
AddReference(variableReferences, new Tuple<string, InstanceType>(p.VariableName,
p.InstanceType), size);
variableReferences.Add(new Tuple<ReferenceSignature, uint>(new ReferenceSignature
{
Name = p.VariableName,
InstanceType = p.InstanceType,
Instance = p.InstanceType == InstanceType.Local ? name : null
}, size));
}
else
{
......@@ -532,7 +543,11 @@ namespace Altar.Repack
OpCode = op,
ReturnType = callinst.ReturnType
};
AddReference(functionReferences, new Tuple<string, InstanceType>(callinst.FunctionName, InstanceType.StackTopOrGlobal), size);
functionReferences.Add(new Tuple<ReferenceSignature, uint>(new ReferenceSignature
{
Name = callinst.FunctionName,
InstanceType = InstanceType.StackTopOrGlobal
}, size));
break;
case InstructionKind.Break:
var breakinst = (Break)inst;
......
This diff is collapsed.
......@@ -14,9 +14,23 @@ namespace Altar
public uint FirstOffset;
public bool HasExtra;
public InstanceType InstanceType;
public uint unknown2;
public int unknown2;
}
[StructLayout(LayoutKind.Sequential)]
public struct ReferenceSignature
{
public string Name;
public InstanceType InstanceType;
public string Instance;
public ReferenceSignature(ReferenceDef r)
{
Name = r.Name;
InstanceType = r.InstanceType;
Instance = null;
}
public override string ToString() => Name;
}
// ---
[StructLayout(LayoutKind.Sequential)]
......@@ -80,6 +94,8 @@ namespace Altar
public uint BBoxMode;
public bool SeparateColMasks;
public Point Origin;
public int Version;
public float UnknownFloat;
public uint[] TextureIndices;
public bool[][,] CollisionMasks;
......@@ -170,6 +186,7 @@ namespace Altar
public RoomView [] Views ;
public RoomObject [] Objects ;
public RoomTile [] Tiles ;
public RoomObjInst [] ObjInst ;
}
[StructLayout(LayoutKind.Sequential)]
public struct TexturePageInfo
......@@ -187,8 +204,8 @@ namespace Altar
public int Size;
internal AnyInstruction[] InstructionsCopy; // I ain't dealin' with no pointers
// (TODO: don't use pointers)
internal IDictionary<Tuple<string, InstanceType>, IList<uint>> functionReferences;
internal IDictionary<Tuple<string, InstanceType>, IList<uint>> variableReferences;
internal IList<Tuple<ReferenceSignature, uint>> functionReferences;
internal IList<Tuple<ReferenceSignature, uint>> variableReferences;
}
[StructLayout(LayoutKind.Sequential)]
public struct TextureInfo
......@@ -248,6 +265,14 @@ namespace Altar
public PointF Scale;
public Colour Colour;
}
[StructLayout(LayoutKind.Sequential)]
public struct RoomObjInst
{
public string ObjName;
public uint Index;
public uint Unk2;
public uint[] Instances;
}
public enum FontAntiAliasing : byte
{
......
......@@ -48,7 +48,7 @@ namespace Altar.Unpack
{
if (off == 0 || (off & 0xFFFFFF00) == 0xFFFFFF00 /* avoid crashes due
to bogus offsets */)
return String.Empty;
return null;
return ReadString((byte*)GMFile.PtrFromOffset(content, off-4));
}
......@@ -147,6 +147,20 @@ namespace Altar.Unpack
return t;
}
static RoomObjInst ReadRoomObjInst(GMFileContent content, IntPtr p)
{
var entry = (RoomObjInstEntry*)p;
var oi = new RoomObjInst();
oi.Index = entry->Index;
oi.ObjName = StringFromOffset(content, entry->Name);
oi.Unk2 = entry->Unk2;
oi.Instances = new uint[entry->InstCount];
for (uint i = 0; i < oi.Instances.Length; i++)
{
oi.Instances[i] = (&entry->Instances)[i];
}
return oi;
}
public static GeneralInfo GetGeneralInfo(GMFileContent content)
{
......@@ -262,6 +276,7 @@ namespace Altar.Unpack
ret.Bounding = se->Bounding;
ret.BBoxMode = se->BBoxMode;
ret.Origin = se->Origin ;
ret.Version = 1;
ret.SeparateColMasks = se->SeparateColMasks.IsTrue();
......@@ -270,6 +285,8 @@ namespace Altar.Unpack
{
var se2 = (SpriteEntry2*)GMFile.PtrFromOffset(content, (&content.Sprites->Offsets)[id]);
tex = &se2->Textures;
ret.Version = 2;
ret.UnknownFloat = se2->funk;
}
if (tex->Count == ~(uint)0)
{
......@@ -541,6 +558,16 @@ namespace Altar.Unpack
ret.Objects = ReadList(content, (CountOffsetsPair*)GMFile.PtrFromOffset(content, re->ObjOffset ), ReadRoomObj );
ret.Tiles = ReadList(content, (CountOffsetsPair*)GMFile.PtrFromOffset(content, re->TileOffset), ReadRoomTile);
if (re->BgOffset != (&content.Rooms->Offsets)[id]+sizeof(RoomEntry))
{
// heuristic to find instance data
uint instanceListOffset = *(uint*)GMFile.PtrFromOffset(content, (&content.Rooms->Offsets)[id]+sizeof(RoomEntry));
if (instanceListOffset > (&content.Rooms->Offsets)[id] && (instanceListOffset&0xFF000000) != 0xFF000000)
{
ret.ObjInst = ReadList(content, (CountOffsetsPair*)GMFile.PtrFromOffset(content, instanceListOffset), ReadRoomObjInst);
}
}
return ret;
}
public static TexturePageInfo GetTexPageInfo(GMFileContent content, uint id)
......@@ -622,9 +649,8 @@ namespace Altar.Unpack
throw new ArgumentOutOfRangeException(nameof(id));
var ag = GMFile.PtrFromOffset(content, (&content.AudioGroup->Offsets)[id]);
ag = GMFile.PtrFromOffset(content, *(uint*)ag);
return ReadString((byte*)ag); // it's just a name
return StringFromOffset(content, *(uint*)ag); // it's just a name
}
public static byte[][] ListToByteArrays(GMFileContent content, SectionCountOffsets* list, long elemLen = 0)
......
......@@ -227,6 +227,16 @@ namespace Altar.Unpack
return r;
}
static JsonData SerializeRoomObjInst(RoomObjInst oi)
{
var r = CreateObj();
r["obj" ] = oi.ObjName;
r["index" ] = oi.Index;
r["unk2" ] = oi.Unk2;
r["instances"] = SerializeArray(oi.Instances, Utils.Identity);
return r;
}
static JsonData SerializeColMask(bool[,] colMask)
{
var j = CreateObj();
......@@ -319,6 +329,10 @@ namespace Altar.Unpack
r["bboxmode"] = sprt.BBoxMode;
r["sepmasks"] = sprt.SeparateColMasks;
r["origin" ] = SerializePoint(sprt.Origin);
if (sprt.Version >= 2)
{
r["unknown1"] = sprt.UnknownFloat;
}
if (sprt.TextureIndices != null)
r["textures"] = SerializeArray(sprt.TextureIndices, Utils.Identity);
......@@ -424,6 +438,7 @@ namespace Altar.Unpack
r["views"] = SerializeArray(room.Views , v => SerializeRoomView(v, objs));
r["objs" ] = SerializeArray(room.Objects , o => SerializeRoomObj (o, objs));
r["tiles"] = SerializeArray(room.Tiles , t => SerializeRoomTile(t, bgs ));
r["objinst"] = SerializeArray(room.ObjInst , i => SerializeRoomObjInst(i));
return r;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment