示例#1
0
 public ControlButton(ushort x, ushort y, uint resId, ButtonIds id, byte flag, ResMan pResMan, byte[] screenBuf,
     ISystem system)
 {
     _x = x;
     _y = y;
     _id = id;
     _flag = flag;
     _resId = resId;
     _resMan = pResMan;
     _frameIdx = 0;
     _resMan.ResOpen(_resId);
     FrameHeader tmp = new FrameHeader(_resMan.FetchFrame(_resMan.FetchRes(_resId), 0));
     _width = _resMan.ReadUInt16(tmp.width);
     _width = (ushort)((_width > Screen.SCREEN_WIDTH) ? Screen.SCREEN_WIDTH : _width);
     _height = _resMan.ReadUInt16(tmp.height);
     if ((x == 0) && (y == 0))
     { // center the frame (used for panels);
         _x = (ushort)((((640 - _width) / 2) < 0) ? 0 : ((640 - _width) / 2));
         _y = (ushort)((((480 - _height) / 2) < 0) ? 0 : ((480 - _height) / 2));
     }
     _dstBuf = new ByteAccess(screenBuf, _y * Screen.SCREEN_WIDTH + _x);
     _system = system;
 }
示例#2
0
        public void Draw()
        {
            FrameHeader fHead = new FrameHeader(_resMan.FetchFrame(_resMan.FetchRes(_resId), (uint)_frameIdx));
            ByteAccess src = new ByteAccess(fHead.Data.Data, fHead.Data.Offset + FrameHeader.Size);
            var dst = new ByteAccess(_dstBuf);

            if (SystemVars.Platform == Platform.PSX && _resId != 0)
            {
                var HIFbuf = new byte[_resMan.ReadUInt16(fHead.height) * _resMan.ReadUInt16(fHead.width)];
                Screen.DecompressHIF(src.Data, src.Offset, HIFbuf);
                src = new ByteAccess(HIFbuf);

                if (_resMan.ReadUInt16(fHead.width) < 300)
                    for (var cnt = 0; cnt < _resMan.ReadUInt16(fHead.height); cnt++)
                    {
                        for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width); cntx++)
                            if (src[cntx] != 0)
                                dst[cntx] = src[cntx];

                        dst.Offset += Screen.SCREEN_WIDTH;
                        for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width); cntx++)
                            if (src[cntx] != 0)
                                dst[cntx] = src[cntx];

                        dst.Offset += Screen.SCREEN_WIDTH;
                        src.Offset += _resMan.ReadUInt16(fHead.width);
                    }
                else if (_resId == SwordRes.SR_DEATHPANEL)
                { // Check for death panel psx version (which is 1/3 of original width)
                    for (var cnt = 0; cnt < _resMan.ReadUInt16(fHead.height) / 2; cnt++)
                    {
                        //Stretched panel is bigger than 640px, check we don't draw outside screen
                        for (var cntx = 0; (cntx < (_resMan.ReadUInt16(fHead.width)) / 3) && (cntx < (Screen.SCREEN_WIDTH - 3)); cntx++)
                            if (src[cntx] != 0)
                            {
                                dst[cntx * 3] = src[cntx];
                                dst[cntx * 3 + 1] = src[cntx];
                                dst[cntx * 3 + 2] = src[cntx];
                            }
                        dst.Offset += Screen.SCREEN_WIDTH;

                        for (var cntx = 0; cntx < (_resMan.ReadUInt16(fHead.width)) / 3; cntx++)
                            if (src[cntx] != 0)
                            {
                                dst[cntx * 3] = src[cntx];
                                dst[cntx * 3 + 1] = src[cntx];
                                dst[cntx * 3 + 2] = src[cntx];
                            }
                        dst.Offset += Screen.SCREEN_WIDTH;
                        src.Offset += _resMan.ReadUInt16(fHead.width) / 3;
                    }
                }
                else
                { //save slots needs to be multiplied by 2 in height
                    for (var cnt = 0; cnt < _resMan.ReadUInt16(fHead.height); cnt++)
                    {
                        for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width) / 2; cntx++)
                            if (src[cntx] != 0)
                            {
                                dst[cntx * 2] = src[cntx];
                                dst[cntx * 2 + 1] = src[cntx];
                            }

                        dst.Offset += Screen.SCREEN_WIDTH;
                        for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width) / 2; cntx++)
                            if (src[cntx] != 0)
                            {
                                dst[cntx * 2] = src[cntx];
                                dst[cntx * 2 + 1] = src[cntx];
                            }

                        dst.Offset += Screen.SCREEN_WIDTH;
                        src.Offset += _resMan.ReadUInt16(fHead.width) / 2;
                    }
                }
            }
            else
                for (var cnt = 0; cnt < _resMan.ReadUInt16(fHead.height); cnt++)
                {
                    for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width); cntx++)
                        if (src[cntx] != 0)
                            dst[cntx] = src[cntx];

                    dst.Offset += Screen.SCREEN_WIDTH;
                    src.Offset += _resMan.ReadUInt16(fHead.width);
                }

            _system.GraphicsManager.CopyRectToScreen(_dstBuf.Data, _dstBuf.Offset, Screen.SCREEN_WIDTH, _x, _y, _width, _height);
        }
