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"
2019-09-20 17:04:02 +00:00
# include "typedefs.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"
# include "keyboard.h"
2019-09-19 19:45:19 +00:00
# include "status.h"
2019-09-20 17:04:02 +00:00
# include "random.h"
# include "sound.h"
# include "names.h"
# include "init.h"
2019-11-24 09:03:19 +00:00
# include "ps_input.h"
2019-09-20 17:04:02 +00:00
# include "gun.h"
2019-08-26 03:59:14 +00:00
# include "view.h"
2019-09-20 17:04:02 +00:00
# include "object.h"
# include "light.h"
# include "cd.h"
# include "cdaudio.h"
2019-11-24 12:59:36 +00:00
# include "input.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 ] ;
// this might be static within the DoPlasma function?
2019-11-24 15:34:23 +00:00
uint8_t * PlasmaBuffer ;
2019-08-26 03:59:14 +00:00
2019-11-18 22:15:48 +00:00
uint8_t energytile [ 66 * 66 ] = { 0 } ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
uint8_t cinemapal [ 768 ] ;
2019-09-20 17:04:02 +00:00
short nLeft [ 50 ] = { 0 } ;
int line ;
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
unsigned int nSmokeBottom ;
unsigned int nSmokeRight ;
unsigned int nSmokeTop ;
unsigned int nSmokeLeft ;
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
int plasma_A [ 5 ] = { 0 } ;
int plasma_B [ 5 ] = { 0 } ;
int plasma_C [ 5 ] = { 0 } ;
2019-08-26 03:59:14 +00:00
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
int zoomsize = 0 ;
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
} ;
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
}
int menu_RandomLong2 ( )
{
2019-08-31 07:47:15 +00:00
int randLong = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
for ( int i = 0 ; i < 32 ; i + + )
{
int val = menu_RandomBit2 ( ) ;
randLong * = 2 ;
randLong | = val ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
return randLong ;
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 + + )
{
if ( * c ! = 96 )
{
2019-09-20 17:04:02 +00:00
if ( * c < = 158 ) {
2019-08-31 07:47:15 +00:00
* ptrW = 96 ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
* ptrW = ( * c ) - 1 ;
}
//continue;
}
else
{
2019-09-20 17:04:02 +00:00
if ( menu_RandomBit2 ( ) ) {
2019-08-31 07:47:15 +00:00
* ptrW = * c ;
c + + ;
ptrW + + ;
continue ;
}
char al = * ( c + 1 ) ;
char ah = * ( c - 1 ) ;
2019-09-20 17:04:02 +00:00
if ( al < = ah ) {
2019-08-31 07:47:15 +00:00
al = ah ;
}
char cl = al ;
2019-09-20 17:04:02 +00:00
al = * ( c - 66 ) ;
2019-08-31 07:47:15 +00:00
2019-09-20 17:04:02 +00:00
if ( cl < = al ) {
2019-08-31 07:47:15 +00:00
cl = al ;
}
al = * ( c + 66 ) ;
2019-09-20 17:04:02 +00:00
if ( cl < = al ) {
2019-08-31 07:47:15 +00:00
cl = al ;
}
al = * ( c + 66 ) ;
2019-09-20 17:04:02 +00:00
if ( cl < = al ) {
2019-08-31 07:47:15 +00:00
cl = al ;
}
al = * ( c + 66 ) ;
2019-09-20 17:04:02 +00:00
if ( cl < = al ) {
2019-08-31 07:47:15 +00:00
cl = al ;
}
al = * ( c - 65 ) ;
2019-09-20 17:04:02 +00:00
if ( cl < = al ) {
2019-08-31 07:47:15 +00:00
cl = al ;
}
al = * ( c - 67 ) ;
2019-09-20 17:04:02 +00:00
if ( cl > al ) {
2019-08-31 07:47:15 +00:00
al = cl ;
}
2019-11-18 22:15:48 +00:00
cl = al ;
2019-09-20 17:04:02 +00:00
if ( al < = 159 ) {
2019-08-31 07:47:15 +00:00
* ptrW = 96 ;
//continue;
}
2019-11-20 16:21:32 +00:00
else
2019-08-31 07:47:15 +00:00
{
if ( ! menu_RandomBit2 ( ) )
{
cl - - ;
}
* ptrW = cl ;
}
}
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
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-08-31 07:47:15 +00:00
for ( i = 0 ; i < 4096 ; i + + )
{
2019-11-18 22:15:48 +00:00
if ( ( * ptrW ) = = 96 ) {
2019-09-20 17:04:02 +00:00
* ptrW = 255 ; // -1?
2019-08-31 07:47:15 +00:00
}
2019-11-20 16:21:32 +00:00
2019-11-18 22:15:48 +00:00
ptrW + + ;
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-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 nPlasmaTile = kTile4092 ;
2019-11-20 18:46:57 +00:00
int nLogoTile ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
# define kPlasmaWidth 320
# define kPlasmaHeight 80
2019-08-26 03:59:14 +00:00
void menu_DoPlasma ( )
{
2019-11-20 18:46:57 +00:00
if ( ! nLogoTile )
nLogoTile = EXHUMED ? kExhumedLogo : kPowerslaveLogo ;
2019-08-26 03:59:14 +00:00
2019-11-24 15:34:23 +00:00
if ( ! PlasmaBuffer )
{
auto pixels = TileFiles . tileCreate ( kTile4092 , kPlasmaWidth , kPlasmaHeight ) ;
memset ( pixels , 96 , kPlasmaWidth * kPlasmaHeight ) ;
2019-08-26 03:59:14 +00:00
2019-11-24 15:34:23 +00:00
PlasmaBuffer = TileFiles . tileCreate ( kTile4093 , kPlasmaWidth , kPlasmaHeight ) ;
memset ( PlasmaBuffer , 96 , kPlasmaWidth * kPlasmaHeight ) ;
2019-08-26 03:59:14 +00:00
2019-11-20 18:46:57 +00:00
nSmokeLeft = 160 - tilesiz [ nLogoTile ] . x / 2 ;
nSmokeRight = nSmokeLeft + tilesiz [ nLogoTile ] . x ;
2019-08-26 03:59:14 +00:00
2019-11-20 18:46:57 +00:00
nSmokeTop = 40 - tilesiz [ nLogoTile ] . y / 2 ;
nSmokeBottom = nSmokeTop + tilesiz [ nLogoTile ] . y - 1 ;
2019-08-26 03:59:14 +00:00
2019-08-31 09:08:38 +00:00
//uint32_t t = time(0) << 16;
//uint32_t t2 = time(0) | t;
2019-11-13 18:28:05 +00:00
nRandom = timerGetTicksU64 ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
for ( int i = 0 ; i < 5 ; i + + )
{
2019-11-20 18:46:57 +00:00
int logoWidth = tilesiz [ nLogoTile ] . x ;
2019-08-31 07:47:15 +00:00
plasma_C [ i ] = ( nSmokeLeft + rand ( ) % logoWidth ) < < 16 ;
plasma_B [ i ] = ( menu_RandomLong2 ( ) % 327680 ) + 0x10000 ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
if ( menu_RandomBit2 ( ) ) {
2019-08-31 07:47:15 +00:00
plasma_B [ i ] = - plasma_B [ i ] ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
plasma_A [ i ] = menu_RandomBit2 ( ) ;
}
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
videoClearScreen ( overscanindex ) ;
2019-08-26 03:59:14 +00:00
2019-11-24 15:34:23 +00:00
uint8_t * plasmapix = const_cast < uint8_t * > ( tilePtr ( nPlasmaTile ) ) ;
uint8_t * r_ebx = plasmapix + 81 ;
const uint8_t * r_edx = tilePtr ( nPlasmaTile ^ 1 ) + 81 ; // flip between value of 4092 and 4093 with xor
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
for ( int x = 0 ; x < kPlasmaWidth - 2 ; x + + )
2019-09-20 17:04:02 +00:00
// for (int x = 1; x < 318; x++)
2019-08-31 07:47:15 +00:00
{
2019-09-20 17:04:02 +00:00
// for (int y = 1; y < 79; y++)
2019-08-31 07:47:15 +00:00
for ( int y = 0 ; y < kPlasmaHeight - 2 ; y + + )
{
uint8_t al = * r_edx ;
if ( al ! = 96 )
{
2019-09-20 17:04:02 +00:00
if ( al > 158 ) {
2019-08-31 07:47:15 +00:00
* r_ebx = al - 1 ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
* r_ebx = 96 ;
}
}
else
{
2019-09-20 17:04:02 +00:00
if ( menu_RandomBit2 ( ) ) {
2019-08-31 07:47:15 +00:00
* r_ebx = * r_edx ;
}
else
{
uint8_t al = * ( r_edx + 1 ) ;
uint8_t cl = * ( r_edx - 1 ) ;
2019-09-20 17:04:02 +00:00
if ( al < = cl ) {
2019-08-31 07:47:15 +00:00
al = cl ;
}
cl = al ;
al = * ( r_edx - 80 ) ;
2019-09-20 17:04:02 +00:00
if ( cl < = al ) {
2019-08-31 07:47:15 +00:00
cl = al ;
}
al = * ( r_edx + 80 ) ;
2019-09-20 17:04:02 +00:00
if ( cl < = al ) {
2019-08-31 07:47:15 +00:00
cl = al ;
}
al = * ( r_edx + 80 ) ;
2019-09-20 17:04:02 +00:00
if ( cl < = al ) {
2019-08-31 07:47:15 +00:00
cl = al ;
}
al = * ( r_edx + 80 ) ;
2019-09-20 17:04:02 +00:00
if ( cl < = al ) {
2019-08-31 07:47:15 +00:00
cl = al ;
}
al = * ( r_edx - 79 ) ;
2019-09-20 17:04:02 +00:00
if ( cl > al ) {
2019-08-31 07:47:15 +00:00
al = cl ;
}
cl = * ( r_edx - 81 ) ;
2019-09-20 17:04:02 +00:00
if ( al < = cl ) {
2019-08-31 07:47:15 +00:00
al = cl ;
}
cl = al ;
2019-09-20 17:04:02 +00:00
if ( al < = 159 ) {
2019-08-31 07:47:15 +00:00
* r_ebx = 96 ;
}
else
{
2019-09-20 17:04:02 +00:00
if ( ! menu_RandomBit2 ( ) ) {
2019-08-31 07:47:15 +00:00
cl - - ;
}
* r_ebx = cl ;
}
}
}
// before restarting inner loop
r_edx + + ;
r_ebx + + ;
}
// before restarting outer loop
r_edx + = 2 ;
r_ebx + = 2 ;
}
2019-11-24 15:34:23 +00:00
auto logopix = tilePtr ( nLogoTile ) ;
2019-08-31 07:47:15 +00:00
for ( int j = 0 ; j < 5 ; j + + )
{
2019-09-20 17:04:02 +00:00
int pB = plasma_B [ j ] ;
int pC = plasma_C [ j ] ;
int badOffset = ( pC > > 16 ) < nSmokeLeft | | ( pC > > 16 ) > = nSmokeRight ;
2019-08-31 07:47:15 +00:00
2019-11-24 15:34:23 +00:00
const uint8_t * ptr3 = ( logopix + ( ( pC > > 16 ) - nSmokeLeft ) * tilesiz [ nLogoTile ] . y ) ;
2019-08-31 07:47:15 +00:00
plasma_C [ j ] + = plasma_B [ j ] ;
2019-08-31 11:44:02 +00:00
if ( ( pB > 0 & & ( plasma_C [ j ] > > 16 ) > = nSmokeRight ) | | ( pB < 0 & & ( plasma_C [ j ] > > 16 ) < = nSmokeLeft ) )
2019-08-31 07:47:15 +00:00
{
2019-09-20 17:04:02 +00:00
int esi = plasma_A [ j ] ;
2019-08-31 07:47:15 +00:00
plasma_B [ j ] = - plasma_B [ j ] ;
plasma_A [ j ] = esi = = 0 ;
}
2019-08-31 15:04:06 +00:00
if ( badOffset )
continue ;
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
unsigned int nSmokeOffset = 0 ;
if ( plasma_A [ j ] )
{
nSmokeOffset = nSmokeTop ;
while ( nSmokeOffset < nSmokeBottom )
{
uint8_t al = * ptr3 ;
2019-09-20 17:04:02 +00:00
if ( al ! = 255 & & al ! = 96 ) {
2019-08-31 07:47:15 +00:00
break ;
}
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
nSmokeOffset + + ;
ptr3 + + ;
}
}
else
{
nSmokeOffset = nSmokeBottom ;
2019-11-20 18:46:57 +00:00
ptr3 + = tilesiz [ nLogoTile ] . y - 1 ;
2019-08-31 07:47:15 +00:00
while ( nSmokeOffset > nSmokeTop )
{
uint8_t al = * ptr3 ;
2019-09-20 17:04:02 +00:00
if ( al ! = 255 & & al ! = 96 ) {
2019-08-31 07:47:15 +00:00
break ;
}
nSmokeOffset - - ;
ptr3 - - ;
}
}
2019-11-24 15:34:23 +00:00
uint8_t * v28 = plasmapix + ( 80 * ( plasma_C [ j ] > > 16 ) ) ;
2019-08-31 07:47:15 +00:00
v28 [ nSmokeOffset ] = 175 ;
}
2019-09-20 17:04:02 +00:00
tileInvalidate ( nPlasmaTile , - 1 , - 1 ) ;
2019-08-31 15:04:06 +00:00
2019-09-20 17:04:02 +00:00
overwritesprite ( 0 , 0 , nPlasmaTile , 0 , 2 , kPalNormal ) ;
2019-11-20 18:46:57 +00:00
overwritesprite ( 160 , 40 , nLogoTile , 0 , 3 , kPalNormal ) ;
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
// flip between tile 4092 and 4093
2019-09-20 17:04:02 +00:00
if ( nPlasmaTile = = kTile4092 ) {
2019-08-31 07:47:15 +00:00
nPlasmaTile = kTile4093 ;
}
2019-09-20 17:04:02 +00:00
else if ( nPlasmaTile = = kTile4093 ) {
2019-08-31 07:47:15 +00:00
nPlasmaTile = kTile4092 ;
}
// draw the fire urn/lamp thingies
2019-09-20 17:04:02 +00:00
int dword_9AB5F = ( ( int ) totalclock / 16 ) & 3 ;
2019-08-31 07:47:15 +00:00
2019-09-20 17:04:02 +00:00
overwritesprite ( 50 , 150 , kTile3512 + dword_9AB5F , 0 , 3 , kPalNormal ) ;
2019-08-26 03:59:14 +00:00
overwritesprite ( 270 , 150 , kTile3512 + ( ( dword_9AB5F + 2 ) & 3 ) , 0 , 3 , kPalNormal ) ;
2019-08-31 07:47:15 +00:00
// TEMP
2019-09-06 05:18:12 +00:00
int time = ( int ) totalclock + 4 ;
2019-09-20 17:04:02 +00:00
while ( ( int ) totalclock < time ) {
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-31 07:47:15 +00:00
}
2019-08-26 03:59:14 +00:00
}
2019-10-14 22:28:17 +00:00
int8_t MapLevelOffsets [ ] = { 0 , 50 , 10 , 20 , 0 , 45 , - 20 , 20 , 5 , 0 , - 10 , 10 , 30 , - 20 , 0 , 20 , 0 , 0 , 0 , 0 } ;
2019-08-26 03:59:14 +00:00
struct TILEFRAMEDEF
{
2019-08-31 07:47:15 +00:00
short nTile ;
short xOffs ;
short yOffs ;
2019-08-26 03:59:14 +00:00
} ;
// 22 bytes
struct MapNamePlaque
{
2019-09-20 17:04:02 +00:00
short xPos ;
short yPos ;
2019-08-31 07:47:15 +00:00
TILEFRAMEDEF tiles [ 2 ] ;
TILEFRAMEDEF text ;
2019-08-26 03:59:14 +00:00
} ;
2019-09-20 17:04:02 +00:00
MapNamePlaque mapNamePlaques [ ] = {
2019-10-14 22:28:17 +00:00
{ 100 , 170 , kTile3376 , 0 , 0 , kTile3377 , 0 , 0 , kTile3411 , 18 , 6 } ,
{ 230 , 10 , kTile3378 , 0 , 0 , kTile3379 , 0 , 0 , kTile3414 , 18 , 6 } , // DENDUR (level 2)
{ 180 , 125 , kTile3380 , 0 , 0 , kTile3381 , 0 , 0 , kTile3417 , 18 , 6 } , // Kalabash
{ 10 , 95 , kTile3382 , 0 , 0 , kTile3383 , 0 , 0 , kTile3420 , 18 , 6 } ,
{ 210 , 160 , kTile3384 , 0 , 0 , kTile3385 , 0 , 0 , kTile3423 , 18 , 6 } ,
{ 10 , 110 , kTile3371 , 0 , 0 , kTile3386 , 0 , 0 , kTile3426 , 18 , 6 } ,
{ 10 , 50 , kTile3387 , 0 , 0 , kTile3388 , 0 , 0 , kTile3429 , 18 , 6 } ,
{ 140 , 0 , kTile3389 , 0 , 0 , kTile3390 , 0 , 0 , kTile3432 , 18 , 6 } ,
{ 30 , 20 , kTile3391 , 0 , 0 , kTile3392 , 0 , 0 , kTile3435 , 18 , 6 } ,
{ 200 , 150 , kTile3409 , 0 , 0 , kTile3410 , 0 , 0 , kTile3418 , 20 , 4 } ,
{ 145 , 170 , kTile3393 , 0 , 0 , kTile3394 , 0 , 0 , kTile3438 , 18 , 6 } ,
{ 80 , 80 , kTile3395 , 0 , 0 , kTile3396 , 0 , 0 , kTile3441 , 18 , 6 } ,
{ 15 , 0 , kTile3397 , 0 , 0 , kTile3398 , 0 , 0 , kTile3444 , 18 , 5 } ,
{ 220 , 35 , kTile3399 , 0 , 0 , kTile3400 , 0 , 0 , kTile3447 , 18 , 6 } ,
{ 190 , 40 , kTile3401 , 0 , 0 , kTile3402 , 0 , 0 , kTile3450 , 18 , 6 } ,
{ 20 , 130 , kTile3403 , 0 , 0 , kTile3404 , 0 , 0 , kTile3453 , 19 , 6 } ,
{ 220 , 160 , kTile3405 , 0 , 0 , kTile3406 , 0 , 0 , kTile3456 , 18 , 6 } ,
{ 20 , 10 , kTile3407 , 0 , 0 , kTile3408 , 0 , 0 , kTile3459 , 18 , 6 } ,
{ 200 , 10 , kTile3412 , 0 , 0 , kTile3413 , 0 , 0 , kTile3419 , 18 , 5 } ,
{ 20 , 10 , kTile3415 , 0 , 0 , kTile3416 , 0 , 0 , kTile3421 , 19 , 4 }
2019-09-20 17:04:02 +00:00
} ;
2019-08-26 03:59:14 +00:00
// 3 different types of fire, each with 4 frames
2019-09-20 17:04:02 +00:00
TILEFRAMEDEF FireTiles [ 3 ] [ 4 ] = {
2019-10-14 22:28:17 +00:00
{ { kTile3484 , 0 , 3 } , { kTile3485 , 0 , 0 } , { kTile3486 , 0 , 3 } , { kTile3487 , 0 , 0 } } ,
{ { kTile3488 , 1 , 0 } , { kTile3489 , 1 , 0 } , { kTile3490 , 0 , 1 } , { kTile3491 , 1 , 1 } } ,
{ { kTile3492 , 1 , 2 } , { kTile3493 , 1 , 0 } , { kTile3494 , 1 , 2 } , { kTile3495 , 1 , 0 } }
2019-09-20 17:04:02 +00:00
} ;
2019-08-26 03:59:14 +00:00
struct Fire
{
2019-08-31 07:47:15 +00:00
short nFireType ;
short xPos ;
short yPos ;
2019-08-26 03:59:14 +00:00
} ;
// 20 bytes
struct MapFire
{
2019-08-31 07:47:15 +00:00
short nFires ;
2019-09-20 17:04:02 +00:00
Fire fires [ 3 ] ;
2019-08-26 03:59:14 +00:00
} ;
/*
level 1 - 3 fires
level 2 - 3 fires
level 3 - 1 fire
*/
2019-09-20 17:04:02 +00:00
MapFire MapLevelFires [ ] = {
3 , { { 0 , 107 , 95 } , { 1 , 58 , 140 } , { 2 , 28 , 38 } } ,
3 , { { 2 , 240 , 0 } , { 0 , 237 , 32 } , { 1 , 200 , 30 } } ,
2 , { { 2 , 250 , 57 } , { 0 , 250 , 43 } , { 2 , 200 , 70 } } ,
2 , { { 1 , 82 , 59 } , { 2 , 84 , 16 } , { 0 , 10 , 95 } } ,
2 , { { 2 , 237 , 50 } , { 1 , 215 , 42 } , { 1 , 210 , 50 } } ,
3 , { { 0 , 40 , 7 } , { 1 , 75 , 6 } , { 2 , 100 , 10 } } ,
3 , { { 0 , 58 , 61 } , { 1 , 85 , 80 } , { 2 , 111 , 63 } } ,
3 , { { 0 , 260 , 65 } , { 1 , 228 , 0 } , { 2 , 259 , 15 } } ,
2 , { { 0 , 81 , 38 } , { 2 , 58 , 38 } , { 2 , 30 , 20 } } ,
3 , { { 0 , 259 , 49 } , { 1 , 248 , 76 } , { 2 , 290 , 65 } } ,
3 , { { 2 , 227 , 66 } , { 0 , 224 , 98 } , { 1 , 277 , 30 } } ,
2 , { { 0 , 100 , 10 } , { 2 , 48 , 76 } , { 2 , 80 , 80 } } ,
3 , { { 0 , 17 , 2 } , { 1 , 29 , 49 } , { 2 , 53 , 28 } } ,
3 , { { 0 , 266 , 42 } , { 1 , 283 , 99 } , { 2 , 243 , 108 } } ,
2 , { { 0 , 238 , 19 } , { 2 , 240 , 92 } , { 2 , 190 , 40 } } ,
2 , { { 0 , 27 , 0 } , { 1 , 70 , 40 } , { 0 , 20 , 130 } } ,
3 , { { 0 , 275 , 65 } , { 1 , 235 , 8 } , { 2 , 274 , 6 } } ,
3 , { { 0 , 75 , 45 } , { 1 , 152 , 105 } , { 2 , 24 , 68 } } ,
3 , { { 0 , 290 , 25 } , { 1 , 225 , 63 } , { 2 , 260 , 110 } } ,
0 , { { 1 , 20 , 10 } , { 1 , 20 , 10 } , { 1 , 20 , 10 } }
} ;
2019-08-26 03:59:14 +00:00
int menu_DrawTheMap ( int nLevel , int nLevelNew , int nLevelBest )
{
2019-08-31 07:47:15 +00:00
int i ;
2019-09-20 17:04:02 +00:00
int x = 0 ;
int var_2C = 0 ;
2019-10-14 22:28:17 +00:00
int nIdleSeconds = 0 ;
2019-08-31 07:47:15 +00:00
int bFadeDone = kFalse ;
2019-08-26 03:59:14 +00:00
2019-09-06 05:18:12 +00:00
int startTime = ( int ) totalclock ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
ClearAllKeys ( ) ;
UnMaskStatus ( ) ;
videoSetViewableArea ( 0 , 0 , xdim - 1 , ydim - 1 ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
// 0-offset the level numbers
nLevel - - ;
nLevelNew - - ;
nLevelBest - - ;
2019-08-26 03:59:14 +00:00
2019-10-14 22:28:17 +00:00
if ( nLevel > = kMap20 ) { // max single player levels
2019-08-31 07:47:15 +00:00
return - 1 ;
}
2019-08-26 03:59:14 +00:00
2019-10-14 22:28:17 +00:00
if ( nLevelNew > = kMap20 ) {
2019-08-31 07:47:15 +00:00
return - 1 ;
}
2019-09-20 17:04:02 +00:00
if ( nLevel < 0 ) {
2019-08-31 07:47:15 +00:00
nLevel = 0 ;
}
2019-09-20 17:04:02 +00:00
if ( nLevelNew < 0 ) {
2019-08-31 07:47:15 +00:00
nLevelNew = nLevel ;
}
2019-10-14 22:28:17 +00:00
int curYPos = MapLevelOffsets [ nLevel ] + ( 200 * ( nLevel / 2 ) ) ;
int destYPos = MapLevelOffsets [ nLevelNew ] + ( 200 * ( nLevelNew / 2 ) ) ;
2019-08-31 07:47:15 +00:00
2019-10-14 22:28:17 +00:00
if ( curYPos < destYPos ) {
2019-08-31 07:47:15 +00:00
var_2C = 2 ;
}
2019-10-14 22:28:17 +00:00
if ( curYPos > destYPos ) {
2019-08-31 07:47:15 +00:00
var_2C = - 2 ;
}
2019-10-14 22:28:17 +00:00
int runtimer = ( int ) totalclock ;
// User has 12 seconds to do something on the map screen before loading the current level
while ( nIdleSeconds < 12 )
2019-08-31 07:47:15 +00:00
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-31 07:47:15 +00:00
2019-09-06 05:18:12 +00:00
if ( ( ( int ) totalclock - startTime ) / kTimerTicks )
2019-08-31 07:47:15 +00:00
{
2019-10-14 22:28:17 +00:00
nIdleSeconds + + ;
2019-09-06 05:18:12 +00:00
startTime = ( int ) totalclock ;
2019-08-31 07:47:15 +00:00
}
2019-10-14 22:28:17 +00:00
int moveTimer = ( int ) totalclock ;
2019-08-31 07:47:15 +00:00
2019-10-14 22:28:17 +00:00
int tileY = curYPos ;
2019-08-31 07:47:15 +00:00
// Draw the background screens
for ( i = 0 ; i < 10 ; i + + )
{
overwritesprite ( x , tileY , kTile3353 + i , 0 , 2 , kPalNormal ) ;
tileY - = 200 ;
}
// for each level - drawing the 'level completed' on-fire smoke markers
for ( i = 0 ; i < kMap20 ; i + + )
{
int screenY = ( i > > 1 ) * - 200 ;
2019-09-20 17:04:02 +00:00
if ( nLevelBest > = i ) // check if the player has finished this level
2019-08-31 07:47:15 +00:00
{
for ( int j = 0 ; j < MapLevelFires [ i ] . nFires ; j + + )
{
2019-09-06 05:18:12 +00:00
int nFireFrame = ( ( ( int ) totalclock > > 4 ) & 3 ) ;
2019-08-31 07:47:15 +00:00
assert ( nFireFrame > = 0 & & nFireFrame < 4 ) ;
int nFireType = MapLevelFires [ i ] . fires [ j ] . nFireType ;
assert ( nFireType > = 0 & & nFireType < 3 ) ;
2019-09-20 17:04:02 +00:00
int nTile = FireTiles [ nFireType ] [ nFireFrame ] . nTile ;
2019-08-31 07:47:15 +00:00
int smokeX = MapLevelFires [ i ] . fires [ j ] . xPos + FireTiles [ nFireType ] [ nFireFrame ] . xOffs ;
2019-10-14 22:28:17 +00:00
int smokeY = MapLevelFires [ i ] . fires [ j ] . yPos + FireTiles [ nFireType ] [ nFireFrame ] . yOffs + curYPos + screenY ;
2019-08-31 07:47:15 +00:00
overwritesprite ( smokeX , smokeY , nTile , 0 , 2 , kPalNormal ) ;
}
}
2019-09-06 05:18:12 +00:00
int t = ( ( ( ( int ) totalclock & 16 ) > > 4 ) ) ;
2019-08-31 07:47:15 +00:00
int nTile = mapNamePlaques [ i ] . tiles [ t ] . nTile ;
int nameX = mapNamePlaques [ i ] . xPos + mapNamePlaques [ i ] . tiles [ t ] . xOffs ;
2019-10-14 22:28:17 +00:00
int nameY = mapNamePlaques [ i ] . yPos + mapNamePlaques [ i ] . tiles [ t ] . yOffs + curYPos + screenY ;
2019-08-31 07:47:15 +00:00
// Draw level name plaque
overwritesprite ( nameX , nameY , nTile , 0 , 2 , kPalNormal ) ;
int8_t shade = 96 ;
if ( nLevelNew = = i )
{
2019-09-06 05:18:12 +00:00
shade = ( Sin ( 16 * ( int ) totalclock ) + 31 ) > > 8 ;
2019-08-31 07:47:15 +00:00
}
else if ( nLevelBest > = i )
{
shade = 31 ;
}
2019-10-14 22:28:17 +00:00
int textY = mapNamePlaques [ i ] . yPos + mapNamePlaques [ i ] . text . yOffs + curYPos + screenY ;
2019-08-31 07:47:15 +00:00
int textX = mapNamePlaques [ i ] . xPos + mapNamePlaques [ i ] . text . xOffs ;
2019-09-20 17:04:02 +00:00
nTile = mapNamePlaques [ i ] . text . nTile ;
2019-08-31 07:47:15 +00:00
// draw the text, alternating between red and black
overwritesprite ( textX , textY , nTile , shade , 2 , kPalNormal ) ;
}
videoNextPage ( ) ;
if ( ! bFadeDone )
{
bFadeDone = kTrue ;
FadeIn ( ) ;
2019-10-14 22:28:17 +00:00
moveTimer = ( int ) totalclock ;
2019-08-31 07:47:15 +00:00
}
2019-10-14 22:28:17 +00:00
if ( curYPos = = destYPos )
2019-08-31 07:47:15 +00:00
{
2019-11-24 12:59:36 +00:00
if ( I_MenuUp ( ) )
2019-08-31 07:47:15 +00:00
{
2019-11-24 12:59:36 +00:00
I_MenuUpClear ( ) ;
2019-08-31 07:47:15 +00:00
if ( nLevelNew < = nLevelBest )
{
nLevelNew + + ;
2019-10-14 22:28:17 +00:00
assert ( nLevelNew < 20 ) ;
2019-08-31 07:47:15 +00:00
2019-10-14 22:28:17 +00:00
destYPos = MapLevelOffsets [ nLevelNew ] + ( 200 * ( nLevelNew / 2 ) ) ;
2019-08-31 07:47:15 +00:00
2019-10-14 22:28:17 +00:00
if ( curYPos < = destYPos ) {
2019-08-31 07:47:15 +00:00
var_2C = 2 ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
var_2C = - 2 ;
}
2019-10-14 22:28:17 +00:00
nIdleSeconds = 0 ;
2019-08-31 07:47:15 +00:00
}
}
2019-11-24 12:59:36 +00:00
if ( I_MenuDown ( ) )
{
I_MenuDownClear ( ) ;
2019-08-31 07:47:15 +00:00
if ( nLevelNew > 0 )
{
nLevelNew - - ;
2019-10-14 22:28:17 +00:00
assert ( nLevelNew > = 0 ) ;
2019-08-31 07:47:15 +00:00
2019-10-14 22:28:17 +00:00
destYPos = MapLevelOffsets [ nLevelNew ] + ( 200 * ( nLevelNew / 2 ) ) ;
2019-08-31 07:47:15 +00:00
2019-10-14 22:28:17 +00:00
if ( curYPos < = destYPos ) {
2019-08-31 07:47:15 +00:00
var_2C = 2 ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
var_2C = - 2 ;
}
2019-10-14 22:28:17 +00:00
nIdleSeconds = 0 ;
2019-08-31 07:47:15 +00:00
}
}
2019-11-24 12:59:36 +00:00
if ( I_AdvanceTrigger ( ) )
2019-08-31 07:47:15 +00:00
{
2019-11-24 12:59:36 +00:00
I_AdvanceTriggerClear ( ) ;
2019-08-31 07:47:15 +00:00
return nLevelNew + 1 ;
}
}
else
{
2019-10-14 22:28:17 +00:00
// scroll the map every couple of ms
if ( totalclock - runtimer > = ( kTimerTicks / 32 ) ) {
curYPos + = var_2C ;
runtimer = ( int ) totalclock ;
}
//curYPos += var_2C * (((int)totalclock - moveTimer) / 2);
2019-08-31 07:47:15 +00:00
2019-11-24 12:59:36 +00:00
if ( I_AdvanceTrigger ( ) )
{
I_AdvanceTriggerClear ( ) ;
if ( var_2C < 8 ) {
2019-08-31 07:47:15 +00:00
var_2C * = 2 ;
}
}
2019-10-14 22:28:17 +00:00
if ( curYPos > destYPos & & var_2C > 0 ) {
curYPos = destYPos ;
2019-08-31 07:47:15 +00:00
}
2019-10-14 22:28:17 +00:00
if ( curYPos < destYPos & & var_2C < 0 ) {
curYPos = destYPos ;
2019-08-31 07:47:15 +00:00
}
2019-10-14 22:28:17 +00:00
nIdleSeconds = 0 ;
2019-08-31 07:47:15 +00:00
}
}
MySetView ( nViewLeft , nViewTop , nViewRight , nViewBottom ) ;
return nLevelNew + 1 ;
2019-08-26 03:59:14 +00:00
}
void menu_AdjustVolume ( )
{
2019-08-31 07:47:15 +00:00
int nOption = 1 ;
2019-09-20 17:04:02 +00:00
int var_8 = 0 ;
2019-08-31 07:47:15 +00:00
while ( 1 )
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-31 07:47:15 +00:00
menu_DoPlasma ( ) ;
2019-09-06 05:18:12 +00:00
overwritesprite ( 80 , 50 , kMenuMusicTile , ( Sin ( ( int ) totalclock < < 4 ) > > 9 ) * ( nOption = = 0 ) , 2 , kPalNormal ) ;
2019-08-31 07:47:15 +00:00
overwritesprite ( 55 , 75 , kMenuBlankTitleTile , 0 , 2 , kPalNormal ) ;
2019-09-20 17:04:02 +00:00
seq_DrawGunSequence (
SeqOffsets [ kSeqSlider ] , // eax
gMusicVolume % 3 , // pick one of 3 frames?
( gMusicVolume > > 1 ) - 93 , // ebx. must be x???
- 22 ,
0 ,
0 ) ;
2019-08-31 07:47:15 +00:00
2019-09-06 05:18:12 +00:00
overwritesprite ( 80 , 110 , kMenuSoundFxTile , ( Sin ( ( int ) totalclock < < 4 ) > > 9 ) * ( nOption = = 1 ) , 2 , kPalNormal ) ;
2019-08-31 07:47:15 +00:00
overwritesprite ( 55 , 135 , kMenuBlankTitleTile , 0 , 2 , kPalNormal ) ;
2019-09-20 17:04:02 +00:00
seq_DrawGunSequence (
2019-11-20 16:21:32 +00:00
SeqOffsets [ kSeqSlider ] ,
gFXVolume % 3 ,
2019-09-20 17:04:02 +00:00
( gFXVolume / 2 ) - 93 ,
38 ,
0 ,
0 ) ;
2019-08-31 07:47:15 +00:00
int y = ( 60 * nOption ) + 38 ;
2019-09-20 17:04:02 +00:00
overwritesprite ( 60 , y , kMenuCursorTile , 0 , 2 , kPalNormal ) ;
2019-08-31 07:47:15 +00:00
overwritesprite ( 206 , y , kMenuCursorTile , 0 , 10 , kPalNormal ) ;
videoNextPage ( ) ;
2019-11-24 12:59:36 +00:00
if ( I_AdvanceTrigger ( ) )
{
I_AdvanceTriggerClear ( ) ;
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
2019-08-31 07:47:15 +00:00
return ;
}
2019-11-24 12:59:36 +00:00
if ( I_MenuUp ( ) )
2019-08-31 07:47:15 +00:00
{
2019-11-24 12:59:36 +00:00
I_MenuUpClear ( ) ;
2019-08-31 07:47:15 +00:00
if ( nOption > 0 )
{
nOption - - ;
PlayLocalSound ( StaticSound [ kSound35 ] , 0 ) ;
}
}
2019-11-24 12:59:36 +00:00
if ( I_MenuDown ( ) )
{
I_MenuDownClear ( ) ;
if ( nOption < 1 )
2019-08-31 07:47:15 +00:00
{
nOption + + ;
PlayLocalSound ( StaticSound [ kSound35 ] , 0 ) ;
}
}
2019-09-20 17:04:02 +00:00
if ( ( int ) totalclock < = var_8 ) {
2019-08-31 07:47:15 +00:00
continue ;
}
2019-09-06 05:18:12 +00:00
var_8 = ( int ) totalclock + 5 ;
2019-08-31 07:47:15 +00:00
2019-11-24 12:59:36 +00:00
if ( I_MenuLeft ( ) )
{
I_MenuLeftClear ( ) ;
switch ( nOption )
2019-08-31 07:47:15 +00:00
{
case 0 :
{
2019-09-20 17:04:02 +00:00
if ( gMusicVolume > 3 ) {
2019-08-31 07:47:15 +00:00
gMusicVolume - = 4 ;
}
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
// TODO SetMusicVolume();
2019-11-24 20:32:07 +00:00
setCDaudiovolume ( gMusicVolume ) ;
2019-08-31 07:47:15 +00:00
continue ;
}
case 1 :
{
2019-09-20 17:04:02 +00:00
if ( gFXVolume > 3 ) {
2019-08-31 07:47:15 +00:00
gFXVolume - = 4 ;
}
2019-09-20 17:04:02 +00:00
if ( LocalSoundPlaying ( ) ) {
2019-08-31 07:47:15 +00:00
UpdateLocalSound ( ) ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
PlayLocalSound ( StaticSound [ kSound23 ] , 0 ) ;
}
continue ;
}
}
}
2019-11-24 12:59:36 +00:00
if ( I_MenuRight ( ) )
{
I_MenuRightClear ( ) ;
switch ( nOption )
2019-08-31 07:47:15 +00:00
{
case 0 :
{
2019-09-20 17:04:02 +00:00
if ( gMusicVolume < 252 ) {
2019-08-31 07:47:15 +00:00
gMusicVolume + = 4 ;
}
2019-08-26 03:59:14 +00:00
2019-11-24 20:32:07 +00:00
// SetMusicVolume();
setCDaudiovolume ( gMusicVolume ) ;
2019-08-31 07:47:15 +00:00
continue ;
}
case 1 :
{
2019-09-20 17:04:02 +00:00
if ( gFXVolume < 252 ) {
2019-08-31 07:47:15 +00:00
gFXVolume + = 4 ;
}
2019-09-20 17:04:02 +00:00
if ( LocalSoundPlaying ( ) ) {
2019-08-31 07:47:15 +00:00
UpdateLocalSound ( ) ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
PlayLocalSound ( StaticSound [ kSound23 ] , 0 ) ;
}
continue ;
}
}
}
2019-09-20 17:04:02 +00:00
if ( GetLocalSound ( ) ! = 23 ) {
2019-08-31 07:47:15 +00:00
continue ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
StopLocalSound ( ) ;
}
}
2019-08-26 03:59:14 +00:00
}
int menu_NewGameMenu ( )
{
2019-08-31 07:47:15 +00:00
const char endMark = 0xF ;
2019-09-20 17:04:02 +00:00
char nameList [ 5 ] [ 25 ] ;
int nNameLen = sizeof ( nameList ) ;
2019-08-31 07:47:15 +00:00
2019-09-20 17:04:02 +00:00
int nNameOffset = 0 ; // char index into slot name string
2019-08-31 07:47:15 +00:00
2019-08-31 16:05:11 +00:00
//int nPages = numpages;
2019-08-31 07:47:15 +00:00
int arg_3E = tilesiz [ kMenuBlankTitleTile ] . x - 10 ;
int nSlot = 0 ;
2019-10-29 21:28:14 +00:00
FILE * fp = fopen ( kSaveFileName , " rb " ) ;
2019-08-31 07:47:15 +00:00
if ( fp = = NULL )
{
memset ( nameList , 0 , nNameLen ) ;
memset ( & GameStats , 0 , sizeof ( GameStat ) ) ;
2019-10-29 21:28:14 +00:00
fp = fopen ( kSaveFileName , " wb+ " ) ;
2019-08-31 07:47:15 +00:00
if ( fp ! = NULL )
{
fwrite ( nameList , nNameLen , 1 , fp ) ;
2019-09-20 17:04:02 +00:00
fwrite ( & GameStats , 75 , 1 , fp ) ; //fwrite(&GameStats, 75, 5, fp); // CHECKME! the size
2019-08-31 07:47:15 +00:00
fwrite ( & endMark , sizeof ( endMark ) , 1 , fp ) ;
fclose ( fp ) ;
}
}
else
{
int nRead = fread ( nameList , 1 , nNameLen , fp ) ;
if ( nRead ! = nNameLen )
{
memset ( nameList , 0 , nNameLen ) ;
}
fclose ( fp ) ;
}
// while (1)
{
ClearAllKeys ( ) ;
while ( 1 )
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-31 07:47:15 +00:00
menu_DoPlasma ( ) ;
int y = ( tilesiz [ kMenuBlankTitleTile ] . y - ( tilesiz [ kMenuBlankTitleTile ] . y / 2 ) / 2 ) + 65 ;
rotatesprite ( 160 < < 16 , y < < 16 , 0x10000 , 0 , kMenuNewGameTile , 0 , 0 , 2 , 0 , 0 , xdim , ydim ) ;
int edi = 0 ;
int arg_4A = 90 ;
int arg_4E = 98 ;
// Loop #3
for ( int i = 0 ; i < 5 ; i + + )
{
2019-09-06 05:18:12 +00:00
int8_t shade = ( ( Sin ( ( int ) totalclock < < 4 ) > > 9 ) * ( i = = nSlot ) ) + ( ( i ! = nSlot ) * 31 ) ;
2019-08-31 07:47:15 +00:00
overwritesprite ( 55 , arg_4A , kMenuBlankTitleTile , shade , 2 , kPalNormal ) ;
myprintext ( 63 , arg_4E , nameList [ i ] , 0 ) ;
arg_4E + = 22 ;
arg_4A + = 22 ;
edi + + ;
}
edi = nSlot * 22 ;
// draw selection markers
overwritesprite ( 35 , edi + 78 , kMenuCursorTile , 0 , 2 , kPalNormal ) ;
overwritesprite ( 233 , edi + 78 , kMenuCursorTile , 0 , 10 , kPalNormal ) ;
videoNextPage ( ) ;
2019-08-31 16:05:11 +00:00
//nPages--;
//if (nPages > 0) {
// continue;
//}
2019-08-31 07:47:15 +00:00
2019-11-24 12:59:36 +00:00
if ( I_EscapeTrigger ( ) )
2019-08-31 07:47:15 +00:00
{
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
2019-11-24 12:59:36 +00:00
I_EscapeTriggerClear ( ) ;
2019-08-31 07:47:15 +00:00
return - 1 ;
}
2019-11-24 12:59:36 +00:00
if ( I_MenuUp ( ) )
{
I_MenuUpClear ( ) ;
PlayLocalSound ( StaticSound [ kSound35 ] , 0 ) ;
2019-09-20 17:04:02 +00:00
if ( nSlot < = 0 ) {
2019-08-31 07:47:15 +00:00
nSlot = 4 ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
nSlot - - ;
}
ClearAllKeys ( ) ;
continue ;
}
2019-11-24 12:59:36 +00:00
if ( I_MenuDown ( ) )
{
I_MenuDownClear ( ) ;
PlayLocalSound ( StaticSound [ kSound35 ] , 0 ) ;
2019-09-20 17:04:02 +00:00
if ( nSlot > = 4 ) {
2019-08-31 07:47:15 +00:00
nSlot = 0 ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
nSlot + + ;
}
2019-11-24 12:59:36 +00:00
inputState . ClearAllKeyStatus ( ) ;
2019-08-31 07:47:15 +00:00
continue ;
}
2019-11-24 12:59:36 +00:00
if ( I_AdvanceTrigger ( ) | | inputState . keyBufferWaiting ( ) )
2019-08-31 07:47:15 +00:00
{
break ;
}
}
}
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
2019-11-24 12:59:36 +00:00
if ( ! inputState . keyBufferWaiting ( ) ) {
inputState . ClearAllKeyStatus ( ) ;
2019-08-31 07:47:15 +00:00
}
2019-09-20 17:04:02 +00:00
char * pName = nameList [ nSlot ] ;
int nNameLength = strlen ( pName ) ;
2019-08-31 07:47:15 +00:00
memset ( pName , 0 , nNameLength ) ;
menu_DoPlasma ( ) ;
overwritesprite ( 55 , ( nSlot * 22 ) + 90 , kMenuBlankTitleTile , 0 , 2 , kPalNormal ) ;
int arg_5A = 90 ;
int arg_52 = 98 ;
for ( int i = 0 ; i < 5 ; i + + )
{
overwritesprite ( 55 , arg_5A , kMenuBlankTitleTile , ( i ! = nSlot ) * 31 , 2 , kPalNormal ) ;
myprintext ( 63 , arg_52 , nameList [ i ] , 0 ) ;
arg_52 + = 22 ;
arg_5A + = 22 ;
}
int x = 35 ;
int y = ( nSlot * 22 ) + 78 ;
while ( 1 )
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-31 07:47:15 +00:00
overwritesprite ( x , y , kMenuCursorTile , 0 , 2 , kPalNormal ) ;
overwritesprite ( 233 , y , kMenuCursorTile , 0 , 10 , kPalNormal ) ;
videoNextPage ( ) ;
char ch = 0 ;
2019-09-20 17:23:47 +00:00
check_keys :
2019-11-24 12:59:36 +00:00
if ( inputState . keyBufferWaiting ( ) )
2019-08-31 07:47:15 +00:00
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-09-20 17:04:02 +00:00
2019-11-24 12:59:36 +00:00
ch = inputState . keyGetChar ( ) ;
2019-09-20 17:23:47 +00:00
if ( ! ch )
{
2019-11-24 12:59:36 +00:00
inputState . keyGetChar ( ) ; //???
2019-09-20 17:23:47 +00:00
goto check_keys ;
2019-08-31 07:47:15 +00:00
}
2019-09-20 17:23:47 +00:00
// handle key input
if ( ch = = asc_Enter )
{
// loc_39ACA:
nameList [ nSlot ] [ nNameOffset ] = 0 ;
2019-08-31 07:47:15 +00:00
2019-09-20 17:23:47 +00:00
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
2019-11-24 12:59:36 +00:00
inputState . ClearKeyStatus ( sc_Return ) ;
2019-08-31 07:47:15 +00:00
2019-09-20 17:23:47 +00:00
if ( nameList [ nSlot ] [ 0 ] = = 0 ) {
return - 1 ;
}
2019-08-31 07:47:15 +00:00
2019-09-20 17:23:47 +00:00
if ( nNameLength ) // does the save slot already exist?
{
menu_DoPlasma ( ) ;
if ( Query ( 2 , 4 , " Overwrite existing game? " , " Y/N " , ' Y ' , 13 , ' N ' , 27 ) > = 2 ) {
return - 1 ;
}
}
2019-08-31 07:47:15 +00:00
2019-10-29 21:28:14 +00:00
FILE * fp = fopen ( kSaveFileName , " rb+ " ) ;
2019-09-20 17:23:47 +00:00
if ( fp = = NULL ) {
2019-09-19 19:45:19 +00:00
return - 1 ;
2019-08-31 07:47:15 +00:00
}
2019-09-20 17:23:47 +00:00
memset ( & GameStats , 0 , sizeof ( GameStat ) ) ;
GameStats . nWeapons = 1 ;
GameStats . nMap = 1 ;
2019-09-19 19:45:19 +00:00
2019-09-20 17:23:47 +00:00
fwrite ( nameList , sizeof ( nameList ) , 1 , fp ) ;
fseek ( fp , sizeof ( nameList ) , SEEK_SET ) ;
fseek ( fp , nSlot * sizeof ( GameStat ) , SEEK_CUR ) ;
fwrite ( & GameStats , sizeof ( GameStat ) , 1 , fp ) ;
fclose ( fp ) ;
return nSlot ;
}
else
{
// Enter wasn't pressed
PlayLocalSound ( 4 , 0 ) ; // ??
2019-09-19 19:45:19 +00:00
2019-09-20 17:23:47 +00:00
if ( ch = = asc_BackSpace )
{
nameList [ nSlot ] [ nNameOffset ] = 0 ;
2019-08-31 07:47:15 +00:00
2019-09-20 17:23:47 +00:00
if ( nNameOffset > 0 ) {
nNameOffset - - ;
}
2019-09-20 17:04:02 +00:00
2019-09-20 17:23:47 +00:00
nameList [ nSlot ] [ nNameOffset ] = 0 ;
2019-09-19 19:45:19 +00:00
}
2019-09-20 17:23:47 +00:00
else if ( ch = = asc_Escape )
{
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
2019-11-24 12:59:36 +00:00
inputState . ClearAllKeyStatus ( ) ;
inputState . keyFlushChars ( ) ;
2019-09-20 17:23:47 +00:00
return - 1 ;
}
2019-11-20 16:21:32 +00:00
else
2019-09-19 19:45:19 +00:00
{
2019-09-20 17:23:47 +00:00
// check if a slot name is being typed
if ( ( ch > = ' 0 ' & & ch < = ' 9 ' )
| | ( ch > = ' A ' & & ch < = ' Z ' )
| | ( ch > = ' a ' & & ch < = ' z ' )
2019-11-20 16:21:32 +00:00
| | ( ch = = ' ' ) )
2019-09-19 19:45:19 +00:00
{
2019-09-20 17:23:47 +00:00
ch = toupper ( ch ) ;
if ( nNameOffset < 24 ) // n chars per slot name
2019-08-31 07:47:15 +00:00
{
2019-09-20 17:23:47 +00:00
nameList [ nSlot ] [ nNameOffset ] = ch ;
nNameOffset + + ;
nameList [ nSlot ] [ nNameOffset ] = ' \0 ' ; // null terminate in the new offset
int nLen = MyGetStringWidth ( nameList [ nSlot ] ) ;
if ( nLen > arg_3E )
{
nNameOffset - - ;
nameList [ nSlot ] [ nNameOffset ] = ' \0 ' ;
}
2019-08-31 07:47:15 +00:00
}
}
}
}
2019-09-20 17:23:47 +00:00
}
2019-08-31 07:47:15 +00:00
2019-09-20 17:23:47 +00:00
// loc_399FD:
menu_DoPlasma ( ) ;
2019-08-31 07:47:15 +00:00
2019-09-20 17:23:47 +00:00
int arg_5E = ( ( int ) totalclock / 30 ) & 1 ;
2019-08-31 07:47:15 +00:00
2019-09-20 17:23:47 +00:00
int y = 90 ;
int arg_42 = 98 ;
2019-09-19 19:45:19 +00:00
2019-09-20 17:23:47 +00:00
for ( int i = 0 ; i < 5 ; i + + )
{
overwritesprite ( 55 , y , kMenuBlankTitleTile , ( i ! = nSlot ) * 31 , 2 , kPalNormal ) ;
int nTextWidth = myprintext ( 63 , arg_42 , nameList [ i ] , 0 ) ;
2019-09-20 17:04:02 +00:00
2019-09-20 17:23:47 +00:00
// flash a full-stop to show the current typing position
if ( arg_5E ! = 0 & & nSlot = = i )
{
myprintext ( nTextWidth , arg_42 , " . " , 0 ) ;
2019-09-20 17:04:02 +00:00
}
2019-09-20 17:23:47 +00:00
arg_42 + = 22 ;
y + = 22 ;
2019-08-31 07:47:15 +00:00
}
}
2019-08-26 03:59:14 +00:00
}
int menu_LoadGameMenu ( )
{
2019-08-31 07:47:15 +00:00
char nameList [ 5 ] [ 25 ] ;
int nSlot = 0 ;
2019-10-29 21:28:14 +00:00
FILE * fp = fopen ( kSaveFileName , " rb " ) ;
2019-08-31 07:47:15 +00:00
if ( fp = = NULL )
{
memset ( nameList , 0 , sizeof ( nameList ) ) ;
}
else
{
fread ( nameList , sizeof ( nameList ) , 1 , fp ) ;
fclose ( fp ) ;
}
while ( 1 )
{
menu_DoPlasma ( ) ;
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-31 07:47:15 +00:00
overwritesprite ( 80 , 65 , kMenuLoadGameTile , 0 , 2 , kPalNormal ) ;
int spriteY = 90 ;
2019-09-20 17:04:02 +00:00
int textY = 98 ;
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
for ( int i = 0 ; i < kMaxSaveSlots ; i + + )
{
2019-11-28 00:22:49 +00:00
int8_t shade = ( ( Sin ( ( int ) totalclock < < 4 ) > > 9 ) * ( i = = nSlot ) ) + ( ( i ! = nSlot ) * 31 ) ;
overwritesprite ( 55 , spriteY , kMenuBlankTitleTile , shade , 2 , kPalNormal ) ;
2019-08-31 07:47:15 +00:00
myprintext ( 63 , textY , nameList [ i ] , 0 ) ;
textY + = 22 ;
spriteY + = 22 ;
}
int y = ( nSlot * 22 ) + 78 ;
2019-09-20 17:04:02 +00:00
overwritesprite ( 35 , y , kMenuCursorTile , 0 , 2 , kPalNormal ) ;
2019-08-31 07:47:15 +00:00
overwritesprite ( 233 , y , kMenuCursorTile , 0 , 10 , kPalNormal ) ;
videoNextPage ( ) ;
2019-11-24 12:59:36 +00:00
if ( I_EscapeTrigger ( ) )
2019-08-31 07:47:15 +00:00
{
2019-11-24 12:59:36 +00:00
I_EscapeTriggerClear ( ) ;
2019-08-31 07:47:15 +00:00
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
return - 1 ;
}
2019-11-24 12:59:36 +00:00
if ( I_MenuUp ( ) )
2019-08-31 07:47:15 +00:00
{
2019-11-24 12:59:36 +00:00
I_MenuUpClear ( ) ;
2019-08-31 07:47:15 +00:00
PlayLocalSound ( StaticSound [ kSound35 ] , 0 ) ;
2019-09-20 17:04:02 +00:00
if ( nSlot > 0 ) {
2019-08-31 07:47:15 +00:00
nSlot - - ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
nSlot = kMaxSaveSlots - 1 ;
}
}
2019-11-24 12:59:36 +00:00
if ( I_MenuDown ( ) )
{
I_MenuDownClear ( ) ;
PlayLocalSound ( StaticSound [ kSound35 ] , 0 ) ;
2019-09-20 17:04:02 +00:00
if ( nSlot < kMaxSaveSlots - 1 ) {
2019-08-31 07:47:15 +00:00
nSlot + + ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
nSlot = 0 ;
}
}
2019-11-24 12:59:36 +00:00
if ( ! I_AdvanceTrigger ( ) ) {
2019-08-31 07:47:15 +00:00
continue ;
}
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
2019-11-24 12:59:36 +00:00
I_AdvanceTriggerClear ( ) ;
inputState . ClearAllKeyStatus ( ) ;
inputState . keyFlushChars ( ) ;
2019-08-31 07:47:15 +00:00
if ( nameList [ nSlot ] [ 0 ] ! = ' \0 ' )
{
PlayLocalSound ( StaticSound [ 33 ] , 0 ) ;
return nSlot ;
}
PlayLocalSound ( 4 , 0 ) ;
}
2019-08-26 03:59:14 +00:00
}
2019-09-20 17:04:02 +00:00
void menu_ResetKeyTimer ( )
{
keytimer = ( int ) totalclock + 2400 ;
}
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
{
2019-12-02 19:28:02 +00:00
if ( bIsDemo )
{
demo_header header ;
fread ( & header , 1 , sizeof ( demo_header ) , fp ) ;
GameStats . nMap = header . nMap ;
GameStats . nWeapons = header . nWeapons ;
GameStats . nCurrentWeapon = header . nCurrentWeapon ;
GameStats . clip = header . clip ;
GameStats . items = header . items ;
GameStats . player . nHealth = header . nHealth ;
GameStats . player . field_2 = header . field_2 ;
GameStats . player . nAction = header . nAction ;
GameStats . player . nSprite = header . nSprite ;
GameStats . player . bIsMummified = header . bIsMummified ;
GameStats . player . someNetVal = header . someNetVal ;
GameStats . player . invincibility = header . invincibility ;
GameStats . player . nAir = header . nAir ;
GameStats . player . nSeq = header . nSeq ;
GameStats . player . nMaskAmount = header . nMaskAmount ;
GameStats . player . keys = header . keys ;
GameStats . player . nMagic = header . nMagic ;
Bmemcpy ( GameStats . player . items , header . item , sizeof ( header . item ) ) ;
Bmemcpy ( GameStats . player . nAmmo , header . nAmmo , sizeof ( header . nAmmo ) ) ;
Bmemcpy ( GameStats . player . pad , header . pad , sizeof ( header . pad ) ) ;
GameStats . player . nCurrentWeapon = header . nCurrentWeapon2 ;
GameStats . player . field_3FOUR = header . field_3FOUR ;
GameStats . player . bIsFiring = header . bIsFiring ;
GameStats . player . field_38 = header . field_38 ;
GameStats . player . field_3A = header . field_3A ;
GameStats . player . field_3C = header . field_3C ;
GameStats . player . nRun = header . nRun ;
GameStats . nLives = header . nLives ;
}
else
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
}
void menu_ResetZoom ( )
{
2019-08-31 07:47:15 +00:00
zoomsize = 0 ;
2019-11-13 22:36:50 +00:00
PlayLocalSound ( StaticSound [ kSound31 ] , 0 ) ;
2019-08-26 03:59:14 +00:00
}
int menu_Menu ( int nVal )
{
2019-08-31 07:47:15 +00:00
GrabPalette ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
int var_1C = 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
StopAllSounds ( ) ;
StopLocalSound ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
menu_ResetKeyTimer ( ) ;
2019-11-24 12:59:36 +00:00
inputState . keyFlushChars ( ) ;
inputState . ClearAllKeyStatus ( ) ;
2019-08-31 07:47:15 +00:00
menu_ResetZoom ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
short ptr [ 5 ] ;
memset ( ptr , 1 , sizeof ( ptr ) ) ;
// disable new game and load game if in multiplayer?
if ( nNetPlayerCount )
{
ptr [ 1 ] = 0 ;
ptr [ 0 ] = 0 ;
}
// denote which menu item we've currently got selected
int nMenu = 0 ;
while ( 1 )
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-31 07:47:15 +00:00
// skip any disabled menu items so we're selecting the first active one
while ( ! ptr [ nMenu ] )
{
nMenu + + ;
2019-09-20 17:04:02 +00:00
if ( nMenu = = 5 ) {
2019-08-31 07:47:15 +00:00
nMenu = 0 ;
}
}
// handle the menu zoom-in
if ( zoomsize < 0x10000 )
{
zoomsize + = 4096 ;
2019-09-20 17:04:02 +00:00
if ( zoomsize > = 0x10000 ) {
2019-08-31 07:47:15 +00:00
zoomsize = 0x10000 ;
}
}
2019-11-22 08:13:27 +00:00
// TODO: Uncomment after fixing demo playback
2019-08-31 07:47:15 +00:00
// menu idle timer
2019-11-22 08:13:27 +00:00
// if (!nVal && (int)totalclock > keytimer) {
// return 9;
// }
2019-08-31 07:47:15 +00:00
// loc_39F54:
menu_DoPlasma ( ) ;
int y = 65 - tilesiz [ kMenuNewGameTile ] . y / 2 ;
// YELLOW loop - Draw the 5 menu options (NEW GAME, TRAINING etc)
for ( int j = 0 ; j < 5 ; j + + )
{
int8_t shade ;
2019-09-20 17:04:02 +00:00
if ( nMenu = = j ) { // currently selected menu item
2019-09-06 05:18:12 +00:00
shade = Sin ( ( int ) totalclock < < 4 ) > > 9 ;
2019-08-31 07:47:15 +00:00
}
2019-09-20 17:04:02 +00:00
else if ( ptr [ j ] ) {
2019-08-31 07:47:15 +00:00
shade = 0 ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
shade = 25 ;
}
picanm [ j + kMenuNewGameTile ] . xofs = 0 ;
picanm [ j + kMenuNewGameTile ] . yofs = 0 ;
rotatesprite ( 160 < < 16 , ( y + tilesiz [ j + kMenuNewGameTile ] . y ) < < 16 , zoomsize , 0 , kMenuNewGameTile + j , shade , 0 , 2 , 0 , 0 , xdim , ydim ) ;
y + = 22 ;
}
// tilesizx is 51
// tilesizy is 33
int markerY = ( 22 * nMenu ) + 53 ;
2019-09-20 17:04:02 +00:00
overwritesprite ( 62 , markerY , kMenuCursorTile , 0 , 2 , kPalNormal ) ;
2019-08-31 07:47:15 +00:00
overwritesprite ( 62 + 146 , markerY , kMenuCursorTile , 0 , 10 , kPalNormal ) ;
videoNextPage ( ) ;
2019-09-20 17:04:02 +00:00
int l = 0 ; // edi
2019-08-31 07:47:15 +00:00
// ORANGE loop
2019-09-20 17:04:02 +00:00
for ( l = 0 ; ; l + + )
2019-08-31 07:47:15 +00:00
{
int nKey = nMenuKeys [ l ] ;
2019-09-20 17:04:02 +00:00
if ( ! nKey ) {
2019-08-31 07:47:15 +00:00
break ;
}
2019-11-24 12:59:36 +00:00
if ( inputState . GetKeyStatus ( nKey ) )
2019-08-31 07:47:15 +00:00
{
2019-09-20 17:04:02 +00:00
goto LABEL_21 ; // TEMP
2019-08-31 07:47:15 +00:00
}
}
// loc_3A0A7
2019-11-24 12:59:36 +00:00
while ( I_EscapeTrigger ( ) )
2019-08-31 07:47:15 +00:00
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-31 07:47:15 +00:00
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
2019-11-24 12:59:36 +00:00
I_EscapeTriggerClear ( ) ;
2019-08-31 07:47:15 +00:00
if ( nVal )
{
StopAllSounds ( ) ;
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
MySetView ( nViewLeft , nViewTop , nViewRight , nViewBottom ) ;
return - 1 ;
}
l = 4 ;
2019-09-20 17:04:02 +00:00
LABEL_21 :
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
menu_ResetKeyTimer ( ) ;
if ( l ! = nMenu )
{
PlayLocalSound ( StaticSound [ kSound35 ] , 0 ) ;
2019-11-24 12:59:36 +00:00
inputState . ClearKeyStatus ( nMenuKeys [ l ] ) ;
2019-09-20 17:04:02 +00:00
nMenu = l ;
2019-08-31 07:47:15 +00:00
}
}
2019-11-24 12:59:36 +00:00
if ( I_AdvanceTrigger ( ) )
2019-08-31 07:47:15 +00:00
{
2019-11-24 12:59:36 +00:00
I_AdvanceTriggerClear ( ) ;
2019-08-31 07:47:15 +00:00
var_1C = 1 ;
}
else if ( var_1C )
{
var_1C = 0 ;
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
2019-09-20 17:04:02 +00:00
switch ( nMenu ) // TODO - change var name?
2019-08-31 07:47:15 +00:00
{
case kMenuNewGame :
{
2019-09-20 17:04:02 +00:00
if ( nTotalPlayers > 1 ) {
2019-08-31 07:47:15 +00:00
menu_ResetZoom ( ) ;
menu_ResetKeyTimer ( ) ;
break ;
}
SavePosition = menu_NewGameMenu ( ) ;
2019-09-20 17:04:02 +00:00
if ( SavePosition = = - 1 ) {
2019-08-31 07:47:15 +00:00
menu_ResetZoom ( ) ;
menu_ResetKeyTimer ( ) ;
break ;
}
FadeOut ( 1 ) ;
StopAllSounds ( ) ;
StopAllSounds ( ) ;
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
MySetView ( nViewLeft , nViewTop , nViewRight , nViewBottom ) ;
return 1 ;
}
case kMenuLoadGame :
{
2019-09-20 17:04:02 +00:00
if ( nTotalPlayers > 1 ) {
2019-08-31 07:47:15 +00:00
menu_ResetZoom ( ) ;
menu_ResetKeyTimer ( ) ;
break ;
}
SavePosition = menu_LoadGameMenu ( ) ;
2019-11-14 16:12:36 +00:00
if ( SavePosition = = - 1 ) {
menu_ResetZoom ( ) ;
menu_ResetKeyTimer ( ) ;
break ;
}
2019-08-31 07:47:15 +00:00
StopAllSounds ( ) ;
StopAllSounds ( ) ;
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
MySetView ( nViewLeft , nViewTop , nViewRight , nViewBottom ) ;
return 2 ;
}
case kMenuTraining :
{
2019-09-20 17:04:02 +00:00
if ( nTotalPlayers > 1 ) {
2019-08-31 07:47:15 +00:00
menu_ResetZoom ( ) ;
menu_ResetKeyTimer ( ) ;
break ;
}
StopAllSounds ( ) ;
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
MySetView ( nViewLeft , nViewTop , nViewRight , nViewBottom ) ;
return 3 ;
}
case kMenuVolume :
{
menu_AdjustVolume ( ) ;
menu_ResetZoom ( ) ;
menu_ResetKeyTimer ( ) ;
break ;
}
case kMenuQuitGame :
{
StopAllSounds ( ) ;
StopAllSounds ( ) ;
PlayLocalSound ( StaticSound [ kSound33 ] , 0 ) ;
MySetView ( nViewLeft , nViewTop , nViewRight , nViewBottom ) ;
return 0 ;
}
2019-11-20 16:21:32 +00:00
default :
2019-08-31 07:47:15 +00:00
menu_ResetZoom ( ) ;
menu_ResetKeyTimer ( ) ;
break ;
}
}
2019-11-24 12:59:36 +00:00
if ( I_MenuUp ( ) )
2019-08-31 07:47:15 +00:00
{
2019-11-24 12:59:36 +00:00
I_MenuUpClear ( ) ;
2019-08-31 07:47:15 +00:00
PlayLocalSound ( StaticSound [ kSound35 ] , 0 ) ;
2019-09-20 17:04:02 +00:00
if ( nMenu < = 0 ) {
2019-08-31 07:47:15 +00:00
nMenu = 4 ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
nMenu - - ;
}
menu_ResetKeyTimer ( ) ;
}
2019-11-24 12:59:36 +00:00
if ( I_MenuDown ( ) )
{
I_MenuDownClear ( ) ;
PlayLocalSound ( StaticSound [ kSound35 ] , 0 ) ;
2019-09-20 17:04:02 +00:00
if ( nMenu > = 4 ) {
2019-08-31 07:47:15 +00:00
nMenu = 0 ;
}
2019-09-20 17:04:02 +00:00
else {
2019-08-31 07:47:15 +00:00
nMenu + + ;
}
menu_ResetKeyTimer ( ) ;
}
2019-11-24 12:59:36 +00:00
2019-08-31 07:47:15 +00:00
// TODO - change to #defines
2019-11-24 12:59:36 +00:00
/* why are these cleares although they are never used anywhere?
2019-09-20 17:04:02 +00:00
if ( KB_KeyDown [ 0x5c ] ) {
2019-08-31 07:47:15 +00:00
KB_KeyDown [ 0x5c ] = 0 ;
}
2019-09-20 17:04:02 +00:00
if ( KB_KeyDown [ 0x5d ] ) {
2019-08-31 07:47:15 +00:00
KB_KeyDown [ 0x5d ] = 0 ;
}
2019-11-24 12:59:36 +00:00
*/
2019-08-31 07:47:15 +00:00
}
2019-09-20 17:04:02 +00:00
return 0 ; // todo
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
2019-09-20 17:04:02 +00:00
int linecount ;
int nextclock ;
2019-08-26 03:59:14 +00:00
short nHeight ;
short nCrawlY ;
short cinematile ;
// TODO - moveme
int LoadCinemaPalette ( int nPal )
{
2019-08-31 07:47:15 +00:00
nPal - - ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
if ( nPal < 0 | | nPal > = kMaxCinemaPals ) {
2019-08-31 07:47:15 +00:00
return - 2 ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
// original code strcpy'd into a buffer first...
2019-08-26 03:59:14 +00:00
2019-11-24 12:59:36 +00:00
auto hFile = kopenFileReader ( cinpalfname [ nPal ] , 1 ) ;
if ( ! hFile . isOpen ( ) ) {
2019-08-31 07:47:15 +00:00
return - 2 ;
}
2019-08-26 03:59:14 +00:00
2019-11-24 12:59:36 +00:00
hFile . Read ( cinemapal , sizeof ( cinemapal ) ) ;
2019-11-03 04:00:08 +00:00
for ( auto & c : cinemapal )
c < < = 2 ;
2019-08-31 07:47:15 +00:00
return nPal ;
2019-08-26 03:59:14 +00:00
}
2019-10-12 21:09:55 +00:00
//int IncrementCinemaFadeIn()
//{
// dest = cinemapal;
// cur = curpal;
//
// int ebx = 0;
//
// for (int i = 0; i < 768; i++)
// {
// ebx++;
//
// if (*cur < *dest)
// {
// (*cur)++;
// }
// else if (*cur == *dest)
// {
// ebx--;
// }
// else
// {
// (*cur)--;
// }
//
// cur++;
// dest++;
// }
//
// MySetPalette(curpal);
// return ebx;
//}
2019-08-26 03:59:14 +00:00
void CinemaFadeIn ( )
{
2019-08-31 07:47:15 +00:00
BlackOut ( ) ;
2019-08-26 03:59:14 +00:00
2019-10-12 22:27:12 +00:00
paletteSetColorTable ( ANIMPAL , cinemapal ) ;
videoSetPalette ( 0 , ANIMPAL , 2 + 8 ) ;
2019-10-12 21:09:55 +00:00
2019-10-12 22:27:12 +00:00
# ifdef USE_OPENGL
if ( videoGetRenderMode ( ) > = REND_POLYMOST )
2019-08-31 07:47:15 +00:00
{
2019-10-12 22:27:12 +00:00
videoNextPage ( ) ;
return ;
}
# endif
int val ;
do
{
val = DoFadeIn ( ) ;
2019-08-31 07:47:15 +00:00
WaitTicks ( 2 ) ;
2019-08-26 03:59:14 +00:00
2019-10-12 22:27:12 +00:00
// need to page flip in each iteration of the loop for non DOS version
videoNextPage ( ) ;
} while ( val > 0 ) ;
2019-08-26 03:59:14 +00:00
}
void ComputeCinemaText ( int nLine )
{
2019-08-31 07:47:15 +00:00
linecount = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
while ( 1 )
{
2019-09-20 17:04:02 +00:00
if ( ! strcmp ( gString [ linecount + nLine ] , " END " ) ) {
2019-08-31 07:47:15 +00:00
break ;
}
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
int nWidth = MyGetStringWidth ( gString [ linecount + nLine ] ) ;
2019-08-31 07:47:15 +00:00
nLeft [ linecount ] = 160 - nWidth / 2 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
linecount + + ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
nCrawlY = 199 ;
nHeight = linecount * 10 ;
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
ClearAllKeys ( ) ;
2019-08-26 03:59:14 +00:00
}
2019-08-31 09:08:38 +00:00
void ReadyCinemaText ( uint16_t nVal )
2019-08-26 03:59:14 +00:00
{
2019-08-31 07:47:15 +00:00
line = FindGString ( " CINEMAS " ) ;
2019-09-20 17:04:02 +00:00
if ( line < 0 ) {
2019-08-31 07:47:15 +00:00
return ;
}
while ( nVal )
{
2019-09-20 17:04:02 +00:00
while ( strcmp ( gString [ line ] , " END " ) ) {
2019-08-31 07:47:15 +00:00
line + + ;
}
line + + ;
nVal - - ;
}
ComputeCinemaText ( line ) ;
2019-08-26 03:59:14 +00:00
}
2019-08-31 07:47:15 +00:00
uint8_t AdvanceCinemaText ( )
2019-08-26 03:59:14 +00:00
{
2019-09-20 17:04:02 +00:00
int tmp = nHeight + nCrawlY > 0 ;
2019-08-31 07:47:15 +00:00
2019-11-28 20:40:17 +00:00
if ( tmp | | CDplaying ( ) )
2019-08-31 07:47:15 +00:00
{
2019-09-06 05:18:12 +00:00
nextclock = ( int ) totalclock + 14 ;
2019-08-31 07:47:15 +00:00
2019-08-31 10:36:26 +00:00
if ( tmp > 0 )
2019-08-31 07:47:15 +00:00
{
2019-09-20 17:04:02 +00:00
short y = nCrawlY ;
int edi = 0 ;
2019-08-31 07:47:15 +00:00
while ( edi < linecount & & y < = 199 )
{
2019-09-20 17:04:02 +00:00
if ( y > = - 10 ) {
2019-08-31 07:47:15 +00:00
myprintext ( nLeft [ edi ] , y , gString [ line + edi ] , 0 ) ;
}
edi + + ;
y + = 10 ;
}
nCrawlY - - ;
}
while ( 1 )
{
2019-08-31 15:04:06 +00:00
HandleAsync ( ) ;
2019-08-31 07:47:15 +00:00
2019-11-24 12:59:36 +00:00
if ( I_AdvanceTrigger ( ) )
{
I_AdvanceTriggerClear ( ) ;
2019-08-31 07:47:15 +00:00
break ;
}
2019-11-28 20:40:17 +00:00
if ( CDplaying ( ) )
2019-08-31 07:47:15 +00:00
{
2019-09-20 17:04:02 +00:00
if ( nextclock < = ( int ) totalclock ) {
2019-08-31 07:47:15 +00:00
return kTrue ;
}
}
else
{
return kTrue ;
}
}
}
return kFalse ;
2019-08-26 03:59:14 +00:00
}
void DoCinemaText ( short nVal )
{
2019-08-31 07:47:15 +00:00
ReadyCinemaText ( nVal ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
while ( 1 )
{
overwritesprite ( 0 , 0 , cinematile , 0 , 2 , kPalNormal ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
uint8_t bContinue = AdvanceCinemaText ( ) ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
WaitVBL ( ) ;
videoNextPage ( ) ;
2019-08-26 03:59:14 +00:00
2019-11-01 22:05:32 +00:00
// TEMP
2019-11-19 10:46:11 +00:00
int time = ( int ) totalclock + 8 ;
2019-11-01 22:05:32 +00:00
while ( ( int ) totalclock < time ) {
HandleAsync ( ) ;
}
2019-09-20 17:04:02 +00:00
if ( ! bContinue ) {
2019-08-31 07:47:15 +00:00
return ;
}
}
2019-08-26 03:59:14 +00:00
}
void GoToTheCinema ( int nVal )
{
2019-08-31 07:47:15 +00:00
UnMaskStatus ( ) ;
switch ( nVal - 1 )
{
default :
return ;
case 0 :
{
LoadCinemaPalette ( 1 ) ;
cinematile = 3454 ;
break ;
}
case 1 :
{
LoadCinemaPalette ( 2 ) ;
cinematile = 3452 ;
break ;
}
case 2 :
{
LoadCinemaPalette ( 3 ) ;
cinematile = 3449 ;
break ;
}
case 3 :
{
LoadCinemaPalette ( 4 ) ;
cinematile = 3445 ;
break ;
}
case 4 :
{
LoadCinemaPalette ( 5 ) ;
cinematile = 3451 ;
break ;
}
case 5 :
{
LoadCinemaPalette ( 6 ) ;
cinematile = 3448 ;
break ;
}
case 6 :
{
LoadCinemaPalette ( 7 ) ;
cinematile = 3446 ;
break ;
}
}
FadeOut ( kFalse ) ;
StopAllSounds ( ) ;
NoClip ( ) ;
2019-11-01 22:05:32 +00:00
overwritesprite ( 0 , 0 , kMovieTile , 100 , 2 , kPalNormal ) ;
2019-08-31 07:47:15 +00:00
videoNextPage ( ) ;
2019-08-26 03:59:14 +00:00
2019-09-20 17:04:02 +00:00
// int386(16, (const union REGS *)&val, (union REGS *)&val)
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
overwritesprite ( 0 , 0 , cinematile , 0 , 2 , kPalNormal ) ;
videoNextPage ( ) ;
CinemaFadeIn ( ) ;
ClearAllKeys ( ) ;
int ebx = - 1 ;
int edx = - 1 ;
switch ( nVal - 1 )
{
default :
WaitAnyKey ( 10 ) ;
break ;
case 0 :
ebx = 4 ;
edx = ebx ;
break ;
case 1 :
ebx = 0 ;
break ;
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
case 2 :
ebx = 2 ;
edx = ebx ;
break ;
case 3 :
ebx = 7 ;
break ;
case 4 :
ebx = 3 ;
edx = ebx ;
break ;
case 5 :
ebx = 8 ;
edx = ebx ;
break ;
case 6 :
ebx = 6 ;
edx = ebx ;
break ;
}
if ( ebx ! = - 1 )
{
if ( edx ! = - 1 )
{
2019-09-20 17:04:02 +00:00
if ( CDplaying ( ) ) {
2019-08-31 07:47:15 +00:00
fadecdaudio ( ) ;
}
2019-11-28 20:40:17 +00:00
playCDtrack ( edx + 2 , false ) ;
2019-08-31 07:47:15 +00:00
}
DoCinemaText ( ebx ) ;
}
FadeOut ( kTrue ) ;
2019-11-28 20:40:17 +00:00
overwritesprite ( 0 , 0 , kMovieTile , 100 , 2 , kPalNormal ) ;
2019-08-31 07:47:15 +00:00
videoNextPage ( ) ;
GrabPalette ( ) ;
Clip ( ) ;
2019-08-26 03:59:14 +00:00
}
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
{
2019-11-01 22:05:32 +00:00
GoToTheCinema ( nScene ) ;
nCinemaSeen [ nScene ] = 1 ;
2019-08-31 07:47:15 +00:00
}
}
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
2019-08-31 07:47:15 +00:00
int selectedLevel = menu_DrawTheMap ( nLevel , nLevelNew , nLevelBest ) ;
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 ] ) {
GoToTheCinema ( 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
2019-11-27 23:50:29 +00:00
GoToTheCinema ( 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
{
2019-11-24 12:59:36 +00:00
if ( ! inputState . keyBufferWaiting ( ) | | ( inputState . keyGetChar ( ) ! = 27 ) ) {
2019-08-31 07:47:15 +00:00
return kFalse ;
}
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
return kTrue ;
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 ) ;
UnMaskStatus ( ) ;
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
2019-08-31 07:47:15 +00:00
PlayLocalSound ( StaticSound [ kSound75 ] , 0 ) ;
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 ! = ' ' ) {
2019-08-31 07:47:15 +00:00
PlayLocalSound ( StaticSound [ kSound71 ] , 0 ) ;
}
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
2019-11-24 12:59:36 +00:00
inputState . keyFlushChars ( ) ;
inputState . ClearAllKeyStatus ( ) ;
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 :
2019-08-31 07:47:15 +00:00
PlayLocalSound ( StaticSound [ kSound75 ] , 0 ) ;
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 ) ;
MySetView ( nViewLeft , nViewTop , nViewRight , nViewBottom ) ;
MaskStatus ( ) ;
2019-08-26 03:59:14 +00:00
}
2019-11-22 23:11:37 +00:00
END_PS_NS