Beispiel #1
0
        protected void FillSettings(BinaryReader binReader)
        {
            Mode = binReader.ReadEnum<Mode>();
            MicrophoneMode = binReader.ReadByte();
            OnDefault = binReader.ReadEnum<Mode>();
            SpotMeter = binReader.ReadByte() > 0;
            TimeLapse = binReader.ReadEnum<TimeLapse>();
            AutoPowerOff = binReader.ReadByte() > 0;
            FieldOfView = binReader.ReadEnum<FieldOfView>();
            PhotoResolution = binReader.ReadEnum<PhotoResolution>();
            VideoResolution = binReader.ReadEnum<VideoResolution>();
            AudioInput = binReader.ReadByte();
            PlayMode = binReader.ReadByte();
            PlaybackPosition = binReader.ReadUInt32();
            BeepSound = binReader.ReadEnum<BeepSound>();
            LedBlink = binReader.ReadEnum<LedBlink>();

            var field = binReader.ReadByte();
            PreviewActive = (byte) (field & 0x1) > 0;
            LiveFeed = (byte) (field & 0x2) > 0;
            Orientation = (Orientation) (field & 0x4);
            OneButton = (byte) (field & 0x8) > 0;
            OnScreen = (byte) (field & 0x10) > 0;
            VideoStandard = (VideoStandard) (field & 0x20);
            LocateCamera = (byte) (field & 0x40) > 0;

            Battery = binReader.ReadByte();
            UsbMode = binReader.ReadByte();
            PhotosAvailableSpace = binReader.ReadUInt16BigEndian();
            PhotosCount = binReader.ReadUInt16BigEndian();
            VideosAvailableSpace = binReader.ReadUInt16BigEndian();
            VideosCount = binReader.ReadUInt16BigEndian();
            Shutter = binReader.ReadByte() > 0;

            field = binReader.ReadByte();
            Busy = (byte) (field & 0x1) > 0;
            Protune = (byte) (field & 0x2) > 0;
            PreviewAvailable = (byte) (field & 0x4) > 0;
        }
Beispiel #2
0
        public void Do(Player player, byte[] msg, ushort len)
        {
            IMuseInternal se = player._se;

            switch (msg[0])
            {
                case 0:
                    // Trigger Event
                    // Triggers are set by doCommand(ImSetTrigger).
                    // When a SysEx marker is encountered whose sound
                    // ID and marker ID match what was set by ImSetTrigger,
                    // something magical is supposed to happen....
                    for (var a = 0; a < se._snm_triggers.Length; ++a)
                    {
                        if (se._snm_triggers[a].Sound == player.Id &&
                            se._snm_triggers[a].Id == msg[1])
                        {
                            se._snm_triggers[a].Sound = se._snm_triggers[a].Id = 0;
                            se.DoCommand(8, se._snm_triggers[a].Command);
                            break;
                        }
                    }
                    break;

                case 1:
                    // maybe_jump.
                    if (player.Scanning)
                        break;
                    using (var br = new BinaryReader(new MemoryStream(msg)))
                    {
                        br.ReadByte();

                        player.MaybeJump(br.ReadByte(), (uint)(br.ReadByte() - 1), (uint)((br.ReadUInt16BigEndian() - 1) * 4 + br.ReadByte()),
                            (uint)((br.ReadByte() * TicksPerBeat) >> 2) + br.ReadByte());
                    }
                    break;

                default:
                    scummSysEx.Do(player, msg, len);
                    break;
            }
        }
