Пример #1
0
        private bool FnGetTo(uint targetPlaceId, uint mode, uint c)
        {
            _compact.Core.upFlag = (ushort)mode; // save mode for action script
            _compact.Core.mode  += 4;            // next level up
            Compact cpt = _skyCompact.FetchCpt(_compact.Core.place);

            if (cpt == null)
            {
                // TODO: warning("can't find _compact's getToTable. Place compact is NULL");
                return(false);
            }
            var raw = _skyCompact.FetchCptRaw(cpt.Core.getToTableId);

            if (raw == null)
            {
                //TODO:  warning("Place compact's getToTable is NULL");
                return(false);
            }

            var getToTable = new UShortAccess(raw, 0);

            while (getToTable.Value != targetPlaceId)
            {
                getToTable.Offset += 4;
            }

            // get new script
            SkyCompact.GetSub(_compact, _compact.Core.mode).Field = getToTable[1];
            SkyCompact.GetSub(_compact, (ushort)(_compact.Core.mode + 2)).Field = 0;

            return(false); // drop out of script
        }
Пример #2
0
        private void VerticalMask()
        {
            if (_sprWidth == 0)
            {
                return;
            }
            var startGridOfs   = (int)((_sprY + _sprHeight - 1) * GridX + _sprX);
            var startScreenPtr = (int)((_sprY + _sprHeight - 1) * GridH * GameScreenWidth + _sprX * GridW);

            for (uint layerCnt = Logic.LAYER_1_ID; layerCnt <= Logic.LAYER_3_ID; layerCnt++)
            {
                var gridOfs   = startGridOfs;
                var screenPtr = startScreenPtr;
                for (uint widCnt = 0; widCnt < _sprWidth; widCnt++)
                {
                    // x_loop
                    var nLayerCnt = layerCnt;
                    while (Logic.ScriptVariables[(int)(nLayerCnt + 3)] != 0)
                    {
                        var scrGrid = new UShortAccess(SkyEngine.ItemList[Logic.ScriptVariables[(int)(layerCnt + 3)]], 0);
                        if (scrGrid[gridOfs] != 0)
                        {
                            VertMaskSub(scrGrid, gridOfs, screenPtr, layerCnt);
                            break;
                        }
                        nLayerCnt++;
                    }
                    // next_x:
                    screenPtr += GridW;
                    gridOfs++;
                }
            }
        }
Пример #3
0
        private bool FnResetId(uint id, uint resetBlock, uint c)
        {
            // used when a mega is to be restarted
            // eg - when a smaller mega turn to larger
            // - a mega changes rooms...

            var cpt = _skyCompact.FetchCpt((ushort)id);
            var rst = new UShortAccess(_skyCompact.FetchCptRaw((ushort)resetBlock), 0);

            if (cpt == null)
            {
                // TODO: warning("fnResetId(): Compact %d (id) == NULL", id);
                return(true);
            }

            if (rst == null)
            {
                // TODO: warning("fnResetId(): Compact %d (resetBlock) == NULL", resetBlock);
                return(true);
            }

            ushort off;

            while ((off = rst[0]) != 0xffff)
            {
                rst.Offset += 2;
                _skyCompact.GetCompactElem(cpt, off).Field = rst[0];
                rst.Offset += 2;
            }
            return(true);
        }
Пример #4
0
 private void VertMaskSub(UShortAccess grid, int gridOfs, int screenPtr, uint layerId)
 {
     for (var cntx = 0; cntx < _sprHeight; cntx++)
     {
         // start_x | block_loop
         if (grid[gridOfs] != 0)
         {
             if ((grid[gridOfs] & 0x8000) == 0)
             {
                 var gridVal = grid[gridOfs] - 1;
                 gridVal *= GridW * GridH;
                 var dataSrc = new ByteAccess(SkyEngine.ItemList[Logic.ScriptVariables[(int)layerId]], gridVal);
                 var dataTrg = screenPtr;
                 for (var grdCntY = 0; grdCntY < GridH; grdCntY++)
                 {
                     for (var grdCntX = 0; grdCntX < GridW; grdCntX++)
                     {
                         if (dataSrc[grdCntX] != 0)
                         {
                             Current[dataTrg + grdCntX] = dataSrc[grdCntX];
                         }
                     }
                     dataSrc.Offset += GridW;
                     dataTrg        += GameScreenWidth;
                 }
             } // dummy_end:
             screenPtr -= GridH * GameScreenWidth;
             gridOfs   -= GridX;
         }
         else
         {
             return;
         }
     } // next_x
 }
Пример #5
0
        private void DoSprites(byte layer)
        {
            ushort drawListNum = Logic.DRAW_LIST_NO;

            while (Logic.ScriptVariables[drawListNum] != 0)
            {
                // std sp loop
                var idNum = Logic.ScriptVariables[drawListNum];
                drawListNum++;

                var drawList = new UShortAccess(_skyCompact.FetchCptRaw((ushort)idNum), 0);
                while (drawList[0] != 0)
                {
                    // new_draw_list:
                    while ((drawList[0] != 0) && (drawList[0] != 0xFFFF))
                    {
                        // back_loop:
                        // not_new_list
                        var spriteData = _skyCompact.FetchCpt(drawList[0]);
                        drawList.Offset += 2;
                        if (((spriteData.Core.status & (1 << layer)) != 0) &&
                            (spriteData.Core.screen == Logic.ScriptVariables[Logic.SCREEN]))
                        {
                            var toBeDrawn = SkyEngine.ItemList[spriteData.Core.frame >> 6];
                            if (toBeDrawn == null)
                            {
                                // TODO: debug(9, "Spritedata %d not loaded", spriteData.frame >> 6);
                                spriteData.Core.status = 0;
                            }
                            else
                            {
                                DrawSprite(toBeDrawn, spriteData);
                                if (layer == Back)
                                {
                                    VerticalMask();
                                }
                                if ((spriteData.Core.status & 8) != 0)
                                {
                                    VectorToGame(0x81);
                                }
                                else
                                {
                                    VectorToGame(1);
                                }
                            }
                        }
                    }
                    while (drawList[0] == 0xFFFF)
                    {
                        drawList = new UShortAccess(_skyCompact.FetchCptRaw(drawList[1]), 0);
                    }
                }
            }
        }
