Example #1
0
        public static int[] WriteSounds(BBData data, SoundInfo[] sounds, StringsChunkBuilder strings, string[] audioGroups)
        {
            int[] offsets             = WriteList(data, sounds, (sounddata, sound) => WriteSound(sounddata, sound, strings, audioGroups));
            var   stringOffsetOffsets = new List <int>();

            for (int i = 0; i < sounds.Length; i++)
            {
                if (sounds[i].Name != null)
                {
                    stringOffsetOffsets.Add(offsets[i] + (int)Marshal.OffsetOf(typeof(SoundEntry), "NameOffset") + 8);
                }
                if (sounds[i].Type != null)
                {
                    stringOffsetOffsets.Add(offsets[i] + (int)Marshal.OffsetOf(typeof(SoundEntry), "TypeOffset") + 8);
                }
                if (sounds[i].File != null)
                {
                    stringOffsetOffsets.Add(offsets[i] + (int)Marshal.OffsetOf(typeof(SoundEntry), "FileOffset") + 8);
                }
            }
            return(stringOffsetOffsets.ToArray());
        }
Example #2
0
        private static void WriteSprite(BBData data, SpriteInfo si, StringsChunkBuilder strings, int[] texPagOffsets)
        {
            var se = new SpriteEntry
            {
                Name     = strings.GetOffset(si.Name),
                Size     = si.Size,
                Bounding = si.Bounding,
                BBoxMode = si.BBoxMode,
                Origin   = si.Origin,

                SeparateColMasks = si.SeparateColMasks ? DwordBool.True : DwordBool.False
            };

            var tmp = new BinBuffer();

            tmp.Write(se);
            data.Buffer.Write(tmp, 0, tmp.Size - 8, 0);

            if (si.Version >= 2)
            {
                var se2 = new SpriteEntry2();
                unsafe
                {
                    se2._pad2[0] = -1;
                    se2._pad2[1] = 1;
                    se2._pad2[2] = 0;
                }
                se2.funk = si.UnknownFloat;
                tmp      = new BinBuffer();
                tmp.Write(se2);
                data.Buffer.Write(tmp, 0, 0x14, 0x38);
            }

            if (si.TextureIndices == null)
            {
                data.Buffer.Write(0xFFFFFFFF);
            }
            else
            {
                data.Buffer.Write(si.TextureIndices.Length);
                foreach (var ti in si.TextureIndices)
                {
                    data.Buffer.Write(texPagOffsets[ti]);
                }

                if (si.CollisionMasks == null)
                {
                    data.Buffer.Write(0xFFFFFFFF);
                }
                else
                {
                    data.Buffer.Write((uint)si.CollisionMasks.Length);
                    foreach (var mask in si.CollisionMasks)
                    {
                        int w = mask.GetLength(0);
                        for (int y = 0; y < mask.GetLength(1); y++)
                        {
                            for (int x = 0; x < w; x += 8)
                            {
                                byte b = 0;
                                if (x < w && mask[x, y])
                                {
                                    b |= 0b00000001;
                                }
                                if (x + 1 < w && mask[x + 1, y])
                                {
                                    b |= 0b00000010;
                                }
                                if (x + 2 < w && mask[x + 2, y])
                                {
                                    b |= 0b00000100;
                                }
                                if (x + 3 < w && mask[x + 3, y])
                                {
                                    b |= 0b00001000;
                                }
                                if (x + 4 < w && mask[x + 4, y])
                                {
                                    b |= 0b00010000;
                                }
                                if (x + 5 < w && mask[x + 5, y])
                                {
                                    b |= 0b00100000;
                                }
                                if (x + 6 < w && mask[x + 6, y])
                                {
                                    b |= 0b01000000;
                                }
                                if (x + 7 < w && mask[x + 7, y])
                                {
                                    b |= 0b10000000;
                                }
                                data.Buffer.Write(b);
                            }
                        }
                    }
                }
            }
            Pad(data, 4, 0);
        }