示例#3
0
文件: Text.cs 项目: scemino/nscumm
        public void MakeTextSprite(byte slot, ByteAccess text, ushort maxWidth, byte pen)
        {
            var lines = new LineInfo[MaxLines];
            var numLines = AnalyzeSentence(text, maxWidth, lines);

            ushort sprWidth = 0;
            ushort lineCnt;
            for (lineCnt = 0; lineCnt < numLines; lineCnt++)
                if (lines[lineCnt].Width > sprWidth)
                    sprWidth = lines[lineCnt].Width;

            var sprHeight = (ushort)(_charHeight * numLines);
            var sprSize = (uint)(sprWidth * sprHeight);
            Debug.Assert(_textBlocks[slot] == null); // if this triggers, the speechDriver failed to call Text::releaseText.
            _textBlocks[slot] = new FrameHeader(new byte[sprSize + FrameHeader.Size]);

            Array.Copy(new[] { (byte)'N', (byte)'u', (byte)' ', (byte)' ' }, 0, _textBlocks[slot].runTimeComp.Data, _textBlocks[slot].runTimeComp.Offset, 4);
            _textBlocks[slot].compSize = 0;
            _textBlocks[slot].width = _resMan.ReadUInt16(sprWidth);
            _textBlocks[slot].height = _resMan.ReadUInt16(sprHeight);
            _textBlocks[slot].offsetX = 0;
            _textBlocks[slot].offsetY = 0;

            var linePtr = new ByteAccess(_textBlocks[slot].Data.Data, _textBlocks[slot].Data.Offset + FrameHeader.Size);
            linePtr.Data.Set(linePtr.Offset, NoCol, (int)sprSize);
            for (lineCnt = 0; lineCnt < numLines; lineCnt++)
            {
                var sprPtr = (sprWidth - lines[lineCnt].Width) / 2; // center the text
                for (ushort pos = 0; pos < lines[lineCnt].Length; pos++)
                {
                    sprPtr += CopyChar(text[0], new ByteAccess(linePtr.Data, linePtr.Offset + sprPtr), sprWidth, pen) - Overlap;
                    text.Offset++;
                }
                text.Offset++; // skip space at the end of the line
                if (SystemVars.Platform == Platform.PSX) //Chars are half height in psx version
                    linePtr.Offset += _charHeight / 2 * sprWidth;
                else
                    linePtr.Offset += _charHeight * sprWidth;
            }
        }
示例#4
0
文件: Text.cs 项目: scemino/nscumm
        private ushort CopyChar(byte ch, ByteAccess sprPtr, ushort sprWidth, byte pen)
        {
            if (ch < ' ')
                ch = 64;
            var chFrame = new FrameHeader(_resMan.FetchFrame(_font, (uint)(ch - ' ')));
            var chData = FrameHeader.Size;
            var dest = sprPtr;
            ByteAccess decChr;
            ushort frameHeight;

            if (SystemVars.Platform == Platform.PSX)
            {
                frameHeight = (ushort)(_resMan.ReadUInt16(chFrame.height) / 2);
                if (_fontId == SwordRes.CZECH_GAME_FONT)
                { //Czech game fonts are compressed
                    var decBuf = new byte[_resMan.ReadUInt16(chFrame.width) * (_resMan.ReadUInt16(chFrame.height) / 2)];
                    Screen.DecompressHIF(chFrame.Data.Data, chFrame.Data.Offset + chData, decBuf);
                    decChr = new ByteAccess(decBuf);
                }
                else //Normal game fonts are not compressed
                    decChr = new ByteAccess(chFrame.Data.Data, chFrame.Data.Offset + chData);
            }
            else
            {
                frameHeight = _resMan.ReadUInt16(chFrame.height);
                decChr = new ByteAccess(chFrame.Data.Data, chFrame.Data.Offset + chData);
            }

            for (ushort cnty = 0; cnty < frameHeight; cnty++)
            {
                for (ushort cntx = 0; cntx < _resMan.ReadUInt16(chFrame.width); cntx++)
                {
                    if (decChr[0] == LetterCol)
                        dest[cntx] = pen;
                    else if (((decChr[0] == BorderCol) || (decChr[0] == BorderColPsx)) && (dest[cntx] == 0)) // don't do a border if there's already a color underneath (chars can overlap)
                        dest[cntx] = BorderCol;
                    decChr.Offset++;
                }
                dest.Offset += sprWidth;
            }

            return _resMan.ReadUInt16(chFrame.width);
        }