Пример #6
0
        public void Engine()
        {
            do
            {
                var    raw       = _skyCompact.FetchCptRaw((ushort)_scriptVariables[LOGIC_LIST_NO]);
                var    logicList = new UShortAccess(raw, 0);
                ushort id;
                while ((id = logicList[0]) != 0)
                {
                    logicList.Offset += 2;
                    // 0 means end of list
                    if (id == 0xffff)
                    {
                        // Change logic data address
                        raw       = _skyCompact.FetchCptRaw(logicList[0]);
                        logicList = new UShortAccess(raw, 0);
                        continue;
                    }

                    _scriptVariables[CUR_ID] = id;
                    _compact = _skyCompact.FetchCpt(id);

                    // check the id actually wishes to be processed
                    if ((_compact.Core.status & (1 << 6)) == 0)
                    {
                        continue;
                    }

                    // ok, here we process the logic bit system

                    if ((_compact.Core.status & (1 << 7)) != 0)
                    {
                        _skyGrid.RemoveObjectFromWalk(_compact);
                    }

                    Debug.Instance.Logic(_compact.Core.logic);
                    _logicTable[_compact.Core.logic]();

                    if ((_compact.Core.status & (1 << 7)) != 0)
                    {
                        _skyGrid.ObjectToWalk(_compact);
                    }

                    // a sync sent to the compact is available for one cycle
                    // only. that cycle has just ended so remove the sync.
                    // presumably the mega has just reacted to it.
                    _compact.Core.sync = 0;
                }
                // usually this loop is run only once, it'll only be run a second time if the game
                // script just asked the user to enter a copy protection code.
                // this is done to prevent the copy protection screen from flashing up.
                // (otherwise it would be visible for 1/50 second)
            } while (CheckProtection());
        }
Пример #7
0
        public void FnTextModule(uint textInfoId, uint textNo)
        {
            FnSetFont(1);
            var msgData = new UShortAccess(_skyCompact.FetchCptRaw((ushort)textInfoId), 0);
            var textId  = LowTextManager(textNo, msgData[1], msgData[2], 209, false);

            Logic.ScriptVariables[Logic.RESULT] = textId.CompactNum;
            var textCompact = _skyCompact.FetchCpt(textId.CompactNum);

            textCompact.Core.xcood = msgData[3];
            textCompact.Core.ycood = msgData[4];
            FnSetFont(0);
        }
Пример #8
0
        private bool FnSetToStand(uint a, uint b, uint c)
        {
            _compact.Core.mood = 1; // high level stood still

            _compact.Core.grafixProgId  = _skyCompact.GetCompactElem(_compact, (ushort)(C_STAND_UP + _compact.Core.megaSet + _compact.Core.dir * 4)).Field;
            _compact.Core.grafixProgPos = 0;

            UShortAccess standList = _skyCompact.GetGrafixPtr(_compact);

            _compact.Core.offset = standList.Value; // get frames offset
            _compact.Core.logic  = L_SIMPLE_MOD;
            _compact.Core.grafixProgPos++;
            SimpleAnim();
            return(false); // drop out of script
        }
Пример #9
0
        private void ArTurn()
        {
            var turnData = new UShortAccess(_skyCompact.FetchCptRaw(_compact.Core.turnProgId), _compact.Core.turnProgPos * 2);

            _compact.Core.frame = turnData[0];
            turnData.Offset    += 2;
            _compact.Core.turnProgPos++;

            if (turnData[0] == 0)
            { // turn done?
              // Back to ar mode
                _compact.Core.arAnimIndex = 0;
                _compact.Core.logic       = L_AR_ANIM;
            }
        }
Пример #10
0
        private static ushort CheckBlock(byte[] block, int blockPos)
        {
            var    b      = new UShortAccess(block, blockPos);
            ushort retVal = 0xFFFF;

            for (byte cnt = 0; cnt < 4; cnt++)
            {
                var fieldVal = b[RouteDirections[cnt]];
                if (fieldVal != 0 && (fieldVal < retVal))
                {
                    retVal = fieldVal;
                }
            }
            return(retVal);
        }
Пример #11
0
        private bool FnTestList(uint id, uint x, uint y)
        {
            _scriptVariables[RESULT] = 0; // assume fail
            var list = new UShortAccess(_skyCompact.FetchCptRaw((ushort)id), 0);

            while (list.Value != 0)
            {
                if ((x >= list[0]) && (x < list[1]) && (y >= list[2]) && (y < list[3]))
                {
                    _scriptVariables[RESULT] = list[4];
                }
                list.Offset += 5 * 2;
            }
            return(true);
        }
Пример #12
0
 public void Script(uint command, UShortAccess scriptData)
 {
     Write("SCRIPT: {0}", Opcodes[command]);
     if (command == 0 || command == 6)
     {
         Write(" {0}", ScriptVars[scriptData[0] / 4]);
     }
     else
     {
         for (var i = 0; i < OpcodeParameter[command]; i++)
         {
             Write(" {0}", scriptData[i]);
         }
     }
     Write(" ");  // Print an empty line as separator
 }