Beispiel #3
0
        void ReadMap()
        {
            var br = new BinaryReader(_stream);
            _stream.Seek(_mapOffset + 22, SeekOrigin.Begin);

            _resMap.resAttr = br.ReadUInt16BigEndian();
            _resMap.typeOffset = br.ReadUInt16BigEndian();
            _resMap.nameOffset = br.ReadUInt16BigEndian();
            _resMap.numTypes = br.ReadUInt16BigEndian();
            _resMap.numTypes++;

            _stream.Seek(_mapOffset + _resMap.typeOffset + 2, SeekOrigin.Begin);
            _resTypes = new ResType[_resMap.numTypes];

            for (int i = 0; i < _resMap.numTypes; i++)
            {
                _resTypes[i].id = br.ReadUInt32BigEndian();
                _resTypes[i].items = br.ReadUInt16BigEndian();
                _resTypes[i].offset = br.ReadUInt16BigEndian();
                _resTypes[i].items++;

                Debug.WriteLine("resType: <{0}> items: {1} offset: {2} (0x{3:X2})", _resTypes[i].id, _resTypes[i].items, _resTypes[i].offset, _resTypes[i].offset);
            }

            _resLists = new Resource[_resMap.numTypes][];

            for (int i = 0; i < _resMap.numTypes; i++)
            {
                _resLists[i] = new Resource[_resTypes[i].items];
                _stream.Seek(_resTypes[i].offset + _mapOffset + _resMap.typeOffset, SeekOrigin.Begin);

                for (int j = 0; j < _resTypes[i].items; j++)
                {
                    var resPtr = _resLists[i][j] = new Resource();

                    resPtr.id = br.ReadUInt16BigEndian();
                    resPtr.nameOffset = (short)br.ReadUInt16BigEndian();
                    resPtr.dataOffset = br.ReadUInt32BigEndian();
                    br.ReadUInt32BigEndian();

                    resPtr.attr = (byte)(resPtr.dataOffset >> 24);
                    resPtr.dataOffset &= 0xFFFFFF;
                }

                for (int j = 0; j < _resTypes[i].items; j++)
                {
                    if (_resLists[i][j].nameOffset != -1)
                    {
                        _stream.Seek(_resLists[i][j].nameOffset + _mapOffset + _resMap.nameOffset, SeekOrigin.Begin);

                        byte len = br.ReadByte();
						_resLists[i][j].name = br.ReadBytes(len).GetText();
                    }
                }
            }
        }
