コード例 #1
0
ファイル: Sound.cs プロジェクト: scemino/nscumm
        private void InitCowSystem()
        {
            if (SystemVars.CurrentCd == 0)
                return;

            if (_cowFile == null)
            {
                var cowName = $"SPEECH{SystemVars.CurrentCd}.CLF";
                _cowFile = TryToOpen(cowName);
                //if (_cowFile.isOpen())
                //{
                //    debug(1, "Using FLAC compressed Speech Cluster");
                //}
                _cowMode = CowMode.CowFLAC;
            }

            if (_cowFile == null)
            {
                var cowName = $"SPEECH{SystemVars.CurrentCd}.CLU";
                _cowFile = TryToOpen(cowName);
                //if (!_cowFile.isOpen())
                //{
                //    _cowFile.open("speech.clu");
                //}
                // TODO: debug(1, "Using uncompressed Speech Cluster");
                _cowMode = CowMode.CowWave;
            }

            if (SystemVars.Platform == Platform.PSX)
            {
                // There's only one file on the PSX, so set it to the current disc.
                _currentCowFile = (byte)SystemVars.CurrentCd;
                if (_cowFile == null)
                {
                    _cowFile = TryToOpen("speech.dat");
                    _cowMode = CowMode.CowPSX;
                }
            }

            if (_cowFile == null)
                _cowFile = TryToOpen("speech.clu");

            if (_cowFile == null)
            {
                _cowFile = TryToOpen("cows.mad");
                _cowMode = CowMode.CowDemo;
            }

            if (_cowFile != null)
            {
                if (SystemVars.Platform == Platform.PSX)
                {
                    // Get data from the external table file
                    using (var tableFile = TryToOpen("speech.tab"))
                    {
                        _cowHeaderSize = (uint)tableFile.BaseStream.Length;
                        _cowHeader = new UIntAccess(new byte[_cowHeaderSize], 0);
                        if ((_cowHeaderSize & 3) != 0)
                            throw new InvalidOperationException($"Unexpected cow header size {_cowHeaderSize}");
                        for (var cnt = 0; cnt < _cowHeaderSize / 4; cnt++)
                            _cowHeader[cnt] = tableFile.ReadUInt32();
                    }
                }
                else
                {
                    _cowHeaderSize = _cowFile.ReadUInt32();
                    _cowHeader = new UIntAccess(new byte[_cowHeaderSize], 0);
                    if ((_cowHeaderSize & 3) != 0)
                        throw new InvalidOperationException("Unexpected cow header size {_cowHeaderSize}");
                    for (var cnt = 0; cnt < (_cowHeaderSize / 4) - 1; cnt++)
                        _cowHeader[cnt] = _cowFile.ReadUInt32();
                    _currentCowFile = (byte)SystemVars.CurrentCd;
                }
            }
            else
            {
                // TODO: warning($"Sound::initCowSystem: Can't open SPEECH{SystemVars.CurrentCd}.CLU");
            }
        }
コード例 #2
0
ファイル: ObjectMan.cs プロジェクト: scemino/nscumm
        public uint FnCheckForTextLine(uint textId)
        {
            byte retVal = 0;
            if (_textList[textId / ITM_PER_SEC, 0] == 0)
                return 0; // section does not exist

            byte lang = (byte)SystemVars.Language;
            var textData = new UIntAccess(_resMan.OpenFetchRes(_textList[textId / ITM_PER_SEC, lang]), Header.Size);
            if ((textId & ITM_ID) < _resMan.ReadUInt32(textData[0]))
            {
                textData.Offset += 4;
                if (textData[(int)(textId & ITM_ID)] != 0)
                    retVal = 1;
            }
            _resMan.ResClose(_textList[textId / ITM_PER_SEC, lang]);
            return retVal;
        }
