void ResetRoomObjects() { int j = 1; for (int i = 0; i < roomData.Objects.Count; i++) { for (; j < _objs.Length; j++) { if (_objs[j].FloatingObjectIndex == 0) break; } _objs[j] = roomData.Objects[i]; // HACK: This is done since an angle doesn't fit into a byte (360 > 256) _objs[j].ActorDir = Game.Version == 8 ? (byte)ScummMath.ToSimpleDir(true, roomData.Objects[i].ActorDir) : roomData.Objects[i].ActorDir; j++; } for (int i = j; i < _objs.Length; i++) { if (_objs[i].FloatingObjectIndex == 0) { _objs[i] = new ObjectData(); } } }
void ClearOwnerOf(int obj) { // Stop the associated object script code (else crashes might occurs) StopObjectScriptCore((ushort)obj); if (GetOwnerCore(obj) == OwnerRoom) { for (var i = 0; i < _objs.Length; i++) { if (_objs[i].Number == obj && (_objs[i].FloatingObjectIndex != 0)) { // Removing an flObject from a room means we can nuke it // _res->nukeResource(rtFlObject, _objs[i].fl_object_index); _objs[i] = new ObjectData(); } } } else { // Alternatively, scan the inventory to see if the object is in there... for (int i = 0; i < _resManager.NumInventory; i++) { if (_inventory[i] == obj) { // Found the object! Nuke it from the inventory. _inventory[i] = 0; // Now fill up the gap removing the object from the inventory created. for (i = 0; i < _resManager.NumInventory - 1; i++) { if (_inventory[i] == 0 && _inventory[i + 1] != 0) { _inventory[i] = _inventory[i + 1]; _invData[i] = _invData[i + 1]; _inventory[i + 1] = 0; // FIXME FIXME FIXME: This is incomplete, as we do not touch flags, status... BUG // TODO: //_res->_types[rtInventory][i]._address = _res->_types[rtInventory][i + 1]._address; //_res->_types[rtInventory][i]._size = _res->_types[rtInventory][i + 1]._size; //_res->_types[rtInventory][i + 1]._address = NULL; //_res->_types[rtInventory][i + 1]._size = 0; } } break; } } } }
protected bool LoadState(string path) { using (var file = ServiceLocator.FileStorage.OpenFileRead(path)) { var br = new BinaryReader(file); var hdr = LoadSaveGameHeader(br); var serializer = Serializer.CreateReader(br, hdr.Version); // Since version 56 we save additional information about the creation of // the save game and the save time. if (hdr.Version >= 56) { var infos = LoadInfos(br); if (infos == null) { //warning("Info section could not be found"); //delete in; return false; } //SetTotalPlayTime(infos.playtime * 1000); } //else //{ // start time counting //setTotalPlayTime(); //} // Due to a bug in scummvm up to and including 0.3.0, save games could be saved // in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here if (hdr.Version == 7) hdr.Version = 8; //_saveLoadDescription = hdr.name; // Unless specifically requested with _saveSound, we do not save the iMUSE // state for temporary state saves - such as certain cutscenes in DOTT, // FOA, Sam and Max, etc. // // Thus, we should probably not stop music when restoring from one of // these saves. This change stops the Mole Man theme from going quiet in // Sam & Max when Doug tells you about the Ball of Twine, as mentioned in // patch #886058. // // If we don't have iMUSE at all we may as well stop the sounds. The previous // default behavior here was to stopAllSounds on all state restores. if (IMuse == null || _saveSound || !_saveTemporaryState) Sound.StopAllSounds(); // Sound->stopCD(); Sound.PauseSounds(true); //closeRoom(); _inventory = new ushort[_inventory.Length]; _invData = new ObjectData[_invData.Length]; _newNames.Clear(); // Because old savegames won't fill the entire gfxUsageBits[] array, // clear it here just to be sure it won't hold any unforseen garbage. Gdi.ClearGfxUsageBits(); // Nuke all resources //for (ResType type = rtFirst; type <= rtLast; type = ResType(type + 1)) // if (type != rtTemp && type != rtBuffer && (type != rtSound || _saveSound || !compat)) // for (ResId idx = 0; idx < _res->_types[type].size(); idx++) // { // _res->nukeResource(type, idx); // } Array.Clear(_strings, 0, _strings.Length); ResetScummVars(); //if (_game.features & GF_OLD_BUNDLE) // loadCharset(0); // FIXME - HACK ? // // Now do the actual loading // SaveOrLoad(serializer); // Update volume settings // SyncSoundSettings(); if (Game.Version < 7) { Camera.LastPosition.X = Camera.CurrentPosition.X; } var sb = _screenB; var sh = _screenH; // Restore the virtual screens and force a fade to black. InitScreens(0, ScreenHeight); Gdi.Fill(MainVirtScreen.Surfaces[0].Pixels, MainVirtScreen.Pitch, 0, MainVirtScreen.Width, MainVirtScreen.Height); MainVirtScreen.SetDirtyRange(0, MainVirtScreen.Height); UpdateDirtyScreen(MainVirtScreen); //UpdatePalette(); _gfxManager.SetPalette(_currentPalette.Colors); InitScreens(sb, sh); _completeScreenRedraw = true; // Reset charset mask _charset.HasMask = false; ClearTextSurface(); ClearDrawObjectQueue(); _verbMouseOver = 0; CameraMoved(); Gdi.NumZBuffer = GetNumZBuffers(); Gdi.SetMaskHeight(roomData.Header.Height); if (VariableRoomFlag.HasValue) { Variables[VariableRoomFlag.Value] = 1; } // Sync with current config setting if (VariableVoiceMode.HasValue) { Variables[VariableVoiceMode.Value] = (int)VoiceMode.VoiceAndText; } Sound.PauseSounds(false); } return true; }
void LoadResource(BinaryReader reader, ResType type, ushort idx) { bool dynamic = false; switch (type) { case ResType.Inventory: case ResType.String: case ResType.Verb: case ResType.VerbImage: case ResType.ActorName: case ResType.ScaleTable: case ResType.Temp: case ResType.FlObject: case ResType.Matrix: case ResType.ObjectName: dynamic = true; break; } if (dynamic) { int size = reader.ReadInt32(); var ptr = reader.ReadBytes(size); //Console.WriteLine("Type: {0}, Index: {1}, Data: {2}", type, idx, size); switch (type) { case ResType.Inventory: { var index = reader.ReadUInt16(); _inventory[idx] = index; _invData[idx] = new ObjectData(index); var br = new BinaryReader(new MemoryStream(ptr)); br.BaseStream.Seek(18, SeekOrigin.Begin); var offset = br.ReadByte(); br.BaseStream.Seek(offset, SeekOrigin.Begin); // read name var name = new List<byte>(); var c = br.ReadByte(); while (c != 0) { name.Add(c); c = br.ReadByte(); } _invData[idx].Name = name.ToArray(); // read script _invData[idx].Script.Data = br.ReadBytes((int)(br.BaseStream.Length - br.BaseStream.Position)); // read verb table br.BaseStream.Seek(19, SeekOrigin.Begin); if (Game.Version == 8) { while (true) { var id = br.ReadInt32(); var off = br.ReadInt32(); if (id == 0) break; _invData[idx].ScriptOffsets.Add(id, off); } _invData[idx].Script.Offset = _invData[idx].ScriptOffsets.Count * 8 + 4; } else { while (true) { var id = br.ReadByte(); var off = br.ReadUInt16(); if (id == 0) break; _invData[idx].ScriptOffsets.Add(id, off); } _invData[idx].Script.Offset = _invData[idx].ScriptOffsets.Count * 3 + 1 + 8; } } break; case ResType.ActorName: { Actors[idx].Name = ptr; } break; case ResType.ObjectName: { var index = reader.ReadUInt16(); _newNames[index] = ptr; } break; case ResType.Matrix: { if (idx == 1) { // BOXM _boxMatrix.Clear(); _boxMatrix.AddRange(ptr); } else if (idx == 2) { // BOXD var br = new BinaryReader(new MemoryStream(ptr)); var numBoxes = br.ReadByte(); _boxes = new Box[numBoxes]; for (int i = 0; i < numBoxes; i++) { var box = new Box(); box.Ulx = br.ReadInt16(); box.Uly = br.ReadInt16(); box.Urx = br.ReadInt16(); box.Ury = br.ReadInt16(); box.Lrx = br.ReadInt16(); box.Lry = br.ReadInt16(); box.Llx = br.ReadInt16(); box.Lly = br.ReadInt16(); box.Mask = br.ReadByte(); box.Flags = (BoxFlags)br.ReadByte(); box.Scale = br.ReadUInt16(); if (Game.Version == 8) { box.ScaleSlot = br.ReadByte(); } _boxes[i] = box; } } } break; case ResType.Verb: { Verbs[idx].Text = ptr; } break; case ResType.VerbImage: { var br = new BinaryReader(new MemoryStream(ptr)); Verbs[idx].ImageWidth = br.ReadUInt16(); Verbs[idx].ImageHeight = br.ReadUInt16(); var imgSize = (int)(br.BaseStream.Length - 4); Verbs[idx].ImageData = new ImageData{ Data = br.ReadBytes(imgSize) }; } break; case ResType.String: { _strings[idx] = ptr; } break; } } // else // { // Console.WriteLine("Type: {0}", type); // } }
void DumpRoomObjectImages(Room room, ObjectData obj, Gdi gdi) { var text = new ScummText(obj.Name); var sb = new StringBuilder(); sb.Append("Object #" + obj.Number).Append(" "); var decoder = new TextDecoder(sb); text.Decode(decoder); sb.AppendFormat(" size: {0}x{1}", obj.Width, obj.Height); Console.WriteLine(sb); var j = 0; foreach (var img in obj.Images) { // try // { var screen = new VirtScreen(0, obj.Width, obj.Height, PixelFormat.Indexed8, 2); if (img.IsBomp) { var bdd = new BompDrawData(); bdd.Src = img.Data; bdd.Dst = new PixelNavigator(screen.Surfaces[0]); bdd.X = 0; bdd.Y = 0; bdd.Width = obj.Width; bdd.Height = obj.Height; bdd.ScaleX = 255; bdd.ScaleY = 255; bdd.DrawBomp(); } else { gdi.DrawBitmap(img, screen, new Point(0, 0), obj.Width, obj.Height & 0xFFF8, 0, obj.Width / 8, room.Header.Width, DrawBitmaps.None, true); } using (var bmp = ToBitmap(room, screen)) { bmp.Save("obj_" + obj.Number + "_" + (++j) + ".png"); } // } // catch (Exception e) // { // Console.ForegroundColor = ConsoleColor.Red; // Console.WriteLine(e); // Console.ResetColor(); // Console.ReadLine(); // } } }
protected ScummEngine(GameSettings settings, IGraphicsManager gfxManager, IInputManager inputManager, IMixer mixer) { Settings = settings; var game = (GameInfo)settings.Game; _resManager = ResourceManager.Load(game); _game = game; InvalidBox = _game.Version < 5 ? (byte)255 : (byte)0; _gameMD5 = ToMd5Bytes(game.MD5); _gfxManager = gfxManager; _inputManager = inputManager; _inputState = inputManager.GetState(); _strings = new byte[_resManager.NumArray][]; _inventory = new ushort[_resManager.NumInventory]; _invData = new ObjectData[_resManager.NumInventory]; CurrentScript = 0xFF; Mixer = mixer; ScreenWidth = Game.Width; ScreenHeight = Game.Height; AudioCDManager = new DefaultAudioCDManager(this, mixer); Sound = new Sound(this, mixer); SetupMusic(); _variables = new int[_resManager.NumVariables]; _bitVars = new BitArray(_resManager.NumBitVariables); _slots = new ScriptSlot[NumScriptSlot]; for (int i = 0; i < NumScriptSlot; i++) { _slots[i] = new ScriptSlot(); } for (int i = 0; i < 200; i++) { _objs[i] = new ObjectData(); } for (int i = 0; i < 6; i++) { _string[i] = new TextSlot(); if (game.Version != 3) { _string[i].Default.Position = new Point(2, 5); } } _colorCycle = new ColorCycle[16]; for (int i = 0; i < _colorCycle.Length; i++) { _colorCycle[i] = new ColorCycle(); } _nest = new NestedScript[MaxScriptNesting + 1]; for (int i = 0; i < _nest.Length; i++) { _nest[i] = new NestedScript(); } _scaleSlots = new ScaleSlot[20]; for (int i = 0; i < _scaleSlots.Length; i++) { _scaleSlots[i] = new ScaleSlot(); } Gdi = Gdi.Create(this, game); switch (game.Version) { case 0: _costumeLoader = new CostumeLoader0(this); _costumeRenderer = new CostumeRenderer0(this); break; case 7: case 8: _costumeLoader = new AkosCostumeLoader(this); _costumeRenderer = new AkosRenderer(this); break; default: _costumeLoader = new ClassicCostumeLoader(this); _costumeRenderer = new ClassicCostumeRenderer(this); break; } CreateCharset(); ResetCursors(); // Create the text surface var pixelFormat = _game.Features.HasFlag(GameFeatures.Is16BitColor) ? PixelFormat.Rgb16 : PixelFormat.Indexed8; _textSurface = new Surface(ScreenWidth * _textSurfaceMultiplier, ScreenHeight * _textSurfaceMultiplier, PixelFormat.Indexed8, false); ClearTextSurface(); if (Game.Platform == Platform.FMTowns) { _townsScreen = new TownsScreen(_gfxManager, ScreenWidth * _textSurfaceMultiplier, ScreenHeight * _textSurfaceMultiplier, PixelFormat.Rgb16); _townsScreen.SetupLayer(0, ScreenWidth, ScreenHeight, 32767); _townsScreen.SetupLayer(1, ScreenWidth * _textSurfaceMultiplier, ScreenHeight * _textSurfaceMultiplier, 16, _textPalette); } if (Game.Version == 0) { InitScreens(8, 144); } else if ((Game.GameId == GameId.Maniac) && (_game.Version <= 1) && _game.Platform != Platform.NES) { InitScreens(16, 152); } else if (Game.Version >= 7) { InitScreens(0, ScreenHeight); } else { InitScreens(16, 144); } // Allocate gfx compositing buffer (not needed for V7/V8 games). if (Game.Version < 7) { _composite = new Surface(ScreenWidth, ScreenHeight, pixelFormat, false); } InitActors(); OwnerRoom = Game.Version >= 7 ? 0x0FF : 0x0F; if (Game.Version < 7) { Camera.LeftTrigger = 10; Camera.RightTrigger = 30; } InitPalettes(); InitializeVerbs(); // WORKAROUND for bug in boot script of Loom (CD) // The boot script sets the characters of string 21, // before creating the string.resource. if (_game.GameId == GameId.Loom) { _strings[21] = new byte[13]; } }
void ClearRoomObjects() { if (Game.Version < 5) { for (var i = 0; i < _objs.Length; i++) { _objs[i] = new ObjectData(); } } else { for (var i = 0; i < _objs.Length; i++) { if (_objs[i].Number < 1) // Optimise codepath continue; // Nuke all non-flObjects (flObjects are nuked in script.cpp) if (_objs[i].FloatingObjectIndex == 0) { _objs[i] = new ObjectData(); } else { // Nuke all unlocked flObjects if (!_objs[i].IsLocked) { // _res->nukeResource(rtFlObject, _objs[i].fl_object_index); _objs[i] = new ObjectData(); } } } } }