示例#5
0
文件: Screen.cs 项目: scemino/nscumm
        private void ProcessImage(uint id)
        {
            FrameHeader frameHead;
            int scale;

            var compact = _objMan.FetchObject(id);

            if (compact.type == TYPE_TEXT)
                frameHead = new FrameHeader(_textMan.GiveSpriteData((byte)compact.target));
            else
                frameHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes((uint)compact.resource), (uint)compact.frame));

            ushort spriteX = (ushort)compact.anim_x;
            ushort spriteY = (ushort)compact.anim_y;


            if ((compact.status & STAT_SHRINK) != 0)
            {
                scale = (compact.scale_a * compact.ycoord + compact.scale_b) / 256;
                spriteX = (ushort)(spriteX + (_resMan.ReadInt16(frameHead.offsetX) * scale) / 256);
                spriteY = (ushort)(spriteY + (_resMan.ReadInt16(frameHead.offsetY) * scale) / 256);
            }
            else
            {
                scale = 256;
                spriteX = (ushort)(spriteX + _resMan.ReadInt16(frameHead.offsetX));
                spriteY = (ushort)(spriteY + _resMan.ReadInt16(frameHead.offsetY));
            }

            var sprData = new ByteAccess(frameHead.Data.Data, frameHead.Data.Offset + FrameHeader.Size);
            if (SystemVars.Platform == Platform.PSX && compact.type != TYPE_TEXT)
            {
                // PSX sprites are compressed with HIF
                var hifBuf = new byte[_resMan.ReadUInt16(frameHead.width) * _resMan.ReadUInt16(frameHead.height) / 2];
                DecompressHIF(sprData.Data, sprData.Offset, hifBuf);
                sprData = new ByteAccess(hifBuf);
            }
            else if (frameHead.runTimeComp[3] == '7')
            { // RLE7 encoded?
                DecompressRLE7(sprData.Data, sprData.Offset, _resMan.ReadUInt32(frameHead.compSize), _rleBuffer);
                sprData = new ByteAccess(_rleBuffer);
            }
            else if (frameHead.runTimeComp[3] == '0')
            { // RLE0 encoded?
                DecompressRLE0(sprData.Data, sprData.Offset, _resMan.ReadUInt32(frameHead.compSize), _rleBuffer);
                sprData = new ByteAccess(_rleBuffer);
            }
            else if (frameHead.runTimeComp[1] == 'I')
            { // new type
                var tonyBuf = new byte[_resMan.ReadUInt32(frameHead.width) * _resMan.ReadUInt16(frameHead.height)];
                DecompressTony(sprData.Data, sprData.Offset, _resMan.ReadUInt32(frameHead.compSize), tonyBuf);
                sprData = new ByteAccess(tonyBuf);
            }

            ushort sprSizeX, sprSizeY;
            if ((compact.status & STAT_SHRINK) != 0)
            {
                //Clean shrink buffer to avoid corruption
                Array.Clear(_shrinkBuffer, 0, SHRINK_BUFFER_SIZE);
                if (SystemVars.Platform == Platform.PSX && (compact.resource != SwordRes.GEORGE_MEGA))
                {
                    // PSX Height shrinked sprites
                    sprSizeX = (ushort)((scale * _resMan.ReadUInt16(frameHead.width)) / 256);
                    sprSizeY = (ushort)((scale * (_resMan.ReadUInt16(frameHead.height))) / 256 / 2);
                    FastShrink(sprData, _resMan.ReadUInt16(frameHead.width), (ushort)((_resMan.ReadUInt16(frameHead.height)) / 2), (uint)scale, _shrinkBuffer);
                }
                else if (SystemVars.Platform == Platform.PSX)
                {
                    // PSX width/height shrinked sprites
                    sprSizeX = (ushort)((scale * _resMan.ReadUInt16(frameHead.width)) / 256 / 2);
                    sprSizeY = (ushort)((scale * _resMan.ReadUInt16(frameHead.height)) / 256 / 2);
                    FastShrink(sprData, (ushort)(_resMan.ReadUInt16(frameHead.width) / 2), (ushort)(_resMan.ReadUInt16(frameHead.height) / 2), (uint)scale, _shrinkBuffer);
                }
                else
                {
                    sprSizeX = (ushort)(scale * _resMan.ReadUInt16(frameHead.width) / 256);
                    sprSizeY = (ushort)(scale * _resMan.ReadUInt16(frameHead.height) / 256);
                    FastShrink(sprData, _resMan.ReadUInt16(frameHead.width), _resMan.ReadUInt16(frameHead.height), (uint)scale, _shrinkBuffer);
                }
                sprData = new ByteAccess(_shrinkBuffer);
            }
            else
            {
                sprSizeX = _resMan.ReadUInt16(frameHead.width);
                if (SystemVars.Platform == Platform.PSX)
                {
                    // PSX sprites are half height
                    sprSizeY = (ushort)(_resMan.ReadUInt16(frameHead.height) / 2);
                }
                else
                    sprSizeY = _resMan.ReadUInt16(frameHead.height);
            }

            if ((compact.status & STAT_OVERRIDE) == 0)
            {
                //mouse size linked to exact size & coordinates of sprite box - shrink friendly
                if (_resMan.ReadUInt16((ushort)frameHead.offsetX) != 0 || _resMan.ReadUInt16((ushort)frameHead.offsetY) != 0)
                {
                    //for megas the mouse area is reduced to account for sprite not
                    //filling the box size is reduced to 1/2 width, 4/5 height
                    compact.mouse_x1 = spriteX + sprSizeX / 4;
                    compact.mouse_x2 = spriteX + 3 * sprSizeX / 4;
                    compact.mouse_y1 = spriteY + sprSizeY / 10;
                    compact.mouse_y2 = spriteY + 9 * sprSizeY / 10;
                }
                else
                {
                    compact.mouse_x1 = spriteX;
                    compact.mouse_x2 = spriteX + sprSizeX;
                    compact.mouse_y1 = spriteY;
                    compact.mouse_y2 = spriteY + sprSizeY;
                }
            }

            ushort sprPitch = sprSizeX;
            ushort incr;
            SpriteClipAndSet(ref spriteX, ref spriteY, ref sprSizeX, ref sprSizeY, out incr);

            if ((sprSizeX > 0) && (sprSizeY > 0))
            {
                if (SystemVars.Platform != Platform.PSX || (compact.type == TYPE_TEXT)
                    || (compact.resource == SwordRes.LVSFLY) || (compact.resource != SwordRes.GEORGE_MEGA && (sprSizeX < 260)))
                {
                    sprData.Offset += incr;
                    DrawSprite(sprData, spriteX, spriteY, sprSizeX, sprSizeY, sprPitch);
                }
                else if (((sprSizeX >= 260) && (sprSizeX < 450)) || ((compact.resource == SwordRes.GMWRITH) && (sprSizeX < 515))
                         // a psx shrinked sprite (1/2 width)
                         || ((compact.resource == SwordRes.GMPOWER) && (sprSizeX < 515)))
                {
                    // some needs to be hardcoded, headers don't give useful infos
                    DrawPsxHalfShrinkedSprite(sprData.Data, sprData.Offset + incr, spriteX, spriteY, (ushort)(sprSizeX / 2), sprSizeY, (ushort)(sprPitch / 2));
                }
                else if (sprSizeX >= 450) // A PSX double shrinked sprite (1/3 width)
                {
                    DrawPsxFullShrinkedSprite(sprData.Data, sprData.Offset + incr, spriteX, spriteY, (ushort)(sprSizeX / 3), sprSizeY, (ushort)(sprPitch / 3));
                }
                else // This is for psx half shrinked, walking george and remaining sprites
                {
                    DrawPsxHalfShrinkedSprite(sprData.Data, sprData.Offset + incr, spriteX, spriteY, sprSizeX, sprSizeY, sprPitch);
                }
                if ((compact.status & STAT_FORE) == 0 &&
                    !(SystemVars.Platform == Platform.PSX && (compact.resource == SwordRes.MOUBUSY)))
                // Check fixes moue sprite being masked by layer, happens only on psx
                {
                    VerticalMask(spriteX, spriteY, sprSizeX, sprSizeY);
                }
            }

            if (compact.type != TYPE_TEXT)
                _resMan.ResClose((uint)compact.resource);
        }
