コード例 #1
0
        public void Load(int id)
        {
            string filename, path;

            var directory = ServiceLocator.FileStorage.GetDirectoryName(_vm.Settings.Game.Path);

            LoadSubtitles(id);

            // For the PSX version, we'll try the PlayStation stream files
            if (SystemVars.Platform == Core.IO.Platform.PSX)
            {
                _vm.GraphicsManager.PixelFormat = PixelFormat.Rgb16;

                // The demo uses the normal file names
                filename = (SystemVars.IsDemo ? SequenceList[id] : SequenceListPsx[id]) + ".str";
                _decoder = new PsxStreamDecoder(_vm.Mixer, CDSpeed.CD2x, _vm.GraphicsManager.PixelFormat);
            }
            else
            {
                filename = $"{SequenceList[id]}.smk";
                _decoder = new SmackerDecoder(_vm.Mixer);
            }

            path = ScummHelper.LocatePath(directory, filename);
            var stream = ServiceLocator.FileStorage.OpenFileRead(path);

            _decoder.LoadStream(stream);
            _decoder.Start();
        }
コード例 #2
0
            private void DecodeBlock(BitStream bits, byte[] block, int offset, int pitch, ushort scale, ushort version, PlaneType plane)
            {
                // Version 2 just has signed 10 bits for DC
                // Version 3 has them huffman coded
                int[] coefficients = new int[8 * 8];
                coefficients[0] = ReadDC(bits, version, plane);
                ReadAC(bits, coefficients, 1); // Read in the AC

                // Dequantize
                float[] dequantData = new float[8 * 8];
                DequantizeBlock(coefficients, dequantData, scale);

                // Perform IDCT
                float[] idctData = new float[8 * 8];
                Idct(dequantData, idctData);

                // Now output the data
                for (int y = 0; y < 8; y++)
                {
                    var dst = offset + pitch * y;

                    // Convert the result to be in the range [0, 255]
                    for (int x = 0; x < 8; x++)
                    {
                        block[dst++] = (byte)(ScummHelper.Clip(idctData[y * 8 + x], -128.0f, 127.0f) + 128);
                    }
                }
            }
コード例 #3
0
        protected virtual ColorCycle[] ReadCYCL()
        {
            var colorCycle = new ColorCycle[16];

            for (int i = 0; i < 16; i++)
            {
                var delay = ScummHelper.SwapBytes(_reader.ReadUInt16());
                var start = _reader.ReadByte();
                var end   = _reader.ReadByte();

                colorCycle[i] = new ColorCycle();

                if (delay == 0 || delay == 0x0aaa || start >= end)
                {
                    continue;
                }

                colorCycle[i].Counter = 0;
                colorCycle[i].Delay   = (ushort)(16384 / delay);
                colorCycle[i].Flags   = 2;
                colorCycle[i].Start   = start;
                colorCycle[i].End     = end;
            }

            return(colorCycle);
        }
コード例 #4
0
        static void WriteMIDIHeader(byte[] input, string type, int ppqn, int totalSize)
        {
            int pos = 0;

            Array.Copy(System.Text.Encoding.UTF8.GetBytes(type), 0, input, pos, 4);
            pos += 4;
            Array.Copy(ScummHelper.GetBytesBigEndian((uint)totalSize), 0, input, pos, 4);
            pos += 4;
            Array.Copy(System.Text.Encoding.UTF8.GetBytes("MDhd"), 0, input, pos, 4);
            pos += 4;
            Array.Copy(new byte[] { 0, 0, 0, 8 }, 0, input, pos, 4);
            pos += 4;
            Array.Copy(new byte[8], 0, input, pos, 8);
            pos += 8;
            Array.Copy(System.Text.Encoding.UTF8.GetBytes("MThd"), 0, input, pos, 4);
            pos += 4;
            Array.Copy(new byte[] { 0, 0, 0, 6 }, 0, input, pos, 4);
            pos += 4;
            Array.Copy(new byte[] { 0, 0, 0, 1 }, 0, input, pos, 4);
            pos         += 4; // MIDI format 0 with 1 track
            input[pos++] = (byte)(ppqn >> 8);
            input[pos++] = (byte)(ppqn & 0xFF);
            Array.Copy(System.Text.Encoding.UTF8.GetBytes("MTrk"), 0, input, pos, 4);
            pos += 4;
            Array.Copy(ScummHelper.GetBytesBigEndian((uint)totalSize), 0, input, pos, 4);
            pos += 4;
        }