Example #3
0
        private static void WriteObject(BBData data, ObjectInfo oi, StringsChunkBuilder strings)
        {
            var oe = new ObjectEntry
            {
                Name        = strings.GetOffset(oi.Name),
                SpriteIndex = oi.SpriteIndex,
                Visible     = oi.IsVisible ? DwordBool.True : DwordBool.False,
                Solid       = oi.IsSolid ? DwordBool.True : DwordBool.False,
                Depth       = oi.Depth,
                Persistent  = oi.IsPersistent ? DwordBool.True : DwordBool.False,

                ParentId = oi.ParentId == null ? -100 : (int)oi.ParentId,
                MaskId   = oi.TexMaskId == null ? -1 : (int)oi.TexMaskId,

                HasPhysics     = oi.Physics != null ? DwordBool.True : DwordBool.False,
                IsSensor       = oi.IsSensor ? DwordBool.True : DwordBool.False,
                CollisionShape = oi.CollisionShape
            };

            oe.Physics = oi.Physics ?? new ObjectPhysics
            {
                Density        = 0.5f,
                Restitution    = 0.1f,
                Group          = 0,
                LinearDamping  = 0.1f,
                AngularDamping = 0.1f,
                Unknown0       = 0,
                Friction       = 0.2f,
                Unknown1       = 1,
                Kinematic      = 0
            };

            for (int i = 0; i < oi.OtherFloats.Length; i++)
            {
                unsafe
                {
                    oe.Rest.MoreFloats[i] = oi.OtherFloats[i];
                }
            }

            var hasMore = oi.OtherFloats.Length > 0;

            if (hasMore)
            {
                BinBuffer tmp = new BinBuffer();
                tmp.Write(oe);
                data.Buffer.Write(tmp.AsByteArray(), 0, (int)Marshal.OffsetOf(typeof(ObjectEntry), "Rest") + (int)Marshal.OffsetOf(typeof(ObjectRest), "ShapePoints_IfMoreFloats"));
            }
            else
            {
                BinBuffer tmp = new BinBuffer();
                tmp.Write(oe);
                data.Buffer.Write(tmp.AsByteArray(), 0, (int)Marshal.OffsetOf(typeof(ObjectEntry), "Rest") + (int)Marshal.OffsetOf(typeof(ObjectRest), "ShapePoints"));
            }
            WriteList(data, oi.ShapePoints, (shapePointData, shapePoint) =>
                      WriteList(shapePointData, shapePoint, (pointPointData, pointPoint) =>
            {
                pointPointData.Buffer.Write(pointPoint[0]);
                pointPointData.Buffer.Write(pointPoint[1]); // probably count
                pointPointData.OffsetOffsets = new int[] { pointPointData.Buffer.Position };
                pointPointData.Buffer.Write(12);            // probably offset
                for (int i = 3; i < pointPoint.Length; i++)
                {
                    pointPointData.Buffer.Write(pointPoint[i]);
                }
            })
                      );
        }