Пример #13
0
        public void LoadSection(byte section)
        {
            FnStopFx();
            _mixer.StopAll();

            _soundData = _skyDisk.LoadFile(section * 4 + SoundFileBase);
            ushort asmOfs;

            if (SystemVars.Instance.GameVersion.Version.Minor == 109)
            {
                if (section == 0)
                {
                    asmOfs = 0x78;
                }
                else
                {
                    asmOfs = 0x7C;
                }
            }
            else
            {
                asmOfs = 0x7E;
            }

            if ((_soundData[asmOfs] != 0x3C) || (_soundData[asmOfs + 0x27] != 0x8D) ||
                (_soundData[asmOfs + 0x28] != 0x1E) || (_soundData[asmOfs + 0x2F] != 0x8D) ||
                (_soundData[asmOfs + 0x30] != 0x36))
            {
                throw new NotSupportedException("Unknown sounddriver version");
            }

            _soundsTotal = _soundData[asmOfs + 1];
            var sRateTabOfs = _soundData.ToUInt16(asmOfs + 0x29);

            _sfxBaseOfs  = _soundData.ToUInt16(asmOfs + 0x31);
            _sampleRates = new ByteAccess(_soundData, sRateTabOfs);

            _sfxInfo = new UShortAccess(_soundData, _sfxBaseOfs);
            // if we just restored a savegame, the sfxqueue holds the sound we need to restart
            if (!SystemVars.Instance.SystemFlags.HasFlag(SystemFlags.GameRestored))
            {
                for (var cnt = 0; cnt < MaxQueuedFx; cnt++)
                {
                    SfxQueue[cnt].Count = 0;
                }
            }
        }
Пример #14
0
        private void Turn()
        {
            var turnData = new UShortAccess(_skyCompact.FetchCptRaw(_compact.Core.turnProgId), _compact.Core.turnProgPos * 2);

            if (turnData[0] != 0)
            {
                _compact.Core.frame = turnData[0];
                _compact.Core.turnProgPos++;
                return;
            }

            // turn_to_script:
            _compact.Core.arAnimIndex = 0;
            _compact.Core.logic       = L_SCRIPT;

            LogicScript();
        }
Пример #15
0
        private bool FnMoveItems(uint listNo, uint screenNo, uint c)
        {
            // Move a list of id's to another screen
            var p = new UShortAccess(_skyCompact.FetchCptRaw((ushort)CptIds.MoveList), 0);

            p = new UShortAccess(_skyCompact.FetchCptRaw(p[(int)listNo]), 0);
            for (int i = 0; i < 2; i++)
            {
                if (p.Value == 0)
                {
                    return(true);
                }
                Compact cpt = _skyCompact.FetchCpt(p.Value); p.Offset += 2;
                cpt.Core.screen = (ushort)(screenNo & 0xffff);
            }
            return(true);
        }
Пример #16
0
        private static UShortAccess CheckInitMove(UShortAccess data, short initStaX)
        {
            var index = 0;

            if (initStaX < 0)
            {
                index          -= 2;
                data[index + 1] = Logic.RIGHTY;
                data[index]     = (ushort)((-initStaX + 7) & 0xFFF8);
            }
            else if (initStaX > 0)
            {
                index      -= 2;
                data[index] = (ushort)((initStaX + 7) & 0xFFF8);
                data[index] = (ushort)((initStaX + 7) & 0xFFF8);
            }
            return(new UShortAccess(data.Data, data.Offset + index * 2));
        }
Пример #17
0
        private UShortAccess MakeRouteData(byte destX, byte destY)
        {
            Array.Clear(_routeBuf, 0, _routeBuf.Length);
            var routeBuf  = new UShortAccess(_routeBuf, 0);
            var routeGrid = new UShortAccess(_routeGrid, 0);

            var routePos = (destY + 1) * RouteGridWidth + destX + 1;
            var dataTrg  = (Logic.ROUTE_SPACE >> 1) - 2;

            var lastVal = (ushort)(routeGrid[routePos] - 1);

            while (lastVal != 0)
            {
                // lastVal == 0 means route is done.
                dataTrg -= 2;

                short walkDirection = 0;
                for (byte cnt = 0; cnt < 4; cnt++)
                {
                    if (lastVal == routeGrid[routePos + RouteDirections[cnt]])
                    {
                        routeBuf[dataTrg + 1] = LogicCommands[cnt];
                        walkDirection         = RouteDirections[cnt];
                        break;
                    }
                }

                if (walkDirection == 0)
                {
                    throw new InvalidOperationException(
                              string.Format("makeRouteData:: can't find way through walkGrid (pos {0})", lastVal));
                }

                while (lastVal != 0 && (lastVal == routeGrid[routePos + walkDirection]))
                {
                    routeBuf[dataTrg] += WalkJump;
                    lastVal--;
                    routePos += walkDirection;
                }
            }
            return(new UShortAccess(routeBuf.Data, routeBuf.Offset + dataTrg * 2));
        }
Пример #18
0
        private bool FnEyeball(uint id, uint b, uint c)
        {
            // set 'result' to frame no. pointing to foster, according to table used
            // eg. FN_eyeball (id_eye_90_table);

            var     eyeTable = new UShortAccess(_skyCompact.FetchCptRaw((ushort)id), 0);
            Compact cpt      = _skyCompact.FetchCpt(ID_BLUE_FOSTER);

            int x = cpt.Core.xcood; // 168 < x < 416

            x  -= 168;
            x >>= 3;

            int y = cpt.Core.ycood; // 256 < y < 296

            y  -= 256;
            y <<= 2;

            _scriptVariables[RESULT] = (uint)(eyeTable[x + y] + S91);
            return(true);
        }
Пример #19
0
        private void InitWalkGrid(byte screen, byte width)
        {
            byte stretch       = 0;
            var  screenGrid    = _grid.GiveGrid(screen);
            var  screenGridPos = Logic.GRID_SIZE;
            var  wGridPos      = new UShortAccess(_routeGrid, ((RouteGridSize >> 1) - RouteGridWidth - 2) * 2);

            Array.Clear(_routeGrid, 0, _routeGrid.Length);
            byte bitsLeft = 0;
            uint gridData = 0;

            for (byte gridCntY = 0; gridCntY < RouteGridHeight - 2; gridCntY++)
            {
                for (byte gridCntX = 0; gridCntX < RouteGridWidth - 2; gridCntX++)
                {
                    if (bitsLeft == 0)
                    {
                        screenGridPos -= 4;
                        gridData       = screenGrid.ToUInt32(screenGridPos);
                        bitsLeft       = 32;
                    }
                    if ((gridData & 1) != 0)
                    {
                        wGridPos[0] = 0xFFFF; // block is not accessible
                        stretch     = width;
                    }
                    else if (stretch != 0)
                    {
                        wGridPos[0] = 0xFFFF;
                        stretch--;
                    }
                    wGridPos.Offset -= 2;
                    bitsLeft--;
                    gridData >>= 1;
                }
                wGridPos.Offset -= 4;
                stretch          = 0;
            }
        }