コード例 #5
0
        TrsFile GetStrings(ScummEngine vm, string file, bool isEncoded)
        {
            //            Debug.WriteLine("trying to read text resources from {0}", file);
            var filename = ScummHelper.LocatePath(ServiceLocator.FileStorage.GetDirectoryName(_vm.Game.Path), ServiceLocator.FileStorage.GetFileName(file));

            return(filename != null?isEncoded?TrsFile.LoadEncoded(filename) : TrsFile.Load(filename) : null);
        }
コード例 #6
0
        TimeSpan GetTimeToWaitBeforeLoop(TimeSpan lastTimeLoop)
        {
            var numTicks = ScummHelper.ToTicks(timeToWait);

            // Notify the script about how much time has passed, in ticks (60 ticks per second)
            if (VariableTimer.HasValue)
            {
                _variables[VariableTimer.Value] = numTicks;
            }
            if (VariableTimerTotal.HasValue)
            {
                _variables[VariableTimerTotal.Value] += numTicks;
            }

            // Determine how long to wait before the next loop iteration should start
            deltaTicks = VariableTimerNext.HasValue ? _variables[VariableTimerNext.Value] : 4;
            if (deltaTicks < 1) // Ensure we don't get into an endless loop
            {
                deltaTicks = 1; // by not decreasing sleepers.
            }
            timeToWait = ScummHelper.ToTimeSpan(deltaTicks);
            if (timeToWait > lastTimeLoop)
            {
                timeToWait -= lastTimeLoop;
            }
            else
            {
                timeToWait = TimeSpan.Zero;
            }
            return(timeToWait);
        }
コード例 #7
0
 public void SeekSan(string filename, int pos, int contFrame)
 {
     _seekFile  = ScummHelper.LocatePath(ServiceLocator.FileStorage.GetDirectoryName(_vm.Game.Path), ServiceLocator.FileStorage.GetFileName(filename));
     _seekPos   = pos;
     _seekFrame = contFrame;
     _pauseTime = 0;
 }
コード例 #8
0
        protected override bool HandleSubTags(ref int offset)
        {
            if (_tbufferSize - offset >= 8)
            {
                var type           = System.Text.Encoding.UTF8.GetString(_tbuffer, offset, 4);
                var size           = ScummHelper.SwapBytes(BitConverter.ToUInt32(_tbuffer, offset + 4));
                var available_size = _tbufferSize - offset;
                switch (type)
                {
                case "MAP ":
                    _inData = false;
                    if (available_size >= (size + 8))
                    {
                        var tmp = new byte[_tbuffer.Length - offset];
                        Array.Copy(_tbuffer, offset, tmp, 0, tmp.Length);
                        HandleMap(tmp);
                    }
                    break;

                case "DATA":
                    _inData   = true;
                    _dataSize = (int)size;
                    offset   += 8;
                    {
                        int reqsize = 1;
                        if (_channels == 2)
                        {
                            reqsize *= 2;
                        }
                        if (_bitsize == 16)
                        {
                            reqsize *= 2;
                        }
                        else if (_bitsize == 12)
                        {
                            if (reqsize > 1)
                            {
                                reqsize = reqsize * 3 / 2;
                            }
                            else
                            {
                                reqsize = 3;
                            }
                        }
                        if ((size % reqsize) != 0)
                        {
                            Debug.WriteLine("Invalid iMUS sound data size : ({0} %% {1}) != 0, correcting...", size, reqsize);
                            size += (uint)(3 - (size % reqsize));
                        }
                    }
                    return(false);
//                    default:
//                        Console.Error.WriteLine("unknown Chunk in iMUS track : {0} ", type);
//                        break;
                }
                offset += (int)(size + 8);
                return(true);
            }
            return(false);
        }