Beispiel #4
0
        public void Do(Player player, byte[] msg, ushort len)
        {
            IMuseInternal se = player._se;
            int p = 0;

            byte code;
            switch (code = msg[p++])
            {
                case 0:
                    {
                        // Allocate new part.
                        // There are 8 bytes (after decoding!) of useful information here.
                        // Here is what we know about them so far:
                        //   BYTE 0: Channel #
                        //   BYTE 1: BIT 01(0x01): Part on?(1 = yes)
                        //            BIT 02(0x02): Reverb? (1 = yes) [bug #1088045]
                        //   BYTE 2: Priority adjustment
                        //   BYTE 3: Volume [guessing]
                        //   BYTE 4: Pan [bug #1088045]
                        //   BYTE 5: BIT 8(0x80): Percussion?(1 = yes) [guessed?]
                        //   BYTE 5: Transpose, if set to 0x80(=-1) it means no transpose
                        //   BYTE 6: Detune
                        //   BYTE 7: Pitchbend factor [bug #1088045]
                        //   BYTE 8: Program
                        var part = player.GetPart((byte)(msg[p] & 0x0F));
                        var buf = DecodeSysExBytes(msg, p + 1, len - 1);
                        if (part != null)
                        {
                            part.SetOnOff((buf[0] & 0x01) != 0);
                            part.EffectLevel((byte)(((buf[0] & 0x02) != 0) ? 127 : 0));
                            part.Priority = (sbyte)buf[1];
                            part.Volume = buf[2];
                            part.Pan = buf[3];
                            part.Percussion = player.SupportsPercussion && ((buf[4] & 0x80) > 0);
                            part.SetTranspose((sbyte)buf[4]);
                            part.Detune = buf[5];
                            part.PitchBendFactor(buf[6]);
                            if (part.Percussion)
                            {
                                if (part.MidiChannel != null)
                                {
                                    part.Off();
                                    se.ReallocateMidiChannels(player.MidiDriver);
                                }
                            }
                            else
                            {
                                if (player.IsMIDI)
                                {
                                    // Even in cases where a program does not seem to be specified,
                                    // i.e. bytes 15 and 16 are 0, we send a program change because
                                    // 0 is a valid program number. MI2 tests show that in such
                                    // cases, a regular program change message always seems to follow
                                    // anyway.
                                    part.Instrument.Program(buf[7], player.IsMT32);
                                }
                                else
                                {
                                    // Like the original we set up the instrument data of the
                                    // specified program here too. In case the global
                                    // instrument data is not loaded already, this will take
                                    // care of setting a default instrument too.
                                    se.CopyGlobalInstrument(buf[7], part.Instrument);
                                }
                                part.SendAll();
                            }
                        }
                    }
                    break;

                case 1:
                        // Shut down a part. [Bug 1088045, comments]
                    {
                        var part = player.GetPart(msg[p]);
                        if (part != null)
                            part.Uninit();
                    }
                    break;

                case 2: // Start of song. Ignore for now.
                    break;

                case 16: // AdLib instrument definition(Part)
                    {
                        var a = (byte)(msg[p++] & 0x0F);
                        ++p; // Skip hardware type
                        var part = player.GetPart(a);
                        if (part != null)
                        {
                            if (len == 62 || len == 48)
                            {
                                var buf = DecodeSysExBytes(msg, p, len - 2);
                                part.SetInstrument(buf);
                            }
                            else
                            {
                                part.ProgramChange(254); // Must be invalid, but not 255 (which is reserved)
                            }
                        }
                    }
                    break;

                case 17: // AdLib instrument definition(Global)
                    {
                        p += 2; // Skip hardware type and... whatever came right before it
                        var a = msg[p++];
                        var buf = DecodeSysExBytes(msg, p, len - 3);
                        if (len == 63 || len == 49)
                            se.SetGlobalInstrument(a, buf);
                    }
                    break;

                case 33: // Parameter adjust
                    {
                        var a = msg[p++] & 0x0F;
                        ++p; // Skip hardware type
                        var buf = DecodeSysExBytes(msg, p, len - 2);
                        var part = player.GetPart((byte)a);
                        if (part != null)
                        {
                            using (var br = new BinaryReader(new MemoryStream(buf)))
                            {
                                part.SetParam((byte)br.ReadUInt16BigEndian(), (int)br.ReadUInt16BigEndian());
                            }
                        }
                    }
                    break;

                case 48: // Hook - jump
                    {
                        if (player.Scanning)
                            break;
                        var buf = DecodeSysExBytes(msg, p + 1, len - 1);
                        using (var br = new BinaryReader(new MemoryStream(buf)))
                        {
                            player.MaybeJump(br.ReadByte(), br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian());
                        }
                    }
                    break;

                case 49: // Hook - global transpose
                    {
                        var buf = DecodeSysExBytes(msg, p + 1, len - 1);
                        player.MaybeSetTranspose(buf);
                    }
                    break;

                case 50: // Hook - part on/off
                    {
                        var tmp = msg[p++] & 0x0F;
                        var buf = DecodeSysExBytes(msg, p, len - 1, 1);
                        buf[0] = (byte)tmp;
                        player.MaybePartOnOff(buf);
                    }
                    break;

                case 51: // Hook - set volume
                    {
                        var tmp = msg[p++] & 0x0F;
                        var buf = DecodeSysExBytes(msg, p, len - 1, 1);
                        buf[0] = (byte)tmp;
                        player.MaybeSetVolume(buf);
                    }
                    break;

                case 52: // Hook - set program
                    {
                        var tmp = msg[p++] & 0x0F;
                        var buf = DecodeSysExBytes(msg, p, len - 1, 1);
                        buf[0] = (byte)tmp;
                        player.MaybeSetProgram(buf);
                    }
                    break;

                case 53: // Hook - set transpose
                    {
                        var tmp = msg[p++] & 0x0F;
                        var buf = DecodeSysExBytes(msg, p, len - 1, 1);
                        buf[0] = (byte)tmp;
                        player.MaybeSetTransposePart(buf);
                    }
                    break;

                case 64: // Marker
                    p++;
                    len--;
                    while (len-- != 0)
                    {
                        se.HandleMarker(player.Id, msg[p++]);
                    }
                    break;

                case 80: // Loop
                    {
                        var buf = DecodeSysExBytes(msg, p + 1, len - 1);
                        using (var br = new BinaryReader(new MemoryStream(buf)))
                        {
                            player.SetLoop(br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian(),
                                br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian(),
                                br.ReadUInt16BigEndian());
                        }
                    }
                    break;

                case 81: // End loop
                    player.ClearLoop();
                    break;

                case 96: // Set instrument
                    {
                        var part = player.GetPart((byte)(msg[p] & 0x0F));
                        var a = (msg[p + 1] & 0x0F) << 12 | (msg[p + 2] & 0x0F) << 8 | (msg[p + 3] & 0x0F) << 4 | (msg[p + 4] & 0x0F);
                        if (part != null)
                            part.SetInstrument((uint)a);
                    }
                    break;

                default:
                    Debug.WriteLine("Unknown SysEx command {0}", (int)code);
                    break;
            }
        }