Пример #20
0
        private bool FnTurnTo(uint dir, uint b, uint c)
        {
            // turn compact to direction dir

            ushort curDir = _compact.Core.dir;          // get current direction

            _compact.Core.dir = (ushort)(dir & 0xffff); // set new direction

            UShortAccess tt = _skyCompact.GetTurnTable(_compact, curDir);

            if (tt[(int)dir] == 0)
            {
                return(true);                         // keep going
            }
            _compact.Core.turnProgId  = tt[(int)dir]; // put turn program in
            _compact.Core.turnProgPos = 0;
            _compact.Core.logic       = L_TURNING;

            Turn();

            return(false); // drop out of script
        }
Пример #21
0
        private void MainAnim()
        {
            // Extension of arAnim()
            _compact.Core.waitingFor = 0; // clear possible zero-zero skip

            var sequence = _skyCompact.GetGrafixPtr(_compact);

            if (sequence[0] == 0)
            {
                // ok, move to new anim segment
                sequence.Offset             += 4;
                _compact.Core.grafixProgPos += 2;
                if (sequence[0] == 0)
                { // end of route?
                  // ok, sequence has finished

                    // will start afresh if new sequence continues in last direction
                    _compact.Core.arAnimIndex = 0;

                    _compact.Core.downFlag = 0; // pass back ok to script
                    _compact.Core.logic    = L_SCRIPT;
                    LogicScript();
                    return;
                }

                _compact.Core.arAnimIndex = 0; // reset position
            }

            ushort dir;

            while ((dir = _compact.Core.dir) != sequence[1])
            {
                // ok, setup turning
                _compact.Core.dir = sequence[1];

                var tt = _skyCompact.GetTurnTable(_compact, dir);
                if (tt[_compact.Core.dir] != 0)
                {
                    _compact.Core.turnProgId  = tt[_compact.Core.dir];
                    _compact.Core.turnProgPos = 0;
                    _compact.Core.logic       = L_AR_TURNING;
                    ArTurn();
                    return;
                }
            }

            var animId   = _skyCompact.GetCompactElem(_compact, (ushort)(C_ANIM_UP + _compact.Core.megaSet + dir * 4)).Field;
            var animList = new UShortAccess(_skyCompact.FetchCptRaw(animId), 0);

            ushort arAnimIndex = _compact.Core.arAnimIndex;

            if (animList[arAnimIndex / 2] == 0)
            {
                arAnimIndex = 0;
                _compact.Core.arAnimIndex = 0; // reset
            }

            _compact.Core.arAnimIndex += S_LENGTH;

            sequence[0]         -= animList[(S_COUNT + arAnimIndex) / 2]; // reduce the distance to travel
            _compact.Core.frame  = animList[(S_FRAME + arAnimIndex) / 2]; // new graphic frame
            _compact.Core.xcood += animList[(S_AR_X + arAnimIndex) / 2];  // update x coordinate
            _compact.Core.ycood += animList[(S_AR_Y + arAnimIndex) / 2];  // update y coordinate
        }
Пример #22
0
        private bool CalcWalkGrid(byte startX, byte startY, byte destX, byte destY)
        {
            short directionX, directionY;
            byte  roiX, roiY; // Rectangle Of Interest in the walk grid

            if (startY > destY)
            {
                directionY = -RouteGridWidth;
                roiY       = startY;
            }
            else
            {
                directionY = RouteGridWidth;
                roiY       = (byte)(RouteGridHeight - 1 - startY);
            }
            if (startX > destX)
            {
                directionX = -1;
                roiX       = (byte)(startX + 2);
            }
            else
            {
                directionX = 1;
                roiX       = (byte)(RouteGridWidth - 1 - startX);
            }

            var walkDest  = (destY + 1) * RouteGridWidth + destX + 1;
            var walkStart = (startY + 1) * RouteGridWidth + startX + 1;

            var routeGrid = new UShortAccess(_routeGrid, 0);

            routeGrid[walkStart] = 1;

            // if we are on the edge, move diagonally from start
            if (roiY < RouteGridHeight - 3)
            {
                walkStart -= directionY;
            }

            if (roiX < RouteGridWidth - 2)
            {
                walkStart -= directionX;
            }

            var gridChanged = true;
            var foundRoute  = false;

            while (!foundRoute && gridChanged)
            {
                gridChanged = false;
                var yWalkCalc = walkStart;
                for (byte cnty = 0; cnty < roiY; cnty++)
                {
                    var xWalkCalc = yWalkCalc;
                    for (byte cntx = 0; cntx < roiX; cntx++)
                    {
                        if (routeGrid[xWalkCalc] == 0)
                        {
                            // block wasn't done, yet
                            var blockRet = CheckBlock(_routeGrid, routeGrid.Offset + xWalkCalc * 2);
                            if (blockRet < 0xFFFF)
                            {
                                routeGrid[xWalkCalc] = (ushort)(blockRet + 1);
                                gridChanged          = true;
                            }
                        }
                        xWalkCalc += directionX;
                    }
                    yWalkCalc += directionY;
                }
                if (routeGrid[walkDest] != 0)
                {
                    // okay, finished
                    foundRoute = true;
                }
                else
                {
                    // we couldn't find the route, let's extend the ROI
                    if (roiY < RouteGridHeight - 4)
                    {
                        walkStart -= directionY;
                        roiY++;
                    }
                    if (roiX < RouteGridWidth - 4)
                    {
                        walkStart -= directionX;
                        roiX++;
                    }
                }
            }
            return(foundRoute);
        }
