diff --git a/source/exhumed/CMakeLists.txt b/source/exhumed/CMakeLists.txt index 8b9472b16..06cbc11e0 100644 --- a/source/exhumed/CMakeLists.txt +++ b/source/exhumed/CMakeLists.txt @@ -28,6 +28,7 @@ set( PCH_SOURCES src/player.cpp src/queen.cpp src/ra.cpp + src/ramses.cpp src/random.cpp src/rat.cpp src/rex.cpp diff --git a/source/exhumed/src/exhumed.cpp b/source/exhumed/src/exhumed.cpp index ab2aa223e..e95b857d0 100644 --- a/source/exhumed/src/exhumed.cpp +++ b/source/exhumed/src/exhumed.cpp @@ -104,38 +104,6 @@ void RemoveEngine() -const uint32_t kSpiritX = 106; -const uint32_t kSpiritY = 97; - -short cPupData[300]; -//int worktile[97 * 106] = { 0 }; -uint8_t *Worktile; -const uint32_t WorktileSize = kSpiritX * 2 * kSpiritY * 2; -int lHeadStartClock; -short *pPupData; -int lNextStateChange; -int nPixels; -int nHeadTimeStart; -short curx[97 * 106]; -short cury[97 * 106]; -int8_t destvelx[97 * 106]; -int8_t destvely[97 * 106]; -uint8_t pixelval[97 * 106]; -int8_t origy[97 * 106]; -int8_t origx[97 * 106]; -int8_t velx[97 * 106]; -int8_t vely[97 * 106]; -short nMouthTile; - -short nPupData = 0; - -short word_964E8 = 0; -short word_964EA = 0; -short word_964EC = 10; - -short nSpiritRepeatX; -short nSpiritRepeatY; -short nPixelsToShow; void CopyTileToBitmap(short nSrcTile, short nDestTile, int xPos, int yPos); void DoTitle(); @@ -160,7 +128,6 @@ short nFreeze; short nSnakeCam = -1; short nBestLevel; -short nSpiritSprite; short nLocalSpr; short levelnew = 1; @@ -181,13 +148,8 @@ short bModemPlay = false; int lCountDown = 0; short nEnergyTowers = 0; - -short nHeadStage; - short nCfgNetPlayers = 0; FILE *vcrfp = NULL; -short nTalkTime = 0; - short forcelevel = -1; int lLocalButtons = 0; @@ -1324,510 +1286,6 @@ void EraseScreen(int nVal) twod->ClearScreen(); } -void InitSpiritHead() -{ - char filename[20]; - - nPixels = 0; - - nSpiritRepeatX = sprite[nSpiritSprite].xrepeat; - nSpiritRepeatY = sprite[nSpiritSprite].yrepeat; - - tileLoad(kTileRamsesNormal); // Ramses Normal Head - - for (int i = 0; i < kMaxSprites; i++) - { - if (sprite[i].statnum) - { - sprite[i].cstat |= 0x8000; - } - } - - auto pTile = tilePtr(kTileRamsesNormal); // Ramses Normal Head - auto pGold = tilePtr(kTileRamsesGold); - for (int x = 0; x < 97; x++) - { - for (int y = 0; y < 106; y++) - { - if (*pTile != TRANSPARENT_INDEX) - { - pixelval[nPixels] = *(pGold + x * 106 + y); - origx[nPixels] = x - 48; - origy[nPixels] = y - 53; - curx[nPixels] = 0; - cury[nPixels] = 0; - vely[nPixels] = 0; - velx[nPixels] = 0; - - destvelx[nPixels] = RandomSize(2) + 1; - - if (curx[nPixels] > 0) { - destvelx[nPixels] = -destvelx[nPixels]; - } - - destvely[nPixels] = RandomSize(2) + 1; - - if (cury[nPixels] > 0) { - destvely[nPixels] = -destvely[nPixels]; - } - - nPixels++; - } - - pTile++; - } - } - - - sprite[nSpiritSprite].yrepeat = 140; - sprite[nSpiritSprite].xrepeat = 140; - sprite[nSpiritSprite].picnum = kTileRamsesWorkTile; - - nHeadStage = 0; - - // work tile is twice as big as the normal head size - Worktile = TileFiles.tileCreate(kTileRamsesWorkTile, kSpiritX * 2, kSpiritY * 2); - - sprite[nSpiritSprite].cstat &= 0x7FFF; - - nHeadTimeStart = (int)totalclock; - - memset(Worktile, TRANSPARENT_INDEX, WorktileSize); - TileFiles.InvalidateTile(kTileRamsesWorkTile); - - nPixelsToShow = 0; - - fadecdaudio(); - - int nTrack; - - if (levelnum == 1) - { - nTrack = 3; - } - else - { - nTrack = 7; - } - - bSubTitles = playCDtrack(nTrack, false) == 0; - - StartSwirlies(); - - sprintf(filename, "LEV%d.PUP", levelnum); - lNextStateChange = (int)totalclock; - lHeadStartClock = (int)totalclock; - - auto headfd = fileSystem.OpenFileReader(filename); // 512?? - if (!headfd.isOpen()) - { - memset(cPupData, 0, sizeof(cPupData)); - } - else - { - nPupData = headfd.Read(cPupData, sizeof(cPupData)); - pPupData = cPupData; - } - nMouthTile = 0; - nTalkTime = 1; -} - -void DimSector(short nSector) -{ - short startwall = sector[nSector].wallptr; - short nWalls = sector[nSector].wallnum; - - for (int i = 0; i < nWalls; i++) - { - if (wall[startwall+i].shade < 40) { - wall[startwall+i].shade++; - } - } - - if (sector[nSector].floorshade < 40) { - sector[nSector].floorshade++; - } - - if (sector[nSector].ceilingshade < 40) { - sector[nSector].ceilingshade++; - } -} - -void CopyHeadToWorkTile(short nTile) -{ - const uint8_t* pSrc = tilePtr(nTile); - uint8_t *pDest = &Worktile[212 * 49 + 53]; - - for (int i = 0; i < 97; i++) - { - memcpy(pDest, pSrc, 106); - - pDest += 212; - pSrc += 106; - } -} - -int DoSpiritHead() -{ - static short word_964E6 = 0; - - PlayerList[0].q16horiz = fix16_sadd(PlayerList[0].q16horiz, fix16_sdiv(fix16_ssub(nDestVertPan[0], PlayerList[0].q16horiz), fix16_from_int(4))); - - TileFiles.InvalidateTile(kTileRamsesWorkTile); - - if (nHeadStage < 2) - { - memset(Worktile, TRANSPARENT_INDEX, WorktileSize); - } - - if (nHeadStage < 2 || nHeadStage != 5) - { - nPixelsToShow = ((int)totalclock - nHeadTimeStart) * 15; - - if (nPixelsToShow > nPixels) { - nPixelsToShow = nPixels; - } - - if (nHeadStage < 3) - { - UpdateSwirlies(); - - if (sprite[nSpiritSprite].shade > -127) { - sprite[nSpiritSprite].shade--; - } - - word_964E6--; - if (word_964E6 < 0) - { - DimSector(sprite[nSpiritSprite].sectnum); - word_964E6 = 5; - } - - if (!nHeadStage) - { - if (((int)totalclock - nHeadTimeStart) > 480) - { - nHeadStage = 1; - nHeadTimeStart = (int)totalclock + 480; - } - - for (int i = 0; i < nPixelsToShow; i++) - { - if (destvely[i] >= 0) - { - vely[i]++; - - if (vely[i] >= destvely[i]) - { - destvely[i] = -(RandomSize(2) + 1); - } - } - else - { - vely[i]--; - - if (vely[i] <= destvely[i]) - { - destvely[i] = RandomSize(2) + 1; - } - } - - // loc_13541 - if (destvelx[i] >= 0) - { - velx[i]++; - - if (velx[i] >= destvelx[i]) - { - destvelx[i] = -(RandomSize(2) + 1); - } - } - else - { - velx[i]--; - - if (velx[i] <= destvelx[i]) - { - destvelx[i] = RandomSize(2) + 1; - } - } - - int esi = vely[i] + (cury[i] >> 8); - - if (esi < 106) - { - if (esi < -105) - { - vely[i] = 0; - esi = 0; - } - } - else - { - vely[i] = 0; - esi = 0; - } - - int ebx = velx[i] + (curx[i] >> 8); - - if (ebx < 97) - { - if (ebx < -96) - { - velx[i] = 0; - ebx = 0; - } - } - else - { - velx[i] = 0; - ebx = 0; - } - - curx[i] = ebx * 256; - cury[i] = esi * 256; - - esi += (ebx + 97) * 212; - - Worktile[106 + esi] = pixelval[i]; - } - - return 1; - } - else - { - if (nHeadStage != 1) { - return 1; - } - - uint8_t nXRepeat = sprite[nSpiritSprite].xrepeat; - if (nXRepeat > nSpiritRepeatX) - { - sprite[nSpiritSprite].xrepeat -= 2; - - nXRepeat = sprite[nSpiritSprite].xrepeat; - if (nXRepeat < nSpiritRepeatX) - { - sprite[nSpiritSprite].xrepeat = nSpiritRepeatX; - } - } - - uint8_t nYRepeat = sprite[nSpiritSprite].yrepeat; - if (nYRepeat > nSpiritRepeatY) - { - sprite[nSpiritSprite].yrepeat -= 2; - - nYRepeat = sprite[nSpiritSprite].yrepeat; - if (nYRepeat < nSpiritRepeatY) - { - sprite[nSpiritSprite].yrepeat = nSpiritRepeatY; - } - } - - int esi = 0; - - for (int i = 0; i < nPixels; i++) - { - int eax = (origx[i] << 8) - curx[i]; - int ecx = eax; - - if (eax) - { - if (eax < 0) { - eax = -eax; - } - - if (eax < 8) - { - curx[i] = origx[i] << 8; - ecx = 0; - } - else { - ecx >>= 3; - } - } - else - { - ecx >>= 3; - } - - int var_1C = (origy[i] << 8) - cury[i]; - int ebp = var_1C; - - if (var_1C) - { - eax = ebp; - - if (eax < 0) { - eax = -eax; - } - - if (eax < 8) - { - cury[i] = origy[i] << 8; - var_1C = 0; - } - else - { - var_1C >>= 3; - } - } - else - { - var_1C >>= 3; - } - - if (var_1C || ecx) - { - curx[i] += ecx; - cury[i] += var_1C; - - esi++; - } - - ecx = (((curx[i] >> 8) + 97) * 212) + (cury[i] >> 8); - - - Worktile[106 + ecx] = pixelval[i]; - } - - if (((int)totalclock - lHeadStartClock) > 600) { - CopyHeadToWorkTile(kTileRamsesGold); - } - - int eax = ((nPixels << 4) - nPixels) / 16; - - if (esi < eax) - { - SoundBigEntrance(); - AddGlow(sprite[nSpiritSprite].sectnum, 20); - AddFlash( - sprite[nSpiritSprite].sectnum, - sprite[nSpiritSprite].x, - sprite[nSpiritSprite].y, - sprite[nSpiritSprite].z, - 128); - - nHeadStage = 3; - TintPalette(255, 255, 255); - CopyHeadToWorkTile(kTileRamsesNormal); - } - - return 1; - } - } - else - { - FixPalette(); - - if (!nPalDiff) - { - nFreeze = 2; - nHeadStage++; - } - - return 0; - } - } - else - { - if (lNextStateChange <= (int)totalclock) - { - if (nPupData) - { - short nPupVal = *pPupData; - pPupData++; - nPupData -= 2; - - if (nPupData > 0) - { - lNextStateChange = (nPupVal + lHeadStartClock) - 10; - nTalkTime = !nTalkTime; - } - else - { - nTalkTime = 0; - nPupData = 0; - } - } - else if (!bSubTitles) - { - if (!CDplaying()) - { - levelnew = levelnum + 1; - fadecdaudio(); - } - } - } - - word_964E8--; - if (word_964E8 <= 0) - { - word_964EA = RandomBit() * 2; - word_964E8 = RandomSize(5) + 4; - } - - int ebx = 592; - word_964EC--; - - if (word_964EC < 3) - { - ebx = 593; - if (word_964EC <= 0) { - word_964EC = RandomSize(6) + 4; - } - } - - ebx += word_964EA; - - uint8_t *pDest = &Worktile[10441]; - const uint8_t* pSrc = tilePtr(ebx); - - for (int i = 0; i < 97; i++) - { - memcpy(pDest, pSrc, 106); - - pDest += 212; - pSrc += 106; - } - - if (nTalkTime) - { - if (nMouthTile < 2) { - nMouthTile++; - } - } - else if (nMouthTile != 0) - { - nMouthTile--; - } - - if (nMouthTile) - { - short nTileSizeX = tilesiz[nMouthTile + 598].x; - short nTileSizeY = tilesiz[nMouthTile + 598].y; - - uint8_t *pDest = &Worktile[212 * (97 - nTileSizeX / 2)] + (159 - nTileSizeY); - const uint8_t *pSrc = tilePtr(nMouthTile + 598); - - while (nTileSizeX > 0) - { - memcpy(pDest, pSrc, nTileSizeY); - - nTileSizeX--; - pDest += 212; - pSrc += nTileSizeY; - } - } - - return 1; - } - - // TEMP FIXME - temporary return value. what to return here? 1? - - return 0; -} - bool GameInterface::CanSave() { return !bRecord && !bPlayback && !paused && !bInDemo && nTotalPlayers == 1; @@ -1841,27 +1299,7 @@ bool GameInterface::CanSave() // This is only the static global data. static SavegameHelper sgh("exhumed", - SA(cPupData), - SV(nPupData), - SV(nPixels), SV(besttarget), - SA(curx), - SA(cury), - SA(destvelx), - SA(destvely), - SA(pixelval), - SA(origy), - SA(origx), - SA(velx), - SA(vely), - SV(nMouthTile), - SV(nSpiritSprite), - SV(word_964E8), - SV(word_964EA), - SV(word_964EC), - SV(nSpiritRepeatX), - SV(nSpiritRepeatY), - SV(nPixelsToShow), SV(nCreaturesLeft), // todo: also maintain a total counter. SV(nFreeze), SV(nSnakeCam), @@ -1874,8 +1312,6 @@ static SavegameHelper sgh("exhumed", SV(nEnergyChan), SV(lCountDown), SV(nEnergyTowers), - SV(nHeadStage), - SV(nTalkTime), SV(levelnum), SV(moveframes), SV(totalmoves), @@ -1883,15 +1319,17 @@ static SavegameHelper sgh("exhumed", SV(nBodyTotal), SV(bSnakeCam), SV(bSlipMode), - SV(lHeadStartClock), - SV(lNextStateChange), - SV(nHeadTimeStart), SV(localclock), SV(tclocks), SV(tclocks2), SV(totalclock), nullptr); +extern short cPupData[300]; +extern uint8_t* Worktile; +extern int lHeadStartClock; +extern short* pPupData; + void SaveTextureState() { diff --git a/source/exhumed/src/exhumed.h b/source/exhumed/src/exhumed.h index cec29dda5..4bf60047e 100644 --- a/source/exhumed/src/exhumed.h +++ b/source/exhumed/src/exhumed.h @@ -279,6 +279,9 @@ void G_DoAutoload(const char* dirname); int savegame(int nSlot); int loadgame(int nSlot); +const uint32_t kSpiritX = 106; +const uint32_t kSpiritY = 97; +const uint32_t WorktileSize = kSpiritX * 2 * kSpiritY * 2; struct SavegameHelper { diff --git a/source/exhumed/src/ramses.cpp b/source/exhumed/src/ramses.cpp new file mode 100644 index 000000000..a26fa368e --- /dev/null +++ b/source/exhumed/src/ramses.cpp @@ -0,0 +1,593 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2010-2020 EDuke32 developers and contributors +Copyright (C) 2020 sirlemonhead, Nuke.YKT +This file is part of PCExhumed. +PCExhumed is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- +#include "ns.h" + +#include "engine.h" +#include "exhumed.h" +#include "sound.h" +#include "view.h" +#include "names.h" +#include "aistuff.h" +#include "player.h" + + +BEGIN_PS_NS + +short cPupData[300]; +uint8_t *Worktile; +int lHeadStartClock; +short* pPupData; +int lNextStateChange; +int nPixels; +int nHeadTimeStart; +short nHeadStage; +short curx[97 * 106]; +short cury[97 * 106]; +int8_t destvelx[97 * 106]; +int8_t destvely[97 * 106]; +uint8_t pixelval[97 * 106]; +int8_t origy[97 * 106]; +int8_t origx[97 * 106]; +int8_t velx[97 * 106]; +int8_t vely[97 * 106]; +short nMouthTile; + +short nPupData = 0; + +short word_964E8 = 0; +short word_964EA = 0; +short word_964EC = 10; + +short nSpiritRepeatX; +short nSpiritRepeatY; +short nSpiritSprite; +short nPixelsToShow; +short nTalkTime = 0; + + +void InitSpiritHead() +{ + char filename[20]; + + nPixels = 0; + + nSpiritRepeatX = sprite[nSpiritSprite].xrepeat; + nSpiritRepeatY = sprite[nSpiritSprite].yrepeat; + + tileLoad(kTileRamsesNormal); // Ramses Normal Head + + for (int i = 0; i < kMaxSprites; i++) + { + if (sprite[i].statnum) + { + sprite[i].cstat |= 0x8000; + } + } + + auto pTile = tilePtr(kTileRamsesNormal); // Ramses Normal Head + auto pGold = tilePtr(kTileRamsesGold); + for (int x = 0; x < 97; x++) + { + for (int y = 0; y < 106; y++) + { + if (*pTile != TRANSPARENT_INDEX) + { + pixelval[nPixels] = *(pGold + x * 106 + y); + origx[nPixels] = x - 48; + origy[nPixels] = y - 53; + curx[nPixels] = 0; + cury[nPixels] = 0; + vely[nPixels] = 0; + velx[nPixels] = 0; + + destvelx[nPixels] = RandomSize(2) + 1; + + if (curx[nPixels] > 0) { + destvelx[nPixels] = -destvelx[nPixels]; + } + + destvely[nPixels] = RandomSize(2) + 1; + + if (cury[nPixels] > 0) { + destvely[nPixels] = -destvely[nPixels]; + } + + nPixels++; + } + + pTile++; + } + } + + + sprite[nSpiritSprite].yrepeat = 140; + sprite[nSpiritSprite].xrepeat = 140; + sprite[nSpiritSprite].picnum = kTileRamsesWorkTile; + + nHeadStage = 0; + + // work tile is twice as big as the normal head size + Worktile = TileFiles.tileCreate(kTileRamsesWorkTile, kSpiritX * 2, kSpiritY * 2); + + sprite[nSpiritSprite].cstat &= 0x7FFF; + + nHeadTimeStart = (int)totalclock; + + memset(Worktile, TRANSPARENT_INDEX, WorktileSize); + TileFiles.InvalidateTile(kTileRamsesWorkTile); + + nPixelsToShow = 0; + + fadecdaudio(); + + int nTrack; + + if (levelnum == 1) + { + nTrack = 3; + } + else + { + nTrack = 7; + } + + bSubTitles = playCDtrack(nTrack, false) == 0; + + StartSwirlies(); + + sprintf(filename, "LEV%d.PUP", levelnum); + lNextStateChange = (int)totalclock; + lHeadStartClock = (int)totalclock; + + auto headfd = fileSystem.OpenFileReader(filename); + if (!headfd.isOpen()) + { + memset(cPupData, 0, sizeof(cPupData)); + } + else + { + nPupData = headfd.Read(cPupData, sizeof(cPupData)); + pPupData = cPupData; + } + nMouthTile = 0; + nTalkTime = 1; +} + +void DimSector(short nSector) +{ + short startwall = sector[nSector].wallptr; + short nWalls = sector[nSector].wallnum; + + for (int i = 0; i < nWalls; i++) + { + if (wall[startwall+i].shade < 40) { + wall[startwall+i].shade++; + } + } + + if (sector[nSector].floorshade < 40) { + sector[nSector].floorshade++; + } + + if (sector[nSector].ceilingshade < 40) { + sector[nSector].ceilingshade++; + } +} + +void CopyHeadToWorkTile(short nTile) +{ + const uint8_t* pSrc = tilePtr(nTile); + uint8_t *pDest = &Worktile[212 * 49 + 53]; + + for (int i = 0; i < kSpiritY; i++) + { + memcpy(pDest, pSrc, kSpiritX); + + pDest += 212; + pSrc += kSpiritX; + } +} + +int DoSpiritHead() +{ + static short word_964E6 = 0; + + PlayerList[0].q16horiz = fix16_sadd(PlayerList[0].q16horiz, fix16_sdiv(fix16_ssub(nDestVertPan[0], PlayerList[0].q16horiz), fix16_from_int(4))); + + TileFiles.InvalidateTile(kTileRamsesWorkTile); + + if (nHeadStage < 2) + { + memset(Worktile, TRANSPARENT_INDEX, WorktileSize); + } + + if (nHeadStage < 2 || nHeadStage != 5) + { + nPixelsToShow = ((int)totalclock - nHeadTimeStart) * 15; + + if (nPixelsToShow > nPixels) { + nPixelsToShow = nPixels; + } + + if (nHeadStage < 3) + { + UpdateSwirlies(); + + if (sprite[nSpiritSprite].shade > -127) { + sprite[nSpiritSprite].shade--; + } + + word_964E6--; + if (word_964E6 < 0) + { + DimSector(sprite[nSpiritSprite].sectnum); + word_964E6 = 5; + } + + if (!nHeadStage) + { + if (((int)totalclock - nHeadTimeStart) > 480) + { + nHeadStage = 1; + nHeadTimeStart = (int)totalclock + 480; + } + + for (int i = 0; i < nPixelsToShow; i++) + { + if (destvely[i] >= 0) + { + vely[i]++; + + if (vely[i] >= destvely[i]) + { + destvely[i] = -(RandomSize(2) + 1); + } + } + else + { + vely[i]--; + + if (vely[i] <= destvely[i]) + { + destvely[i] = RandomSize(2) + 1; + } + } + + if (destvelx[i] >= 0) + { + velx[i]++; + + if (velx[i] >= destvelx[i]) + { + destvelx[i] = -(RandomSize(2) + 1); + } + } + else + { + velx[i]--; + + if (velx[i] <= destvelx[i]) + { + destvelx[i] = RandomSize(2) + 1; + } + } + + int esi = vely[i] + (cury[i] >> 8); + + if (esi < kSpiritX) + { + if (esi < -105) + { + vely[i] = 0; + esi = 0; + } + } + else + { + vely[i] = 0; + esi = 0; + } + + int ebx = velx[i] + (curx[i] >> 8); + + if (ebx < kSpiritY) + { + if (ebx < -96) + { + velx[i] = 0; + ebx = 0; + } + } + else + { + velx[i] = 0; + ebx = 0; + } + + curx[i] = ebx * 256; + cury[i] = esi * 256; + + esi += (ebx + kSpiritY) * 212; + + Worktile[kSpiritX + esi] = pixelval[i]; + } + + return 1; + } + else + { + if (nHeadStage != 1) { + return 1; + } + + uint8_t nXRepeat = sprite[nSpiritSprite].xrepeat; + if (nXRepeat > nSpiritRepeatX) + { + sprite[nSpiritSprite].xrepeat -= 2; + + nXRepeat = sprite[nSpiritSprite].xrepeat; + if (nXRepeat < nSpiritRepeatX) + { + sprite[nSpiritSprite].xrepeat = nSpiritRepeatX; + } + } + + uint8_t nYRepeat = sprite[nSpiritSprite].yrepeat; + if (nYRepeat > nSpiritRepeatY) + { + sprite[nSpiritSprite].yrepeat -= 2; + + nYRepeat = sprite[nSpiritSprite].yrepeat; + if (nYRepeat < nSpiritRepeatY) + { + sprite[nSpiritSprite].yrepeat = nSpiritRepeatY; + } + } + + int esi = 0; + + for (int i = 0; i < nPixels; i++) + { + int eax = (origx[i] << 8) - curx[i]; + int ecx = eax; + + if (eax) + { + if (eax < 0) { + eax = -eax; + } + + if (eax < 8) + { + curx[i] = origx[i] << 8; + ecx = 0; + } + else { + ecx >>= 3; + } + } + else + { + ecx >>= 3; + } + + int var_1C = (origy[i] << 8) - cury[i]; + int ebp = var_1C; + + if (var_1C) + { + eax = ebp; + + if (eax < 0) { + eax = -eax; + } + + if (eax < 8) + { + cury[i] = origy[i] << 8; + var_1C = 0; + } + else + { + var_1C >>= 3; + } + } + else + { + var_1C >>= 3; + } + + if (var_1C || ecx) + { + curx[i] += ecx; + cury[i] += var_1C; + + esi++; + } + + ecx = (((curx[i] >> 8) + kSpiritY) * 212) + (cury[i] >> 8); + + Worktile[kSpiritX + ecx] = pixelval[i]; + } + + if (((int)totalclock - lHeadStartClock) > 600) + { + CopyHeadToWorkTile(kTileRamsesGold); + } + + int eax = ((nPixels << 4) - nPixels) / 16; + + if (esi < eax) + { + SoundBigEntrance(); + AddGlow(sprite[nSpiritSprite].sectnum, 20); + AddFlash( + sprite[nSpiritSprite].sectnum, + sprite[nSpiritSprite].x, + sprite[nSpiritSprite].y, + sprite[nSpiritSprite].z, + 128); + + nHeadStage = 3; + TintPalette(255, 255, 255); + CopyHeadToWorkTile(kTileRamsesNormal); + } + + return 1; + } + } + else + { + FixPalette(); + + if (!nPalDiff) + { + nFreeze = 2; + nHeadStage++; + } + + return 0; + } + } + else + { + if (lNextStateChange <= (int)totalclock) + { + if (nPupData) + { + short nPupVal = *pPupData; + pPupData++; + nPupData -= 2; + + if (nPupData > 0) + { + lNextStateChange = (nPupVal + lHeadStartClock) - 10; + nTalkTime = !nTalkTime; + } + else + { + nTalkTime = 0; + nPupData = 0; + } + } + else if (!bSubTitles) + { + if (!CDplaying()) + { + levelnew = levelnum + 1; + fadecdaudio(); + } + } + } + + word_964E8--; + if (word_964E8 <= 0) + { + word_964EA = RandomBit() * 2; + word_964E8 = RandomSize(5) + 4; + } + + int ebx = 592; + word_964EC--; + + if (word_964EC < 3) + { + ebx = 593; + if (word_964EC <= 0) { + word_964EC = RandomSize(6) + 4; + } + } + + ebx += word_964EA; + + uint8_t *pDest = &Worktile[10441]; + const uint8_t* pSrc = tilePtr(ebx); + + for (int i = 0; i < kSpiritY; i++) + { + memcpy(pDest, pSrc, kSpiritX); + + pDest += 212; + pSrc += kSpiritX; + } + + if (nTalkTime) + { + if (nMouthTile < 2) { + nMouthTile++; + } + } + else if (nMouthTile != 0) + { + nMouthTile--; + } + + if (nMouthTile) + { + short nTileSizeX = tilesiz[nMouthTile + 598].x; + short nTileSizeY = tilesiz[nMouthTile + 598].y; + + uint8_t *pDest = &Worktile[212 * (kSpiritY - nTileSizeX / 2)] + (159 - nTileSizeY); + const uint8_t *pSrc = tilePtr(nMouthTile + 598); + + while (nTileSizeX > 0) + { + memcpy(pDest, pSrc, nTileSizeY); + + nTileSizeX--; + pDest += 212; + pSrc += nTileSizeY; + } + } + + return 1; + } + + return 0; +} + +// This is only the static global data. +static SavegameHelper sgh("ramses", + SA(cPupData), + SV(nPupData), + SV(nPixels), + SA(curx), + SA(cury), + SA(destvelx), + SA(destvely), + SA(pixelval), + SA(origy), + SA(origx), + SA(velx), + SA(vely), + SV(nMouthTile), + SV(nSpiritSprite), + SV(word_964E8), + SV(word_964EA), + SV(word_964EC), + SV(nSpiritRepeatX), + SV(nSpiritRepeatY), + SV(nPixelsToShow), + SV(nTalkTime), + SV(lHeadStartClock), + SV(lNextStateChange), + SV(nHeadStage), + SV(nHeadTimeStart) + ); + +END_PS_NS