Beispiel #5
0
        public override void LoadMusic(byte[] data)
        {
            input = new MemoryStream(data);
            UnloadMusic();

            int midiType;
            var isGmf = false;
            var br = new BinaryReader(input);
            var sig = br.ReadBytes(4);
            input.Seek(0, SeekOrigin.Begin);

            if (AreEquals(sig, "RIFF"))
            {
                // Skip the outer RIFF header.
                input.Seek(8, SeekOrigin.Current);
            }

            if (AreEquals(sig, "MThd"))
            {
                // SMF with MTHd information.
                input.Seek(4, SeekOrigin.Current);
                var len = br.ReadUInt32BigEndian();
                if (len != 6)
                {
                    throw new InvalidOperationException(string.Format("MThd length 6 expected but found {0}", len));
                }
                br.ReadByte(); //?
                midiType = br.ReadByte();
                // Verify that this MIDI either is a Type 2
                // or has only 1 track. We do not support
                // multitrack Type 1 files.
                NumTracks = br.ReadUInt16BigEndian();
                
                if (midiType > 2 /*|| (midiType < 2 && _numTracks > 1)*/)
                {
                    throw new InvalidOperationException(string.Format("No support for a Type {0} MIDI with {1} tracks", midiType, NumTracks));
                }
                PulsesPerQuarterNote = br.ReadUInt16BigEndian();
            }
            else if (AreEquals(sig, "GMF\x1"))
            {
                // Older GMD/MUS file with no header info.
                // Assume 1 track, 192 PPQN, and no MTrk headers.
                isGmf = true;
                midiType = 0;
                NumTracks = 1;
                PulsesPerQuarterNote = 192;
                // 'GMD\x1' + 3 bytes of useless (translate: unknown) information
                input.Seek(7, SeekOrigin.Current);
            }
            else
            {
                throw new InvalidOperationException(string.Format("Expected MThd or GMD header but found '{0}{1}{2}{3}' instead", sig[0], sig[1], sig[2], sig[3]));
            }

            // Now we identify and store the location for each track.
            if (NumTracks > Tracks.Length)
            {
                throw new InvalidOperationException(string.Format("Can only handle {0} tracks but was handed {1}", Tracks.Length, NumTracks));
            }

            uint totalSize = 0;
            var tracksRead = 0;
            while (tracksRead < NumTracks)
            {
                sig = br.ReadBytes(4);
                if (!AreEquals(sig, "MTrk") && !isGmf)
                {
                    var msg = new StringBuilder();
                    msg.AppendFormat("Position: {0} ('{1}')", input.Position - 4, (char)sig[0]).AppendLine();
                    msg.AppendFormat("Hit invalid block '{0}{1}{2}{3}' while scanning for track locations", sig[0], sig[1], sig[2], sig[3]);
                    throw new InvalidOperationException(msg.ToString());
                }

                // If needed, skip the MTrk and length bytes
                Tracks[tracksRead] = new Track{ Position = input.Position + (isGmf ? -4 : 4) };
                if (!isGmf)
                {
                    var len = br.ReadUInt32BigEndian();
                    totalSize += len;
                    input.Seek(len, SeekOrigin.Current);
                }
                else
                {
                    // TODO: vs An SMF End of Track meta event must be placed
                    // at the end of the stream.
//                    data[size++] = 0xFF;
//                    data[size++] = 0x2F;
//                    data[size++] = 0x00;
//                    data[size++] = 0x00;
                    throw new NotImplementedException("Gmf not implemented");
                }
                ++tracksRead;
            }

            // If this is a Type 1 MIDI, we need to now compress
            // our tracks down into a single Type 0 track.
            //_buffer = 0;

            if (midiType == 1)
            {
                // FIXME: Doubled the buffer size to prevent crashes with the
                // Inherit the Earth MIDIs. Jamieson630 said something about a
                // better fix, but this will have to do in the meantime.
//                _buffer = (byte*)malloc(size * 2);
//                compressToType0();
//                _numTracks = 1;
//                _tracks[0] = _buffer;
                throw new NotImplementedException("MidiType 1 not yet implemented.");
            }

            // Note that we assume the original data passed in
            // will persist beyond this call, i.e. we do NOT
            // copy the data to our own buffer. Take warning....
            ResetTracking();
            Tempo = 500000;
            ActiveTrack = 0;
        }