示例#6
0
        private void PerformPostProcessing(byte[] screen)
        {
            // TODO: We don't support displaying these in true color yet,
            // nor using the PSX fonts to display subtitles.
            if (SystemVars.Platform == Core.IO.Platform.PSX /* || _decoderType == kVideoDecoderMP2*/)
                return;

            if (_movieTexts.Count > 0)
            {
                if (_decoder.CurrentFrame == _movieTexts[0]._startFrame)
                {
                    var text = new ByteAccess(System.Text.Encoding.UTF8.GetBytes(_movieTexts[0]._text));
                    _textMan.MakeTextSprite(2, text, 600, Text.LetterCol);

                    var frame = new FrameHeader(_textMan.GiveSpriteData(2));
                    _textWidth = _resMan.ReadUInt16(frame.width);
                    _textHeight = _resMan.ReadUInt16(frame.height);
                    _textX = 320 - _textWidth / 2;
                    _textY = 420 - _textHeight;
                    _textColor = _movieTexts[0]._color;
                }
                if (_decoder.CurrentFrame == _movieTexts[0]._endFrame)
                {
                    _textMan.ReleaseText(2, false);
                    _movieTexts.RemoveAt(0);
                }
            }

            ByteAccess src, dst;
            int x, y;

            if (_textMan.GiveSpriteData(2) != null)
            {
                src = new ByteAccess(_textMan.GiveSpriteData(2));
                src.Offset += FrameHeader.Size;
                dst = new ByteAccess(screen, _textY * Screen.SCREEN_WIDTH + _textX * 1);

                for (y = 0; y < _textHeight; y++)
                {
                    for (x = 0; x < _textWidth; x++)
                    {
                        switch (src[x])
                        {
                            case Text.BorderCol:
                                dst[x] = (byte)GetBlackColor();
                                break;
                            case Text.LetterCol:
                                dst[x] = (byte)FindTextColor();
                                break;
                        }
                    }
                    src.Offset += _textWidth;
                    dst.Offset += Screen.SCREEN_WIDTH;
                }
            }
            else if (_textX != 0 && _textY != 0)
            {
                // If the frame doesn't cover the entire screen, we have to
                // erase the subtitles manually.

                int frameWidth = _decoder.GetWidth();
                int frameHeight = _decoder.GetHeight();
                int frameX = (_vm.Settings.Game.Width - frameWidth) / 2;
                int frameY = (_vm.Settings.Game.Height - frameHeight) / 2;

                dst = new ByteAccess(screen, _textY * _vm.Settings.Game.Width);

                for (y = 0; y < _textHeight; y++)
                {
                    if (_textY + y < frameY || _textY + y >= frameY + frameHeight)
                    {
                        dst.Data.Set(dst.Offset + _textX, (byte)GetBlackColor(), _textWidth);
                    }
                    else {
                        if (frameX > _textX)
                        {
                            dst.Data.Set(dst.Offset + _textX, (byte)GetBlackColor(), frameX - _textX);
                        }
                        if (frameX + frameWidth < _textX + _textWidth)
                        {
                            dst.Data.Set(dst.Offset + frameX + frameWidth, (byte)GetBlackColor(), _textX + _textWidth - (frameX + frameWidth));
                        }
                    }

                    dst.Offset += _vm.Settings.Game.Width;
                }

                _textX = 0;
                _textY = 0;
            }
        }