Пример #23
0
        private void SortSprites()
        {
            var sortList     = new StSortList[30];
            int currDrawList = Logic.DRAW_LIST_NO;

            while (Logic.ScriptVariables[currDrawList] != 0)
            {
                // big_sort_loop
                uint spriteCnt    = 0;
                var  loadDrawList = Logic.ScriptVariables[currDrawList];
                currDrawList++;

                bool nextDrawList;
                do
                {
                    // a_new_draw_list:
                    var drawListData = new UShortAccess(_skyCompact.FetchCptRaw((ushort)loadDrawList), 0);
                    nextDrawList = false;
                    while (!nextDrawList && (drawListData[0] != 0))
                    {
                        if (drawListData[0] == 0xFFFF)
                        {
                            loadDrawList = drawListData[1];
                            nextDrawList = true;
                        }
                        else
                        {
                            // process_this_id:
                            var spriteComp = _skyCompact.FetchCpt(drawListData[0]);
                            if (((spriteComp.Core.status & 4) != 0) && // is it sortable playfield?(!?!)
                                (spriteComp.Core.screen == Logic.ScriptVariables[Logic.SCREEN]))
                            {
                                // on current screen
                                var spriteData = SkyEngine.ItemList[spriteComp.Core.frame >> 6];
                                if (spriteData == null)
                                {
                                    // TODO: debug(9, "Missing file %d", spriteComp.frame >> 6);
                                    spriteComp.Core.status = 0;
                                }
                                else
                                {
                                    sortList[spriteCnt].YCood =
                                        (uint)
                                        (spriteComp.Core.ycood + spriteData.ToUInt16(18) + spriteData.ToUInt16(8));
                                    sortList[spriteCnt].Compact = spriteComp;
                                    sortList[spriteCnt].Sprite  = spriteData;
                                    spriteCnt++;
                                }
                            }
                            drawListData.Offset += 2;
                        }
                    }
                } while (nextDrawList);
                // made_list:
                if (spriteCnt > 1)
                {
                    // bubble sort
                    for (var cnt1 = 0; cnt1 < spriteCnt - 1; cnt1++)
                    {
                        for (var cnt2 = cnt1 + 1; cnt2 < spriteCnt; cnt2++)
                        {
                            if (sortList[cnt1].YCood > sortList[cnt2].YCood)
                            {
                                StSortList tmp;
                                tmp.YCood              = sortList[cnt1].YCood;
                                tmp.Sprite             = sortList[cnt1].Sprite;
                                tmp.Compact            = sortList[cnt1].Compact;
                                sortList[cnt1].YCood   = sortList[cnt2].YCood;
                                sortList[cnt1].Sprite  = sortList[cnt2].Sprite;
                                sortList[cnt1].Compact = sortList[cnt2].Compact;
                                sortList[cnt2].YCood   = tmp.YCood;
                                sortList[cnt2].Sprite  = tmp.Sprite;
                                sortList[cnt2].Compact = tmp.Compact;
                            }
                        }
                    }
                }
                for (var cnt = 0; cnt < spriteCnt; cnt++)
                {
                    DrawSprite(sortList[cnt].Sprite, sortList[cnt].Compact);
                    if ((sortList[cnt].Compact.Core.status & 8) != 0)
                    {
                        VectorToGame(0x81);
                    }
                    else
                    {
                        VectorToGame(1);
                    }
                    if ((sortList[cnt].Compact.Core.status & 0x200) == 0)
                    {
                        VerticalMask();
                    }
                }
            }
        }
Пример #24
0
        public ushort DoAutoRoute(Compact cpt)
        {
            var cptScreen = (byte)cpt.Core.screen;
            var cptWidth  = (byte)SkyCompact.GetMegaSet(cpt).gridWidth;

            InitWalkGrid(cptScreen, cptWidth);

            byte  startX, startY, destX, destY;
            short initStaX, initStaY, initDestX, initDestY;

            ClipCoordX(cpt.Core.xcood, out startX, out initStaX);
            ClipCoordY(cpt.Core.ycood, out startY, out initStaY);
            ClipCoordX(cpt.Core.arTargetX, out destX, out initDestX);
            ClipCoordY(cpt.Core.arTargetY, out destY, out initDestY);

            var raw = _skyCompact.FetchCptRaw(cpt.Core.animScratchId);

            Array.Clear(raw, 0, 64);
            var routeDest = new UShortAccess(raw, 0);

            if ((startX == destX) && (startY == destY))
            {
                return(2);
            }

            var routeGrid = new UShortAccess(_routeGrid, 0);

            if (routeGrid[(destY + 1) * RouteGridWidth + destX + 1] != 0)
            {
                //if ((cpt == &Sky::SkyCompact::foster) && (cptScreen == 12) && (destX == 2) && (destY == 14)) {
                if (_skyCompact.CptIsId(cpt, (ushort)CptIds.Foster) && (cptScreen == 12) && (destX == 2) &&
                    (destY == 14))
                {
                    /* workaround for Scriptbug #1043047
                     * In screen 12 (the pipe factory) Joey can block Foster's target
                     * coordinates (2/14). This is normally not too tragic, but in the
                     * scene when foster gets thrown out by Lamb (first time you enter
                     * the pipe factory), the game would enter an infinite loop. */
                    routeGrid[(destY + 1) * RouteGridWidth + destX + 1] = 0;
                    // hide this part joey from the grid
                }
                else
                {
                    return(1); // AR destination is an unaccessible block
                }
            }

            if (!CalcWalkGrid(startX, startY, destX, destY))
            {
                return(1); // can't find route to block
            }
            var routeData = MakeRouteData(destX, destY);

            // the route is done.
            // if there was an initial x movement (due to clipping) tag it onto the start
            routeData = CheckInitMove(routeData, initStaX);

            byte cnt = 0;

            do
            {
                routeDest[cnt]     = routeData[cnt];
                routeDest[cnt + 1] = routeData[cnt + 1];
                cnt += 2;
            } while (routeData[cnt - 2] != 0);
            return(0);
        }