Beispiel #6
0
        SoundHandle StartTalkSound(int offset, int b, int mode)
        {
            Stream file;
            SoundHandle handle = new SoundHandle();
            var id = -1;

            if (vm.Game.GameId == GameId.CurseOfMonkeyIsland)
            {
                sfxMode |= mode;
                return handle;
            }
            else if (vm.Game.GameId == GameId.Dig)
            {
                sfxMode |= mode;
                if (!(vm.Game.Features.HasFlag(GameFeatures.Demo)))
                    return handle;
                throw new NotImplementedException();
            }
            else
            {
                if (_sfxFilename == null)
                {
                    //                    Console.Error.WriteLine("StartTalkSound: SFX file not found");
                    return handle;
                }

                // Some games frequently assume that starting one sound effect will
                // automatically stop any other that may be playing at that time. So
                // that is what we do here, but we make an exception for speech.
                if (mode == 1 && (vm.Game.GameId == GameId.Tentacle || vm.Game.GameId == GameId.SamNMax))
                {
                    id = 777777 + _talkSoundChannel;
                    _mixer.StopID(id);
                }

                int num = 0;
                if (b > 8)
                {
                    num = (b - 8) >> 1;
                }

                offset += 8;

                _mouthSyncTimes = new ushort[num + 1];
                file = ServiceLocator.FileStorage.OpenFileRead(_sfxFilename);
                var br = new BinaryReader(file);
                file.Seek(offset, SeekOrigin.Begin);
                for (int i = 0; i < num; i++)
                {
                    _mouthSyncTimes[i] = br.ReadUInt16BigEndian();
                }

                // Adjust offset to account for the mouth sync times. It is noteworthy
                // that we do not adjust the size here for compressed streams, since
                // they only set size to the size of the compressed sound data.
                offset += num * 2;
                // TODO: In case we ever set up the size for VOC streams, we should
                // really check whether the size contains the _mouthSyncTimes.
                // if (SoundMode == SoundMode.VOCMode)
                //      size -= num * 2;

                _mouthSyncTimes[num] = 0xFFFF;
                sfxMode |= mode;
                _curSoundPos = 0;
                _mouthSyncMode = true;
            }

            var input = new VocStream(file, true);

            var iMuseDigital = vm.MusicEngine as IMuseDigital;
            if (iMuseDigital != null)
            {
                iMuseDigital.StartVoice(TalkSoundID, input);
            }
            else
            {
                if (mode == 1)
                {
                    handle = _mixer.PlayStream(SoundType.SFX, input, id);
                }
                else
                {
                    handle = _mixer.PlayStream(SoundType.Speech, input, id);
                }
            }
            return handle;
        }