コード例 #3
0
ファイル: ResMan.cs プロジェクト: scemino/nscumm
 private void OpenScriptResourceLittleEndian(uint id)
 {
     bool needByteSwap = false;
     if (_isBigEndian)
     {
         // Cluster files are in big endian fomat.
         // If the resource are not in memory anymore, and therefore will be read
         // from disk, they will need to be byte swaped.
         MemHandle memHandle = ResHandle(id);
         if (memHandle != null)
             needByteSwap = (memHandle.cond == MemMan.MEM_FREED);
     }
     ResOpen(id);
     if (needByteSwap)
     {
         MemHandle handle = ResHandle(id);
         if (handle == null)
             return;
         // uint32 totSize = handle.size;
         Header head = new Header(handle.data);
         head.comp_length = ScummHelper.SwapBytes(head.comp_length);
         head.decomp_length = ScummHelper.SwapBytes(head.decomp_length);
         head.version = ScummHelper.SwapBytes(head.version);
         UIntAccess data = new UIntAccess(handle.data, Header.Size);
         uint size = handle.size - Header.Size;
         if ((size & 3) != 0)
             throw new InvalidOperationException($"Odd size during script endian conversion. Resource ID ={id}, size = {size}");
         size >>= 2;
         for (uint cnt = 0; cnt < size; cnt++)
         {
             data[0] = ScummHelper.SwapBytes(data[0]);
             data.Offset += 4;
         }
     }
 }
コード例 #4
0
ファイル: Sound.cs プロジェクト: scemino/nscumm
 public void CloseCowSystem()
 {
     _cowFile.Dispose();
     _cowFile = null;
     _cowHeader = null;
     _currentCowFile = 0;
 }
コード例 #5
0
ファイル: Screen.cs プロジェクト: scemino/nscumm
        private void RenderParallax(byte[] data)
        {
            ushort paraScrlX, paraScrlY;
            ushort scrnScrlX, scrnScrlY;
            ushort scrnWidth, scrnHeight;
            ushort paraSizeX, paraSizeY;
            ParallaxHeader header = null;
            UIntAccess lineIndexes = null;

            if (SystemVars.Platform == Platform.PSX) //Parallax headers are different in PSX version
                FetchPsxParallaxSize(data, out paraSizeX, out paraSizeY);
            else
            {
                header = new ParallaxHeader(data);
                lineIndexes = new UIntAccess(data, ParallaxHeader.Size);
                paraSizeX = _resMan.ReadUInt16(header.sizeX);
                paraSizeY = _resMan.ReadUInt16(header.sizeY);
            }

            Debug.Assert((paraSizeX >= SCREEN_WIDTH) && (paraSizeY >= SCREEN_DEPTH));

            // we have to render more than the visible screen part for displaying scroll frames
            scrnScrlX = (ushort)Math.Min((uint)_oldScrollX, Logic.ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_X]);
            scrnWidth = (ushort)(SCREEN_WIDTH + Math.Abs((int)_oldScrollX - (int)Logic.ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_X]));
            scrnScrlY = (ushort)Math.Min((uint)_oldScrollY, Logic.ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_Y]);
            scrnHeight = (ushort)(SCREEN_DEPTH + Math.Abs((int)_oldScrollY - (int)Logic.ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_Y]));


            if (_scrnSizeX != SCREEN_WIDTH)
            {
                double scrlfx = (paraSizeX - SCREEN_WIDTH) / ((double)(_scrnSizeX - SCREEN_WIDTH));
                paraScrlX = (ushort)(scrnScrlX * scrlfx);
            }
            else
                paraScrlX = 0;

            if (_scrnSizeY != SCREEN_DEPTH)
            {
                double scrlfy = (paraSizeY - SCREEN_DEPTH) / ((double)(_scrnSizeY - SCREEN_DEPTH));
                paraScrlY = (ushort)(scrnScrlY * scrlfy);
            }
            else
                paraScrlY = 0;

            if (SystemVars.Platform == Platform.PSX)
            {
                DrawPsxParallax(data, paraScrlX, scrnScrlX, scrnWidth);
            }
            else
            {
                for (ushort cnty = 0; cnty < scrnHeight; cnty++)
                {
                    var src = _resMan.ReadUInt32(lineIndexes[cnty + paraScrlY]);
                    var dest = scrnScrlX + (cnty + scrnScrlY) * _scrnSizeX;
                    ushort remain = paraScrlX;
                    ushort xPos = 0;
                    while (remain != 0)
                    {
                        // skip past the first part of the parallax to get to the right scrolling position
                        byte doSkip = data[src++];
                        if (doSkip <= remain)
                            remain -= doSkip;
                        else
                        {
                            xPos = (ushort)(doSkip - remain);
                            dest += xPos;
                            remain = 0;
                        }
                        byte doCopy = data[src++];
                        if (doCopy <= remain)
                        {
                            remain -= doCopy;
                            src += doCopy;
                        }
                        else
                        {
                            ushort remCopy = (ushort)(doCopy - remain);
                            Array.Copy(data, (int)(src + remain), _screenBuf, dest, remCopy);
                            dest += remCopy;
                            src += doCopy;
                            xPos = remCopy;
                            remain = 0;
                        }
                    }
                    while (xPos < scrnWidth)
                    {
                        byte skip;
                        if ((skip = data[src++]) != 0)
                        {
                            dest += skip;
                            xPos += skip;
                        }
                        if (xPos < scrnWidth)
                        {
                            byte doCopy;
                            if ((doCopy = data[src++]) != 0)
                            {
                                if (xPos + doCopy > scrnWidth)
                                    doCopy = (byte)(scrnWidth - xPos);
                                Array.Copy(data, (int)src, _screenBuf, dest, doCopy);
                                dest += doCopy;
                                xPos += doCopy;
                                src += doCopy;
                            }
                        }
                    }
                }
            }
        }