示例#7
0
文件: Screen.cs 项目: scemino/nscumm
 public void AddToGraphicList(byte listId, uint objId)
 {
     if (listId == 0)
     {
         Debug.Assert(_foreLength < MAX_FORE);
         _foreList[_foreLength++] = objId;
     }
     if (listId == 1)
     {
         Debug.Assert(_sortLength < MAX_SORT);
         var cpt = _objMan.FetchObject(objId);
         _sortList[_sortLength].id = (int)objId;
         _sortList[_sortLength].y = cpt.anim_y; // gives feet coords if boxed mega, otherwise top of sprite box
         if ((cpt.status & STAT_SHRINK) == 0)
         {     // not a boxed mega using shrinking
             Header frameRaw = new Header(_resMan.OpenFetchRes((uint)cpt.resource));
             FrameHeader frameHead = new FrameHeader(_resMan.FetchFrame(frameRaw.Data, (uint)cpt.frame));
             _sortList[_sortLength].y += _resMan.ReadUInt16(frameHead.height) - 1; // now pointing to base of sprite
             _resMan.ResClose((uint)cpt.resource);
         }
         _sortLength++;
     }
     if (listId == 2)
     {
         Debug.Assert(_backLength < MAX_BACK);
         _backList[_backLength++] = objId;
     }
 }
示例#8
0
文件: Screen.cs 项目: scemino/nscumm
        public void ShowFrame(ushort x, ushort y, uint resId, uint frameNo, byte[] fadeMask = null, sbyte fadeStatus = 0)
        {
            byte[] frame = new byte[40 * 40];
            int i, j;

            // PSX top menu is black
            if (SystemVars.Platform != Platform.PSX)
            {
                // Dark gray background
                frame.Set(0, 199, frame.Length);
            }

            if (resId != 0xffffffff)
            {
                FrameHeader frameHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes(resId), frameNo));
                var frameData = new ByteAccess(frameHead.Data.Data, frameHead.Data.Offset + FrameHeader.Size);

                if (SystemVars.Platform == Platform.PSX)
                {
                    //We need to decompress PSX frames
                    var frameBufferPSX = new byte[_resMan.ReadUInt16(frameHead.width) * _resMan.ReadUInt16(frameHead.height) / 2];
                    DecompressHIF(frameData.Data, frameData.Offset, frameBufferPSX);

                    for (i = 0; i < _resMan.ReadUInt16(frameHead.height) / 2; i++)
                    {
                        for (j = 0; j < _resMan.ReadUInt16(frameHead.width); j++)
                        {
                            var data = frameBufferPSX[i * _resMan.ReadUInt16(frameHead.width) + j];
                            frame[(i * 2 + 4) * 40 + j + 2] = data;
                            frame[(i * 2 + 1 + 4) * 40 + j + 2] = data; //Linedoubling the sprite
                        }
                    }
                }
                else
                {
                    for (i = 0; i < _resMan.ReadUInt16(frameHead.height); i++)
                        for (j = 0; j < _resMan.ReadUInt16(frameHead.height); j++)
                            frame[(i + 4) * 40 + j + 2] = frameData[i * _resMan.ReadUInt16(frameHead.width) + j];
                }

                _resMan.ResClose(resId);
            }

            if (fadeMask != null)
            {
                for (i = 0; i < 40; i++)
                {
                    for (j = 0; j < 40; j++)
                    {
                        if (fadeMask[((i % 8) * 8) + (j % 8)] >= fadeStatus)
                            frame[i * 40 + j] = 0;
                    }
                }
            }

            _system.GraphicsManager.CopyRectToScreen(frame, 40, x, y, 40, 40);
        }