Beispiel #7
0
            public bool LoadInstrument(Stream stream)
            {
                var br = new BinaryReader(stream);
                ushort soundType = br.ReadUInt16BigEndian();
                if (soundType != 1)
                {
                    Debug.WriteLine("Player_Mac::loadInstrument: Unsupported sound type {0}", soundType);
                    return false;
                }
                var typeCount = br.ReadUInt16BigEndian();
                if (typeCount != 1)
                {
                    Debug.WriteLine("Player_Mac::loadInstrument: Unsupported data type count %d", typeCount);
                    return false;
                }
                var dataType = br.ReadUInt16BigEndian();
                if (dataType != 5)
                {
                    Debug.WriteLine("Player_Mac::loadInstrument: Unsupported data type %d", dataType);
                    return false;
                }

                br.ReadUInt32BigEndian(); // initialization option

                var cmdCount = br.ReadUInt16BigEndian();
                if (cmdCount != 1)
                {
                    Debug.WriteLine("Player_Mac::loadInstrument: Unsupported command count %d", cmdCount);
                    return false;
                }
                var command = br.ReadUInt16BigEndian();
                if (command != 0x8050 && command != 0x8051)
                {
                    Debug.WriteLine("Player_Mac::loadInstrument: Unsupported command 0x%04X", command);
                    return false;
                }

                br.ReadUInt16BigEndian(); // 0
                var soundHeaderOffset = br.ReadUInt32BigEndian();

                stream.Seek(soundHeaderOffset, SeekOrigin.Begin);

                var soundDataOffset = br.ReadUInt32BigEndian();
                var size = br.ReadUInt32BigEndian();
                var rate = br.ReadUInt32BigEndian() >> 16;
                var loopStart = br.ReadUInt32BigEndian();
                var loopEnd = br.ReadUInt32BigEndian();
                byte encoding = br.ReadByte();
                byte baseFreq = br.ReadByte();

                if (encoding != 0)
                {
                    Debug.WriteLine("Player_Mac::loadInstrument: Unsupported encoding %d", encoding);
                    return false;
                }

                stream.Seek(soundDataOffset, SeekOrigin.Current);

                var data = br.ReadBytes((int)size);
                _instrument._data = data;
                _instrument._size = size;
                _instrument._rate = rate;
                _instrument._loopStart = loopStart;
                _instrument._loopEnd = loopEnd;
                _instrument._baseFreq = baseFreq;

                return true;
            }
Beispiel #8
0
        MdatResource LoadMdatFile(Stream musicData)
        {
            var br = new BinaryReader(musicData);
            bool hasHeader = false;
            var mdatSize = musicData.Length;
            if (mdatSize >= 0x200)
            {

                // 0x0000: 10 Bytes Header "TFMX-SONG "
                var buf = System.Text.Encoding.UTF8.GetString(br.ReadBytes(10));
                hasHeader = buf == "TFMX-SONG ";
            }

            if (!hasHeader)
            {
                Debug.WriteLine("Tfmx: File is not a Tfmx Module");
                return null;
            }

            var resource = new MdatResource();

            resource.mdatAlloc = null;
            resource.mdatOffset = 0;
            resource.mdatLen = 0;

            // 0x000A: int16 flags
            resource.headerFlags = br.ReadUInt16BigEndian();
            // 0x000C: int32 ?
            // 0x0010: 6*40 Textfield
            musicData.Seek(4 + 6 * 40, SeekOrigin.Current);

            /* 0x0100: Songstart x 32*/
            for (int i = 0; i < NumSubsongs; ++i)
                resource.subsong[i].songstart = br.ReadUInt16BigEndian();
            /* 0x0140: Songend x 32*/
            for (int i = 0; i < NumSubsongs; ++i)
                resource.subsong[i].songend = br.ReadUInt16BigEndian();
            /* 0x0180: Tempo x 32*/
            for (int i = 0; i < NumSubsongs; ++i)
                resource.subsong[i].tempo = br.ReadUInt16BigEndian();

            /* 0x01c0: unused ? */
            musicData.Seek(16, SeekOrigin.Current);

            /* 0x01d0: trackstep, pattern data p, macro data p */
            var offTrackstep = br.ReadUInt32BigEndian();
            uint offPatternP, offMacroP;

            // This is how MI`s TFMX-Player tests for unpacked Modules.
            if (offTrackstep == 0)
            { // unpacked File
                resource.trackstepOffset = 0x600 + 0x200;
                offPatternP = 0x200 + 0x200;
                offMacroP = 0x400 + 0x200;
            }
            else
            { // packed File
                resource.trackstepOffset = offTrackstep;
                offPatternP = br.ReadUInt32BigEndian();
                offMacroP = br.ReadUInt32BigEndian();
            }

            // TODO: if a File is packed it could have for Ex only 2 Patterns/Macros
            // the following loops could then read beyond EOF.
            // To correctly handle this it would be necessary to sort the pointers and
            // figure out the number of Macros/Patterns
            // We could also analyze pointers if they are correct offsets,
            // so that accesses can be unchecked later

            // Read in pattern starting offsets
            musicData.Seek(offPatternP, SeekOrigin.Begin);
            for (int i = 0; i < MaxPatternOffsets; ++i)
                resource.patternOffset[i] = br.ReadUInt32BigEndian();

            // use last PatternOffset (stored at 0x5FC in mdat) if unpacked File
            // or fixed offset 0x200 if packed
            resource.sfxTableOffset = offTrackstep != 0 ? 0x200 : resource.patternOffset[127];

            // Read in macro starting offsets
            musicData.Seek(offMacroP, SeekOrigin.Begin);
            for (int i = 0; i < MaxMacroOffsets; ++i)
                resource.macroOffset[i] = br.ReadUInt32BigEndian();

            // Read in mdat-file
            // TODO: we can skip everything thats already stored in the resource-structure.
            var mdatOffset = offTrackstep != 0 ? 0x200 : 0x600;  // 0x200 is very conservative
            var allocSize = mdatSize - mdatOffset;

            musicData.Seek(mdatOffset, SeekOrigin.Begin);
            var mdatAlloc = br.ReadBytes((int)allocSize);

            resource.mdatAlloc = mdatAlloc;
            resource.mdatOffset = mdatOffset;
            resource.mdatLen = (int)mdatSize;
            return resource;
        }