Пример #25
0
        private void ArAnim()
        {
            // Follow a route
            // Mega should be in getToMode

            // only check collisions on character boundaries
            if (((_compact.Core.xcood & 7) != 0) || ((_compact.Core.ycood & 7) != 0))
            {
                MainAnim();
                return;
            }

            // On character boundary. Have we been told to wait?
            // if not - are WE colliding?

            if (_compact.Core.waitingFor == 0xffff)
            { // 1st cycle of re-route does not require collision checks
                MainAnim();
                return;
            }

            if (_compact.Core.waitingFor != 0)
            {
                // ok, we've been told we've hit someone
                // we will wait until we are no longer colliding
                // with them. here we check to see if we are (still) colliding.
                // if we are then run the stop script. if not clear the flag
                // and continue.

                // remember - this could be the first ar cycle for some time,
                // we might have been told to wait months ago. if we are
                // waiting for one person then another hits us then
                // c_waiting_for will be replaced by the new mega - this is
                // fine because the later collision will almost certainly
                // take longer to clear than the earlier one.

                if (Collide(_skyCompact.FetchCpt(_compact.Core.waitingFor)))
                {
                    StopAndWait();
                    return;
                }

                // we are not in fact hitting this person so clr & continue
                // it must have registered some time ago

                _compact.Core.waitingFor = 0; // clear id flag
            }

            // ok, our turn to check for collisions

            var    logicList = new UShortAccess(_skyCompact.FetchCptRaw((ushort)_scriptVariables[LOGIC_LIST_NO]), 0);
            ushort id;

            while ((id = logicList[0]) != 0)
            { // get an id
                logicList.Offset += 2;
                if (id == 0xffff)
                {                                                                           // address change?
                    logicList = new UShortAccess(_skyCompact.FetchCptRaw(logicList[0]), 0); // get new logic list
                    continue;
                }

                if (id == (ushort)(_scriptVariables[CUR_ID] & 0xffff)) // is it us?
                {
                    continue;
                }

                _scriptVariables[HIT_ID] = id; // save target id for any possible c_mini_bump
                var cpt = _skyCompact.FetchCpt(id);

                if ((cpt.Core.status & (1 << ST_COLLISION_BIT)) == 0) // can it collide?
                {
                    continue;
                }

                if (cpt.Core.screen != _compact.Core.screen) // is it on our screen?
                {
                    continue;
                }

                if (Collide(cpt))
                { // check for a hit
                  // ok, we've hit a mega
                  // is it moving... or something else?

                    if (cpt.Core.logic != L_AR_ANIM)
                    { // check for following route
                      // it is doing something else
                      // we restart our get-to script
                      // first tell it to wait for us - in case it starts moving
                      // ( *it may have already hit us and stopped to wait )

                        _compact.Core.waitingFor = 0xffff; // effect 1 cycle collision skip
                                                           // tell it it is waiting for us
                        cpt.Core.waitingFor = (ushort)(_scriptVariables[CUR_ID] & 0xffff);
                        // restart current script
                        SkyCompact.GetSub(_compact, _compact.Core.mode + 2).Field = 0;
                        _compact.Core.logic = L_SCRIPT;
                        LogicScript();
                        return;
                    }

                    Script(_compact.Core.miniBump, 0);
                    return;
                }
            }

            // ok, there was no collisions
            // now check for interaction request
            // *note: the interaction is always set up as an action script

            if (_compact.Core.request != 0)
            {
                _compact.Core.mode          = C_ACTION_MODE; // put into action mode
                _compact.Core.actionSub     = _compact.Core.request;
                _compact.Core.actionSub_off = 0;
                _compact.Core.request       = 0; // trash request
                _compact.Core.logic         = L_SCRIPT;
                LogicScript();
                return;
            }

            // any flag? - or any change?
            // if change then re-run the current script, which must be
            // a position independent get-to		 ----

            if (_compact.Core.atWatch == 0)
            { // any flag set?
                MainAnim();
                return;
            }

            // ok, there is an at watch - see if it's changed

            if (_compact.Core.atWas == _scriptVariables[_compact.Core.atWatch / 4])
            { // still the same?
                MainAnim();
                return;
            }

            // changed so restart the current script
            // *not suitable for base initiated ARing
            SkyCompact.GetSub(_compact, _compact.Core.mode + 2).Field = 0;

            _compact.Core.logic = L_SCRIPT;
            LogicScript();
        }