示例#9
0
        private int fnISpeak(SwordObject cpt, int id, int cdt, int textNo, int spr, int f, int z, int x)
        {
            _speechClickDelay = 3;
            if (((textNo & ~1) == 0x3f0012) && (cdt == 0) && (spr == 0))
            {
                cdt = SwordRes.GEOSTDLCDT; // workaround for missing animation when examining
                spr = SwordRes.GEOSTDL;    // the conductor on the train roof
            }
            cpt.logic = LOGIC_speech;

            // first setup the talk animation
            if (cdt != 0 && (spr == 0))
            { // if 'cdt' is non-zero but 'spr' is zero - 'cdt' is an anim table tag
                var animTabData = _resMan.OpenFetchRes((uint)cdt);
                var anim = new AnimSet(animTabData, Header.Size + cpt.dir * AnimSet.Size);

                cpt.anim_resource = (int)_resMan.ReadUInt32(anim.cdt);
                if (anim.cdt != 0)
                    cpt.resource = (int)_resMan.ReadUInt32(anim.spr);
                _resMan.ResClose((uint)cdt);
            }
            else
            {
                cpt.anim_resource = cdt;
                if (cdt != 0)
                    cpt.resource = spr;
            }
            cpt.anim_pc = 0; // start anim from first frame
            if (cpt.anim_resource != 0)
            {
                if (cpt.resource == 0)
                    throw new InvalidOperationException($"ID {id}: Can't run anim with cdt={cdt}, spr={spr}");

                FrameHeader frameHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes((uint)cpt.resource), 0));
                if (frameHead.offsetX != 0 && frameHead.offsetY != 0)
                { // is this a boxed mega?
                    cpt.status |= STAT_SHRINK;
                    cpt.anim_x = cpt.xcoord;
                    cpt.anim_y = cpt.ycoord;
                }
                else
                    cpt.status &= ~STAT_SHRINK;

                _resMan.ResClose((uint)cpt.resource);
            }
            if (SystemVars.PlaySpeech != 0)
                _speechRunning = _sound.StartSpeech((ushort)(textNo >> 16), (ushort)(textNo & 0xFFFF));
            else
                _speechRunning = false;
            _speechFinished = false;
            if (SystemVars.ShowText != 0 || (!_speechRunning))
            {
                _textRunning = true;

                var text = _objMan.LockText((uint) textNo);
                cpt.speech_time = GetTextLength(text) + 5;
                uint textCptId = _textMan.LowTextManager(text, cpt.speech_width, (byte)cpt.speech_pen);
                _objMan.UnlockText((uint) textNo);

                SwordObject textCpt = _objMan.FetchObject(textCptId);
                textCpt.screen = cpt.screen;
                textCpt.target = (int)textCptId;

                // the graphic is a property of Text, so we don't lock/unlock it.
                ushort textSpriteWidth = _resMan.ReadUInt16(new FrameHeader(_textMan.GiveSpriteData((byte)textCpt.target)).width);
                ushort textSpriteHeight = _resMan.ReadUInt16(new FrameHeader(_textMan.GiveSpriteData((byte)textCpt.target)).height);

                cpt.text_id = (int)textCptId;

                // now set text coords, above the player, usually

                const int TEXT_MARGIN = 3; // distance kept from edges of screen
                const int ABOVE_HEAD = 20; // distance kept above talking sprite
                ushort textX, textY;
                if (((id == GEORGE) || ((id == NICO) && (ScriptVars[(int)ScriptVariableNames.SCREEN] == 10))) && (cpt.anim_resource == 0))
                {
                    // if George is doing Voice-Over text (centered at the bottom of the screen)
                    textX = (ushort)(ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_X] + 128 + (640 / 2) - textSpriteWidth / 2);
                    textY = (ushort)(ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_Y] + 128 + 400);
                }
                else
                {
                    if ((id == GEORGE) && (ScriptVars[(int)ScriptVariableNames.SCREEN] == 79))
                        textX = (ushort)cpt.mouse_x2; // move it off george's head
                    else
                        textX = (ushort)((cpt.mouse_x1 + cpt.mouse_x2) / 2 - textSpriteWidth / 2);

                    textY = (ushort)(cpt.mouse_y1 - textSpriteHeight - ABOVE_HEAD);
                }
                // now ensure text is within visible screen
                ushort textLeftMargin, textRightMargin, textTopMargin, textBottomMargin;
                textLeftMargin = (ushort)(Screen.SCREEN_LEFT_EDGE + TEXT_MARGIN + ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_X]);
                textRightMargin = (ushort)(Screen.SCREEN_RIGHT_EDGE - TEXT_MARGIN + ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_X] - textSpriteWidth);
                textTopMargin = (ushort)(Screen.SCREEN_TOP_EDGE + TEXT_MARGIN + ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_Y]);
                textBottomMargin = (ushort)(Screen.SCREEN_BOTTOM_EDGE - TEXT_MARGIN + ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_Y] - textSpriteHeight);

                textCpt.anim_x = textCpt.xcoord = ScummHelper.Clip(textX, textLeftMargin, textRightMargin);
                textCpt.anim_y = textCpt.ycoord = ScummHelper.Clip(textY, textTopMargin, textBottomMargin);
            }
            return SCRIPT_STOP;
        }