コード例 #6
0
ファイル: Control.cs プロジェクト: scemino/nscumm
        void SaveThumbnail(BinaryWriter output, Surface thumb)
        {
            var bpp = Surface.GetBytesPerPixel(thumb.PixelFormat);
            if (bpp != 2 && bpp != 4)
            {
                // TODO: warning("trying to save thumbnail with bpp %u", bpp);
                return;
            }

            ThumbnailHeader header = new ThumbnailHeader();
            header.Type = ScummHelper.MakeTag('T', 'H', 'M', 'B');
            header.Size = (uint)(ThumbnailHeaderSize + thumb.Width * thumb.Height * bpp);
            header.Version = THMB_VERSION;
            header.Width = (ushort)thumb.Width;
            header.Height = (ushort)thumb.Height;

            output.WriteUInt32BigEndian(header.Type);
            output.WriteUInt32BigEndian(header.Size);
            output.WriteByte(header.Version);
            output.WriteUInt16BigEndian(header.Width);
            output.WriteUInt16BigEndian(header.Height);

            // Serialize the PixelFormat
            output.WriteByte(bpp);
            output.WriteByte(3);
            output.WriteByte(2);
            output.WriteByte(3);
            output.WriteByte(8);
            output.WriteByte(11);
            output.WriteByte(5);
            output.WriteByte(0);
            output.WriteByte(0);

            // Serialize the pixel data
            for (uint y = 0; y < thumb.Height; ++y)
            {
                switch (bpp)
                {
                    case 2:
                        {
                            var pixels = new UShortAccess(thumb.Pixels, (int)(y * thumb.Width * 2));
                            for (uint x = 0; x < thumb.Width; ++x)
                            {
                                output.WriteUInt16BigEndian(pixels[0]);
                                pixels.Offset += 2;
                            }
                        }
                        break;

                    case 4:
                        {
                            var pixels = new UIntAccess(thumb.Pixels, (int)(y * thumb.Width * 4));
                            for (var x = 0; x < thumb.Width; ++x)
                            {
                                output.WriteUInt32BigEndian(pixels[0]);
                                pixels.Offset += 4;
                            }
                        }
                        break;

                    default:
                        throw new NotSupportedException();
                }
            }
        }
コード例 #7
0
ファイル: Control.cs プロジェクト: scemino/nscumm
        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;
        }