コード例 #9
0
        public bool Exists(string fileName)
        {
            // Try the file name by itself
            var path = ScummHelper.LocatePath(_gamePath, fileName);

            if (path != null)
            {
                return(true);
            }

            // Try the .rsrc extension
//            if (File::exists(fileName + ".rsrc"))
//                return true;

            // Check if we have a MacBinary file
            path = ScummHelper.LocatePath(_gamePath, fileName + ".bin");
            if (path != null /*&& isMacBinary(tempFile)*/)
            {
                return(true);
            }

            // Check if we have an AppleDouble file
//            if (tempFile.open(constructAppleDoubleName(fileName)) && tempFile.readUint32BE() == 0x00051607)
//                return true;

            return(false);
        }
コード例 #10
0
 private void LoadSubtitles(int id)
 {
     if (SystemVars.ShowText != 0)
     {
         var filename = $"{SequenceList[id]}.txt";
         var path     = ScummHelper.LocatePath(_directory, filename);
         if (path != null)
         {
             using (var f = new StreamReader(ServiceLocator.FileStorage.OpenFileRead(path)))
             {
                 string line;
                 while ((line = f.ReadLine()) != null)
                 {
                     var m = _regex.Match(line);
                     if (m.Success)
                     {
                         var start = ushort.Parse(m.Groups[1].Value);
                         var end   = ushort.Parse(m.Groups[2].Value);
                         var color = ushort.Parse(m.Groups[3].Value);
                         var text  = m.Groups[4].Value;
                         _movieTexts.Add(new MovieText(start, end, text, color));
                     }
                 }
             }
         }
     }
 }
コード例 #11
0
        public Stream OpenContent(string path)
        {
            var installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
            var fullPath          = ScummHelper.LocatePath(installedLocation.Path, path);

            return(OpenFileRead(fullPath));
        }
コード例 #12
0
        public override void SetDirection(int direction)
        {
            int dir = ScummHelper.NewDirToOldDir(direction);
            int res = 0;

            switch (dir)
            {
            case 0:
                res = 4;        // Left
                break;

            case 1:
                res = 5;        // Right
                break;

            case 2:
                res = 6;        // Face Camera
                break;

            default:
                res = 7;        // Face Away
                break;
            }

            AnimFrameRepeat = -1;
            AnimateActor(res);
        }
コード例 #13
0
        public bool Open(string filename, ref bool compressed)
        {
            if (_file != null)
            {
                return(true);
            }

            filename = ScummHelper.LocatePath(ServiceLocator.FileStorage.GetDirectoryName(ScummEngine.Instance.Game.Path), filename);
            _file    = new BinaryReader(ServiceLocator.FileStorage.OpenFileRead(filename));

            int slot = _cache.MatchFile(filename);

            Debug.Assert(slot != -1);
            compressed = _cache.IsSndDataExtComp(slot);
            _numFiles  = _cache.GetNumFiles(slot);
            Debug.Assert(_numFiles != 0);
            _bundleTable = _cache.GetTable(slot);
            _indexTable  = _cache.GetIndexTable(slot);
            Debug.Assert(_bundleTable != null);
            _compTableLoaded = false;
            _outputSize      = 0;
            _lastBlock       = -1;

            return(true);
        }
コード例 #14
0
        public NutRenderer(ScummEngine vm, string filename)
        {
            _vm = vm;
            var directory = ServiceLocator.FileStorage.GetDirectoryName(_vm.Game.Path);
            var path      = ScummHelper.LocatePath(directory, filename);

            LoadFont(path);
        }
コード例 #15
0
 public void SetFacing(Actor a)
 {
     _mirror = (ScummHelper.NewDirToOldDir(a.Facing) != 0) || ((akhd.flags & 1) != 0);
     if (a.Flip)
     {
         _mirror = !_mirror;
     }
 }
コード例 #16
0
        public Stream OpenContent(string path)
        {
            var exe      = Environment.GetCommandLineArgs()[0];
            var dir      = Path.GetDirectoryName(exe);
            var fullPath = ScummHelper.LocatePath(dir, path);

            return(OpenFileRead(fullPath));
        }
コード例 #17
0
        void SetupSfxFile()
        {
            var dir = ServiceLocator.FileStorage.GetDirectoryName(vm.Game.Path);

            _sfxFilename = (from filename in new[] { vm.Game.Id + ".sou", "monster.sou" }
                            let path = ScummHelper.NormalizePath(ServiceLocator.FileStorage.Combine(dir, filename))
                                       where path != null
                                       select path).FirstOrDefault();
        }