示例#10
0
        private int fnAnim(SwordObject cpt, int id, int cdt, int spr, int e, int f, int z, int x)
        {

            if (cdt != 0 && (spr == 0))
            {
                var animTab = _resMan.OpenFetchRes((uint)cdt);
                var animOffset = Header.Size + cpt.dir * AnimSet.Size;
                var anim = new AnimSet(animTab, animOffset);
                cpt.anim_resource = (int)_resMan.ReadUInt32(anim.cdt);
                cpt.resource = (int)_resMan.ReadUInt32(anim.spr);
                _resMan.ResClose((uint)cdt);
            }
            else
            {
                cpt.anim_resource = cdt;
                cpt.resource = spr;
            }
            if ((cpt.anim_resource == 0) || (cpt.resource == 0))
                throw new InvalidOperationException($"fnAnim called width ({cdt}/{spr}) => ({cpt.anim_resource}/{cpt.resource})");

            var frameHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes((uint)cpt.resource), 0));
            if (frameHead.offsetX != 0 || frameHead.offsetY != 0)
            { // boxed mega anim?
                cpt.status |= STAT_SHRINK;
                cpt.anim_x = cpt.xcoord; // set anim coords to 'feet' coords - only need to do this once
                cpt.anim_y = cpt.ycoord;
            }
            else
            {
                // Anim_driver sets anim coords to cdt coords for every frame of a loose anim
                cpt.status &= ~STAT_SHRINK;
            }
            _resMan.ResClose((uint)cpt.resource);

            cpt.logic = LOGIC_anim;
            cpt.anim_pc = 0;
            cpt.sync = 0;
            return SCRIPT_STOP;
        }
示例#11
0
文件: Control.cs 项目: scemino/nscumm
        private void RenderVolumeBar(byte id, byte volL, byte volR)
        {
            ushort destX = (ushort)(_volumeButtons[id].x + 20);
            ushort destY = (ushort)(_volumeButtons[id].y + 116);

            for (var chCnt = 0; chCnt < 2; chCnt++)
            {
                byte vol = (chCnt == 0) ? volL : volR;
                FrameHeader frHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes(SwordRes.SR_VLIGHT), (uint)((vol + 15) >> 4)));
                var destMem = new ByteAccess(_screenBuf, destY * Screen.SCREEN_WIDTH + destX);
                var srcMem = new ByteAccess(frHead.Data.Data, frHead.Data.Offset + FrameHeader.Size);
                ushort barHeight = _resMan.ReadUInt16(frHead.height);
                byte[] psxVolBuf = null;

                if (SystemVars.Platform == Platform.PSX)
                {
                    psxVolBuf = new byte[_resMan.ReadUInt16(frHead.height) / 2 * _resMan.ReadUInt16(frHead.width)];
                    Screen.DecompressHIF(srcMem.Data, srcMem.Offset, psxVolBuf);
                    srcMem = new ByteAccess(psxVolBuf);
                    barHeight /= 2;
                }

                for (ushort cnty = 0; cnty < barHeight; cnty++)
                {
                    Array.Copy(srcMem.Data, srcMem.Offset, destMem.Data, destMem.Offset, _resMan.ReadUInt16(frHead.width));

                    if (SystemVars.Platform == Platform.PSX)
                    { 
                        //linedoubling
                        destMem.Offset += Screen.SCREEN_WIDTH;
                        Array.ConstrainedCopy(srcMem.Data, srcMem.Offset, destMem.Data, destMem.Offset, _resMan.ReadUInt16(frHead.width));
                    }

                    srcMem.Offset += _resMan.ReadUInt16(frHead.width);
                    destMem.Offset += Screen.SCREEN_WIDTH;
                }

                _system.GraphicsManager.CopyRectToScreen(_screenBuf, destY * Screen.SCREEN_WIDTH + destX, Screen.SCREEN_WIDTH, destX, destY, _resMan.ReadUInt16(frHead.width), _resMan.ReadUInt16(frHead.height));
                _resMan.ResClose(SwordRes.SR_VLIGHT);
                destX += 32;
            }
        }
