Пример #1
0
 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
     });
 }
Пример #2
0
 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
     });
 }
Пример #3
0
        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));
        }
Пример #4
0
        // 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;
            }));
        }
Пример #5
0
        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;
            }));
        }
Пример #6
0
        // 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 *)&section->Entries + elemOff * sizeof(uint); i < amount; rde += rdeSize, i++)
            {
                r[i] = iter((IntPtr)rde);
            }

            return(r);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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++;
                }
            }
        }