コード例 #18
0
        byte ApplyVolumeAdjust(byte @in)
        {
            int @out = _tLevel[_musicData[_musicPos + 1]];

            @out += (@in & 0x7f);
            @out  = ScummHelper.Clip(@out, 1, 127);

            return((byte)(@out & 0xff));
        }
コード例 #19
0
        static int GenerateSine(int x, int oscLength)
        {
            if (oscLength == 0)
            {
                return(0);
            }

            // TODO: Maybe using a look-up-table would be better?
            return(ScummHelper.Clip((int)(128 * Math.Sin(2.0 * Math.PI * x / oscLength)), -128, 127));
        }
コード例 #20
0
        protected override ResourceFile OpenRoom(byte roomIndex)
        {
            var diskNum   = Index.RoomResources[roomIndex].RoomNum;
            var diskName  = string.Format(Game.Pattern, diskNum);
            var game1Path = ScummHelper.NormalizePath(ServiceLocator.FileStorage.Combine(Directory, diskName));

            var file = new ResourceFile5(new XorStream(ServiceLocator.FileStorage.OpenFileRead(game1Path), 0x69));

            return(file);
        }
コード例 #21
0
        private BinaryReader TryToOpen(string filename)
        {
            var directory = ServiceLocator.FileStorage.GetDirectoryName(_settings.Game.Path);
            var path      = ScummHelper.LocatePath(directory, filename);

            if (path != null)
            {
                return(new BinaryReader(ServiceLocator.FileStorage.OpenFileRead(path)));
            }
            return(null);
        }
コード例 #22
0
        protected override void WriteVariable(uint index, int value)
        {
            //            Console.WriteLine("SetResult({0},{1})", index, value);
            if ((index & 0xF000) == 0)
            {
                ScummHelper.AssertRange(0, index, _resManager.NumVariables - 1, "variable (writing)");
                Variables[index] = value;
                return;
            }

            if ((index & 0x8000) != 0)
            {
                if (Game.Version <= 3 && !(Game.GameId == GameId.Indy3 && Game.Platform == Platform.FMTowns) &&
                    !(Game.GameId == GameId.Loom && Game.Platform == Platform.PCEngine))
                {
                    var bit = (int)(index & 0xF);
                    index = (index >> 4) & 0xFF;
                    ScummHelper.AssertRange(0, index, _resManager.NumVariables - 1, "variable (writing)");
                    if (value > 0)
                    {
                        Variables[index] |= (1 << bit);
                    }
                    else
                    {
                        Variables[index] &= ~(1 << bit);
                    }
                }
                else
                {
                    index &= 0x7FFF;

                    ScummHelper.AssertRange(0, index, _bitVars.Length - 1, "bit variable (writing)");
                    _bitVars[(int)index] = value != 0;
                }
                return;
            }

            if ((index & 0x4000) != 0)
            {
                if (Game.Features.HasFlag(GameFeatures.FewLocals))
                {
                    index &= 0xF;
                }
                else
                {
                    index &= 0xFFF;
                }

                ScummHelper.AssertRange(0, index, 20, "local variable (writing)");
                //Console.WriteLine ("SetLocalVariables(script={0},var={1},value={2})", CurrentScript, index, value);
                Slots[CurrentScript].LocalVariables[index] = value;
                return;
            }
        }
コード例 #23
0
        protected override ResourceFile OpenRoom(byte roomIndex)
        {
            var diskNum  = Index.RoomResources[roomIndex].RoomNum;
            var diskName = Game.Pattern == null?string.Format("{0}.{1:000}", Game.Id, diskNum) : string.Format(Game.Pattern, diskNum);

            var game1Path = ScummHelper.NormalizePath(ServiceLocator.FileStorage.Combine(Directory, diskName));

            var file = new ResourceFile7(ServiceLocator.FileStorage.OpenFileRead(game1Path));

            return(file);
        }
