private static void WriteRefDef(BBData data, ReferenceDef rd, StringsChunkBuilder strings) { data.Buffer.Write(new RefDefEntry { NameOffset = strings.GetOffset(rd.Name), Occurrences = rd.Occurrences, FirstAddress = rd.FirstOffset }); }
private static void WriteRefDefWithOthers(BBData data, ReferenceDef rd, StringsChunkBuilder strings) { data.Buffer.Write(new RefDefEntryWithOthers { NameOffset = strings.GetOffset(rd.Name), InstanceType = (int)rd.InstanceType, _pad1 = rd.unknown2, Occurrences = rd.Occurrences, FirstAddress = rd.FirstOffset }); }
public static ReferenceDef[] GetRefDefsWithLength(GMFileContent content, SectionRefDefs *section) { return(GetRefDefsInternal(content, section, 1, section->Entries.NameOffset /* actually length, because reasons */, 12, p => { var rde = (RefDefEntry *)p; var ret = new ReferenceDef(); ret.Name = StringFromOffset(content, rde->NameOffset); ret.Occurrences = rde->Occurrences; ret.FirstOffset = rde->FirstAddress; return ret; }, false)); }
// FFS YoYo Games, WHY? #pragma warning disable CSE0003 // "Use expression-bodied members": too ugly with those lambdas public static ReferenceDef[] GetRefDefs(GMFileContent content, SectionRefDefs *section) { return(GetRefDefsInternal(content, section, 0, 0, 12 /* sizeof RefDefEntry */, p => { var rde = (RefDefEntry *)p; var ret = new ReferenceDef(); ret.Name = StringFromOffset(content, rde->NameOffset); ret.Occurrences = rde->Occurrences; ret.FirstOffset = rde->FirstAddress; return ret; })); }
public static ReferenceDef[] GetRefDefsWithOthers(GMFileContent content, SectionRefDefs *section) { return(GetRefDefsInternal(content, section, 3, 0, 20 /* sizeof RefDefEntryWithOthers */, p => { var rde = (RefDefEntryWithOthers *)p; // they really are doing a Redigit here (well, this AND the DwordBools (instead of 1-byte bools or bit flags)) var ret = new ReferenceDef(); ret.Name = StringFromOffset(content, rde->NameOffset); ret.Occurrences = rde->Occurrences; ret.FirstOffset = rde->FirstAddress; return ret; })); }
// C# doesn't like pointers of generic types... static ReferenceDef[] GetRefDefsInternal(GMFileContent content, SectionRefDefs *section, long elemOff, uint amount, uint rdeSize, Func <IntPtr, ReferenceDef> iter) { amount = amount == 0 ? section->Header.Size / rdeSize : amount; var r = new ReferenceDef[amount]; uint i = 0; for (var rde = (byte *)§ion->Entries + elemOff * sizeof(uint); i < amount; rde += rdeSize, i++) { r[i] = iter((IntPtr)rde); } return(r); }
private static JsonData SerializeReferenceDef(ReferenceDef rd) { if (!rd.HasExtra) { return(new JsonData(rd.Name)); } var r = CreateObj(); r["name"] = rd.Name; //r["occurrences"] = rd.Occurrences; //r["type"] = rd.VariableType.ToString(); //if (rd.FirstOffset != 0xFFFFFFFF) // r["firstoffset"] = rd.FirstOffset; if (rd.HasExtra) { r["instancetype"] = (int)rd.InstanceType; r["unknown"] = rd.unknown2; } return(r); }
public static GMFile /* errors: different return type? */ ReadFile(string baseDir, JsonData projFile) { var f = new GMFile(); // OBJT: depends on SPRT, obj<->id map // ROOM: depends on OBJT, BGND // SCPT: depends on CODE if (projFile.Has("chunkorder") && projFile["chunkorder"].IsArray) { f.ChunkOrder = DeserializeArray(projFile["chunkorder"], jd => SectionHeadersExtensions.FromChunkName((string)jd)); } else { Console.Error.WriteLine("Warning: Project file doesn't have a chunk order. You should export with a newer Altar.NET version."); f.ChunkOrder = new SectionHeaders[] { SectionHeaders.General, SectionHeaders.Options, SectionHeaders.Language, SectionHeaders.Extensions, SectionHeaders.Sounds, SectionHeaders.AudioGroup, SectionHeaders.Sprites, SectionHeaders.Backgrounds, SectionHeaders.Paths, SectionHeaders.Scripts, SectionHeaders.Globals, SectionHeaders.Shaders, SectionHeaders.Fonts, SectionHeaders.Timelines, SectionHeaders.Objects, SectionHeaders.Rooms, SectionHeaders.DataFiles, SectionHeaders.TexturePage, SectionHeaders.Code, SectionHeaders.Variables, SectionHeaders.Functions, SectionHeaders.Strings, SectionHeaders.Textures, SectionHeaders.Audio, SectionHeaders.EmbedImage, }; } if (projFile.Has("general")) { Console.WriteLine("Loading general..."); try { f.General = DeserializeGeneral(LoadJson(baseDir, (string)(projFile["general"]))); if (f.General.Version >= new Version(2, 0)) { Console.Error.WriteLine("Warning: GM:S 2.0 support is incomplete!"); } } catch (Exception) { Console.Error.WriteLine("Error loading general"); throw; } } if (projFile.Has("options")) { Console.WriteLine("Loading options..."); try { f.Options = DeserializeOptions(LoadJson(baseDir, (string)(projFile["options"]))); } catch (Exception) { Console.Error.WriteLine("Error loading options"); throw; } } if (projFile.Has("strings")) { Console.WriteLine("Loading strings..."); try { f.Strings = DeserializeArray(LoadJson(baseDir, (string)(projFile["strings"])), jd => (string)jd); } catch (Exception) { Console.Error.WriteLine("Error loading strings"); throw; } } var variables = new ReferenceDef[0]; var functions = new ReferenceDef[0]; if (projFile.Has("variables")) { Console.WriteLine("Loading variables..."); try { var vardata = LoadJson(baseDir, (string)(projFile["variables"])); variables = DeserializeArray(vardata.IsArray ? vardata : vardata["variables"], DeserializeReferenceDef); if (vardata.Has("extra")) { f.VariableExtra = DeserializeArray(vardata["extra"], jd => (uint)jd); } } catch (Exception) { Console.Error.WriteLine("Error loading variables"); throw; } } if (projFile.Has("functions")) { Console.WriteLine("Loading functions..."); try { var funcdata = LoadJson(baseDir, (string)(projFile["functions"])); functions = DeserializeArray(funcdata.IsArray ? funcdata : funcdata["functions"], DeserializeReferenceDef); if (funcdata.Has("locals")) { f.FunctionLocals = DeserializeArray(funcdata["locals"], DeserializeFuncLocals); } } catch (Exception) { Console.Error.WriteLine("Error loading functions"); throw; } } f.RefData = new RefData { Variables = variables, Functions = functions }; if (projFile.Has("textures")) { Console.WriteLine("Loading textures..."); var textures = projFile["textures"].ToArray(); var ts = new TextureInfo[textures.Length]; for (int i = 0; i < textures.Length; i++) { try { var texinfo = new TextureInfo { PngData = File.ReadAllBytes(Path.Combine(baseDir, (string)(textures[i]))) }; var bp = new UniquePtr(texinfo.PngData); unsafe { var png = (PngHeader *)bp.BPtr; texinfo.Width = Utils.SwapEnd32(png->IHDR.Width); texinfo.Height = Utils.SwapEnd32(png->IHDR.Height); } ts[i] = texinfo; } catch (Exception) { Console.Error.WriteLine($"Error loading {textures[i]}"); throw; } } f.Textures = ts; } if (projFile.Has("tpags")) { Console.Write("Loading texture pages... "); var cl = Console.CursorLeft; var ct = Console.CursorTop; var tpags = projFile["tpags"].ToArray(); var tps = new TexturePageInfo[tpags.Length]; for (int i = 0; i < tpags.Length; i++) { Console.SetCursorPosition(cl, ct); Console.WriteLine(O_PAREN + (i + 1) + SLASH + tpags.Length + C_PAREN); try { tps[i] = DeserializeTPag(LoadJson(baseDir, (string)(tpags[i]))); } catch (Exception) { Console.Error.WriteLine($"Error loading {tpags[i]}"); throw; } } f.TexturePages = tps; } if (projFile.Has("audio")) { Console.WriteLine("Loading audio..."); var audio = projFile["audio"].ToArray(); var ais = new AudioInfo[audio.Length]; for (int i = 0; i < audio.Length; i++) { try { var audioinfo = new AudioInfo { Wave = File.ReadAllBytes(Path.Combine(baseDir, (string)(audio[i]))) }; ais[i] = audioinfo; } catch (Exception) { Console.Error.WriteLine($"Error loading {audio[i]}"); throw; } } f.Audio = ais; } if (projFile.Has("sprites")) { Console.Write("Loading sprites... "); var cl = Console.CursorLeft; var ct = Console.CursorTop; var sprites = projFile["sprites"].ToArray(); var ss = new SpriteInfo[sprites.Length]; for (int i = 0; i < sprites.Length; i++) { Console.SetCursorPosition(cl, ct); Console.WriteLine(O_PAREN + (i + 1) + SLASH + sprites.Length + C_PAREN); try { ss[i] = DeserializeSprite(LoadJson(baseDir, (string)(sprites[i]))); ss[i].Name = Path.GetFileNameWithoutExtension((string)(sprites[i])); } catch (Exception) { Console.Error.WriteLine($"Error loading {sprites[i]}"); throw; } } f.Sprites = ss; } if (projFile.Has("objs")) { Console.Write("Loading objects... "); var cl = Console.CursorLeft; var ct = Console.CursorTop; var objs = projFile["objs"].ToArray(); var objNames = objs.Select(o => Path.GetFileNameWithoutExtension((string)o)).ToArray(); var os = new ObjectInfo[objs.Length]; for (int i = 0; i < objs.Length; i++) { Console.SetCursorPosition(cl, ct); Console.WriteLine(O_PAREN + (i + 1) + SLASH + objs.Length + C_PAREN); try { os[i] = DeserializeObj( LoadJson(baseDir, (string)(objs[i])), f.Sprites, s => (uint)Array.IndexOf(objNames, s)); os[i].Name = objNames[i]; } catch (Exception) { Console.Error.WriteLine($"Error loading {objs[i]}"); throw; } } f.Objects = os; } if (projFile.Has("code")) { Console.WriteLine("Loading code..."); var code = projFile["code"].ToArray(); var cs = new CodeInfo[code.Length]; var strings = new StringsListBuilder(); strings.AddStrings(f.Strings); IDictionary <string, uint> objectIndices = new Dictionary <string, uint>(f.Objects.Length); for (uint i = 0; i < f.Objects.Length; i++) { objectIndices[f.Objects[i].Name] = i; } for (int i = 0; i < code.Length; i++) { Console.WriteLine((string)(code[i])); try { cs[i] = Assembler.DeserializeCodeFromFile(Path.Combine(baseDir, (string)(code[i])), f.General.BytecodeVersion, strings, objectIndices); cs[i].Name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension((string)(code[i]))); cs[i].ArgumentCount = 1; if (f.FunctionLocals != null) { for (int j = 0; j < f.FunctionLocals.Length; j++) { int fastIndex = (j + i) % f.FunctionLocals.Length; if (f.FunctionLocals[fastIndex].FunctionName == cs[i].Name) { cs[i].ArgumentCount = f.FunctionLocals[fastIndex].LocalNames.Length; break; } } } } catch (Exception) { Console.Error.WriteLine($"Error loading {code[i]}"); throw; } } f.Code = cs; f.Strings = strings.GetStrings(); } if (projFile.Has("sounds")) { Console.WriteLine("Loading sounds..."); var sounds = projFile["sounds"].ToArray(); var ss = new SoundInfo[sounds.Length]; for (int i = 0; i < sounds.Length; i++) { try { ss[i] = DeserializeSound(LoadJson(baseDir, (string)(sounds[i]))); ss[i].Name = Path.GetFileNameWithoutExtension((string)(sounds[i])); } catch (Exception) { Console.Error.WriteLine($"Error loading {sounds[i]}"); throw; } } f.Sound = ss; } if (projFile.Has("bg")) { Console.WriteLine("Loading backgrounds..."); var bg = projFile["bg"].ToArray(); var bs = new BackgroundInfo[bg.Length]; for (int i = 0; i < bg.Length; i++) { try { bs[i] = DeserializeBg(LoadJson(baseDir, (string)(bg[i]))); bs[i].Name = Path.GetFileNameWithoutExtension((string)(bg[i])); } catch (Exception) { Console.Error.WriteLine($"Error loading {bg[i]}"); throw; } } f.Backgrounds = bs; } if (projFile.Has("paths")) { Console.WriteLine("Loading paths..."); var paths = projFile["paths"].ToArray(); var ps = new PathInfo[paths.Length]; for (int i = 0; i < paths.Length; i++) { try { ps[i] = DeserializePath(LoadJson(baseDir, (string)(paths[i]))); ps[i].Name = Path.GetFileNameWithoutExtension((string)(paths[i])); } catch (Exception) { Console.Error.WriteLine($"Error loading {paths[i]}"); throw; } } f.Paths = ps; } if (projFile.Has("scripts")) { Console.WriteLine("Loading scripts..."); var scripts = projFile["scripts"].ToArray(); var ss = new ScriptInfo[scripts.Length]; for (int i = 0; i < scripts.Length; i++) { try { ss[i] = DeserializeScript(LoadJson(baseDir, (string)(scripts[i])), f.Code); ss[i].Name = Path.GetFileNameWithoutExtension((string)(scripts[i])); } catch (Exception) { Console.Error.WriteLine($"Error loading {scripts[i]}"); throw; } } f.Scripts = ss; } if (projFile.Has("fonts")) { Console.WriteLine("Loading fonts..."); var fonts = projFile["fonts"].ToArray(); var fs = new FontInfo[fonts.Length]; for (int i = 0; i < fonts.Length; i++) { try { fs[i] = DeserializeFont(LoadJson(baseDir, (string)(fonts[i]))); fs[i].CodeName = Path.GetFileNameWithoutExtension((string)(fonts[i])); } catch (Exception) { Console.Error.WriteLine($"Error loading {fonts[i]}"); throw; } } f.Fonts = fs; } if (projFile.Has("rooms")) { Console.Write("Loading rooms... "); var cl = Console.CursorLeft; var ct = Console.CursorTop; var rooms = projFile["rooms"].ToArray(); var rs = new RoomInfo[rooms.Length]; for (int i = 0; i < rooms.Length; i++) { Console.SetCursorPosition(cl, ct); Console.WriteLine(O_PAREN + (i + 1) + SLASH + rooms.Length + C_PAREN); try { rs[i] = DeserializeRoom(LoadJson(baseDir, (string)(rooms[i])), f.Backgrounds, f.Objects); rs[i].Name = Path.GetFileNameWithoutExtension((string)(rooms[i])); } catch (Exception) { Console.Error.WriteLine($"Error loading {rooms[i]}"); throw; } } f.Rooms = rs; } if (projFile.Has("audiogroups")) { Console.WriteLine("Loading audio groups..."); try { f.AudioGroups = DeserializeArray(LoadJson(baseDir, (string)(projFile["audiogroups"])), jd => (string)jd); } catch (Exception) { Console.Error.WriteLine("Error loading audio groups"); throw; } } if (projFile.Has("shaders")) { Console.WriteLine("Loading shaders..."); var shaders = projFile["shaders"].ToArray(); var ss = new ShaderInfo[shaders.Length]; for (int i = 0; i < shaders.Length; i++) { try { ss[i] = DeserializeShader(LoadJson(baseDir, (string)(shaders[i]))); ss[i].Name = Path.GetFileNameWithoutExtension((string)(shaders[i])); } catch (Exception) { Console.Error.WriteLine($"Error loading {shaders[i]}"); throw; } } f.Shaders = ss; } return(f); }
public static void ResolveReferenceOffsets(BBData data, IList <Tuple <ReferenceSignature, uint> > references, StringsChunkBuilder strings, bool extended, out IList <ReferenceDef> startOffsetsAndCounts) { startOffsetsAndCounts = new List <ReferenceDef>(); int localCount = 0; int nonLocalCount = 0; for (int i = 0; i < references.Count; i++) { Tuple <ReferenceSignature, uint> last = references[i]; uint diff; uint existing; uint count = 0; var targetRef = references[i].Item1; var start = references[i].Item2; if (targetRef.InstanceType >= InstanceType.StackTopOrGlobal && extended && targetRef.VariableIndex != -1) { for (InstanceType possibleInstanceType = InstanceType.Self; possibleInstanceType >= InstanceType.Local; possibleInstanceType--) { for (int j = i + 1; j < references.Count; j++) { if (references[j].Item1.Name == targetRef.Name && references[j].Item1.InstanceType == possibleInstanceType) { targetRef.InstanceType = references[j].Item1.InstanceType; targetRef.Instance = references[j].Item1.Instance; break; } } if (targetRef.InstanceType < InstanceType.StackTopOrGlobal) { break; } } if (targetRef.InstanceType >= InstanceType.StackTopOrGlobal) { targetRef.InstanceType = InstanceType.Self; // ?? } } if (targetRef.InstanceType == InstanceType.Local && targetRef.Name == "arguments") { //localCount = 0; } if (start != 0xFFFFFFFF) { count = 1; for (int j = i + 1; j < references.Count;) { if (references[j].Item1.Name == targetRef.Name && (!extended || (targetRef.VariableIndex != -1) || (references[j].Item1.InstanceType >= InstanceType.StackTopOrGlobal) || (references[j].Item1.InstanceType == targetRef.InstanceType && //references[j].Item1.VariableType == targetRef.VariableType && (references[j].Item1.InstanceType != InstanceType.Local || references[j].Item1.Instance == targetRef.Instance))) && ((targetRef.VariableIndex == -1) || (targetRef.VariableIndex == references[j].Item1.VariableIndex))) { diff = (references[j].Item2 - last.Item2) & 0xFFFFFF; data.Buffer.Position = (int)last.Item2 + 4; existing = data.Buffer.ReadUInt32(); data.Buffer.Write(diff | existing); last = references[j]; references.RemoveAt(j); count++; } else { j++; } } diff = strings.GetIndex(last.Item1.Name); data.Buffer.Position = (int)last.Item2 + 4; existing = data.Buffer.ReadUInt32(); data.Buffer.Write(diff | existing); } var def = new ReferenceDef { FirstOffset = start, HasExtra = extended, InstanceType = targetRef.InstanceType, Name = targetRef.Name, Occurrences = count, unknown2 = targetRef.InstanceType == InstanceType.Local ? localCount : targetRef.VariableType == VariableType.StackTop ? nonLocalCount : -6, VariableType = targetRef.VariableType }; if (targetRef.VariableIndex == -1) { startOffsetsAndCounts.Add(def); } else { while (startOffsetsAndCounts.Count <= targetRef.VariableIndex) { startOffsetsAndCounts.Add(new ReferenceDef()); } startOffsetsAndCounts[targetRef.VariableIndex] = def; } if (targetRef.InstanceType == InstanceType.Local) { localCount++; } else if (targetRef.VariableType == VariableType.StackTop) { nonLocalCount++; } } }