コード例 #8
0
ファイル: Control.cs プロジェクト: scemino/nscumm
        public void DoRestore()
        {
            var bufPos = new ByteAccess(_restoreBuf);
            _objMan.LoadLiveList(new UShortAccess(_restoreBuf));
            bufPos.Offset += ObjectMan.TOTAL_SECTIONS * 2;
            for (var cnt = 0; cnt < Logic.NUM_SCRIPT_VARS; cnt++)
            {
                Logic.ScriptVars[cnt] = bufPos.Data.ToUInt32(bufPos.Offset);
                bufPos.Offset += 4;
            }
            uint playerSize = (SwordObject.Size - 12000) / 4;
            var cpt = _objMan.FetchObject(Logic.PLAYER);
            var playerRaw = new UIntAccess(cpt.Data, cpt.Offset);

            for (var cnt2 = 0; cnt2 < playerSize; cnt2++)
            {
                playerRaw[0] = bufPos.Data.ToUInt32(bufPos.Offset);
                playerRaw.Offset += 4;
                bufPos.Offset += 4;
            }

            Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_DIR] = (uint)cpt.dir;
            Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_X] = (uint)cpt.xcoord;
            Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_Y] = (uint)cpt.ycoord;
            Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_STANCE] = StaticRes.STAND;
            Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_PLACE] = (uint)cpt.place;
            SystemVars.JustRestoredGame = 1;
            if (SystemVars.IsDemo)
                Logic.ScriptVars[(int)ScriptVariableNames.PLAYINGDEMO] = 1;
        }
コード例 #9
0
ファイル: Control.cs プロジェクト: scemino/nscumm
        private void SaveGameToFile(byte slot)
        {
            ushort cnt;
            var fName = $"sword1.{slot:D3}";
            ushort[] liveBuf = new ushort[ObjectMan.TOTAL_SECTIONS];

            using (var stream = _saveFileMan.OpenForSaving(fName))
            using (var outf = new BinaryWriter(stream))
            {
                //if (!outf)
                //{
                //    // Display an error message and do nothing
                //    displayMessage(0, "Unable to create file '%s'. (%s)", fName, _saveFileMan.popErrorDesc().c_str());
                //    return;
                //}

                outf.WriteUInt32((uint)SAVEGAME_HEADER);

                outf.Write(StrToBytes(_saveNames[slot], 40));
                outf.WriteByte(SAVEGAME_VERSION);

                if (!IsPanelShown()) // Generate a thumbnail only if we are outside of game menu
                    SaveThumbnail(outf);

                // Date / time
                DateTime curTime = DateTime.Now;

                uint saveDate =
                    (uint)
                        ((curTime.Day & 0xFF) << 24 | ((curTime.Month + 1) & 0xFF) << 16 |
                         ((curTime.Year + 1900) & 0xFFFF));
                ushort saveTime = (ushort)((curTime.Hour & 0xFF) << 8 | ((curTime.Minute) & 0xFF));

                outf.WriteUInt32BigEndian(saveDate);
                outf.WriteUInt16BigEndian(saveTime);

                // TODO: outf.WriteUInt32BigEndian(g_engine.getTotalPlayTime() / 1000); replaced by 0
                outf.WriteUInt32BigEndian(0);

                _objMan.SaveLiveList(liveBuf);
                for (cnt = 0; cnt < ObjectMan.TOTAL_SECTIONS; cnt++)
                    outf.WriteUInt16(liveBuf[cnt]);

                var cpt = _objMan.FetchObject(Logic.PLAYER);
                Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_DIR] = (uint)cpt.dir;
                Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_X] = (uint)cpt.xcoord;
                Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_Y] = (uint)cpt.ycoord;
                Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_STANCE] = StaticRes.STAND;
                Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_PLACE] = (uint)cpt.place;

                for (cnt = 0; cnt < Logic.NUM_SCRIPT_VARS; cnt++)
                    outf.WriteUInt32(Sword1.Logic.ScriptVars[cnt]);

                uint playerSize = (SwordObject.Size - 12000) / 4;
                var playerRaw = new UIntAccess(cpt.Data, cpt.Offset);
                for (var cnt2 = 0; cnt2 < playerSize; cnt2++)
                    outf.WriteUInt32(playerRaw[cnt2]);
            }
            // TODO: error
            //if (outf.err())
            //    displayMessage(0, "Couldn't write to file '%s'. Device full? (%s)", fName, _saveFileMan.popErrorDesc().c_str());
            //delete outf;
        }