コード例 #24
0
        protected override byte[] ReadCharset(byte id)
        {
            var diskName = string.Format("{0:00}.lfl", 99 - id);
            var path     = ScummHelper.NormalizePath(ServiceLocator.FileStorage.Combine(Directory, diskName));

            using (var file = ServiceLocator.FileStorage.OpenFileRead(path))
            {
                var reader = new BinaryReader(file);
                var size   = reader.ReadUInt16();
                return(reader.ReadBytes(size));
            }
        }
コード例 #25
0
        void AdvanceInput(RhtChannel ins)
        {
            sbyte cur = (sbyte)ins.data[ins.posOffset++];

            for (int i = 0; i < 2; i++)
            {
                int b = (2 * (cur & 7) + 1) * stepTable[ins.decState] / 8;
                ins.samples[i] = (short)ScummHelper.Clip(ins.samples[i ^ 1] + ((cur & 8) != 0 ? b : -b), -2048, 2047);
                ins.decState   = (sbyte)ScummHelper.Clip(ins.decState + adjustIndex[cur & 7], 0, 48);
                cur          >>= 4;
            }
        }
コード例 #26
0
        static void akos_queCommand(byte cmd, Actor a, int param_1, int param_2, ScummEngine vm)
        {
            var v = (ScummEngine6)vm;

            v._akosQueuePos++;
            ScummHelper.AssertRange(0, v._akosQueuePos, 31, "akos_queCommand: _akosQueuePos");

            v._akosQueue[v._akosQueuePos].cmd    = cmd;
            v._akosQueue[v._akosQueuePos].actor  = a.Number;
            v._akosQueue[v._akosQueuePos].param1 = (short)param_1;
            v._akosQueue[v._akosQueuePos].param2 = (short)param_2;
        }
コード例 #27
0
        protected virtual bool DrawStrip(PixelNavigator navDst, int width, int height, int stripnr, BinaryReader smapReader)
        {
            // Do some input verification and make sure the strip/strip offset
            // are actually valid. Normally, this should never be a problem,
            // but if e.g. a savegame gets corrupted, we can easily get into
            // trouble here. See also bug #795214.
            long offset = -1;
            long smapLen;

            if (game.Features.HasFlag(GameFeatures.SixteenColors))
            {
                smapLen = smapReader.ReadInt16();
                if (stripnr * 2 + 2 < smapLen)
                {
                    smapReader.BaseStream.Seek(stripnr * 2, SeekOrigin.Current);
                    offset = smapReader.ReadInt16();
                }
            }
            else if (game.Version < 5)
            {
                smapLen = smapReader.ReadInt32();
                if (stripnr * 4 + 4 < smapLen)
                {
                    smapReader.BaseStream.Seek(stripnr * 4, SeekOrigin.Current);
                    offset = smapReader.ReadInt32();
                }
            }
            else if (game.Version == 8)
            {
                smapLen = smapReader.BaseStream.Length;
                // Skip to the BSTR->WRAP->OFFS chunk
                smapReader.BaseStream.Seek(24, SeekOrigin.Current);
                if (stripnr * 4 + 8 < smapLen)
                {
                    smapReader.BaseStream.Seek(stripnr * 4, SeekOrigin.Current);
                    offset = 16 + smapReader.ReadUInt32();
                }
            }
            else
            {
                smapLen = smapReader.BaseStream.Length;
                if (stripnr * 4 + 8 < smapLen)
                {
                    smapReader.BaseStream.Seek(stripnr * 4, SeekOrigin.Begin);
                    offset = smapReader.ReadUInt32() - 8;
                }
            }

            ScummHelper.AssertRange(0, offset, smapLen - 1, "screen strip");
            smapReader.BaseStream.Seek(offset, SeekOrigin.Begin);

            return(DecompressBitmap(navDst, smapReader, height));
        }