Beispiel #9
0
        public bool RestoreGameFromFile(byte slot)
        {

            ushort cnt;
            var fName = $"sword1.{slot:D3}";
            using (var inf = new BinaryReader(_saveFileMan.OpenForLoading(fName)))
            {
                // TODO:
                //if (inf==null)
                //{
                //    // Display an error message, and do nothing
                //    // TODO: DisplayMessage(0, "Can't open file '%s'. (%s)", fName, _saveFileMan.popErrorDesc().c_str());
                //    return false;
                //}

                uint saveHeader = inf.ReadUInt32();
                if (saveHeader != SAVEGAME_HEADER)
                {
                    // Display an error message, and do nothing
                    // TODO: DisplayMessage(0, "Save game '%s' is corrupt", fName);
                    return false;
                }

                inf.BaseStream.Seek(40, SeekOrigin.Current); // skip description
                byte saveVersion = inf.ReadByte();

                if (saveVersion > SAVEGAME_VERSION)
                {
                    // TODO: warning("Different save game version");
                    return false;
                }

                if (saveVersion < 2) // These older version of the savegames used a flag to signal presence of thumbnail
                    inf.BaseStream.Seek(1, SeekOrigin.Current);

                SkipThumbnail(inf);

                inf.ReadUInt32BigEndian(); // save date
                inf.ReadUInt16BigEndian(); // save time

                if (saveVersion < 2)
                {
                    // Before version 2 we didn't had play time feature
                    // TODO: g_engine.setTotalPlayTime(0);
                }
                else
                {
                    var time = inf.ReadUInt32BigEndian();
                    // TODO: g_engine.setTotalPlayTime(time * 1000);
                }

                _restoreBuf = new byte[
                    ObjectMan.TOTAL_SECTIONS * 2 +
                    Logic.NUM_SCRIPT_VARS * 4 +
                    (SwordObject.Size - 12000)];

                var liveBuf = new UShortAccess(_restoreBuf);
                var scriptBuf = new UIntAccess(_restoreBuf, 2 * ObjectMan.TOTAL_SECTIONS);
                var playerBuf = new UIntAccess(_restoreBuf, 2 * ObjectMan.TOTAL_SECTIONS + 4 * Logic.NUM_SCRIPT_VARS);

                for (cnt = 0; cnt < ObjectMan.TOTAL_SECTIONS; cnt++)
                    liveBuf[cnt] = inf.ReadUInt16();

                for (cnt = 0; cnt < Logic.NUM_SCRIPT_VARS; cnt++)
                    scriptBuf[cnt] = inf.ReadUInt32();

                uint playerSize = (SwordObject.Size - 12000) / 4;
                for (var cnt2 = 0; cnt2 < playerSize; cnt2++)
                    playerBuf[cnt2] = inf.ReadUInt32();

                // TODO: error
                //if (inf.err() || inf.eos())
                //{
                //    displayMessage(0, "Can't read from file '%s'. (%s)", fName, _saveFileMan.popErrorDesc().c_str());
                //    delete inf;
                //    free(_restoreBuf);
                //    _restoreBuf = NULL;
                //    return false;
                //}
            }

            return true;
        }