Пример #26
0
        public ushort Script(ushort scriptNo, ushort offset)
        {
            do
            {
                bool restartScript = false;

                // process a script
                // low level interface to interpreter

                ushort moduleNo = (ushort)(scriptNo >> 12);
                var    data     = _moduleList[moduleNo]; // get module address

                if (data == null)
                {                                 // We need to load the script module
                    _moduleList[moduleNo] = _skyDisk.LoadScriptFile((ushort)(moduleNo + F_MODULE_0));
                    data = _moduleList[moduleNo]; // module has been loaded
                }

                var scriptData = new UShortAccess(data, 0);

                Debug.Instance.Write("Doing Script: {0}:{1}:{2:X}", moduleNo, scriptNo & 0xFFF, offset != 0 ? offset - scriptData[scriptNo & 0xFFF] : 0);

                // WORKAROUND for bug #3149412: "Invalid Mode when giving shades to travel agent"
                // Using the dark glasses on Trevor (travel agent) multiple times in succession would
                // wreck the trevor compact's mode, as the script in question doesn't account for using
                // this item at this point in the game (you will only have it here if you play the game
                // in an unusual way) and thus would loop indefinitely / never drop out.
                // To prevent this, we trigger the generic response by pretending we're using an item
                // which the script /does/ handle.
                if (scriptNo == TREVOR_SPEECH && _scriptVariables[OBJECT_HELD] == IDO_SHADES)
                {
                    _scriptVariables[OBJECT_HELD] = IDO_GLASS;
                }


                // Check whether we have an offset or what
                if (offset != 0)
                {
                    scriptData = new UShortAccess(data, offset * 2);
                }
                else
                {
                    scriptData.Offset += scriptData[scriptNo & 0x0FFF] * 2;
                }

                uint b = 0, c = 0;

                while (!restartScript)
                {
                    var command = scriptData.Value; scriptData.Offset += 2; // get a command
                    Debug.Instance.Script(command, scriptData);

                    uint   a;
                    ushort s;
                    switch (command)
                    {
                    case 0:     // push_variable
                        Push(_scriptVariables[scriptData.Value / 4]); scriptData.Offset += 2;
                        break;

                    case 1:     // less_than
                        a = Pop();
                        b = Pop();
                        if (b < a)
                        {
                            Push(1);
                        }
                        else
                        {
                            Push(0);
                        }
                        break;

                    case 2:     // push_number
                        Push(scriptData.Value); scriptData.Offset += 2;
                        break;

                    case 3:     // not_equal
                        a = Pop();
                        b = Pop();
                        if (a != b)
                        {
                            Push(1);
                        }
                        else
                        {
                            Push(0);
                        }
                        break;

                    case 4:     // if_and
                        a = Pop();
                        b = Pop();
                        if (a != 0 && b != 0)
                        {
                            Push(1);
                        }
                        else
                        {
                            Push(0);
                        }
                        break;

                    case 5:     // skip_zero
                        s = scriptData.Value; scriptData.Offset += 2;

                        a = Pop();
                        if (a == 0)
                        {
                            scriptData.Offset += s;
                        }
                        break;

                    case 6:     // pop_var
                        b = _scriptVariables[scriptData.Value / 4] = Pop(); scriptData.Offset += 2;
                        break;

                    case 7:     // minus
                        a = Pop();
                        b = Pop();
                        Push(b - a);
                        break;

                    case 8:     // plus
                        a = Pop();
                        b = Pop();
                        Push(b + a);
                        break;

                    case 9:     // skip_always
                        s = scriptData.Value; scriptData.Offset += 2;
                        scriptData.Offset += s;
                        break;

                    case 10:     // if_or
                        a = Pop();
                        b = Pop();
                        if (a != 0 || b != 0)
                        {
                            Push(1);
                        }
                        else
                        {
                            Push(0);
                        }
                        break;

                    case 11:     // call_mcode
                    {
                        a = scriptData.Value; scriptData.Offset += 2;
                        System.Diagnostics.Debug.Assert(a <= 3);
                        switch (a)
                        {
                        case 3:
                            c = Pop();
                            b = Pop();
                            a = Pop();
                            break;

                        case 2:
                            b = Pop();
                            a = Pop();
                            break;

                        case 1:
                            a = Pop();
                            break;
                        }

                        ushort mcode = (ushort)(scriptData.Value / 4); scriptData.Offset += 2;         // get mcode number

                        Debug.Instance.Mcode(mcode, a, b, c);

                        var  saveCpt = _compact;
                        bool ret     = _mcodeTable[mcode](a, b, c);
                        _compact = saveCpt;

                        if (!ret)
                        {
                            return((ushort)(scriptData.Offset / 2));
                        }
                    }
                    break;

                    case 12:     // more_than
                        a = Pop();
                        b = Pop();
                        if (b > a)
                        {
                            Push(1);
                        }
                        else
                        {
                            Push(0);
                        }
                        break;

                    case 14:                                              // switch
                        c = s = scriptData.Value; scriptData.Offset += 2; // get number of cases

                        a = Pop();                                        // and value to switch on

                        do
                        {
                            if (a == scriptData.Value)
                            {
                                scriptData.Offset += scriptData[1];
                                scriptData.Offset += 2;
                                break;
                            }
                            scriptData.Offset += 4;
                        } while (--s != 0);

                        if (s == 0)
                        {
                            scriptData.Offset += scriptData.Value;     // use the default
                        }
                        break;

                    case 15:     // push_offset
                    {
                        var elem = _skyCompact.GetCompactElem(_compact, scriptData.Value);
                        Push(elem.Field); scriptData.Offset += 2;
                    }
                    break;

                    case 16:     // pop_offset
                    {
                        // pop a value into a compact
                        var elem = _skyCompact.GetCompactElem(_compact, scriptData.Value); scriptData.Offset += 2;
                        elem.Field = (ushort)Pop();
                    }
                    break;

                    case 17:     // is_equal
                        a = Pop();
                        b = Pop();
                        if (a == b)
                        {
                            Push(1);
                        }
                        else
                        {
                            Push(0);
                        }
                        break;

                    case 18:
                    {         // skip_nz
                        short t = (short)scriptData.Value; scriptData.Offset += 2;
                        a = Pop();
                        if (a != 0)
                        {
                            scriptData.Offset += t;
                        }
                        break;
                    }

                    case 13:
                    case 19:     // script_exit
                        return(0);

                    case 20:     // restart_script
                        offset        = 0;
                        restartScript = true;
                        break;

                    default:
                        throw new InvalidOperationException(string.Format("Unknown script command: {0}", command));
                    }
                }
            } while (true);
        }