示例#12
0
文件: Control.cs 项目: scemino/nscumm
        private void SetupSaveRestorePanel(bool saving)
        {
            ReadSavegameDescriptions();

            FrameHeader savePanel = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes(SwordRes.SR_WINDOW), 0));
            short panelX = (short)((640 - _resMan.ReadUInt16(savePanel.width)) / 2);
            short panelY = (short)((480 - _resMan.ReadUInt16(savePanel.height)) / 2);
            ControlButton panel = new ControlButton((ushort)panelX, (ushort)panelY, SwordRes.SR_WINDOW, 0, 0, _resMan, _screenBuf, _system);
            panel.Draw();
            _resMan.ResClose(SwordRes.SR_WINDOW);
            CreateButtons(_saveButtons, 14);
            RenderText(_lStrings[(int)LangStrings.STR_CANCEL], _saveButtons[13].x - 10, _saveButtons[13].y, TextModes.TEXT_RIGHT_ALIGN);
            if (saving)
            {
                RenderText(_lStrings[(int)LangStrings.STR_SAVE], _saveButtons[12].x + 30, _saveButtons[13].y, TextModes.TEXT_LEFT_ALIGN);
            }
            else
            {
                RenderText(_lStrings[(int)LangStrings.STR_RESTORE], _saveButtons[12].x + 30, _saveButtons[13].y, TextModes.TEXT_LEFT_ALIGN);
            }
            ReadSavegameDescriptions();
            _selectedSavegame = 255;
            ShowSavegameNames();
        }
示例#13
0
文件: Control.cs 项目: scemino/nscumm
        private void RenderText(string str, int x, int y, TextModes mode)
        {
            int i = 0;
            var font = _font;
            if (mode.HasFlag(TextModes.TEXT_RED_FONT))
            {
                mode &= ~TextModes.TEXT_RED_FONT;
                font = _redFont;
            }

            if (mode == TextModes.TEXT_RIGHT_ALIGN) // negative x coordinate means right-aligned.
                x -= GetTextWidth(str);
            else if (mode == TextModes.TEXT_CENTER)
                x -= GetTextWidth(str) / 2;

            ushort destX = (ushort)x;
            while (i < str.Length)
            {
                var dst = new ByteAccess(_screenBuf, +y * Screen.SCREEN_WIDTH + destX);

                FrameHeader chSpr = new FrameHeader(_resMan.FetchFrame(font, (uint)(str[i] - 32)));
                var sprData = new ByteAccess(chSpr.Data.Data, chSpr.Data.Offset + FrameHeader.Size);

                if (SystemVars.Platform == Platform.PSX)
                {
                    //Text fonts are compressed in psx version
                    var HIFbuf = new byte[_resMan.ReadUInt16(chSpr.height) * _resMan.ReadUInt16(chSpr.width)];
                    Screen.DecompressHIF(sprData.Data, sprData.Offset, HIFbuf);
                    sprData = new ByteAccess(HIFbuf);
                }

                for (ushort cnty = 0; cnty < _resMan.ReadUInt16(chSpr.height); cnty++)
                {
                    for (ushort cntx = 0; cntx < _resMan.ReadUInt16(chSpr.width); cntx++)
                    {
                        if (sprData[cntx] != 0)
                            dst[cntx] = sprData[cntx];
                    }

                    if (SystemVars.Platform == Platform.PSX)
                    { //On PSX version we need to double horizontal lines
                        dst.Offset += Screen.SCREEN_WIDTH;
                        for (ushort cntx = 0; cntx < _resMan.ReadUInt16(chSpr.width); cntx++)
                            if (sprData[cntx] != 0)
                                dst[cntx] = sprData[cntx];
                    }

                    sprData.Offset += _resMan.ReadUInt16(chSpr.width);
                    dst.Offset += Screen.SCREEN_WIDTH;
                }
                destX = (ushort)(destX + _resMan.ReadUInt16(chSpr.width) - 3);
                i++;
            }

            _system.GraphicsManager.CopyRectToScreen(_screenBuf, +y * Screen.SCREEN_WIDTH + x, Screen.SCREEN_WIDTH, x, y, (destX - x) + 3, 28);
        }