2019-08-26 03:59:14 +00:00
# include "compat.h"
# include "baselayer.h"
2019-08-31 09:08:38 +00:00
# include "renderlayer.h"
# include "typedefs.h"
# include "common.h"
2019-08-26 03:59:14 +00:00
# include "keyboard.h"
# include "control.h"
# include "engine.h"
# include "exhumed.h"
2019-08-31 09:08:38 +00:00
# include "osdcmds.h"
2019-08-26 03:59:14 +00:00
# include "map.h"
# include "sequence.h"
# include "movie.h"
# include "names.h"
# include "menu.h"
# include "player.h"
# include "network.h"
# include "input.h"
# include "sound.h"
# include "cd.h"
# include "view.h"
# include "status.h"
# include "config.h"
# include "init.h"
# include "ra.h"
# include "version.h"
# include "timer.h"
# include "runlist.h"
# include "anubis.h"
# include "spider.h"
# include "mummy.h"
# include "fish.h"
# include "lion.h"
# include "light.h"
# include "move.h"
# include "lavadude.h"
# include "rex.h"
# include "set.h"
# include "queen.h"
# include "roach.h"
# include "wasp.h"
# include "scorp.h"
# include "rat.h"
# include "cdrom.h"
# include "cdaudio.h"
# include "serial.h"
# include "network.h"
# include "random.h"
# include "items.h"
# include "trigdat.h"
# include "record.h"
# include "lighting.h"
# include <string.h>
# include <cstdio> // for printf
# include <cstdlib>
# include <stdarg.h>
# include <ctype.h>
# include <time.h>
# include <assert.h>
2019-08-31 09:08:38 +00:00
# ifdef _WIN32
# include "winbits.h"
# endif /* _WIN32 */
2019-08-27 06:08:18 +00:00
# ifdef __cplusplus
extern " C " {
# endif
extern const char * s_buildRev ;
extern const char * s_buildTimestamp ;
# ifdef __cplusplus
}
# endif
2019-08-31 09:08:38 +00:00
const char * AppProperName = APPNAME ;
const char * AppTechnicalName = APPBASENAME ;
2019-08-26 03:59:14 +00:00
void FinishLevel ( ) ;
int htimer = 0 ;
/* these are XORed in the original game executable then XORed back to normal when the game first starts. Here they are normally */
const char * gString [ ] =
{
2019-08-27 06:08:18 +00:00
" CINEMAS " ,
" THE ANCIENT EGYPTIAN CITY " ,
" OF KARNAK HAS BEEN SEIZED " ,
" BY UNKNOWN POWERS, AND GREAT " ,
" TURMOIL IS SPREADING INTO " ,
" NEIGHBORING LANDS, POSING " ,
" A GRAVE THREAT TO PLANET " ,
" EARTH. MILITANT FORCES FROM " ,
" ALL PARTS OF THE GLOBE HAVE " ,
" ENTERED THE KARNAK VALLEY, " ,
" BUT NONE HAVE RETURNED. THE " ,
" ONLY KNOWN INFORMATION " ,
" REGARDING THIS CRISIS CAME " ,
" FROM A DYING KARNAK VILLAGER " ,
" WHO MANAGED TO WANDER OUT OF " ,
" THE VALLEY TO SAFETY. " ,
" 'THEY'VE STOLEN THE GREAT " ,
" KING'S MUMMY...', MURMURED " ,
" THE DYING VILLAGER, BUT THE " ,
" VILLAGER DIED BEFORE HE " ,
" COULD SAY MORE. WITH NO " ,
" OTHER OPTIONS, WORLD " ,
" LEADERS HAVE CHOSEN TO DROP " ,
" YOU INTO THE VALLEY VIA " ,
" HELICOPTER IN AN ATTEMPT " ,
" TO FIND AND DESTROY THE " ,
" THREATENING FORCES AND " ,
" RESOLVE THE MYSTERY THAT " ,
" HAS ENGULFED THIS ONCE " ,
" PEACEFUL LAND. FLYING AT " ,
" HIGH ALTITUDE TO AVOID " ,
" BEING SHOT DOWN LIKE OTHERS " ,
" BEFORE YOU, YOUR COPTER " ,
" MYSTERIOUSLY EXPLODES IN THE " ,
" AIR AS YOU BARELY ESCAPE, " ,
" WITH NO POSSIBLE CONTACT " ,
" WITH THE OUTSIDE WORLD. " ,
" SCARED AS HELL, YOU DESCEND " ,
" INTO THE HEART OF KARNAK... " ,
" HOME TO THE CELEBRATED " ,
" BURIAL CRYPT OF THE GREAT " ,
" KING RAMSES. " ,
" END " ,
" AN EVIL FORCE KNOWN AS THE " ,
" KILMAAT HAS BESIEGED THE " ,
" SANCTITY OF MY PALACE AND " ,
" IS PULLING AT THE VERY " ,
" TENDRILS OF MY EXISTENCE. " ,
" THESE FORCES INTEND TO " ,
" ENSLAVE ME BY REANIMATING " ,
" MY PRESERVED CORPSE. I HAVE " ,
" PROTECTED MY CORPSE WITH A " ,
" GENETIC KEY. IF YOU ARE " ,
" UNSUCCESSFUL I CANNOT " ,
" PROTECT CIVILIZATION, AND " ,
" CHAOS WILL PREVAIL. I AM " ,
" BEING TORN BETWEEN WORLDS " ,
" AND THIS INSIDIOUS " ,
" EXPERIMENT MUST BE STOPPED. " ,
" END " ,
" I HAVE HIDDEN A MYSTICAL " ,
" GAUNTLET AT EL KAB THAT WILL " ,
" CHANNEL MY ENERGY THROUGH " ,
" YOUR HANDS. FIND THE " ,
" GAUNTLET AND CROSS THE ASWAN " ,
" HIGH DAM TO DEFEAT THE EVIL " ,
" BEAST SET. " ,
" END " ,
" SET WAS A FORMIDABLE FOE. " ,
" NO MORTAL HAS EVEN CONQUERED " ,
" THEIR OWN FEAR, MUCH LESS " ,
" ENTERED MORTAL BATTLE AND " ,
" TAKEN HIS LIFE. " ,
" END " ,
" YOU'VE MADE IT HALFWAY TOWARD " ,
" FULLFILLING YOUR DESTINY. " ,
" THE KILMAAT ARE GROWING " ,
" RESTLESS WITH YOUR PROGRESS. " ,
" SEEK OUT A TEMPLE IN THIS " ,
" CITADEL WHERE I WILL PROVIDE " ,
" MORE INFORMATION " ,
" END " ,
" THE KILMAAT RACE HAS " ,
" CONTINUED THEIR MONSTEROUS " ,
" ANIMAL-HUMAN EXPERIMENTS IN " ,
" AN EFFORT TO SOLVE THE KEY OF " ,
" ANIMATING MY CORPSE. THE " ,
" VICTORY DEFEATING SET DIDN'T " ,
" SLOW YOU DOWN AS MUCH AS " ,
" THEY HAD PLANNED. THEY ARE " ,
" ACTIVELY ROBBING A SLAVE " ,
" GIRL OF HER LIFE TO CREATE " ,
" ANOTHER MONSTEROUS " ,
" ABOMINATION, COMBINING HUMAN " ,
" AND INSECT INTENT ON SLAYING " ,
" YOU. PREPARE YOURSELF FOR " ,
" BATTLE AS SHE WILL BE WAITING " ,
" FOR YOU AT THE LUXOR TEMPLE. " ,
" END " ,
" YOU'VE DONE WELL TO DEFEAT " ,
" SELKIS. YOU HAVE DISTRACTED " ,
" THE KILMAAT WITH YOUR " ,
" PRESENCE AND THEY HAVE " ,
" TEMPORARILY ABANDONED " ,
" ANIMATION OF MY CORPSE. " ,
" THE ALIEN QUEEN KILMAATIKHAN " ,
" HAS A PERSONAL VENDETTA " ,
" AGAINST YOU. ARROGANCE IS " ,
" HER WEAKNESS, AND IF YOU CAN " ,
" DEFEAT KILMAATIKHAN, THE " ,
" BATTLE WILL BE WON. " ,
" END " ,
" THE KILMAAT HAVE BEEN " ,
" DESTROYED. UNFORTUNATELY, " ,
" YOUR RECKLESSNESS HAS " ,
" DESTROYED THE EARTH AND ALL " ,
" OF ITS INHABITANTS. ALL THAT " ,
" REMAINS IS A SMOLDERING HUNK " ,
" OF ROCK. " ,
" END " ,
" THE KILMAAT HAVE BEEN " ,
" DEFEATED AND YOU SINGLE " ,
" HANDEDLY SAVED THE EARTH " ,
" FROM DESTRUCTION. " ,
" " ,
" " ,
" " ,
" YOUR BRAVERY AND HEROISM " ,
" ARE LEGENDARY. " ,
" END " ,
" ITEMS " ,
" LIFE BLOOD " ,
" LIFE " ,
" VENOM " ,
" YOU'RE LOSING YOUR GRIP " ,
" FULL LIFE " ,
" INVINCIBILITY " ,
" INVISIBILITY " ,
" TORCH " ,
" SOBEK MASK " ,
" INCREASED WEAPON POWER! " ,
" THE MAP! " ,
" AN EXTRA LIFE! " ,
" .357 MAGNUM! " ,
" GRENADE " ,
" M-60 " ,
" FLAME THROWER! " ,
" COBRA STAFF! " ,
" THE EYE OF RAH GAUNTLET! " ,
" SPEED LOADER " ,
" AMMO " ,
" FUEL " ,
" COBRA! " ,
" RAW ENERGY " ,
" POWER KEY " ,
" TIME KEY " ,
" WAR KEY " ,
" EARTH KEY " ,
" MAGIC " ,
" LOCATION PRESERVED " ,
" COPYRIGHT " ,
" LOBOTOMY SOFTWARE, INC. " ,
" 3D ENGINE BY 3D REALMS " ,
" " ,
" LASTLEVEL " ,
" INCOMING MESSAGE " ,
" " ,
" OUR LATEST SCANS SHOW " ,
" THAT THE ALIEN CRAFT IS " ,
" POWERING UP, APPARENTLY " ,
" IN AN EFFORT TO LEAVE. " ,
" THE BAD NEWS IS THAT THEY " ,
" SEEM TO HAVE LEFT A DEVICE " ,
" BEHIND, AND ALL EVIDENCE " ,
" SAYS ITS GOING TO BLOW A " ,
" BIG HOLE IN OUR FINE PLANET. " ,
" A SQUAD IS TRYING TO DISMANTLE " ,
" IT RIGHT NOW, BUT NO LUCK SO " ,
" FAR, AND TIME IS RUNNING OUT. " ,
" " ,
" GET ABOARD THAT CRAFT NOW " ,
" BEFORE IT LEAVES, THEN FIND " ,
" AND SHOOT ALL THE ENERGY " ,
" TOWERS TO GAIN ACCESS TO THE " ,
" CONTROL ROOM. THERE YOU NEED TO " ,
" TAKE OUT THE CONTROL PANELS AND " ,
" THE CENTRAL POWER SOURCE. THIS " ,
" IS THE BIG ONE BUDDY, BEST OF " ,
" LUCK... FOR ALL OF US. " ,
" " ,
" " ,
" CREDITS " ,
" EXHUMED " ,
" " ,
" EXECUTIVE PRODUCERS " ,
" " ,
" BRIAN MCNEELY " ,
" PAUL LANGE " ,
" " ,
" GAME CONCEPT " ,
" " ,
" PAUL LANGE " ,
" " ,
" GAME DESIGN " ,
" " ,
" BRIAN MCNEELY " ,
" " ,
" ADDITIONAL DESIGN " ,
" " ,
" PAUL KNUTZEN " ,
" PAUL LANGE " ,
" JOHN VAN DEUSEN " ,
" KURT PFEIFER " ,
" DOMINICK MEISSNER " ,
" DANE EMERSON " ,
" " ,
" GAME PROGRAMMING " ,
" " ,
" KURT PFEIFER " ,
" JOHN YUILL " ,
" " ,
" ADDITIONAL PROGRAMMING " ,
" " ,
" PAUL HAUGERUD " ,
" " ,
" ADDITIONAL TECHNICAL SUPPORT " ,
" " ,
" JOHN YUILL " ,
" PAUL HAUGERUD " ,
" JEFF BLAZIER " ,
" " ,
" LEVEL DESIGN " ,
" " ,
" PAUL KNUTZEN " ,
" " ,
" ADDITIONAL LEVELS " ,
" " ,
" BRIAN MCNEELY " ,
" " ,
" MONSTERS AND WEAPONS " ,
" " ,
" JOHN VAN DEUSEN " ,
" " ,
" ARTISTS " ,
" " ,
" BRIAN MCNEELY " ,
" PAUL KNUTZEN " ,
" JOHN VAN DEUSEN " ,
" TROY JACOBSON " ,
" KEVIN CHUNG " ,
" ERIC KLOKSTAD " ,
" RICHARD NICHOLS " ,
" JOE KRESOJA " ,
" JASON WIGGIN " ,
" " ,
" MUSIC AND SOUND EFFECTS " ,
" " ,
" SCOTT BRANSTON " ,
" " ,
" PRODUCT TESTING " ,
" " ,
" DOMINICK MEISSNER " ,
" TOM KRISTENSEN " ,
" JASON WIGGIN " ,
" MARK COATES " ,
" " ,
" INSTRUCTION MANUAL " ,
" " ,
" TOM KRISTENSEN " ,
" " ,
" SPECIAL THANKS " ,
" " ,
" JACQUI LYONS " ,
" MARJACQ MICRO, LTD. " ,
" MIKE BROWN " ,
" IAN MATHIAS " ,
" CHERYL LUSCHEI " ,
" 3D REALMS " ,
" KENNETH SILVERMAN " ,
" GREG MALONE " ,
" MILES DESIGN " ,
" REDMOND AM/PM MINI MART " ,
" 7-11 DOUBLE GULP " ,
" " ,
" THANKS FOR PLAYING " ,
" " ,
" THE END " ,
" " ,
" GUESS YOURE STUCK HERE " ,
" UNTIL THE SONG ENDS " ,
" " ,
" MAYBE THIS IS A GOOD " ,
" TIME TO THINK ABOUT ALL " ,
" THE THINGS YOU CAN DO " ,
" AFTER THE MUSIC IS OVER. " ,
" " ,
" OR YOU COULD JUST STARE " ,
" AT THIS SCREEN " ,
" " ,
" AND WATCH THESE MESSAGES " ,
" GO BY... " ,
" " ,
" ...AND WONDER JUST HOW LONG " ,
" WE WILL DRAG THIS OUT... " ,
" " ,
" AND BELIEVE ME, WE CAN DRAG " ,
" IT OUT FOR QUITE A WHILE. " ,
" " ,
" SHOULD BE OVER SOON... " ,
" " ,
" ANY MOMENT NOW... " ,
" " ,
" " ,
" " ,
" SEE YA " ,
" " ,
" END " ,
" PASSWORDS " ,
" HOLLY " ,
" KIMBERLY " ,
" LOBOCOP " ,
" LOBODEITY " ,
" LOBOLITE " ,
" LOBOPICK " ,
" LOBOSLIP " ,
" LOBOSNAKE " ,
" LOBOSPHERE " ,
" LOBOSWAG " ,
" LOBOXY " ,
" " ,
" PASSINFO " ,
" " ,
" HI SWEETIE, I LOVE YOU " ,
" " ,
" " ,
" SNAKE CAM ENABLED " ,
" FLASHES TOGGLED " ,
" FULL MAP " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" EOF " ,
" " ,
2019-08-26 03:59:14 +00:00
} ;
static char g_rootDir [ BMAX_PATH ] ;
char g_modDir [ BMAX_PATH ] = " / " ;
buildvfs_kfd kopen4loadfrommod ( const char * fileName , char searchfirst )
{
buildvfs_kfd kFile = buildvfs_kfd_invalid ;
if ( g_modDir [ 0 ] ! = ' / ' | | g_modDir [ 1 ] ! = 0 )
{
static char staticFileName [ BMAX_PATH ] ;
Bsnprintf ( staticFileName , sizeof ( staticFileName ) , " %s/%s " , g_modDir , fileName ) ;
kFile = kopen4load ( staticFileName , searchfirst ) ;
}
return ( kFile = = buildvfs_kfd_invalid ) ? kopen4load ( fileName , searchfirst ) : kFile ;
}
2019-08-31 09:08:38 +00:00
int32_t g_commandSetup = 0 ;
int32_t g_noSetup = 0 ;
2019-08-26 03:59:14 +00:00
int g_useCwd ;
2019-08-31 09:08:38 +00:00
void G_ExtPreInit ( int32_t argc , char const * const * argv )
{
g_useCwd = G_CheckCmdSwitch ( argc , argv , " -usecwd " ) ;
# ifdef _WIN32
GetModuleFileName ( NULL , g_rootDir , BMAX_PATH ) ;
Bcorrectfilename ( g_rootDir , 1 ) ;
//buildvfs_chdir(g_rootDir);
# else
buildvfs_getcwd ( g_rootDir , BMAX_PATH ) ;
strcat ( g_rootDir , " / " ) ;
# endif
}
2019-08-26 03:59:14 +00:00
# define kSpiritX = 106;
# define kSpiritY = 97;
short cPupData [ 300 ] ;
//int worktile[97 * 106] = { 0 };
2019-08-31 07:47:15 +00:00
uint8_t worktile [ ( 97 * 2 ) * ( 106 * 2 ) ] = { 0 } ;
2019-08-26 03:59:14 +00:00
int lHeadStartClock ;
short * pPupData ;
int lNextStateChange ;
int nPixels ;
int nHeadTimeStart ;
short curx [ 97 * 106 ] ;
short cury [ 97 * 106 ] ;
2019-08-31 07:47:15 +00:00
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 ] ;
2019-08-26 03:59:14 +00:00
short nMouthTile ;
short nPupData = 0 ;
int headfd = - 1 ;
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 ( ) ;
// void TestSaveLoad();
void EraseScreen ( int nVal ) ;
void LoadStatus ( ) ;
int FindGString ( const char * str ) ;
void MySetView ( int x1 , int y1 , int x2 , int y2 ) ;
void mysetbrightness ( char al ) ;
void FadeIn ( ) ;
char sHollyStr [ 40 ] ;
short nFontFirstChar ;
short nBackgroundPic ;
short nShadowPic ;
short nCreaturesLeft = 0 ;
short bNoSound = kFalse ;
short nFreeze ;
short bFullScreen ;
short nSnakeCam = - 1 ;
short nBestLevel ;
short nSpiritSprite ;
short nLocalSpr ;
short levelnew = 1 ;
int nNetPlayerCount = 0 ;
short nClockVal ;
short fps ;
short nRedTicks ;
short lastlevel ;
2019-08-31 11:44:02 +00:00
volatile short bInMove ;
2019-08-26 03:59:14 +00:00
short nAlarmTicks ;
short nButtonColor ;
short nEnergyChan ;
short bSerialPlay = kFalse ;
short bModemPlay = kFalse ;
int lCountDown = 0 ;
short nEnergyTowers = 0 ;
short nHeadStage ;
short nCfgNetPlayers = 0 ;
FILE * vcrfp = NULL ;
short nTalkTime = 0 ;
short forcelevel = - 1 ;
int lLocalButtons = 0 ;
int lLocalCodes = 0 ;
short bHiRes = kFalse ;
short bCoordinates = kFalse ;
short bNoCDCheck = kFalse ;
int nNetTime = - 1 ;
short nCodeMin = 0 ;
short nCodeMax = 0 ;
short nCodeIndex = 0 ;
short levelnum = - 1 ;
2019-08-27 06:08:18 +00:00
//short nScreenWidth = 320;
//short nScreenHeight = 200;
2019-08-26 03:59:14 +00:00
int moveframes ;
int flash ;
int localclock ;
int totalmoves ;
short nCurBodyNum = 0 ;
short nBodyTotal = 0 ;
short textpages ;
short nCDTrackLength = 0 ;
short lastfps ;
short nCDTracks = 0 ;
short bMapMode = kFalse ;
short bNoCreatures = kFalse ;
short nTotalPlayers = 1 ;
short socket = 0 ;
short nFirstPassword = 0 ;
short nFirstPassInfo = 0 ;
short nPasswordCount = 0 ;
short word_964B0 = 0 ;
short word_9AC30 = 0 ;
short word_96E3C = 0 ;
short word_96E3E = - 1 ;
short word_96E40 = 0 ;
short nGamma = 0 ;
short word_CB326 ;
short screensize ;
short bSnakeCam = kFalse ;
short bRecord = kFalse ;
short bPlayback = kFalse ;
short bPause = kFalse ;
short bInDemo = kFalse ;
short bSlipMode = kFalse ;
short bDoFlashes = kTrue ;
short bHolly = kFalse ;
short nItemTextIndex ;
short scan_char = 0 ;
int nStartLevel ;
int nTimeLimit ;
2019-10-27 16:36:25 +00:00
int bVanilla = 0 ;
2019-08-26 03:59:14 +00:00
char debugBuffer [ 256 ] ;
short wConsoleNode ; // TODO - move me into network file
void DebugOut ( const char * fmt , . . . )
{
# ifdef _DEBUG
2019-08-27 06:08:18 +00:00
va_list args ;
2019-08-26 03:59:14 +00:00
va_start ( args , fmt ) ;
2019-08-27 06:08:18 +00:00
debugBuffer [ 0 ] = ' \0 ' ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
vsprintf ( debugBuffer , fmt , args ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
initprintf ( " %s " , debugBuffer ) ;
fflush ( stdout ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
va_end ( args ) ;
2019-08-26 03:59:14 +00:00
# endif
}
2019-08-27 06:08:18 +00:00
void ShutDown ( void )
{
StopCD ( ) ;
if ( bSerialPlay )
{
if ( bModemPlay ) {
HangUp ( ) ;
}
UnInitSerial ( ) ;
}
KB_Shutdown ( ) ;
RemoveEngine ( ) ;
UnInitNet ( ) ;
UnInitFX ( ) ;
}
2019-08-26 03:59:14 +00:00
void bail2dos ( const char * fmt , . . . )
{
2019-08-27 06:08:18 +00:00
char buf [ 256 ] ;
2019-08-26 03:59:14 +00:00
# ifdef __WATCOMC__
2019-08-27 06:08:18 +00:00
setvmode ( 3 ) ;
2019-08-26 03:59:14 +00:00
# endif
2019-08-27 06:08:18 +00:00
initprintf ( " bailed to dos \n " ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
va_list args ;
va_start ( args , fmt ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
vsprintf ( buf , fmt , args ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
va_end ( args ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
initprintf ( buf ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( * buf ! = 0 )
{
if ( ! ( buf [ 0 ] = = ' ' & & buf [ 1 ] = = 0 ) )
{
char titlebuf [ 256 ] ;
Bsprintf ( titlebuf , APPNAME " %s " , s_buildRev ) ;
wm_msgbox ( titlebuf , " %s " , buf ) ;
}
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
exit ( 0 ) ;
2019-08-26 03:59:14 +00:00
}
2019-08-31 07:47:15 +00:00
void faketimerhandler ( )
2019-08-26 03:59:14 +00:00
{
2019-09-06 05:18:12 +00:00
if ( ( ( int ) totalclock < ototalclock + 1 ) | | bInMove )
2019-08-31 11:44:02 +00:00
return ;
2019-08-31 19:05:16 +00:00
ototalclock + + ;
2019-08-31 11:44:02 +00:00
2019-08-31 19:05:16 +00:00
if ( ! ( ototalclock & 3 ) & & moveframes < 4 )
2019-08-27 06:08:18 +00:00
moveframes + + ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
PlayerInterruptKeys ( ) ;
2019-08-31 07:47:15 +00:00
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
void timerhandler ( )
{
2019-08-27 06:08:18 +00:00
scan_char + + ;
if ( scan_char = = kTimerTicks )
{
scan_char = 0 ;
lastfps = fps ;
fps = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( nCDTrackLength > 0 ) {
nCDTrackLength - - ;
}
}
2019-08-26 03:59:14 +00:00
}
2019-08-31 15:04:06 +00:00
void HandleAsync ( )
{
handleevents ( ) ;
if ( ! bInMove )
OSD_DispatchQueued ( ) ;
}
2019-08-26 03:59:14 +00:00
int MyGetStringWidth ( const char * str )
{
2019-08-27 06:08:18 +00:00
int nLen = strlen ( str ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nWidth = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
for ( int i = 0 ; i < nLen ; i + + )
{
int nPic = seq_GetSeqPicnum ( kSeqFont2 , 0 , str [ i ] - 32 ) ;
nWidth + = tilesiz [ nPic ] . x + 1 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
return nWidth ;
2019-08-26 03:59:14 +00:00
}
void UpdateScreenSize ( )
{
2019-10-29 14:17:15 +00:00
int xsize = xdim - scale ( screensize * 16 , xdim , 320 ) ;
int ysize = scale ( ydim , xsize , xdim ) ;
int y1 = ( ( ydim > > 1 ) - ( ysize > > 1 ) ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
MySetView (
2019-10-29 14:17:15 +00:00
( xdim > > 1 ) - ( xsize > > 1 ) ,
2019-08-27 06:08:18 +00:00
y1 ,
2019-10-29 14:17:15 +00:00
( xdim > > 1 ) - ( xsize > > 1 ) + xsize - 1 ,
( y1 + ysize - 1 ) ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
RefreshStatus ( ) ;
2019-08-26 03:59:14 +00:00
}
void ResetPassword ( )
{
2019-08-27 06:08:18 +00:00
nCodeMin = nFirstPassword ;
nCodeIndex = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nCodeMax = ( nFirstPassword + nPasswordCount ) - 1 ;
2019-08-26 03:59:14 +00:00
}
void DoPassword ( int nPassword )
{
2019-08-27 06:08:18 +00:00
if ( nNetPlayerCount ) {
return ;
}
const char * str = gString [ nFirstPassInfo + nPassword ] ;
if ( str [ 0 ] ! = ' \0 ' ) {
StatusMessage ( 750 , str ) ;
}
switch ( nPassword )
{
case 0 :
{
if ( ! nNetPlayerCount ) {
bHolly = kTrue ;
}
break ;
}
case 2 : // LOBOCOP
{
lLocalCodes | = 0x20 ;
break ;
}
case 3 : // LOBODEITY
{
lLocalCodes | = 0x40 ;
break ;
}
case 4 :
{
if ( bDoFlashes = = kFalse ) {
bDoFlashes = kTrue ;
}
else {
bDoFlashes = kFalse ;
}
break ;
}
case 5 :
{
lLocalCodes | = 0x80 ;
break ;
}
case 6 :
{
if ( ! nNetPlayerCount )
{
if ( bSlipMode = = kFalse )
{
bSlipMode = kTrue ;
StatusMessage ( 300 , " Slip mode %s " , " ON " ) ;
}
else {
bSlipMode = kFalse ;
StatusMessage ( 300 , " Slip mode %s " , " OFF " ) ;
}
}
break ;
}
case 7 :
{
if ( ! nNetPlayerCount )
{
if ( bSnakeCam = = kFalse ) {
bSnakeCam = kTrue ;
}
else {
bSnakeCam = kFalse ;
}
}
break ;
}
case 8 :
{
GrabMap ( ) ;
bShowTowers = kTrue ;
break ;
}
case 9 :
{
lLocalCodes | = 0x100 ; // LOBOSWAG?
break ;
}
case 10 :
{
if ( bCoordinates = = kFalse ) {
bCoordinates = kTrue ;
}
else {
bCoordinates = kFalse ;
}
break ;
}
default :
return ;
}
2019-08-26 03:59:14 +00:00
}
void mysetbrightness ( char nBrightness )
{
2019-08-27 06:08:18 +00:00
g_visibility = 2048 - ( nBrightness < < 9 ) ;
2019-08-26 03:59:14 +00:00
}
void CheckKeys ( )
{
2019-08-27 06:08:18 +00:00
int eax ;
if ( BUTTON ( gamefunc_Enlarge_Screen ) )
{
2019-10-29 14:17:15 +00:00
if ( screensize = = 0 )
2019-08-27 06:08:18 +00:00
{
if ( ! bFullScreen )
{
bFullScreen = kTrue ;
UnMaskStatus ( ) ;
}
}
else
{
2019-10-29 14:17:15 +00:00
screensize - - ;
if ( screensize < 0 ) {
screensize = 0 ;
2019-08-27 06:08:18 +00:00
}
UpdateScreenSize ( ) ;
}
CONTROL_ClearButton ( gamefunc_Enlarge_Screen ) ;
}
if ( BUTTON ( gamefunc_Mouse_Sensitivity_Up ) )
{
if ( lMouseSens < 64 )
lMouseSens + + ;
CONTROL_ClearButton ( gamefunc_Mouse_Sensitivity_Up ) ;
StatusMessage ( 500 , " MOUSE SENSITIVITY SET TO %d " , lMouseSens ) ;
}
else
{
if ( BUTTON ( gamefunc_Mouse_Sensitivity_Down ) )
{
if ( lMouseSens > = 1 )
lMouseSens - = 1 ;
CONTROL_ClearButton ( gamefunc_Mouse_Sensitivity_Down ) ;
StatusMessage ( 500 , " MOUSE SENSITIVITY SET TO %d " , lMouseSens ) ;
}
}
// F11?
if ( BUTTON ( gamefunc_Gamma_Correction ) )
{
nGamma + + ;
if ( nGamma > 4 )
nGamma = 0 ;
2019-08-31 07:47:15 +00:00
mysetbrightness ( ( uint8_t ) nGamma ) ;
2019-08-27 06:08:18 +00:00
CONTROL_ClearButton ( gamefunc_Gamma_Correction ) ;
}
if ( BUTTON ( gamefunc_Shrink_Screen ) )
{
if ( bFullScreen )
{
bFullScreen = kFalse ;
}
else
{
2019-10-29 14:17:15 +00:00
if ( ( screensize + 1 ) < 15 )
screensize + + ;
2019-08-27 06:08:18 +00:00
}
UpdateScreenSize ( ) ;
CONTROL_ClearButton ( gamefunc_Shrink_Screen ) ;
}
// print version string?
if ( KB_KeyDown [ sc_V ] & & KB_KeyDown [ sc_LeftAlt ] )
{
KB_KeyDown [ sc_V ] = 0 ;
StatusMessage ( 300 , versionstr ) ;
return ;
}
// go to 3rd person view?
if ( KB_KeyDown [ sc_C ] & & KB_KeyDown [ sc_LeftAlt ] )
{
if ( ! nFreeze )
{
if ( bCamera ) {
bCamera = kFalse ;
}
else {
bCamera = kTrue ;
}
if ( bCamera )
GrabPalette ( ) ;
}
KB_KeyDown [ sc_C ] = 0 ;
return ;
}
if ( KB_KeyDown [ sc_Pause ] )
{
if ( ! nNetPlayerCount )
{
if ( bPause )
{
bPause = kFalse ;
KB_KeyDown [ sc_Pause ] = 0 ;
}
else
{
bPause = kTrue ;
NoClip ( ) ;
int nLen = MyGetStringWidth ( " PAUSED " ) ;
myprintext ( ( 320 - nLen ) / 2 , 100 , " PAUSED " , 0 ) ;
Clip ( ) ;
videoNextPage ( ) ;
}
}
return ;
}
// Handle cheat codes
if ( ! bInDemo & & KB_KeyWaiting ( ) )
{
char ch = KB_GetCh ( ) ;
if ( bHolly )
{
if ( ch )
{
int nStringLen = strlen ( sHollyStr ) ;
if ( ch = = asc_Enter )
{
char * pToken = strtok ( sHollyStr , " " ) ;
2019-10-28 19:14:54 +00:00
if ( nStringLen = = 0 ) // bjd - added this check. watcom allows passing NULL to strcmp so the below checks will all fail OK on DOS but will cause a crash on Windows
2019-08-27 06:08:18 +00:00
{
2019-10-28 19:14:54 +00:00
bHolly = kFalse ;
StatusMessage ( 1 , " " ) ;
}
else if ( ! strcmp ( pToken , " GOTO " ) )
{
// move player to X, Y coordinates
2019-08-27 06:08:18 +00:00
int nSprite = PlayerList [ 0 ] . nSprite ;
pToken = strtok ( NULL , " , " ) ;
sprite [ nSprite ] . x = atoi ( pToken ) ;
pToken = strtok ( NULL , " , " ) ;
sprite [ nSprite ] . y = atoi ( pToken ) ;
setsprite ( nSprite , & sprite [ nSprite ] . pos ) ;
sprite [ nSprite ] . z = sector [ sprite [ nSprite ] . sectnum ] . floorz ;
}
else if ( ! strcmp ( pToken , " LEVEL " ) )
{
pToken = strtok ( NULL , " " ) ;
levelnew = atoi ( pToken ) ;
}
else if ( ! strcmp ( pToken , " DOORS " ) )
{
for ( int i = 0 ; i < kMaxChannels ; i + + )
{
// CHECKME - does this toggle?
if ( sRunChannels [ i ] . c = = 0 ) {
runlist_ChangeChannel ( i , 1 ) ;
}
else {
runlist_ChangeChannel ( i , 0 ) ;
}
}
}
else if ( ! strcmp ( pToken , " EXIT " ) )
{
FinishLevel ( ) ;
}
else if ( ! strcmp ( pToken , " CREATURE " ) )
{
// i = nNetPlayerCount;
if ( ! nNetPlayerCount )
{
pToken = strtok ( NULL , " " ) ;
switch ( atoi ( pToken ) )
{
// TODO - enums?
case 0 :
BuildAnubis ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita , kFalse ) ;
break ;
case 1 :
BuildSpider ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita ) ;
break ;
case 2 :
BuildMummy ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita ) ;
break ;
case 3 :
BuildFish ( - 1 , initx , inity , initz + eyelevel [ nLocalPlayer ] , initsect , inita ) ;
break ;
case 4 :
BuildLion ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita ) ;
break ;
case 5 :
BuildLava ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita , nNetPlayerCount ) ;
break ;
case 6 :
BuildRex ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita , nNetPlayerCount ) ;
break ;
case 7 :
BuildSet ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita , nNetPlayerCount ) ;
break ;
case 8 :
BuildQueen ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita , nNetPlayerCount ) ;
break ;
case 9 :
BuildRoach ( 0 , - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita ) ;
break ;
case 10 :
BuildRoach ( 1 , - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita ) ;
break ;
case 11 :
BuildWasp ( - 1 , initx , inity , sector [ initsect ] . floorz - 25600 , initsect , inita ) ;
break ;
case 12 :
BuildScorp ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita , nNetPlayerCount ) ;
break ;
case 13 :
BuildRat ( - 1 , initx , inity , sector [ initsect ] . floorz , initsect , inita ) ;
break ;
default :
break ;
}
}
}
else
{
if ( nStringLen = = 0 )
{
bHolly = kFalse ;
StatusMessage ( 1 , " " ) ;
}
else
{
for ( int i = 0 ; i < nPasswordCount ; + + i )
{
if ( ! strcmp ( sHollyStr , gString [ i + nFirstPassword ] ) )
{
DoPassword ( i ) ;
break ;
}
}
}
}
sHollyStr [ 0 ] = ' \0 ' ;
}
else if ( ch = = asc_BackSpace )
{
if ( nStringLen ! = 0 ) {
sHollyStr [ nStringLen - 1 ] = ' \0 ' ;
}
}
else if ( nStringLen < ( sizeof ( sHollyStr ) - 1 ) ) // do we have room to add a char and null terminator?
{
sHollyStr [ nStringLen ] = toupper ( ch ) ;
sHollyStr [ nStringLen + 1 ] = ' \0 ' ;
}
}
else
{
KB_GetCh ( ) ;
}
}
if ( isalpha ( ch ) )
{
ch = toupper ( ch ) ;
int ecx = nCodeMin ;
int ebx = nCodeMin ;
int edx = nCodeMin - 1 ;
while ( ebx < = nCodeMax )
{
if ( ch = = gString [ ecx ] [ nCodeIndex ] )
{
nCodeMin = ebx ;
nCodeIndex + + ;
if ( gString [ ecx ] [ nCodeIndex ] = = 0 )
{
ebx - = nFirstPassword ;
DoPassword ( ebx ) ;
ResetPassword ( ) ;
}
break ;
}
else if ( gString [ ecx ] [ nCodeIndex ] < ch )
{
nCodeMin = ebx + 1 ;
}
else if ( gString [ ecx ] [ nCodeIndex ] > ch )
{
nCodeMax = edx ;
}
ecx + + ;
edx + + ;
ebx + + ;
}
if ( nCodeMin > nCodeMax ) {
ResetPassword ( ) ;
}
}
}
2019-08-26 03:59:14 +00:00
}
void DoCredits ( )
{
2019-08-27 06:08:18 +00:00
NoClip ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
playCDtrack ( 19 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int var_20 = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
FadeOut ( 0 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nCreditsIndex = FindGString ( " CREDITS " ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
while ( strcmp ( gString [ nCreditsIndex ] , " END " ) ! = 0 )
{
EraseScreen ( overscanindex ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nStart = nCreditsIndex ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
// skip blanks
while ( strlen ( gString [ nCreditsIndex ] ) ! = 0 ) {
nCreditsIndex + + ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
// vars
int eax = ( 10 * ( nCreditsIndex - nStart - 1 ) ) / 2 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( eax < 0 ) {
eax + + ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
eax > > = 1 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int y = 100 - eax ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int edi = nStart ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
for ( int i = nStart ; i < nCreditsIndex ; i + + )
{
// var 24 ==
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nWidth = MyGetStringWidth ( gString [ edi ] ) ;
myprintext ( ( 320 - nWidth ) / 2 , y , gString [ edi ] , 0 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
edi + + ;
y + = 10 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
videoNextPage ( ) ;
FadeIn ( ) ;
2019-08-26 03:59:14 +00:00
2019-09-06 05:18:12 +00:00
while ( ( int ) totalclock + 600 > ( int ) totalclock )
2019-08-27 06:08:18 +00:00
{
if ( KB_KeyDown [ sc_F12 ] )
{
var_20 + + ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
KB_KeyDown [ sc_F12 ] = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( var_20 > 5 ) {
return ;
}
}
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
FadeOut ( 0 ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
while ( CDplaying ( ) )
{
if ( KB_KeyWaiting ( ) ) {
KB_GetCh ( ) ;
}
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
Clip ( ) ;
2019-08-26 03:59:14 +00:00
}
void FinishLevel ( )
{
2019-08-27 06:08:18 +00:00
if ( levelnum > nBestLevel ) {
nBestLevel = levelnum - 1 ;
}
levelnew = levelnum + 1 ;
StopAllSounds ( ) ;
bCamera = kFalse ;
bMapMode = kFalse ;
if ( levelnum ! = kMap20 )
{
EraseScreen ( 4 ) ;
SetLocalChan ( 1 ) ;
PlayLocalSound ( StaticSound [ 59 ] , 0 ) ;
videoNextPage ( ) ;
WaitTicks ( 12 ) ;
WaitVBL ( ) ;
RefreshBackground ( ) ;
RefreshStatus ( ) ;
DrawView ( ) ;
2019-08-26 03:59:14 +00:00
videoNextPage ( ) ;
2019-08-27 06:08:18 +00:00
}
FadeOut ( 1 ) ;
EraseScreen ( overscanindex ) ;
if ( levelnum = = 0 )
{
nPlayerLives [ 0 ] = 0 ;
levelnew = 100 ;
}
else
{
DoAfterCinemaScene ( levelnum ) ;
if ( levelnum = = kMap20 )
{
DoCredits ( ) ;
nPlayerLives [ 0 ] = 0 ;
}
}
2019-08-26 03:59:14 +00:00
}
void WritePlaybackInputs ( )
{
2019-08-27 06:08:18 +00:00
fwrite ( & moveframes , sizeof ( moveframes ) , 1 , vcrfp ) ;
fwrite ( & sPlayerInput [ nLocalPlayer ] , sizeof ( PlayerInput ) , 1 , vcrfp ) ;
2019-08-26 03:59:14 +00:00
}
2019-08-31 07:47:15 +00:00
uint8_t ReadPlaybackInputs ( )
2019-08-26 03:59:14 +00:00
{
2019-08-27 06:08:18 +00:00
assert ( sizeof ( PlayerInput ) = = 32 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( fread ( & moveframes , 1 , sizeof ( moveframes ) , vcrfp ) )
{
2019-08-26 03:59:14 +00:00
#if 0
2019-08-27 06:08:18 +00:00
fread ( & sPlayerInput [ nLocalPlayer ] , 1 , sizeof ( PlayerInput ) , vcrfp ) ;
2019-08-26 03:59:14 +00:00
# else
2019-08-27 06:08:18 +00:00
/*
struct PlayerInput
{
int xVel ;
int yVel ;
short nAngle ;
short buttons ;
short nTarget ;
char horizon ;
2019-08-31 07:47:15 +00:00
int8_t nItem ;
2019-08-27 06:08:18 +00:00
int h ;
char i ;
char field_15 [ 11 ] ;
} ;
*/
fread ( & sPlayerInput [ nLocalPlayer ] . xVel , 1 , sizeof ( sPlayerInput [ nLocalPlayer ] . xVel ) , vcrfp ) ;
fread ( & sPlayerInput [ nLocalPlayer ] . yVel , 1 , sizeof ( sPlayerInput [ nLocalPlayer ] . yVel ) , vcrfp ) ;
fread ( & sPlayerInput [ nLocalPlayer ] . nAngle , 1 , sizeof ( sPlayerInput [ nLocalPlayer ] . nAngle ) , vcrfp ) ;
fread ( & sPlayerInput [ nLocalPlayer ] . buttons , 1 , sizeof ( sPlayerInput [ nLocalPlayer ] . buttons ) , vcrfp ) ;
fread ( & sPlayerInput [ nLocalPlayer ] . nTarget , 1 , sizeof ( sPlayerInput [ nLocalPlayer ] . nTarget ) , vcrfp ) ;
fread ( & sPlayerInput [ nLocalPlayer ] . horizon , 1 , sizeof ( sPlayerInput [ nLocalPlayer ] . horizon ) , vcrfp ) ;
fread ( & sPlayerInput [ nLocalPlayer ] . nItem , 1 , sizeof ( sPlayerInput [ nLocalPlayer ] . nItem ) , vcrfp ) ;
fread ( & sPlayerInput [ nLocalPlayer ] . h , 1 , sizeof ( sPlayerInput [ nLocalPlayer ] . h ) , vcrfp ) ;
fread ( & sPlayerInput [ nLocalPlayer ] . i , 1 , sizeof ( sPlayerInput [ nLocalPlayer ] . i ) , vcrfp ) ;
// skip pad
fseek ( vcrfp , 11 , SEEK_CUR ) ;
2019-08-26 03:59:14 +00:00
# endif
2019-08-27 06:08:18 +00:00
besttarget = sPlayerInput [ nLocalPlayer ] . nTarget ;
Ra [ nLocalPlayer ] . nTarget = besttarget ;
return kTrue ;
}
else
{
fclose ( vcrfp ) ;
vcrfp = NULL ;
bPlayback = kFalse ;
return kFalse ;
}
2019-08-26 03:59:14 +00:00
}
void SetHiRes ( )
{
2019-08-27 06:08:18 +00:00
//nScreenWidth = 640;
//nScreenHeight = 400;
bHiRes = kTrue ;
2019-08-26 03:59:14 +00:00
}
void DoClockBeep ( )
{
2019-08-27 06:08:18 +00:00
for ( int i = headspritestat [ 407 ] ; i ! = - 1 ; i = nextspritestat [ i ] ) {
2019-09-21 15:47:55 +00:00
PlayFX2 ( StaticSound [ kSound74 ] , i ) ;
2019-08-27 06:08:18 +00:00
}
2019-08-26 03:59:14 +00:00
}
void DoRedAlert ( int nVal )
{
2019-08-27 06:08:18 +00:00
if ( nVal )
{
nAlarmTicks = 69 ;
nRedTicks = 30 ;
}
for ( int i = headspritestat [ 405 ] ; i ! = - 1 ; i = nextspritestat [ i ] )
{
if ( nVal )
{
2019-09-21 15:47:55 +00:00
PlayFXAtXYZ ( StaticSound [ kSoundAlarm ] , sprite [ i ] . x , sprite [ i ] . y , sprite [ i ] . z , sprite [ i ] . sectnum ) ;
2019-08-27 06:08:18 +00:00
AddFlash ( sprite [ i ] . sectnum , sprite [ i ] . x , sprite [ i ] . y , sprite [ i ] . z , 192 ) ;
}
}
2019-08-26 03:59:14 +00:00
}
void LockEnergyTiles ( )
{
2019-08-27 06:08:18 +00:00
// old loadtilelockmode = 1;
tileLoad ( kTile3603 ) ;
2019-08-26 03:59:14 +00:00
tileLoad ( kEnergy1 ) ;
tileLoad ( kEnergy2 ) ;
2019-08-27 06:08:18 +00:00
// old loadtilelockmode = 0;
2019-08-26 03:59:14 +00:00
}
void DrawClock ( )
{
2019-08-27 06:08:18 +00:00
int ebp = 49 ;
2019-08-26 03:59:14 +00:00
tileLoad ( kTile3603 ) ;
2019-08-27 06:08:18 +00:00
nRedTicks = 0 ;
memset ( ( void * ) waloff [ kTile3603 ] , - 1 , 4096 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( lCountDown / 30 ! = nClockVal )
{
nClockVal = lCountDown / 30 ;
DoClockBeep ( ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nVal = nClockVal ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
while ( nVal )
{
int v2 = nVal & 0xF ;
int yPos = 32 - tilesiz [ v2 + kTile3606 ] . y / 2 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
CopyTileToBitmap ( v2 + kTile3606 , kTile3603 , ebp - tilesiz [ v2 + kTile3606 ] . x / 2 , yPos ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
ebp - = 15 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nVal / = 16 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
DoEnergyTile ( ) ;
2019-08-26 03:59:14 +00:00
}
2019-08-31 09:08:38 +00:00
void M32RunScript ( const char * s ) { UNREFERENCED_PARAMETER ( s ) ; }
void app_crashhandler ( void )
{
ShutDown ( ) ;
}
void G_Polymer_UnInit ( void ) { }
int app_main ( int argc , char const * const * argv )
2019-08-26 03:59:14 +00:00
{
2019-08-31 09:08:38 +00:00
char tempbuf [ 256 ] ;
# ifdef _WIN32
# ifndef DEBUGGINGAIDS
if ( ! G_CheckCmdSwitch ( argc , argv , " -noinstancechecking " ) & & win_checkinstance ( ) )
{
# ifdef EDUKE32_STANDALONE
if ( ! wm_ynbox ( APPNAME , " It looks like " APPNAME " is already running. \n \n "
# else
if ( ! wm_ynbox ( APPNAME , " It looks like the game is already running. \n \n "
# endif
" Are you sure you want to start another copy? " ) )
return 3 ;
}
# endif
backgroundidle = 0 ;
# ifndef USE_PHYSFS
# ifdef DEBUGGINGAIDS
extern int32_t ( * check_filename_casing_fn ) ( void ) ;
check_filename_casing_fn = check_filename_casing ;
# endif
# endif
# endif
G_ExtPreInit ( argc , argv ) ;
OSD_SetLogFile ( APPBASENAME " .log " ) ;
OSD_SetFunctions ( NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
GAME_clearbackground ,
BGetTime ,
GAME_onshowosd ) ;
wm_setapptitle ( APPNAME ) ;
initprintf ( " Exhumed %s \n " , s_buildRev ) ;
PrintBuildInfo ( ) ;
2019-08-27 06:08:18 +00:00
int i ;
2019-08-26 03:59:14 +00:00
2019-08-31 09:08:38 +00:00
2019-08-31 14:07:47 +00:00
//int esi = 1;
//int edi = esi;
int doTitle = kTrue ;
int stopTitle = kFalse ;
int tclocks , tclocks2 ;
levelnew = 1 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
// REVERT - change back to kTrue
2019-08-26 03:59:14 +00:00
// short bDoTitle = kFalse;
2019-08-27 06:08:18 +00:00
wConsoleNode = 0 ;
2019-09-19 02:12:24 +00:00
int nMenu = 0 ; // TEMP
2019-08-27 06:08:18 +00:00
// Check for any command line arguments
for ( i = 1 ; i < argc ; i + + )
{
2019-08-31 09:08:38 +00:00
const char * pChar = argv [ i ] ;
2019-08-27 06:08:18 +00:00
if ( * pChar = = ' / ' )
{
pChar + + ;
2019-08-31 09:08:38 +00:00
//strlwr(pChar);
2019-08-27 06:08:18 +00:00
2019-08-31 09:08:38 +00:00
if ( Bstrcasecmp ( pChar , " nocreatures " ) = = 0 ) {
2019-08-27 06:08:18 +00:00
bNoCreatures = kTrue ;
}
2019-08-31 09:08:38 +00:00
else if ( Bstrcasecmp ( pChar , " nosound " ) = = 0 ) {
2019-08-27 06:08:18 +00:00
bNoSound = kTrue ;
}
2019-08-31 09:08:38 +00:00
else if ( Bstrcasecmp ( pChar , " record " ) = = 0 )
2019-08-27 06:08:18 +00:00
{
if ( ! bPlayback )
{
vcrfp = fopen ( " data.vcr " , " wb+ " ) ;
if ( vcrfp ! = NULL ) {
bRecord = kTrue ;
}
else {
DebugOut ( " Can't open data file for recording \n " ) ;
}
}
}
2019-08-31 09:08:38 +00:00
else if ( Bstrcasecmp ( pChar , " playback " ) = = 0 )
2019-08-27 06:08:18 +00:00
{
if ( ! bRecord )
{
vcrfp = fopen ( " data.vcr " , " rb " ) ;
if ( vcrfp ! = NULL ) {
bPlayback = kTrue ;
2019-08-31 14:07:47 +00:00
doTitle = kFalse ;
2019-08-27 06:08:18 +00:00
}
else {
DebugOut ( " Can't open data file 'data.vcr' for reading \n " ) ;
}
}
}
2019-08-31 09:08:38 +00:00
else if ( Bstrncasecmp ( pChar , " null " , 4 ) = = 0 )
2019-08-27 06:08:18 +00:00
{
pChar + = 4 ;
bSerialPlay = kTrue ;
nNetPlayerCount = 1 ;
nTotalPlayers = 2 ;
2019-08-31 14:07:47 +00:00
doTitle = kFalse ;
2019-08-27 06:08:18 +00:00
char ch = * pChar ;
// bjd - unused/unfished code in original .exe?
switch ( ch - 1 )
{
default :
break ;
case 0 :
case 1 :
case 2 :
case 3 :
break ;
}
if ( forcelevel < 0 )
{
forcelevel = levelnew ;
}
}
2019-08-31 09:08:38 +00:00
else if ( Bstrcasecmp ( pChar , " modem " ) = = 0 )
2019-08-27 06:08:18 +00:00
{
bModemPlay = kTrue ;
bSerialPlay = kTrue ;
nNetPlayerCount = 1 ;
nTotalPlayers = 2 ;
2019-08-31 14:07:47 +00:00
doTitle = kFalse ;
2019-08-27 06:08:18 +00:00
if ( forcelevel < 0 ) {
forcelevel = levelnew ;
}
}
2019-08-31 09:08:38 +00:00
else if ( Bstrcasecmp ( pChar , " network " ) = = 0 )
2019-08-27 06:08:18 +00:00
{
nNetPlayerCount = - 1 ;
forcelevel = levelnew ;
bModemPlay = kFalse ;
bSerialPlay = kFalse ;
2019-08-31 14:07:47 +00:00
doTitle = kFalse ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 09:08:38 +00:00
else if ( Bstrcasecmp ( pChar , " setup " ) = = 0 ) {
g_commandSetup = 1 ;
}
else if ( Bstrcasecmp ( pChar , " nosetup " ) = = 0 ) {
g_noSetup = 1 ;
g_commandSetup = 0 ;
}
2019-08-27 06:08:18 +00:00
else
{
char c = tolower ( * pChar ) ;
switch ( c )
{
case ' h ' :
SetHiRes ( ) ;
break ;
case ' s ' :
socket = atoi ( pChar + 1 ) ;
break ;
case ' t ' :
nNetTime = atoi ( pChar + 1 ) ;
if ( nNetTime < 0 ) {
nNetTime = 0 ;
}
else {
nNetTime = nNetTime * 1800 ;
}
break ;
case ' c ' :
{
// CHANGEME? - make this a strcmp. this is how the original does it though...
if ( pChar [ 1 ] = = ' d ' & & pChar [ 2 ] = = ' o ' & & pChar [ 3 ] = = ' f ' & & pChar [ 4 ] = = ' f ' ) {
bNoCDCheck = kTrue ;
}
}
default :
{
if ( isdigit ( c ) )
{
levelnew = atoi ( pChar ) ;
forcelevel = levelnew ;
2019-08-31 14:07:47 +00:00
doTitle = kFalse ;
2019-08-27 06:08:18 +00:00
initprintf ( " Jumping to level %d... \n " , levelnew ) ;
}
break ;
}
}
}
}
}
if ( nNetPlayerCount & & forcelevel = = - 1 ) {
forcelevel = 1 ;
}
2019-08-31 09:08:38 +00:00
// This needs to happen afterwards, as G_CheckCommandLine() is where we set
// up the command-line-provided search paths (duh).
// TODO:
//G_ExtInit();
# if defined(RENDERTYPEWIN) && defined(USE_OPENGL)
if ( forcegl ) initprintf ( " GL driver blacklist disabled. \n " ) ;
# endif
// used with binds for fast function lookup
hash_init ( & h_gamefuncs ) ;
for ( bssize_t i = kMaxGameFunctions - 1 ; i > = 0 ; i - - )
{
if ( gamefunctions [ i ] [ 0 ] = = ' \0 ' )
continue ;
hash_add ( & h_gamefuncs , gamefunctions [ i ] , i , 0 ) ;
}
# ifdef STARTUP_SETUP_WINDOW
int const readSetup =
# endif
CONFIG_ReadSetup ( ) ;
if ( enginePreInit ( ) )
{
wm_msgbox ( " Build Engine Initialization Error " ,
" There was a problem initializing the Build engine: %s " , engineerrstr ) ;
ERRprintf ( " app_main: There was a problem initializing the Build engine: %s \n " , engineerrstr ) ;
Bexit ( 2 ) ;
}
if ( Bstrcmp ( setupfilename , kSetupFilename ) )
initprintf ( " Using config file \" %s \" . \n " , setupfilename ) ;
//G_ScanGroups();
# ifdef STARTUP_SETUP_WINDOW
if ( readSetup < 0 | | ( ! g_noSetup & & gSetup . forcesetup ) | | g_commandSetup )
{
if ( quitevent | | ! startwin_run ( ) )
{
engineUnInit ( ) ;
Bexit ( 0 ) ;
}
}
# endif
2019-08-27 06:08:18 +00:00
// Decrypt strings code would normally be here
2019-08-26 03:59:14 +00:00
#if 0
2019-08-27 06:08:18 +00:00
for ( int i = 0 ; ; i + + )
{
int j = i - 1 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
while ( j > = 0 )
{
if ( gString_Enc [ i ] = = gString_Enc [ j ] ) {
break ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
j - - ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( j < 0 )
{
int k = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
while ( 1 )
{
2019-08-31 07:47:15 +00:00
uint8_t v27 = gString_Enc [ i + k ] ;
2019-08-27 06:08:18 +00:00
if ( v27 )
{
gString_Enc [ i + k ] = v27 ^ 0xFF ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
k + + ;
}
else {
break ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
}
2019-08-26 03:59:14 +00:00
// strupr(gString[j]);
2019-08-27 06:08:18 +00:00
int blah = 123 ;
2019-08-26 03:59:14 +00:00
// if (!strcmp(*(char **)((char *)gString + v29), "EOF", v27, v30))
// break;
2019-08-27 06:08:18 +00:00
}
}
2019-08-26 03:59:14 +00:00
# endif
2019-08-27 06:08:18 +00:00
// loc_115F5:
nItemTextIndex = FindGString ( " ITEMS " ) ;
nFirstPassword = FindGString ( " PASSWORDS " ) ;
nFirstPassInfo = FindGString ( " PASSINFO " ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
// count the number of passwords available
2019-08-31 14:07:47 +00:00
for ( nPasswordCount = 0 ; strlen ( gString [ nFirstPassword + nPasswordCount ] ) ! = 0 ; nPasswordCount + + )
2019-08-27 06:08:18 +00:00
{
}
ResetPassword ( ) ;
nCDTracks = initcdaudio ( ) ;
2019-10-12 21:09:55 +00:00
// GetCurPal(NULL);
2019-08-27 06:08:18 +00:00
2019-08-31 09:08:38 +00:00
CONFIG_WriteSetup ( 1 ) ;
CONFIG_ReadSetup ( ) ;
initprintf ( " Initializing OSD... \n " ) ;
Bsprintf ( tempbuf , " Exhumed %s " , s_buildRev ) ;
OSD_SetVersion ( tempbuf , 10 , 0 ) ;
2019-08-31 10:58:30 +00:00
OSD_SetParameters ( 0 , 0 , 0 , 0 , 0 , 0 , OSD_ERROR , OSDTEXT_RED , gamefunctions [ gamefunc_Show_Console ] [ 0 ] = = ' \0 ' ? OSD_PROTECTED : 0 ) ;
2019-08-31 09:08:38 +00:00
registerosdcommands ( ) ;
2019-08-27 06:08:18 +00:00
if ( nNetPlayerCount = = - 1 )
{
nNetPlayerCount = nCfgNetPlayers - 1 ;
nTotalPlayers + = nNetPlayerCount ;
}
// loc_116A5:
if ( nNetPlayerCount )
{
InitInput ( ) ;
forcelevel = nStartLevel ;
nNetTime = 1800 * nTimeLimit ;
if ( nNetTime = = 0 ) {
nNetTime = - 1 ;
}
int nWaitTicks = 0 ;
if ( ! bSerialPlay )
{
if ( InitNet ( socket , nTotalPlayers ) )
{
DebugOut ( " Found network players! \n " ) ;
nWaitTicks = 30 ;
}
else
{
AbortNetworkPlay ( ) ;
DebugOut ( " Network play aborted \n " ) ;
initprintf ( " Network play aborted \n " ) ;
nWaitTicks = 60 ;
}
WaitTicks ( nWaitTicks ) ;
}
}
// temp - moving InstallEngine(); before FadeOut as we use nextpage() in FadeOut
InstallEngine ( ) ;
2019-08-31 14:07:47 +00:00
if ( enginePostInit ( ) )
ShutDown ( ) ;
2019-08-27 06:08:18 +00:00
// loc_11745:
FadeOut ( 0 ) ;
2019-08-26 03:59:14 +00:00
// InstallEngine();
2019-08-27 06:08:18 +00:00
KB_Startup ( ) ;
SetupInput ( ) ;
InitView ( ) ;
myloadconfig ( ) ;
2019-09-19 13:38:28 +00:00
InitFX ( ) ;
LoadFX ( ) ;
2019-08-27 06:08:18 +00:00
setCDaudiovolume ( gMusicVolume ) ;
seq_LoadSequences ( ) ;
InitStatus ( ) ;
InitTimer ( ) ;
for ( i = 0 ; i < kMaxPlayers ; i + + ) {
nPlayerLives [ i ] = kDefaultLives ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nBestLevel = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
UpdateScreenSize ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
EraseScreen ( overscanindex ) ;
ResetEngine ( ) ;
EraseScreen ( overscanindex ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
ResetView ( ) ;
GrabPalette ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( bSerialPlay & & ! InitSerial ( ) ) {
bail2dos ( " Unable to connect " ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
if ( doTitle )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
while ( ! stopTitle )
2019-08-27 06:08:18 +00:00
{
DoTitle ( ) ;
2019-08-31 14:07:47 +00:00
stopTitle = kTrue ;
2019-08-27 06:08:18 +00:00
}
}
// loc_11811:
if ( forcelevel > - 1 )
{
levelnew = forcelevel ;
2019-08-31 14:07:47 +00:00
goto STARTGAME1 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
// no forcelevel specified...
if ( ! bPlayback )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
goto STARTGAME1 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
MENU :
SavePosition = - 1 ;
nMenu = menu_Menu ( 0 ) ;
switch ( nMenu )
{
case - 1 :
goto MENU ;
case 0 :
goto EXITGAME ;
case 3 :
forcelevel = 0 ;
goto STARTGAME2 ;
case 9 :
vcrfp = fopen ( " demo.vcr " , " rb " ) ;
if ( vcrfp = = NULL ) {
goto MENU ;
}
InitRandom ( ) ;
bInDemo = kTrue ;
bPlayback = kTrue ;
KB_FlushKeyboardQueue ( ) ;
KB_ClearKeysDown ( ) ;
break ;
}
STARTGAME1 :
2019-08-27 06:08:18 +00:00
levelnew = 1 ;
levelnum = 1 ;
if ( ! nNetPlayerCount ) {
FadeOut ( 0 ) ;
}
2019-08-31 14:07:47 +00:00
STARTGAME2 :
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
bCamera = kFalse ;
ClearCinemaSeen ( ) ;
PlayerCount = 0 ;
lastlevel = - 1 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
for ( i = 0 ; i < nTotalPlayers ; i + + )
{
int nPlayer = GrabPlayer ( ) ;
if ( nPlayer < 0 ) {
bail2dos ( " Can't create local player \n " ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
InitPlayerInventory ( nPlayer ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( i = = wConsoleNode ) {
PlayerList [ nPlayer ] . someNetVal = - 3 ;
}
else {
PlayerList [ nPlayer ] . someNetVal = - 4 ;
}
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nNetMoves = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( bPlayback )
{
menu_GameLoad2 ( vcrfp ) ;
levelnew = GameStats . nMap ;
levelnum = GameStats . nMap ;
forcelevel = GameStats . nMap ;
}
2019-08-31 14:07:47 +00:00
if ( forcelevel > - 1 )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
// YELLOW SECTION
levelnew = forcelevel ;
2019-08-27 06:08:18 +00:00
UpdateInputs ( ) ;
2019-08-31 14:07:47 +00:00
forcelevel = - 1 ;
2019-08-27 06:08:18 +00:00
if ( bRecord & & ! bInDemo ) {
menu_GameSave2 ( vcrfp ) ;
}
2019-08-31 14:07:47 +00:00
goto LOOP3 ;
2019-08-27 06:08:18 +00:00
}
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
// PINK SECTION
2019-08-27 06:08:18 +00:00
UpdateInputs ( ) ;
2019-08-31 14:07:47 +00:00
nNetMoves = 1 ;
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
if ( nMenu = = 2 )
{
levelnew = 1 ;
levelnum = 1 ;
levelnew = menu_GameLoad ( SavePosition ) ;
lastlevel = - 1 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( bRecord & & ! bInDemo ) {
menu_GameSave2 ( vcrfp ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
nBestLevel = levelnew - 1 ;
LOOP1 :
if ( nPlayerLives [ nLocalPlayer ] < = 0 ) {
goto MENU ;
}
if ( levelnew > 99 ) {
goto EXITGAME ;
}
if ( ! bInDemo & & levelnew > nBestLevel & & levelnew ! = 0 & & levelnew < = kMap20 & & SavePosition > - 1 ) {
menu_GameSave ( SavePosition ) ;
}
LOOP2 :
if ( ! nNetPlayerCount & & ! bPlayback & & levelnew > 0 & & levelnew < = kMap20 ) {
levelnew = showmap ( levelnum , levelnew , nBestLevel ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
if ( levelnew > nBestLevel ) {
nBestLevel = levelnew ;
}
LOOP3 :
2019-08-27 06:08:18 +00:00
while ( levelnew ! = - 1 )
{
// BLUE
if ( CDplaying ( ) ) {
fadecdaudio ( ) ;
}
CheckCD ( ) ;
2019-08-31 15:04:06 +00:00
#if 0
2019-08-27 06:08:18 +00:00
if ( ! bNoCDCheck )
{
while ( ! checkcdrom ( ) )
{
EraseScreen ( overscanindex ) ;
Query ( 2 , 0 , " Insert CD into drive " , " (ESC to abort) " ) ;
KB_ClearKeysDown ( ) ;
if ( KB_GetCh ( ) = = asc_Escape ) {
bail2dos ( " Aborted \n " ) ;
}
}
}
2019-08-31 15:04:06 +00:00
# endif
2019-08-27 06:08:18 +00:00
if ( levelnew = = kMap20 )
{
lCountDown = 81000 ;
nAlarmTicks = 30 ;
nRedTicks = 0 ;
nClockVal = 0 ;
nEnergyTowers = 0 ;
}
if ( ! LoadLevel ( levelnew ) ) {
// TODO "Can't load level %d...\n", nMap;
2019-08-31 14:07:47 +00:00
goto EXITGAME ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
levelnew = - 1 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
if ( nNetPlayerCount = = 0 & & lastlevel = = levelnum )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
RestoreSavePoint ( nLocalPlayer , & initx , & inity , & initz , & initsect , & inita ) ;
}
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
lastlevel = levelnum ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
for ( i = 0 ; i < nTotalPlayers ; i + + )
{
SetSavePoint ( i , initx , inity , initz , initsect , inita ) ;
RestartPlayer ( i ) ;
InitPlayerKeys ( i ) ;
}
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
UpdateScreenSize ( ) ;
fps = 0 ;
lastfps = 0 ;
InitStatus ( ) ;
ResetView ( ) ;
ResetEngine ( ) ;
totalmoves = 0 ;
GrabPalette ( ) ;
ResetMoveFifo ( ) ;
moveframes = 0 ;
bInMove = kFalse ;
2019-09-06 05:18:12 +00:00
tclocks = ( int ) totalclock ;
2019-08-31 14:07:47 +00:00
nPlayerDAng = 0 ;
lPlayerXVel = 0 ;
lPlayerYVel = 0 ;
movefifopos = movefifoend ;
nCDTrackLength = 0 ;
RefreshStatus ( ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( bSerialPlay ) {
ClearSerialInbuf ( ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
mysetbrightness ( ( uint8_t ) nGamma ) ;
//int edi = totalclock;
2019-09-06 05:18:12 +00:00
tclocks2 = ( int ) totalclock ;
2019-08-31 15:04:06 +00:00
CONTROL_BindsEnabled = 1 ;
2019-08-31 14:07:47 +00:00
// Game Loop
while ( 1 )
{
if ( levelnew > = 0 )
2019-08-31 15:04:06 +00:00
{
CONTROL_BindsEnabled = 0 ;
2019-08-31 14:07:47 +00:00
goto LOOP1 ;
2019-08-31 15:04:06 +00:00
}
HandleAsync ( ) ;
OSD_DispatchQueued ( ) ;
2019-08-31 14:07:47 +00:00
// Section B
if ( ! nCDTrackLength & & ! nFreeze & & ! nNetPlayerCount )
{
int nTrack = levelnum ;
if ( nTrack ! = 0 ) {
nTrack - - ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
nCDTrackLength = playCDtrack ( ( nTrack % 8 ) + 11 ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
if ( ! nCDTrackLength ) {
nCDTrackLength = - 1 ;
}
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
// End Section B
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
SetView1 ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
if ( levelnum = = kMap20 )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
LockEnergyTiles ( ) ;
DoEnergyTile ( ) ;
DrawClock ( ) ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
DrawView ( ) ;
UpdateMap ( ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( bMapMode )
{
2019-08-31 16:05:11 +00:00
#if 0
2019-08-31 14:07:47 +00:00
if ( bHiRes & & nViewBottom > nMaskY )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
videoSetViewableArea ( nViewLeft , nViewTop , nViewRight , nMaskY ) ;
DrawMap ( ) ;
videoSetViewableArea ( nViewLeft , nViewTop , nViewRight , nViewBottom ) ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
else
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
DrawMap ( ) ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 16:05:11 +00:00
# else
// TODO: Map should not be drawn on top of status bar. Redraw status bar?
DrawMap ( ) ;
# endif
2019-08-31 14:07:47 +00:00
}
2019-08-26 03:59:14 +00:00
2019-08-31 14:07:47 +00:00
videoNextPage ( ) ;
2019-08-26 03:59:14 +00:00
// TODO CONTROL_GetButtonInput();
2019-08-31 14:07:47 +00:00
CheckKeys ( ) ;
UpdateSounds ( ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
bInMove = kTrue ;
2019-08-27 06:08:18 +00:00
2019-09-06 05:18:12 +00:00
moveframes = ( ( int ) totalclock - tclocks2 ) / 4 ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( moveframes > 4 )
moveframes = 4 ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( moveframes ! = 0 )
2019-09-06 05:18:12 +00:00
tclocks2 = ( int ) totalclock ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( bPlayback )
{
// YELLOW
if ( ( bInDemo & & KB_KeyWaiting ( ) | | ! ReadPlaybackInputs ( ) ) & & KB_GetCh ( ) )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
KB_FlushKeyboardQueue ( ) ;
KB_ClearKeysDown ( ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
bPlayback = kFalse ;
bInDemo = kFalse ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( vcrfp ) {
fclose ( vcrfp ) ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
2019-08-31 15:04:06 +00:00
CONTROL_BindsEnabled = 0 ;
2019-08-31 14:07:47 +00:00
goto MENU ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
}
else if ( bRecord | | moveframes )
{
GetLocalInput ( ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
sPlayerInput [ nLocalPlayer ] . xVel = lPlayerXVel ;
sPlayerInput [ nLocalPlayer ] . yVel = lPlayerYVel ;
sPlayerInput [ nLocalPlayer ] . buttons = lLocalButtons | lLocalCodes ;
sPlayerInput [ nLocalPlayer ] . nAngle = nPlayerDAng ;
sPlayerInput [ nLocalPlayer ] . nTarget = besttarget ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
Ra [ nLocalPlayer ] . nTarget = besttarget ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
lLocalCodes = 0 ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
sPlayerInput [ nLocalPlayer ] . horizon = nVertPan [ nLocalPlayer ] ;
}
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
// loc_11F72:
if ( bRecord & & ! bInDemo ) {
WritePlaybackInputs ( ) ;
}
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( nNetPlayerCount )
{
if ( moveframes )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
UpdateInputs ( ) ;
moveframes = nNetMoveFrames ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
}
else
{
// loc_11FBC:
while ( bPause )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
ClearAllKeys ( ) ;
if ( WaitAnyKey ( - 1 ) ! = sc_Pause )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
bPause = kFalse ;
2019-08-27 06:08:18 +00:00
}
}
2019-08-31 14:07:47 +00:00
}
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
// loc_11FEE:
tclocks + = moveframes * 4 ;
while ( moveframes & & levelnew < 0 )
{
FixPalette ( ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( levelnum = = kMap20 )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
if ( lCountDown < = 0 )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
for ( int i = 0 ; i < nTotalPlayers ; i + + ) {
nPlayerLives [ i ] = 0 ;
}
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
DoFailedFinalScene ( ) ;
levelnew = 100 ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
break ;
}
// Pink section
lCountDown - - ;
DrawClock ( ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( nRedTicks )
{
nRedTicks - - ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( nRedTicks < = 0 ) {
DoRedAlert ( 0 ) ;
}
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
nAlarmTicks - - ;
nButtonColor - - ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( nAlarmTicks < = 0 ) {
DoRedAlert ( 1 ) ;
2019-08-27 06:08:18 +00:00
}
}
2019-08-31 14:07:47 +00:00
}
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
// YELLOW SECTION
MoveThings ( ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( totalvel [ nLocalPlayer ] = = 0 )
{
bobangle = 0 ;
}
else
{
bobangle + = 56 ;
bobangle & = kAngleMask ;
}
// loc_120E9:
totalmoves + + ;
moveframes - - ;
if ( nNetTime > 0 )
{
nNetTime - - ;
if ( ! nNetTime ) {
nFreeze = 3 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
}
else if ( nNetTime = = 0 )
{
if ( BUTTON ( gamefunc_Open ) )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
CONTROL_ClearButton ( gamefunc_Open ) ;
goto MENU2 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
}
}
// END YELLOW SECTION
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
// loc_12149:
if ( bInDemo )
{
2019-09-06 05:18:12 +00:00
while ( tclocks > ( int ) totalclock ) { HandleAsync ( ) ; }
tclocks = ( int ) totalclock ;
2019-08-31 14:07:47 +00:00
}
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
bInMove = kFalse ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( ! bInDemo )
{
if ( BUTTON ( gamefunc_Escape ) )
{
CONTROL_ClearButton ( gamefunc_Escape ) ;
MENU2 :
2019-08-31 15:04:06 +00:00
CONTROL_BindsEnabled = 0 ;
2019-08-31 14:07:47 +00:00
nMenu = menu_Menu ( 1 ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
switch ( nMenu )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
case 0 :
goto EXITGAME ;
case 1 :
goto STARTGAME1 ;
case 2 :
levelnum = levelnew = menu_GameLoad ( SavePosition ) ;
lastlevel = - 1 ;
nBestLevel = levelnew - 1 ;
goto LOOP2 ;
case 3 : // When selecting 'Training' from ingame menu when already playing a level
if ( levelnum = = 0 | | ! Query ( 2 , 4 , " Quit current game? " , " Y/N " , ' Y ' , 13 , ' N ' , 27 ) )
{
levelnew = 0 ;
levelnum = 0 ;
}
break ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 15:04:06 +00:00
CONTROL_BindsEnabled = 1 ;
2019-08-31 14:07:47 +00:00
RefreshStatus ( ) ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
else if ( KB_KeyDown [ sc_PrintScreen ] )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
videoCaptureScreen ( " captxxxx.png " , 0 ) ;
KB_KeyDown [ sc_PrintScreen ] = 0 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
else if ( BUTTON ( gamefunc_Map ) ) // e.g. TAB (to show 2D map)
{
CONTROL_ClearButton ( gamefunc_Map ) ;
2019-08-27 06:08:18 +00:00
2019-08-31 14:07:47 +00:00
if ( ! nFreeze ) {
bMapMode = ! bMapMode ;
}
}
else if ( BUTTON ( gamefunc_Zoom_Out ) )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
lMapZoom - = ldMapZoom ;
if ( lMapZoom < = 32 )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
lMapZoom = 32 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
else if ( ldMapZoom < = 16 )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
ldMapZoom = 16 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
else
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
ldMapZoom - = 2 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
}
else if ( BUTTON ( gamefunc_Zoom_In ) )
{
lMapZoom + = ldMapZoom ;
if ( lMapZoom > = 1280 )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
lMapZoom = 1280 ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
else if ( ldMapZoom > = 128 )
2019-08-27 06:08:18 +00:00
{
2019-08-31 14:07:47 +00:00
ldMapZoom = 128 ;
}
else
{
ldMapZoom + = 2 ;
2019-08-27 06:08:18 +00:00
}
}
2019-08-31 14:07:47 +00:00
if ( PlayerList [ nLocalPlayer ] . nHealth > 0 )
2019-08-27 06:08:18 +00:00
{
if ( BUTTON ( gamefunc_Inventory_Left ) )
{
SetPrevItem ( nLocalPlayer ) ;
CONTROL_ClearButton ( gamefunc_Inventory_Left ) ;
}
if ( BUTTON ( gamefunc_Inventory_Right ) )
{
SetNextItem ( nLocalPlayer ) ;
CONTROL_ClearButton ( gamefunc_Inventory_Right ) ;
}
if ( BUTTON ( gamefunc_Inventory ) )
{
UseCurItem ( nLocalPlayer ) ;
CONTROL_ClearButton ( gamefunc_Inventory ) ;
}
}
2019-10-28 19:14:54 +00:00
else {
2019-08-31 14:07:47 +00:00
SetAirFrame ( ) ;
2019-10-28 19:14:54 +00:00
}
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
if ( record_mode = = 3 & & movefifopos = = movefifoend ) {
2019-08-27 06:08:18 +00:00
levelnew = 0 ;
}
2019-08-31 14:07:47 +00:00
fps + + ;
2019-08-27 06:08:18 +00:00
}
2019-08-31 14:07:47 +00:00
EXITGAME :
2019-08-27 06:08:18 +00:00
if ( bRecord ) {
fclose ( vcrfp ) ;
}
FadeSong ( ) ;
if ( CDplaying ( ) ) {
fadecdaudio ( ) ;
}
StopAllSounds ( ) ;
StopLocalSound ( ) ;
mysaveconfig ( ) ;
if ( bSerialPlay )
{
if ( nNetPlayerCount ! = 0 ) {
bSendBye = kTrue ;
UpdateSerialInputs ( ) ;
}
}
else
{
if ( nNetPlayerCount ! = 0 ) {
SendGoodbye ( ) ;
}
}
2019-08-31 14:07:47 +00:00
ShutDown ( ) ;
2019-08-27 06:08:18 +00:00
return 0 ;
2019-08-26 03:59:14 +00:00
}
void mychangespritesect ( int nSprite , int nSector )
{
2019-08-27 06:08:18 +00:00
DoKenTest ( ) ;
changespritesect ( nSprite , nSector ) ;
DoKenTest ( ) ;
2019-08-26 03:59:14 +00:00
}
void mydeletesprite ( int nSprite )
{
2019-08-27 06:08:18 +00:00
if ( nSprite < 0 | | nSprite > kMaxSprites ) {
bail2dos ( " bad sprite value %d handed to mydeletesprite " , nSprite ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
deletesprite ( nSprite ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( nSprite = = besttarget ) {
besttarget = - 1 ;
}
2019-08-26 03:59:14 +00:00
}
void KeyFn1 ( )
{
2019-08-27 06:08:18 +00:00
menu_DoPlasma ( ) ;
overwritesprite ( 160 , 100 , kSkullHead , 0 , 3 , kPalNormal ) ;
overwritesprite ( 161 , 130 , kSkullJaw , 0 , 3 , kPalNormal ) ;
videoNextPage ( ) ;
2019-08-26 03:59:14 +00:00
}
void DoGameOverScene ( )
{
2019-08-27 06:08:18 +00:00
FadeOut ( 0 ) ;
ClearAllKeys ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( LoadCinemaPalette ( 16 ) < 0 ) {
return ;
}
2019-08-26 03:59:14 +00:00
2019-10-12 21:09:55 +00:00
SetOverscan ( ANIMPAL ) ;
2019-08-27 06:08:18 +00:00
NoClip ( ) ;
overwritesprite ( 0 , 0 , kTile3591 , 0 , 2 , kPalNormal ) ;
Clip ( ) ;
2019-08-26 03:59:14 +00:00
videoNextPage ( ) ;
2019-08-27 06:08:18 +00:00
CinemaFadeIn ( ) ;
2019-09-21 15:47:55 +00:00
PlayGameOverSound ( ) ;
2019-08-27 06:08:18 +00:00
WaitAnyKey ( 3 ) ;
FadeOut ( 0 ) ;
2019-10-12 21:09:55 +00:00
SetOverscan ( BASEPAL ) ;
2019-08-26 03:59:14 +00:00
}
// TODO - missing some values?
short word_10010 [ ] = { 6 , 25 , 43 , 50 , 68 , 78 , 101 , 111 , 134 , 158 , 173 , 230 , 6000 } ;
void DoTitle ( )
{
2019-08-27 06:08:18 +00:00
return ; // REVERT
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
short theArray [ 13 ] ;
memcpy ( theArray , word_10010 , sizeof ( word_10010 ) ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
videoSetViewableArea ( 0 , 0 , xdim - 1 , ydim - 1 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
BlackOut ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
overwritesprite ( 0 , 0 , kPublisherLogo , 0 , 2 , kPalNormal ) ;
2019-08-26 03:59:14 +00:00
videoNextPage ( ) ;
2019-08-27 06:08:18 +00:00
FadeIn ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
ClearAllKeys ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
WaitAnyKey ( 2 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
FadeOut ( 0 ) ;
2019-08-26 03:59:14 +00:00
2019-10-12 21:09:55 +00:00
SetOverscan ( BASEPAL ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nScreenTile = seq_GetSeqPicnum ( kSeqScreens , 0 , 0 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
overwritesprite ( 0 , 0 , nScreenTile , 0 , 2 , kPalNormal ) ;
2019-08-26 03:59:14 +00:00
videoNextPage ( ) ;
2019-08-27 06:08:18 +00:00
FadeIn ( ) ;
2019-09-21 15:47:55 +00:00
PlayLogoSound ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
WaitAnyKey ( 2 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
FadeOut ( 0 ) ;
ClearAllKeys ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
PlayMovie ( " book.mov " ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
FadeOut ( 0 ) ;
2019-08-26 03:59:14 +00:00
2019-10-12 21:09:55 +00:00
SetOverscan ( BASEPAL ) ;
2019-08-27 06:08:18 +00:00
GrabPalette ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
SetLocalChan ( 1 ) ;
PlayLocalSound ( StaticSound [ 59 ] , 0 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
SetLocalChan ( 0 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
EraseScreen ( 4 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
playCDtrack ( 19 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
videoNextPage ( ) ;
FadeIn ( ) ;
WaitVBL ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int String_Copyright = FindGString ( " COPYRIGHT " ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
const char * a = gString [ String_Copyright ] ;
const char * b = gString [ String_Copyright + 1 ] ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
menu_DoPlasma ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nTile = kSkullHead ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
overwritesprite ( 160 , 100 , kSkullHead , 0 , 3 , kPalNormal ) ;
overwritesprite ( 161 , 130 , kSkullJaw , 0 , 3 , kPalNormal ) ;
videoNextPage ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
WaitNoKey ( 2 , KeyFn1 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( time ( 0 ) & 0xF ) {
2019-09-21 15:47:55 +00:00
PlayGameOverSound ( ) ;
2019-08-27 06:08:18 +00:00
}
else {
PlayLocalSound ( StaticSound [ 61 ] , 0 ) ;
}
2019-08-26 03:59:14 +00:00
2019-09-06 05:18:12 +00:00
int nStartTime = ( int ) totalclock ;
2019-08-27 06:08:18 +00:00
int nCount = 0 ;
2019-09-06 05:18:12 +00:00
int var_18 = ( int ) totalclock ;
2019-08-27 06:08:18 +00:00
int var_4 = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int esi = 130 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
var_18 + = theArray [ 0 ] ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
while ( LocalSoundPlaying ( ) )
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
menu_DoPlasma ( ) ;
overwritesprite ( 160 , 100 , nTile , 0 , 3 , kPalNormal ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nStringWidth = MyGetStringWidth ( a ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int y = ydim - 24 ;
myprintext ( ( xdim / 2 - nStringWidth / 2 ) , y , a , 0 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nStringWidth = MyGetStringWidth ( b ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
y = ydim - 16 ;
myprintext ( ( xdim / 2 - nStringWidth / 2 ) , y , b , 0 ) ;
2019-08-26 03:59:14 +00:00
2019-09-06 05:18:12 +00:00
if ( ( int ) totalclock > var_18 )
2019-08-27 06:08:18 +00:00
{
nCount + + ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
assert ( nCount < = 12 ) ;
var_18 = nStartTime + theArray [ nCount ] ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
var_4 = var_4 = = 0 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
short nTile = kSkullJaw ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( var_4 )
{
if ( esi > = 135 ) {
nTile = kTile3583 ;
}
else {
esi + = 5 ;
}
}
else if ( esi < = 130 )
{
esi = 130 ;
}
else
{
esi - = 2 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
y = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( nTile = = kTile3583 )
{
y = 131 ;
}
else
{
y = esi ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( y > 135 ) {
y = 135 ;
}
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
overwritesprite ( 161 , y , nTile , 0 , 3 , kPalNormal ) ;
videoNextPage ( ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
WaitNoKey ( 1 , KeyFn1 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
videoSetViewableArea ( nViewLeft , nViewTop , nViewRight , nViewBottom ) ;
2019-08-26 03:59:14 +00:00
}
void CopyTileToBitmap ( short nSrcTile , short nDestTile , int xPos , int yPos )
{
2019-08-27 06:08:18 +00:00
int nOffs = tilesiz [ nDestTile ] . y * xPos ;
2019-08-31 07:47:15 +00:00
uint8_t * pDest = ( uint8_t * ) waloff [ nDestTile ] + nOffs + yPos ;
uint8_t * pDestB = pDest ;
2019-08-27 06:08:18 +00:00
tileLoad ( nSrcTile ) ;
int destYSize = tilesiz [ nDestTile ] . y ;
int srcYSize = tilesiz [ nSrcTile ] . y ;
2019-08-31 07:47:15 +00:00
uint8_t * pSrc = ( uint8_t * ) waloff [ nSrcTile ] ;
2019-08-27 06:08:18 +00:00
for ( int x = 0 ; x < tilesiz [ nSrcTile ] . x ; x + + )
{
pDest + = destYSize ;
for ( int y = 0 ; y < srcYSize ; y + + )
{
2019-08-31 07:47:15 +00:00
uint8_t val = * pSrc ;
2019-08-27 06:08:18 +00:00
if ( val ! = 0xFF ) {
* pDestB = val ;
}
pDestB + + ;
pSrc + + ;
}
// reset pDestB
pDestB = pDest ;
}
2019-08-26 03:59:14 +00:00
}
int CopyCharToBitmap ( char nChar , int nTile , int xPos , int yPos )
{
2019-08-27 06:08:18 +00:00
if ( nChar = = ' ' ) {
return 4 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nChar = toupper ( nChar ) ;
int nFontTile = seq_GetSeqPicnum ( kSeqFont2 , 0 , nChar - 32 ) + 102 ;
CopyTileToBitmap ( nFontTile , nTile , xPos , yPos ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
return tilesiz [ nFontTile ] . x + 1 ;
2019-08-26 03:59:14 +00:00
}
// Note: strings passed should be uppercase
int myprintext ( int x , int y , const char * str , int shade )
{
2019-08-27 06:08:18 +00:00
if ( y < - 15 | | y > = 200 )
return x ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
const char * c = str ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
while ( * c ! = ' \0 ' )
{
int nTile = seq_GetSeqPicnum ( kSeqFont2 , 0 , ( * c ) - 32 ) ;
overwritesprite ( x , y , nTile , shade , 2 , kPalNormal ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int tileWidth = tilesiz [ nTile ] . x ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
x + = tileWidth + 1 ;
c + + ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
return x ;
2019-08-26 03:59:14 +00:00
}
void EraseScreen ( int nVal )
{
2019-08-27 06:08:18 +00:00
if ( nVal = = - 1 ) {
nVal = overscanindex ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 16:05:11 +00:00
videoClearScreen ( nVal ) ;
#if 0
2019-08-27 06:08:18 +00:00
for ( int i = 0 ; i < numpages ; i + + )
{
2019-08-26 03:59:14 +00:00
videoClearScreen ( nVal ) ;
2019-08-27 06:08:18 +00:00
videoNextPage ( ) ;
}
2019-08-31 16:05:11 +00:00
# endif
2019-08-26 03:59:14 +00:00
}
int Query ( short nLines , short nKeys , . . . )
{
2019-08-27 06:08:18 +00:00
short i ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
char strings [ 20 ] [ 80 ] ;
char keys [ 20 ] ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
va_list args ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
short bPrevClip = bClip ;
NoClip ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
short nWidth = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
va_start ( args , nKeys ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
for ( i = 0 ; i < nLines ; i + + )
{
char * str = va_arg ( args , char * ) ;
strcpy ( strings [ i ] , str ) ;
strupr ( strings [ i ] ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int strWidth = MyGetStringWidth ( strings [ i ] ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( strWidth > nWidth ) {
nWidth = strWidth ;
}
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
for ( i = 0 ; i < nKeys ; i + + ) {
keys [ i ] = va_arg ( args , char ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
va_end ( args ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nHeight = ( nLines + 1 ) * 10 ;
int y1 = ( 200 - nHeight ) / 2 ;
int yB = y1 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
// add some padding to left and right sides of text in the box
nWidth + = 30 ;
int x1 = ( 320 - nWidth ) / 2 ;
int x2 = x1 + nWidth ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( bHiRes )
{
x1 * = 2 ;
y1 * = 2 ;
nHeight * = 2 ;
x2 * = 2 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
// draw background box that the text sits in
for ( i = 0 ; i < nHeight ; i + + ) {
2019-08-26 03:59:14 +00:00
renderDrawLine ( x1 < < 12 , ( y1 + i ) < < 12 , x2 < < 12 , ( y1 + i ) < < 12 , overscanindex ) ;
2019-08-27 06:08:18 +00:00
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
y1 = yB + 5 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
// draw each line of text
for ( i = 0 ; i < nLines ; i + + ) {
myprintext ( ( 320 - MyGetStringWidth ( strings [ i ] ) ) / 2 , ( y1 + i * 10 ) , strings [ i ] , 0 ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
videoNextPage ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( bPrevClip ) {
Clip ( ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
i = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( nKeys )
{
KB_FlushKeyboardQueue ( ) ;
while ( 1 )
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-27 06:08:18 +00:00
char key = toupper ( KB_GetCh ( ) ) ;
for ( i = 0 ; i < nKeys ; i + + )
{
if ( keys [ i ] = = 0 | | key = = keys [ i ] )
{
RefreshStatus ( ) ;
ClearAllKeys ( ) ;
return i ;
}
}
}
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
RefreshStatus ( ) ;
ClearAllKeys ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
return i ;
2019-08-26 03:59:14 +00:00
}
void InitSpiritHead ( )
{
2019-08-27 06:08:18 +00:00
char filename [ 20 ] ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nPixels = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
tileLoad ( kTileRamsesNormal ) ; // Ramses Normal Head
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
for ( int i = 0 ; i < kMaxSprites ; i + + )
{
if ( sprite [ i ] . statnum )
{
sprite [ i ] . cstat | = 0x8000 ;
}
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
uint8_t * pTile = ( uint8_t * ) waloff [ kTileRamsesNormal ] ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
for ( int x = 0 ; x < 97 ; x + + )
{
for ( int y = 0 ; y < 106 ; y + + )
{
if ( * pTile ! = 255 )
{
2019-08-31 07:47:15 +00:00
pixelval [ nPixels ] = * ( uint8_t * ) ( waloff [ kTileRamsesGold ] + x * 106 + y ) ;
2019-08-27 06:08:18 +00:00
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 + + ;
}
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
waloff [ kTileRamsesWorkTile ] = ( intptr_t ) worktile ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
sprite [ nSpiritSprite ] . yrepeat = 140 ;
sprite [ nSpiritSprite ] . xrepeat = 140 ;
sprite [ nSpiritSprite ] . picnum = kTileRamsesWorkTile ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nHeadStage = 0 ;
// work tile is twice as big as the normal head size
tilesiz [ kTileRamsesWorkTile ] . x = 97 * 2 ; // 194;
tilesiz [ kTileRamsesWorkTile ] . y = 106 * 2 ; // 212;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
sprite [ nSpiritSprite ] . cstat & = 0x7FFF ;
2019-08-26 03:59:14 +00:00
2019-09-06 05:18:12 +00:00
nHeadTimeStart = ( int ) totalclock ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
memset ( worktile , - 1 , sizeof ( worktile ) ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nPixelsToShow = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
fadecdaudio ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nTrack ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( levelnum = = 1 )
{
nTrack = 3 ;
}
else
{
nTrack = 7 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nCDTrackLength = playCDtrack ( nTrack ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
bSubTitles = nCDTrackLength = = 0 ;
StartSwirlies ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
sprintf ( filename , " LEV%d.PUP " , levelnum ) ;
2019-09-06 05:18:12 +00:00
lNextStateChange = ( int ) totalclock ;
lHeadStartClock = ( int ) totalclock ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
headfd = kopen4load ( filename , 512 ) ; // 512??
nPupData = kread ( headfd , cPupData , sizeof ( cPupData ) ) ;
pPupData = cPupData ;
kclose ( headfd ) ;
headfd = - 1 ;
nMouthTile = 0 ;
nTalkTime = 1 ;
2019-08-26 03:59:14 +00:00
}
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 )
{
2019-08-27 06:08:18 +00:00
tileLoad ( nTile ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
uint8_t * pSrc = ( uint8_t * ) waloff [ nTile ] ;
uint8_t * pDest = ( uint8_t * ) & worktile [ 212 * 49 + 53 ] ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
for ( int i = 0 ; i < 97 ; i + + )
{
memcpy ( pDest , pSrc , 106 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
pDest + = 212 ;
pSrc + = 106 ;
}
2019-08-26 03:59:14 +00:00
}
# if 1
int DoSpiritHead ( )
{
2019-08-27 06:08:18 +00:00
static short word_964E6 = 0 ;
nVertPan [ 0 ] + = ( nDestVertPan [ 0 ] - nVertPan [ 0 ] ) / 4 ;
if ( nHeadStage < 2 )
{
memset ( worktile , - 1 , sizeof ( worktile ) ) ;
}
if ( nHeadStage < 2 | | nHeadStage ! = 5 )
{
2019-09-06 05:18:12 +00:00
nPixelsToShow = ( ( int ) totalclock - nHeadTimeStart ) * 15 ;
2019-08-27 06:08:18 +00:00
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 )
{
2019-09-06 05:18:12 +00:00
if ( ( ( int ) totalclock - nHeadTimeStart ) > 480 )
2019-08-27 06:08:18 +00:00
{
nHeadStage = 1 ;
2019-09-06 05:18:12 +00:00
nHeadTimeStart = ( int ) totalclock + 480 ;
2019-08-27 06:08:18 +00:00
}
2019-08-26 03:59:14 +00:00
// int ecx = 0;
2019-08-27 06:08:18 +00:00
// loc_1362C
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 ;
}
}
// loc_13593
int esi = vely [ i ] + ( cury [ i ] > > 8 ) ;
if ( esi < 106 )
{
if ( esi < - 105 )
{
vely [ i ] = 0 ;
esi = 0 ;
}
}
else
{
vely [ i ] = 0 ;
esi = 0 ;
}
// loc_135C6
int ebx = velx [ i ] + ( curx [ i ] > > 8 ) ;
if ( ebx < 97 )
{
if ( ebx < - 96 )
{
velx [ i ] = 0 ;
ebx = 0 ;
}
}
else
{
velx [ i ] = 0 ;
ebx = 0 ;
}
// loc_135F9
2019-08-31 10:36:26 +00:00
curx [ i ] = ebx * 256 ;
cury [ i ] = esi * 256 ;
2019-08-27 06:08:18 +00:00
//ecx += 2;
2019-08-26 03:59:14 +00:00
// ecx++;
2019-08-27 06:08:18 +00:00
esi + = ( ebx + 97 ) * 212 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
// uint8_t *pVal = (uint8_t*)worktile;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
worktile [ 106 + esi ] = pixelval [ i ] ;
//pVal += (106 + esi);
//*pVal = pixelval[i];
}
return 1 ;
}
else
{
// loc_13679:
if ( nHeadStage ! = 1 ) {
return 1 ;
}
2019-08-31 07:47:15 +00:00
uint8_t nXRepeat = sprite [ nSpiritSprite ] . xrepeat ;
2019-08-27 06:08:18 +00:00
if ( nXRepeat > nSpiritRepeatX )
{
sprite [ nSpiritSprite ] . xrepeat - = 2 ;
nXRepeat = sprite [ nSpiritSprite ] . xrepeat ;
if ( nXRepeat < nSpiritRepeatX )
{
sprite [ nSpiritSprite ] . xrepeat = nSpiritRepeatX ;
}
}
2019-08-31 07:47:15 +00:00
uint8_t nYRepeat = sprite [ nSpiritSprite ] . yrepeat ;
2019-08-27 06:08:18 +00:00
if ( nYRepeat > nSpiritRepeatY )
{
sprite [ nSpiritSprite ] . yrepeat - = 2 ;
nYRepeat = sprite [ nSpiritSprite ] . yrepeat ;
if ( nYRepeat < nSpiritRepeatY )
{
sprite [ nSpiritSprite ] . yrepeat = nSpiritRepeatY ;
}
}
// loc_13705
int esi = 0 ;
2019-08-26 03:59:14 +00:00
// int edx = 0;
2019-08-27 06:08:18 +00:00
// loc_137E7:
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 ;
}
// loc_1374B
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 ) ;
2019-08-26 03:59:14 +00:00
// edx++;
2019-08-31 07:47:15 +00:00
// uint8_t *pVal = (uint8_t*)worktile;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
worktile [ 106 + ecx ] = pixelval [ i ] ;
//pVal += (106 + ecx);
//*pVal = pixelval[i];
}
2019-09-06 05:18:12 +00:00
if ( ( ( int ) totalclock - lHeadStartClock ) > 600 ) {
2019-08-27 06:08:18 +00:00
CopyHeadToWorkTile ( kTileRamsesGold ) ;
}
int eax = ( ( nPixels < < 4 ) - nPixels ) / 16 ;
if ( esi < eax )
{
2019-09-21 15:47:55 +00:00
SoundBigEntrance ( ) ;
2019-08-27 06:08:18 +00:00
AddGlow ( sprite [ nSpiritSprite ] . sectnum , 20 ) ;
AddFlash (
sprite [ nSpiritSprite ] . sectnum ,
sprite [ nSpiritSprite ] . x ,
sprite [ nSpiritSprite ] . y ,
sprite [ nSpiritSprite ] . z ,
128 ) ;
nHeadStage = 3 ;
2019-10-12 21:09:55 +00:00
TintPalette ( 255 , 255 , 255 ) ;
2019-08-27 06:08:18 +00:00
CopyHeadToWorkTile ( kTileRamsesNormal ) ;
}
return 1 ;
}
}
else
{
// loc_138A7
FixPalette ( ) ;
if ( ! nPalDiff )
{
nFreeze = 2 ;
nHeadStage + + ;
}
return 0 ;
}
}
else
{
2019-09-06 05:18:12 +00:00
if ( lNextStateChange < = ( int ) totalclock )
2019-08-27 06:08:18 +00:00
{
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 ;
tileLoad ( ebx ) ;
// TODO - fixme. How big is worktile?
2019-08-31 07:47:15 +00:00
uint8_t * pDest = ( uint8_t * ) & worktile [ 10441 ] ;
uint8_t * pSrc = ( uint8_t * ) waloff [ ebx ] ;
2019-08-27 06:08:18 +00:00
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 )
{
2019-08-26 03:59:14 +00:00
tileLoad ( nMouthTile + 598 ) ;
2019-08-27 06:08:18 +00:00
short nTileSizeX = tilesiz [ nMouthTile + 598 ] . x ;
short nTileSizeY = tilesiz [ nMouthTile + 598 ] . y ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
// TODO - checkme. near loc_133AA
2019-08-31 07:47:15 +00:00
// uint8_t *pDest = (uint8_t*)worktile;
2019-08-26 03:59:14 +00:00
// pDest += (212 * (97 - nTileSizeX / 2)) + (159 - nTileSizeY);
2019-08-31 07:47:15 +00:00
uint8_t * pDest = ( uint8_t * ) & worktile [ 212 * ( 97 - nTileSizeX / 2 ) ] + ( 159 - nTileSizeY ) ;
uint8_t * pSrc = ( uint8_t * ) waloff [ nMouthTile + 598 ] ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
while ( nTileSizeX > 0 )
{
memcpy ( pDest , pSrc , nTileSizeY ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nTileSizeX - - ;
pDest + = 212 ;
pSrc + = nTileSizeY ;
}
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
return 1 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
// TEMP FIXME - temporary return value. what to return here? 1?
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
return 0 ;
2019-08-26 03:59:14 +00:00
}
# endif
#if 0
int DoSpiritHead ( )
{
2019-08-27 06:08:18 +00:00
static short word_964E6 = 0 ;
nVertPan [ 0 ] + = ( nDestVertPan [ 0 ] - nVertPan [ 0 ] ) / 4 ;
if ( nHeadStage < 2 )
{
memset ( worktile , - 1 , sizeof ( worktile ) ) ;
}
else if ( nHeadStage = = 5 )
{
2019-09-06 05:18:12 +00:00
if ( lNextStateChange < = ( int ) totalclock )
2019-08-27 06:08:18 +00:00
{
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 ;
loadtile ( ebx ) ;
// TODO - fixme. How big is worktile?
2019-08-31 07:47:15 +00:00
uint8_t * pDest = ( uint8_t * ) & worktile [ 10441 ] ;
uint8_t * pSrc = waloff [ ebx ] ;
2019-08-27 06:08:18 +00:00
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 )
{
loadtile ( nMouthTile + 598 ) ;
short nTileSizeX = tilesizx [ nMouthTile + 598 ] ;
short nTileSizeY = tilesizy [ nMouthTile + 598 ] ;
// TODO - checkme. near loc_133AA
2019-08-31 07:47:15 +00:00
// uint8_t *pDest = (uint8_t*)worktile;
2019-08-27 06:08:18 +00:00
// pDest += (212 * (97 - nTileSizeX / 2)) + (159 - nTileSizeY);
2019-08-31 07:47:15 +00:00
uint8_t * pDest = ( uint8_t * ) & worktile [ 212 * ( 97 - nTileSizeX / 2 ) ] + ( 159 - nTileSizeY ) ;
uint8_t * pSrc = waloff [ nMouthTile + 598 ] ;
2019-08-27 06:08:18 +00:00
while ( nTileSizeX > 0 )
{
memcpy ( pDest , pSrc , nTileSizeY ) ;
nTileSizeX - - ;
pDest + = 212 ;
pSrc + = nTileSizeY ;
}
}
return 1 ;
}
2019-09-06 05:18:12 +00:00
nPixelsToShow = ( ( int ) totalclock - nHeadTimeStart ) * 15 ;
2019-08-27 06:08:18 +00:00
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 )
{
2019-09-06 05:18:12 +00:00
if ( ( ( int ) totalclock - nHeadTimeStart ) > 480 )
2019-08-27 06:08:18 +00:00
{
nHeadStage = 1 ;
2019-09-06 05:18:12 +00:00
nHeadTimeStart = ( int ) totalclock + 480 ;
2019-08-27 06:08:18 +00:00
}
// int ecx = 0;
// loc_1362C
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 ) ;
}
}
// loc_13593
int esi = vely [ i ] + ( cury [ i ] > > 8 ) ;
if ( esi > = 106 )
{
vely [ i ] = 0 ;
esi = 0 ;
}
else if ( esi < - 105 )
{
vely [ i ] = 0 ;
esi = 0 ;
}
// loc_135C6
int ebx = velx [ i ] + ( curx [ i ] > > 8 ) ;
if ( ebx > = 97 )
{
velx [ i ] = 0 ;
ebx = 0 ;
}
else if ( ebx < - 96 )
{
velx [ i ] = 0 ;
ebx = 0 ;
}
// loc_135F9
curx [ i ] = ebx < < 8 ;
cury [ i ] = esi < < 8 ;
//ecx += 2;
// ecx++;
2019-08-31 07:47:15 +00:00
// uint8_t *pVal = (uint8_t*)worktile;
2019-08-27 06:08:18 +00:00
worktile [ 106 + esi + ( ebx + 97 ) * 212 ] = pixelval [ i ] ;
//pVal += (106 + esi);
//*pVal = pixelval[i];
}
}
else if ( nHeadStage = = 1 )
{
2019-08-31 07:47:15 +00:00
uint8_t nXRepeat = sprite [ nSpiritSprite ] . xrepeat ;
2019-08-27 06:08:18 +00:00
if ( nXRepeat > nSpiritRepeatX )
{
sprite [ nSpiritSprite ] . xrepeat - = 2 ;
nXRepeat = sprite [ nSpiritSprite ] . xrepeat ;
if ( nXRepeat < nSpiritRepeatX )
{
sprite [ nSpiritSprite ] . xrepeat = nSpiritRepeatX ;
}
}
2019-08-31 07:47:15 +00:00
uint8_t nYRepeat = sprite [ nSpiritSprite ] . yrepeat ;
2019-08-27 06:08:18 +00:00
if ( nYRepeat > nSpiritRepeatY )
{
sprite [ nSpiritSprite ] . yrepeat - = 2 ;
nYRepeat = sprite [ nSpiritSprite ] . yrepeat ;
if ( nYRepeat < nSpiritRepeatY )
{
sprite [ nSpiritSprite ] . yrepeat = nSpiritRepeatY ;
}
}
// loc_13705
int esi = 0 ;
// int edx = 0;
// loc_137E7:
for ( int i = 0 ; i < nPixels ; i + + )
{
int eax = ( origx [ i ] < < 8 ) - curx [ i ] ;
int ecx = eax ;
if ( eax & & klabs ( eax ) < 8 )
{
curx [ i ] = origx [ i ] < < 8 ;
ecx = 0 ;
}
else
{
ecx > > = 3 ;
}
// loc_1374B
int var_1C = ( origy [ i ] < < 8 ) - cury [ i ] ;
int ebp = var_1C ;
if ( ebp & & klabs ( ebp ) < 8 )
{
cury [ i ] = origy [ i ] < < 8 ;
var_1C = 0 ;
}
else
{
var_1C > > = 3 ;
}
if ( var_1C | ecx )
{
curx [ i ] + = ecx ;
cury [ i ] + = var_1C ;
esi + + ;
}
// edx++;
2019-08-31 07:47:15 +00:00
// uint8_t *pVal = (uint8_t*)worktile;
2019-08-27 06:08:18 +00:00
worktile [ 106 + ( ( ( curx [ i ] > > 8 ) + 97 ) * 212 ) + ( cury [ i ] > > 8 ) ] = pixelval [ i ] ;
//pVal += (106 + ecx);
//*pVal = pixelval[i];
}
2019-09-06 05:18:12 +00:00
if ( ( ( int ) totalclock - lHeadStartClock ) > 600 ) {
2019-08-27 06:08:18 +00:00
CopyHeadToWorkTile ( kTileRamsesGold ) ;
}
int eax = ( nPixels * 15 ) / 16 ;
if ( esi < eax )
{
// SoundBigEntrance(); // TODO
AddGlow ( sprite [ nSpiritSprite ] . sectnum , 20 ) ;
AddFlash (
sprite [ nSpiritSprite ] . sectnum ,
sprite [ nSpiritSprite ] . x ,
sprite [ nSpiritSprite ] . y ,
sprite [ nSpiritSprite ] . z ,
128 ) ;
nHeadStage = 3 ;
2019-10-12 21:09:55 +00:00
TintPalette ( 255 , 255 , 255 ) ;
2019-08-27 06:08:18 +00:00
CopyHeadToWorkTile ( kTileRamsesNormal ) ;
}
}
return 1 ;
}
// loc_138A7
FixPalette ( ) ;
if ( ! nPalDiff )
{
nFreeze = 2 ;
nHeadStage + + ;
}
return 0 ;
2019-08-26 03:59:14 +00:00
}
# endif