コード例 #28
0
        public void Play(int track, int numLoops, int startFrame, int duration, bool only_emulate)
        {
            if (numLoops != 0 || startFrame != 0)
            {
                _cd.track    = track;
                _cd.numLoops = numLoops;
                _cd.start    = startFrame;
                _cd.duration = duration;

                // Try to load the track from a compressed data file, and if found, use
                // that. If not found, attempt to start regular Audio CD playback of
                // the requested track.
                string[] trackName = new string[2];
                trackName[0] = string.Format("track{0}", track);
                trackName[1] = string.Format("track{0:00}", track);
                ISeekableAudioStream stream = null;
                var directory = ServiceLocator.FileStorage.GetDirectoryName(_vm.Game.Path);
                for (int i = 0; stream == null && i < 2; ++i)
                {
                    var path = ScummHelper.LocatePath(directory, trackName[i]);
                    if (path != null)
                    {
                        // TODO: open stream
                    }
                }

                // Stop any currently playing emulated track
                _mixer.StopHandle(_handle);

                if (stream != null)
                {
                    var start = new Timestamp(0, startFrame, 75);
                    var end   = duration != 0 ? new Timestamp(0, startFrame + duration, 75) : stream.Length;

                    /*
                     * FIXME: Seems numLoops == 0 and numLoops == 1 both indicate a single repetition,
                     * while all other positive numbers indicate precisely the number of desired
                     * repetitions. Finally, -1 means infinitely many
                     */
                    _emulating = true;
                    _handle    = _mixer.PlayStream(SoundType.Music, LoopingAudioStream.Create(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops), -1, _cd.volume, _cd.balance);
                }
                else
                {
                    _emulating = false;
                    if (!only_emulate)
                    {
                        PlayCD(track, numLoops, startFrame, duration);
                    }
                }
            }
        }
コード例 #29
0
        public bool PlayPsx(ushort id, bool loop)
        {
            Stop();

            string path;

            if (_file == null)
            {
                path = ScummHelper.LocatePath(_directory, "tunes.dat");
                if (path == null)
                {
                    return(false);
                }
                _file = ServiceLocator.FileStorage.OpenFileRead(path);
            }

            path = ScummHelper.LocatePath(_directory, "tunes.tab");
            if (path == null)
            {
                return(false);
            }

            uint offset;
            int  size;

            using (var tableFile = ServiceLocator.FileStorage.OpenFileRead(path))
            {
                var br = new BinaryReader(tableFile);
                tableFile.Seek((id - 1) * 8, SeekOrigin.Begin);
                offset = br.ReadUInt32() * 0x800;
                size   = br.ReadInt32();
            }

            // Because of broken tunes.dat/tab in psx demo, also check that tune offset is
            // not over file size
            if ((size != 0) && (size != int.MaxValue) && ((int)(offset + size) <= _file.Length))
            {
                _file.Seek(offset, SeekOrigin.Begin);
                var br = new BinaryReader(_file);
                var ms = new MemoryStream(br.ReadBytes(size));
                _audioSource = new LoopingAudioStream(new XAStream(ms, 11025), loop ? 0 : 1);
                FadeUp();
            }
            else
            {
                _audioSource = null;
                return(false);
            }

            return(true);
        }
コード例 #30
0
        void StartSoundEx(int sound, int velo, int pan, int note)
        {
            var ptr    = _vm.ResourceManager.GetSound(_vm.Sound.MusicType, sound);
            var offset = 2;

            if (pan > 99)
            {
                pan = 99;
            }

            velo = velo != 0 ? (velo * ptr[offset + 14] + 50) / 100 : ptr[offset + 14];
            velo = ScummHelper.Clip(velo, 1, 255);
            ushort pri = ptr.ToUInt16(offset + 10);

            if (ptr[offset + 13] == 0)
            {
                velo >>= 1;

                if (velo == 0)
                {
                    velo = 1;
                }

                pan = pan != 0 ? (((pan << 7) - pan) + 50) / 100 : 64;

                PlayPcmTrack(sound, ptr, offset + 6, velo != 0 ? velo : ptr[offset + 14] >> 1, pan, note != 0 ? note : ptr[offset + 50], pri);
            }
            else if (ptr[offset + 13] == 2)
            {
                int volLeft  = velo;
                int volRight = velo;

                if (pan < 50)
                {
                    volRight = ((pan * 2 + 1) * velo + 50) / 100;
                }
                else if (pan > 50)
                {
                    volLeft = (((99 - pan) * 2 + 1) * velo + 50) / 100;
                }

                SetVolumeCD(volLeft, volRight);

                if (_cdaForceRestart == 0 && sound == _cdaCurrentSound)
                {
                    return;
                }

                PlayCdaTrack(sound, ptr, offset + 6, true);
            }
        }