2019-11-20 16:21:32 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 2010 - 2019 EDuke32 developers and contributors
Copyright ( C ) 2019 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 .
*/
//-------------------------------------------------------------------------
2019-11-22 23:11:37 +00:00
# include "ns.h"
2019-09-19 19:45:19 +00:00
# include "compat.h"
2019-09-20 17:04:02 +00:00
# include "build.h"
2019-09-19 19:45:19 +00:00
# include "exhumed.h"
2020-08-18 07:52:08 +00:00
# include "aistuff.h"
2019-09-19 19:45:19 +00:00
# include "player.h"
# include "sequence.h"
2019-09-20 17:04:02 +00:00
# include "menu.h"
# include "names.h"
# include "engine.h"
2020-01-02 18:56:57 +00:00
# include "c_bind.h"
2019-09-19 19:45:19 +00:00
# include "status.h"
2019-09-20 17:04:02 +00:00
# include "sound.h"
# include "names.h"
2019-11-24 09:03:19 +00:00
# include "ps_input.h"
2019-08-26 03:59:14 +00:00
# include "view.h"
2020-04-12 06:09:38 +00:00
# include "raze_sound.h"
2020-06-14 16:57:55 +00:00
# include "menu.h"
2020-01-05 09:48:44 +00:00
# include "v_2ddrawer.h"
2020-08-21 20:30:51 +00:00
# include "gamestate.h"
2020-08-21 20:40:09 +00:00
# include "statistics.h"
# include "v_draw.h"
2019-09-20 17:04:02 +00:00
# include <string>
2019-08-26 03:59:14 +00:00
# include <assert.h>
# ifdef __WATCOMC__
# include <stdlib.h>
# endif
2019-11-22 23:11:37 +00:00
BEGIN_PS_NS
2019-10-29 21:28:14 +00:00
# define kSaveFileName "savgamea.sav"
2019-09-20 17:04:02 +00:00
# define kMaxSaveSlots 5
# define kMaxSaveSlotChars 25
2019-08-26 03:59:14 +00:00
GameStat GameStats ;
short nCinemaSeen [ 30 ] ;
2019-11-18 22:15:48 +00:00
uint8_t energytile [ 66 * 66 ] = { 0 } ;
2019-08-26 03:59:14 +00:00
short SavePosition = - 1 ;
2019-08-31 07:47:15 +00:00
uint8_t * cur ;
uint8_t * dest ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
unsigned int nRandom = 0x41C6167E ;
int dword_9AB57 = 0x1F ;
short word_9AB5B = 0 ;
2019-08-26 03:59:14 +00:00
int keytimer = 0 ;
2019-09-20 17:04:02 +00:00
short nMenuKeys [ ] = { sc_N , sc_L , sc_M , sc_V , sc_Q , sc_None } ; // select a menu item using the keys. 'N' for New Gane, 'V' for voume etc. 'M' picks Training for some reason...
2019-08-26 03:59:14 +00:00
void menu_ResetKeyTimer ( ) ;
2019-09-20 17:04:02 +00:00
enum {
2019-08-31 07:47:15 +00:00
kMenuNewGame = 0 ,
kMenuLoadGame ,
kMenuTraining ,
kMenuVolume ,
kMenuQuitGame ,
kMenuMaxItems
2019-08-26 03:59:14 +00:00
} ;
2020-08-22 09:56:54 +00:00
void RunCinemaScene ( int num ) ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
void ClearCinemaSeen ( )
{
memset ( nCinemaSeen , 0 , sizeof ( nCinemaSeen ) ) ;
}
2019-08-26 03:59:14 +00:00
unsigned int menu_RandomBit2 ( )
{
2019-08-31 07:47:15 +00:00
unsigned int result = nRandom & 1 ;
2019-09-20 17:04:02 +00:00
if ( - - dword_9AB57 > 0 )
2019-08-31 07:47:15 +00:00
{
nRandom = ( result < < 31 ) | ( nRandom > > 1 ) ;
}
else
{
dword_9AB57 = 31 ;
nRandom ^ = nRandom > > 4 ;
}
return result ;
2019-08-26 03:59:14 +00:00
}
2019-09-20 17:04:02 +00:00
void InitEnergyTile ( )
{
memset ( energytile , 96 , sizeof ( energytile ) ) ;
}
2019-08-26 03:59:14 +00:00
void DoEnergyTile ( )
{
2019-08-31 07:47:15 +00:00
nButtonColor + = nButtonColor < 0 ? 8 : 0 ;
2019-11-24 15:34:23 +00:00
auto energy1 = TileFiles . tileMakeWritable ( kEnergy1 ) ;
auto energy2 = TileFiles . tileMakeWritable ( kEnergy2 ) ;
uint8_t * ptr1 = energy1 + 1984 ;
uint8_t * ptr2 = energy2 + 2048 ;
2019-08-31 07:47:15 +00:00
short nColor = nButtonColor + 161 ;
int i , j ;
for ( i = 0 ; i < 32 ; i + + )
{
memset ( ptr1 , nColor , 64 ) ;
memset ( ptr2 , nColor , 64 ) ;
ptr1 - = 64 ;
ptr2 + = 64 ;
nColor + + ;
2019-11-20 16:21:32 +00:00
2019-09-20 17:04:02 +00:00
if ( nColor > = 168 ) {
2019-08-31 07:47:15 +00:00
nColor = 160 ;
}
}
2019-11-05 06:15:21 +00:00
tileInvalidate ( kEnergy1 , - 1 , - 1 ) ;
2019-08-31 07:47:15 +00:00
if ( nSmokeSparks )
{
2019-11-18 22:15:48 +00:00
uint8_t * c = & energytile [ 67 ] ; // skip a line
2019-11-24 15:34:23 +00:00
uint8_t * ptrW = energy2 ;
2019-08-31 07:47:15 +00:00
for ( i = 0 ; i < 64 ; i + + )
{
for ( j = 0 ; j < 64 ; j + + )
{
2019-12-03 22:02:17 +00:00
uint8_t val = * c ;
if ( val ! = 96 )
2019-08-31 07:47:15 +00:00
{
2019-12-03 22:02:17 +00:00
if ( val > 158 ) {
* ptrW = val - 1 ;
2019-08-31 07:47:15 +00:00
}
2019-09-20 17:04:02 +00:00
else {
2019-12-03 22:02:17 +00:00
* ptrW = 96 ;
2019-08-31 07:47:15 +00:00
}
}
else
{
2019-09-20 17:04:02 +00:00
if ( menu_RandomBit2 ( ) ) {
2019-08-31 07:47:15 +00:00
* ptrW = * c ;
}
2019-12-03 22:02:17 +00:00
else
{
uint8_t al = * ( c + 1 ) ;
uint8_t ah = * ( c - 1 ) ;
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
if ( al < = ah ) {
al = ah ;
}
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
uint8_t cl = al ;
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
al = * ( c - 66 ) ;
if ( cl < = al ) {
cl = al ;
}
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
al = * ( c + 66 ) ;
if ( cl < = al ) {
cl = al ;
}
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
al = * ( c + 66 ) ;
if ( cl < = al ) {
cl = al ;
}
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
al = * ( c + 66 ) ;
if ( cl < = al ) {
cl = al ;
}
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
al = * ( c - 65 ) ;
if ( cl < = al ) {
cl = al ;
}
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
al = * ( c - 67 ) ;
if ( cl > al ) {
al = cl ;
}
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
cl = al ;
2019-11-18 22:15:48 +00:00
2019-12-03 22:02:17 +00:00
if ( al < = 159 ) {
* ptrW = 96 ;
2019-08-31 07:47:15 +00:00
}
2019-12-03 22:02:17 +00:00
else
{
if ( ! menu_RandomBit2 ( ) ) {
cl - - ;
}
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
* ptrW = cl ;
}
}
2019-08-31 07:47:15 +00:00
}
c + + ;
ptrW + + ;
}
c + = 2 ;
}
2019-11-18 22:15:48 +00:00
c = & energytile [ 67 ] ;
2019-11-24 15:34:23 +00:00
ptrW = energy2 ;
2019-08-31 07:47:15 +00:00
2019-12-03 22:02:17 +00:00
// copy back to energytile[]
2019-08-31 07:47:15 +00:00
for ( i = 0 ; i < 64 ; i + + )
{
memcpy ( c , ptrW , 64 ) ;
c + = 66 ;
ptrW + = 64 ;
}
2019-11-24 15:34:23 +00:00
ptrW = energy2 ;
2019-11-20 16:21:32 +00:00
2019-12-03 22:02:17 +00:00
// kEnergy2 is 64 x 64
2019-08-31 07:47:15 +00:00
for ( i = 0 ; i < 4096 ; i + + )
{
2019-12-03 22:02:17 +00:00
if ( ptrW [ i ] = = 96 ) {
ptrW [ i ] = 255 ; // -1?
2019-08-31 07:47:15 +00:00
}
}
word_9AB5B - - ;
if ( word_9AB5B < = 0 )
{
int randSize = ( RandomSize ( 5 ) & 0x1F ) + 16 ;
int randSize2 = ( RandomSize ( 5 ) & 0x1F ) + 16 ;
int val = randSize < < 5 ;
val + = randSize ;
val * = 2 ;
val + = randSize2 ;
2019-12-03 22:02:17 +00:00
assert ( val < 4356 ) ;
2019-11-18 22:15:48 +00:00
energytile [ val ] = 175 ;
2019-09-20 17:04:02 +00:00
word_9AB5B = 1 ;
2019-08-31 07:47:15 +00:00
}
2019-11-05 06:15:21 +00:00
tileInvalidate ( kEnergy2 , - 1 , - 1 ) ;
2019-08-31 07:47:15 +00:00
}
2019-08-26 03:59:14 +00:00
}
int menu_NewGameMenu ( )
{
2019-08-31 07:47:15 +00:00
2019-12-13 20:01:14 +00:00
return 0 ;
2019-08-26 03:59:14 +00:00
}
int menu_LoadGameMenu ( )
{
2019-12-13 20:01:14 +00:00
return 0 ;
2019-08-26 03:59:14 +00:00
}
2019-12-02 19:28:02 +00:00
void menu_GameLoad2 ( FILE * fp , bool bIsDemo )
2019-08-26 03:59:14 +00:00
{
2020-08-22 08:03:21 +00:00
fread ( & GameStats , sizeof ( GameStats ) , 1 , fp ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
nPlayerWeapons [ nLocalPlayer ] = GameStats . nWeapons ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
PlayerList [ nLocalPlayer ] . nCurrentWeapon = GameStats . nCurrentWeapon ;
2019-09-20 17:04:02 +00:00
nPlayerClip [ nLocalPlayer ] = GameStats . clip ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int nPistolBullets = PlayerList [ nLocalPlayer ] . nAmmo [ kWeaponPistol ] ;
2019-09-20 17:04:02 +00:00
if ( nPistolBullets > = 6 ) {
2019-08-31 07:47:15 +00:00
nPistolBullets = 6 ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
nPistolClip [ nLocalPlayer ] = nPistolBullets ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
memcpy ( & PlayerList [ nLocalPlayer ] , & GameStats . player , sizeof ( Player ) ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
nPlayerItem [ nLocalPlayer ] = GameStats . items ;
nPlayerLives [ nLocalPlayer ] = GameStats . nLives ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
SetPlayerItem ( nLocalPlayer , nPlayerItem [ nLocalPlayer ] ) ;
CheckClip ( nLocalPlayer ) ;
2019-08-26 03:59:14 +00:00
}
short menu_GameLoad ( int nSlot )
{
2019-08-31 07:47:15 +00:00
memset ( & GameStats , 0 , sizeof ( GameStats ) ) ;
2019-11-20 16:21:32 +00:00
2019-10-29 21:28:14 +00:00
FILE * fp = fopen ( kSaveFileName , " rb " ) ;
2019-09-20 17:04:02 +00:00
if ( fp = = NULL ) {
2019-08-31 07:47:15 +00:00
return 0 ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
fseek ( fp , 125 , SEEK_SET ) ;
fseek ( fp , nSlot * sizeof ( GameStats ) , SEEK_CUR ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
menu_GameLoad2 ( fp ) ;
fclose ( fp ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
return GameStats . nMap ;
2019-08-26 03:59:14 +00:00
}
void menu_GameSave2 ( FILE * fp )
{
2019-08-31 07:47:15 +00:00
memset ( & GameStats , 0 , sizeof ( GameStats ) ) ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
GameStats . nMap = ( uint8_t ) levelnew ;
GameStats . nWeapons = nPlayerWeapons [ nLocalPlayer ] ;
2019-08-31 07:47:15 +00:00
GameStats . nCurrentWeapon = PlayerList [ nLocalPlayer ] . nCurrentWeapon ;
2019-09-20 17:04:02 +00:00
GameStats . clip = nPlayerClip [ nLocalPlayer ] ;
GameStats . items = nPlayerItem [ nLocalPlayer ] ;
GameStats . nLives = nPlayerLives [ nLocalPlayer ] ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
memcpy ( & GameStats . player , & PlayerList [ nLocalPlayer ] , sizeof ( GameStats . player ) ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
fwrite ( & GameStats , sizeof ( GameStats ) , 1 , fp ) ;
2019-08-26 03:59:14 +00:00
}
void menu_GameSave ( int nSaveSlot )
{
2019-09-20 17:04:02 +00:00
if ( nSaveSlot < 0 ) {
2019-08-31 07:47:15 +00:00
return ;
}
2019-10-29 21:28:14 +00:00
FILE * fp = fopen ( kSaveFileName , " rb+ " ) ;
2019-08-31 07:47:15 +00:00
if ( fp ! = NULL )
{
2019-09-20 17:04:02 +00:00
fseek ( fp , 125 , SEEK_SET ) ; // skip save slot names
2019-08-31 07:47:15 +00:00
fseek ( fp , sizeof ( GameStat ) * nSaveSlot , SEEK_CUR ) ;
menu_GameSave2 ( fp ) ;
fclose ( fp ) ;
}
2019-08-26 03:59:14 +00:00
}
2019-09-20 17:04:02 +00:00
# define kMaxCinemaPals 16
const char * cinpalfname [ kMaxCinemaPals ] = {
" 3454.pal " ,
" 3452.pal " ,
" 3449.pal " ,
" 3445.pal " ,
" set.pal " ,
" 3448.pal " ,
" 3446.pal " ,
" hsc1.pal " ,
" 2972.pal " ,
" 2973.pal " ,
" 2974.pal " ,
" 2975.pal " ,
" 2976.pal " ,
" heli.pal " ,
" 2978.pal " ,
" terror.pal "
} ;
2019-08-26 03:59:14 +00:00
void CinemaFadeIn ( )
{
}
2019-11-01 22:05:32 +00:00
short nBeforeScene [ ] = { 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-08-26 03:59:14 +00:00
void CheckBeforeScene ( int nLevel )
{
2019-08-31 07:47:15 +00:00
if ( nLevel = = kMap20 )
{
DoLastLevelCinema ( ) ;
return ;
}
2019-11-01 22:05:32 +00:00
short nScene = nBeforeScene [ nLevel ] ;
if ( nScene )
2019-08-31 07:47:15 +00:00
{
2019-11-01 22:05:32 +00:00
if ( ! nCinemaSeen [ nScene ] )
2019-08-31 07:47:15 +00:00
{
2020-08-22 09:56:54 +00:00
RunCinemaScene ( nScene ) ;
2019-11-01 22:05:32 +00:00
nCinemaSeen [ nScene ] = 1 ;
2019-08-31 07:47:15 +00:00
}
}
2019-08-26 03:59:14 +00:00
}
2020-08-21 20:30:51 +00:00
int SyncScreenJob ( ) ;
2019-08-26 03:59:14 +00:00
int showmap ( short nLevel , short nLevelNew , short nLevelBest )
{
2019-08-31 07:47:15 +00:00
FadeOut ( 0 ) ;
EraseScreen ( overscanindex ) ;
GrabPalette ( ) ;
BlackOut ( ) ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
if ( nLevelNew ! = 11 ) {
2019-08-31 07:47:15 +00:00
CheckBeforeScene ( nLevelNew ) ;
}
2019-08-26 03:59:14 +00:00
2020-08-21 20:30:51 +00:00
int selectedLevel ;
menu_DrawTheMap ( nLevel , nLevelNew , nLevelBest , [ & ] ( int lev ) {
gamestate = GS_LEVEL ;
selectedLevel = lev ;
2020-08-21 20:40:09 +00:00
if ( lev ! = nLevelNew ) STAT_Cancel ( ) ;
2020-08-21 20:30:51 +00:00
} ) ;
SyncScreenJob ( ) ;
2019-09-20 17:04:02 +00:00
if ( selectedLevel = = 11 ) {
2019-08-31 07:47:15 +00:00
CheckBeforeScene ( selectedLevel ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
return selectedLevel ;
2019-08-26 03:59:14 +00:00
}
void DoAfterCinemaScene ( int nLevel )
{
2019-11-27 23:50:29 +00:00
short nAfterScene [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 5 , 0 , 0 , 0 , 0 , 7 , 0 , 0 , 0 , 0 , 6 } ;
2019-08-26 03:59:14 +00:00
2019-11-27 23:50:29 +00:00
if ( nAfterScene [ nLevel ] ) {
2020-08-22 09:56:54 +00:00
RunCinemaScene ( nAfterScene [ nLevel ] ) ;
2019-08-31 07:47:15 +00:00
}
2019-08-26 03:59:14 +00:00
}
void DoFailedFinalScene ( )
{
2019-08-31 07:47:15 +00:00
videoSetViewableArea ( 0 , 0 , xdim - 1 , ydim - 1 ) ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
if ( CDplaying ( ) ) {
2019-08-31 07:47:15 +00:00
fadecdaudio ( ) ;
}
2019-08-26 03:59:14 +00:00
2019-11-28 20:40:17 +00:00
playCDtrack ( 9 , false ) ;
2019-08-31 07:47:15 +00:00
FadeToWhite ( ) ;
2019-08-26 03:59:14 +00:00
2020-08-22 09:56:54 +00:00
RunCinemaScene ( 4 ) ;
2019-08-26 03:59:14 +00:00
}
int FindGString ( const char * str )
{
2019-08-31 07:47:15 +00:00
int i = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
while ( 1 )
{
if ( ! strcmp ( gString [ i ] , str ) )
return i + 1 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
if ( ! strcmp ( gString [ i ] , " EOF " ) )
break ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
i + + ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
return - 1 ;
2019-08-26 03:59:14 +00:00
}
2019-08-31 07:47:15 +00:00
uint8_t CheckForEscape ( )
2019-08-26 03:59:14 +00:00
{
2020-01-01 10:35:47 +00:00
return inputState . CheckAllInput ( ) ;
2019-08-26 03:59:14 +00:00
}
void DoStatic ( int a , int b )
{
2019-09-20 17:04:02 +00:00
RandomLong ( ) ; // nothing done with the result of this?
2019-08-26 03:59:14 +00:00
2019-11-24 12:59:36 +00:00
auto pixels = TileFiles . tileMakeWritable ( kTileLoboLaptop ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int v2 = 160 - a / 2 ;
2019-09-20 17:04:02 +00:00
int v4 = 81 - b / 2 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int var_18 = v2 + a ;
2019-09-20 17:04:02 +00:00
int v5 = v4 + b ;
2019-08-26 03:59:14 +00:00
2019-11-24 12:59:36 +00:00
auto pTile = ( pixels + ( 200 * v2 ) ) + v4 ;
2019-08-26 03:59:14 +00:00
2019-12-02 16:46:57 +00:00
tileInvalidate ( kTileLoboLaptop , - 1 , - 1 ) ;
2019-08-31 07:47:15 +00:00
while ( v2 < var_18 )
{
uint8_t * pStart = pTile ;
pTile + = 200 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int v7 = v4 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
while ( v7 < v5 )
{
* pStart = RandomBit ( ) * 16 ;
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
v7 + + ;
pStart + + ;
}
v2 + + ;
}
2019-08-26 03:59:14 +00:00
2019-11-24 12:59:36 +00:00
tileInvalidate ( kTileLoboLaptop , 0 , 0 ) ;
2019-08-31 07:47:15 +00:00
overwritesprite ( 0 , 0 , kTileLoboLaptop , 0 , 2 , kPalNormal ) ;
videoNextPage ( ) ;
2019-08-26 03:59:14 +00:00
}
void DoLastLevelCinema ( )
{
2019-08-31 07:47:15 +00:00
FadeOut ( 0 ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
videoSetViewableArea ( 0 , 0 , xdim - 1 , ydim - 1 ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
EraseScreen ( - 1 ) ;
RestorePalette ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int nString = FindGString ( " LASTLEVEL " ) ;
2019-08-26 03:59:14 +00:00
2020-02-23 19:40:45 +00:00
PlayLocalSound ( StaticSound [ kSound75 ] , 0 , false , CHANF_UI ) ;
2019-08-26 03:59:14 +00:00
2019-11-24 12:59:36 +00:00
auto pixels = TileFiles . tileMakeWritable ( kTileLoboLaptop ) ;
// uh, what?
//memcpy((void*)waloff[kTileLoboLaptop], (void*)waloff[kTileLoboLaptop], tilesiz[kTileLoboLaptop].x * tilesiz[kTileLoboLaptop].y);
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int var_24 = 16 ;
int var_28 = 12 ;
2019-08-26 03:59:14 +00:00
2019-09-06 05:18:12 +00:00
int nEndTime = ( int ) totalclock + 240 ;
2019-08-26 03:59:14 +00:00
2019-11-24 12:59:36 +00:00
while ( inputState . keyBufferWaiting ( ) ) {
inputState . keyGetChar ( ) ;
2019-08-31 07:47:15 +00:00
}
2019-08-26 03:59:14 +00:00
2019-09-06 05:18:12 +00:00
while ( nEndTime > ( int ) totalclock )
2019-08-31 07:47:15 +00:00
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
if ( var_24 > = 116 )
{
if ( var_28 < 192 )
var_28 + = 20 ;
}
else
{
var_24 + = 20 ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
DoStatic ( var_28 , var_24 ) ;
2019-12-02 14:05:37 +00:00
// WaitVBL();
int time = ( int ) totalclock + 4 ;
while ( ( int ) totalclock < time ) {
HandleAsync ( ) ;
}
2019-08-31 07:47:15 +00:00
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
// loc_3AD75
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
do
2019-12-02 14:05:37 +00:00
{
LABEL_11 :
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-12-02 14:05:37 +00:00
2019-08-31 07:47:15 +00:00
if ( strlen ( gString [ nString ] ) = = 0 )
break ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int esi = nString ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
while ( strlen ( gString [ esi ] ) ! = 0 )
esi + + ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int ebp = esi ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
ebp - = nString ;
2019-12-02 15:15:45 +00:00
ebp < < = 2 ;
ebp = 81 - ebp ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int var_1C = esi - nString ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
// loc_3ADD7
while ( 1 )
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
if ( strlen ( gString [ nString ] ) = = 0 )
break ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int xPos = 70 ;
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
const char * nChar = gString [ nString ] ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
nString + + ;
2019-08-26 03:59:14 +00:00
2019-11-24 12:59:36 +00:00
TileFiles . tileMakeWritable ( kTileLoboLaptop ) ;
2019-08-31 07:47:15 +00:00
while ( * nChar )
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
if ( * nChar ! = ' ' ) {
2020-02-23 19:40:45 +00:00
PlayLocalSound ( StaticSound [ kSound71 ] , 0 , false , CHANF_UI ) ;
2019-08-31 07:47:15 +00:00
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
xPos + = CopyCharToBitmap ( * nChar , kTileLoboLaptop , xPos , ebp ) ;
nChar + + ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
overwritesprite ( 0 , 0 , kTileLoboLaptop , 0 , 2 , kPalNormal ) ;
videoNextPage ( ) ;
2019-08-26 03:59:14 +00:00
2019-12-02 14:05:37 +00:00
// WaitVBL();
int time = ( int ) totalclock + 4 ;
while ( ( int ) totalclock < time ) {
HandleAsync ( ) ;
}
2019-08-31 07:47:15 +00:00
if ( CheckForEscape ( ) )
goto LABEL_28 ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
ebp + = 8 ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
nString + + ;
2019-08-26 03:59:14 +00:00
2020-01-01 10:35:47 +00:00
inputState . ClearAllInput ( ) ;
2019-08-26 03:59:14 +00:00
2019-12-02 14:05:37 +00:00
int v11 = ( kTimerTicks * ( var_1C + 2 ) ) + ( int ) totalclock ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
do
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-26 03:59:14 +00:00
2019-09-06 05:18:12 +00:00
if ( v11 < = ( int ) totalclock )
2019-08-31 07:47:15 +00:00
goto LABEL_11 ;
2019-11-24 12:59:36 +00:00
} while ( ! inputState . keyBufferWaiting ( ) ) ;
2019-11-20 16:21:32 +00:00
}
2019-11-24 12:59:36 +00:00
while ( inputState . keyGetChar ( ) ! = 27 ) ;
2019-08-26 03:59:14 +00:00
LABEL_28 :
2020-02-23 19:40:45 +00:00
PlayLocalSound ( StaticSound [ kSound75 ] , 0 , false , CHANF_UI ) ;
2019-08-26 03:59:14 +00:00
2019-12-02 14:05:37 +00:00
nEndTime = ( int ) totalclock + 240 ;
while ( nEndTime > ( int ) totalclock )
2019-08-31 07:47:15 +00:00
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
DoStatic ( var_28 , var_24 ) ;
2019-08-26 03:59:14 +00:00
2019-12-02 14:05:37 +00:00
// WaitVBL();
int time = ( int ) totalclock + 4 ;
while ( ( int ) totalclock < time ) {
HandleAsync ( ) ;
}
2019-09-20 17:04:02 +00:00
if ( var_28 > 20 ) {
2019-08-31 07:47:15 +00:00
var_28 - = 20 ;
continue ;
}
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
if ( var_24 > 20 ) {
2019-08-31 07:47:15 +00:00
var_24 - = 20 ;
continue ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
break ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
EraseScreen ( - 1 ) ;
tileLoad ( kTileLoboLaptop ) ;
FadeOut ( 0 ) ;
2019-08-26 03:59:14 +00:00
}
2019-12-26 21:00:04 +00:00
static SavegameHelper sgh ( " menu " ,
SA ( nCinemaSeen ) ,
2019-12-27 09:52:40 +00:00
SA ( energytile ) ,
SV ( nButtonColor ) ,
SV ( word_9AB5B ) ,
2019-12-26 21:00:04 +00:00
nullptr ) ;
2019-11-22 23:11:37 +00:00
END_PS_NS