Пример #27
0
        private void StdSpeak(Compact target, uint textNum, uint animNum)
        {
            animNum += (uint)(target.Core.megaSet / NEXT_MEGA_SET);
            animNum &= 0xFF;

            var talkTable = new UShortAccess(_skyCompact.FetchCptRaw((ushort)CptIds.TalkTableList), 0);

            target.Core.grafixProgId  = talkTable[(int)animNum];
            target.Core.grafixProgPos = 0;
            var animPtr = _skyCompact.GetGrafixPtr(target);

            if (animPtr != null)
            {
                target.Core.offset         = animPtr[0]; animPtr.Offset += 2;
                target.Core.getToFlag      = animPtr[0]; animPtr.Offset += 2;
                target.Core.grafixProgPos += 2;
            }
            else
            {
                target.Core.grafixProgId = 0;
            }

            bool speechFileFound = false;

            if (SkyEngine.IsCDVersion)
            {
                speechFileFound = _skySound.StartSpeech((ushort)textNum);
            }


            // Set the focus region to that area
            // Calculate the point where the character is
            int x = target.Core.xcood - TOP_LEFT_X;
            int y = target.Core.ycood - TOP_LEFT_Y;

            // TODO: Make the box size change based on the object that has the focus
            _skyScreen.SetFocusRectangle(new Rect(x, y, 192, 128));


            if (SystemVars.Instance.SystemFlags.HasFlag(SystemFlags.AllowText) || !speechFileFound)
            {
                // form the text sprite, if player wants subtitles or
                // if we couldn't find the speech file
                var textInfo    = _skyText.LowTextManager(textNum, FIXED_TEXT_WIDTH, 0, (byte)target.Core.spColor, true);
                var textCompact = _skyCompact.FetchCpt(textInfo.CompactNum);
                target.Core.spTextId = textInfo.CompactNum; //So we know what text to kill
                var textGfxHeader = ServiceLocator.Platform.ToStructure <DataFileHeader>(textInfo.TextData, 0);

                textCompact.Core.screen = target.Core.screen;   //put it on our screen

                if (_scriptVariables[SCREEN] == target.Core.screen)
                { // Only use coordinates if we are on the current screen
                  //talking on-screen
                  //create the x coordinate for the speech text
                  //we need the talkers sprite information
                    var    targetGfx = SkyEngine.ItemList[target.Core.frame >> 6];
                    var    header    = ServiceLocator.Platform.ToStructure <DataFileHeader>(targetGfx, 0);
                    ushort xPos      = (ushort)(target.Core.xcood + header.s_offset_x);
                    ushort width     = (ushort)(header.s_width >> 1);

                    xPos += (ushort)(width - FIXED_TEXT_WIDTH / 2); //middle of talker

                    if (xPos < TOP_LEFT_X)
                    {
                        xPos = TOP_LEFT_X;
                    }

                    width = (ushort)(xPos + FIXED_TEXT_WIDTH);
                    if (TOP_LEFT_X + FULL_SCREEN_WIDTH <= width)
                    {
                        xPos  = TOP_LEFT_X + FULL_SCREEN_WIDTH;
                        xPos -= FIXED_TEXT_WIDTH;
                    }

                    textCompact.Core.xcood = xPos;
                    ushort yPos = (ushort)(target.Core.ycood + (header.s_offset_y - 6 - textGfxHeader.s_height));

                    if (yPos < TOP_LEFT_Y)
                    {
                        yPos = TOP_LEFT_Y;
                    }

                    textCompact.Core.ycood = yPos;
                }
                else
                {
                    //talking off-screen
                    target.Core.spTextId    = 0; //don't kill any text 'cos none was made
                    textCompact.Core.status = 0; //don't display text
                }
                // In CD version, we're doing the timing by checking when the VOC has stopped playing.
                // Setting spTime to 10 thus means that we're doing a pause of 10 gamecycles between
                // each sentence.
                if (speechFileFound)
                {
                    target.Core.spTime = 10;
                }
                else
                {
                    target.Core.spTime = (ushort)(_skyText.NumLetters + 5);
                }
            }
            else
            {
                target.Core.spTime   = 10;
                target.Core.spTextId = 0;
            }
            target.Core.logic = L_TALK;
        }
Пример #28
0
        private void PointerEngine(ushort xPos, ushort yPos)
        {
            UShortAccess currentList;
            var          currentListNum = Logic.ScriptVariables[Logic.MOUSE_LIST_NO];

            do
            {
                currentList = new UShortAccess(_skyCompact.FetchCptRaw((ushort)currentListNum), 0);
                while ((currentList[0] != 0) && (currentList[0] != 0xFFFF))
                {
                    var itemNum  = currentList[0];
                    var itemData = _skyCompact.FetchCpt(itemNum);
                    currentList.Offset += 2;
                    if ((itemData.Core.screen == Logic.ScriptVariables[Logic.SCREEN]) &&
                        ((itemData.Core.status & 16) != 0))
                    {
                        if (itemData.Core.xcood + itemData.Core.mouseRelX > xPos)
                        {
                            continue;
                        }
                        if (itemData.Core.xcood + itemData.Core.mouseRelX + itemData.Core.mouseSizeX < xPos)
                        {
                            continue;
                        }
                        if (itemData.Core.ycood + itemData.Core.mouseRelY > yPos)
                        {
                            continue;
                        }
                        if (itemData.Core.ycood + itemData.Core.mouseRelY + itemData.Core.mouseSizeY < yPos)
                        {
                            continue;
                        }
                        // we've hit the item
                        if (Logic.ScriptVariables[Logic.SPECIAL_ITEM] == itemNum)
                        {
                            return;
                        }
                        Logic.ScriptVariables[Logic.SPECIAL_ITEM] = itemNum;
                        if (Logic.ScriptVariables[Logic.GET_OFF] != 0)
                        {
                            Logic.MouseScript(Logic.ScriptVariables[Logic.GET_OFF], itemData);
                        }
                        Logic.ScriptVariables[Logic.GET_OFF] = itemData.Core.mouseOff;
                        if (itemData.Core.mouseOn != 0)
                        {
                            Logic.MouseScript(itemData.Core.mouseOn, itemData);
                        }
                        return;
                    }
                }
                if (currentList[0] == 0xFFFF)
                {
                    currentListNum = currentList[1];
                }
            } while (currentList[0] != 0);

            if (Logic.ScriptVariables[Logic.SPECIAL_ITEM] != 0)
            {
                Logic.ScriptVariables[Logic.SPECIAL_ITEM] = 0;

                if (Logic.ScriptVariables[Logic.GET_OFF] != 0)
                {
                    Logic.Script((ushort)Logic.ScriptVariables[Logic.GET_OFF], (ushort)(Logic.ScriptVariables[Logic.GET_OFF] >> 16));
                }
                Logic.ScriptVariables[Logic.GET_OFF] = 0;
            }
        }