Example #4
0
        public static int[] WriteGeneral(BBData data, GeneralInfo ge, RoomInfo[] rooms, StringsChunkBuilder strings)
        {
            var ret = new SectionGeneral
            {
                Debug             = ge.IsDebug,
                FilenameOffset    = strings.GetOffset(ge.FileName),
                ConfigOffset      = strings.GetOffset(ge.Configuration),
                NameOffset        = strings.GetOffset(ge.Name),
                DisplayNameOffset = strings.GetOffset(ge.DisplayName),
                GameID            = ge.GameID,
                WindowSize        = ge.WindowSize,
                BytecodeVersion   = (Int24)ge.BytecodeVersion,
                Major             = ge.Version.Major,
                Minor             = ge.Version.Minor,
                Release           = ge.Version.Build,
                Build             = ge.Version.Revision,

                Info          = ge.InfoFlags,
                ActiveTargets = ge.ActiveTargets,
                AppID         = ge.SteamAppID,

                LastObj  = 0,
                LastTile = 0
            };
            var stringOffsetOffsets = new int[]
            {
                (int)Marshal.OffsetOf(typeof(SectionGeneral), "FilenameOffset") - 3,
                (int)Marshal.OffsetOf(typeof(SectionGeneral), "ConfigOffset") - 3,
                (int)Marshal.OffsetOf(typeof(SectionGeneral), "NameOffset") - 3,
                (int)Marshal.OffsetOf(typeof(SectionGeneral), "DisplayNameOffset") - 3
            };

            foreach (var room in rooms)
            {
                foreach (var obj in room.Objects)
                {
                    if (obj.InstanceID > ret.LastObj)
                    {
                        ret.LastObj = obj.InstanceID;
                    }
                }
                foreach (var tile in room.Tiles)
                {
                    if (tile.InstanceID > ret.LastTile)
                    {
                        ret.LastTile = tile.InstanceID;
                    }
                }
            }
            ret.LastObj++;
            ret.LastTile++;

            for (int i = 0; i < 4; i++)
            {
                unsafe
                {
                    ret._unknown[i] = ge.unknown[i];
                }
            }

            unsafe
            {
                Marshal.Copy(ge.LicenseMD5Hash, 0, (IntPtr)ret.MD5, 0x10);
            }

            ret.CRC32 = ge.LicenceCRC32;

            ret.Timestamp = (ulong)(ge.Timestamp.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

            if (ge.WeirdNumbers == null)
            {
                ret.NumberCount = 0;
            }
            else
            {
                ret.NumberCount = (uint)ge.WeirdNumbers.Length;
            }

            var tmp = new BinBuffer();

            tmp.Write(ret);
            data.Buffer.Write(tmp, 0, tmp.Size - 12, 8);

            for (int i = 0; i < ret.NumberCount; i++)
            {
                data.Buffer.Write(ge.WeirdNumbers[i]);
            }

            // TODO for 2.0: some lengthy checksum/hash at the end?
            // exits after launch if GEN8 is modified at all,
            // doesn't launch if the extra stuff is missing
            //for (int i = 0; i < 16; i++)
            //    data.Buffer.Write(0x3F3F3F3F);

            return(stringOffsetOffsets);
        }
Example #5
0
 public static int[] WriteList <T>(BBData data, T[] things,
                                   Action <BBData, T, StringsChunkBuilder, int[]> writeThing,
                                   StringsChunkBuilder strings, int[] texPagOffsets)
 {
     return(WriteList(data, things, (thingdata, thing) => writeThing(thingdata, thing, strings, texPagOffsets)));
 }
Example #6
0
        public static int[] WriteFunctionLocals(BBData data, FunctionLocalsInfo[] functions, StringsChunkBuilder strings)
        {
            var stringOffsetOffsets = new List <int>();

            data.Buffer.Write(functions.Length);

            foreach (var func in functions)
            {
                data.Buffer.Write((uint)func.LocalNames.Length);
                stringOffsetOffsets.Add(data.Buffer.Position + 8);
                data.Buffer.Write(strings.GetOffset(func.FunctionName));
                for (uint i = 0; i < func.LocalNames.Length; i++)
                {
                    stringOffsetOffsets.Add(data.Buffer.Position + 12);
                    data.Buffer.Write(new FunctionLocalEntry
                    {
                        Index = i,
                        Name  = strings.GetOffset(func.LocalNames[i])
                    });
                }
            }

            return(stringOffsetOffsets.ToArray());
        }
Example #7
0
        private static void WriteRoom(BBData data, RoomInfo ri, StringsChunkBuilder strings)
        {
            var re = new RoomEntry
            {
                Name       = strings.GetOffset(ri.Name),
                Caption    = ri.Caption == null ? 0 : strings.GetOffset(ri.Caption),
                Size       = ri.Size,
                Speed      = ri.Speed,
                Persistent = ri.IsPersistent ? DwordBool.True : DwordBool.False,
                Colour     = ri.Colour,

                DrawBackgroundColour = ri.DrawBackgroundColour ? DwordBool.True : DwordBool.False,
                _unknown             = ri._unknown,

                Flags = 0,

                World          = ri.World,
                Bounding       = ri.Bounding,
                Gravity        = ri.Gravity,
                MetresPerPixel = ri.MetresPerPixel
            };

            if (ri.EnableViews)
            {
                re.Flags |= RoomEntryFlags.EnableViews;
            }
            if (ri.ShowColour)
            {
                re.Flags |= RoomEntryFlags.ShowColour;
            }
            if (ri.ClearDisplayBuffer)
            {
                re.Flags |= RoomEntryFlags.ClearDisplayBuffer;
            }
            if (ri.UnknownFlag)
            {
                re.Flags |= RoomEntryFlags.Unknown;
            }

            var bgOffsetOffset      = (int)Marshal.OffsetOf(typeof(RoomEntry), "BgOffset");
            var viewOffsetOffset    = (int)Marshal.OffsetOf(typeof(RoomEntry), "ViewOffset");
            var objOffsetOffset     = (int)Marshal.OffsetOf(typeof(RoomEntry), "ObjOffset");
            var tileOffsetOffset    = (int)Marshal.OffsetOf(typeof(RoomEntry), "TileOffset");
            int objInstOffsetOffset = (int)Marshal.OffsetOf(typeof(RoomEntry), "MetresPerPixel") + 4;

            data.Buffer.Write(re);
            data.OffsetOffsets = new int[] { bgOffsetOffset, viewOffsetOffset, objOffsetOffset, tileOffsetOffset };

            if (ri.ObjInst != null)
            {
                data.Buffer.Write(0);
                data.OffsetOffsets = data.OffsetOffsets.Concat(new int[] { objInstOffsetOffset }).ToArray();
            }

            data.Buffer.Position = bgOffsetOffset;
            data.Buffer.Write(data.Buffer.Size);
            data.Buffer.Position = data.Buffer.Size;
            WriteList(data, ri.Backgrounds, WriteRoomBg);

            data.Buffer.Position = viewOffsetOffset;
            data.Buffer.Write(data.Buffer.Size);
            data.Buffer.Position = data.Buffer.Size;
            WriteList(data, ri.Views, WriteRoomView);

            data.Buffer.Position = objOffsetOffset;
            data.Buffer.Write(data.Buffer.Size);
            data.Buffer.Position = data.Buffer.Size;
            WriteList(data, ri.Objects, WriteRoomObj);

            data.Buffer.Position = tileOffsetOffset;
            data.Buffer.Write(data.Buffer.Size);
            data.Buffer.Position = data.Buffer.Size;
            WriteList(data, ri.Tiles, WriteRoomTile);

            if (ri.ObjInst != null)
            {
                data.Buffer.Position = objInstOffsetOffset;
                data.Buffer.Write(data.Buffer.Size);
                data.Buffer.Position = data.Buffer.Size;
                WriteList(data, ri.ObjInst, WriteRoomObjInst, strings);
            }

            // Unknown stuff for 2.0
            //for (int i = 0; i < 8; i++)
            //    data.Buffer.Write(0x3F3F3F3F);
        }