diff options
Diffstat (limited to 'game/code/main')
37 files changed, 13491 insertions, 0 deletions
diff --git a/game/code/main/allgcmain.cpp b/game/code/main/allgcmain.cpp new file mode 100644 index 0000000..ad8c143 --- /dev/null +++ b/game/code/main/allgcmain.cpp @@ -0,0 +1,10 @@ +#include <main/commandlineoptions.cpp> +#include <main/game.cpp> +#include <main/gcmain.cpp> +#include <main/gcplatform.cpp> +#include <main/singletons.cpp> +#include <main/gamecube_extras/gcmanager.cpp> +#ifndef RAD_RELEASE +#include <main/gamecube_extras/screenshot.c> +#endif +#include <main/tuidunaligned.cpp> diff --git a/game/code/main/allps2main.cpp b/game/code/main/allps2main.cpp new file mode 100644 index 0000000..9d76b0d --- /dev/null +++ b/game/code/main/allps2main.cpp @@ -0,0 +1,6 @@ +#include <main/commandlineoptions.cpp> +#include <main/game.cpp> +#include <main/ps2main.cpp> +#include <main/ps2platform.cpp> +#include <main/singletons.cpp> +#include <main/tuidunaligned.cpp> diff --git a/game/code/main/commandlineoptions.cpp b/game/code/main/commandlineoptions.cpp new file mode 100644 index 0000000..58b9676 --- /dev/null +++ b/game/code/main/commandlineoptions.cpp @@ -0,0 +1,403 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: commandlineoptions.cpp +// +// Description: CommandLineOptions class implementation. +// +// History: + Created -- Darwin Chau +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +// Standard C Library +#include <string.h> +// Foundation Tech +#include <raddebug.hpp> + +//======================================== +// Project Includes +//======================================== +#include <main/commandlineoptions.h> +#include <memory/srrmemory.h> + +//#ifdef RAD_GAMECUBE +//#define strupr(x) (x) +//#pragma message("strupr not defined on the game cube") +//#endif + + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + +// +// Bit flag for options. +// +#ifdef NEALL_DEMOTEST +simpsonsUInt64 CommandLineOptions::sOptions = ( 1 << CLO_DEMO_TEST | 1 << CLO_NO_TRAFFIC ); +#else +simpsonsUInt64 CommandLineOptions::sOptions = 0; +#endif + +short CommandLineOptions::s_defaultLevel = 0; +short CommandLineOptions::s_defaultMission = 0; + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================== +// CommandLineOptions::InitDefaults +//============================================================================== +// +// Description: Initialize default command-line options. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void CommandLineOptions::InitDefaults() +{ + simpsonsUInt64 orValue = 1; + +#ifdef RAD_RELEASE + // enable CLO_CD_FILES_ONLY in release builds for all platforms + // + orValue = 1; + orValue <<= CLO_CD_FILES_ONLY; + sOptions |= orValue; +#endif + +#if defined( RAD_GC ) || defined( RAD_PS2 ) + // enable CLO_NO_HEAPS for GC and PS2 only + // + orValue = 1; + orValue <<= CLO_NO_HEAPS; + sOptions |= orValue; +#endif +} + +//============================================================================== +// CommandLineOptions::HandleOption +//============================================================================== +// +// Description: Interpret the command line string token. +// +// Parameters: option - command line string token. +// +// Return: None. +// +//============================================================================== +void CommandLineOptions::HandleOption( const char* const optionIn ) +{ + simpsonsUInt64 andValue; + simpsonsUInt64 orValue = 1; + bool optionFound = true; + + rReleaseAssertMsg( NUM_CLO < (sizeof( sOptions ) * 8), + "*** WARNING: Too many commandline options!" ); + + char option[ 256 ]; + strcpy( option, optionIn ); + rReleasePrintf( "Commandline Option: %s\n", option ); + + if( strcmp( strupr(option), "NOMUSIC" ) == 0 ) + { + orValue <<= CLO_NO_MUSIC; + } + else if( strcmp( strupr(option), "NOEFFECTS" ) == 0 ) + { + orValue <<= CLO_NO_EFFECTS; + } + else if( strcmp( strupr(option), "NODIALOG" ) == 0 ) + { + orValue <<= CLO_NO_DIALOG; + } + else if( strcmp( strupr(option), "MUTE" ) == 0 ) + { + orValue <<= CLO_MUTE; + } + else if( strcmp( strupr(option), "SKIPMOVIE" ) == 0 ) + { + orValue <<= CLO_SKIP_MOVIE; + } + else if( strcmp( strupr(option), "MEMMONITOR" ) == 0 ) + { + orValue <<= CLO_MEMORY_MONITOR; + } + else if( strcmp( strupr(option), "HEAPSTATS" ) == 0 ) + { + orValue <<= CLO_HEAP_STATS; + } + else if( strcmp( strupr(option), "CDFILES" ) == 0 ) + { + orValue <<= CLO_CD_FILES_ONLY; + } + else if( strcmp( strupr(option), "HOSTFILES" ) == 0 ) + { + // + // Careful to avoid the PS2-hated 64-bit constant + // + andValue = 1; + andValue <<= CLO_CD_FILES_ONLY; + andValue = ~andValue; + + sOptions = sOptions & andValue; + + // + // Skip the or operation below + // + optionFound = false; + } + else if( strcmp( strupr(option), "FIREWIRE" ) == 0 ) + { + orValue <<= CLO_FIREWIRE; + } + else if( strcmp( strupr(option), "SNPROFILER" ) == 0 ) + { + orValue <<= CLO_SN_PROFILER; + } + else if( strcmp( strupr(option), "ARTSTATS" ) == 0 ) + { + orValue <<= CLO_ART_STATS; + } + else if( strcmp( strupr(option), "PROPSTATS" ) == 0 ) + { + orValue <<= CLO_PROP_STATS; + } + else if( strcmp( strupr(option), "FEUNJOINED" ) == 0 ) + { + orValue <<= CLO_FE_UNJOINED; + } + else if( strcmp( strupr(option), "SPEEDOMETER" ) == 0 ) + { + orValue <<= CLO_SHOW_SPEED; + } + else if( strcmp( strupr(option), "NOHUD" ) == 0 ) + { + orValue <<= CLO_NO_HUD; + } + else if( strcmp( strupr(option), "DEBUGBV" ) == 0 ) + { + orValue <<= CLO_DEBUGBV; + } + else if( strcmp( strupr(option), "NOTRAFFIC" ) == 0 ) + { + orValue <<= CLO_NO_TRAFFIC; + } + else if( strcmp( strupr(option), "SKIPSUNDAY" ) == 0 ) + { + orValue <<= CLO_SKIP_SUNDAY; + } + else if( strcmp( strupr(option), "SKIPFE" ) == 0 ) + { + orValue <<= CLO_SKIP_FE; + } + else if( strcmp( strupr(option), "FEGAGS" ) == 0 ) + { + orValue <<= CLO_FE_GAGS_TEST; + } + else if( strcmp( strupr(option), "FPS" ) == 0 ) + { + orValue <<= CLO_FPS; + } + else if( strcmp( strupr(option), "DESIGNER" ) == 0 ) + { + orValue <<= CLO_DESIGNER; + } + else if( strcmp( strupr(option), "DETECTLEAKS" ) == 0 ) + { + orValue <<= CLO_DETECT_LEAKS; + } + else if( strcmp( strupr(option), "NOHEAPS" ) == 0 ) + { + orValue <<= CLO_NO_HEAPS; + } + else if( strcmp( strupr(option), "PRINTMEMORY" ) == 0 ) + { + orValue <<= CLO_PRINT_MEMORY; + } + else if( strcmp( strupr(option), "DEMOTEST" ) == 0 ) + { + orValue <<= CLO_DEMO_TEST; + } + else if( strcmp( strupr(option), "NOSPLASH" ) == 0 ) + { + orValue <<= CLO_NO_SPLASH; + } + else if( strcmp( strupr(option), "LANGUAGE" ) == 0 ) + { + orValue <<= CLO_LANG_PROMPT; + } + else if( strcmp( strupr(option), "SKIPMEMCHECK" ) == 0 ) + { + orValue <<= CLO_SKIP_MEMCHECK; + } + else if( strcmp( strupr(option), "NOHAPTIC" ) == 0 ) + { + orValue <<= CLO_NO_HAPTIC; + } + else if( strcmp( strupr(option), "RANDOMBUTTONS" ) == 0 ) + { + orValue <<= CLO_RANDOM_BUTTONS; + } + else if( strcmp( strupr(option), "SEQUENTIALDEMO" ) == 0 ) + { + orValue <<= CLO_SEQUENTIAL_DEMO; + } + else if ( strcmp( strupr(option), "PCTEST" ) == 0 ) + { + orValue <<= CLO_PARKED_CAR_TEST; + } + else if ( strcmp( strupr(option), "NOAVRIL" ) == 0 ) + { + orValue <<= CLO_NO_AVRIL; + } + else if ( strcmp( strupr(option), "SHORTDEMO" ) == 0 ) + { + orValue <<= CLO_SHORT_DEMO; + } + else if( strcmp( strupr( option), "PRINTLOADTIME" ) == 0 ) + { + orValue <<= CLO_PRINT_LOAD_TIME; + } + else if( strcmp( strupr( option), "PRINTFRAMERATE" ) == 0 ) + { + orValue <<= CLO_PRINT_FRAMERATE; + } + else if ( strcmp( strupr( option ), "SHOWDYNALOAD" ) == 0 ) + { + orValue <<= CLO_SHOW_DYNA_ZONES; + } + else if ( strcmp( strupr( option ), "NOPEDS" ) == 0 ) + { + orValue <<= CLO_NO_PEDS; + } + else if ( strcmp( strupr( option ), "MANUALRESETDAMAGE" ) == 0 ) + { + orValue <<= CLO_MANUAL_RESET_DAMAGE; + } + else if ( strcmp( strupr( option ), "WINDOW" ) == 0 ) + { + orValue <<= CLO_WINDOW_MODE; + } + else if ( strcmp( strupr( option ), "NOTUTORIAL" ) == 0 ) + { + orValue <<= CLO_NO_TUTORIAL; + } + else if ( strcmp( strupr( option ), "COINS" ) == 0 ) + { + orValue <<= CLO_COINS; + } + else if ( strcmp( strupr( option ), "PROGSCAN" ) == 0 ) + { + orValue <<= CLO_PROGRESSIVE_SCAN; + } + else if ( strcmp( strupr( option ), "LARGEHEAPS" ) == 0 ) + { + orValue <<= CLO_LARGEHEAPS; + } + else if ( strcmp( strupr( option ), "MEMCARDCHEAT" ) == 0 ) + { + orValue <<= CLO_MEMCARD_CHEAT; + } + else if ( strcmp( strupr( option ), "TOOL" ) == 0 ) + { + orValue <<= CLO_PS2_TOOL; + } + else if ( strcmp( strupr( option ), "FILENOTFOUND" ) == 0 ) + { + orValue <<= CLO_FILE_NOT_FOUND; + } + else if ( strcmp( strupr( option ), "NOLOADINGSPEW" ) == 0 ) + { + orValue <<= CLO_NO_LOADING_SPEW; + } + else if ( strcmp( strupr( option ), "AUDIOSPEW" ) == 0 ) + { + orValue <<= CLO_AUDIO_LOADING_SPEW; + } + else if ( strcmp( strupr( option ), "RELEASEPRINT" ) == 0 ) + { + extern bool g_AllowDebugOutput; + g_AllowDebugOutput = true; + optionFound = false; + } + else if ( strcmp( strupr( option ), "NOFRUITLESS" ) == 0 ) + { + extern bool gFruitless; + gFruitless = false; + optionFound = false; + } + else if ( strcmp( strupr( option ), "RADTUNER" ) == 0 ) + { + extern bool gTuneSound; + gTuneSound = true; + optionFound = false; + } + + else + { + // special case for "l<N>" and "m<N>" commandline options + // + optionFound = false; + int stringLength = strlen( option ); + char lastChar = option[ stringLength - 1 ]; + option[ stringLength - 1 ] = '\0'; + + if( strcmp( strupr(option), "L" ) == 0 ) + { + s_defaultLevel = lastChar - '1'; + } + else if( strcmp( strupr(option), "M" ) == 0 ) + { + s_defaultMission = lastChar - '1'; + } + } + + if( optionFound ) + { + sOptions = sOptions | orValue; + } + else + { + rDebugPrintf( "Unhandled command line option: %s\n", option ); + } +} + + +//============================================================================== +// CommandLineOptions::Get +//============================================================================== +// +// Description: Retrieve the specified option. +// +// Parameters: eOption - the enumerated command line option. +// +// Return: bool - true if the option is enabled, false otherwise. +// +//============================================================================== +bool CommandLineOptions::Get( CmdLineOptionEnum eOption ) +{ + simpsonsUInt64 andValue = 1; + + rAssert( NUM_CLO <= 64 ); + + andValue <<= eOption; + return( ( sOptions & andValue ) != 0 ); +} + + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** diff --git a/game/code/main/commandlineoptions.h b/game/code/main/commandlineoptions.h new file mode 100644 index 0000000..35ef57f --- /dev/null +++ b/game/code/main/commandlineoptions.h @@ -0,0 +1,132 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: commandlineoptions.h +// +// Description: CommandLineOptions class declaration. +// +// History: + Created -- Darwin Chau +// +//============================================================================= + +#ifndef COMMANDLINEOPTIONS_H +#define COMMANDLINEOPTIONS_H + +#include <main/globaltypes.h> + +//#if defined( WORLD_BUILDER ) || defined( TOOLS ) +//typedef long simpsonsUInt64; +//#endif + +// +// Remember, we can only have 64 of these things +// +enum CmdLineOptionEnum +{ + CLO_NO_MUSIC, // Disable music + CLO_NO_EFFECTS, // Disable sound effects + CLO_NO_DIALOG, // Disable dialog + CLO_MUTE, // Disable all sound + CLO_SKIP_MOVIE, // Skip intro movie + CLO_MEMORY_MONITOR, // Enable RadMemoryMonitor + CLO_HEAP_STATS, // Enable heap stats display + CLO_CD_FILES_ONLY, // PS2 Only - Only load files from CD/DVD + CLO_FIREWIRE, // PS2 Only - Enable IEEE Firewire support + CLO_SN_PROFILER, // PS2 Only - Enable SN profiler + CLO_ART_STATS, // Custom display for the Artists, Such as FPS,Texture/Mesh Allocations etc. + CLO_PROP_STATS, // Enables logging of prop memory usage + + CLO_RANDOM_BUTTONS, // Enables random button pressing + CLO_DEMO_TEST, // Enables one-second demo loop time for testing purposes + CLO_SEQUENTIAL_DEMO,// Enable demo loop in sequential order + CLO_SHORT_DEMO, // Run demo loop at 60 seconds per demo + + CLO_FE_UNJOINED, // Load Scrooby FE resources as un-joined files. + CLO_FE_GAGS_TEST, // Test FE main menu gags. + CLO_NO_SPLASH, // Disables the splash screen + CLO_SKIP_FE, // Skip FE upon boot-up + CLO_LANG_PROMPT, // Force language selection prompt at boot-up. (PAL only) + CLO_SKIP_MEMCHECK, // Skip memory card boot-up check. + CLO_SHOW_SPEED, // Show Speedometer(s) on In-game HUD + CLO_NO_HUD, // No Heads-Up-Display + CLO_NO_TUTORIAL, // No Tutorial Pop-Up Messages + CLO_COINS, // Starts game w/ 100 coins + + CLO_DEBUGBV, // Display Debug Bounding Volumes. + CLO_SKIP_SUNDAY, // Jump into the mission, skip sunday drive + CLO_NO_TRAFFIC, // Disable traffic ya! + CLO_FPS, // Display render stats always + CLO_DESIGNER, // Designer-optimised tune parameter + CLO_DETECT_LEAKS, // Enables printout of all the memory leaks in the + CLO_NO_HEAPS, // Don't use radcore heaps - it's easier to track leaks without them + CLO_PRINT_MEMORY, // Print memory information to the TTY every few frames + CLO_NO_HAPTIC, // Disables controller rumble + CLO_PARKED_CAR_TEST,// Place parked cars on all locators (bye, bye framerate) + CLO_NO_AVRIL, // Disable licensed music + CLO_PRINT_LOAD_TIME,// print the time taken on the loading screen + CLO_PRINT_FRAMERATE,// print the framerate after a few seconds of running + + CLO_SHOW_DYNA_ZONES,// renders all the dyna-load zones as white boxes + + CLO_MANUAL_RESET_DAMAGE, // will reset the cars damage state when the user does a manual reset + + CLO_NO_PEDS, + + CLO_WINDOW_MODE, // windowed mode (versus fullscreen) for windows. + + CLO_PROGRESSIVE_SCAN, + CLO_LARGEHEAPS, + + CLO_MEMCARD_CHEAT, // unlock everything in the game temporarily before saving data to memory card + + CLO_PS2_TOOL, + CLO_FILE_NOT_FOUND, //Testing for file not found + CLO_NO_LOADING_SPEW, // Don't Spew <<START>>, <<END>> messages + CLO_AUDIO_LOADING_SPEW, // Spew Audio loading info + + NUM_CLO // Must not exceed 64 +}; + +//----------------------------------------------------------------------------- +// +// Synopsis: Any user specified command line options are stored here. +// +//----------------------------------------------------------------------------- +class CommandLineOptions +{ + public: + + // + // Initialize default command-line options. + // + static void InitDefaults(); + + // + // Interpret the command line string token. + // + static void HandleOption( const char* const optionIn ); + + // + // Retrive the specified option. + // + static bool Get( CmdLineOptionEnum eOption ); + + inline static short GetDefaultLevel() { return s_defaultLevel; } + inline static short GetDefaultMission() { return s_defaultMission; } + + private: + + // Declared but not defined to prevent copying and assignment. + CommandLineOptions( const CommandLineOptions& ); + CommandLineOptions& operator=( const CommandLineOptions& ); + + static simpsonsUInt64 sOptions; + + // default level and mission to load for 'skipfe' option + // + static short s_defaultLevel; + static short s_defaultMission; + +}; + +#endif // COMMANDLINEOPTIONS_H diff --git a/game/code/main/dvderrors.xls b/game/code/main/dvderrors.xls Binary files differnew file mode 100644 index 0000000..1167f9f --- /dev/null +++ b/game/code/main/dvderrors.xls diff --git a/game/code/main/errorsGC.h b/game/code/main/errorsGC.h new file mode 100644 index 0000000..c1f2d2b --- /dev/null +++ b/game/code/main/errorsGC.h @@ -0,0 +1,62 @@ +const char* ERROR_STRINGS[] = +{ +//English + "Success", + "FILE NOT FOUND", + "The Disc Cover is open.\n If you want to continue the game,\n please close the Disc Cover.", + "This is not \nThe Simpsons Hit & Run\nGame Disc. Please insert\nThe Simpsons Hit & Run\nGame Disc.", + "Please insert \nThe Simpsons Hit & Run\n Game Disc.", + "Please insert \nThe Simpsons Hit & Run\n Game Disc.", + "The Game Disc could not be read.\nPlease read the\nNintendo GameCube Instruction Booklet\nfor more information.", + "Please insert \nThe Simpsons Hit & Run\n Game Disc.", + "Please insert \nThe Simpsons Hit & Run\n Game Disc.", + "Please insert \nThe Simpsons Hit & Run\n Game Disc.", + "Please insert \nThe Simpsons Hit & Run\n Game Disc.", + "Please insert \nThe Simpsons Hit & Run\n Game Disc.", + "Please insert \nThe Simpsons Hit & Run\n Game Disc.", +//French + "Success", + "FILE NOT FOUND", + "Le couvercle est ouvert.\nPour continuer à jouer,\nveuillez fermer le couvercle.", + "Ce n'est pas le disque\nThe Simpsons Hit & Run. Veuillez insérer\nle disque: The Simpsons Hit & Run.", + "Veuillez insérer le disque:\nThe Simpsons Hit & Run.", + "Veuillez insérer le disque:\nThe Simpsons Hit & Run.", + "La lecture du disque a échoué.\nVeuillez vous référer au\nmanuel d'instructions\nNINTENDO GAMECUBE\npour de plus amples informations.", + "Veuillez insérer le disque:\nThe Simpsons Hit & Run.", + "Veuillez insérer le disque:\nThe Simpsons Hit & Run.", + "Veuillez insérer le disque:\nThe Simpsons Hit & Run.", + "Veuillez insérer le disque:\nThe Simpsons Hit & Run.", + "Veuillez insérer le disque:\nThe Simpsons Hit & Run.", + "Veuillez insérer le disque:\nThe Simpsons Hit & Run.", +//German + "Success", + "FILE NOT FOUND", + "Der Disc-Deckel ist geöffnet.\nBitte den Disc-Deckel schließen,\num mit dem Spiel fortzufahren.", + "Es befindet sich nicht die THE SIMPSONS\nHit & Run Game Disc im Laufwerk.\nBitte legen Sie die THE SIMPSONS\nHit & Run Game Disc ein.", + "Bitte die\nTHE SIMPSONS Hit & Run-Game Disc\neinlegen.", + "Bitte die\nTHE SIMPSONS Hit & Run-Game Disc\neinlegen.", + "Diese Game Disc kann nicht gelesen\nwerden. Bitte lesen Sie die\nBedienungsanleitung,\num weitere Informationen zu erhalten.", + "Bitte die\nTHE SIMPSONS Hit & Run-Game Disc\neinlegen.", + "Bitte die\nTHE SIMPSONS Hit & Run-Game Disc\neinlegen.", + "Bitte die\nTHE SIMPSONS Hit & Run-Game Disc\neinlegen.", + "Bitte die\nTHE SIMPSONS Hit & Run-Game Disc\neinlegen.", + "Bitte die\nTHE SIMPSONS Hit & Run-Game Disc\neinlegen.", + "Bitte die\nTHE SIMPSONS Hit & Run-Game Disc\neinlegen.", +//Spanish + "Success", + "FILE NOT FOUND", + "La tapa está abierta.\nSi quieres seguir jugando,\ncierra la tapa.", + "Este no es el disco de\nThe Simpsons Hit & Run. Coloca el disco de\nThe Simpsons Hit & Run.", + "Coloca el disco de The Simpsons Hit & Run.", + "Coloca el disco de The Simpsons Hit & Run.", + "No se puede leer el disco.\nConsulta el manual de\ninstrucciones de NINTENDO GAMECUBE\npara obtener más información.", + "Coloca el disco de The Simpsons Hit & Run.", + "Coloca el disco de The Simpsons Hit & Run.", + "Coloca el disco de The Simpsons Hit & Run.", + "Coloca el disco de The Simpsons Hit & Run.", + "Coloca el disco de The Simpsons Hit & Run.", + "Coloca el disco de The Simpsons Hit & Run.", + + "" // dummy terminator + +}; diff --git a/game/code/main/errorsPS2.h b/game/code/main/errorsPS2.h new file mode 100644 index 0000000..7fa2b28 --- /dev/null +++ b/game/code/main/errorsPS2.h @@ -0,0 +1,62 @@ +const char* ERROR_STRINGS[] = +{ +//English + "Success", + "FILE NOT FOUND", + "The disc tray is open", + "Incorrect disc. \nInsert The Simpsons Hit & Run disc.", + "No disc. \nInsert The Simpsons Hit & Run disc.", + "Incorrect disc. \nInsert The Simpsons Hit & Run disc.", + "Incorrect disc. \nInsert The Simpsons Hit & Run disc.", + "Incorrect disc. \nInsert The Simpsons Hit & Run disc.", + "Incorrect disc. \nInsert The Simpsons Hit & Run disc.", + "Incorrect disc. \nInsert The Simpsons Hit & Run disc.", + "Incorrect disc. \nInsert The Simpsons Hit & Run disc.", + "Incorrect disc. \nInsert The Simpsons Hit & Run disc.", + "Incorrect disc. \nInsert The Simpsons Hit & Run disc.", +//French + "Success", + "FILE NOT FOUND", + "Le compartiment à disque est ouvert.", + "Disque incorrect.\nInsérez le disque The Simpsons Hit & Run.", + "Aucun disque.\nInsérez le disque The Simpsons Hit & Run.", + "Disque incorrect.\nInsérez le disque The Simpsons Hit & Run.", + "Disque incorrect.\nInsérez le disque The Simpsons Hit & Run.", + "Disque incorrect.\nInsérez le disque The Simpsons Hit & Run.", + "Disque incorrect.\nInsérez le disque The Simpsons Hit & Run.", + "Disque incorrect.\nInsérez le disque The Simpsons Hit & Run.", + "Disque incorrect.\nInsérez le disque The Simpsons Hit & Run.", + "Disque incorrect.\nInsérez le disque The Simpsons Hit & Run.", + "Disque incorrect.\nInsérez le disque The Simpsons Hit & Run.", +//German + "Success", + "FILE NOT FOUND", + "Die DVD/CD - Lade ist geöffnet", + "Falsche DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", + "Keine DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", + "Falsche DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", + "Falsche DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", + "Falsche DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", + "Falsche DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", + "Falsche DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", + "Falsche DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", + "Falsche DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", + "Falsche DVD/CD-ROM. Leg die\nTHE SIMPSONS Hit & Run-DVD/CD-ROM ein.", +//Spanish + "Success", + "FILE NOT FOUND", + "La bandeja del disco está abierta.", + "Disco incorrecto.\nInserta el disco de The Simpsons Hit & Run.", + "No se ha introducido ningún disco.\nInserta el disco de Simpsons Hit & Run.", + "Disco incorrecto.\nInserta el disco de The Simpsons Hit & Run.", + "Disco incorrecto.\nInserta el disco de The Simpsons Hit & Run.", + "Disco incorrecto.\nInserta el disco de The Simpsons Hit & Run.", + "Disco incorrecto.\nInserta el disco de The Simpsons Hit & Run.", + "Disco incorrecto.\nInserta el disco de The Simpsons Hit & Run.", + "Disco incorrecto.\nInserta el disco de The Simpsons Hit & Run.", + "Disco incorrecto.\nInserta el disco de The Simpsons Hit & Run.", + "Disco incorrecto.\nInserta el disco de The Simpsons Hit & Run.", + + "" // dummy terminator + +}; diff --git a/game/code/main/errorsWIN32.h b/game/code/main/errorsWIN32.h new file mode 100644 index 0000000..2ad955d --- /dev/null +++ b/game/code/main/errorsWIN32.h @@ -0,0 +1,31 @@ +const char* ERROR_STRINGS[] = +{ +//English + "Success", + "FileNotFound", + "ShellOpen", + "WrongMedia", + "There's a problem with the disc you're using. It may be dirty or damaged. Press A to continue.", + "There's a problem with the disc you're using. It may be dirty or damaged. Press A to continue.", + "There's a problem with the disc you're using. It may be dirty or damaged. Press A to continue.", + "Your Xbox doesn't have enough free blocks to save games. Press A to continue without saving or B to free more blocks.", + "Your Xbox doesn't have enough free blocks to save games. Press A to continue without saving or B to free more blocks.", + "MediaEncodingErr", + "MediaWrongType", + "MediaInvalid", + "DataCorrupt", +//French + "NON SOUTENU", + "NON SOUTENU", + "NON SOUTENU", + "NON SOUTENU", + "ÉCHEC DE MATÉRIEL", + "ÉCHEC DE MATÉRIEL", + "ÉCHEC DE MATÉRIEL", + "ÉCHEC DE MATÉRIEL", + "HORS DE L'ESPACE", + "NON SOUTENU", + "NON SOUTENU", + "NON SOUTENU", + "NON SOUTENU", +}; diff --git a/game/code/main/errorsXBOX.h b/game/code/main/errorsXBOX.h new file mode 100644 index 0000000..ec4d492 --- /dev/null +++ b/game/code/main/errorsXBOX.h @@ -0,0 +1,62 @@ +const char* ERROR_STRINGS[] = +{ +//English + "Success", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", + "The Disc Tray is open.\nIf you want to continue the game,\nplease close the Disc Tray.", + "This is not \nThe Simpsons Hit & Run\nGame Disc. Please insert\nThe Simpsons Hit & Run\nGame Disc.", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", + "There is a problem with\nthe disc you're using.\nIt may be dirty or damaged.", +//French + "Success", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", + "", + "", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", + "Le disque utilisé présente une anomalie.\nIl est peut-être sale ou endommagé.", +//German + "Success", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", + "", + "", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", + "Problem bei der benutzten CD:\nCD ist verschmutzt oder beschädigt.", +//Spanish + "Success", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + "", + "", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + "Hay un problema con el disco que estás usando.\nPuede estar sucio o dañado.", + + "" // dummy terminator + +}; diff --git a/game/code/main/game.cpp b/game/code/main/game.cpp new file mode 100644 index 0000000..8330f32 --- /dev/null +++ b/game/code/main/game.cpp @@ -0,0 +1,709 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: game.cpp +// +// Description: The game loop +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +// Standard Library +#include <stdlib.h> +#include <string.h> +// Foundation Tech +#include <raddebug.hpp> +#include <raddebugcommunication.hpp> +#include <raddebugconsole.hpp> +#include <raddebugwatch.hpp> +#include <radfile.hpp> +#include <radmemorymonitor.hpp> +#include <radtime.hpp> +// Pure3D +#include <p3d/loadmanager.hpp> +#include <p3d/utility.hpp> + +#ifdef RAD_WIN32 +#pragma warning( push ) +#pragma warning( disable : 4005 ) // disable warning for redefinition of RGB macro (wingdi.h,raddebugconsole.hpp) +#include <windows.h> // for peekmessage... +#pragma warning( pop ) +#endif + +//======================================== +// Project Includes +//======================================== +#include <contexts/contextenum.h> +#include <debug/profiler.h> +#include <gameflow/gameflow.h> +#include <presentation/gui/ingame/guiscreenmissionload.h> +#include <main/commandlineoptions.h> +#include <main/game.h> +#include <main/platform.h> + +#ifdef RAD_GAMECUBE +#include <main/gamecube_extras/gcmanager.h> +#endif + +#include <memory/srrmemory.h> +#include <memory/memoryutilities.h> + +#include <render/RenderFlow/RenderFlow.h> +#include <sound/soundmanager.h> +#include <input/inputmanager.h> + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + +// +// Static pointer to instance of this singleton. +// +Game* Game::spInstance = NULL; + +bool g_inDemoMode = false; + +//#define DEMO_MODE_PROFILER + +#ifdef DEMO_MODE_PROFILER + #define DEMOPROFILE(X) X +#else + #define DEMOPROFILE(X) +#endif + +#ifdef DEMO_MODE_PROFILER + +#ifdef RAD_PS2 +#include <libgraph.h> +#endif + +DemoProfiler::DemoProfiler(unsigned mf) : + recording(false), maxFrames(mf), nChannel(0), currentFrame(0), + alertStatus(PROFILER_ALERT_GREEN), + numFramesBelow_20(0), numFramesBetween_20_30(0),numFramesBetween_30_40(0), numFramesAbove_40(0) +{ + for( int i=0; i < MAX_CHANNEL; i++) + { + channel[i] = NULL; + } +} + +void DemoProfiler::AddChannel(unsigned c, const char* name) +{ + rReleaseAssert(c < MAX_CHANNEL); + channel[c] = new Channel; + channel[c]->samples = new unsigned[maxFrames]; + memset(channel[c]->samples, 0, maxFrames*sizeof(unsigned)); + channel[c]->t0 = 0; + strncpy(channel[c]->name, name, 254); + nChannel++; +} + +void DemoProfiler::Start(unsigned c) +{ + if(!channel[c]) return; + if( recording ) + { + channel[c]->t0 = radTimeGetMicroseconds64(); + } +} + + +void DemoProfiler::Stop(unsigned c) +{ + if(!channel[c]) return; + if( recording ) + { + radTime64 elapsed = radTimeGetMicroseconds64() - channel[c]->t0; + channel[c]->samples[currentFrame] += elapsed; + + if(c == 0) + { + alertStatus = PROFILER_ALERT_GREEN; + if( elapsed >= 50000 ) + { + numFramesBelow_20++; + alertStatus = PROFILER_ALERT_RED; + } + else if( (elapsed < 50000) && (elapsed >= 33333) ) + { + numFramesBetween_20_30++; + alertStatus = PROFILER_ALERT_YELLOW; + } + else if( (elapsed < 33333) && (elapsed >= 25000) ) + { + numFramesBetween_30_40++; + } + else + { + numFramesAbove_40++; + } + } + } +} + +void DemoProfiler::Set(unsigned c, unsigned val) +{ + if(!channel[c]) return; + if( recording ) + { + channel[c]->samples[currentFrame] = val; + } +} + +void DemoProfiler::StartRecording() +{ + recording = true; +} + +bool DemoProfiler::IsRecording() +{ + return recording; +} + +unsigned DemoProfiler::GetSample(unsigned c) +{ + return (recording && channel[c]) ? channel[c]->samples[currentFrame] : 0; +} + +unsigned DemoProfiler::GetCurrentFrame() +{ + return currentFrame; +} + +void DemoProfiler::Accumulate(unsigned c, unsigned val) +{ + if(!channel[c]) return; + if( recording ) + { + channel[c]->samples[currentFrame] += val; + } +} + +void DemoProfiler::NextFrame() +{ + if( recording ) + { + currentFrame++; + if(currentFrame >= maxFrames) + { + Dump(); + recording = false; + } + } +} + +DemoProfiler::AlertStatus DemoProfiler::GetAlertStatus() +{ + return alertStatus; +} + +void DemoProfiler::Dump() +{ + rReleasePrintf("\n\n~~~~~~~~~~~~~~~~~~~~~ PROFILER STATS ~~~~~~~~~~~~~~~~~~~~~\n"); + rReleasePrintf( "Total Frames: %d\n" + "< 20 fps: %d (%.2f%%)\n" + "20-30 fps: %d (%.2f%%)\n" + "30-40 fps: %d (%.2f%%)\n" + ">40 fps: %d (%.2f%%)\n", + maxFrames, + numFramesBelow_20, 100.0f * (float)numFramesBelow_20 / (float)maxFrames, + numFramesBetween_20_30, 100.0f * (float)numFramesBetween_20_30 / (float)maxFrames, + numFramesBetween_30_40, 100.0f * (float)numFramesBetween_30_40 / (float)maxFrames, + numFramesAbove_40, 100.0f * (float)numFramesAbove_40 / (float)maxFrames ); + + for( unsigned i=0; i < MAX_CHANNEL; i++) + { + if(channel[i]) + { + rReleasePrintf("%s\t", channel[i]->name); + } + } + rReleasePrintf("\n"); + + for( unsigned i=0; i < maxFrames; i++ ) + { + for( unsigned j=0; j < MAX_CHANNEL; j++ ) + { + if(channel[j]) + { + rReleasePrintf("%.1f\t", (float)channel[j]->samples[i] * 0.001f); + } + } + rReleasePrintf("\n"); + + if( !(i % 10) ) + { + rmt::Sin(0.0f); +#ifdef RAD_PS2 + sceGsSyncV(0); +#endif + } + } + + while(1) + { + rmt::Sin(0.0f); + } +} + + +DemoProfiler g_DemoProfiler( 1850 ); // about a minute at 30 fps + +#include <pddi/pddi.hpp> + +static bool g_DemoProfiler_Started = false; +static const int g_DemoProfiler_StartFrame = 150; +static int g_DemoProfiler_CurrentFrame = 0; + +#endif + + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================== +// Game::CreateInstance +//============================================================================== +// Description: Create the game +// +// Parameters: platform - the platform that the game is to be created on +// +// Return: pointer to the created game +// +// Constraints: This is a singleton so only one instance is allowed. +// +//============================================================================== +Game* Game::CreateInstance( Platform* platform ) +{ + rAssert( platform != NULL ); + + rAssertMsg( (spInstance == NULL), "Trying to create more than one instance of the game!" ); + +MEMTRACK_PUSH_GROUP( "Game" ); + if( spInstance == NULL ) + { + spInstance = new(GMA_PERSISTENT) Game( platform ); + rAssert( spInstance != NULL ); + } +MEMTRACK_POP_GROUP( "Game" ); + + return spInstance; +} + + +//============================================================================== +// Game::DestroyInstance +//============================================================================== +// Description: Destroy the game +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void Game::DestroyInstance() +{ + delete( GMA_PERSISTENT, spInstance ); + spInstance = NULL; +} + + +//============================================================================== +// Game::GetInstance +//============================================================================== +// Synopsis: Get an instance of the game +// +// Parameters: None. +// +// Returns: a poitner to the game +// +// Constraints: Game must be created before this is called +// +//============================================================================== +Game* Game::GetInstance() +{ + rAssertMsg((spInstance != NULL), "Trying to get an instance of the game before it is created!"); + + return spInstance; +} + +//============================================================================= +// Game::GetPlatform +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: Platform +// +//============================================================================= +Platform* Game::GetPlatform() +{ + return mpPlatform; +} + + +//============================================================================== +// Game::Initialize +//============================================================================== +// Synopsis: Initialize the game +// +// Parameters: None. +// +// Returns: None. +// +//============================================================================== +void Game::Initialize() +{ + rAssert( mpPlatform != NULL ); + + // + // Initialize the platform and core systems. + // + mpPlatform->InitializePlatform(); + + // + // Initialize the timer system + // + ::radTimeCreateList( &mpTimerList, + 16, // Default + GMA_PERSISTENT ); + + rAssert( mpTimerList != NULL ); + + // + // Create the GameFlow & Couple the RenderFlow + // + mpGameFlow = GameFlow::CreateInstance(); + mpRenderFlow = RenderFlow::GetInstance(); + mpRenderFlow->DoAllRegistration(); + + CGuiScreenMissionLoad::InitializePermanentVariables(); + +#ifdef RAD_E3 + rReleasePrintf( "\n----------=[ SIMPSONS HIT & RUN - E3 BUILD ]=----------\n\n" ); +#endif + + // + // Set the starting context + // + mpGameFlow->SetContext( CONTEXT_BOOTUP ); +} + + +//============================================================================== +// Game::Terminate +//============================================================================== +// Synopsis: Clean up and shut down. +// +// Parameters: None. +// +// Returns: None. +// +//============================================================================== +void Game::Terminate() +{ + rAssert( mpGameFlow != NULL ); + rAssert( mpRenderFlow != NULL ); + rAssert( mpTimerList != NULL ); + rAssert( mpPlatform != NULL ); + + // + // Kill the flow servers. + // + mpGameFlow->DestroyInstance(); + mpGameFlow = NULL; + + // Render flow destroyed by singletons.cpp + //mpRenderFlow->DestroyInstance(); + mpRenderFlow = NULL; + + // + // Release the game's references to the timer list. + // + mpTimerList->Release(); + mpTimerList = NULL; +} + + +//============================================================================== +// Game::Run +//============================================================================== +// Synopsis: This is where game loop spins. It exits after Stop() is called. +// +// Parameters: None. +// +// Returns: None. +// +//============================================================================== +const unsigned PROFILE_CHANNEL_ALL = 0; +const unsigned PROFILE_CHANNEL_AI = 1; +const unsigned PROFILE_CHANNEL_RENDER = 2; +const unsigned PROFILE_CHANNEL_LOAD = 3; + +void Game::Run() +{ + extern bool g_AllowDebugOutput; + +#ifdef DEMO_MODE_PROFILER + g_AllowDebugOutput = false; + g_DemoProfiler.AddChannel(0, "All"); + g_DemoProfiler.AddChannel(1, "Ai"); + g_DemoProfiler.AddChannel(2, "Render"); + g_DemoProfiler.AddChannel(3, "Load"); + g_DemoProfiler.AddChannel(4, "Opaque"); + g_DemoProfiler.AddChannel(5, "Translucent"); + g_DemoProfiler.AddChannel(6, "World Sphere"); + g_DemoProfiler.AddChannel(7, "Anim Entity"); + g_DemoProfiler.AddChannel(8, "Breakable"); + g_DemoProfiler.AddChannel(9, "InstAnimDynaPhys"); + g_DemoProfiler.AddChannel(10, "InstDynaPhys"); + g_DemoProfiler.AddChannel(11, "InstStat"); + g_DemoProfiler.AddChannel(12, "InstStatPhys"); + g_DemoProfiler.AddChannel(13,"Lens Flare"); + g_DemoProfiler.AddChannel(14, "State Prop"); + g_DemoProfiler.AddChannel(15, "Static"); + g_DemoProfiler.AddChannel(16, "Tristrip"); + g_DemoProfiler.AddChannel(17, "AnimCollision"); + g_DemoProfiler.AddChannel(18, "Cars"); + g_DemoProfiler.AddChannel(19, "Characters"); + g_DemoProfiler.AddChannel(20, "ABH"); + g_DemoProfiler.AddChannel(21, "Actor"); + g_DemoProfiler.AddChannel(22, "AnimatedIcon"); + g_DemoProfiler.AddChannel(23, "ParticleSystem"); + +#endif + + unsigned time = radTimeGetMilliseconds(); + while( !mExitNow ) + { + DEMOPROFILE( g_DemoProfiler.Start(PROFILE_CHANNEL_ALL); ) + + BEGIN_PROFILER_FRAME(); + + BEGIN_PROFILE( "GameLoop" ) + + unsigned newTime = radTimeGetMilliseconds(); + unsigned elapsed = newTime - time; + time = newTime; + + // + // Service the windows message loop. + // +#ifdef RAD_WIN32 + MSG msg; + while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) + { + if( msg.message == WM_QUIT ) + { + //Chuck someone closed the Window we are going to try to exit the game + //if the game isnt in a context that can easily transition to the EXIT context we + // are going to call the Launch Dashboard and return to the main loop and shutdown + if ( GetGameFlow()->GetCurrentContext() != CONTEXT_FRONTEND && + GetGameFlow()->GetCurrentContext() != CONTEXT_GAMEPLAY && + GetGameFlow()->GetCurrentContext() != CONTEXT_PAUSE ) + { + GetGame()->GetPlatform()->LaunchDashboard(); + //return to the winmain and shutdown + return; + } + //we are in a context that will transition nicely to the Exit context. + else + { + mpGameFlow->SetContext( CONTEXT_EXIT ); + } + } + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } +#endif // RAD_WIN32 + + // + // Service the GameFlow and RenderFlow. + // + + if ( !mpPlatform->PausedForErrors() ) + { + DEMOPROFILE( g_DemoProfiler.Start(PROFILE_CHANNEL_AI); ) + mpTimerList->Service(); //nv + mpGameFlow->OnTimerDone(elapsed, NULL); + DEMOPROFILE( g_DemoProfiler.Stop(PROFILE_CHANNEL_AI); ) + + if( !mExitNow ) + { + DEMOPROFILE( g_DemoProfiler.Start(PROFILE_CHANNEL_RENDER); ) + mpRenderFlow->OnTimerDone(elapsed, NULL); + DEMOPROFILE( g_DemoProfiler.Stop(PROFILE_CHANNEL_RENDER); ) + } + } + else if (mpPlatform->IsControllerError()) // if controller unplugged + { // need to update input manager + if (InputManager::GetInstance()) + { + InputManager::GetInstance()->Update( elapsed ); + } + } + else + { +#ifdef RAD_GAMECUBE + GCManager::GetInstance()->OnTimerDone( elapsed, NULL ); +#endif + } + + // + // Service FTech subsystems. + // + ::radFileService(); + ::radDbgComService(); + ::radDebugConsoleService(); + + if( CommandLineOptions::Get( CLO_MEMORY_MONITOR) ) + { + ::radMemoryMonitorService(); + } + + // + // Service the sound renderer. + // + SoundManager::GetInstance()->Update(); + + if ( mpPlatform->PausedForErrors() ) + { + // + // [ps] We update sound without a valid context or elapsed time. + // We use 0 and NUM_CONTEXTS, since these values are unlikely to + // happen in the real game. + // + SoundManager::GetInstance()->UpdateOncePerFrame( 0, NUM_CONTEXTS, false, true ); + } + + // + // Spin Pure3D async loading. + // + DEMOPROFILE( g_DemoProfiler.Start(PROFILE_CHANNEL_LOAD); ) + p3d::loadManager->SwitchTask(); + DEMOPROFILE( g_DemoProfiler.Stop(PROFILE_CHANNEL_LOAD); ) + + ++mFrameCount; + + DEMOPROFILE( g_DemoProfiler.Stop(PROFILE_CHANNEL_ALL); ) + +#ifdef DEMO_MODE_PROFILER + g_AllowDebugOutput = true; + if(g_inDemoMode) + { + if( !g_DemoProfiler_Started && (g_DemoProfiler_CurrentFrame == g_DemoProfiler_StartFrame) ) + { + g_DemoProfiler_Started = true; + g_DemoProfiler.StartRecording(); + rReleasePrintf("Beginning demo profile run\n"); + } + + if(g_DemoProfiler.IsRecording()) + { + pddiColour colour(255,255,255); + if( g_DemoProfiler.GetAlertStatus() == DemoProfiler::PROFILER_ALERT_YELLOW) + colour.Set(255,255,0); + else + if( g_DemoProfiler.GetAlertStatus() == DemoProfiler::PROFILER_ALERT_RED) + colour.Set(255,0,0); + + char duff[255]; + sprintf(duff, "%d %d", g_DemoProfiler.GetCurrentFrame(), (g_DemoProfiler.GetSample(0) + 500) / 1000); + p3d::pddi->DrawString( duff, 10, 400, colour ); + } + + g_DemoProfiler.NextFrame(); + g_DemoProfiler_CurrentFrame++; + } + + g_AllowDebugOutput = false; +#endif // DEMO_MODE_PROFILER + + END_PROFILE( "GameLoop" ) + + END_PROFILER_FRAME(); + } +} + + +//============================================================================== +// Game::Stop +//============================================================================== +// Synopsis: Sets the flag to break us out of the game loop. +// +// Parameters: None. +// +// Returns: None. +// +//============================================================================== +void Game::Stop() +{ + // + // Stop any further rendering from happening. + // + mExitNow = true; +} + + +unsigned Game::GetRandomSeed () +{ + radDate date; + ::radTimeGetDate (&date); + return ( ( date.m_Year << 16 ) | ( date.m_Month << 8 ) | ( date.m_Day ) ) ^ ( ( date.m_Second << 24 ) | ( date.m_Minute << 8 ) | ( date.m_Hour ) ); +} + + + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** + +//============================================================================== +// Game::Game +//============================================================================== +// Synopsis: Constructor. +// +// Parameters: platform - platform on which game should be created +// +// Returns: N/A. +// +//============================================================================== +Game::Game( Platform* platform ) : + mpPlatform( platform ), + mpTimerList( NULL ), + mpGameFlow( NULL ), + mpRenderFlow( NULL ), + mFrameCount( 0 ), + mExitNow( false ), + mDemoCount( 0 ), + mTimeMS( 0 ) +{ +} + + +//============================================================================== +// Game::~Game +//============================================================================== +// Synopsis: Destructor. +// +// Parameters: None. +// +// Returns: N/A. +// +//============================================================================== +Game::~Game() +{ +} diff --git a/game/code/main/game.h b/game/code/main/game.h new file mode 100644 index 0000000..f090ce8 --- /dev/null +++ b/game/code/main/game.h @@ -0,0 +1,139 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: game.h +// +// Description: The game loop +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +#ifndef GAME_H +#define GAME_H + +//======================================== +// Forward References +//======================================== +class Platform; +struct IRadTimerList; +class GameFlow; +class RenderFlow; + +#include <radtime.hpp> + +class DemoProfiler +{ +public: + DemoProfiler(unsigned maxFrames); + + void AddChannel(unsigned c, const char* name); + + void NextFrame(); + + void Start(unsigned c); // start timing channel c + void Stop(unsigned c); // stop timing channel c + void Set(unsigned c, unsigned val); // set sample value for channel c + unsigned GetSample(unsigned c); + unsigned GetCurrentFrame(); + void Accumulate(unsigned c, unsigned val); // add value to sample for channel c + void Dump(); // print out all samples + + void StartRecording(); + bool IsRecording(); + enum AlertStatus { PROFILER_ALERT_GREEN, PROFILER_ALERT_YELLOW, PROFILER_ALERT_RED }; + AlertStatus GetAlertStatus(); + +private: + enum { MAX_CHANNEL = 64 }; + + struct Channel + { + char name[255]; + unsigned* samples; + radTime64 t0; + }; + + bool recording; + unsigned maxFrames; + + Channel* channel[MAX_CHANNEL]; + unsigned nChannel; + unsigned currentFrame; + + AlertStatus alertStatus; + unsigned numFramesBelow_20; + unsigned numFramesBetween_20_30; + unsigned numFramesBetween_30_40; + unsigned numFramesAbove_40; +}; + +extern DemoProfiler g_DemoProfiler; + +//============================================================================= +// +// Synopsis: The game loop +// +//============================================================================= +class Game +{ + public: + + // Static Methods (for creating and getting an instance of the game) + static Game* CreateInstance( Platform* platform ); + static void DestroyInstance(); + static Game* GetInstance(); + + Platform* GetPlatform(); + + + // Game Flow Public Methods + void Initialize(); + void Terminate(); + + void Run(); + void Stop(); + + IRadTimerList* GetTimerList() { return mpTimerList; } + + unsigned int GetFrameCount() const { return mFrameCount; }; + + unsigned int GetDemoCount() const { return mDemoCount; }; + void IncrementDemoCount() { ++mDemoCount; }; + void SetTime( unsigned int timeMS ) { mTimeMS = timeMS; }; + unsigned int GetTime() { return mTimeMS; }; + + static unsigned GetRandomSeed (); + + private: + + // Constructors, Destructors, and Operators + Game( Platform* platform ); + virtual ~Game(); + + // Unused Constructors, Destructors, and Operators + Game(); + Game( const Game& aGame ); + Game& operator=( const Game& aGame ); + + // Static Singleton Attribute + static Game* spInstance; + + // Private Attributes + Platform* mpPlatform; + IRadTimerList* mpTimerList; + GameFlow* mpGameFlow; + RenderFlow* mpRenderFlow; + + unsigned int mFrameCount; + + bool mExitNow; + + unsigned int mDemoCount; + unsigned int mTimeMS; +}; + +inline Game* GetGame() { return( Game::GetInstance() ); } + +#endif // GAME_H + diff --git a/game/code/main/gamecube_extras/buildlicense.bat b/game/code/main/gamecube_extras/buildlicense.bat new file mode 100644 index 0000000..500aea5 --- /dev/null +++ b/game/code/main/gamecube_extras/buildlicense.bat @@ -0,0 +1,8 @@ +..\..\..\libs\pure3d\tools\commandline\bin\p3dimage -b 4 -c -o licensee.p3d ..\..\..\exportart\frontend\scrooby\resource\images\_gc\license.png +@rem..\..\..\libs\pure3d\tools\commandline\bin\convert2dxtn -f 1 licensee.p3d +..\..\..\libs\pure3d\tools\commandline\bin\p3dgc licensee.p3d +attrib -r license.h +..\..\..\build\tools\bin2h licensee.p3d > license.h +..\..\..\libs\pure3d\lib\perl\bin\perl ..\..\..\build\tools\sizeprint.pl license.h license.png >> license.h +attrib +r license.h +rem @del licensee.p3d diff --git a/game/code/main/gamecube_extras/gcmanager.cpp b/game/code/main/gamecube_extras/gcmanager.cpp new file mode 100644 index 0000000..8d7fa7c --- /dev/null +++ b/game/code/main/gamecube_extras/gcmanager.cpp @@ -0,0 +1,711 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: GCManager.cpp +// +// Description: Implement GCManager +// +// History: 14/06/2002 + Created -- Cary Brisebois +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +#include <dolphin.h> +#include <dolphin/os.h> +#include <dolphin/lg.h> +#include <dolphin/dvd.h> + +// Foundation Tech +#include <raddebug.hpp> +#include <raddebugwatch.hpp> +#include <radFile.hpp> +#include <radcontroller.hpp> +#include <radthread.hpp> + + +//======================================== +// Project Includes +//======================================== +#include <main/gamecube_extras/GCManager.h> +#include <main/gcplatform.h> +#include <main/game.h> +#include <gameflow/gameflow.h> +#include <main/platform.h> +#include <memory/srrmemory.h> +#include <input/inputmanager.h> + +#include <debug/profiler.h> + +#include <sound/soundmanager.h> + +#include <data/gamedatamanager.h> + +#include <presentation/fmvplayer/fmvplayer.h> +#include <presentation/presentation.h> + +unsigned int MIN_TIME = 500; //0.5 seconds in milliseconds, as per doc + +#ifdef DEBUGWATCH +int sX = 640; +int sY = 480; +#endif + +//***************************************************************************** +// +// Call backs +// +//***************************************************************************** + +void ResetButtonCallBack( void ) +{ + if ( OSGetResetButtonState() ) + { + //Inform the GCManager + GCManager::GetInstance()->Reset(); + } + else + { + //Reset the callback the last one was bogus. + OSSetResetCallback( ResetButtonCallBack ); + } +} + +void CheckForGCNReset() +{ + GCManager::GetInstance()->TestForReset(); +} + + +#ifdef DEBUGWATCH +void ChangeResolutionCallback( void* userData ) +{ + sY = sX * 12; + sX *= 16; + + GCManager::GetInstance()->ChangeResolution( sX, sY, 32 ); +} +#endif + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + +GCManager* GCManager::mInstance = NULL; + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +GCManager* GCManager::GetInstance() +{ +MEMTRACK_PUSH_GROUP( "GCManager" ); + if ( !mInstance ) + { + mInstance = new(GMA_PERSISTENT) GCManager(); + } +MEMTRACK_POP_GROUP( "GCManager" ); + + return mInstance; +} + +//============================================================================= +// GCManager::Init +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void GCManager::Init() +{ + //We want a callback to test for reset + GetGame()->GetTimerList()->CreateTimer( &mTimer, 500, this ); +} + +//============================================================================= +// GCManager::Reset +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void GCManager::Reset() +{ + mReset = true; +} + +//============================================================================= +// GCManager::OnTimerDone +//============================================================================= +// Description: Comment +// +// Parameters: ( unsigned int elapsedTime, void * pUserData ) +// +// Return: void +// +//============================================================================= +void GCManager::OnTimerDone( unsigned int elapsedTime, void * pUserData ) +{ + BEGIN_PROFILE( "GCManager" ); + if ( mReset ) + { + PerformReset(); + } + + TestForReset(); + + END_PROFILE( "GCManager" ); +} + + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** + +//============================================================================== +// GCManager::GCManager +//============================================================================== +// Description: Constructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +GCManager::GCManager() : + mDoingReset( false ), + mTimer( NULL ) +{ + unsigned int i; + for ( i = 0; i < Input::MaxControllers; ++i ) + { + mControllerReset[i] = false; + mResetTime[i] = 0; + } + + //Set up the reset callback. + OSSetResetCallback( ResetButtonCallBack ); + +#ifdef DEBUGWATCH + radDbgWatchAddFunction( "Set Resolution", &ChangeResolutionCallback, this, "GCManager" ); + + radDbgWatchAddInt( &sX, "X Resolution (multiple of 16)", "GCManager", NULL, NULL, 1, 40 ); +// radDbgWatchAddInt( &sY, "Y Resolution", "GCManager", NULL, NULL, 16, 480 ); +#endif +} + +//============================================================================== +// GCManager::~GCManager +//============================================================================== +// Description: Destructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +GCManager::~GCManager() +{ + if ( mTimer ) + { + mTimer->Release(); + } +} + +//============================================================================= +// GCManager::TestForReset +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void GCManager::TestForReset() +{ + + unsigned int inputCount = 0; + PADStatus controllers[PAD_MAX_CONTROLLERS]; + + for ( inputCount = 0; inputCount < PAD_MAX_CONTROLLERS; ++inputCount ) + { + controllers[ inputCount ].button = 0; + } + + PADRead(controllers); + //while( PAD_ERR_TRANSFER == PADRead(controllers) ){ ::radThreadSleep( 32 ); } + + LGPosition lgStatus[ SI_MAX_CHAN ]; + memset( lgStatus, 0, sizeof( LGPosition )*SI_MAX_CHAN ); + + extern bool g_isLGInitialized; + if( g_isLGInitialized ) + { + LGRead( lgStatus ); + } + + rAssert( PAD_MAX_CONTROLLERS == SI_MAX_CHAN ); + for ( inputCount = 0; inputCount < PAD_MAX_CONTROLLERS; ++inputCount ) + { + if( lgStatus[inputCount].err == LG_ERR_NONE ) + { + controllers[inputCount].err = PAD_ERR_NONE; + controllers[inputCount].button = 0; + + if( lgStatus[inputCount].button & LG_BUTTON_B ) + { + controllers[inputCount].button |= PAD_BUTTON_B; + } + if( lgStatus[inputCount].button & LG_BUTTON_X ) + { + controllers[inputCount].button |= PAD_BUTTON_X; + } + if( lgStatus[inputCount].button & LG_BUTTON_START ) + { + controllers[inputCount].button |= PAD_BUTTON_MENU; + } + } + + if ( controllers[ inputCount ].err == PAD_ERR_NONE && + controllers[ inputCount ].button & PAD_BUTTON_B && + controllers[ inputCount ].button & PAD_BUTTON_X && + controllers[ inputCount ].button & PAD_BUTTON_MENU ) + { + if ( mControllerReset[inputCount] ) + { + if ( OSTicksToMilliseconds( OSGetTime() ) - mResetTime[inputCount] > MIN_TIME ) + { + mControllerReset[inputCount] = false; + mResetTime[inputCount] = 0; + + //Call reset + ControllerReset(); + break; + } + } + else + { + if ( mResetTime[inputCount] == 0 ) + { + if(GetGameFlow()==NULL)return; + ContextEnum context = GetGameFlow()->GetCurrentContext(); + + if ( context == CONTEXT_LOADING_SUPERSPRINT || + context == CONTEXT_SUPERSPRINT || + context == CONTEXT_LOADING_GAMEPLAY || + context == CONTEXT_GAMEPLAY || + context == CONTEXT_PAUSE ) + { + if ( GetInputManager()->GetControllerPlayerIDforController( inputCount ) >= 0 ) + { + mResetTime[inputCount] = OSTicksToMilliseconds( OSGetTime() ); + mControllerReset[inputCount] = true; + } + } + else + { + mResetTime[inputCount] = OSTicksToMilliseconds( OSGetTime() ); + mControllerReset[inputCount] = true; + } + + } + } + } + else + { + mResetTime[inputCount] = 0; + mControllerReset[inputCount] = false; + } + } + + if ( OSGetResetButtonState() ) + { + mReset = true; + } + + if ( mReset ) + { + //Bye bye! + PerformReset(); + } +} + +//============================================================================= +// GCManager::ControllerReset +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void GCManager::ControllerReset() +{ + //TODO: Test if we should reset here or not! + //For now... + Reset(); + + //Potentially, we could reset to the main menu... That might be better. +} + +//============================================================================= +// GCManager::PerformReset +//============================================================================= +// Description: Comment +// +// Parameters: ( bool displaySplash ) +// +// Return: void +// +//============================================================================= +void GCManager::PerformReset( bool displaySplash, bool launchIPL ) +{ + // Wait until the switch is released + if ( !mDoingReset && ( mReset ) && ( !OSGetResetButtonState( ) ) ) + { + mDoingReset = true; + + if ( !GetGame()->GetPlatform()->PausedForErrors() ) + { + // If we have troubles with sound, we should shut it down here. Don't foget + // to service the sound system enough time for the changes to be reflected. + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->Pause( ); + } + else + { + GetSoundManager()->StopForMovie(); + + while( !( GetSoundManager()->IsStoppedForMovie() ) ) + { + ::radMovieService2( ); + ::radFileService( ); + SoundManager::GetInstance()->Update(); + SoundManager::GetInstance()->UpdateOncePerFrame( 0, NUM_CONTEXTS, false, true ); + } + } + } + + if ( displaySplash && !launchIPL && DVDCheckDisk() ) + { + //Fade to black + // GetGame()->GetPlatform()->DisplaySplashScreen( Platform::FadeToBlack, NULL, 1.0f, 1.0f, 0.0f, tColour(0,0,0), 100 ); + } + + StopEverything(); + + GXDrawDone(); + + // + // One last TRC when we reset + // + VISetBlack(true); + VIFlush(); + VIWaitForRetrace(); + + //TODO: If we have progressive scan mode enabled, we need to keep it enabled on reset. + //This could be tricky. + + if ( launchIPL || !DVDCheckDisk() ) + { + // Reset the system + OSResetSystem( + OS_RESET_HOTRESET, + 0, + launchIPL ); + } + else + { + // Reset the system + OSResetSystem( + OS_RESET_RESTART, + 0, + false ); + } + } +} + +//============================================================================= +// GCManager::StopEverything +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void GCManager::StopEverything() +{ + //Stop the controllers. + StopRumble(); + + //Wait for the memory cards to complete. + while ( GetGameDataManager()->IsUsingDrive() ) + { + ::radFileService(); + ::radControllerSystemService(); + GetGameDataManager()->Update( 16 ); + } + + ::radControllerTerminate(); + + //Shutdown the platform. +#ifdef RAD_RELEASE + //GetGame()->GetPlatform()->ShutdownPlatform(); //This causes a crash in FTech... +#endif +} + +//============================================================================= +// GCManager::ChangeResolution +//============================================================================= +// Description: Comment +// +// Parameters: ( int x, int y, int bpp ) +// +// Return: void +// +//============================================================================= +void GCManager::ChangeResolution( int x, int y, int bpp ) +{ + rAssert( x % 16 == 0 ); //This must be a multiple of 16pixels! + + GetGame()->GetPlatform()->DisplaySplashScreen( Platform::Error, NULL, NULL, 0.0f, 0.0f, tColour(0,0,0), 0 ); + p3d::context->GetDisplay()->InitDisplay( x, y, bpp ); +} + +//============================================================================= +// GCManager::DoProgressiveScanTest +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void GCManager::DoProgressiveScanTest() +{ + //Test for button b being held down and ask if they want progressive mode + //Or not. + bool doProgressiveQuestion = false; + + if ( VIGetDTVStatus() != 1 ) + { + return; + } + + //There's a cable present.. + + //If the progressive mode flagis set, then we make the message show also. + if ( OSGetProgressiveMode() ) + { + //The flag is set from last time. + doProgressiveQuestion = true; + } + else + { + unsigned int inputCount = 0; + PADStatus controllers[PAD_MAX_CONTROLLERS]; + + for ( inputCount = 0; inputCount < PAD_MAX_CONTROLLERS; ++inputCount ) + { + controllers[ inputCount ].button = 0; + } + + ::radThreadSleep( 32 ); + + PADRead(controllers); + + for ( inputCount = 0; inputCount < PAD_MAX_CONTROLLERS && !doProgressiveQuestion; ++inputCount ) + { + if ( controllers[ inputCount ].err == PAD_ERR_NONE && + controllers[ inputCount ].button & PAD_BUTTON_B ) + { + //Someone is holding B. + doProgressiveQuestion = true; + break; + } + } + + ::radControllerSystemService(); + ::radThreadSleep( 16 ); + ::radControllerSystemService(); + ::radThreadSleep( 16 ); + + LGPosition lgStatus[ SI_MAX_CHAN ]; + memset( lgStatus, 0, sizeof( LGPosition )*SI_MAX_CHAN ); + LGRead( lgStatus ); + + for ( inputCount = 0; inputCount < SI_MAX_CHAN && !doProgressiveQuestion; ++inputCount ) + { + if ( lgStatus[ inputCount ].err == LG_ERR_NONE && + lgStatus[ inputCount ].button & LG_BUTTON_B ) + { + //Someone is holding B. + doProgressiveQuestion = true; + break; + } + } + } + + if ( doProgressiveQuestion ) + { + //Display the question. + //TODO: Localization + GetGame()->GetPlatform()->DisplaySplashScreen( Platform::Error, "Do you want to display in progressive mode?", 0.7f ); + + bool setProgressiveOn = ((GCPlatform*)GetGame()->GetPlatform())->DisplayYesNo( 0.7f, -0.2f, -0.1f, 0.1f, -0.1f ); + + if ( setProgressiveOn != ((GCPlatform*)GetGame()->GetPlatform())->GetInitData()->progressive ) + { + + //Do the TRC delay stuff. + + //Set the screen black + VISetBlack( TRUE ); + VIFlush(); + VIWaitForRetrace(); + + unsigned int i; + for( i=0; i<10; i++ ) + { //Set screen black and wait for several frames + VIWaitForRetrace(); + } + + //Change modes + ((GCPlatform*)GetGame()->GetPlatform())->GetInitData()->progressive = setProgressiveOn; + + //Need to re-init the display. + p3d::context->GetDisplay()->InitDisplay( ((GCPlatform*)GetGame()->GetPlatform())->GetInitData() ); + + for( i=0; i<100; i++ ) + { //Set screen black and wait for several dozen frames + VIWaitForRetrace(); + } + + VISetBlack(FALSE); + VIFlush(); + VIWaitForRetrace(); + } + + //Set progressive scan mode + OSSetProgressiveMode( setProgressiveOn ); + + //Display message that progressive is enabled + //TODO: localization + if ( setProgressiveOn && OSGetProgressiveMode() ) + { + GetGame()->GetPlatform()->DisplaySplashScreen( Platform::Error, "Screen has been set to progressive mode.\n Press the A Button to continue.", 0.7f ); + } + else if ( !setProgressiveOn && !OSGetProgressiveMode() ) + { + GetGame()->GetPlatform()->DisplaySplashScreen( Platform::Error, "Screen has been set to interlaced mode.\n Press the A Button to continue.", 0.7f ); + } + + if ( setProgressiveOn == OSGetProgressiveMode() ) + { + //Wait for input or 10 second timeout. + unsigned int time = OSTicksToMilliseconds( OSGetTime() ); + + bool waiting = true; + + PADStatus controllers[PAD_MAX_CONTROLLERS]; + PADStatus lastControllers[PAD_MAX_CONTROLLERS]; + + unsigned int inputCount = 0; + + for ( inputCount = 0; inputCount < PAD_MAX_CONTROLLERS; ++inputCount ) + { + controllers[ inputCount ].button = 0; + lastControllers[ inputCount ].button = 0; + } + + LGPosition lgStatus[ SI_MAX_CHAN ]; + memset( lgStatus, 0, sizeof( LGPosition )*SI_MAX_CHAN ); + + while ( waiting ) + { + ::radControllerSystemService(); + ::radThreadSleep( 32 ); + PADRead(controllers); + LGRead( lgStatus ); + + for ( inputCount = 0; inputCount < PAD_MAX_CONTROLLERS; ++inputCount ) + { + if( lgStatus[inputCount].err == LG_ERR_NONE ) + { + controllers[inputCount].err = PAD_ERR_NONE; + controllers[inputCount].button = 0; + + if( lgStatus[inputCount].button & LG_BUTTON_A ) + { + controllers[inputCount].button = PAD_BUTTON_A; + } + if( lgStatus[inputCount].button & LG_BUTTON_START ) + { + controllers[inputCount].button = PAD_BUTTON_MENU; + } + } + + if ( controllers[ inputCount ].err == PAD_ERR_NONE && + ( !( controllers[ inputCount ].button & PAD_BUTTON_A ) && + lastControllers[ inputCount ].button & PAD_BUTTON_A ) || + ( !( controllers[ inputCount ].button & PAD_BUTTON_MENU ) && + lastControllers[ inputCount ].button & PAD_BUTTON_MENU ) ) + { + waiting = false; + break; + } + + if( controllers[ inputCount ].err == PAD_ERR_NONE ) + { + lastControllers[ inputCount ] = controllers[ inputCount ]; + } + } + + unsigned int newTime = OSTicksToMilliseconds( OSGetTime() ); + if ( newTime - time > 10000 ) + { + waiting = false; + } + } + } + } +} + +//============================================================================= +// GCManager::StopRumble +//============================================================================= +// Description: Lets get ready to stop rumbling! +// +// Parameters: () +// +// Return: void +// +//============================================================================= + +void GCManager::StopRumble() +{ + PADControlMotor( PAD_CHAN0, PAD_MOTOR_STOP_HARD ); + PADControlMotor( PAD_CHAN1, PAD_MOTOR_STOP_HARD ); + PADControlMotor( PAD_CHAN2, PAD_MOTOR_STOP_HARD ); + PADControlMotor( PAD_CHAN3, PAD_MOTOR_STOP_HARD ); +} diff --git a/game/code/main/gamecube_extras/gcmanager.h b/game/code/main/gamecube_extras/gcmanager.h new file mode 100644 index 0000000..720e1fa --- /dev/null +++ b/game/code/main/gamecube_extras/gcmanager.h @@ -0,0 +1,83 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: gcmanager.h +// +// Description: Blahblahblah +// +// History: 14/06/2002 + Created -- Cary Brisebois +// +//============================================================================= + +#ifndef GCMANAGER_H +#define GCMANAGER_H + +//======================================== +// Nested Includes +//======================================== +#include <radtime.hpp> // IRadTimerCallback + +//======================================== +// Forward References +//======================================== +#include <dolphin/pad.h> + +//============================================================================= +// +// Synopsis: Blahblahblah +// +//============================================================================= + +class GCManager : public IRadTimerCallback +{ +public: + static GCManager* GetInstance(); + + void Init(); + + void Reset(); + void PerformReset( bool displaySplash = true, bool launchIPL = false ); + + //For IRadTimerCallback + void OnTimerDone( unsigned int elapsedTime, void * pUserData ); + + void ChangeResolution( int x, int y, int bpp ); + + void DoProgressiveScanTest(); + + // MKR - adding StopRumble, turn off rumble immediately (for use when the GC cover is opened) + void StopRumble(); + + void TestForReset(); + +private: + static GCManager* mInstance; + + bool mReset; + bool mDoingReset; + + bool mControllerReset[PAD_MAX_CONTROLLERS]; + unsigned int mResetTime[PAD_MAX_CONTROLLERS]; + + // Timer for updates. + IRadTimer* mTimer; + + GCManager(); + virtual ~GCManager(); + + void ControllerReset(); + void StopEverything(); + + //Prevent wasteful constructor creation. + GCManager( const GCManager& gcmanager ); + GCManager& operator=( const GCManager& gcmanager ); +}; + + +//***************************************************************************** +// +// Inline Public Member Functions +// +//***************************************************************************** + +#endif //GCMANAGER_H diff --git a/game/code/main/gamecube_extras/license.h b/game/code/main/gamecube_extras/license.h new file mode 100644 index 0000000..332339b --- /dev/null +++ b/game/code/main/gamecube_extras/license.h @@ -0,0 +1,963 @@ +"\xff\x44\x33\x50\x00\x00\x00\x0c\x00\x00\x43\x52\x00\x00\x70\x00\x00\x00" +"\x00\x9d\x00\x00\x00\x9d\x00\x03\x24\x70\x33\x64\x67\x63\x20\x76\x65\x72" +"\x73\x69\x6f\x6e\x20\x31\x2e\x30\x2e\x31\x20\x28\x77\x69\x74\x68\x20\x41" +"\x54\x47\x20\x32\x2e\x30\x29\x00\x00\x40\x2e\x2e\x5c\x2e\x2e\x5c\x2e\x2e" +"\x5c\x6c\x69\x62\x73\x5c\x70\x75\x72\x65\x33\x64\x5c\x74\x6f\x6f\x6c\x73" +"\x5c\x63\x6f\x6d\x6d\x61\x6e\x64\x6c\x69\x6e\x65\x5c\x62\x69\x6e\x5c\x70" +"\x33\x64\x67\x63\x20\x6c\x69\x63\x65\x6e\x73\x65\x65\x2e\x70\x33\x64\x00" +"\x00\x00\x28\x52\x75\x6e\x20\x61\x74\x20\x4a\x75\x6c\x79\x20\x30\x36\x2c" +"\x20\x32\x30\x30\x33\x2c\x20\x32\x31\x3a\x33\x33\x3a\x33\x35\x20\x62\x79" +"\x20\x74\x63\x68\x75\x00\x00\x00\x00\x70\x00\x00\x00\x00\xf1\x00\x00\x00" +"\xf1\x00\x03\x28\x70\x33\x64\x69\x6d\x61\x67\x65\x20\x76\x65\x72\x73\x69" +"\x6f\x6e\x20\x31\x2e\x34\x2e\x30\x20\x28\x77\x69\x74\x68\x20\x41\x54\x47" +"\x20\x32\x2e\x30\x29\x00\x00\x00\x90\x2e\x2e\x5c\x2e\x2e\x5c\x2e\x2e\x5c" +"\x6c\x69\x62\x73\x5c\x70\x75\x72\x65\x33\x64\x5c\x74\x6f\x6f\x6c\x73\x5c" +"\x63\x6f\x6d\x6d\x61\x6e\x64\x6c\x69\x6e\x65\x5c\x62\x69\x6e\x5c\x70\x33" +"\x64\x69\x6d\x61\x67\x65\x20\x2d\x62\x20\x34\x20\x2d\x63\x20\x2d\x6f\x20" +"\x6c\x69\x63\x65\x6e\x73\x65\x65\x2e\x70\x33\x64\x20\x2e\x2e\x5c\x2e\x2e" +"\x5c\x2e\x2e\x5c\x65\x78\x70\x6f\x72\x74\x61\x72\x74\x5c\x66\x72\x6f\x6e" +"\x74\x65\x6e\x64\x5c\x73\x63\x72\x6f\x6f\x62\x79\x5c\x72\x65\x73\x6f\x75" +"\x72\x63\x65\x5c\x69\x6d\x61\x67\x65\x73\x5c\x5f\x67\x63\x5c\x6c\x69\x63" +"\x65\x6e\x73\x65\x2e\x70\x6e\x67\x00\x28\x52\x75\x6e\x20\x61\x74\x20\x4a" +"\x75\x6c\x79\x20\x30\x36\x2c\x20\x32\x30\x30\x33\x2c\x20\x32\x31\x3a\x33" +"\x33\x3a\x33\x35\x20\x62\x79\x20\x74\x63\x68\x75\x00\x00\x00\x01\x90\x00" +"\x00\x00\x00\x3d\x00\x00\x41\xb8\x0c\x6c\x69\x63\x65\x6e\x73\x65\x2e\x70" +"\x6e\x67\x00\x00\x00\x36\xb0\x00\x00\x02\x80\x00\x00\x01\xe0\x00\x00\x00" +"\x04\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" +"\x00\x00\x00\x00\x01\x90\x01\x00\x00\x00\x35\x00\x00\x41\x7b\x0c\x6c\x69" +"\x63\x65\x6e\x73\x65\x2e\x70\x6e\x67\x00\x00\x00\x36\xb0\x00\x00\x02\x80" +"\x00\x00\x01\xe0\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" +"\x00\x01\x00\x01\x90\x02\x00\x00\x41\x46\x00\x00\x41\x46\x00\x00\x41\x36" +"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00" +"\x02\x80\x00\x00\x01\xe0\x04\x03\x00\x00\x00\xc7\xff\xc1\xd7\x00\x00\x00" +"\x30\x50\x4c\x54\x45\x00\x00\x00\x03\x04\x08\x06\x11\x0e\x0f\x25\x21\x09" +"\x3c\x40\x0f\x5d\x5e\x54\x53\x18\xa0\x2d\x19\x24\x98\x5b\xf0\xeb\x70\xcf" +"\xbf\x1d\x11\x77\x80\x19\xb3\xc0\x44\xe0\xed\x1d\xb4\xc1\xd6\xd6\xd7\x9b" +"\x02\x02\xf4\x00\x00\x20\x00\x49\x44\x41\x54\x78\x9c\xed\x7d\x5b\x6c\x1b" +"\x47\xba\x66\xa9\x9b\xcd\x41\x44\xaa\x8f\x92\xe0\x78\x10\xbf\x0c\xe3\x1b" +"\x30\x4e\xcc\x61\x2c\x5b\xe7\xf8\x42\x86\xb0\x95\x27\x9b\x02\xd7\xb6\x0e" +"\x06\x90\x49\xc8\x36\x86\xb1\xf4\xb0\xce\x9e\x03\x38\xc8\xbc\x04\x38\x83" +"\x09\xf2\xb4\xc8\x24\x80\x03\xf2\x49\x89\x01\x05\xe4\x13\x37\xb2\x9f\x18" +"\x0a\x44\x3c\x7e\xb2\x28\x08\x16\xf9\x44\x56\xa1\x57\x14\x67\x17\x90\xaa" +"\xf7\x32\x58\xe5\xed\x70\xff\xbf\xaa\x9b\x17\x5d\x7c\x95\xed\x38\xae\xcf" +"\x6e\xb1\xbb\xba\xbb\xaa\xfa\xeb\xbf\x2e\xdd\x7f\xff\xff\x4f\x88\x82\x82" +"\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82" +"\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82" +"\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82" +"\x82\x82\x82\x8b\xbe\x37\xf6\x0e\x0d\xbe\xe8\x4a\xbc\xbc\x00\xf6\x86\x86" +"\xae\xbc\xe8\x5a\xbc\xac\xe8\xdb\x03\xec\x0d\xa7\x3e\xbc\xfe\xa2\x2b\xf2" +"\x72\x02\x85\x0f\xd8\xfb\xf8\xe3\x8f\x15\x81\x8f\x0f\x21\x7c\xa9\xd4\xc7" +"\x12\x2f\xba\x36\x2f\x1d\x34\x21\x7c\x1f\xb7\xf1\xa2\xeb\xf3\x92\xe1\x0d" +"\x14\xbe\x0f\x3f\xee\xc2\x9e\x17\x5d\xa5\x97\x08\x7d\x1b\x84\x4f\x12\x18" +"\x78\xd1\xd5\x7a\x59\xb0\xc7\x1d\x37\x7a\x91\x7a\xfd\x45\x57\xec\xa5\x00" +"\x0e\xbb\x6d\xf6\x52\xd7\xff\x47\x87\xc0\xa9\xff\xa2\xa6\xd2\x0f\xc5\x9e" +"\xbd\x3d\xc2\x97\xfa\xb4\xab\x1d\x4f\xcd\x28\x11\x7c\x18\xb4\x6e\xf6\xae" +"\xb7\x86\x5b\xd7\xfe\xd0\xd9\x9e\xca\x28\x11\x7c\x18\xb4\x5d\x5d\x7d\xde" +"\xf5\x54\xea\x6f\xce\x24\xf0\xd3\x9f\xe0\xcf\x70\x56\x89\xe0\xc3\xf0\x86" +"\xb7\x67\xd4\xb8\x7e\xe0\xba\x24\xb0\x85\x3f\x87\x95\x08\x3e\x14\x1a\x91" +"\x2d\xb6\xd5\x42\x91\xbb\xee\x8a\xe2\xc7\x3f\x09\x3e\x77\x29\x11\x7c\x18" +"\xfa\x24\x81\x9f\xfe\x47\xfb\xf9\xed\x53\x48\xb8\xbe\xfe\xa9\x1c\x85\x95" +"\x08\x3e\x1c\xbf\x76\x5a\xac\xd3\xf7\x7d\xbc\xfe\xe1\xa7\x1f\x5f\xff\x29" +"\xf5\x13\xb4\xe5\xa9\xef\x94\x08\x3e\x1c\xd8\x09\x7e\xba\xee\xf6\x82\xeb" +"\xa9\x16\xb0\xd9\xfa\xe9\xba\x20\x30\xfb\xcd\x54\xe6\x92\x12\xc1\x07\xa3" +"\xef\x43\xd9\x6c\x51\x0e\xaf\x7d\xfc\xd3\xfa\xfb\xeb\x3f\xad\x7f\xfa\xe1" +"\xa7\x7f\xc3\x26\x9c\xfb\x5a\x89\xe0\xc3\x81\x04\xca\xd6\xdb\x6a\x5d\x6f" +"\xa5\xae\xad\x5f\x5b\x4f\x7d\x28\x66\x87\x53\x39\x25\x82\x8f\x00\x98\x09" +"\x5e\xff\x49\x76\x7f\xff\x6b\xfd\x6f\x1f\x5f\x13\xe4\x89\x1e\x71\x2a\x97" +"\xcb\x28\x11\x7c\x28\xa0\x13\xbc\x7e\xed\x27\x41\xe0\xf0\x4f\x1f\x7e\xdc" +"\x79\x32\xb9\x7e\x3c\xa7\x44\xf0\x11\x80\x9d\x60\xea\x3f\xff\x04\x04\x7e" +"\xf8\x71\xd7\x1b\x99\xd4\x61\x02\x12\x88\x22\xf8\x9d\x12\xc1\x07\x03\x59" +"\x4b\xc1\xbc\xa5\x9b\xbe\x2b\xef\x11\xa2\x03\x7f\xb9\xec\x7f\x51\x22\xf8" +"\x30\x88\x99\x60\xea\xda\xf5\x36\x7b\xd7\xaf\x04\x30\xfd\x9f\x90\x40\x25" +"\x82\x0f\x87\x57\x3e\xcb\xb9\xf2\x77\xfd\x30\x0a\x5c\xdf\xde\xd4\x1f\x73" +"\x4a\x04\x1f\x09\xd0\x09\x5e\x6b\xb5\xfe\xf6\xa1\xdb\xf5\x11\xf1\x96\x4b" +"\xd2\x97\x53\x03\xf1\x23\x00\x86\xde\x94\x1c\x7c\xaf\xbc\x8d\xdb\x6f\x74" +"\xd1\x27\x07\x62\xf5\x44\xfc\x40\xfc\xda\x1d\x39\x02\xb8\xa5\x0d\x7f\x98" +"\xeb\x81\x12\xc1\x87\xc1\x2b\x47\x0e\xd9\xf5\x05\x36\xd0\xa7\x44\xf0\xe1" +"\xe8\x73\x47\x0e\xa2\xa7\xae\x1f\x10\xa4\xa5\x33\x6d\xf9\x53\x22\xf8\x70" +"\x0c\x4b\xfa\xc8\xdb\xff\x94\xbb\x3c\xe5\xb2\xd6\x25\x82\xea\xbd\xe0\xa3" +"\x41\x3b\x90\x9b\x91\x02\x78\xf3\xcd\x61\x87\xbc\xd4\x14\x30\xa9\x5e\xca" +"\x3c\x1a\xf6\x4c\xe5\xfe\x4d\x0a\x60\x80\x90\x5d\x59\x41\xe0\x4c\x4a\x89" +"\xe0\xa3\x42\x1b\xce\xe6\xa4\xe0\xdd\xc0\xcd\xe3\x52\x16\xfb\xf0\x57\x89" +"\xe0\xa3\x60\x68\x2a\x73\x73\x4a\x36\x5c\x31\x20\x0b\x11\x0c\x88\x47\x62" +"\x18\x88\xd3\xff\xaa\x44\xf0\xc1\xd0\xdb\x02\x98\xcb\x4c\x60\xc2\x71\x47" +"\x16\x91\xc8\x0c\x74\x8f\x8a\xc0\x07\x43\x08\xa0\x33\xf6\xce\x60\x82\x86" +"\x2d\x18\x7e\x3f\x41\x11\x9c\x18\x4e\xbd\xfd\xfa\x63\xe1\x55\xe3\x5b\x08" +"\x60\x26\x87\x14\xc2\xc0\x31\x81\x49\xd0\x9e\x2f\x13\x29\x89\x99\xe1\xb1" +"\xc7\xc5\xbf\x04\x5e\xe8\xf5\x3c\x77\xc8\x1e\x70\x8f\x17\xa4\x2e\xa0\x67" +"\x85\x08\xee\xce\xe5\xf0\x3b\xe9\x83\xc8\xe9\x3f\x7f\xfe\xd8\xf8\x4f\x2f" +"\xf8\x8a\x9e\x2f\x64\x0f\x78\x99\xf4\x4d\xe5\xa6\x89\x9e\x15\xbd\xe0\x41" +"\xd9\x84\x7f\x8d\x4d\xf9\xf7\x9f\x7f\xfe\xd9\x70\xea\x0f\xa9\x54\xea\x5f" +"\x52\xa9\xab\x29\x81\xdf\x4b\xa2\xfe\x8c\xeb\xf8\xf7\xf7\xb0\xe7\x33\x58" +"\x85\xe5\x2a\xa4\xff\xfb\x0b\xbe\xa4\xe7\x0b\xd9\x03\x4e\xe0\x90\x71\x93" +"\x68\xd9\xec\xb7\x04\x99\xcb\x22\x81\xbf\x72\x08\x4c\xb5\x5a\x97\xaf\xb5" +"\xd6\x0f\x88\x1f\xc4\x55\x60\x0d\x88\xfa\x13\xac\xae\x0f\xc3\xdf\xd4\xb5" +"\xd6\x1f\x52\xad\xf5\xab\xc3\xad\x16\x72\x7b\xee\x05\x5f\xd2\x73\x85\x33" +"\x04\x4f\x60\xc7\x37\x83\x33\x98\xef\x88\x64\x2e\xd0\x21\x10\x98\xfb\xdf" +"\x40\xa0\xb7\xd5\x9a\x70\x09\xfc\xc3\x75\x20\xea\x32\xae\xff\xbf\xc3\xad" +"\xd6\x25\xd8\x0b\xe4\xa5\x7e\x03\xcb\xab\x46\xa0\x33\x07\xfc\x57\x42\xfe" +"\x98\xfb\x1a\x59\xcc\x84\x44\x1f\x88\x04\xfe\x93\x43\xe0\xdb\xd7\x5a\x81" +"\xdf\xb5\x2e\x6b\xd7\xd6\x03\xd7\xfe\x7e\xad\x95\x6a\x5d\xfd\xec\xda\x3a" +"\x10\x35\xf1\x7e\xeb\x0a\xec\x7a\xbf\x35\x71\xa0\xf5\xb7\xf7\xae\xb5\xae" +"\xbc\xd1\xfa\xe9\x9f\x5f\x31\x02\xdd\x39\x20\xb6\xde\xcc\x8c\x43\x60\xdf" +"\xc1\xf4\xbf\x1d\x76\x74\x4b\x48\xe0\xc4\xfb\xeb\x7b\xbd\xad\x2b\xa1\xf7" +"\xd7\xdf\xbe\x36\xf1\xbb\x56\x5f\xeb\xea\x95\xd6\x10\x12\xf5\x0f\x2d\xe2" +"\x6d\x4d\xc0\x2e\xad\xf5\x19\xb0\xf9\xf7\xc1\x6b\xeb\x57\x5f\x31\x02\x41" +"\x00\xe1\x29\x38\x7b\xf9\x3d\x0d\x27\x31\x40\x60\x5a\xb0\x98\x03\x31\x24" +"\xde\x6c\x3a\x9d\x45\x02\xff\xf4\xfe\xfa\xef\x0f\xb4\xfe\xf0\xef\xef\xaf" +"\x5f\x79\x73\xe8\x77\xad\xc1\x3d\x57\x0f\xac\x7b\x81\xa8\xcf\x7e\xd3\x4a" +"\x05\x5a\x7f\xdf\xd5\xba\x3a\xd4\x4a\xfd\xe9\xfd\x16\xc8\x23\x0a\xe6\xab" +"\x44\xa0\xfb\x14\x3c\x74\x49\xcb\x1d\x1e\xd4\xfa\x86\xff\x38\x03\x13\xc0" +"\x4f\x32\x97\xc5\xce\x29\x47\x02\x81\xc0\x3f\xec\x12\x04\xa6\xf6\xa4\x7e" +"\xd7\x3a\xbc\xf7\x73\x6f\x6b\x18\x44\xed\xcf\xbf\x69\x5d\x9d\x68\xad\xef" +"\x42\x89\x14\x04\x9e\x7b\xf5\x08\x9c\xca\x7d\x0b\x02\x38\x43\x06\xfb\xf6" +"\x1e\x98\x09\x78\xd3\x37\x03\x90\x2a\x86\x60\x82\xf6\x5f\x6f\x1f\x98\x11" +"\x04\x8a\x71\x16\x08\xbc\xfa\xf9\x67\xbf\x83\x21\xe4\xf3\x37\x5a\xad\xa3" +"\x57\xae\x02\x81\xc3\xc3\xad\x54\x87\xc0\xff\xfd\xea\x11\x98\xcd\x5d\x86" +"\x27\xde\x7f\x83\xf6\x0a\x4d\x38\xe0\x9d\x09\xa0\x72\x69\x2a\xd4\x3e\x40" +"\x77\x08\x04\x74\x13\x38\xf1\x0f\xeb\x7b\xaf\x8d\x01\x81\xeb\xc0\xa4\xd7" +"\x21\x70\x1d\x46\x98\x57\x8d\x40\x18\x27\x86\x73\xd9\x6f\xe1\xe9\xd5\x3b" +"\x93\x05\xda\x02\x53\x30\x0d\xdc\xd3\x47\xb4\xf7\xdc\x03\xb6\x26\xf0\x4f" +"\xd7\x60\xcc\x58\x07\x02\x5b\xad\xff\x7b\xb5\x4d\xe0\x6f\x5a\xaf\x26\x81" +"\xb9\xe1\xd4\x15\xa2\x05\x86\x03\xe4\x40\xe8\x93\x4b\x44\xfb\x6e\x10\x9e" +"\x82\x03\xb8\x7b\x6f\xc0\x25\x70\x68\xb8\x97\xc0\x56\x60\xb8\xb5\x3e\x86" +"\x04\xee\xfd\x73\x9b\x40\x98\x28\xbe\x6a\x04\x3a\x4d\x18\x1e\x7d\x07\x53" +"\x7d\xe2\xed\x41\x80\x1c\xcf\x0c\x92\xc9\xaf\xc5\x2b\x95\xa9\x9b\xbf\x96" +"\x04\xae\xbf\xae\xf7\x36\xe1\x56\xa8\xaf\x75\x05\x08\xf4\xb6\x8e\x76\x08" +"\xec\x7b\xf5\x08\x24\xf8\x31\xaf\x7c\x97\xff\xc7\xcb\x1f\x06\xa6\xf0\x5d" +"\xc2\xc1\xcc\x65\xaf\x78\xa0\x03\x42\x33\xee\x28\x7c\xf5\x40\x2f\x81\xd7" +"\xfe\xfe\xfe\xdf\x75\x68\xc2\xa4\x95\x02\x02\xff\x65\x58\x10\x18\xba\xf6" +"\xea\x11\xb8\x2b\x3b\xb3\x4b\xbc\x08\xbc\xf2\xc7\x5c\x76\x62\x68\x12\xc6" +"\x5f\x3d\x8b\xba\x10\xb1\x77\x77\x46\xcc\x03\xcf\xc3\xd3\xc7\x81\x56\xea" +"\xdf\xaf\xad\xff\xf3\xe7\x57\xde\x6f\x0d\x03\x45\xbf\x83\xe7\xe2\xab\x40" +"\x66\x00\x7a\x3d\xbd\xb5\x7e\xad\xf5\x6f\x7f\xba\xb6\x7e\xf8\x1f\x5e\x3d" +"\x02\xfb\xa6\x32\x97\xa6\x5c\x2d\xe6\x0c\x39\x88\x6f\xb3\x3e\x49\x67\xb2" +"\x13\x62\x6f\xbf\x9c\x07\xc2\x63\xee\xff\x91\x2f\x13\x52\x7f\x86\xf1\xe4" +"\x27\x90\xc3\xbe\x6b\xeb\xff\xf8\xf9\xf9\x56\xeb\xef\xbf\x59\xbf\x1a\x12" +"\x0f\xc8\xbb\x60\x3c\x01\x2a\x3f\xff\x9f\xaf\x16\x81\x1d\x11\x14\xed\xb8" +"\x6f\x88\x60\x4f\x98\xce\xc8\x89\xcc\x41\xd9\x84\x77\x89\xb7\x08\x38\x46" +"\x88\xd9\x1e\xb6\xe1\xf7\x88\x76\x15\x5f\x26\xfc\xdd\xdb\x4a\xc1\xb3\x9c" +"\x24\x70\x3d\x04\x04\xb6\xfe\xe3\xd5\x22\xb0\x47\x04\xf7\x4a\x87\x27\xc3" +"\xae\x1a\x64\x4a\x12\x18\x80\xd5\x03\xa9\xcb\xda\xd0\xd0\xd1\x3f\xe9\x57" +"\x86\x2e\xe3\x2b\x42\x7c\xf1\x37\x31\x3c\x3c\x04\x53\xea\x54\x40\x23\xc3" +"\x57\xfa\x52\xa9\xa3\xf1\x5d\x57\x3e\xff\xaf\xff\xf3\xd5\x22\xb0\x47\x04" +"\x7f\x2d\x95\x4a\xe4\x0d\x47\xad\x31\x2c\x9b\xf0\x95\xa1\xa1\x2b\x83\x44" +"\x7f\x8f\xf4\x5d\xfd\x2c\x00\x9d\xa4\xfb\xe6\xf9\xfc\xeb\x83\xfb\x27\xae" +"\xad\x5f\x3d\x3f\x74\xf8\xf5\x37\x0f\xf7\xf5\xfd\xf3\x67\x81\x03\xaf\x5a" +"\x1f\xd8\x2b\x82\xc7\xd3\x33\x81\x9e\x9d\xc7\x73\x33\x57\x25\x59\x63\x63" +"\xbf\xff\x1c\xfe\x7f\xfe\x67\x5c\xe9\xc2\xbf\xf7\xbd\xb9\xe9\x95\xfe\xa5" +"\x17\x73\x25\x2f\x0a\xdd\x22\x28\x5f\xe5\x77\x70\x30\x37\x73\xe0\xc1\xfa" +"\x8f\xcf\x0e\x0f\x6f\x4c\x7a\xd5\x94\x4a\x3d\xbd\x60\xb6\x8b\xc0\x41\x31" +"\x8a\x5c\xda\xf3\x40\x0c\x0d\x0d\x6d\x4c\x7a\xfb\xc5\x5d\xcb\x8b\x41\x8f" +"\x08\x5e\x22\x07\xae\x07\x88\x36\x05\xbf\x37\xf1\x15\x43\x76\xe6\xcd\xd4" +"\x95\x57\x4d\xd3\xfb\x98\xe8\x11\xc1\xef\xde\x86\x3f\x1f\xe7\x70\x32\x8d" +"\x1f\x27\x78\xb3\x37\xa7\xd2\x37\x1f\x9a\xc5\x2b\x8e\x9e\xb9\xe0\x5e\x6c" +"\xc8\x72\x15\x76\xfd\x3a\x33\x9c\xcd\x85\x1e\x9a\xc3\x2b\x8e\x6e\x11\xcc" +"\x78\x3b\x9f\xa8\x86\x88\xfe\xc9\xcd\xe3\x19\x25\x80\x0f\x45\x97\x08\xde" +"\xec\x10\x98\x9b\xd0\xff\xa8\x04\xf0\x91\xd0\x25\x82\x37\xb5\xae\x29\x0d" +"\x74\x7f\x4a\x00\x1f\x09\x1d\x11\xfc\x2e\xe0\xed\x30\x98\x55\x02\xf8\x88" +"\xe8\x12\x41\xf1\x69\x6f\x5b\x06\x95\x00\x3e\x22\x7a\x1f\x47\xda\x50\x02" +"\xf8\xa8\xe8\x99\x0b\x76\x75\x82\x4a\x00\x1f\x15\x5b\x89\x60\x66\x48\x09" +"\xe0\x23\x63\x0b\x11\xcc\x2a\x01\x7c\x1c\x6c\x16\x41\x25\x80\x8f\x85\x4d" +"\x22\xa8\x04\xf0\x31\xb1\x51\x04\x95\x00\x3e\x26\x36\x8a\xa0\x12\xc0\xc7" +"\xc5\x06\x11\x54\x73\xc0\xc7\x45\xaf\x08\x2a\x01\x7c\x7c\xf4\x88\xa0\x12" +"\xc0\xc7\x47\x97\x08\x66\xd5\x53\xf0\x93\xa0\x23\x82\xea\x35\xcc\x13\xa1" +"\x2d\x82\x4a\x00\x9f\x10\xae\x08\x2a\x01\x7c\x42\x38\x22\xa8\x04\xf0\x89" +"\x81\x22\x98\x55\x02\xf8\xe4\x00\x11\xbc\x3c\xa5\xe6\x80\x4f\x81\x5d\xd9" +"\xef\xf6\x0e\x1d\x50\x02\xf8\xc4\x00\x11\xcc\x7d\x9c\x53\x02\xf8\xe4\x90" +"\x6e\x63\x94\x00\x3e\x31\x50\x04\x73\x4a\x00\x9f\x02\x28\x82\x4a\x00\x9f" +"\x02\x7d\x53\x39\x15\x1b\xf2\xa9\xf0\xc6\x50\xe0\x45\x57\x41\x41\x41\x41" +"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\xe1\x25\x85\x9e\x4b" +"\xa7\x95\x86\xe2\xc9\xa1\x67\x33\xb9\x5c\x56\x19\x9c\x3e\x31\xa6\x72\xb9" +"\x2b\x6f\x4e\xe5\xa4\x7b\x67\x85\xc7\x46\x7f\x46\x78\x81\xf0\x0a\xdb\x5d" +"\x81\xd4\x04\xfe\xed\x4b\x09\x23\xf2\x03\x13\x32\xed\x91\x54\x18\x7d\xdd" +"\x77\xc1\x9b\xeb\xda\x33\x7c\x85\xbc\xf9\x54\xd5\x94\xd0\x73\xa1\xde\x7c" +"\x9d\xe4\x54\xa8\xef\x11\x75\x2c\xc7\x77\xbc\xa5\x4d\x3a\xea\x9d\x83\x8e" +"\x2b\x21\x32\x99\x4e\x4f\x88\x1f\x34\x27\xdf\x9d\x41\x07\x39\x7a\x56\xa6" +"\x79\xd3\x02\x37\xb6\xcb\xcb\x9b\xfe\xa2\xbd\xae\x65\xd3\xed\xf5\xbe\x6c" +"\x06\xfa\x89\x47\xa9\x0d\xfa\x04\x85\x1e\x79\xbb\xe4\xfe\xf4\xb4\x37\xbb" +"\x69\xef\xee\x74\x2e\x9d\x9b\x7e\x94\xec\x09\xd9\x7c\xf6\x53\x42\xcf\x7d" +"\xeb\xac\x39\x8a\x46\x2f\xd4\x26\x83\x82\xf9\x26\x72\x96\x9d\x9e\xfc\x0a" +"\x36\x1c\xd6\xbc\x99\xc0\x6b\xe9\xc1\x83\x5b\xd7\x01\x64\xc0\x9b\x9e\xee" +"\x6c\xf4\xa7\xdb\x7e\x10\x26\x33\x13\x7d\x93\x99\x5e\xb7\x08\xde\xad\xeb" +"\xe3\x4d\x7f\x43\x76\x6d\x2e\xc0\x49\x06\x02\xc9\x5b\x1b\xf7\x7a\xd3\x33" +"\x64\x17\xec\x7f\x38\xf6\x3e\x03\x02\xfb\xdb\xfa\xc5\x83\x52\x44\xde\xba" +"\x31\x38\x99\x0e\x91\x49\xf8\xf9\x0b\xd4\x2d\xd0\x0f\x25\xbe\x96\x99\x12" +"\x52\xe1\xfd\x92\x00\x81\x64\x6b\x59\xea\x9f\x86\x96\x3a\xd8\xd9\xe8\x10" +"\x88\x57\xbf\x89\x95\xc9\xad\xeb\x23\x8e\xcd\x6e\x72\x41\xe1\x26\x43\xbf" +"\xf2\xda\x86\x3b\x41\xf0\xd6\xf4\x4d\x4e\x3f\xec\x4a\x01\x33\x90\xd1\x4e" +"\x7b\x9c\x39\x96\xc3\xae\x0b\x1d\xeb\x7a\xd3\x82\xca\xc9\xf7\xe0\xd2\x2f" +"\x91\xec\x5f\xc8\xb1\x1b\x58\x59\x2f\x08\xe2\x31\x20\x14\x1b\xa4\x77\x5a" +"\x10\x38\xb5\x75\x4e\xd3\x18\x56\xbd\xb3\xd1\x21\xf0\xad\x34\xd6\x3a\xdb" +"\x73\x74\x5f\xef\x66\x1b\x82\xa9\xcd\x05\x74\x25\x6f\x24\xb0\x2f\x7d\x03" +"\x12\xfa\xbf\xd8\x74\xce\xe6\x4c\xb6\xed\x7b\x9e\x02\xe8\xc5\x65\x77\x66" +"\x37\xb0\xd4\x97\x9d\xc6\x84\x14\xd6\xf6\x52\x1f\xb4\x95\xd7\x32\x20\x87" +"\xa2\x59\x4e\x61\xb5\xe5\xf1\xaf\xa5\x37\x49\x87\x84\xde\xdd\x88\x70\xa3" +"\x43\xa0\x6c\xbd\x93\x3d\x27\xee\x4e\x93\x2d\xe1\xdd\xba\x2d\x76\x25\x6f" +"\x24\x50\xee\xf2\xfe\x65\x9b\x0b\xec\xc2\xe4\x8d\x67\xe0\x5c\x25\x87\x4d" +"\xe3\x1b\xd9\x42\xa6\xdb\x55\xba\xe4\x95\x0c\x40\x91\x7d\xb2\x5f\xfb\xad" +"\x73\xf7\x84\x04\xe6\x66\x60\xda\x13\x98\xca\x05\xa0\x73\xff\x96\xec\xca" +"\xee\x06\x09\x9e\x84\xc9\xb8\x06\x59\xc0\xe0\x21\x37\xfa\xd3\x07\xd3\x22" +"\x70\x83\xd3\xef\x78\xd1\x85\x34\x0c\x49\x53\x37\x26\xd3\x13\x70\x62\x2e" +"\x95\xbb\xe9\xcd\xe5\xc8\xc1\xcc\xe4\x0d\xf4\x8b\x37\x25\x7c\x82\x62\xc1" +"\xbb\x89\x38\x74\x82\x40\x72\xbf\x8c\x3f\xe2\x24\x7b\x61\xa4\xc3\x56\x91" +"\x4d\x65\x33\x30\x9a\x88\x26\xd3\x2f\x2b\x38\x21\x4b\x86\xec\xb3\x37\xbc" +"\xd9\x29\xec\xb3\x3b\x09\xa2\xe4\xfe\x34\x0c\x64\x53\x90\x7e\x10\xf3\xd6" +"\xb2\x37\x9d\x0c\x9e\x0e\x99\x69\x10\x17\xa8\xea\x04\x94\xe4\xb6\x02\xe8" +"\xf9\x80\x43\xa8\xd9\x04\x3a\x76\x91\x23\xab\xcb\x2e\x12\x08\x42\xd9\x97" +"\xfe\x12\x5b\x44\xf6\xdb\xc9\xcc\x9b\xd9\x74\x36\x9b\x0e\x0c\xa7\x67\x2e" +"\x4d\xc1\xb5\x1c\xbb\x71\x30\x3d\x81\x1b\xfd\x98\x2c\xe2\xff\xb8\xc3\xb6" +"\x37\x73\x20\xfd\x15\x5c\x46\x26\x7d\x43\x9b\x4a\xa7\x02\x90\xfb\x6f\x33" +"\x62\x80\xdd\x8d\xf7\xeb\x2b\x97\xa9\x49\x3c\xf4\x72\x16\xa5\xff\x9b\x3e" +"\xd9\xb1\x38\xc9\x53\x69\x41\xa0\x28\x31\x9b\x91\xcc\xbd\x25\x26\x08\x80" +"\x63\x37\x0e\xe0\x20\x0d\xa3\xb5\x18\xb3\xa7\xbb\x12\xfa\xd3\xc3\xe9\x2f" +"\xbc\x93\x99\x94\x17\x72\xd5\xd3\x97\x27\x33\x90\x95\x9b\xc1\x53\x12\x38" +"\x41\xbc\x4e\x0d\x8e\xbb\x04\xf6\x63\xd5\x7b\x08\xf4\x4e\xb9\x37\x0b\x09" +"\xec\x83\x24\xd8\xd3\x3f\xed\xc5\x71\x71\x62\x77\xfa\x5b\xf8\x4b\x50\x88" +"\x61\xc9\x4e\xe8\xb0\x5b\x08\xb0\x48\xc6\x8b\x77\x08\x7c\xeb\x4b\x68\xcd" +"\x20\x9d\x97\x26\x33\xa2\x81\x4f\x8a\x4e\xf6\xb5\x74\x2e\xf3\x06\x5c\x4a" +"\xff\xb4\x64\x6a\x66\x0a\x76\x81\xc0\xe3\xc9\xd9\x4c\xbf\x6c\x76\x4e\x32" +"\x56\x4b\xf4\xcb\x33\xde\x34\xf0\x28\x28\x9f\x74\x09\x04\xe9\x84\x1c\x27" +"\xd3\x53\x37\x76\xa5\x81\xba\xaf\xba\x12\xde\x82\x83\x6f\x88\x26\x0c\x8b" +"\xb8\x3c\xa8\x6f\x26\x90\xfd\x72\x87\x08\x94\x23\xd3\x6e\x97\xc0\xc9\x6f" +"\x1c\x02\x2f\xb9\x04\xbe\xd6\x9e\x9b\x89\x3e\x10\x2b\x93\x21\xc7\x26\xfa" +"\x33\xa9\xa9\xf4\x37\xc0\x85\xd7\x25\x70\x5a\x4f\xa7\x52\x40\x98\xec\x01" +"\x64\xce\x6d\x02\x27\x67\x52\x30\x39\x84\x4b\x80\xeb\x69\x13\x08\x39\x06" +"\x06\x45\x8e\x13\x6d\xa6\x84\xc0\x63\xe7\x7b\x30\x9d\x95\x75\x73\x92\xdb" +"\x04\x5e\xc2\x12\x26\x6f\x74\x13\x08\xed\x06\xa4\x11\x2a\xf6\x7a\x1f\xee" +"\x87\x36\xde\x49\x90\xdd\xb9\x43\xe0\xe4\x97\x42\x04\xf0\x66\xef\xc0\xa8" +"\x22\x08\x9c\x26\xe4\x72\x47\x02\xfb\xa0\xe0\x0d\x12\x38\x9c\x4a\x3b\xd5" +"\x14\x04\x4e\x62\x2b\x9a\xc8\x0e\xbe\x96\x49\xa5\x52\x13\x0e\x53\x52\x02" +"\xbd\x40\x60\xea\xf2\xd6\x04\x66\x67\x60\xdf\xa0\x94\xbb\x2e\x09\xc4\x5b" +"\xf3\xdb\x8c\x33\x4a\x8b\xb6\x3a\x28\x7a\x0c\x28\x58\x4f\x3b\x23\x86\x93" +"\xdc\x26\x70\x62\x33\x81\xfd\x69\x5c\x42\xc8\x12\xee\x9f\xcc\xec\xee\x24" +"\x68\x97\xb0\x53\x74\x08\xcc\xc2\x05\x81\xf0\xc2\x55\x4f\xee\x04\x81\x78" +"\xab\x61\xc2\xf7\x55\xa7\x0f\xc4\xce\x08\x49\x85\x6b\xcc\xde\x18\xd4\x64" +"\x47\x71\xcc\xe9\x2f\x04\x81\xfd\xe9\x03\x99\xf4\x37\x39\xb8\x96\xd7\xfb" +"\x06\xc9\x06\x02\x03\xaf\xf7\x91\x1e\x02\x49\xda\x19\xfd\xb2\xdf\xf4\xf5" +"\xb9\xb4\x75\x13\x28\x72\xbc\x9c\x69\x33\xd5\x2f\xce\xc7\x99\x14\x99\xec" +"\x22\xb0\x9f\x6c\x49\xe0\x6b\x4e\x03\xea\x97\x4d\xdc\x25\xf0\xb7\x40\x60" +"\x3b\x81\x4c\x65\x3a\x4d\x58\xe4\x7b\x63\xb0\x9d\xc1\xd3\x01\x46\x61\x0d" +"\x6e\xf3\x41\xa0\xc7\x7d\x1a\xc2\x67\x3a\x0d\xb2\x87\x9a\x42\x39\xce\xd3" +"\x45\x7f\x37\x81\xf0\xb4\xf2\x97\xec\x0d\xd1\x00\xe1\x99\x63\x03\x81\x70" +"\xf6\x7b\xbd\x04\x66\x1d\x16\xb0\xcb\xf1\x6e\x4d\x20\x34\xd1\x2f\xdb\x4c" +"\x11\x29\xf6\x20\x29\x7d\x59\xa7\x58\x27\x79\x2b\x02\xfb\x9d\x19\x0e\x08" +"\x1b\xce\x65\x5d\x02\x5f\x03\x02\xdb\x09\xfd\x82\x47\x97\x40\x10\x10\x78" +"\xbe\xda\x29\x02\x67\xb0\x11\x64\xd2\x38\xae\xcb\xba\xca\x6e\x1b\x6a\x7f" +"\x2c\x83\x2d\x0b\x2b\x13\x22\xed\xa7\x34\x41\x60\x5f\x1a\x2a\x04\xe3\x30" +"\xf6\xf3\xfd\xd3\x1b\x08\x9c\x26\x7d\x5f\xf5\x12\x38\x29\x46\xd2\xb7\x26" +"\x70\x3a\x33\x89\x97\xb0\x99\x40\xb2\x81\x29\xe4\x1a\xea\xd3\x7f\xc3\x69" +"\xfe\x1b\x09\xec\xea\x03\xbd\x69\x1c\x4b\xfa\x6e\x60\x65\xbc\x62\xe6\x25" +"\xea\xfc\xd6\x8d\xdd\x9d\x04\xc1\x5e\x5b\x02\xe1\x34\x78\xca\xda\x21\x02" +"\xf1\x49\x64\x77\x1a\x1b\x99\x37\x2b\x07\x5a\xe8\xb6\x61\x82\x02\xb7\x68" +"\x12\x19\x82\x87\xe2\x41\x78\x00\x21\xfd\xdd\x7d\x20\x5c\x6e\xe0\x2d\xc1" +"\x11\xf6\xfd\x3d\x04\xa2\x38\xef\x9e\xee\x25\x50\xc8\x48\x5f\x0e\x7b\x2b" +"\x3d\xd3\x23\x81\x83\x93\x2e\x81\x93\x69\x77\xb4\x10\x4c\xc1\x18\xd5\x87" +"\x1d\x19\xdc\xa7\xc0\x56\x04\x76\x49\xa0\x14\xf0\xdd\x30\x7c\x4d\x63\x65" +"\xdb\x7d\xe0\x97\x5d\x09\x70\x64\xa7\x09\x83\x60\x40\x6f\xe2\x64\xe0\x4d" +"\x3d\x25\x81\xfd\x38\x03\x1c\x4e\x05\xd0\x99\xa9\x4c\x48\xe7\x72\xd0\x4b" +"\xf4\x67\xf0\xc9\x44\x4b\x4f\xc0\x03\x9d\x7e\x43\xf4\xf2\x02\x6f\x89\x0b" +"\xc2\xc9\x00\x5c\x0b\x48\x62\x4e\x70\x21\x08\xbc\x91\x13\x95\x12\xe2\x0c" +"\x1b\x1d\x02\x35\x0c\xe4\x35\xf5\x15\xbe\x93\x80\xe6\xe3\x12\x38\x35\x0d" +"\x13\x8c\x74\xe6\x92\x7c\xc6\xe9\x6f\x77\x76\xd3\xb2\x16\x21\x2f\x10\x85" +"\xc7\x4d\x77\x25\x6f\x49\x20\xce\xd7\xf1\xee\x23\x45\x7f\x11\xbd\x26\x4e" +"\x54\xa1\xf6\x9d\x04\x51\xd2\x17\x93\x99\xc9\x09\x51\xf3\x09\x10\x4c\x27" +"\x83\x63\xe9\xa7\x9c\x4c\xeb\xee\xd7\xde\x9a\xb3\x22\x26\xa1\xdf\x60\xec" +"\x28\xbc\xa4\x63\x19\xe4\x20\x7d\x45\x77\x5e\x76\xed\x82\xc9\x3d\xde\xef" +"\xbf\x10\x0d\x77\x1f\x4f\xa7\x6f\xbe\x3e\x99\xbe\x7c\x1c\xae\x21\x9b\xfe" +"\xe6\x20\x48\x32\x88\x33\xec\x81\x27\x94\xc9\xf4\xb7\xc7\x9d\x47\x91\x5d" +"\x82\x68\x7c\x32\x80\x67\x9c\x6c\xe6\x30\x9c\xe1\x85\x61\x1d\x08\x9d\x4c" +"\xdf\x94\x2f\xc3\x9d\xe7\x54\x98\x60\xdf\xc0\x92\xf0\x05\xd8\xb7\x28\xb2" +"\xe2\x89\xa4\x9d\x0c\x19\x42\x26\x97\xa7\xd2\x37\xa1\xa8\x03\xce\x93\x44" +"\x1f\xdc\x33\x90\x28\xbc\xf5\x99\xf7\x74\xd8\x0d\x04\x66\xa6\x32\x83\x5d" +"\x09\x50\xa9\x2c\x96\x97\x11\x41\xd9\x20\xef\x9b\x83\x90\xc1\x2e\xc8\xe0" +"\x58\xfa\x3d\xf2\x74\x98\x74\x5e\x82\x1e\x77\x28\x1a\xc6\x48\x6e\x01\xb8" +"\xa2\x14\xe6\xac\x09\xe7\x9c\x70\xe1\x0e\xcd\x07\x70\x22\x02\x3b\x27\xc4" +"\x43\x33\xe9\x83\x43\x35\x98\xb6\xc0\x49\x64\x57\x2a\x30\x8c\x3b\x87\xf1" +"\xc4\x5d\xa9\xb7\x9d\x64\xc4\xe0\x2e\x91\x25\xa4\xc2\xc5\xa5\x52\x43\xa9" +"\xd4\xa5\x3e\x58\x85\x65\xd7\x65\x38\x1d\xbf\x97\xee\x97\x63\x88\x8e\xf3" +"\x22\xc1\x39\x16\x7c\x20\x15\x3a\x20\xce\x74\x93\x21\x43\x58\xbd\x04\xa7" +"\xc0\x1a\x64\x2a\x09\xec\xc3\x89\x13\xfc\x0e\xa7\x2e\xe1\x91\x48\x60\x0a" +"\x2b\xd1\x49\x80\x92\xbc\xa9\xc1\xbe\xd4\x25\x1d\xf3\x79\x53\x56\x33\x05" +"\x79\xbf\xe7\x4d\x3d\xed\xf3\x71\x7f\x26\x77\x19\x84\xe3\x78\xfb\x8d\x74" +"\x1f\x91\x59\x0e\x3a\x5b\x88\xae\x17\xd2\xed\xf2\xc4\x9e\xc1\xc1\x4e\x92" +"\xfb\xf3\xba\xb3\xd1\x55\xb3\xbe\xbe\xae\x9f\x3e\xb1\xab\xaf\xbd\x26\xf0" +"\xd6\x74\x77\xb6\x6e\xce\x9d\xed\xf6\x7b\x9e\xf6\x56\x57\x09\xce\xb1\x7d" +"\x4e\x9e\xd8\xd2\x07\x7b\x12\xe0\x48\xe7\x14\xb9\x0c\xb6\xeb\xd1\x9b\xef" +"\x13\x61\xca\x71\xa7\x36\xf1\xf4\x59\x3d\x31\x76\xa5\xdc\xf7\xe1\x3b\x02" +"\xf7\xe1\xf4\xf9\x40\x17\x76\x43\x2f\x56\x2b\x37\x99\xde\xf8\x96\xf4\xa9" +"\xf0\x7c\x09\xfc\x39\xe8\x85\x27\x1f\xe9\x8d\xfc\x23\x63\xf7\x4e\xbc\x66" +"\x79\xa9\xf0\xf4\x5d\x79\x6f\x6e\xa9\xa7\x9d\xdd\xbd\x74\xd8\xd9\x57\xc5" +"\x7d\x83\x3b\x9b\x9f\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\xc2" +"\x2f\x06\x66\x94\xe8\xf3\xa5\x1f\xee\x12\x72\x72\x7e\x7e\x21\x4e\x7c\x4d" +"\x4c\x3d\x39\xdf\x75\xc4\xfc\xfc\x7c\x63\xbb\xd3\x7d\xf3\x96\x5c\xb9\x08" +"\x47\xdd\xed\xa4\xaf\x75\x6f\x6c\xc0\x42\xb7\x06\xc2\x0f\xe7\xcd\x37\xdd" +"\x5c\x08\x31\xca\x4d\x4b\xd6\x61\x7b\x60\x59\xf3\x91\xf9\x76\x36\x27\xec" +"\x66\x34\x52\x7a\xc0\x09\x3a\x54\xe7\xe2\xfc\x42\x3b\xdf\xa4\x1d\xc5\xa2" +"\xb0\xe4\x07\x97\xf4\x08\x08\x5a\x84\x14\x17\x07\x6a\x84\x68\x74\x25\xc9" +"\x02\x03\x0c\x53\x0d\x0a\x7f\x34\x4b\x1e\xc2\xab\x49\x1a\xdf\xee\x7c\xee" +"\x54\xdc\xa0\x2b\x67\x6a\x9d\x64\xd3\x39\xc3\x97\xdf\x78\x82\xa5\xf5\x64" +"\x36\xb0\x02\xd9\x97\xca\x25\x77\xbb\x78\x2a\x59\x92\x75\xd8\x1e\x73\x17" +"\xe8\x4a\xe2\x34\x8d\xba\xdb\x6b\x43\x3c\x9e\x58\x7a\xd0\x19\x50\x1d\x93" +"\x5a\x26\x23\x26\x6e\xe9\xb5\x84\x85\xbf\x09\x36\x4a\xad\x07\x17\xf5\x70" +"\x14\xa1\xe0\x98\x20\x90\xd0\x92\x8f\xc6\x0d\x21\x6c\x1e\x24\xf0\xdd\x45" +"\xe7\x90\x8a\xb6\x7d\x39\xc5\x92\xfc\xf5\xd0\x3c\x59\xed\x24\xfb\x9c\xcb" +"\x0b\x6f\x24\xd0\x5c\x24\x73\xdd\x12\x68\x92\x72\x45\xef\x22\xd0\x26\x46" +"\xc9\xd8\x56\xe0\x25\x0a\x50\x55\x33\xda\x26\xd0\x00\x5e\xf2\xc1\x4d\x77" +"\xaa\x1b\x7e\x1a\x35\x68\x1e\xf2\xe5\xa2\xcc\xea\x80\x85\xbf\xb1\x1a\xe1" +"\x0f\xe4\xfd\x51\xc0\x59\x17\x81\x1e\x6a\x8d\xdf\x22\x47\x9b\x23\xfb\x68" +"\xb0\xa1\xf1\x5a\x7c\x74\x8c\x20\x81\x84\x2f\x12\x4f\x83\x18\xcd\x38\x89" +"\xc4\x8d\xc2\xe9\x66\xa1\x70\xb4\x40\xde\x39\x47\x8c\x55\x57\x02\x81\xc0" +"\xf1\x23\x5a\x72\x96\x14\x0a\xe3\xb3\x82\xc0\x33\xb7\x93\x71\x83\xdf\x0b" +"\x19\x0d\xbd\x90\x4f\x06\x4e\x34\x43\xe4\x44\x33\xc0\x6b\xe3\x85\x0f\x0a" +"\xb7\x4e\xcc\x92\xa4\xe0\xd1\x03\x04\x92\x78\xf9\x6e\x33\x80\xf9\x11\x9d" +"\x36\x48\x7e\xfc\x96\xaf\x70\xa2\x69\x34\x49\x61\x16\xc8\x86\x3a\x18\x76" +"\xc8\x28\x7c\xd0\x24\xfa\xaa\x10\xde\x53\x50\x55\x3d\x44\x3f\x58\x21\x64" +"\x34\x8a\x65\x7d\x6f\x9c\x2f\xe4\xa1\xbc\xef\x4f\xac\x78\x0a\xb7\x9a\x21" +"\x2d\x79\x81\x44\x9a\x21\xc8\xa5\x41\xf6\x43\xa5\x91\x40\xac\xe0\x2d\x93" +"\xde\x46\x3a\xeb\x89\xb8\x43\x60\xb1\xea\x83\x4b\x89\x42\x41\xd1\xcd\xdc" +"\x3c\x0a\x0c\x9b\x05\x3a\x04\x9a\x34\x14\xae\x19\x2c\xc1\x8e\x50\x9b\x79" +"\xca\xb5\xb1\x2a\x17\x04\xea\xd4\xd2\xed\x84\xc5\x93\x96\x59\xb5\xf7\x72" +"\x9b\x15\x99\x5e\xf3\xad\x2e\x84\x12\x6b\xb4\x43\xe0\x2a\xdc\x5a\x1e\x4d" +"\xb0\xd8\x39\x41\x60\x84\xf1\x9a\x8f\xde\x3b\x6a\xf3\x38\x67\xf4\x83\x5a" +"\x71\x59\xb7\xf9\x1d\x5e\x1b\xa3\xb3\x7c\xf9\xdd\xe5\xc8\x6a\x55\x9e\x09" +"\x04\x92\xb2\xcd\x2d\xcc\x0f\x6e\x28\x30\x18\xae\x99\xd4\xa6\x6b\x34\x9e" +"\x60\xbc\x62\x40\x1d\xf8\x5c\x55\x87\x94\x78\x62\xce\x11\x18\x2c\x15\x12" +"\x42\xef\x36\x19\x16\xcd\xe2\x70\x8b\x23\xcc\x86\x7f\x87\x39\xe3\x96\xd9" +"\x5c\xd5\xed\xe4\x32\xe4\xc2\x02\x76\xb2\xe4\x12\x18\xae\x45\x04\x81\x26" +"\xbd\x73\xa2\x10\x92\x12\x68\x19\x74\x84\xe6\xa1\xa0\x27\x14\x45\x73\x14" +"\x7a\x24\x97\xc0\x55\xbe\x4a\x06\x6a\x66\xcd\xac\x7a\xe8\x11\x1a\x2a\x2e" +"\xfa\x59\x10\x09\x64\x76\x3d\x64\xd6\x06\x96\xf8\xb2\x05\x2c\xc6\xcb\xd5" +"\xa6\xc9\x74\x2b\x7c\xbf\x68\xd1\x78\x47\x02\xed\x1a\x49\x58\x31\xcb\xa4" +"\xd8\x92\x81\x40\x3f\x7b\xb7\x4e\x68\xde\xac\xc4\xac\x22\x4b\xbe\xcb\xc2" +"\x15\xb3\x16\x5e\x8c\x2d\x42\x5a\x71\xc9\x0c\xf1\x38\xeb\x22\x70\x99\x97" +"\x30\x3f\x42\x22\xc0\xc6\x40\xcd\x43\xe3\xd4\x2a\x5b\x31\x66\xd6\xa1\x0e" +"\x1e\xba\x8f\x06\xe8\x8f\x65\x8b\x2f\xff\xb5\x8b\xc0\x38\x94\x6e\x95\x05" +"\xe9\x2c\x10\x83\xca\xbe\x03\xb5\x8e\x16\x97\x0e\x55\xc3\xd5\xb3\x26\x33" +"\x99\x87\x5e\xa0\x51\x3a\x2b\x08\x04\xe4\xcd\x9a\xe8\x9a\x34\x9b\x2e\x9b" +"\x20\x37\x24\x56\xb7\x59\x5c\x83\x43\xf2\xb1\xda\x40\xe5\xc9\x08\x3c\x0b" +"\xc2\xd5\x26\xd0\x86\x7a\x09\x02\xa1\x20\x0f\x54\x65\xd1\xa4\xd8\x1b\x15" +"\x6b\x70\x7b\x06\xd8\x5c\x85\xb3\x00\x5f\x2d\x5b\xd0\x61\x19\x74\x34\x9e" +"\x58\xe5\x7f\x85\x83\xda\x04\x36\x57\x61\x44\x89\x2d\x69\xdc\x72\x08\xac" +"\xfb\x91\xc0\x18\x2b\x2e\x42\x27\xe0\x69\xf2\x8a\x59\x35\xa2\x82\xc0\x43" +"\x2c\xa2\xd3\x55\x1a\xea\x10\x58\x2a\x5a\x45\xd1\x1d\x68\x9c\xde\x47\x02" +"\xe1\xaa\xca\xa5\x58\xc5\x47\xa1\x0e\x3e\xaa\xcb\xed\x04\x0b\x75\x11\x08" +"\x49\xfc\x1e\x87\xbe\xcf\xc3\xa9\x05\x04\xd6\x7d\x4e\xad\x19\x0c\x18\x03" +"\x35\x1f\x10\x38\x42\xa3\x1c\xa9\x92\x12\xe8\x97\x04\x9a\x4b\x9c\x99\x58" +"\xed\x18\xb4\x11\x99\x4f\xac\x32\x50\x23\x4f\x04\x7b\x9e\x57\xdb\x04\xfe" +"\x08\xeb\x40\x20\x3b\xb4\xe4\x10\xa8\x71\xac\x71\xb1\x92\xc0\xd1\x79\xe4" +"\x54\x04\xa4\x62\x65\x24\x54\x06\x86\xb8\x0d\xdd\xc7\xc8\xd1\x6e\x02\xf3" +"\xe3\x04\x2f\x19\xd2\x7b\x09\xac\x8d\x44\x8b\xf7\x21\x17\x2e\x2a\x29\x08" +"\x34\xd9\x8a\x4e\x57\x46\x02\xdd\x04\x2e\x42\x7e\x21\xe2\x89\xeb\xe5\x6a" +"\x0f\x81\x50\x87\x08\x85\x73\x70\xfb\x5d\xda\xd8\x40\xe0\x5f\xe1\x1c\x5f" +"\xc0\xe0\xdd\x04\xfa\xeb\x06\x65\x40\x20\x15\x04\x46\xf0\xd8\x1e\x02\x63" +"\xf7\x23\xd4\xc6\xb2\x63\xd0\xa4\x43\x4f\x47\xa0\x0e\xe2\x57\xef\xf4\x81" +"\x61\x1a\x82\x35\x6e\x87\x1c\x02\x8d\x20\x4e\x39\x8a\x15\x39\x05\xd8\x73" +"\xae\x5c\x81\xd9\x42\xa8\x9c\xc7\x66\x4d\x62\x55\x32\x04\x07\x59\x46\xdc" +"\x21\xf0\x08\x4a\x60\x45\x0c\x4b\x5d\x04\xc2\x9c\x04\x3a\x03\xe2\x63\x03" +"\x95\x01\xe6\x10\x88\x62\xcf\x2d\x7d\xdf\xb9\x6e\x02\x21\x3f\x20\xb0\x84" +"\x63\x64\x17\x81\x0c\xea\x30\x0e\x12\x18\xc7\xed\x53\xbc\xb6\x3f\xda\x43" +"\xa0\xa5\x01\x81\x71\x12\xee\x91\xc0\x9a\x11\xa1\xa6\x2b\x81\xe7\xb1\x77" +"\xeb\x21\x90\x57\x81\x60\x22\xfa\x40\x83\x2e\x63\x57\xf0\xe4\x04\xfa\xf3" +"\xd0\xa3\x46\x13\x4b\x62\xe6\x45\xa1\x43\x5d\x1e\xa8\x19\x4b\x38\xab\x13" +"\xbd\xc9\xc5\x3c\x47\x02\xab\x1a\xaf\xfa\xe8\xad\x3b\x77\xcd\xa5\x30\x4b" +"\xc6\xb1\x8d\x86\xb1\x51\x8f\x59\xbc\xc1\x17\x13\x55\x87\x40\x64\x27\x61" +"\x19\x77\x71\xad\x4d\xa0\x7d\x92\x8d\x01\x3b\xc4\x64\xbc\x1a\xa4\x2b\x77" +"\x62\xd5\xef\x61\x7f\x19\x7a\xfd\xda\xc5\x43\xac\x43\x20\x5f\xc4\xfc\x88" +"\xa7\x46\x4c\x68\x7e\x86\x43\x20\xf3\x33\x7f\x9e\x9f\xa7\xfb\x59\x00\xa4" +"\xbf\x34\x67\x56\x65\x69\x40\xa0\x86\x17\x9e\x60\x67\x81\xc0\x15\x98\x2d" +"\x25\x96\x24\x81\xf1\x62\x05\x3a\xdb\xc3\x4c\xf6\x81\x40\x60\x25\x78\xdf" +"\x9d\xc6\x60\xca\x19\xa8\x25\xbd\x55\xa6\xf0\xcc\x00\x4d\x98\x94\x19\xa1" +"\x4d\x20\xb0\xfa\x84\x04\xf2\x26\x49\xd2\x26\x87\x71\x37\x8a\xdd\x77\xa8" +"\x0c\xe3\xeb\x28\xa5\x4d\x90\x71\x6a\x45\x18\x0c\x6c\x01\xe2\xe3\x0c\x86" +"\xc3\xf3\x9c\x46\xcb\x36\x0c\x11\x0c\xa6\xcc\xd0\x8f\x58\x04\x6f\xe3\x59" +"\xca\x6b\x31\xd1\xfd\x5e\xc4\xb1\xc3\x64\x76\xc8\xbe\x4b\x61\x7a\x3f\x47" +"\x9b\x31\x36\x07\x37\x81\x19\x9c\x0d\x81\x50\x9a\x2c\xc9\xf6\xc0\x40\x1a" +"\xa4\x49\x68\x87\xc9\x00\x14\xd7\x08\xa2\x3c\x9c\x80\xec\x3d\xbc\x29\xc5" +"\x82\x78\x6c\xdb\x86\xd2\xce\xc2\x55\x35\xf9\x0a\x74\x52\xd0\xdd\xdb\x81" +"\xc4\x42\xd3\x80\x94\x95\xe2\xc2\x72\x02\x49\x1f\x85\xaa\x9a\x90\x00\x39" +"\x00\x9f\x3e\x6e\xc3\xd4\x80\x8d\xb2\x24\x9d\xa3\xa5\x22\x8c\xc2\x03\x36" +"\xdc\x73\xbe\xec\xc7\x5e\x1d\xc6\x77\xa2\x43\x75\x92\x74\x35\xc1\x4e\x41" +"\x27\x45\x4c\x8e\x97\x8c\x5d\x27\xcb\x07\xa9\x05\x53\x84\x06\xaf\x73\x16" +"\x7a\x30\x55\x8f\x0e\x9d\x52\x27\xb3\x53\xfa\xbe\x68\x3b\xd9\x13\x25\x87" +"\x4f\x13\x72\x44\xee\x82\x96\x23\x56\x4f\x0f\x11\xbd\xab\xe4\x23\xa7\x36" +"\x66\x16\x22\xfb\xe4\xfe\x10\x89\x12\x0d\x76\x0f\x89\x64\xc8\x61\x84\x68" +"\x3f\xf4\x1c\x8b\xf9\x69\xa1\xee\x2c\x62\x95\x11\x82\x75\xd0\x9d\xee\xf2" +"\x30\x6c\xf6\x3e\x22\xe2\x0e\x5d\x1b\xe9\xaa\x42\xf1\xfe\x69\xa2\x43\x56" +"\x9e\x11\xb9\x8d\x95\xee\xa9\x0f\x21\xfb\x4e\xbb\x95\x12\x49\x51\xb2\xb3" +"\x30\x57\x46\xf8\x8e\xdd\x8d\x07\x42\x7b\xd8\x93\x68\x6c\xf3\xdc\xc2\xb3" +"\xfc\x90\x73\x8a\x8b\x4f\x5c\x9f\x1d\x82\xd9\xfc\xc0\x7e\x4e\x25\x45\x1f" +"\x72\x40\xa2\xba\x29\x29\x12\x78\xc8\x39\xe5\xfb\x4f\x58\x9b\x9d\xc3\xf8" +"\xed\xe8\x8b\xae\x82\x83\x42\x21\xfa\xb8\xa7\x78\x0a\x85\x67\x50\x11\x05" +"\x05\x05\x05\x05\x05\x05\x05\x05\x85\xc7\xc0\xda\x82\xf8\xb9\x28\x7f\xc8" +"\xf6\xda\x46\xa1\x25\xec\x9c\x76\x17\xb5\x95\x8f\xfe\x34\x98\xdc\x42\xe5" +"\x77\x71\xbe\x77\x5b\x9f\xbf\xb3\xc5\x41\x0b\x0f\xcc\xf7\xe4\x16\x75\xf0" +"\xcd\x6f\xab\x5f\x7c\x06\x30\xeb\xf8\x27\xea\xaf\x3b\x9b\xdb\x6a\x1b\xa9" +"\x50\x89\xb9\x6a\x50\xb3\x86\x6f\xb7\xa2\x8f\x5c\x4c\x59\x9c\xd7\xfb\x00" +"\x61\xe2\x8b\x1a\x4f\xa9\x93\x10\xde\xe2\x95\xbb\x59\xdf\x9c\x36\xde\x59" +"\x35\xb6\xaa\x03\x7d\xa0\xf6\x6e\x87\x21\x98\x4b\xb4\x09\x34\x56\xb6\x3b" +"\x50\x2a\xd8\x4c\xe7\x31\xde\xff\x98\x04\xa2\x66\x8d\xe8\xbd\xef\xe3\x7c" +"\x48\x60\xb0\xd4\x49\xd8\x4a\x67\xe1\xdf\x4c\xa0\xde\xa5\x5a\xdd\xb2\x0e" +"\xcf\x81\x40\x63\x2e\xee\x29\x8c\x35\x89\x96\xbc\x58\xc7\xdb\xb8\xea\xaf" +"\x27\xcf\x11\xad\x10\x18\xbf\xed\x2b\x1c\x6d\x40\x25\xe7\xce\xa3\xb2\x10" +"\x95\x9c\xc9\x59\x60\x6f\xd6\x28\x44\x21\x4d\x2b\xd7\xe2\xba\x38\x4d\x12" +"\xe8\xb1\xe3\x44\xb7\x2f\x88\xdf\x77\x9a\x51\x71\x1e\x2a\x38\x43\x06\x9c" +"\x24\x34\x9d\xef\x7c\x8f\x07\x8c\x14\xe2\x9e\x66\x3c\x59\x47\x45\xe7\x89" +"\x82\xb1\xac\x8d\x07\x48\xc4\x06\x02\x75\xbe\x7a\x06\x0a\xd4\xe7\x66\x89" +"\x9e\x4c\x54\x88\x67\x05\xf5\x9c\x71\xa8\x8c\x61\x43\x15\xcf\x37\xfd\x75" +"\x5f\x21\x1a\xb9\x1d\xc2\xd7\x88\x90\x70\x6e\x0e\x6e\x46\x7d\x16\x72\x26" +"\xa8\x43\x8d\x34\x81\x40\xcc\xf2\x9d\x15\x03\xab\xd5\x20\xe3\xb7\x46\xa3" +"\x74\xb6\x70\xcb\xd3\x7c\xa6\xed\x78\x61\x94\xe9\xdc\xa6\x79\xb3\xce\xeb" +"\x28\x0a\xab\x7e\x66\x33\x92\x9c\x6b\x84\xeb\x06\x45\x2d\x4c\xa2\x20\x94" +"\x85\x89\xe4\xa2\xbf\xc6\xe3\x66\x95\x1e\xa1\x79\x48\xdb\x57\xae\x9d\x2b" +"\x27\x2d\x53\x68\x6a\x80\xc0\x44\x93\x11\xbe\xca\x4a\xf8\xbb\x96\xcc\xcb" +"\xf3\x8a\x8c\x8e\xd9\xf8\x9a\x1b\x35\x9d\xb6\x1d\xe7\xab\xf4\x0e\xc7\xac" +"\x8a\xf5\xd9\xa4\x5d\x35\x29\xaf\x24\xed\xa6\x87\x71\x20\xd0\x00\x02\xa1" +"\xc0\xd1\x26\x0b\x05\x19\xaf\xa0\x62\x35\xc1\x78\x1d\x2a\x63\x8f\xd6\xa0" +"\x8a\xcc\x5f\x37\xd8\x10\x2b\xc2\xbd\x81\x32\x34\xbe\x40\x43\x24\x51\x9f" +"\x75\x75\xa8\x9c\xd3\xe8\xe8\x6a\x15\x75\x9b\xf3\x34\x0e\x74\xc6\x63\x8c" +"\x96\x68\x9e\x9f\x4b\xcc\x3d\xcb\x57\x5e\x3a\x3d\x51\x27\xe5\xe5\x72\x29" +"\xbc\x14\xc4\x26\x82\xfa\xc9\x77\xea\x3a\xdd\x0f\xf5\xf5\xd0\x26\x48\x60" +"\xf9\x96\x50\x16\x96\x1b\x56\x62\x31\x66\x85\x2d\x8e\xfa\x8a\x5b\x42\x87" +"\x52\xf7\x57\x13\xf7\x83\x82\xc0\x53\x90\x7c\x9e\x9e\xa6\x87\xe1\xf7\x02" +"\x1b\xcb\xcb\xf3\x62\xf5\x64\xa4\x12\xb3\x50\xa9\x92\x0c\x2e\xc5\x7e\xe4" +"\xe7\x69\xb4\x5c\x2a\x2f\x5b\xa8\x8b\xb9\xc0\x7c\xb4\xb9\xcc\x8f\xe0\xfb" +"\x78\x6c\xc2\xe5\x12\x16\xc8\x2d\xd4\x7d\x84\x2b\x26\x1b\x58\x8a\x55\x07" +"\x44\x35\xa0\xf1\x96\xab\x20\x81\xc1\xb8\x8f\x45\xa2\x44\x83\x32\xe2\x45" +"\x06\x12\x08\xd9\xc0\xef\xbb\xb5\x18\x1c\x0e\x7d\x20\x3f\x07\x7f\x87\x68" +"\x9c\xe7\x13\x16\xcf\x0f\xb0\x64\x94\x7e\xbf\x42\xf8\x8f\x0f\x7b\xa9\xf8" +"\x54\xb0\x47\xa1\x76\xa5\x72\x29\xb1\xe8\x77\x08\xac\xfb\xa8\xc1\xe6\x44" +"\xcd\xb1\x07\x49\x26\x85\xb2\x10\xff\x2f\xc6\x2a\x89\xd2\xd1\x00\xcd\x63" +"\x1a\xea\xc3\xe6\x6a\xf0\x57\x10\x88\x1a\xc5\x15\x7a\x4a\xfc\x2e\xd3\x9a" +"\x73\x5e\xac\x42\x62\x35\xbe\x28\x3e\x77\x80\x95\x25\xb8\x15\xf1\x72\x89" +"\xb3\x10\x2a\x92\x56\xa9\x0f\x95\x3f\x73\xf4\x50\xd5\xe7\x12\x18\x27\x91" +"\x71\x54\x8f\xa0\x4a\x6a\xae\x82\xca\x1f\x5f\x5d\x5b\x4d\xd6\x71\xe8\x81" +"\xa6\x11\x30\x50\x81\x00\xf2\xce\x2d\xf1\x26\x15\x09\xac\x10\x03\x75\xa8" +"\x90\xe1\x69\xc8\xf2\x08\x25\x78\x8f\x22\x63\x48\x20\xea\x6e\x2d\xa0\xf8" +"\x99\xbe\x30\x3e\x69\x4b\x02\x8b\xdd\x04\xfa\xe8\x85\x11\x24\x10\x3b\x0f" +"\x1f\x83\xb6\x41\x4b\x11\x0a\x62\x1a\xab\xa2\x8a\x89\xe6\x7d\x75\x41\x20" +"\x1b\x39\xcd\x3b\x04\x02\x33\x63\xcc\x83\xbf\x09\xfc\xb8\x06\x8f\x89\x2d" +"\x11\xd4\x73\xe2\x9b\x77\x12\xab\x8e\x44\xf9\x6d\x16\x28\x97\x82\xb4\x81" +"\x04\xde\x1a\xf1\xd1\x80\x07\x4a\x8a\x75\x08\x8c\x42\x87\x07\x12\x28\x08" +"\x1c\x39\x25\x09\x84\x2e\x12\xab\x88\xea\x72\x8b\x70\xa8\x93\x81\x65\xa0" +"\x5a\x5e\x10\x88\xb7\xa7\x5c\x19\x10\x04\xae\x8c\xec\x93\x04\x1a\x36\x10" +"\x88\x5a\x60\x5a\x25\x41\xfa\x90\x8f\x6f\x9e\x0e\xfc\x8c\x23\x81\xf7\xbb" +"\x08\x04\xea\x74\x24\x10\x2e\x9d\x14\x57\x84\xb2\xf0\x5c\xb9\x8a\x12\xc8" +"\x2b\x48\x20\xa6\xa1\x22\x3e\xa4\x27\xba\x24\xd0\x0a\xb2\x65\x94\x8e\xc6" +"\x07\x48\x33\x1e\x13\x5b\x24\x87\x84\x4a\x11\x2e\x33\x0c\x2b\x41\xd6\x80" +"\xc2\xce\x71\xd4\x8a\x51\x4b\x07\xde\xf0\x33\x12\x54\xea\xb6\x09\x4c\x58" +"\x92\x40\x3f\x23\x7b\x1c\x09\xe4\x27\x25\x81\x75\x5e\xf1\x9c\x00\x12\xa5" +"\x04\x96\xda\x04\xfa\x18\x36\x61\x91\xaa\x3b\x04\x86\x97\xcb\x92\xc0\x39" +"\x16\x3a\xcf\x37\xbf\xe9\xde\x39\x18\xf8\xcd\x09\x12\x18\xae\x26\x05\x81" +"\x73\x48\x20\xe1\xcd\xa4\xe9\x10\x08\xbd\xf5\xb9\x4a\xf0\xfe\x5d\x7f\x25" +"\x76\x3f\x61\xc5\xd8\x18\x5e\x21\xa4\x15\x2b\x17\xe8\x4a\x33\x5c\x4d\x30" +"\xd9\xa8\xe2\x34\xba\x86\x87\xc7\xe9\xc8\x72\xd8\x92\xe7\x25\x96\xa0\xe1" +"\x8d\x95\x04\x81\x26\x9c\x69\x0b\x9e\xee\x99\xd0\xb7\xcd\x96\x9b\x17\x91" +"\x37\x28\x09\x3a\x37\x1a\x80\x1d\xcd\x0b\x50\x20\x0c\x68\x8d\xc4\x12\x7e" +"\x67\x73\xeb\x0e\x10\xc8\xb0\x73\xb3\x59\x88\x23\x81\x41\xf6\x4e\x09\x3f" +"\x55\xe3\xe7\x90\x2c\xc8\xcb\xcf\xce\x63\xce\x75\x5e\x0d\xb2\x77\x21\xad" +"\x76\x71\x3f\x0d\x89\x5e\xc2\xe6\x0d\x41\xe0\x2c\x2f\x15\xcc\x67\x49\x20" +"\x4c\x1e\xe8\x0a\x5d\xe5\x15\x03\x6a\x2e\x86\xcb\x51\x9a\xa4\x71\x68\x84" +"\xf8\x39\x1d\xca\x7e\xb9\xc9\x97\x19\xb7\xca\x76\xc9\xc7\xec\x90\xc1\x61" +"\x70\x6e\x60\x5a\x90\x85\xca\xd4\x82\xd3\x58\x14\xbf\xdf\x89\xc0\x70\x89" +"\x0a\x3e\xf8\xd5\x58\x19\x73\x6a\xf2\x46\x99\xc1\xe0\xca\x02\x50\x0a\x43" +"\xbd\x68\x80\x53\x36\xc2\xab\x45\x7b\xd9\x47\x2d\xc8\x3d\x02\xe2\x94\xa0" +"\xcb\x7a\x99\x61\x9b\x8f\x31\x6c\x6c\xc5\x66\xb9\xf1\x0e\xe7\xec\x30\x34" +"\x56\x5e\x4f\xb0\x39\x18\x9b\x56\x29\xdc\x2b\xd8\x3f\x4a\x9b\x50\x05\x02" +"\x6d\x9a\x79\x84\x58\x41\x55\x1c\x1d\xea\x5e\x18\x8d\xad\x08\x66\xb9\x8a" +"\x1a\xd1\x04\x5c\x51\x82\x45\xc5\xfe\xe2\xc2\x33\x1d\x44\xf6\x4a\xcd\x23" +"\x48\xd1\x10\xf6\xb5\x8e\xd6\x52\xef\x68\x07\x75\xe2\x41\x65\xe1\xe1\x11" +"\xa9\xc6\xf4\x84\x9c\x34\x72\x8a\xe8\xb0\xbd\x6f\xaf\xa3\xf9\x1c\x81\x59" +"\x05\xa5\x25\xfc\x1d\x3a\xed\x1e\x03\x68\xab\x14\x8f\x88\x03\x2c\xa1\xae" +"\x84\x42\xb5\xd3\xed\x92\xf4\xa1\x28\xe6\x10\x75\x8b\x23\x47\x3c\x01\x54" +"\xac\x6e\xac\x22\x1c\x33\x74\xca\x29\x4b\x62\x9f\xf8\x8b\x3a\x54\xfd\x54" +"\x14\x75\xa7\x6e\xa5\x03\x7a\xc0\x5d\x3f\xdc\x4e\xfd\xb9\x43\xb7\x47\x46" +"\xad\x87\x1c\x70\xf6\x81\x07\xbc\xe2\xd0\xd9\x85\xb9\x07\x4e\xfa\xe1\x80" +"\xe4\xf3\x7c\x38\x7d\xe9\x70\xb4\x70\xfe\xc1\x07\xec\x7f\xd8\x01\x0a\x0a" +"\x0a\x0a\x0a\x0a\x0a\x0a\x0a\xcf\x07\x1e\xfb\x0e\x9a\x1d\xce\x6f\xd2\x5e" +"\x69\xe2\xc3\x76\xc0\x9a\xd4\x8f\x69\x73\xac\xb9\xad\x92\xc4\xb3\x06\x39" +"\x58\x9d\x4d\x91\xa1\xfd\xc1\x7c\xa9\x73\x48\x84\x2f\x24\x1f\x50\x8f\xde" +"\x09\xf8\xc5\xf9\xbb\xb0\x6c\x7c\xaa\x59\x5b\x40\xc3\x45\xc8\xbc\x71\x52" +"\x56\x37\xb8\xc5\x33\xae\xb4\x9b\x1c\xe5\x76\x32\xfa\x80\xe2\x76\x0e\x87" +"\x56\x19\x89\xad\xf0\xca\x86\x07\x04\xcd\x72\x54\x34\x11\xf7\xb3\xd1\x20" +"\x3b\x9f\xec\x28\x7a\xc6\x49\x2f\x0e\xd1\x11\xb4\x10\x72\x91\x60\x23\x73" +"\x79\x9a\xe7\x9d\x57\xe9\x3a\x6f\x44\xf8\xb6\xb5\x58\x69\x1b\x31\x4a\xf8" +"\xe0\x89\xd9\x68\x6c\xfc\xf8\xd4\xac\xeb\xf8\xba\x23\xc1\xdc\x6f\x5d\xb7" +"\xf8\xa2\x55\xda\x4d\x9a\xf4\x7c\x84\x47\xb7\x2d\x6e\x27\x91\xf8\xf1\x14" +"\x39\x4b\xca\x8b\x46\x2f\x81\xfe\x45\x22\x3e\x5b\xd5\xd6\x9c\x5a\x6a\x7c" +"\x99\xe8\xed\xfa\x76\x2b\xc3\x04\x06\x28\xd1\x4b\x9d\xcd\x43\x75\x62\xe4" +"\x93\xa1\x2e\x06\x22\x8c\x90\xe2\x76\x95\x30\x2a\xa4\x57\x5e\x34\x7e\x9f" +"\x98\xf1\xc8\x86\x56\xe1\xaf\x93\xb9\x00\x1a\x1c\x11\x22\x2d\x98\x4c\x6b" +"\x73\x5e\xc2\xb2\xa1\x58\x23\x24\x1c\xdd\xbc\x73\x87\xad\xdd\x20\xa6\x00" +"\x00\x20\x00\x49\x44\x41\x54\x61\xd8\x51\x4f\x79\x15\x5f\x8c\x94\x17\xf5" +"\xd5\xdb\xe3\x05\x61\x12\x88\x26\x7b\x1a\xda\x08\x86\xb4\xf1\x40\x90\xdd" +"\x8a\x55\xd1\x30\xcf\x87\x6f\xf7\x6f\x91\x77\xbe\x47\x0d\x5e\x20\x52\x9f" +"\x2d\xcc\x16\xf2\x27\x0a\xfb\x9b\xc2\x90\x10\x09\xb4\xe2\x42\x79\x56\x28" +"\xc0\x65\x0f\xd4\xf5\xef\xcf\x14\xa2\xc5\xc5\xf1\x5b\xc9\xf8\x28\xbe\x13" +"\x43\xeb\x0d\x93\xec\xbf\x1b\x32\x0a\x23\x2b\xc2\xd6\xcf\x59\xd7\x92\x2b" +"\x20\x53\xb7\x0b\x71\x54\xfe\xb5\x8d\x00\x79\x8d\x44\xf4\x42\xbe\x50\x30" +"\x6e\x93\x48\x47\x6b\xe8\x13\x26\x6f\x48\xa0\x30\x46\x2c\xcc\x8e\x17\x8e" +"\x14\xc8\xfe\xef\xf5\xc2\xf7\x49\x2d\x39\x46\x4e\xac\x86\x90\x40\xe4\x9f" +"\x98\x51\x27\xc7\x78\x32\x4e\x74\xb4\x5c\xdc\xf1\xa7\x48\x6e\x57\x05\x81" +"\x04\x08\xd4\x78\x35\xc6\xcc\xe5\xc8\x6a\xcd\xa4\x0c\x35\x6e\xe3\x34\x9a" +"\xb4\x9b\x67\x81\x40\xc6\x1b\xd8\x28\xf0\xca\x8c\x55\xfb\x30\xb7\xb9\x95" +"\xac\xcf\xf2\x45\xbe\x18\xa4\xbc\xca\x97\x82\x3f\x22\x81\x46\x09\x75\x65" +"\x3a\xaf\xa0\x09\xe1\x40\xdd\xcc\x1b\x34\x5f\x5c\x0c\x4b\xb5\x1a\xd1\x29" +"\x0a\xa3\xc6\x2f\x36\x3c\x14\xad\x2c\x78\xc5\x5d\x0f\xde\xe5\xf1\x22\x9b" +"\xe5\xa5\x60\xd5\x0e\x25\x44\x59\x80\x30\x23\x05\x0d\x8a\x60\x7a\xd5\xac" +"\xda\x43\x9c\x49\xad\xa1\xd0\x9d\x0b\x02\x3d\x68\x8c\x88\x36\x55\x7b\x6d" +"\xc3\xb6\xcf\xc1\x01\x67\x9b\x6b\x1e\x3b\xd1\x40\x02\x0d\x69\x12\x99\x28" +"\xb0\x10\x67\xf0\xaf\x4a\x78\x72\x39\xbc\xfa\x84\xe6\x71\xdb\x42\xa7\x87" +"\x69\x48\x9a\x6e\x95\xf1\x85\xbb\xc9\x4c\x7c\xad\x2c\x4c\xf6\x8a\x8b\xa8" +"\x67\x3b\xc2\x7c\x75\x12\xab\xe2\x57\x02\x03\xc2\xd2\x2d\x7c\x3f\x61\x95" +"\x1b\xc5\x92\x1f\xdf\xa4\x27\x16\x7d\x74\xd5\x2a\x2e\xf9\xa3\xb8\x9b\x97" +"\xd0\x14\x26\x1e\xae\x63\xc7\x3e\xc0\x78\x1e\x5f\xfc\x2f\x0e\x30\xb4\x09" +"\xc4\x86\x85\xe5\xf8\x98\x0f\x0d\x5d\x56\xe0\x56\x31\x77\x1d\x32\xb4\x06" +"\x2a\x68\x7a\x53\x2a\x5a\xb1\x9a\xf3\x45\x82\x49\xcf\x2d\x43\x11\xc1\xba" +"\x51\x8a\x59\x45\xcb\xd5\x1a\x7a\xda\x04\x12\x6a\xa1\xc1\x91\x9f\xed\x59" +"\x0e\x2e\xa1\x79\xe3\xdc\xa1\xea\x49\x93\x0d\x54\x91\x40\x9f\xb4\x77\x2e" +"\x37\x68\x54\xe8\xf5\x98\xc1\xcc\x6a\xb1\xb1\xed\x18\xf8\x84\xf0\x51\x02" +"\x37\xd1\x25\xd0\x64\x49\x9a\x24\x74\x95\x8e\xa0\x7a\x03\x09\x1c\xa1\x73" +"\x14\x09\xac\xe0\x57\x02\x52\x02\x13\xab\xdc\x12\xea\x27\x24\x30\x06\x04" +"\x86\x60\x70\x89\x20\x63\x34\x82\x0a\x0d\x9e\x97\xa6\xeb\x03\xf5\xa4\x43" +"\x60\x0d\x2d\xd9\xf0\x66\xe1\x25\xa1\x96\x25\x80\xd6\x8e\x15\x1f\x75\xd7" +"\x23\x63\xa8\x00\x41\x02\x2d\xc8\xb2\xe2\x7c\x91\xe0\xa1\x77\x2d\x28\xc2" +"\x47\x23\xd1\xe2\x2a\x2a\x1c\xa4\xd6\xb0\x9b\xc0\x3c\x12\xe8\xa1\x63\x79" +"\x54\xfb\x15\x97\xa0\x86\x96\xde\x2c\xd6\x5c\x09\x2c\x14\x6e\x9d\x15\x6a" +"\x41\xac\x82\xc9\x7e\x10\xc6\x45\x3b\x4f\x60\xbe\x4d\x20\xbe\xfc\x5e\xd5" +"\x84\x5a\xab\x4d\xe0\x85\x91\x2e\x02\x91\x98\x62\x75\x24\xda\x43\x20\xee" +"\x68\x12\xd9\x07\x0a\x5d\x99\x64\x0a\xfa\xc0\x0e\x81\xd2\x60\x6d\xd1\x21" +"\x30\x0a\x9d\x29\x12\xf8\xae\xb3\xee\xb1\x1d\x02\xe1\xf0\xfb\x6d\x02\x09" +"\x5a\x12\x15\x17\x35\x6a\x93\x62\x65\x24\xe4\x6a\x0d\x05\x81\x61\x20\xf0" +"\x8e\x43\x20\x1a\xfa\xa1\xb6\x0f\x86\x2b\x83\x33\x92\xe4\x82\x40\x1d\x08" +"\x84\x0a\xfb\xec\x0e\x81\x23\xa7\x4d\xba\xd3\x4d\xd8\xe8\x91\x40\xc2\x2d" +"\xe8\xe8\x79\x49\x6f\x13\x78\x1a\xd5\x66\x2e\x81\xa2\x5b\x89\x86\xab\x24" +"\xb4\x81\x40\x9d\xde\x97\x04\x46\x91\x10\x4b\x47\xad\x1d\x10\x48\xa2\x1b" +"\x08\xac\x42\x1e\xb8\x1e\x72\x08\x74\xd7\xc3\xcb\xe5\x5e\x09\xd4\x67\xb1" +"\x46\xa8\xa9\x02\x56\xe0\xb4\x84\x28\x53\x6a\x0d\x05\x81\x90\x39\xb1\x5c" +"\x02\xe1\xb8\xb0\x34\x6f\x34\x22\x74\x3f\x1b\x70\xec\x0b\x97\xd0\x7a\x2f" +"\x61\xb9\x04\x1a\x34\xa4\x9f\x2e\x3e\xc4\x35\xc3\x63\x43\xe7\x43\xd0\x07" +"\x5a\x82\xc0\xfb\xa8\x4d\x0b\x5b\x30\xfa\x9d\xdd\x2f\x08\xac\x40\x47\xc8" +"\x9b\x49\x1f\xfb\x20\x56\x09\xa3\xfa\x26\x51\x23\x86\x85\x8a\xb5\xb2\x85" +"\x0a\xe1\xf3\x89\xfb\xe5\x25\xa1\x8c\x14\xda\xb1\x01\xb1\x76\x8e\x46\x83" +"\xa3\x58\xcd\xb0\xd0\xef\xb5\x9b\x70\x00\xa7\x91\x21\xcd\x36\xb0\x4f\x45" +"\x02\x51\xd5\x26\xfa\xc0\x3c\x5a\x27\xdf\x19\xa8\x61\xc7\x60\x71\x0b\xcb" +"\x92\x1f\x85\x99\x4b\x52\x15\xba\x0c\xfc\x8c\xc7\x5d\xad\xa1\x50\x54\x9b" +"\x2c\x64\x0a\x02\xe1\x70\x62\x56\x84\xb6\x0f\x0e\x1d\x38\x4c\xfd\x30\x62" +"\x1c\xc5\xce\x3a\xc8\x90\x40\x6e\xd3\xef\x25\x81\x3a\x6d\x36\x7f\x30\x76" +"\x9a\x40\x92\x58\xab\x1a\xc2\x58\xf5\x04\x85\xfe\x21\x1c\x30\xe3\x68\x12" +"\xe8\x77\x0c\x0f\xa9\x85\xfa\x32\xde\xc0\x71\x2c\x84\x5f\xae\xac\xad\x05" +"\x0c\xca\xf6\xc1\xc0\x5b\x35\xe8\x32\x8c\xc0\x78\x0c\x74\x49\x51\x61\x02" +"\xbd\x82\xba\xb2\x9a\xc7\x4e\xa2\xde\x96\xb3\x59\x6c\xdb\xbc\x9a\xc0\x9e" +"\x15\x67\x40\x5a\x99\x95\xf3\xd0\xe0\x1a\x3e\xda\x40\xcb\xe7\x65\xb9\xbe" +"\x42\x62\xab\xbc\x8a\x86\x84\x2b\xf8\xdd\x01\x94\x55\x3f\x29\xbe\xc1\xf2" +"\x95\xe0\x06\x57\x89\xdf\x82\x7c\x98\xc7\xd5\x1a\x26\xe9\x1d\x1c\xcb\xeb" +"\x58\x93\xa6\x50\xc8\xf9\x84\x15\xe4\x5e\x58\x1b\xb0\xab\x3e\x76\x91\x61" +"\xf9\x70\x88\x6d\xdb\x21\xde\xe4\xcb\x65\xe8\xfb\x92\x2c\xca\xe1\x6a\xec" +"\x1d\x57\xaf\xeb\xdd\x46\x7b\x44\x27\x7a\xa0\xa3\xd6\x42\xdd\x17\xea\xcb" +"\x3c\x01\x77\xbf\x07\x0d\xfd\x1c\xdb\x43\xb2\xcf\xd5\xa9\xc1\xdd\x6e\xe7" +"\xd0\x63\x04\xb8\xb9\xb0\x28\xfe\x11\xeb\x68\x54\xe8\xae\x0b\xf5\x99\x50" +"\xba\x1d\x89\xca\x5c\xc4\x8f\xe6\x28\x07\xbb\xcb\x1c\x0a\x6d\xae\xb7\x6b" +"\x05\x49\x84\xc5\x21\x6a\xe7\x9c\x43\x46\x3a\x6a\x41\x79\x29\x7b\x8f\xb4" +"\x2f\xe5\xe7\x04\xdd\x7e\x02\x53\xab\xad\x1e\xc1\x5e\x55\xe8\xec\x09\x94" +"\xd6\x5b\x18\x15\xbe\xba\x18\x0b\x3c\xfe\x39\x4f\x60\x54\xa8\xa0\xa0\xa0" +"\xa0\xa0\xa0\xa0\xa0\xa0\xf0\x92\x61\x83\x09\x22\xfa\x4b\xfd\x2b\x59\xbb" +"\xb7\xe1\x43\x40\x7d\xfe\x8e\xc7\x46\xe3\xbe\xf9\xf8\x45\xe9\x34\x75\xab" +"\x0f\x01\x65\x26\x17\xa9\xbd\xa5\x86\x73\x6d\x0b\x03\xc3\x2d\xb1\x95\x59" +"\xa1\xd1\xa5\x56\xfd\x79\x61\x83\x09\x22\x3a\xa6\x8a\x13\x73\x59\xbc\xc5" +"\xea\x02\xbe\xe3\x23\xe2\xbd\x9f\x21\x1f\xee\x36\x1e\x20\x4e\xc5\x4c\x82" +"\x2c\x9e\xdc\xc2\x6c\xf0\x61\x8f\xc8\x67\x3b\xab\xfa\x56\x56\x71\xbd\x8a" +"\xd1\x9f\x11\x36\x98\x20\xe2\xbb\x55\x8b\x04\x43\xc9\x0d\x42\x10\xab\xe8" +"\xf8\x6a\xba\x58\x21\x5a\x49\x24\x6c\x54\x4a\xb6\xf3\x42\x05\xdd\x0f\x9b" +"\xf7\x3d\x84\x40\x6d\xad\x6b\x63\x2b\x02\x3b\x7e\x59\x7f\x16\xd8\xd6\x04" +"\x91\x08\x06\x92\x46\x61\xa4\x70\xdb\x77\x8b\x8c\x46\x7d\x85\x13\x2b\x44" +"\x4f\x16\x2b\x27\xf0\xbd\x0c\x10\x48\x4a\x27\x0a\x27\x1a\x9e\xc2\x79\x47" +"\x29\x89\x4e\x58\x75\xfb\x3c\x39\xd3\x0c\xf8\xeb\x92\x7f\x62\x42\x01\xe7" +"\x3c\x85\x0b\xf6\x9e\xb9\x28\x31\xa4\xbb\x56\x24\x70\xb4\x19\x20\x91\xe6" +"\x88\xf8\x25\x78\xc6\x89\xc2\x7e\x4b\x94\x1a\x61\xb7\x0a\xb3\xc9\xd0\x89" +"\xd5\x10\x39\x8a\x66\x85\xa2\xe0\xa6\x01\xc7\x25\x9b\xe4\xcc\xad\x48\xbc" +"\x5c\x2a\xdc\x7a\x06\xaa\xcb\x27\xc5\xb6\x26\x88\x44\xbc\x6e\x6f\xe8\xf4" +"\x7b\x5e\x31\x1b\x27\x9b\x4c\x18\x9a\x04\x19\xad\x08\xe7\x6c\x82\x40\x34" +"\xf8\xd3\x79\x89\xd7\x8c\x8a\xe3\x84\x35\xdc\x84\x35\x6e\x21\x81\xa6\xb4" +"\x40\xb5\x93\x4c\xe3\x36\x9a\x73\x08\x77\xad\x17\x2d\x24\xd0\xa8\x27\x2c" +"\x93\x15\xeb\xf8\x8b\xde\x77\xb9\x15\x44\x73\x44\x2c\x35\xc9\x6e\x15\x19" +"\xbd\x60\x27\x1a\x70\x1a\x8d\x46\x64\xc1\x0b\xdc\x32\x57\x78\x3c\x82\x66" +"\x18\xa5\x44\x63\xe7\x55\x97\x4f\x8a\xed\x4d\x10\x09\x76\x62\xfb\x2d\x52" +"\xce\xc7\xaa\x66\x9c\x5b\xfc\x08\xcd\xa3\xd5\x4b\x42\xf6\x81\x82\x40\x83" +"\x5e\x40\x85\x69\x90\x19\xae\x13\xd6\x44\xe3\xf6\x40\x55\x5a\xe3\xf9\x45" +"\xfb\xd3\xe8\x09\x0a\x05\x14\x97\xd0\xd5\xaa\x70\xd7\x8a\x04\x9a\x55\xb3" +"\x7a\xa8\x1a\x5e\xc2\x5f\x42\xf0\x0c\xb8\x75\x0d\x51\x2a\x9c\x8a\x96\x8b" +"\x6c\xa0\x6a\x32\x1d\xf5\x7f\xf4\x88\x70\xbc\x5a\x8a\x2d\x96\x4b\x7e\x9a" +"\x8c\x97\x7f\x6c\x92\x9d\x57\x5d\x3e\x31\xb6\x35\x41\x24\x28\x43\x17\x43" +"\x40\xa0\xc9\x82\x84\xdf\xe3\x17\x3a\xee\x3b\x89\x43\xa0\x74\x88\x09\x82" +"\xf8\x6e\xc8\x71\xc2\x1a\x66\x71\x63\x85\x2f\x4a\x09\x8c\xea\x85\x42\x7e" +"\x2e\x49\xd1\x85\xe8\x22\x1a\xc5\x15\x2b\xc2\xf3\x69\xac\x82\x8a\xde\x70" +"\x65\x40\xfc\xa2\xc5\x37\x47\xcd\xa9\x41\xe7\x1c\x02\xab\x04\x15\x97\xe8" +"\xe7\x31\x4a\x57\xf9\x08\x16\x0c\xb7\xe9\x36\x2f\x61\xbe\x65\xdb\x22\x3b" +"\xaf\xba\x7c\x62\x6c\x6b\x82\x48\x50\x3c\xa1\x43\x2f\xe7\xa1\x63\x24\xf4" +"\xaf\x23\x47\xf0\x3a\x50\xc1\xe3\x12\xa8\xbb\x04\xe2\x71\x8e\x13\x56\x93" +"\xa2\x8b\x44\x91\x97\x0f\x06\xf1\x30\x0b\x9c\x5c\xeb\x10\x28\xdc\xb5\x3a" +"\x04\xd6\xcd\x6a\xc2\xc2\x5f\xd4\x6c\x20\x81\x44\x96\x8a\x04\xc2\xcd\x49" +"\xf2\x9a\x29\x08\x44\xfd\xab\x20\x50\xb7\x81\x40\x60\xb8\x4c\x19\x16\xf3" +"\x62\x69\xeb\x60\x5b\x13\x44\xdc\x59\xae\x22\x81\x1a\xaa\x41\x2d\x4d\x10" +"\xc8\x5d\x09\x14\xca\x3b\x87\x40\x3c\xce\x71\xc2\x3a\x94\x60\x66\x35\x26" +"\x08\x84\xce\x11\x35\x93\xe5\x71\x97\x40\xe1\xae\x15\xb5\xa1\xb1\x4a\x18" +"\x24\x0f\xba\xb8\x50\x58\x48\x20\x9e\x21\xcc\x11\xb1\x54\x49\xa0\xc1\x06" +"\x24\x81\x50\xb0\x43\x60\x70\xa9\x2c\x25\x70\x81\x46\x77\x5e\x75\xf9\xa4" +"\xd8\xde\x04\x11\xf7\x0a\x7b\x3f\x8b\x14\xb1\xcd\x9c\x3d\x22\x9c\x9b\x2e" +"\x73\x69\xb2\x1a\x66\x24\x18\x15\x2e\x59\xe1\x80\x98\x45\x1c\x27\xac\xa3" +"\x06\x0b\xb3\x72\x55\x4e\x89\xaa\xa8\x78\x17\x05\x58\x89\xa5\x43\x55\x93" +"\xde\xfa\xf1\x2e\xaa\x31\xa1\x53\xc5\x7f\x16\x52\x87\x7d\x20\x9e\xe1\x98" +"\x23\xa2\x59\xe1\x05\x20\x50\x28\x2e\x59\x84\xc6\x8b\xb5\xb3\x78\xe7\x2c" +"\xe8\x7c\x6b\xbc\x81\x73\x55\xfe\x23\x5f\x7e\x06\xaa\xcb\x27\xc4\xf6\x26" +"\x88\xb8\xd7\x44\x93\xdd\x15\xfc\x80\x2c\x48\xe1\xfa\x17\x68\xe3\x1d\xa1" +"\xe4\x8c\xe3\x89\x6b\x55\x12\xa1\x73\x74\x05\xa6\xd4\x26\xfa\xbc\x15\x4e" +"\x58\x63\x6b\x70\x91\x68\xbd\x18\x47\x1d\xa8\xcd\x9b\x1a\xbf\x8b\x87\x94" +"\x19\xba\x5c\x15\xee\x5a\xa1\x90\xfa\x90\x0d\xa3\x2a\xa5\x2b\x3a\x7a\x42" +"\x85\x29\x7c\xa2\xee\x98\x23\xe2\xc7\x1e\xcb\x65\x16\x42\xc5\xe5\x61\x18" +"\x8d\x1b\x11\x2c\xf8\x2e\xd4\xb0\x1a\x66\xc5\x6a\x8c\x45\x3d\x90\x1d\x7b" +"\x06\xaa\xcb\x27\xc5\x03\x4d\x10\x75\xd2\xfe\x71\xbc\x9d\x92\x23\xfb\x9c" +"\x95\x6e\x9d\x63\x47\x29\x89\x3a\xc5\x90\xd6\x56\x4b\xa2\x7d\x61\xc7\x80" +"\x70\x5f\xb4\xed\xf9\x74\xdf\x69\xb8\x35\xd0\x99\xed\x13\xdb\xce\x19\xb2" +"\xd4\x2e\xb3\xc2\xe8\x29\x28\xd8\x3d\x5b\x0b\x75\xbc\xba\xfe\x4c\x55\x97" +"\xcf\x17\x91\x95\x91\x07\x3b\xd8\x51\x78\x30\xc2\xcd\x0f\x9e\x3e\x6c\xca" +"\xab\x0c\x6d\xfc\xf6\xf3\x71\x2a\xac\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xf0" +"\xf4\x18\x5d\x0b\xa1\x42\xce\x37\xdf\xdc\x60\x04\xe6\x9f\x8f\x63\x10\xc2" +"\x8b\xf3\x0b\x9e\x79\x61\x9f\xa5\xaf\x6d\x3e\x5b\x17\x56\x89\x86\xcd\x9a" +"\xa5\x2d\x73\x37\xe6\x7f\xb6\x2a\xb7\x1d\x82\xc6\x8a\x96\x88\x0d\x64\x07" +"\x37\xbc\x0e\xd1\x68\x3e\x51\x91\x8a\x90\x43\x62\x7e\x6c\xd0\x2d\xa6\xc9" +"\xc2\x08\x82\x37\xf7\xda\xdb\x38\xfa\x4b\xfc\x5c\x5e\xb2\x3c\x2b\x18\xf5" +"\x7d\x01\x7c\x93\x45\x56\xf4\x8d\x8f\x61\x34\x8f\xd1\x28\xd1\x91\xde\x80" +"\xd8\xd6\x36\xda\x29\x22\xd0\x2a\x11\x2d\x51\x8c\x6d\x08\x8c\x3d\x61\x0c" +"\xae\x97\x03\xc9\x15\x72\x96\xe5\x05\x03\x9e\xd2\x99\xdb\x27\x0a\xf9\x02" +"\xfa\x06\x45\x3b\x43\xb2\xbf\x49\x67\x0b\xb3\x2e\x81\x68\x4b\x78\xa2\xe0" +"\x2b\xcc\x8e\xe7\xb5\xdb\x81\x33\xb7\x83\xf9\xfd\x4d\x61\x12\x88\x04\x22" +"\xff\xa4\x24\x35\x71\x91\xc6\xfe\xa6\x70\xb6\x2a\x42\x2d\x22\x81\x7a\xe1" +"\xbc\x1d\x20\xa3\xbf\xc4\xa7\x64\x93\xf1\xb8\x20\xd0\x43\x4b\x66\x3c\x52" +"\x0f\xd2\x78\x22\x5a\x4e\x2e\x87\xd1\xc8\xaf\x8c\xce\x00\x2b\x2e\x81\x18" +"\x50\x30\x48\x7d\xd4\x0a\xe7\x8b\x3f\x34\x82\x8c\x2f\xda\xc9\xbc\xf0\x14" +"\xba\x28\x02\x87\x01\x0c\xa1\x89\xb3\xd9\x1a\x8d\xbf\xdb\x5c\x33\x6a\xd2" +"\xc6\x38\x56\x43\x0d\x9e\x05\x9b\xcf\xd3\xab\xf1\x73\x42\x78\xe9\xd0\x92" +"\x4f\x68\xdd\xf9\x52\x84\xa0\x51\x8b\x95\x34\x98\xbf\x3a\xc0\x82\x35\x83" +"\x6a\xc2\x9e\xc8\x21\x10\x03\x0a\xe2\x7b\x6d\x2b\xa2\xd3\x77\x98\x9f\x16" +"\x56\xd8\x98\xe3\x4d\x54\xda\xf8\x8a\xd7\xf8\x4b\x3e\xa1\x70\xcb\x17\xad" +"\x72\xb2\xfe\xae\xe8\x31\x31\x2a\x66\xa3\xb8\x68\x2e\xc9\x30\xad\xbf\x2c" +"\x14\x17\x07\xaa\x92\xc0\x04\x6b\xa2\xea\x82\x2f\x37\xfc\xec\x87\xda\x40" +"\xcd\x5f\x33\xd1\x18\xa9\x8b\xc0\x8a\x70\xb5\x98\xa8\x34\x7d\x6c\xae\xee" +"\xa7\x30\xc4\xd4\x88\xf4\x26\x2a\x08\x3c\x51\x28\x1c\x5d\xe1\x15\x11\x2f" +"\x8e\xe7\xcb\xf7\xf8\x6d\xc7\xf7\x24\x12\x58\x2a\x2e\x86\x17\xf7\xff\x02" +"\x5f\xd4\xa0\x3d\x97\x24\x30\xc8\x2c\x24\x30\xcc\x2c\xf4\x0d\x8a\x04\xca" +"\x58\x87\x1b\x09\x34\x99\xe5\xa3\x17\x4e\xa3\xde\x28\x41\x2d\xe9\x4d\x54" +"\x44\x7d\xd3\xf8\x92\xc6\x1d\x02\xcb\xf9\xf2\xca\xc8\x61\x27\x7a\x99\x43" +"\xe0\x83\x83\x0a\xbf\xac\x48\xb4\x25\x10\xbf\x39\x00\xca\xfc\x34\xea\xa3" +"\x21\x1d\x09\x14\x06\xa1\x48\x20\x1a\x71\x46\x5c\x02\x7d\x34\x2f\x5d\x8c" +"\x12\x7d\x84\x5b\xd2\x9b\x28\xf6\xa5\x01\x52\x5e\x34\x6b\x31\x97\x40\x7e" +"\x5f\x3b\x1a\xa4\xe7\x2e\x90\x0e\x81\xd0\xca\x3f\x08\xbc\xd8\xcb\xdd\x79" +"\x44\x96\xc2\x4b\x3e\x31\x00\xe8\x40\x01\x88\x95\xc1\x40\xe0\x56\x9a\x18" +"\xb5\xd3\x43\x3f\x10\x26\x81\xd0\x3f\x2e\x93\xbb\x04\x03\x0a\xfa\x68\x40" +"\xc7\x08\x97\xe8\xf8\x93\xe8\xcb\x61\x8b\xdb\xf4\x1c\x12\x88\x1c\x97\x17" +"\x07\xea\xbc\xfa\x8e\x68\xc2\xe8\x41\xf3\x84\xc5\xc7\x85\x9f\x09\x0c\x6c" +"\x5b\x5c\x0c\xd2\xb1\x3b\x4f\x1f\xa3\xfa\xe7\x06\x83\x95\xe3\x49\x79\x59" +"\x36\x06\x21\x8c\x93\x26\x46\xb0\x85\xeb\x4f\xb0\x68\x92\xd1\x66\x19\xd9" +"\x8d\xd0\x05\x98\x6a\xd7\xa5\x81\xa2\x2d\xda\xee\x28\x8b\x13\x38\x17\x3d" +"\x85\x0a\x77\x9e\x27\x99\x6d\x5b\xfe\x7a\x92\xa1\x52\x4f\x86\x31\xf4\xd5" +"\xed\xfd\x20\xd6\x06\x67\xb3\x68\xe3\xe8\x29\xb3\x3d\xbf\xc0\x71\xf8\x48" +"\xdb\x5b\xe8\xe1\xf6\x8f\xee\xc4\x2b\xd4\x4e\x9d\xde\x74\x94\x88\x76\xe8" +"\xe8\xf7\x86\x4e\x77\x99\x04\x1e\x41\x7b\xc4\xb6\xee\x0e\x35\x7e\x18\xe6" +"\xb0\xfb\x33\x39\x3d\xd4\xd1\xe5\x29\x3c\x22\x1e\xe4\xae\x47\xe1\xe1\xd0" +"\x9f\xa9\x07\x5e\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +"\x05\x05\x05\x05\x05\x05\x05\x05\x85\x57\x08\xe6\xfc\xfc\xc2\xb9\xde\x84" +"\xde\x2f\x28\x0c\xfc\x00\xf2\x87\xbb\x9d\xcd\xf9\x79\xd7\x32\xfc\xe4\x7c" +"\xa8\x1d\x74\x01\x03\x9a\xeb\xbd\x71\x1d\x7a\x72\xdd\xd6\x10\x70\x6d\xde" +"\x35\xee\x92\x3e\x56\xa0\x42\xf3\xb3\x9d\x02\xda\x0e\x54\xb0\x5e\x9e\xad" +"\x42\x4f\x48\x6c\x15\xdc\xe1\xf9\x80\x57\x47\xd1\x62\xbc\x8d\x4d\xc1\xb6" +"\xf1\x03\x48\xb3\xf3\x8d\x5e\x91\x25\xdd\xd0\xdb\x1e\xf9\x59\x81\x04\x15" +"\x1f\xb9\xb9\x71\x1d\x3a\xf1\x0d\x4c\x91\xdd\xa1\x2d\x3f\xf2\xc3\x7d\xa6" +"\x50\x2b\x8b\xb5\xba\x53\xa1\x8b\xcc\x21\xc9\x70\xa2\x68\x22\x84\xbb\x93" +"\x30\x1b\x71\x18\x35\xdb\x05\x48\x3f\xae\x5b\x7b\xfd\x08\x6e\x95\xb8\xc3" +"\x28\x56\x34\xde\x2d\x1e\x9b\x08\x44\x8e\xfc\x9d\xeb\x8f\xd5\x3a\x5e\x61" +"\x68\xb4\xa3\xb8\x45\x02\xfd\x94\x0c\x95\xc4\x56\xa4\x7d\x7d\x32\x32\x85" +"\x6f\x4b\x09\xc4\x7d\x22\xd2\x81\x58\x73\x9c\xab\x14\x2b\xba\xfb\x05\x02" +"\xd4\x65\xb4\x53\x40\x14\xdd\x48\x6b\xfb\x65\xce\x89\x76\x01\x65\xf1\x77" +"\xab\xe0\x0e\xee\xbe\x67\x8b\xa2\x70\x68\xed\x59\xd1\x0b\xb7\x7d\xb7\xc9" +"\x68\x54\x46\x4c\x17\x71\x1b\xc8\x3b\xdf\xa3\xb3\x71\x41\xe0\x68\x5c\x7c" +"\x1b\x29\x08\x2c\x2f\x11\xe1\x81\x64\x85\x9e\x2e\xe4\x49\xb2\x81\x7e\x52" +"\x1c\x02\x8d\x7c\xfe\xcc\xed\xe4\x39\x9d\xdf\x0b\x19\x0d\x52\x98\x4d\x46" +"\x68\x13\x7d\x93\x14\x6e\xe1\x97\x93\x7a\x61\xd6\x3e\x9c\x8c\xcb\x08\xea" +"\xc9\xa8\x70\x84\xee\x93\xa2\xbb\x4a\x84\x8f\x15\x59\x21\xb8\x43\x4e\xe4" +"\xf4\x91\x42\x5c\x4b\x9e\x27\xfb\xed\xa8\x43\xa0\xef\x54\x1c\xbf\xde\x34" +"\xe8\xbd\x90\x0c\xe4\x10\xa4\xb7\xb5\x39\x2c\x0a\xcb\x85\x6a\xaf\xee\x9d" +"\x0b\x11\x51\xf6\x5c\x08\xf6\x3d\x17\x02\xc3\x4c\x5b\x48\x2c\x97\xab\x46" +"\xe3\xdd\xe6\x9a\x8c\x98\xae\x73\xc6\x2d\x63\xd5\x8e\x26\x6c\x8c\xc5\xe0" +"\x67\x0b\x4c\x7c\x1b\x29\xbf\x77\x2c\x79\x1c\x0f\x24\xa7\xf8\xa2\x59\xe5" +"\xd1\x85\x51\xe6\x10\x18\xcc\x93\x20\xb3\x99\xc1\xef\x0d\xd9\xc5\x78\x91" +"\xd1\x24\x6d\xa2\x6f\x92\x44\x0d\xbf\x9c\xd4\x20\x57\x9b\x2f\x41\x69\x18" +"\x41\x7d\x29\xd2\x26\x30\x42\x57\xa5\x8f\x15\x22\x25\x30\x6f\x54\x65\xe4" +"\xf4\xd3\xbc\x64\x36\xd9\x9e\xb5\x64\xd5\x21\x30\x12\x25\xf8\xf5\xa6\x8f" +"\xde\x3b\x2a\x03\x39\x5c\xa4\xb7\x31\x44\x7d\xb1\x82\xe5\xea\xc2\x99\xca" +"\xb2\x6e\x17\xf3\x9c\xf2\xe5\xb3\xcf\x89\xc0\x01\x6a\x32\x73\x29\x5c\xf3" +"\xe1\x77\x8d\x17\x30\x62\x3a\x8f\x97\x97\x13\x4b\x87\x96\x62\x16\x17\xa1" +"\x69\xfc\xcc\xa0\x21\x6e\x61\xe8\x81\x58\xdd\xae\x87\x4c\xd7\x03\x49\x71" +"\xf1\x90\xc5\x67\xd1\x4f\x8a\x24\x10\xbf\xd1\x62\xe8\x35\x25\x6f\x56\x07" +"\x16\x63\xf5\xe4\x11\x0c\xd4\x5c\x2e\xe1\x87\x45\x1f\x50\x52\xc4\xc8\xe9" +"\x35\x93\xf9\x97\x0e\x89\xe0\x0b\x51\x87\x40\x58\x73\x7c\xac\x60\x27\x8b" +"\x05\x54\xd1\x79\x87\xf0\xd0\x1f\x2b\xf1\x0f\x98\x9f\x49\x02\x29\xfc\x35" +"\xeb\xef\xe2\xfd\x72\x02\x39\xf8\x20\x57\xa8\x25\x1e\x2e\xbc\xb5\x40\x11" +"\x15\x51\x76\xd5\xf1\xe4\xf0\x1c\x08\x3c\xc4\xcc\xfa\x5c\xd5\xcf\xcc\x40" +"\xf9\x1e\xbf\x25\x02\x7e\x5b\x70\xcd\x55\x19\x18\x5d\xf6\x81\x3a\x8d\x27" +"\x2a\xf8\xd1\x72\x0c\xbf\xde\x6d\x7b\x20\x29\x2e\x62\xdc\x75\x7b\x94\x3a" +"\x04\x46\xf0\x23\x37\xa8\x77\x39\x8f\x0e\x4d\x62\x55\xa4\x06\x7d\x93\x20" +"\x81\x1e\x4a\x84\xc7\xfc\x1a\x96\x36\x20\xe2\x7a\x77\x11\xe8\xf8\x58\xc1" +"\x8f\x2d\x69\x43\x44\x4e\x17\x07\xa0\x9f\xfd\xa3\x7a\x33\x59\x77\x24\x30" +"\x19\x25\xee\xa7\x87\x32\x90\x03\x14\x16\x19\x17\x04\x8a\x72\x4b\xa2\x08" +"\x2c\xbb\xf2\xfc\x08\x8c\xd5\xcd\xfa\xc8\x69\x0f\xb5\xd1\x51\xc9\x11\x19" +"\x31\x1d\x85\x26\x51\x1d\x19\x71\x09\x24\x34\x6e\x8a\x70\x21\xb1\x5a\x02" +"\x46\x6d\xd7\x03\x49\x71\x11\x77\x9f\xb4\x69\xbb\x0f\xdc\xe7\x10\x18\x16" +"\x61\xd2\x91\x1a\xf4\x4d\xb2\x81\xc0\x91\xd3\x3d\x04\xfa\x8e\xc8\xb0\xf7" +"\x4e\x85\x8a\xf8\xb9\x25\xaf\x84\x25\x81\xe8\x17\x6b\xd4\x76\x09\xf4\x45" +"\x87\x5c\x02\x65\x20\x07\x28\x0c\x63\xaa\xf7\x10\x78\x48\x94\xfd\xfc\x08" +"\x2c\x62\x10\x80\xbd\xe8\x16\x8b\xdf\xd7\x8e\xd0\xd3\xae\x04\x86\xab\xe4" +"\x30\x8d\x0b\x02\x99\x87\x86\x64\xa8\x93\x58\x0d\x26\x1e\x46\x7d\xa0\x4d" +"\x60\x15\xfd\xa4\xb8\x04\x6a\xd1\x55\x87\x40\xc8\xf2\xb0\x24\x10\x7d\x93" +"\xf4\x12\x08\xa5\xf5\x10\x18\x44\x09\xbc\xef\xaf\x6b\x17\x44\x85\x4c\x9a" +"\x17\x91\xd3\x1d\x02\x97\x88\xce\xde\x75\x09\xd4\x43\x2b\x0e\x81\x4e\x20" +"\x07\x28\x2c\x66\x95\x7b\x09\x84\xaa\x1d\x7e\x7e\x04\x56\x0d\x18\x2e\xe8" +"\xca\x1d\x92\x28\xc1\x78\x3c\x3a\x42\xa1\x07\xa4\xf1\x72\x23\xb1\x84\xa1" +"\x12\xf8\x1d\x8c\x51\xe4\xaf\x1b\x20\x15\x22\xac\x48\x02\x06\x91\x6a\xc7" +"\x03\xc9\x62\x98\x8d\x35\xd1\x8d\x89\x70\x2b\x46\xc9\x7e\xe8\x8b\xf0\x42" +"\x9a\x11\x7a\x6b\x59\x10\x38\x8e\xbe\x49\x90\x40\xe8\x46\x25\x81\x58\x5a" +"\xb8\x8a\x04\x8e\x4b\x02\xb9\x87\x26\x0f\x55\x93\x75\x61\x88\x03\x83\x08" +"\x5f\x6a\x47\x4e\x2f\xe3\xb7\x96\xe3\x74\xae\x3e\x44\x45\xbc\x26\x72\xe2" +"\x3e\x74\xa1\x40\xe0\x5c\x50\x06\x72\x80\xbe\x15\x9d\x70\xc5\x9c\x72\x91" +"\x40\xe1\x4c\x25\x21\x08\xfc\xe0\x99\xf3\xe7\x83\x81\xb1\x09\x2d\x06\xaa" +"\x17\x8c\x4b\x4f\x26\x22\x62\x7a\x99\xf3\x38\x06\x46\x3f\x49\xd1\x08\xc9" +"\x6f\xdb\xcb\xe2\x1b\x4a\xfc\xde\x31\x1e\xa6\xe3\xae\x07\x12\x8e\x31\x21" +"\xf6\x72\x11\xda\x9c\xe8\x9c\xae\xd1\x25\xe9\x23\x05\x83\x2c\x84\xca\x2c" +"\x44\xd0\x37\x09\xaf\x72\xf1\xe5\x64\x03\x57\x12\xed\x08\xea\x21\xfc\xb6" +"\x72\x8e\xae\x2d\xd4\x09\xe6\x63\xd3\x31\x1a\xc0\x0a\xc1\xd9\x17\x9d\xc8" +"\xe9\x7f\x85\x01\x97\x33\x0f\x9b\x13\xc1\x1c\x3c\x9c\x2e\xd0\x45\x19\xa2" +"\x81\x39\x81\x1c\x74\xde\x48\xac\x62\xdc\x09\x2c\xf7\x02\x6f\xf2\x1a\xaf" +"\xeb\xa2\x6c\x0e\x83\xf2\x73\xf3\x84\xe2\x39\xd5\xe5\xc9\x04\x23\x33\x94" +"\xef\x9c\x92\x6e\x4b\x86\x8e\x40\x8a\x2e\xbe\x89\xec\x0a\x28\xd7\xf6\x40" +"\x22\x3e\x7c\xdc\xbb\xe9\xd3\x47\x2d\x8a\x0e\x4d\xe4\xee\x6e\xdf\x24\x9d" +"\xd2\x9c\x53\x49\x7b\x0d\x7d\xac\x74\xb2\xc1\x6f\x2d\xf5\xc3\x22\x0b\x4f" +"\x88\x1c\x76\xbf\xdf\x24\x5d\x27\x38\x91\x1e\x3c\x81\xee\x98\xea\x12\x4e" +"\xd9\x5d\xf1\x28\x9e\x3b\x36\xbb\x34\x34\x1a\x3f\x1b\xc7\x36\x2f\x01\xb4" +"\xcd\x4e\x3c\x4d\xb6\x29\x49\x61\x5b\x78\x0a\x9b\xe6\xf0\xda\xd8\x8b\xa8" +"\x88\x82\x82\x82\x82\x82\x82\x82\x82\xc2\x73\x85\xd0\x90\x2d\xb8\x4f\x5a" +"\x1b\x35\x75\xdb\x42\x9f\xdf\x22\xa6\xc0\xc5\x1e\x9f\x8a\xba\xdd\x24\x91" +"\x2e\x55\xe0\x0f\x0b\xc4\x8e\x3a\xeb\x18\x23\x1d\xd5\x7e\xdb\x14\xb7\x55" +"\x88\x03\x01\xcf\x9a\xab\x29\xdc\xb2\x02\x2f\x02\xa8\x21\x43\x0f\xba\x96" +"\xd8\xda\xa4\x68\xea\x81\xa7\xd4\x59\x0f\x6f\xa1\x1c\x33\x7b\xa2\x0f\x98" +"\x55\x7c\xaf\x53\x49\x32\x87\x24\xbf\x7c\x99\x2d\x20\x43\x1a\xb0\x11\x27" +"\x44\x7a\x47\xa7\x26\x9f\xc2\xb7\x0a\x71\x20\xf7\x1d\xc2\x10\x9e\xe4\x22" +"\x2c\x89\x9f\x89\x3b\x73\xf1\x72\x73\x2e\x10\x2c\xc9\xcd\x07\x12\xe8\x1e" +"\x84\x18\xd8\xa2\xfe\xfe\x1e\x02\x13\xf7\x4f\x61\x44\x59\x83\x3a\xea\x36" +"\xa0\xb7\x1d\xdb\xc0\x71\xa6\xac\xfb\x65\x71\xed\xc0\xf6\x4e\x58\xf7\xad" +"\x42\x1c\xc8\x7d\x03\x68\x55\x2b\xdc\xfa\xbc\xd8\xc0\x89\xbd\x51\x08\x7c" +"\x85\x21\xbe\x1a\x4d\xe2\x13\x1c\x6a\xea\xce\x41\xeb\xbb\x20\x7e\x41\xe8" +"\xe6\xce\xa1\x46\x0c\xd5\x76\xe8\xf4\xf7\x4c\xe1\x68\x43\x9b\x9b\x25\x7a" +"\x12\x04\x40\xaa\xdc\xe2\xc9\x73\x44\xc4\x5d\x3f\xdf\xf4\xd7\x7d\x85\x68" +"\x04\x5d\x53\xa2\xba\xaf\x8c\x1a\xd2\xf2\xa2\x87\x5a\x64\xbc\x09\xcd\x32" +"\x59\x37\x0a\x51\x1d\x72\x3d\xb1\x1a\x12\x04\xc6\x6a\xa6\x11\x42\x27\x29" +"\x26\x95\x31\xd6\xcf\x37\x23\xf5\x59\x7d\xee\xbc\xa7\x90\x17\x0a\xb9\xc2" +"\x07\x4d\xcf\x6a\x40\x84\x7c\xbf\x20\x42\xbe\xcb\xa8\xb9\x24\xc2\x66\x75" +"\xfb\xc5\x4a\x60\x6f\x14\x02\x83\x8e\x00\x37\x55\x2e\x08\x4c\xdc\x65\x84" +"\xaf\xd2\x12\xfe\x12\x52\xc4\x68\x02\x8c\x7e\xb0\x0a\xdd\x97\x01\x07\x51" +"\x5e\x1b\x6d\xb2\x50\x90\xf1\x0a\x86\x17\x48\xb0\x32\x46\x57\xb7\x47\x6b" +"\x90\x1d\xc3\xb7\xb1\x43\xac\x18\x25\x18\x88\xdd\x25\xd0\x47\xa3\xe6\x0a" +"\xb7\x0c\xc6\xeb\x1e\x9a\x8f\x2c\x30\xc3\x2e\x36\x1c\x02\x13\x84\x48\xa5" +"\xdd\x6d\x27\x9c\x41\xb2\x3e\x9b\x28\xb0\x3d\x65\x0c\xdb\x5e\x35\xe8\x1a" +"\xb5\x85\xca\xf0\x94\x13\xf2\xdd\x21\x30\xc9\x66\x23\x6c\xc7\x23\x31\x3f" +"\x0e\x36\x44\x21\xd0\xf0\x85\xba\x29\xa2\x80\xd3\x28\x8f\xf3\x73\x18\x43" +"\x18\x35\x76\xd0\xb8\x2e\x50\x52\x64\x73\xe1\xa5\x98\x85\x6f\xbe\x3c\xb4" +"\xd9\xe0\x16\x3a\x2b\x09\x57\x4c\x36\x80\xaa\x37\x66\x02\x31\xd0\x78\xcb" +"\x55\x90\xc0\x60\xdc\xc7\x22\x51\xa2\xe1\xab\x6e\xf1\x2d\x43\xb9\x56\x5e" +"\x25\xe1\xa5\xa2\x75\xa8\x8a\x9a\x81\x3c\x3f\xcf\xe0\x3c\xf9\x0a\x3e\x46" +"\x29\xb2\x78\xa8\xe2\xa1\x24\x61\x15\x31\x9c\x81\xbf\x46\xa4\x83\x14\x74" +"\xa7\x42\xa8\x55\x5e\x86\x92\x96\x12\x16\x6f\x14\x2d\xa1\xf3\x17\x04\xa2" +"\xd3\x10\xeb\xc5\x4a\xe0\xa6\x28\x04\x40\x20\x3a\xc2\x26\x42\xd1\xd4\xa0" +"\x51\x8c\x61\x5f\xb6\xe0\x66\x8f\xd2\x50\x71\x09\xba\x2b\xec\xd7\x91\xc0" +"\x38\x89\x8c\x63\x58\x02\x74\xee\x3e\x57\x41\x7d\x86\xaf\xae\xad\x26\x21" +"\x3b\x8b\x60\xf0\x60\x03\x55\xc0\xc2\x1b\x82\x24\x90\x61\x20\xef\x15\xbe" +"\x18\xab\x88\xb0\xcd\x3c\x7a\xc1\xd3\x2c\x3a\x04\xb2\x04\x76\x65\x22\xe4" +"\x3c\xc7\x18\xeb\x16\xea\xb4\xa4\x83\x14\x74\x66\x41\xb0\x1c\x74\x42\x01" +"\x79\xc9\x80\xdb\x5d\x04\xe6\x5f\x6c\x1f\xb8\x29\x0a\x41\xb9\xa4\x8b\x28" +"\xce\x52\x53\xc7\x6f\xb3\x7d\xf8\x8b\x4e\x4e\x84\xb6\x2e\x51\x45\x43\x7d" +"\x24\x10\x5a\x32\xfa\x29\x2a\xc9\xf0\x02\xb1\x8a\x1f\xbd\xa1\x44\x44\x76" +"\xa8\x2d\xb6\x08\xea\x0c\x84\x8e\x48\x12\xb8\xc8\x6b\x44\x5f\x40\xbd\x24" +"\x12\x38\x8b\xe3\xf0\x1c\xaf\xb8\x7d\x20\x89\xc7\x84\xce\x89\x70\x0c\x67" +"\x50\x42\x02\x7d\x6c\x23\x81\xa8\x94\xeb\x26\xf0\x68\xdb\xcf\xca\x8b\xc3" +"\xa6\x28\x04\xbc\x64\xbc\x8b\x23\xb0\xd4\xd4\x05\x59\x43\x97\x12\xc8\xa5" +"\xc7\x21\x0c\xbb\xee\x12\x98\xb0\x04\x81\x55\x3f\x23\x7b\x24\x81\x1a\x3f" +"\x29\x09\xac\xf3\x8a\xe7\x04\x06\xbf\xee\x48\xe0\x62\x84\x86\xcc\x4a\x71" +"\x31\x2c\x25\x10\x76\x1a\x75\xb7\x09\xd7\x0c\xdd\x72\x08\x14\xe1\x0c\x04" +"\x81\xd2\x41\x4a\x17\x81\x58\x76\x0f\x81\x05\x47\x02\x3d\xe7\x1e\x74\x89" +"\xcf\x14\x1b\xa2\x10\xc0\x3c\xb0\xb8\x72\x31\xce\x43\xb8\x86\x7d\x1f\x2a" +"\x95\x44\x1f\xa8\xc1\x81\xd8\x99\xa1\xda\x0e\xd8\x68\x42\xc3\x26\x30\xf8" +"\x34\x12\x4b\xbc\xe6\xa3\xb7\xee\xc4\xaa\x26\x46\x52\xa7\x36\x0b\x71\x24" +"\x30\xc8\xde\x29\x89\x20\x06\xe7\x9c\xef\xb9\x38\x4c\x63\x96\x63\x30\x50" +"\x40\x17\x8b\x5f\x19\x94\xd9\xd9\x08\xe3\xec\x1d\x9c\xce\x25\x6a\x24\x52" +"\x8a\x55\x0e\x01\x81\x67\x30\x9c\x81\xb8\x05\xe7\xf9\x02\x3a\x48\x19\x90" +"\xfe\x90\x90\x40\xa1\x32\xc4\x90\xef\xf5\xf3\x22\xcc\xbb\xde\xc4\xa3\x96" +"\xcb\x95\x8d\x4e\xf8\x9e\x23\x36\x44\x21\x40\xfd\x1c\x3b\xc9\x6c\x42\x1c" +"\x4d\x1d\xa7\x2c\x8a\xbf\x40\xc0\x5d\x11\xe4\x1c\xd5\x76\xd8\x69\x05\x69" +"\x83\x14\x9b\xe5\xc6\x3b\x9c\xb7\x55\x6e\x73\xf4\x3c\x5d\x85\x3e\x73\x05" +"\xf6\x8f\xd2\x26\xb3\x43\x18\x88\x9d\x79\xb0\x4b\x88\x50\x60\x16\xa8\x4b" +"\xe0\x26\x1d\x13\x5e\x4e\x4c\x96\x14\x6e\x51\x0c\xce\x16\xa8\x85\x4e\x52" +"\x0e\x63\x00\x76\xe6\x81\x1c\x80\xed\x72\x93\x8b\xb0\xed\x09\x76\x86\x8a" +"\xd5\xae\x90\xef\xa8\xad\x5b\x83\x5a\xd3\xe5\x08\xe5\xcc\x7c\x81\xfe\x06" +"\x37\x44\x21\x00\x9c\xd2\xf7\xc9\x35\xd4\xd4\x25\xa0\x33\x93\xb1\xd4\x75" +"\x38\x14\x21\x14\x63\x5a\x94\x10\x27\xa8\xf9\x11\x4f\x80\x78\xa2\x9b\xb2" +"\x83\x63\x86\x4e\x91\x8d\x81\xd8\x85\xb6\xce\x29\xe9\x08\xe9\xc4\x48\x6f" +"\xa3\xa3\x79\xdb\x07\xd9\xef\xdb\xb0\xb7\x13\xf2\xdd\xc5\x3e\x8c\x8b\xe0" +"\x54\xe7\xe7\x08\xdd\x1e\x39\xbb\x8d\x93\x44\x85\x47\x01\x3c\x88\x6c\xfb" +"\x38\xaf\xf0\x28\xd8\x5f\xf8\xd9\x44\x6e\x53\x50\x50\x50\x50\x50\x50\x78" +"\x34\xf4\xbd\xfe\xa2\x6b\xf0\x72\xc3\x58\x5b\xf8\xa5\x7e\x19\x77\x71\x7e" +"\xc1\x90\x71\x02\x1c\xa0\x4e\xac\x41\xfc\x0d\xb9\x6e\x61\x94\x00\x91\xe8" +"\x84\x1a\x30\x37\x58\xaa\x25\xd9\xbd\x71\xb2\x01\x86\x50\x60\x74\x1d\xd9" +"\x67\x37\xc7\x6c\xb1\x75\x31\x4a\x82\xb0\x86\xcb\x9a\xb4\xaa\x4b\xda\x01" +"\x78\x42\x96\x4b\x12\x1f\x97\x3b\x2a\x3c\x34\x8c\x13\xce\xcb\x7f\x24\xe4" +"\xec\xfc\xfc\x3d\xf1\xe4\xe6\xd9\x2a\x68\x01\x9a\xd7\xcd\xbb\xa9\x6d\xb3" +"\xbe\xc8\x76\x66\x75\x3b\x09\x34\x54\x0b\xf7\xe8\x10\x13\x6c\x94\xc5\xc3" +"\x32\xcc\x27\xbe\xf9\x33\xf1\xb3\x65\x11\x6a\x20\xc2\x44\x78\x81\xee\x83" +"\x0d\x76\x3e\xb9\xc9\x08\x4e\x3e\xcc\xcb\x23\x85\xb2\xd1\x04\x1a\x0c\xa4" +"\x22\x49\xa3\x1a\x8f\xd4\xc4\x42\x29\x6a\x95\x4c\x4a\x4b\xda\xda\x21\xb1" +"\x78\xa8\xf8\xcc\xba\xa3\x81\xc2\x60\x88\x50\x03\x4f\x0d\x5f\x0c\xad\x70" +"\x41\xe6\x96\x41\x0b\xfc\x4d\x38\xd4\x4d\x1d\x68\x57\x88\x3f\x87\x60\xa5" +"\x46\x3b\x4e\x80\x8b\x58\x4d\xa7\x96\x4f\x9a\x3e\x4a\x02\x09\xe9\x0a\x35" +"\xd0\x4b\x20\x56\x71\x53\x7c\x01\x27\x24\x01\x1e\x69\x88\xb7\x9b\xc9\xb8" +"\x7e\x5e\x68\xde\xce\xd0\xa8\x87\x62\xec\x4d\x83\x1e\x65\xab\x65\x48\x39" +"\xd4\xe4\x4b\x66\xcd\xac\x8a\xe5\x5c\x19\x48\xf0\x75\x08\x1c\xa8\x8b\x88" +"\xe2\xe2\x86\xd0\x92\x21\x09\x8f\x13\xcf\x66\x02\xa3\xb1\x1a\xb1\xdc\xb3" +"\xda\x04\x96\x9f\xc3\xbb\x55\xe9\x23\x1b\x63\x74\x47\xe0\x3f\x2a\xce\x04" +"\x81\x85\xd9\x13\x85\xc8\x32\x10\x38\x7e\xdb\x90\x41\x85\x45\xa8\x01\x0c" +"\x2f\x90\xc7\x30\x01\xfb\x57\x65\x7b\x42\x01\x39\x83\x21\xbd\xcf\xdc\x1e" +"\x3d\x67\x14\x66\xcf\xcc\x16\xbe\x4f\xe2\x71\xab\x23\x21\x7a\xbb\x49\x8a" +"\xe8\x66\x9f\xd8\xe4\xe2\x5c\xdc\x6f\x89\x57\xfa\x68\xec\x30\x0e\xcb\x58" +"\x54\x7c\xb2\xbe\x97\xf0\xfb\x03\x35\x3f\xc3\x85\x90\x62\x09\x09\x8c\x40" +"\x4e\xb7\xce\x48\x4d\x11\xda\x50\x84\x91\x39\x10\x54\xd4\x2d\x88\xa0\x05" +"\xc2\x90\x0e\x23\x91\xa3\x58\x47\xa2\x70\x9f\xd0\x80\x2f\x9a\x44\x1d\x5f" +"\x13\x09\x4c\x8e\x39\x04\xa2\x02\x0f\x12\x9f\xe1\x03\xa8\x24\x90\x5f\xb4" +"\x50\xfd\x55\x43\xc5\x59\xac\x16\x61\xd1\x44\x25\x48\xc5\xeb\xf8\x44\x43" +"\x67\xa4\x1d\x6a\x40\x84\x17\x78\xb7\x69\x13\x9e\x14\x37\x57\x5a\xaa\x1a" +"\x2c\xb1\x1c\x61\x76\xdd\x43\x97\x23\xcb\x9c\xd1\x64\x5d\xe3\x49\x16\xa7" +"\x36\x3d\xcf\x91\x40\xad\xa9\x35\xcd\xb8\xe1\x12\xa8\xd1\x02\x3a\xd9\x27" +"\xba\x6c\x60\xc5\x52\xb8\xe6\xaf\xe3\x42\x34\x0e\xb7\xc5\xc7\x6c\xb6\x8f" +"\x2e\xa3\xf9\x2f\xc6\xd1\x45\xdb\x00\x2c\x05\x6e\x15\x0a\x54\x42\xc8\x27" +"\x1a\xd2\x99\x4e\xd0\x82\x2a\xde\x07\x24\x10\xe3\x22\xe0\x32\x00\xc2\xbc" +"\xe6\x10\x88\x61\x64\xe3\xfe\xea\x56\x51\x4c\x76\x96\xc0\x65\x8c\xe6\x3d" +"\x8e\x8a\x33\xd4\x89\x35\x09\x5a\x58\x60\x14\xef\x12\xd4\x4e\x5c\x27\x86" +"\x1a\x30\xeb\x06\xdd\x83\x41\x7d\xcb\x63\xcc\x23\xfa\x39\xbf\x68\xd0\x66" +"\xcd\x5f\x35\xd9\x10\x8d\xf3\xfb\x66\xa8\xc8\xe6\xcc\xba\x8f\xa1\xaa\xcd" +"\x72\x14\x14\x5a\x13\x1a\xf5\xa0\xf1\xdf\x05\x81\x06\x3d\x4f\x6f\xc3\x92" +"\x27\x86\x74\xed\x5e\x8e\xc7\x40\xfa\x70\x91\x81\x5c\x7d\x4c\x83\x9c\x96" +"\xcc\x10\x6a\xcb\x6d\x16\x27\xda\x32\x32\x47\x45\xc0\xe2\x4e\xd0\x82\x8a" +"\x08\x5a\xc0\xf3\x89\x52\x39\x2e\x09\xc4\xb8\x08\xb8\x00\x81\xb5\x88\x43" +"\x20\xe1\x3f\x96\xad\xb0\xf5\x0c\xdd\x4f\x3b\x04\xb2\x00\x5f\x2d\x37\x85" +"\xf3\x7f\x61\x88\x84\xf5\x43\xab\x95\x85\xfb\x84\x88\x31\x1a\x43\x0d\xf8" +"\xea\xf2\x75\xfa\x3d\xfe\x03\x48\x1b\xde\x54\x19\x72\x3e\x5c\xf5\xd7\x85" +"\x62\x23\x0c\x15\x47\xe3\xb5\x3a\x52\x88\x8a\x8e\x36\x81\xf6\x9b\xff\xcd" +"\x67\xc9\x2f\x44\xe6\x60\xf0\xc0\x85\x98\x96\x51\x28\x10\x10\xf0\xb6\x04" +"\x1a\xd8\xa5\x62\x4e\x56\x58\x50\x30\xc0\x50\x87\x6c\x58\x18\xd2\xc6\x95" +"\xc0\x1a\xf1\x15\x0a\x47\x9b\x42\xff\x24\x7c\xee\xdf\xe3\x79\x49\x20\xc6" +"\x45\xc0\x05\x08\xa4\xcb\x2e\x81\x70\x40\x09\x8d\xf9\x9e\x29\x81\x26\x89" +"\x50\x0b\xa3\x79\x73\x54\x1f\xa1\x3d\xf5\x92\x4b\x20\x85\xaa\x8b\x51\x03" +"\xeb\xe4\xab\xfb\x05\x81\x2b\x23\x27\xeb\xf2\x63\x19\x43\xda\x7e\xa1\x8d" +"\x10\x5e\xb6\x1f\x58\x46\xd3\x21\xd8\x8b\xda\x5b\x97\x40\xe8\xec\xf8\x9a" +"\xdb\x07\x12\x6d\x94\x89\x85\x84\xe3\x7e\x4a\x81\x46\xf4\xbb\x5f\xc7\x45" +"\x9a\xb5\xfb\x50\xb9\x6b\x32\x1c\x88\x06\xea\x11\xb4\xcd\x5c\x2b\xa3\xf7" +"\xf8\x12\x41\x8b\x29\x11\xb4\xa0\x22\x83\x16\x10\x27\x68\x41\xa8\x4d\x60" +"\x0d\x97\x81\x9a\x54\x24\xb6\x09\x44\x25\xd8\x33\x83\x0e\x04\x9e\x24\xe7" +"\x78\x25\xb1\x44\x8e\x9c\x10\xb1\xce\xbb\x09\xbc\x47\xe3\x9a\xe8\x81\x85" +"\x45\x60\x5d\x84\x17\xe0\xf7\xb5\x08\x50\x74\xea\x02\xda\x42\xc0\xad\xde" +"\x77\xc8\x95\x40\xfc\x5a\x43\x10\x48\x12\x76\xbc\x8b\xc0\x64\xfc\x1f\x9b" +"\x62\x14\x16\xb4\x07\xab\x72\x49\x84\xf4\x91\x11\x62\x8f\x24\x4d\x0c\x9d" +"\x81\xda\x36\x62\x3a\x12\x18\xf7\x88\x3b\x33\x50\x47\x7d\x47\x92\xa0\x8d" +"\x1e\x2d\x09\x33\x76\x19\xb4\x00\x0d\xe9\x1c\x02\x81\x55\x87\x40\x8c\x8b" +"\x90\x10\x12\x68\x44\xe8\xd0\x6c\x87\x40\x5e\x79\x96\x06\x06\x7c\x59\x6b" +"\x92\xbb\xe6\x52\xb8\x9e\x1c\xb7\x8a\x68\x4f\xcd\x0c\x5a\x42\x6b\x33\x61" +"\x78\xc6\x1b\xa6\x70\xa8\x80\x21\x04\x9c\xf0\x02\x68\x4e\xc7\x0c\x26\xe6" +"\x87\x11\x16\xd0\x9b\x7e\x66\x56\x7d\xec\x34\x6c\x43\x6b\x12\xaa\x3a\x67" +"\xc2\x03\x4d\xb1\x8a\x44\xb4\xe7\x81\x28\xef\x1a\x97\x8b\x18\x84\x31\x20" +"\x73\x15\xf2\x6a\xe0\x92\x58\x36\xb1\x0f\xa4\x3a\xda\x87\xe1\x79\xe1\x3a" +"\x4e\x40\x9b\x30\xa5\x5c\x02\x02\x47\xf1\x73\x2e\x9d\x63\xd0\x02\x53\x04" +"\x2d\xd8\x0b\x7d\x20\xd6\x26\x2a\x09\xc4\xb8\x08\xb8\x0c\x30\xf3\x14\x17" +"\x9a\x39\xec\x03\xad\x72\x29\xc6\xc6\x6e\x3f\xbb\x61\x24\xc2\x40\xc2\xcb" +"\xb6\x65\x52\x68\x86\xf0\x24\x60\x70\xc6\x59\x88\x43\xe3\x41\xc3\xb3\x0a" +"\x67\x27\x64\x73\x90\xa1\x06\x92\x8c\xae\x04\x69\x95\x70\x1b\x2e\x39\x80" +"\xd7\x53\xb7\xd1\x9a\xd5\xc2\xb1\x53\x08\x15\x5c\xf1\x28\x1d\xa3\x18\x1b" +"\x1c\xfa\x54\xbf\xf8\x04\xab\xcf\xbe\x3b\xb6\x80\x3d\xc1\x0f\x74\x55\xb7" +"\xff\x4a\x70\x21\x9a\x18\x9c\xc2\x94\x56\x88\x0d\x9d\x3c\x2c\x31\xa1\xb8" +"\xf3\xd9\x18\xe9\x3b\x81\xf2\x0a\x63\x78\x90\xae\xd5\xa3\x3e\xce\x92\x94" +"\xb1\x65\x59\x5f\x0c\x5a\xc0\xdc\xa0\x05\x2b\x7e\x8a\xc3\x8a\x51\x66\x79" +"\x8c\x8b\x80\x4b\x82\x9d\xb5\x99\x1f\x64\xfd\x04\x67\x63\x78\x88\x81\x66" +"\x75\xcf\x6e\x1c\xc6\x38\x01\x18\xa3\xfb\x48\x48\xdb\x7b\x6a\xab\x03\x64" +"\xe0\x00\x69\xaa\x26\xc2\x0b\x8c\x04\x88\x0e\x8b\x50\xb8\x89\x98\xe0\x9e" +"\xd3\xd0\xf0\x50\x47\x76\xd2\x3d\x87\x53\xe7\xe3\x35\xa9\x95\x33\xd6\xe6" +"\xdd\x80\x52\x18\xa8\x40\x04\x2b\xd0\x3a\x85\x39\x69\x8e\xbe\x6f\x0f\xc6" +"\xff\x6e\xe7\xb4\xb9\xbe\x9b\x82\x16\x74\x5f\x89\x88\x7a\x80\x8a\xc4\x44" +"\xa0\x73\x8a\xe7\x25\x88\x62\x80\xcf\x0f\x9e\xa6\xcb\x92\x59\x1d\xe9\x8d" +"\x7f\xa4\xed\x79\xac\xdc\xf4\xe6\x53\x07\xf0\xb2\x9f\x36\x83\xe7\x8c\x20" +"\x34\x68\xa3\x6d\x4b\xe7\x63\x63\xf6\xd3\xb4\x19\xe3\xa9\xad\xf2\xcc\x67" +"\xff\x1a\x61\x67\x71\xa6\x00\x7d\xdc\x58\xa0\xb3\xb9\x65\x6f\xf0\xc8\xe8" +"\xe4\xa4\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xf0\xb3\x84" +"\x9e\xda\xe8\x7b\x49\x4f\x91\x9d\x7b\x03\x77\x20\xb5\x63\x59\xfd\x8c\xe0" +"\xcd\xa6\x67\x9c\xbf\xde\x6c\x26\x93\x4b\x65\xd3\xe9\xf4\xd7\xde\x74\x3a" +"\xe4\xcd\xce\x68\xd9\x6c\x66\x7a\x0a\x12\xd2\x1f\xe1\x5f\x38\x90\xe8\xb8" +"\xff\x5b\x71\xfc\x54\x66\x82\x4c\xa5\x6f\x90\xfe\xf4\x4c\x36\x9d\x91\x6b" +"\xd3\x78\x70\xfa\x26\x1e\x94\x81\x83\x26\x48\x36\x83\x67\x7e\x17\x20\xe4" +"\x78\x26\x9b\x79\x76\xef\x43\x5f\x1c\x26\xd3\xf8\xf7\x18\xfc\x9d\xcc\x84" +"\x0e\x64\x27\x7e\x9b\x26\xde\xaf\x61\xfb\x5b\xf2\xda\xc4\xaf\x6e\x90\xc9" +"\x69\x2d\xfd\x05\x99\xfc\xc8\x9b\xfe\xe2\x60\x7a\x1a\x8e\xec\x4f\x7f\xf4" +"\x49\x3a\xf0\x5b\x58\xf7\x7e\x49\x88\x96\x4d\x87\x48\x0e\x13\x9d\xb5\xaf" +"\x87\xe1\xc0\x69\xd8\xf6\xe6\xc8\x41\xe4\x74\x9a\x64\x6f\x78\xd3\x37\x89" +"\x17\xce\xc8\x7e\xf5\x62\xaf\xf5\x99\xe0\xb5\xb4\xf3\xd7\x9b\x86\xcb\x3b" +"\x36\x01\x6b\xa1\xef\x60\x3b\x43\xfa\x27\xfa\xbf\x42\x02\xd2\x5f\xe8\xfd" +"\x48\xa0\x96\xfd\x1a\x8e\xfc\x55\xfa\xa3\xfe\xf4\x04\x1e\xdc\x3f\x01\x9b" +"\xd9\xf4\x97\xe4\x63\x24\xd0\x59\xfb\x02\x0f\x44\x02\xf7\x1c\x87\xd4\x74" +"\xe0\x57\xb0\x03\x6e\x43\x06\x6e\x49\x40\x2c\xbf\x38\xb4\x09\x04\x5a\x40" +"\xbe\x90\xc0\x2f\x86\x49\x3f\x34\xbf\xfe\x89\x63\xe9\x09\x1d\x09\xec\xd7" +"\x81\xb1\x2f\xa4\xb0\x4a\x02\xa1\x69\x92\x29\x3c\xf1\x3b\x60\x5a\x12\x28" +"\xd7\xc4\x81\x13\xb0\x3d\xe3\x25\xfd\x9f\xa4\xa7\x25\x81\xaf\xa5\x27\xe0" +"\x04\x59\xc4\x2f\x0d\x6d\x02\x8f\xa5\x43\x72\xcd\xfb\x05\x5c\x6a\x7f\xfa" +"\x06\x48\x60\x1a\xba\x39\x20\x70\x12\x7a\x49\xe0\xe5\x18\x5e\x3f\x10\x88" +"\x44\x4e\xa6\x2f\x8b\xf6\x38\x33\x99\x9e\x96\x04\xca\x35\x71\x20\x6c\xff" +"\x2b\x74\x98\xfd\xa9\x74\x46\x12\x08\x9d\x23\x8a\x6f\xbf\xe8\x04\x7e\x61" +"\x68\x13\x28\x3b\x43\x58\xcb\x22\x03\x5a\x3a\x7d\x10\xa4\x29\x9d\x09\x90" +"\x74\x26\x2d\x79\x79\x4d\x12\x98\x83\xfe\x11\xb8\xc8\x4d\xe3\xe1\x33\xc0" +"\xb4\x43\xa0\x58\x73\x09\x04\xd6\x40\x9c\xb3\xe9\x0f\x5d\x02\xd3\x5f\xe3" +"\xb9\xd3\x2f\xea\x32\x9f\x1d\x36\x13\xf8\x09\x32\x00\xe2\x96\xc3\x41\x16" +"\x2e\x39\xfd\x75\x2f\x81\x33\x59\x60\x55\x4f\xcb\xfe\x6c\x06\xfa\xbe\xef" +"\x24\x81\x62\xcd\x25\x30\x27\x08\x04\x11\x7e\x25\x08\xd4\x42\x82\x40\xa7" +"\x09\xeb\x82\x40\x90\xbe\x89\xbd\x90\xf8\x15\x34\xe1\x63\x92\x97\xdf\xe2" +"\x11\xa2\x0f\xfc\x88\x60\x27\x88\x98\x81\xd4\xaf\x1d\x02\x71\xcd\x25\xf0" +"\x23\x6c\xc2\x13\x20\xc7\x0e\x81\x1f\xfd\xa2\x9b\xb0\xf7\x23\xf8\xfb\x5b" +"\xd9\xc3\xc3\xda\xb4\x77\xa2\x1f\xc7\xd7\x89\x29\x98\xa6\xdc\xc0\x41\x84" +"\xa4\xba\x07\x91\x5f\x21\x47\x9f\x7c\x2d\x4e\x9f\x01\x59\x74\x09\xd4\xbb" +"\x09\x4c\xc1\x58\x3c\x01\x72\xfc\x4a\x0c\x22\x62\xec\xfd\x15\x4c\x43\xc8" +"\x41\xdc\x0e\xf5\x87\x0e\x8a\xab\x9d\x0c\x91\xd7\x50\x02\x75\x32\x83\xbc" +"\x60\xbf\x26\x25\x70\xba\x8b\x40\x32\xe9\x12\x88\x6b\x6d\x02\xf7\xfc\xea" +"\x23\x20\xd0\x9b\xee\x4c\x63\xc8\x2f\x73\x1a\x83\x17\x95\x9d\x70\x26\xd2" +"\x7a\x0e\xb7\xf5\x2c\x99\x0c\x80\xf0\x4d\x4c\xde\x24\xc7\xa6\x75\x68\xc5" +"\xc7\x71\x7a\x77\xdc\x99\x48\x4f\x8b\xd1\xf8\x13\xd9\x84\xb1\xab\x93\x04" +"\xca\x35\x97\xc0\x69\x32\x39\xf1\x1a\x1c\x96\x45\x02\x0f\x88\x89\xf4\xb7" +"\xbf\xc8\x89\x34\x3c\x6f\xe5\xb2\xe9\x61\xf1\x28\x97\xce\x64\x27\x60\x1b" +"\x1e\xb9\xe0\x31\x0e\x27\xd5\x93\xd9\x5c\x26\x04\x03\x49\x2e\xfd\xc5\x14" +"\x8c\xc5\xe2\x51\xee\x13\xb9\xf2\x61\xf2\xfc\xa3\x01\x00\x00\x00\xa9\x49" +"\x44\x41\x54\x3a\x7d\x1d\x36\xa7\x32\xd3\x30\x17\x84\x93\xbe\x96\x6b\x90" +"\x02\x53\x1f\x1d\x33\x49\xa7\xb2\x39\xa0\x52\x3e\x04\x06\x70\x47\xee\x17" +"\xf9\x28\xd7\x05\x6f\xaa\xe7\x02\xbd\xa1\x61\x3d\x35\xf1\x08\xe7\x1d\xd8" +"\x62\xcd\x85\xd6\xc9\x60\xf8\xfa\x2f\x9c\x3f\x05\x05\x05\x05\x05\x05\x05" +"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +"\x05\x85\xed\xf1\xff\x01\xf2\x3f\x50\x38\x83\xb3\x93\x7a\x00\x00\x00\x00" +"\x49\x45\x4e\x44\xae\x42\x60\x82"; + +static const unsigned int LICENSE_SIZE = 72771; + +static const char* LICENSE_NAME = "license.png"; + diff --git a/game/code/main/gamecube_extras/screenshot.c b/game/code/main/gamecube_extras/screenshot.c new file mode 100644 index 0000000..bf44be2 --- /dev/null +++ b/game/code/main/gamecube_extras/screenshot.c @@ -0,0 +1,345 @@ +/*---------------------------------------------------------------------------* + Project: onetri + File: screenshot.h + + Copyright 1998, 1999, 2000 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + Created 05-25-01 by Steve Rabin + + *---------------------------------------------------------------------------*/ + +#include <main/gamecube_extras/screenshot.h> +#include <dolphin/hio.h> +#include <string.h> + + +#define WIDTH_SCREENSHOT 640 +#define HEIGHT_SCREENSHOT 480 +#define SIZE_SCREENSHOT_RGB WIDTH_SCREENSHOT*HEIGHT_SCREENSHOT*3 +#define SIZE_SCREENSHOT_YUV WIDTH_SCREENSHOT*HEIGHT_SCREENSHOT*2 + +#define XFB_BASE 1 +#define XFB_RANGE 6 +#define EFB_BASE 11 +#define EFB_RANGE 9 +#define PING_BASE 20 +#define PING_RANGE 9 +#define MINIMIZE_BUFFER_TRUE 35 +#define MINIMIZE_BUFFER_FALSE 36 + + +typedef enum { + GRAB_NOT_TRANSFERRING, + GRAB_TRANSFERRING +} GRAB_STATUS; + + +//Globals +BOOL g_connected = FALSE; +BOOL g_ping_received = FALSE; +u32 g_received_signal = 0; +BOOL g_mail_waiting = FALSE; +BOOL g_minimize_buffer = FALSE; +s32 g_usb_channel = -1; +u8* g_data; + + +static BOOL HostIOEnumCallback( s32 chan ) +{ + g_usb_channel = chan; + return( FALSE ); +} + +static void HostIOCallback( void ) +{ + //Mail is waiting for us - don't look at it yet + g_mail_waiting = TRUE; +} + + + +static void CopyoutEFB( u8* image_buffer, u32 width, u32 height ) +{ + u16 i, j; + u32 color; + + for( j=0; j<height; j++ ) { + for( i=0; i<width; i++ ) { + GXPeekARGB( i, j, &color ); + image_buffer[2] = (u8)(color & 0x000000FF); + image_buffer[1] = (u8)((color & 0x0000FF00) >> 8); + image_buffer[0] = (u8)((color & 0x00FF0000) >> 16); + image_buffer += 3; + } + } +} + + + +static void CopyoutPortionEFB( u8* image_buffer, u32 width, u32 startByte, u32 totalBytes ) +{ + u32 color; + + u16 x = (u16)((u32)(startByte/3) % width); + u16 y = (u16)((u32)(startByte/3) / width); + u32 component = startByte%3; + + u32 count = 0; + while( count < totalBytes ) + { + GXPeekARGB( x, y, &color ); + + if( component == 0 ) { + count++; + image_buffer[0] = (u8)((color & 0x00FF0000) >> 16); + } + if( component <= 1 && count < totalBytes ) { + count++; + image_buffer[1 - component] = (u8)((color & 0x0000FF00) >> 8); + } + if( component <= 2 && count < totalBytes ) { + count++; + image_buffer[2 - component] = (u8)(color & 0x000000FF); + } + image_buffer += 3 - component; + component = 0; + + x++; + if( x >= width ) { + x = 0; + y++; + } + } + + +} + + + +static void TakeScreenshotEFB( SCREENSHOTAllocator allocator ) +{ + if( g_data == 0 ) { + g_data = (u8*)allocator( SIZE_SCREENSHOT_RGB ); + } + CopyoutEFB( g_data, WIDTH_SCREENSHOT, HEIGHT_SCREENSHOT ); + DCFlushRange( &g_data[0], SIZE_SCREENSHOT_RGB ); + OSReport( "SCREENSHOT: Saved off screenshot to local memory.\n" ); +} + + + +static void TakeScreenshotXFB( void* bufferXFB, SCREENSHOTAllocator allocator ) +{ + void* buffer = bufferXFB; + if( g_data == 0 ) { + g_data = (u8*)allocator( SIZE_SCREENSHOT_YUV ); + } + memcpy( g_data, buffer, SIZE_SCREENSHOT_YUV ); + DCFlushRange( &g_data[0], SIZE_SCREENSHOT_YUV ); + OSReport( "SCREENSHOT: Saved off screenshot to local memory.\n" ); +} + + + +static void WriteScreenshotPortionEFBtoUSB( u32 chunk, SCREENSHOTAllocator allocator ) +{ + u32 i; + u32 size1K = 1024; + u32 size100K = size1K*100; + if( g_data == 0 ) { + g_data = (u8*)allocator( size1K ); + } + for( i=0; i<100; i++ ) + { + CopyoutPortionEFB( g_data, WIDTH_SCREENSHOT, (chunk*size100K)+(i*size1K), size1K ); + DCFlushRange( &g_data[0], size1K ); + while( !HIOWrite( 0x00000500 + (i*size1K), g_data, (s32)size1K ) ) { + //Spin until communication is successful + } + } +} + + + +static GRAB_STATUS GrabChunk( u32 chunk, + void* bufferXFB, + SCREENSHOTAllocator allocator, + SCREENSHOTDeallocator deallocator ) +{ + if( chunk >= XFB_BASE && chunk < XFB_BASE + XFB_RANGE ) + { + void* buffer = 0; + + if( chunk == XFB_BASE ) + { //save off XFB screenshot + if( !g_minimize_buffer ) { + TakeScreenshotXFB( bufferXFB, allocator ); + } + } + + //transfer chunk + if( g_minimize_buffer ) { + u8* fb = (u8*)bufferXFB; + buffer = (void*)( &fb[100*1024*(chunk - XFB_BASE)] ); + } + else { + buffer = (void*)( &g_data[100*1024*(chunk - XFB_BASE)] ); + } + + while( !HIOWrite( 0x00000500, buffer, 100*1024 ) ) { + //Spin until communication is successful + } + OSReport( "SCREENSHOT: Wrote chunk #%d.\n", chunk ); + + //communicate that the chunk is ready to be read + while( !HIOWriteMailbox( chunk ) ) { + //Spin until communication is successful + } + OSReport( "SCREENSHOT: Notify of write chunk #%d put in mailbox.\n", g_received_signal ); + } + else if( chunk >= EFB_BASE && chunk < EFB_BASE + EFB_RANGE ) + { + void* buffer; + + if( chunk == EFB_BASE ) + { //save off EFB screenshot + if( !g_minimize_buffer ) { + TakeScreenshotEFB( allocator ); + } + } + + if( g_minimize_buffer ) + { + WriteScreenshotPortionEFBtoUSB( chunk - EFB_BASE, allocator ); + } + else + { //transfer chunk + buffer = (void*)( &g_data[100*1024*(chunk - EFB_BASE)] ); + while( !HIOWrite( 0x00000500, buffer, 100*1024 ) ) { + //Spin until communication is successful + } + } + OSReport( "SCREENSHOT: Wrote chunk #%d.\n", chunk ); + + //communicate that the chunk is ready to be read + while( !HIOWriteMailbox( chunk ) ) { + //Spin until communication is successful + } + OSReport( "SCREENSHOT: Notify of write chunk #%d put in mailbox.\n", g_received_signal ); + + } + + if( chunk == XFB_BASE + XFB_RANGE - 1 || + chunk == EFB_BASE + EFB_RANGE - 1 ) + { //free screenshot buffer space + if( g_data ) { + deallocator( g_data ); + g_data = 0; + } + return( GRAB_NOT_TRANSFERRING ); + } + else { + return( GRAB_TRANSFERRING ); + } + +} + + + +static void CheckMail( void* bufferXFB, + SCREENSHOTAllocator allocator, + SCREENSHOTDeallocator deallocator ) +{ + u32 temp = 0; + u32 escapeCount = 0; + GRAB_STATUS status = GRAB_TRANSFERRING; + while( status == GRAB_TRANSFERRING ) + { + escapeCount++; + if( g_mail_waiting ) + { + if( HIOReadMailbox( &temp ) ) { + g_mail_waiting = FALSE; + status = GRAB_NOT_TRANSFERRING; + if( temp >= PING_BASE && temp < PING_BASE + PING_RANGE ) + { //ping message received + while( !HIOWriteMailbox( temp ) ) { + //Spin until communication is successful + } + OSReport( "SCREENSHOT: Sent ping back.\n" ); + } + else if( (temp >= XFB_BASE && temp < XFB_BASE + XFB_RANGE) || + (temp >= EFB_BASE && temp < EFB_BASE + EFB_RANGE) ) + { //request for screen capture + escapeCount = 0; + g_received_signal = temp; + OSReport( "SCREENSHOT: Grab screenshot request.\n" ); + status = GrabChunk( g_received_signal, bufferXFB, allocator, deallocator ); + } + else if( temp == MINIMIZE_BUFFER_TRUE ) + { //request to use minimal memory (100K), however game pauses + g_minimize_buffer = TRUE; + } + else if( temp == MINIMIZE_BUFFER_FALSE ) + { //request to not use minimal memory and keep game running + g_minimize_buffer = FALSE; + } + } + } + if( !g_minimize_buffer ) + { //Escape loop since were not pausing the game to transfer + return; + } + if( g_minimize_buffer && escapeCount > 150000000 ) + { //The PC screenshot app has died - escape + if( g_data ) { + deallocator( g_data ); + g_data = 0; + } + return; + } + } + +} + + + +static BOOL ConnectToUSB( void ) +{ + if( !g_connected ) + { + if( HIOEnumDevices( HostIOEnumCallback ) ) { + if( g_usb_channel >= 0 ) { + if( HIOInit( g_usb_channel, HostIOCallback ) ) { + u32 temp = 0; + HIOReadMailbox( &temp ); + g_connected = TRUE; + OSReport( "SCREENSHOT: USB connected\n" ); + } + } + } + } + + return( g_connected ); +} + + + +void SCREENSHOTService( void* bufferXFB, + SCREENSHOTAllocator allocator, + SCREENSHOTDeallocator deallocator ) +{ + if( !g_connected ) { + ConnectToUSB(); + } + else if( g_mail_waiting ) { + CheckMail( bufferXFB, allocator, deallocator ); + } + +} diff --git a/game/code/main/gamecube_extras/screenshot.h b/game/code/main/gamecube_extras/screenshot.h new file mode 100644 index 0000000..45d86e0 --- /dev/null +++ b/game/code/main/gamecube_extras/screenshot.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------------* + Project: onetri + File: screenshot.h + + Copyright 1998, 1999, 2000 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + Created 05-25-01 by Steve Rabin + + *---------------------------------------------------------------------------*/ + + +#ifndef __SCREENSHOT_H__ +#define __SCREENSHOT_H__ + +#include "dolphin.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +// access to the memory allocator of choice +typedef void*(*SCREENSHOTAllocator) ( u32 size ); +typedef void (*SCREENSHOTDeallocator) ( void* block ); + + +void SCREENSHOTService( void* bufferXFB, + SCREENSHOTAllocator allocator, + SCREENSHOTDeallocator deallocator ); + + +#ifdef __cplusplus +} +#endif + + +#endif // __SCREENSHOT_H__
\ No newline at end of file diff --git a/game/code/main/gcmain.cpp b/game/code/main/gcmain.cpp new file mode 100644 index 0000000..d3ff15a --- /dev/null +++ b/game/code/main/gcmain.cpp @@ -0,0 +1,221 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: GCmain.cpp +// +// Description: This file contains the main enrty point to the game. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +#include <string.h> +// Foundation Tech +#include <raddebug.hpp> +#include <radobject.hpp> + +//======================================== +// Project Includes +//======================================== +#include <main/game.h> +#include <main/gcplatform.h> +#include <main/singletons.h> +#include <main/commandlineoptions.h> +#include <memory/srrmemory.h> + +//======================================== +// Forward Declarations +//======================================== +static void ProcessCommandLineArguments( int argc, char* argv[] ); + +static void ProcessCommandLineArgumentsFromFile( ); + +//============================================================================= +// Function: main +//============================================================================= +// +// Description: Main entry point. +// +// Parameters: GC argc, number of command line argurments +// argv, array of pointes to these tokens. +// +// Returns: 0 success, non zero error. +// +//============================================================================= +int main( int argc, char* argv[] ) +{ + // + // Pick out and store command line settings. + // + CommandLineOptions::InitDefaults(); + ProcessCommandLineArguments( argc, argv ); + + // + // Have to get FTech setup first so that we can use all the memory services. + // + GCPlatform::InitializeFoundation(); + + + srand (Game::GetRandomSeed ()); + + + // Now disable the default heap + // +#ifndef RAD_RELEASE + tName::SetAllocator (GMA_DEBUG); + + //g_HeapActivityTracker.EnableHeapAllocs (GMA_DEFAULT, false); + //g_HeapActivityTracker.EnableHeapFrees (GMA_DEFAULT, false); +#endif + + HeapMgr()->PushHeap (GMA_PERSISTENT); + + //Process any commandline options from the command.txt file + ProcessCommandLineArgumentsFromFile(); + + + // + // Instantiate all the singletons before doing anything else. + // + CreateSingletons(); + + // + // Construct the platform object. + // + GCPlatform* pPlatform = GCPlatform::CreateInstance(); + rAssert( pPlatform != NULL ); + + // + // Create the game object. + // + Game* pGame = Game::CreateInstance( pPlatform ); + rAssert( pGame != NULL ); + + + // + // Initialize the game. + // + pGame->Initialize(); + + HeapMgr()->PopHeap (GMA_PERSISTENT); + + // + // Run it! Control will not return from here until the game is stopped. + // + pGame->Run(); + + // + // Terminate the game (this frees all resources allocated by the game). + // + pGame->Terminate(); + + // + // Destroy the game object. + // + Game::DestroyInstance(); + + // + // Destroy the game and platform (do it in this order in case the game's + // destructor references the platform. + // + GCPlatform::DestroyInstance(); + + // + // Show some debug output + // +#ifdef RAD_DEBUG + radObject::DumpObjects(); +#endif; + + // + // Dump all the singletons. + // + DestroySingletons(); + + // + // Pass any error codes back to the operating system. + // + return( 0 ); +} + + +//============================================================================= +// Function: ProcessCommandLineArguments +//============================================================================= +// +// Description: Pick out the command line options and stuff them in +// the game database. +// +// Parameters: GC argc, number of command line argurments +// argv, array of pointes to these tokens. +// +// Returns: None. +// +//============================================================================= +void ProcessCommandLineArguments( int argc, char* argv[] ) +{ +#ifndef FINAL + + rDebugPrintf( "*************************************************************\n" ); + rDebugPrintf( "Command Line Args:\n" ); + + // + // Pick out all the command line options and store them in GameDB. + // Also dump them to the output for handy dandy viewing. + // + int i; + for( i = 0; i < argc; ++i ) + { + char* argument = argv[i]; + + rDebugPrintf( "arg%d: %s\n", i, argument ); + + CommandLineOptions::HandleOption( argument ); + } + if( !CommandLineOptions::Get( CLO_ART_STATS ) ) + { + CommandLineOptions::HandleOption( "noheaps" ); + } + + + rDebugPrintf( "*************************************************************\n" ); + +#endif // FINAL +} + + + +void ProcessCommandLineArgumentsFromFile() +{ +#ifndef FINAL + + //Chuck: looking for additional command line args being passed in from a file + //its for QA testing etc. + + IRadFile* pfile =NULL; + + ::radFileOpenSync(&pfile,"command.txt"); + + if (pfile != NULL) + { + + char commandlinestring [256]; + commandlinestring[ 0 ] = '\0'; + + pfile->ReadSync(commandlinestring,255); + + //QA created the command line file and wants to pass additional arguements + + char* argument = strtok(commandlinestring," "); + while (argument != NULL) + { + CommandLineOptions::HandleOption(argument); + argument=strtok(NULL," "); + } + pfile->Release(); + } +#endif //FINAL +} //end of Function diff --git a/game/code/main/gcplatform.cpp b/game/code/main/gcplatform.cpp new file mode 100644 index 0000000..4c30055 --- /dev/null +++ b/game/code/main/gcplatform.cpp @@ -0,0 +1,1758 @@ +//=========================================================================== +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// Component: GCPlatform +// +// Description: Abstracts the differences for setting up and shutting down +// the different platforms. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//=========================================================================== + +//======================================== +// System Includes +//======================================== + +// Standard Lib +#include <stdlib.h> +#include <string.h> +#include <dolphin/vi.h> +#include <dolphin/gx.h> +#include <dolphin/os.h> +#include <dolphin/lg.h> +#include <dolphin/dvd.h> +#include <dolphin.h> +// Pure 3D +#include <p3d/anim/compositedrawable.hpp> +#include <p3d/anim/expression.hpp> +#include <p3d/anim/multicontroller.hpp> +#include <p3d/anim/polyskin.hpp> +#include <p3d/anim/sequencer.hpp> +#include <p3d/anim/skeleton.hpp> +#include <p3d/camera.hpp> +#include <p3d/gameattr.hpp> +#include <p3d/image.hpp> +#include <p3d/imagefont.hpp> +#include <p3d/light.hpp> +#include <p3d/locator.hpp> +#include <p3d/platform.hpp> +#include <p3d/scenegraph/scenegraph.hpp> +#include <p3d/sprite.hpp> +#include <p3d/utility.hpp> +#include <p3d/texture.hpp> +#include <p3d/file.hpp> +#include <p3d/shader.hpp> +#include <p3d/matrixstack.hpp> +#include <p3d/memory.hpp> +#include <p3d/bmp.hpp> +#include <p3d/png.hpp> +#include <p3d/targa.hpp> +#include <p3d/font.hpp> +#include <p3d/texturefont.hpp> +#include <p3d/unicode.hpp> + +// Pure 3D: Loader-specific +#include <render/Loaders/GeometryWrappedLoader.h> +#include <render/Loaders/StaticEntityLoader.h> +#include <render/Loaders/StaticPhysLoader.h> +#include <render/Loaders/TreeDSGLoader.h> +#include <render/Loaders/FenceLoader.h> +#include <render/Loaders/IntersectLoader.h> +#include <render/Loaders/AnimCollLoader.h> +#include <render/Loaders/AnimDSGLoader.h> +#include <render/Loaders/DynaPhysLoader.h> +#include <render/Loaders/InstStatPhysLoader.h> +#include <render/Loaders/InstStatEntityLoader.h> +#include <render/Loaders/WorldSphereLoader.h> +#include <render/Loaders/BillboardWrappedLoader.h> +#include <render/Loaders/instparticlesystemloader.h> +#include <render/Loaders/breakableobjectloader.h> +#include <render/Loaders/lensflareloader.h> +#include <render/Loaders/AnimDynaPhysLoader.h> +#include <p3d/shadow.hpp> +#include <p3d/anim/vertexanimkey.hpp> +#include <p3d/anim/animatedobject.hpp> +#include <p3d/effects/particleloader.hpp> +#include <p3d/effects/opticloader.hpp> +// Foundation Tech +#include <raddebug.hpp> +#include <raddebugcommunication.hpp> +#include <raddebugwatch.hpp> +#include <radfile.hpp> +#include <radmemorymonitor.hpp> +#include <radplatform.hpp> +#include <radthread.hpp> +#include <radtime.hpp> +#include <radmovie2.hpp> + +//This is so we can get the name of the file that's failing. +#include <../src/radfile/common/requests.hpp> + +// sim - for InstallSimLoaders +#include <simcommon/simutility.hpp> + +// Stateprops +#include <stateprop/statepropdata.hpp> + +// To turn off movies during an error. +#include <presentation/fmvplayer/fmvplayer.h> +#include <presentation/presentation.h> + +//======================================== +// Project Includes +//======================================== +#include <input/inputmanager.h> +#include <main/gcplatform.h> +#include <main/game.h> +#include <main/commandlineoptions.h> +#include <memory/srrmemory.h> +#include <render/RenderManager/RenderManager.h> +#include <render/Loaders/AllWrappers.h> + +#include <loading/locatorloader.h> +#include <loading/cameradataloader.h> +#include <loading/roadloader.h> +#include <loading/pathloader.h> +#include <loading/intersectionloader.h> +#include <loading/roaddatasegmentloader.h> +#include <atc/atcloader.h> + +#include <main/gamecube_extras/gcmanager.h> +#include <debug/debuginfo.h> + +#include <radload/radload.hpp> + +#include <main/errorsgc.h> +#include <presentation/gui/guitextbible.h> + +#define GC_SECTION "GC_SECTION" + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + +// Static pointer to instance of singleton. +GCPlatform* GCPlatform::spInstance = NULL; + +//Add baked in loadable headers here. +static unsigned char gLicenseP3D[] = +#include <main/gamecube_extras/license.h> + +//The Adlib font. <sigh> +unsigned char gFont[] = +#include <font/defaultfont.h> + +//GX Warning Levels. +//GX_WARN_NONE +//GX_WARN_SEVERE +//GX_WARN_MEDIUM +//GX_WARN_ALL + +const GXWarningLevel gxWarningLevel = GX_WARN_NONE; + +void LoadMemP3DFile( unsigned char* buffer, unsigned int size, tEntityStore* store ) +{ + tFileMem* file = new tFileMem(buffer,size); + file->AddRef(); + file->SetFilename("memfile.p3d"); + p3d::loadManager->GetP3DHandler()->Load( file, p3d::inventory ); + file->Release(); +} + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================== +// GCPlatform::CreateInstance +//============================================================================== +// +// Description: Creates the GCPlatform. +// +// Parameters: None. +// +// Return: Pointer to the GCPlatform. +// +// Constraints: This is a singleton so only one instance is allowed. +// +//============================================================================== +GCPlatform* GCPlatform::CreateInstance() +{ +MEMTRACK_PUSH_GROUP( "GCPlatform" ); + rAssert( spInstance == NULL ); + + spInstance = new(GMA_PERSISTENT) GCPlatform; + rAssert( spInstance ); +MEMTRACK_POP_GROUP( "GCPlatform" ); + + return spInstance; +} + +//============================================================================== +// GCPlatform::GetInstance +//============================================================================== +// +// Description: - Access point for the GCPlatform singleton. +// +// Parameters: None. +// +// Return: Pointer to the GCPlatform. +// +// Constraints: This is a singleton so only one instance is allowed. +// +//============================================================================== +GCPlatform* GCPlatform::GetInstance() +{ + rAssert( spInstance != NULL ); + + return spInstance; +} + + +//============================================================================== +// GCPlatform::DestroyInstance +//============================================================================== +// +// Description: Destroy the GCPlatform. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void GCPlatform::DestroyInstance() +{ + rAssert( spInstance != NULL ); + + delete( GMA_PERSISTENT, spInstance ); + spInstance = NULL; +} + + + +//============================================================================== +// GCPlatform::InitializeFoundation +//============================================================================== +// Description: Get FTech ready to go. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be initialized in a particular order. +// Consult their documentation before changing. Also, we need +// to only init the quick things to allow time for drawing the +// first license screens. +// +//============================================================================== +void GCPlatform::InitializeFoundation() +{ + // + // Initialize the memory heaps + // + GCPlatform::InitializeMemory(); + +#ifndef FINAL + // + // Register an out-of-memory display handler in case something goes bad + // while allocating the heaps + // + ::radMemorySetOutOfMemoryCallback( PrintOutOfMemoryMessage, NULL ); +#endif + +#ifndef RAD_RELEASE + // + // Initialize memory monitor by JamesCo. TM. + // + if( CommandLineOptions::Get( CLO_MEMORY_MONITOR ) ) + { + const int KB = 1024; + ::radMemoryMonitorInitialize( 2048 * KB, GMA_DEBUG ); + } +#endif + + // Setup the memory heaps + // + HeapMgr()->PrepareHeapsStartup (); + + // Seed the heap stack + // + HeapMgr()->PushHeap (GMA_PERSISTENT); + + // + // Initilalize the platform system + // + ::radPlatformInitialize(); + + // + // Initialize the timer system + // + ::radTimeInitialize(); + +#ifndef RAD_RELEASE + // + // Initialize the debug communication system. + // + ::radDbgComTargetInitialize( HostIO, + radDbgComDefaultPort, // Default + NULL, // Default + GMA_DEBUG ); + + // + // Initialize the Watcher. + // + ::radDbgWatchInitialize( "SRR2", + 16384 * 16, // Default + GMA_DEBUG ); +#endif + + // + // Initialize the file system. + // + ::radFileInitialize( 50, // Default + 32, // Default + GMA_PERSISTENT ); + + ::radLoadInitialize(); + + ::radDriveMount(0, GMA_PERSISTENT); + + // + // Initialize the new movie player + // + ::radMovieInitialize2( GMA_PERSISTENT ); + +} + + +//============================================================================== +// GCPlatform::InitializeMemory +//============================================================================== +// +// Description: +// +// Parameters: +// +// Return: +// +//============================================================================== +void GCPlatform::InitializeMemory() +{ + // + // Only do this once! + // + if( gMemorySystemInitialized == true ) + { + return; + } + + gMemorySystemInitialized = true; + + // + // Initialize thread system. + // + ::radThreadInitialize(); + + // + // Initialize memory system. + // + ::radMemoryInitialize( VMM_MAIN_RAM, VMM_ARAM ); +} + +//============================================================================== +// GCPlatform::InitializePlatform +//============================================================================== +// Description: Get the GC ready to go. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================= +void GCPlatform::InitializePlatform() +{ + HeapMgr()->PushHeap (GMA_PERSISTENT); + + // + // Get some rendering action setup. + // + InitializePure3D(); + + // + // Add anything here that needs to be before the drive is opened. + // + + //This is slow. + InitializeFoundationDrive(); + + // + // Initialize the controller. + // + GetInputManager()->Init(); + +#ifndef PAL + // no progressive scan on PAL builds, only on NTSC + // + GCManager::GetInstance()->DoProgressiveScanTest(); +#endif // !PAL + + //TRC: The license screen needs to be + DisplaySplashScreen( License, NULL ); + + + //Set the serial cable debug verbosity level + GXSetVerifyLevel( gxWarningLevel ); + + HeapMgr()->PopHeap (GMA_PERSISTENT); +} + +void GCPlatform::OnControllerError(const char *msg) +{ + DisplaySplashScreen( Error, msg, 0.7f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + mErrorState = CTL_ERROR; + mPauseForError = true; + +} + + +//============================================================================== +// GCPlatform::ShutdownPlatform +//============================================================================== +// Description: Shut down the GC. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void GCPlatform::ShutdownPlatform() +{ + ShutdownPure3D(); + ShutdownFoundation(); + + //Shutdown the steering wheel system. + ::radControllerTerminate(); +} + +//============================================================================= +// GCPlatform::ResetMachine +//============================================================================= +// Description: resets the machine +// +// Parameters: none +// +// Return: void +// +//============================================================================= +void GCPlatform::ResetMachine() +{ + LaunchDashboard(); +} + +//============================================================================= +// GCPlatform::LaunchDashboard +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void GCPlatform::LaunchDashboard() +{ + GCManager::GetInstance()->Reset(); + GCManager::GetInstance()->PerformReset( false ); +} + + +//============================================================================= +// GCPlatform::DisplaySplashScreen +//============================================================================= +// Description: Comment +// +// Parameters: ( SplashScreen screenID, +// const char* overlayText = NULL, +// float fontScale = 1.0f, +// float textPosX = 0.0f, +// float textPosY = 0.0f, +// tColour textColour, +// int fadeFrames = 3 ) +// +// Return: void +// +//============================================================================= +void GCPlatform::DisplaySplashScreen( SplashScreen screenID, + const char* overlayText, + float fontScale, + float textPosX, + float textPosY, + tColour textColour, + int fadeFrames ) +{ + //Just in case this was called during a draw! + GXWaitDrawDone(); + + HeapMgr()->PushHeap( GMA_TEMP ); + + p3d::inventory->PushSection(); + p3d::inventory->AddSection( GC_SECTION ); + p3d::inventory->SelectSection( GC_SECTION ); + + unsigned char* screen = NULL; + const char* texname = NULL; + int size = 0; + tTexture* texture = NULL; + + P3D_UNICODE unicodeText[256]; + + + //Create shader + tShader* splashShader = new tShader("simple"); + splashShader->SetInt(PDDI_SP_FILTER, PDDI_FILTER_NONE); + splashShader->AddRef(); + + if ( screenID == FadeToBlack ) + { + splashShader->SetInt(PDDI_SP_BLENDMODE,PDDI_BLEND_ALPHA); + splashShader->SetInt(PDDI_SP_FILTER,PDDI_FILTER_BILINEAR); + } + else if ( screenID == Error ) + { + splashShader->SetColour(PDDI_SP_DIFFUSE, tColour(0, 0, 0)); + splashShader->SetColour(PDDI_SP_AMBIENT, tColour(0, 0, 0)); + splashShader->SetColour(PDDI_SP_SPECULAR, tColour(0, 0, 0)); + splashShader->SetColour(PDDI_SP_EMISSIVE, tColour(0, 0, 0)); + } + else + { + //This is so we can handle more baked in screens if we want + switch (screenID) + { + case License: + { + screen = gLicenseP3D; + texname = LICENSE_NAME; + size = LICENSE_SIZE; + } + break; + default: + rAssert( false); + } + + // Load the in screen texture file from memory + p3d::load(screen, size, HeapMgr()->GetCurrentHeap()); + + // Get the texture to draw + texture = p3d::find<tTexture>(texname); + rAssert( texture ); + + // Put it in our shader + splashShader->SetTexture(PDDI_SP_BASETEX, texture); + } + + // Save the current Projection mode so I can restore it later + pddiProjectionMode pm = p3d::pddi->GetProjectionMode(); + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_DEVICE); + + pddiCullMode cm = p3d::pddi->GetCullMode(); + p3d::pddi->SetCullMode(PDDI_CULL_NONE); + + //CREATE THE FONT + tTextureFont* thisFont = NULL; + + if ( overlayText != NULL ) + { + // Convert memory buffer into a texturefont. + // + //p3d::load(gFont, DEFAULTFONT_SIZE, HeapMgr()->GetCurrentHeap() ); + LoadMemP3DFile( gFont, DEFAULTFONT_SIZE, p3d::inventory ); + + thisFont = p3d::find<tTextureFont>("adlibn_20"); + rAssert( thisFont ); + + thisFont->AddRef(); + tShader* fontShader = thisFont->GetShader(); + fontShader->SetInt(PDDI_SP_BLENDMODE,PDDI_BLEND_ALPHA); + fontShader->SetInt(PDDI_SP_FILTER,PDDI_FILTER_BILINEAR); + + p3d::AsciiToUnicode( overlayText, unicodeText, 256 ); + + // Make the missing letter into somthing I can see + // + thisFont->SetMissingLetter(p3d::ConvertCharToUnicode('j')); + } + + // Fade up the screen + int a = 0; + do + { + if ( screenID != FadeToBlack ) + { + p3d::pddi->SetColourWrite(true, true, true, true); + p3d::pddi->SetClearColour( pddiColour(0,0,0) ); + } + + p3d::pddi->BeginFrame(); + + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_DEVICE); + + GXSetScissorBoxOffset(0, 0); +#ifdef PAL + GXSetScissor(0, 0, 640, 528); +#else + GXSetScissor(0, 0, 640, 480); +#endif + + if ( screenID != FadeToBlack ) + { + p3d::pddi->Clear(PDDI_BUFFER_ALL); + } + + int bright = 255; + if (a < fadeFrames) bright = (a * 255) / fadeFrames / 10; + if ( bright > 255 ) bright = 255; + + tColour c; + if ( screenID == FadeToBlack) + { + c.Set(0, 0, 0, bright); + } + else + { + c.Set(bright, bright, bright, 255); + } + + if ( screenID != Error ) + { + p3d::pddi->PushMatrix(PDDI_MATRIX_MODELVIEW); + p3d::pddi->IdentityMatrix(PDDI_MATRIX_MODELVIEW); + + p3d::stack->Push(); + p3d::stack->LoadIdentity(); + + pddiPrimStream* stream; + + if ( screenID == FadeToBlack ) + { + stream = p3d::pddi->BeginPrims(splashShader->GetShader(), PDDI_PRIM_TRISTRIP, PDDI_V_C, 4); + } + else + { + stream = p3d::pddi->BeginPrims(splashShader->GetShader(), PDDI_PRIM_TRISTRIP, PDDI_V_CT, 4); + } + +#ifdef PAL + stream->Colour(c); stream->UV(0.0F, 0.0F); stream->Coord( 0.0F, 528.0F, 2.01F); + stream->Colour(c); stream->UV(1.0F, 0.0F); stream->Coord(640.0F, 528.0F, 2.01F); +#else + stream->Colour(c); stream->UV(0.0F, 0.0F); stream->Coord( 0.0F, 480.0F, 2.01F); + stream->Colour(c); stream->UV(1.0F, 0.0F); stream->Coord(640.0F, 480.0F, 2.01F); +#endif + stream->Colour(c); stream->UV(0.0F, 1.0F); stream->Coord( 0.0F, 0.0F, 2.01F); + stream->Colour(c); stream->UV(1.0F, 1.0F); stream->Coord(640.0F, 0.0F, 2.01F); + + p3d::pddi->EndPrims(stream); + + p3d::stack->Pop(); + + p3d::pddi->PopMatrix(PDDI_MATRIX_MODELVIEW); + } + + if (overlayText != NULL) + { + tColour colour = textColour; + colour.SetAlpha( bright ); + + thisFont->SetColour( colour ); + + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_ORTHOGRAPHIC); + + p3d::stack->Push(); + p3d::stack->LoadIdentity(); + + p3d::stack->Translate( textPosX, textPosY, 1.5f); + float scaleSize = 1.0f / 480.0f; //This is likely good for 528 also. + p3d::stack->Scale(scaleSize * fontScale, scaleSize* fontScale , 1.0f); + + if ( textPosX != 0.0f || textPosY != 0.0f ) + { + thisFont->DisplayText( unicodeText ); + } + else + { + thisFont->DisplayText( unicodeText, 3 ); + } + + p3d::stack->Pop(); + } + + p3d::pddi->EndFrame(); + p3d::context->SwapBuffers(); + + ++a; + + if (screenID == FadeToBlack && bright >= 255) + { + //This is a sucky hack... + break; + } + + } while (a <= fadeFrames); + + // [ps]: flush out this screen now. + if ( screenID == FadeToBlack ) + { + GXSetScissorBoxOffset(0, 0); +#ifdef PAL + GXSetScissor(0, 0, 640, 528); +#else + GXSetScissor(0, 0, 640, 480); +#endif + + p3d::pddi->Clear(PDDI_BUFFER_ALL); + } + + // Remove the texture from the shader + splashShader->SetTexture(PDDI_SP_BASETEX, NULL); + splashShader->Release(); + + // remove the texture from the inventory + if ( texture ) + { + p3d::inventory->Remove(texture); + } + + p3d::pddi->SetCullMode(cm); + p3d::pddi->SetProjectionMode(pm); + + if ( thisFont ) + { + thisFont->Release(); + p3d::inventory->Remove(thisFont); + } + + p3d::inventory->RemoveSectionElements(GC_SECTION); + p3d::inventory->DeleteSection(GC_SECTION); + p3d::inventory->PopSection(); + + HeapMgr()->PopHeap( GMA_TEMP ); +} + +//============================================================================= +// GCPlatform::DisplaySplashScreen +//============================================================================= +// Description: Comment +// +// Parameters: ( const char* overlayText = NULL, +// float fontScale = 1.0f, +// float textPosX = 0.0f, +// float textPosY = 0.0f, +// tColour textColour, +// int fadeFrames = 3 ) +// +// Return: void +// +//============================================================================= +void GCPlatform::DisplaySplashScreen( const char* textureName, + const char* overlayText, + float fontScale, + float textPosX, + float textPosY, + tColour textColour, + int fadeFrames ) +{ + //Just in case this was called during a draw! + GXWaitDrawDone(); + + HeapMgr()->PushHeap( GMA_TEMP ); + + p3d::inventory->PushSection(); + p3d::inventory->AddSection( GC_SECTION ); + p3d::inventory->SelectSection( GC_SECTION ); + + tTexture* texture = NULL; + + P3D_UNICODE unicodeText[256]; + + rAssertMsg( textureName, "There must be a texture, use the other one with Error otherwise." ); + + //Create shader + tShader* splashShader = new tShader("simple"); + splashShader->SetInt(PDDI_SP_FILTER, PDDI_FILTER_NONE); + splashShader->AddRef(); + + + // Get the texture to draw + texture = p3d::find<tTexture>(textureName); + rAssert( texture ); + + // Put it in our shader + splashShader->SetTexture(PDDI_SP_BASETEX, texture); + + + // Save the current Projection mode so I can restore it later + pddiProjectionMode pm = p3d::pddi->GetProjectionMode(); + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_DEVICE); + + pddiCullMode cm = p3d::pddi->GetCullMode(); + p3d::pddi->SetCullMode(PDDI_CULL_NONE); + + //CREATE THE FONT + tTextureFont* thisFont = NULL; + + if ( overlayText != NULL ) + { + // Convert memory buffer into a texturefont. + // + //p3d::load(gFont, DEFAULTFONT_SIZE, HeapMgr()->GetCurrentHeap()); + LoadMemP3DFile( gFont, DEFAULTFONT_SIZE, p3d::inventory ); + + thisFont = p3d::find<tTextureFont>("adlibn_20"); + rAssert( thisFont ); + + thisFont->AddRef(); + tShader* fontShader = thisFont->GetShader(); + fontShader->SetInt(PDDI_SP_BLENDMODE,PDDI_BLEND_ALPHA); + fontShader->SetInt(PDDI_SP_FILTER,PDDI_FILTER_BILINEAR); + + + p3d::AsciiToUnicode( overlayText, unicodeText, 256 ); + + // Make the missing letter into somthing I can see + // + thisFont->SetMissingLetter(p3d::ConvertCharToUnicode('j')); + } + + // Fade up the screen + int a = 0; + + do + { + p3d::pddi->SetColourWrite(true, true, true, true); + p3d::pddi->SetClearColour( pddiColour(0,0,0) ); + p3d::pddi->BeginFrame(); + p3d::pddi->Clear(PDDI_BUFFER_ALL); + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_DEVICE); + + GXSetScissorBoxOffset(0, 0); +#ifdef PAL + GXSetScissor(0, 0, 640, 528); +#else + GXSetScissor(0, 0, 640, 480); +#endif + + p3d::pddi->PushMatrix(PDDI_MATRIX_MODELVIEW); + p3d::pddi->IdentityMatrix(PDDI_MATRIX_MODELVIEW); + + int bright = 255; + if (a < fadeFrames) bright = (a * 255) / fadeFrames; + if ( bright > 255 ) bright = 255; + tColour c(bright, bright, bright, 255); + + p3d::stack->Push(); + p3d::stack->LoadIdentity(); + + pddiPrimStream* stream = p3d::pddi->BeginPrims(splashShader->GetShader(), PDDI_PRIM_TRISTRIP, PDDI_V_CT, 4); + +#ifdef PAL + stream->Colour(c); stream->UV(0.0F, 0.0F); stream->Coord( 0.0F, 528.0F, 2.01F); + stream->Colour(c); stream->UV(1.0F, 0.0F); stream->Coord(640.0F, 528.0F, 2.01F); +#else + stream->Colour(c); stream->UV(0.0F, 0.0F); stream->Coord( 0.0F, 480.0F, 2.01F); + stream->Colour(c); stream->UV(1.0F, 0.0F); stream->Coord(640.0F, 480.0F, 2.01F); +#endif + stream->Colour(c); stream->UV(0.0F, 1.0F); stream->Coord( 0.0F, 0.0F, 2.01F); + stream->Colour(c); stream->UV(1.0F, 1.0F); stream->Coord(640.0F, 0.0F, 2.01F); + + p3d::pddi->EndPrims(stream); + + p3d::stack->Pop(); + + p3d::pddi->PopMatrix(PDDI_MATRIX_MODELVIEW); + + if (overlayText != NULL) + { + tColour colour = textColour; + colour.SetAlpha( bright ); + + thisFont->SetColour( colour ); + + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_ORTHOGRAPHIC); + p3d::stack->Push(); + p3d::stack->LoadIdentity(); + + p3d::stack->Translate( textPosX, textPosY, 1.5f); + float scaleSize = 1.0f / 480.0f; //This is likely good for 528 also. + p3d::stack->Scale(scaleSize * fontScale, scaleSize* fontScale , 1.0f); + + thisFont->DisplayText( unicodeText ); + + p3d::stack->Pop(); + } + + p3d::pddi->EndFrame(); + p3d::context->SwapBuffers(); + + ++a; + + } while (a <= fadeFrames); + + // Remove the texture from the shader + splashShader->SetTexture(PDDI_SP_BASETEX, NULL); + splashShader->Release(); + + p3d::pddi->SetCullMode(cm); + p3d::pddi->SetProjectionMode(pm); + + if ( overlayText != NULL ) + { + thisFont->Release(); + p3d::inventory->Remove(thisFont); + } + + p3d::inventory->RemoveSectionElements(GC_SECTION); + p3d::inventory->DeleteSection(GC_SECTION); + p3d::inventory->PopSection(); + + HeapMgr()->PopHeap( GMA_TEMP ); +} + +//============================================================================= +// GCPlatform::DisplayYesNo +//============================================================================= +// Description: Comment +// +// Parameters: ( float fontScale = 1.0f, +// float yesPosX = 0.0f, +// float yesPosY = 0.0f, +// float noPosX = 0.0f, +// float noPosY = 0.0f, +// int fadeFrames = 3 ) +// +// Return: bool +// +//============================================================================= +bool GCPlatform::DisplayYesNo( float fontScale, + float yesPosX, + float yesPosY, + float noPosX, + float noPosY, + int fadeFrames ) +{ + //Just in case this was called during a draw! + GXWaitDrawDone(); + + HeapMgr()->PushHeap( GMA_TEMP ); + + p3d::inventory->PushSection(); + p3d::inventory->AddSection( GC_SECTION ); + p3d::inventory->SelectSection( GC_SECTION ); + + // Save the current Projection mode so I can restore it later + pddiProjectionMode pm = p3d::pddi->GetProjectionMode(); + + pddiCullMode cm = p3d::pddi->GetCullMode(); + p3d::pddi->SetCullMode(PDDI_CULL_NONE); + + //CREATE THE FONT + tTextureFont* thisFont = NULL; + + // Convert memory buffer into a texturefont. + // + //p3d::load(gFont, DEFAULTFONT_SIZE, HeapMgr()->GetCurrentHeap()); + LoadMemP3DFile( gFont, DEFAULTFONT_SIZE, p3d::inventory ); + + thisFont = p3d::find<tTextureFont>("adlibn_20"); + rAssert( thisFont ); + + thisFont->AddRef(); + tShader* fontShader = thisFont->GetShader(); + fontShader->SetInt(PDDI_SP_BLENDMODE,PDDI_BLEND_ALPHA); + fontShader->SetInt(PDDI_SP_FILTER,PDDI_FILTER_BILINEAR); + + //This is the text! + const char* yes = "Yes"; + const char* no = "No"; + + P3D_UNICODE unicodeYes[256]; + P3D_UNICODE unicodeNo[256]; + + p3d::AsciiToUnicode( yes, unicodeYes, 256 ); + p3d::AsciiToUnicode( no, unicodeNo, 256 ); + + // Make the missing letter into somthing I can see + // + thisFont->SetMissingLetter(p3d::ConvertCharToUnicode('j')); + + unsigned int inputCount = 0; + PADStatus controllers[PAD_MAX_CONTROLLERS]; + + for ( inputCount = 0; inputCount < PAD_MAX_CONTROLLERS; ++inputCount ) + { + controllers[ inputCount ].button = 0; + } + + LGPosition lgStatus[ SI_MAX_CHAN ]; + memset( lgStatus, 0, sizeof( LGPosition )*SI_MAX_CHAN ); + + bool yesSelected = true; + bool buttonAPressed[ PAD_MAX_CONTROLLERS ]; + bool buttonAReleased = false; + + // Fade up the screen + int a = 0; + tColour colour; + + unsigned int start = OSTicksToMilliseconds( OSGetTime() ); + + bool buttonDown[ PAD_MAX_CONTROLLERS ]; + + unsigned int i; + + for ( i = 0; i < PAD_MAX_CONTROLLERS; ++i ) + { + buttonDown[ i ] = false; + buttonAPressed[ i ] = false; + } + + do + { + unsigned int end = OSTicksToMilliseconds( OSGetTime() ); + unsigned int milliseconds = end - start; + start = end; + + p3d::pddi->BeginFrame(); + + GXSetScissorBoxOffset(0, 0); +#ifdef PAL + GXSetScissor(0, 0, 640, 528); +#else + GXSetScissor(0, 0, 640, 480); +#endif + int bright = 255; + if (a < fadeFrames) bright = (a * 255) / fadeFrames; + if ( bright > 255 ) bright = 255; + tColour c(bright, bright, bright, 255); + + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_ORTHOGRAPHIC); + + float scaleSize = 1.0f / 480.0f; //This is likely good for 528 also. + + //Draw Yes + p3d::stack->Push(); + p3d::stack->LoadIdentity(); + + p3d::stack->Translate( yesPosX, yesPosY, 1.5f); + p3d::stack->Scale(scaleSize * fontScale, scaleSize* fontScale , 1.0f); + + if ( yesSelected ) + { + colour = tColour(255, 255, 255, bright); + } + else + { + colour = tColour(100, 100, 100, bright); + } + + thisFont->SetColour( colour ); + thisFont->DisplayText( unicodeYes ); + + p3d::stack->Pop(); + + //Draw No + p3d::stack->Push(); + p3d::stack->LoadIdentity(); + + p3d::stack->Translate( noPosX, noPosY, 1.5f); + p3d::stack->Scale(scaleSize * fontScale, scaleSize* fontScale , 1.0f); + + if ( !yesSelected ) + { + colour = tColour(255, 255, 255, bright); + } + else + { + colour = tColour(100, 100, 100, bright); + } + + thisFont->SetColour( colour ); + thisFont->DisplayText( unicodeNo ); + + p3d::stack->Pop(); + + p3d::pddi->EndFrame(); + p3d::context->SwapBuffers(); + + if ( bright < 255 ) + { + ++a; + } + + ::radControllerSystemService(); + ::radThreadSleep( 32 ); + + PADRead(controllers); + LGRead( lgStatus ); + + rAssert( PAD_MAX_CONTROLLERS == SI_MAX_CHAN ); + for ( i = 0; i < PAD_MAX_CONTROLLERS; ++i ) + { + bool start = controllers[ i ].err == PAD_ERR_NONE && + ( controllers[ i ].button & PAD_BUTTON_MENU ); + + start = start || + (lgStatus[ i ].err == LG_ERR_NONE && (lgStatus[ i ].button & LG_BUTTON_START )); + + bool x = controllers[ i ].err == PAD_ERR_NONE && + ( controllers[ i ].button & PAD_BUTTON_A ); + + x = x || + (lgStatus[ i ].err == LG_ERR_NONE && (lgStatus[ i ].button & LG_BUTTON_A )); + + if ( x || start ) + { + buttonAPressed[ i ] = true; + } + else if ( buttonAPressed[ i ] ) + { + buttonAReleased = true; + break; + } + + bool dLeft = ( controllers[ i ].err == PAD_ERR_NONE && + ( ( controllers[ i ].button & PAD_BUTTON_LEFT ) || + ( controllers[ i ].stickX < -50 ) ) ); + bool dRight = ( controllers[ i ].err == PAD_ERR_NONE && + ( ( controllers[ i ].button & PAD_BUTTON_RIGHT ) || + ( controllers[ i ].stickX > 50 ) ) ); + + dLeft = dLeft || + (lgStatus[ i ].err == LG_ERR_NONE && ((lgStatus[ i ].button & LG_BUTTON_LEFT) || (lgStatus[ i ].wheel < -50 ))); + + dRight = dRight || + (lgStatus[ i ].err == LG_ERR_NONE && ((lgStatus[ i ].button & LG_BUTTON_RIGHT) || (lgStatus[ i ].wheel > 50 ))); + + if ( ( dLeft || dRight ) && !buttonDown[ i ] ) + { + yesSelected = !yesSelected; + buttonDown[ i ] = true; + } + else if ( !dLeft && !dRight ) + { + buttonDown[ i ] = false; + } + } + + GXWaitDrawDone(); + } while ( !buttonAReleased ); + + p3d::pddi->SetCullMode(cm); + p3d::pddi->SetProjectionMode(pm); + + thisFont->Release(); + + p3d::inventory->Remove(thisFont); + + p3d::inventory->RemoveSectionElements(GC_SECTION); + p3d::inventory->DeleteSection(GC_SECTION); + p3d::inventory->PopSection(); + + HeapMgr()->PopHeap( GMA_TEMP ); + + return yesSelected; +} + +//============================================================================= +// GCPlatform::OnDriveError +//============================================================================= +// Description: Comment +// +// Parameters: ( radFileError error, const char* pDriveName, void* pUserData ) +// +// Return: bool +// +//============================================================================= +bool GCPlatform::OnDriveError( radFileError error, const char* pDriveName, void* pUserData ) +{ + GCManager::GetInstance()->OnTimerDone( 16, NULL ); + + // Halt rumbling + GCManager::GetInstance()->StopRumble(); + + bool inFrame = p3d::context->InFrame(); + + const int NUM_RADFILE_ERRORS = 13; + unsigned int errorIndex = error; + +#ifdef PAL + switch( CGuiTextBible::GetCurrentLanguage() ) + { + case Scrooby::XL_FRENCH: + { + errorIndex += 1 * NUM_RADFILE_ERRORS; + + break; + } + case Scrooby::XL_GERMAN: + { + errorIndex += 2 * NUM_RADFILE_ERRORS; + + break; + } + case Scrooby::XL_SPANISH: + { + errorIndex += 3 * NUM_RADFILE_ERRORS; + + break; + } + default: + { + break; + } + } +#endif // PAL + + rAssert( errorIndex < sizeof( ERROR_STRINGS ) / sizeof( ERROR_STRINGS[ 0 ] ) ); + + switch ( error ) + { + case Success: + { + if ( mErrorState != NONE ) + { + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( FadeToBlack ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = NONE; + mPauseForError = false; + } + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->UnPause( ); + } + else + { + GetSoundManager()->ResumeAfterMovie(); + } + return true; + break; + } + case FileNotFound: + { + if ( CommandLineOptions::Get( CLO_FILE_NOT_FOUND ) ) + { + rAssert( pUserData != NULL ); + + radFileRequest* request = static_cast<radFileRequest*>( pUserData ); + const char* fileName = request->GetFilename(); + + //Get rid of the slashes. + unsigned int i; + unsigned int lastIndex = 0; + for ( i = 0; i < strlen( fileName ); ++i ) + { + if ( fileName[ i ] == '\\' ) + { + lastIndex = i; + } + } + + unsigned int adjustedIndex = lastIndex == 0 ? lastIndex : lastIndex + 1; + + char adjustedName[32]; + strncpy( adjustedName, &fileName[adjustedIndex], ( strlen( fileName ) - lastIndex ) ); + adjustedName[ strlen( fileName ) - lastIndex ] = '\0'; + + char errorString[256]; + sprintf( errorString, "%s:\n%s", ERROR_STRINGS[errorIndex], adjustedName ); + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( Error, errorString, 1.0f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = P_ERROR; + mPauseForError = true; + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->Pause( ); + } + else + { + GetSoundManager()->StopForMovie(); + } + return true; + } + else + { + error = NoMedia; + //Fall through. + } + } + case ShellOpen: + case WrongMedia: + case NoMedia: + case MediaCorrupt: + case HardwareFailure: + { + //This could be the wrong disc. + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( Error, ERROR_STRINGS[errorIndex], 1.0f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = P_ERROR; + mPauseForError = true; + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->Pause( ); + } + else + { + GetSoundManager()->StopForMovie(); + } + return true; + } + default: + { + //Others are not supported. + rAssert( false ); + } + } + + return false; +} + + + +//****************************************************************************** +// +// Protected Member Functions +// +//****************************************************************************** + + +//============================================================================== +// GCPlatform::InitializeFoundationDrive +//============================================================================== +// Description: Get FTech ready to go. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be initialized in a particular order. +// Consult their documentation before changing. This is all the +// slower elements of FTech +// +//============================================================================== +void GCPlatform::InitializeFoundationDrive() +{ + // + // Get the DVD drive and hold it open for the life of the game. + // This is a costly operation so we only want to do it once. + // + + ::radDriveOpen( &mpIRadDrive, + "DVD:", + NormalPriority, // Default + GMA_PERSISTENT ); + + rAssert( mpIRadDrive != NULL ); + + mpIRadDrive->RegisterErrorHandler( this, NULL ); + + // + // Set the read-write granulatity to prevent operations from + // being partitioned. + // +// const int GRANULARITY = 20 * 1024 * 1024; +// mpIRadDrive->SetReadWriteGranularity( GRANULARITY ); + + DVDSetAutoFatalMessaging( true ); +} + + +//============================================================================== +// GCPlatform::ShutdownFoundation +//============================================================================== +// Description: Shut down Foundation Tech. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be terminated in the reverse order that +// they were initialized in. +// +//============================================================================== +void GCPlatform::ShutdownFoundation() +{ + // + // Release the drive we've held open since the begining. + // + mpIRadDrive->Release(); + mpIRadDrive = NULL; + + // + // Shutdown the systems in the reverse order. + // + ::radDriveUnmount(); + ::radFileTerminate(); + +#ifndef RAD_RELEASE + ::radDbgWatchTerminate(); + if( CommandLineOptions::Get( CLO_MEMORY_MONITOR ) ) + { + ::radMemoryMonitorTerminate(); + } + ::radDbgComTargetTerminate(); +#endif + + ::radTimeTerminate(); + ::radPlatformTerminate(); + ::radMemoryTerminate(); + ::radThreadTerminate(); +} + + +//============================================================================== +// GCPlatform::InitializePure3D +//============================================================================== +// Description: Get Pure3D ready to go. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void GCPlatform::InitializePure3D() +{ +MEMTRACK_PUSH_GROUP( "GCPlatform" ); + // + // Initialise Pure3D platform object. + // This call differs between different platforms. The Win32 version, + // for example requires the application instance to be passed in. + // + mpPlatform = tPlatform::Create(); + rAssert( mpPlatform != NULL ); + + // + // Initialiase the Pure3D context object. + // We have to create on of these for every window, and for every PDDI + // instance we use for rendering. Since almost every application only + // uses one window and PDDI library at a time, we one need to create one + // context. + // + + //tContextInitData init; We're storing this as a member var called mInitData. + + // + // These values only take effect in fullscreen mode. In windowed mode, the + // dimensions of the window define the rendering area. We'll define them + // anyway for completeness sake. + // + mInitData.xsize = WindowSizeX; + mInitData.ysize = WindowSizeY; + + // + // Depth of the rendering buffer. Again, this value only works in + // fullscreen mode. In window mode, the depth of the desktop is used. + // This value should be either 16 or 32. Depths of 4, 8, and 24 are not + // supported by most 3D hardware, and not by Pure3D. + // +// mInitData.bpp = WindowBPP; + mInitData.bufferMask = PDDI_BUFFER_COLOUR | PDDI_BUFFER_DEPTH; + // + // Rendering to NTSC or PAL. + // +#ifdef PAL + mInitData.pal = true; +#else + mInitData.pal = false; + + //Progressive only available in NTSC +// mInitData.progressive = OSGetProgressiveMode() && VIGetDTVStatus(); + mInitData.progressive = false; +#endif + + //TODO: Investigate VSync + mInitData.lockToVsync = false; + // + // Create the context. + // + mpContext = mpPlatform->CreateContext( &mInitData ); + rAssert( mpContext != NULL ); + + VISetBlack(FALSE); + VIFlush(); + VIWaitForRetrace(); + + // + // Assign this context to the platform. + // + mpPlatform->SetActiveContext( mpContext ); + p3d::pddi->EnableZBuffer( true ); + + // + // This call installs chunk handlers for all the primary chunk types that + // Pure3D supports. This includes textures, materials, geometries, and the + // like. + // +// p3d::InstallDefaultLoaders(); + P3DASSERT(p3d::context); + tP3DFileHandler* p3d = new(GMA_GC_VMM) tP3DFileHandler; +// p3d::loadManager->AddHandler(p3d); + p3d::context->GetLoadManager()->AddHandler(p3d, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_GC_VMM) tPNGHandler, "png"); + + if( CommandLineOptions::Get( CLO_FE_UNJOINED ) ) + { + p3d::context->GetLoadManager()->AddHandler(new(GMA_GC_VMM) tBMPHandler, "bmp"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_GC_VMM) tTargaHandler, "tga"); + } + else + { + p3d::context->GetLoadManager()->AddHandler(new(GMA_GC_VMM) tBMPHandler, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_GC_VMM) tPNGHandler, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_GC_VMM) tTargaHandler, "p3d"); + } + +// p3d->AddHandler(new tGeometryLoader); +// GeometryWrappedLoader* pGWL = new GeometryWrappedLoader; + GeometryWrappedLoader* pGWL = + (GeometryWrappedLoader*)GetAllWrappers()->mpLoader( AllWrappers::msGeometry ); + pGWL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pGWL ); + + StaticEntityLoader* pSEL = + (StaticEntityLoader*)GetAllWrappers()->mpLoader( AllWrappers::msStaticEntity ); + pSEL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pSEL ); + + StaticPhysLoader* pSPL = + (StaticPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msStaticPhys ); + pSPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pSPL ); + + TreeDSGLoader* pTDL = + (TreeDSGLoader*)GetAllWrappers()->mpLoader( AllWrappers::msTreeDSG ); + pTDL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pTDL ); + + FenceLoader* pFL = + (FenceLoader*)GetAllWrappers()->mpLoader( AllWrappers::msFenceEntity ); + pFL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pFL ); + + IntersectLoader* pIL = + (IntersectLoader*)GetAllWrappers()->mpLoader( AllWrappers::msIntersectDSG ); + pIL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pIL ); + + AnimCollLoader* pACL = + (AnimCollLoader*)GetAllWrappers()->mpLoader( AllWrappers::msAnimCollEntity ); + pACL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pACL ); + + AnimDSGLoader* pAnimDSGLoader = + (AnimDSGLoader*)GetAllWrappers()->mpLoader( AllWrappers::msAnimEntity ); + pAnimDSGLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimDSGLoader ); + + DynaPhysLoader* pDPL = + (DynaPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msDynaPhys ); + pDPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pDPL ); + + InstStatPhysLoader* pISPL = + (InstStatPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msInstStatPhys ); + pISPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pISPL ); + + InstStatEntityLoader* pISEL = + (InstStatEntityLoader*)GetAllWrappers()->mpLoader( AllWrappers::msInstStatEntity ); + pISEL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pISEL ); + + LocatorLoader* pLL = + (LocatorLoader*)GetAllWrappers()->mpLoader( AllWrappers::msLocator); + pLL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pLL ); + + RoadLoader* pRL = + (RoadLoader*)GetAllWrappers()->mpLoader( AllWrappers::msRoadSegment); + pRL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pRL ); + + PathLoader* pPL = + (PathLoader*)GetAllWrappers()->mpLoader( AllWrappers::msPathSegment); + pPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pPL ); + + WorldSphereLoader* pWSL = + (WorldSphereLoader*)GetAllWrappers()->mpLoader( AllWrappers::msWorldSphere); + pWSL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pWSL ); + + LensFlareLoader* pLSL = + (LensFlareLoader*)GetAllWrappers()->mpLoader( AllWrappers::msLensFlare); + pLSL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pLSL ); + + BillboardWrappedLoader* pBWL = + (BillboardWrappedLoader*)GetAllWrappers()->mpLoader( AllWrappers::msBillboard); + pBWL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pBWL ); + + InstParticleSystemLoader* pInstParticleSystemLoader = + (InstParticleSystemLoader*) GetAllWrappers()->mpLoader( AllWrappers::msInstParticleSystem); + pInstParticleSystemLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pInstParticleSystemLoader ); + + BreakableObjectLoader* pBreakableObjectLoader = + (BreakableObjectLoader*) GetAllWrappers()->mpLoader( AllWrappers::msBreakableObject); + pBreakableObjectLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pBreakableObjectLoader ); + + AnimDynaPhysLoader* pAnimDynaPhysLoader = + (AnimDynaPhysLoader*) GetAllWrappers()->mpLoader( AllWrappers::msAnimDynaPhys); + pAnimDynaPhysLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimDynaPhysLoader ); + + AnimDynaPhysWrapperLoader* pAnimWrapperLoader = + (AnimDynaPhysWrapperLoader*) GetAllWrappers()->mpLoader( AllWrappers::msAnimDynaPhysWrapper); + pAnimWrapperLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimWrapperLoader ); + + p3d->AddHandler(new(GMA_GC_VMM) tTextureLoader); + p3d->AddHandler( new(GMA_GC_VMM) tSetLoader ); + p3d->AddHandler(new(GMA_GC_VMM) tShaderLoader); + p3d->AddHandler(new(GMA_GC_VMM) tCameraLoader); + p3d->AddHandler(new(GMA_GC_VMM) tGameAttrLoader); + p3d->AddHandler(new(GMA_GC_VMM) tLightLoader); + + p3d->AddHandler(new(GMA_GC_VMM) tLocatorLoader); + p3d->AddHandler(new(GMA_GC_VMM) tLightGroupLoader); + p3d->AddHandler(new(GMA_GC_VMM) tImageLoader); + p3d->AddHandler(new(GMA_GC_VMM) tTextureFontLoader); + p3d->AddHandler(new(GMA_GC_VMM) tImageFontLoader); + p3d->AddHandler(new(GMA_GC_VMM) tSpriteLoader); + //p3d->AddHandler(new(GMA_GC_VMM) tBillboardQuadGroupLoader); + p3d->AddHandler(new(GMA_GC_VMM) tSkeletonLoader); + p3d->AddHandler(new(GMA_GC_VMM) tPolySkinLoader); + p3d->AddHandler(new(GMA_GC_VMM) tCompositeDrawableLoader); + p3d->AddHandler(new(GMA_GC_VMM) tAnimationLoader); + p3d->AddHandler(new(GMA_GC_VMM) tFrameControllerLoader); + p3d->AddHandler(new(GMA_GC_VMM) tMultiControllerLoader); + p3d->AddHandler(new(GMA_GC_VMM) tAnimatedObjectFactoryLoader); + p3d->AddHandler(new(GMA_GC_VMM) tAnimatedObjectLoader); + p3d->AddHandler(new(GMA_GC_VMM) tParticleSystemFactoryLoader); + p3d->AddHandler(new(GMA_GC_VMM) tParticleSystemLoader); + p3d->AddHandler(new(GMA_GC_VMM) tLensFlareGroupLoader); + p3d->AddHandler(new(GMA_GC_VMM) sg::Loader); + + p3d->AddHandler(new(GMA_GC_VMM) tExpressionGroupLoader); + p3d->AddHandler(new(GMA_GC_VMM) tExpressionMixerLoader); + p3d->AddHandler(new(GMA_GC_VMM) tExpressionLoader); + + p3d->AddHandler(new(GMA_GC_VMM) tVertexAnimKeyLoader); + + //p3d->AddHandler(new p3d::tIgnoreLoader); + + tSEQFileHandler* sequencerFileHandler = new(GMA_GC_VMM) tSEQFileHandler; + p3d::loadManager->AddHandler(sequencerFileHandler, "seq"); + + // sim lib + sim::InstallSimLoaders(); + + p3d->AddHandler(new(GMA_GC_VMM) CameraDataLoader, SRR2::ChunkID::WALKERCAM ); + p3d->AddHandler(new(GMA_GC_VMM) CameraDataLoader, SRR2::ChunkID::FOLLOWCAM ); + p3d->AddHandler(new(GMA_GC_VMM) IntersectionLoader); +// p3d->AddHandler(new(GMA_GC_VMM) RoadLoader); + p3d->AddHandler(new(GMA_GC_VMM) RoadDataSegmentLoader); + p3d->AddHandler(new(GMA_GC_VMM) ATCLoader); + p3d->AddHandler(new(GMA_GC_VMM) CStatePropDataLoader); +MEMTRACK_POP_GROUP( "GCPlatform" ); +} + + +//============================================================================== +// GCPlatform::ShutdownPure3D +//============================================================================== +// Description: Clean up and shut down Pure3D. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void GCPlatform::ShutdownPure3D() +{ + // + // Clean-up the Pure3D Inventory + // + p3d::inventory->RemoveAllElements(); + p3d::inventory->DeleteAllSections(); + + // + // Clean-up the space taken by the Pure 3D context. + // + if( mpContext != NULL ) + { + mpPlatform->DestroyContext( mpContext ); + mpContext = NULL; + } + + // + // Clean-up the space taken by the Pure 3D platform. + // + if( mpPlatform != NULL ) + { + tPlatform::Destroy( mpPlatform ); + mpPlatform = NULL; + } +} + + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** + + +//============================================================================== +// GCPlatform::GCPlatform +//============================================================================== +// Description: Constructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +GCPlatform::GCPlatform() : + mpPlatform( NULL ), + mpContext( NULL ) +{ +} + + +//============================================================================== +// GCPlatform::~GCPlatform +//============================================================================== +// Description: Destructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +GCPlatform::~GCPlatform() +{ +} diff --git a/game/code/main/gcplatform.h b/game/code/main/gcplatform.h new file mode 100644 index 0000000..ddab488 --- /dev/null +++ b/game/code/main/gcplatform.h @@ -0,0 +1,160 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: gcplatform.h +// +// Description: Abstracts the differences for setting up and shutting down +// the different platforms. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +#ifndef GCPLATFORM_H +#define GCPLATFORM_H + +//======================================== +// Nested Includes +//======================================== +#include <main/platform.h> // base class + +#include <p3d/platform.hpp> + +//======================================== +// Forward References +//======================================== +struct IRadMemoryHeap; +//class tPlatform; +class tContext; + +// +// This value define the resolution of the rendering area. +// Based on the width, Pure3D figures out the approriate height. +// +const int WindowSizeX = 640; + +#ifdef PAL +const int WindowSizeY = 524; +#else +const int WindowSizeY = 480; +#endif + +// +// The depth of the rendering area. This value only has an effect +// when Pure3D has taken over the entire display. When running in +// a window on the desktop, Pure3D uses the same bit depth as the +// desktop. Pure3D only supports 16, and 32 rendering depths. +// +static const int WindowBPP = 16; + +//Turn this on to disable ARAM use. Use this to test leaks in the ARAM heap. +//#define NO_ARAM + +#ifdef NO_ARAM +const int VMM_MAIN_RAM = 0; +const int VMM_ARAM = 0; +#else +const int VMM_MAIN_RAM = ( 1 * 1024 * 1024 ) + ( 500 * 1024 ); +const int VMM_ARAM = 6 * 1024 * 1024; +#endif + + +//============================================================================= +// +// Synopsis: Provides abstraction for setting up and closing down the GC. +// +//============================================================================= +class GCPlatform : public Platform +{ + public: + + // Static Methods for accessing this singleton. + static GCPlatform* CreateInstance(); + static GCPlatform* GetInstance(); + static void DestroyInstance(); + + // Had to workaround our nice clean design cause FTech must be init'ed + // before anything else is done. + static void InitializeFoundation(); + static void InitializeMemory(); + + // Implement Platform interface. + virtual void InitializePlatform(); + virtual void ShutdownPlatform(); + + virtual void InitializeFoundation(); + + virtual void LaunchDashboard(); + virtual void ResetMachine(); + virtual void DisplaySplashScreen( SplashScreen screenID, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ); + + virtual void DisplaySplashScreen( const char* textureName, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ); + + bool DisplayYesNo( float fontScale = 1.0f, + float yesPosX = 0.0f, + float yesPosY = 0.0f, + float noPosX = 0.0f, + float noPosY = 0.0f, + int fadeFrames = 3 ); + + tContextInitData* GetInitData(); + + virtual bool OnDriveError( radFileError error, const char* pDriveName, void* pUserData ); + virtual void OnControllerError(const char *msg); + + protected: + + virtual void InitializeFoundationDrive(); + virtual void ShutdownFoundation(); + + virtual void InitializePure3D(); + virtual void ShutdownPure3D(); + + private: + + // Constructors, Destructors, and Operators + GCPlatform(); + virtual ~GCPlatform(); + + // Unused Constructors, Destructors, and Operators + GCPlatform( const GCPlatform& aPlatform ); + GCPlatform& operator=( const GCPlatform& aPlatform ); + + // Pointer to the one and only instance of this singleton. + static GCPlatform* spInstance; + + // Pure 3D attributes + tPlatform* mpPlatform; + tContext* mpContext; + + tContextInitData mInitData; +}; + +//============================================================================= +// GCPlatform::GetInitData +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: tContextInitData +// +//============================================================================= +inline tContextInitData* GCPlatform::GetInitData() +{ + return &mInitData; +} + +#endif // GCPLATFORM_H diff --git a/game/code/main/globaltypes.h b/game/code/main/globaltypes.h new file mode 100644 index 0000000..9a8aaae --- /dev/null +++ b/game/code/main/globaltypes.h @@ -0,0 +1,30 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: globaltypes.h +// +// Description: Declarations of utility types. +// +// History: 2/18/2003 + Created -- Esan +// +//============================================================================= + +#ifndef GLOBALTYPES_H +#define GLOBALTYPES_H + +// +// define 64 bit integer for all platforms +// +#ifdef RAD_PS2 +typedef unsigned long simpsonsUInt64; +#endif + +#ifdef RAD_GAMECUBE +typedef unsigned long long simpsonsUInt64; +#endif + +#if defined RAD_XBOX || defined RAD_WIN32 +typedef unsigned __int64 simpsonsUInt64; +#endif + +#endif //GLOBALTYPES_H diff --git a/game/code/main/pchsrr2.cpp b/game/code/main/pchsrr2.cpp new file mode 100644 index 0000000..3c4b8cb --- /dev/null +++ b/game/code/main/pchsrr2.cpp @@ -0,0 +1,15 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: pchsrr2.cpp +// +// Description: Manually generate pre-compiled headers. +// +// History: + Created -- Darwin Chau +// +//============================================================================= + +//======================================== +// Project Includes +//======================================== +#include <main/pchsrr2.h> diff --git a/game/code/main/pchsrr2.h b/game/code/main/pchsrr2.h new file mode 100644 index 0000000..931fe85 --- /dev/null +++ b/game/code/main/pchsrr2.h @@ -0,0 +1,23 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: pchsrr2.h +// +// Description: Manually generate pre-compiled headers. +// +// History: + Created -- Darwin Chau +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +#include <p3d/pure3d.hpp> +#include <raddebug.hpp> +#include <raddebugwatch.hpp> + +//======================================== +// Project Includes +//======================================== +//#include <memory/memoryoverrides.h> + diff --git a/game/code/main/platform.h b/game/code/main/platform.h new file mode 100644 index 0000000..bd7dfcd --- /dev/null +++ b/game/code/main/platform.h @@ -0,0 +1,104 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// Component: Platform +// +// Description: Pure virtual interface that abstracts the differences for +// setting up and shutting down the different platforms. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// + Added the Splash screens + dashboard -- Cary Brisebois +// +//============================================================================= + +#ifndef PLATFORM_H +#define PLATFORM_H + +//======================================== +// Nested Includes +//======================================== +#include <p3d/p3dtypes.hpp> // tColour + +#include <radfile.hpp> + +struct IRadDrive; + +//============================================================================= +// +// Synopsis: Implement this interface for each platform that the game will +// support (e.g. PS2, GameCube, Xbox, etc.). +// +//============================================================================= +class Platform : public IRadDriveErrorCallback +{ + public: + + // NOTE: Each derived platform must also implement the following + // static function. This has to be static because we need + // to init FTech before anything is allocated. + // + // static void InitializeFoundation(); + + virtual void InitializePlatform() = 0; + virtual void ShutdownPlatform() = 0; + + virtual void LaunchDashboard() = 0; + virtual void ResetMachine() = 0; + + //These are the baked in screens + enum SplashScreen + { + License, //Shows the baked in license screen as the background + Error, //Displays a blank black background + FadeToBlack + }; + + virtual void DisplaySplashScreen( SplashScreen screenID, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ) = 0; + + virtual void DisplaySplashScreen( const char* textureName, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ) = 0; + virtual void OnControllerError(const char *msg) = 0; + + //Override this if you wanna support it. + virtual bool OnDriveError( radFileError error, const char* pDriveName, void* pUserData ) { return false; }; + void ClearControllerError() { OnDriveError(Success, NULL, NULL);} + bool PausedForErrors() const { return mPauseForError; }; + bool IsControllerError() const { return mErrorState==CTL_ERROR; }; + IRadDrive* GetHostDrive( void ) const { return mpIRadDrive; } + + protected: + enum ErrorState + { + NONE, + P_ERROR, + CTL_ERROR + }; + + ErrorState mErrorState; + + virtual void InitializeFoundationDrive() = 0; + virtual void ShutdownFoundation() = 0; + + virtual void InitializePure3D() = 0; + virtual void ShutdownPure3D() = 0; + + bool mPauseForError; + + // Foundation attributes + IRadDrive* mpIRadDrive; + + Platform() : mPauseForError( false ), mpIRadDrive( 0 ) {}; +}; + +#endif // PLATFORM_H diff --git a/game/code/main/ps2main.cpp b/game/code/main/ps2main.cpp new file mode 100644 index 0000000..b5d0b61 --- /dev/null +++ b/game/code/main/ps2main.cpp @@ -0,0 +1,295 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: ps2main.cpp +// +// Description: This file contains the main enrty point to the game. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +#include <string.h> +// Foundation Tech +#include <raddebug.hpp> +#include <radobject.hpp> +#include <radthread.hpp> +#include <radtextdisplay.hpp> + +#include <pddi/ps2/ps2context.hpp> + +//======================================== +// Project Includes +//======================================== +#include <main/game.h> +#include <main/ps2platform.h> +#include <main/singletons.h> +#include <main/commandlineoptions.h> +#include <memory/memoryutilities.h> +#include <memory/srrmemory.h> + +#ifdef RAD_MW + #include <mwutils.h> +#endif + +//======================================== +// Forward Declarations +//======================================== +static void ProcessCommandLineArguments( int argc, char* argv[] ); + +static void ProcessCommandLineArgumentsFromFile( ); + + + +void OutputHandler (const char * pString ) +{ + static int ypos = 0; + static IRadTextDisplay* textDisplay = 0; + + + if (!textDisplay || (ypos > 20)) + { + if (textDisplay) + { + textDisplay->Release (); + } + ::radTextDisplayGet( &textDisplay, GMA_TEMP ); + textDisplay->SetBackgroundColor( 0 ); + textDisplay->SetTextColor( 0xffffffff ); + textDisplay->Clear(); + ypos = 0; + } + + if ( textDisplay ) + { + textDisplay->TextOutAt( pString, 0, ypos ); + textDisplay->SwapBuffers(); + ypos++; + } + + radThreadSleep (200); +} + + +//============================================================================= +// Function: main +//============================================================================= +// +// Description: Main entry point. +// +// Parameters: PS2EE argc, number of command line argurments +// argv, array of pointes to these tokens. +// +// Returns: 0 success, non zero error. +// +//============================================================================= +int main( int argc, char* argv[] ) +{ + //::rDebugSetOutputHandler (OutputHandler); + + // Get rid of junk in the frame buffer, + // before pddi gets initialised + sceGsSyncV(0); + *GS_PMODE = SCE_GS_SET_PMODE(0,0,0,0,0,0,0); + sceGsResetPath(); + ps2_clearvram(); + +#ifdef RAD_MW + mwInit(); +#endif + + /* + int bytes = static_cast<int>(27.0f * 1024.0 * 1024.0); + char* p = (char*)malloc (bytes); + memset (p, 0x00, bytes); + free (p); + */ + + /* +#ifdef RAD_RELEASE + if (CommandLineOptions::Get (CLO_CD_FILES_ONLY)) + { + void* p = malloc (96 * 1024 * 1024); + } +#endif + */ + + // + // All settings get stored in GameDB. + // + CommandLineOptions::InitDefaults(); + ProcessCommandLineArguments( argc, argv ); + + // + // Have to get FTech setup first so that we can use all the memory services. + // + PS2Platform::InitializeFoundation(); + + srand (Game::GetRandomSeed ()); + +#ifndef RAD_RELEASE + tName::SetAllocator (GMA_DEBUG); + + // Now disable the default heap + // + //g_HeapActivityTracker.EnableHeapAllocs (GMA_DEFAULT, false); + //g_HeapActivityTracker.EnableHeapFrees (GMA_DEFAULT, false); + + // Can never free from the persistent heap + // + //g_HeapActivityTracker.EnableHeapFrees (GMA_PERSISTENT, false); +#endif + + HeapMgr()->PushHeap (GMA_PERSISTENT); + + //Process any commandline options from the command.txt file + ProcessCommandLineArgumentsFromFile(); + + // + // Instantiate all the singletons before doing anything else. + // + CreateSingletons(); + + // + // Construct the platform object. + // + PS2Platform* pPlatform = PS2Platform::CreateInstance(); + rAssert( pPlatform != NULL ); + + // + // Create the game object. + // + Game* pGame = Game::CreateInstance( pPlatform ); + rAssert( pGame != NULL ); + + + + + + // + // Initialize the game. + // + pGame->Initialize(); + + HeapMgr()->PopHeap (GMA_PERSISTENT); + + // + // Run it! Control will not return from here until the game is stopped. + // + pGame->Run(); + + // + // Terminate the game (this frees all resources allocated by the game). + // + pGame->Terminate(); + + // + // Destroy the game object. + // + Game::DestroyInstance(); + + // + // Destroy the game and platform (do it in this order in case the game's + // destructor references the platform. + // + PS2Platform::DestroyInstance(); + + // + // Show some debug output + // +#ifdef RAD_DEBUG + radObject::DumpObjects(); +#endif; + + // + // Dump all the singletons. + // + DestroySingletons(); + + // + // Pass any error codes back to the operating system. + // + return( 0 ); +} + + +//============================================================================= +// Function: ProcessCommandLineArguments +//============================================================================= +// +// Description: Pick out the command line options and stuff them in +// the game database. +// +// Parameters: PS2EE argc, number of command line argurments +// argv, array of pointes to these tokens. +// +// Returns: None. +// +//============================================================================= +void ProcessCommandLineArguments( int argc, char* argv[] ) +{ +//#ifndef FINAL + + rDebugPrintf( "*************************************************************\n" ); + rDebugPrintf( "Command Line Args:\n" ); + + // + // Pick out all the command line options and store them in GameDB. + // Also dump them to the output for handy dandy viewing. + // + int i; + for( i = 0; i < argc; ++i ) + { + char* argument = argv[i]; + + rDebugPrintf( "arg%d: %s\n", i, argument ); + + CommandLineOptions::HandleOption( argument ); + + } + if( !CommandLineOptions::Get( CLO_ART_STATS ) ) + { + //CommandLineOptions::HandleOption( "noheaps" ); + } + + + rDebugPrintf( "*************************************************************\n" ); + +//#endif // FINAL +} + + + +void ProcessCommandLineArgumentsFromFile() +{ +#ifndef FINAL + + //Chuck: looking for additional command line args being passed in from a file + //its for QA testing etc. + + IRadFile* pfile =NULL; + + ::radFileOpenSync(&pfile,"command.txt"); + + if (pfile != NULL) + { + char commandlinestring [256]; + commandlinestring[ 0 ] = '\0'; + + pfile->ReadSync(commandlinestring,255); + + //QA created the command line file and wants to pass additional arguements + + char* argument = strtok(commandlinestring," "); + while (argument != NULL) + { + CommandLineOptions::HandleOption(argument); + argument=strtok(NULL," "); + } + pfile->Release(); + } +#endif //FINAL +} //end of Function
\ No newline at end of file diff --git a/game/code/main/ps2platform.cpp b/game/code/main/ps2platform.cpp new file mode 100644 index 0000000..8849a30 --- /dev/null +++ b/game/code/main/ps2platform.cpp @@ -0,0 +1,1847 @@ +//=========================================================================== +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// Component: PS2Platform +// +// Description: Abstracts the differences for setting up and shutting down +// the different platforms. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//=========================================================================== + +//======================================== +// System Includes +//======================================== +// Sony +#include <libcdvd.h> +#include <sifdev.h> +#include <sifrpc.h> +#include <sifcmd.h> +#include <eetypes.h> +#include <eekernel.h> +#include <libpad.h> + +// Standard Lib +#include <stdlib.h> +#include <string.h> +// SN Systems +#include <libsn.h> +// Pure 3D +#include <p3d/anim/compositedrawable.hpp> +#include <p3d/anim/expression.hpp> +#include <p3d/anim/multicontroller.hpp> +#include <p3d/anim/polyskin.hpp> +#include <p3d/anim/sequencer.hpp> +#include <p3d/anim/skeleton.hpp> +#include <p3d/camera.hpp> +#include <p3d/gameattr.hpp> +#include <p3d/image.hpp> +#include <p3d/imagefont.hpp> +#include <p3d/light.hpp> +#include <p3d/locator.hpp> +#include <p3d/platform.hpp> +#include <p3d/scenegraph/scenegraph.hpp> +#include <p3d/sprite.hpp> +#include <p3d/utility.hpp> +#include <p3d/texture.hpp> +#include <p3d/file.hpp> +#include <p3d/shader.hpp> +#include <p3d/matrixstack.hpp> +#include <p3d/memory.hpp> +#include <p3d/bmp.hpp> +#include <p3d/png.hpp> +#include <p3d/targa.hpp> +#include <p3d/font.hpp> +#include <p3d/texturefont.hpp> +#include <p3d/unicode.hpp> +#include <pddi/pddiext.hpp> +// Pure 3D: Loader-specific +#include <render/Loaders/GeometryWrappedLoader.h> +#include <render/Loaders/StaticEntityLoader.h> +#include <render/Loaders/StaticPhysLoader.h> +#include <render/Loaders/TreeDSGLoader.h> +#include <render/Loaders/FenceLoader.h> +#include <render/Loaders/IntersectLoader.h> +#include <render/Loaders/AnimCollLoader.h> +#include <render/Loaders/AnimDSGLoader.h> +#include <render/Loaders/DynaPhysLoader.h> +#include <render/Loaders/InstStatPhysLoader.h> +#include <render/Loaders/InstStatEntityLoader.h> +#include <render/Loaders/WorldSphereLoader.h> +#include <render/Loaders/BillboardWrappedLoader.h> +#include <render/Loaders/instparticlesystemloader.h> +#include <render/Loaders/breakableobjectloader.h> +#include <render/Loaders/lensflareloader.h> +#include <render/Loaders/AnimDynaPhysLoader.h> +#include <p3d/shadow.hpp> +#include <p3d/anim/animatedobject.hpp> +#include <p3d/anim/vertexanimkey.hpp> +#include <p3d/effects/particleloader.hpp> +#include <p3d/effects/opticloader.hpp> + +//This is so we can get the name of the file that's failing. +#include <../src/radfile/common/requests.hpp> + +// Foundation Tech +#include <raddebug.hpp> +#include <radthread.hpp> +#include <radplatform.hpp> +#include <radtime.hpp> +#include <radmemorymonitor.hpp> +#include <raddebugcommunication.hpp> +#include <raddebugwatch.hpp> +#include <radfile.hpp> +#include <radmovie2.hpp> +#include <radload/radload.hpp> +#include <radtextdisplay.hpp> + +// sim - for InstallSimLoaders +#include <simcommon/simutility.hpp> +// StateProps +#include <stateprop/statepropdata.hpp> + +// To turn off movies during an error. +#include <presentation/fmvplayer/fmvplayer.h> +#include <presentation/presentation.h> + +//======================================== +// Project Includes +//======================================== +#include <input/inputmanager.h> +#include <main/ps2platform.h> +#include <main/game.h> +#include <main/commandlineoptions.h> +#include <memory/srrmemory.h> +#include <render/RenderManager/RenderManager.h> +#include <render/Loaders/AllWrappers.h> + +#include <loading/locatorloader.h> +#include <loading/cameradataloader.h> +#include <loading/roadloader.h> +#include <loading/pathloader.h> +#include <loading/intersectionloader.h> +#include <loading/roaddatasegmentloader.h> +#include <atc/atcloader.h> + +#include <debug/debuginfo.h> + +#include <main/errorsps2.h> + +#include <sound/soundmanager.h> + +#include <presentation/presentation.h> +#include <presentation/gui/guitextbible.h> +#include <data/gamedatamanager.h> + +#include <cheats/cheatinputsystem.h> + +#include <mission/gameplaymanager.h> +#include <pddi/pddi.hpp> + +#define PS2_SECTION "PS2_SECTION" + +// #define IOP_MEMORY_TEST + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + +IRadCementLibrary* PS2Platform::s_MainCement = NULL; + +// Static pointer to instance of singleton. +PS2Platform* PS2Platform::spInstance = NULL; + + +//The Adlib font. <sigh> +unsigned char gFont[] = +#include <font/defaultfont.h> + + +// +// Uncomment the define below to run off a DVD +// +/***** #define DVD_MEDIA *****/ +#define DVD_MEDIA + +// +// This value define the resolution of the rendering area. +// Based on the width, Pure3D figures out the approriate height. +// +static const int WindowSizeX = 640; + +// +// The depth of the rendering area. This value only has an effect +// when Pure3D has taken over the entire display. When running in +// a window on the desktop, Pure3D uses the same bit depth as the +// desktop. Pure3D only supports 16, and 32 rendering depths. +// +static const int WindowBPP = 32; + +void LoadMemP3DFile( unsigned char* buffer, unsigned int size, tEntityStore* store ) +{ + tFileMem* file = new tFileMem(buffer,size); + file->AddRef(); + file->SetFilename("memfile.p3d"); + p3d::loadManager->GetP3DHandler()->Load( file, p3d::inventory ); + file->Release(); +} + +extern bool gIgnoreLastFrameSyncCheck; + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================== +// PS2Platform::CreateInstance +//============================================================================== +// +// Description: Creates the PS2Platform. +// +// Parameters: None. +// +// Return: Pointer to the PS2Platform. +// +// Constraints: This is a singleton so only one instance is allowed. +// +//============================================================================== +PS2Platform* PS2Platform::CreateInstance() +{ +MEMTRACK_PUSH_GROUP( "PS2Platform" ); + rAssert( spInstance == NULL ); + + spInstance = new(GMA_PERSISTENT) PS2Platform; + rAssert( spInstance ); +MEMTRACK_POP_GROUP("PS2Platform"); + + return spInstance; +} + +//============================================================================== +// PS2Platform::GetInstance +//============================================================================== +// +// Description: - Access point for the PS2Platform singleton. +// +// Parameters: None. +// +// Return: Pointer to the PS2Platform. +// +// Constraints: This is a singleton so only one instance is allowed. +// +//============================================================================== +PS2Platform* PS2Platform::GetInstance() +{ + rAssert( spInstance != NULL ); + + return spInstance; +} + + +//============================================================================== +// PS2Platform::DestroyInstance +//============================================================================== +// +// Description: Destroy the PS2Platform. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void PS2Platform::DestroyInstance() +{ + rAssert( spInstance != NULL ); + + delete( GMA_PERSISTENT, spInstance ); + spInstance = NULL; +} + + +//============================================================================== +// PS2Platform::InitializeFoundation +//============================================================================== +// Description: Get FTech ready to go. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be initialized in a particular order. +// Consult their documentation before changing. +// +//============================================================================== +void PS2Platform::InitializeFoundation() +{ + const char IRX_PATH[] = "IRX\\"; + const char SONY_LIB_NAME[] = "IOPRP254.IMG"; + + // + // Initialize the memory heaps + // + PS2Platform::InitializeMemory(); + +#ifndef FINAL + // + // Register an out-of-memory display handler in case something goes bad + // while allocating the heaps + // + ::radMemorySetOutOfMemoryCallback( PrintOutOfMemoryMessage, NULL ); +#endif + + // + // Initialize memory monitor by JamesCo. TM. + // + if( CommandLineOptions::Get( CLO_MEMORY_MONITOR) ) + { + const int KB = 1024; + ::radMemoryMonitorInitialize( 100 * KB, GMA_DEBUG ); + } + + // Setup the memory heaps + // + HeapMgr()->PrepareHeapsStartup (); + + + // Seed the heap stack with this + // + HeapMgr()->PushHeap (GMA_PERSISTENT); + + // + // Initilalize the platform system + // On the PS2, provide the root path for IRXs. + // +#ifdef DVD_MEDIA + radPlatformGameMediaType mediaType = GameMediaDVD; +#else + radPlatformGameMediaType mediaType = GameMediaCD; +#endif // DVD_MEDIA + + if( CommandLineOptions::Get( CLO_FIREWIRE ) ) + { + ::radPlatformInitialize( IRX_PATH, + IOPMediaCDVD, + mediaType, + NULL, + GMA_PERSISTENT ); + } + else if( CommandLineOptions::Get( CLO_CD_FILES_ONLY ) ) + { + ::radPlatformInitialize( IRX_PATH, + IOPMediaCDVD, + mediaType, + SONY_LIB_NAME, + GMA_PERSISTENT ); + } + else + { + ::radPlatformInitialize( IRX_PATH, + IOPMediaHost, + mediaType, + SONY_LIB_NAME, + GMA_PERSISTENT ); + } + + + +#ifdef IOP_MEMORY_TEST + + IRadTextDisplay * pDisp; + + radTextDisplayGet( & pDisp, RADMEMORY_ALLOC_DEFAULT ); + + char buf[ 256 ]; + + unsigned int maxFreeMemSize = sceSifQueryMaxFreeMemSize( ); + unsigned int totalFreeMemSize = sceSifQueryTotalFreeMemSize( ); + unsigned int memSize = sceSifQueryMemSize( ); + + sprintf( + buf, + "\nMemSize: [0x%x]\nTotalFreeMemSize: [0x%x]\nMaxFreeMemSize:[0x%x]\n", + memSize, + totalFreeMemSize, + maxFreeMemSize ); + + pDisp->TextOut( buf ); + pDisp->SwapBuffers( ); + + while( 1 ) { } + + pDisp->Release( ); +#endif + + + + // Eat up 6 mb if "TOOL" in command line for testing IOP crashes. + + if ( CommandLineOptions::Get( CLO_PS2_TOOL ) ) + { + + // Results from above: + + // Tool: + // MemSize: [0x7fff00] + // TotalFreeMemSize: [0x798400] + // MaxFreeMemSize: [0x798200] + // + // Artist Box: + // MemSize: [0x200000] + // TotalFreeMemSize: [0x1a3900] + // MaxFreeMemSize: [0x1a3900] + + + const unsigned int toolMaxFreeMemSize = 0x798200; + const unsigned int consumerMaxFreeMemSize = 0x1a3900; + const unsigned int difMaxFreeMemSize = toolMaxFreeMemSize - consumerMaxFreeMemSize; + + const int allocChunkSize = 4096 * 16; + + rReleasePrintf( "Consuming [0x%x] bytes on tool:\n", difMaxFreeMemSize ); + + unsigned int maxFreeMemSize; + + do + { + void * pMem = sceSifAllocIopHeap( allocChunkSize ); + rReleaseAssertMsg( pMem, "Out of memory consuming extra tool memory" ); + maxFreeMemSize = sceSifQueryMaxFreeMemSize( ); + rReleasePrintf( "BURNING IOP: MaxFreeMemSize: [0x%x]\n", maxFreeMemSize ); + } while( maxFreeMemSize > consumerMaxFreeMemSize ); + } + + // + // Initialize the timer system + // + ::radTimeInitialize(); + + // + // Initialize the debug communication system. + // + if( CommandLineOptions::Get( CLO_FIREWIRE ) ) + { + ::radDbgComTargetInitialize( FireWire, + radDbgComDefaultPort, + (void*)"", + GMA_DEBUG ); + } + else + { + ::radDbgComTargetInitialize( Deci, + radDbgComDefaultPort, // Default + NULL, // Default + GMA_DEBUG ); + } + + // + // Initialize the Watcher. + // +#ifdef DEBUGWATCH + ::radDbgWatchInitialize( "SRR2", + 16384 * 32, // Default + GMA_DEBUG ); +#endif // DEBUGWATCH + + // + // Initialize the file system. + // + ::radFileInitialize( 50, // Default + 32, // Default + GMA_PERSISTENT ); + + ::radLoadInitialize( ); + + if( CommandLineOptions::Get( CLO_FIREWIRE ) ) + { + ::radSetDefaultDrive( "REMOTEDRIVE:" ); + } + else if( CommandLineOptions::Get( CLO_CD_FILES_ONLY ) ) + { + ::radSetDefaultDrive( "CDROM:" ); + } + else + { + ::radSetDefaultDrive( "HOSTDRIVE:" ); + } + + ::radDriveMount( 0, GMA_PERSISTENT ); + + // + // On PS2, synchronously load the art.rcf file. This is needed before + // anything else can happen. + // + if( CommandLineOptions::Get( CLO_CD_FILES_ONLY ) ) + { + radFileRegisterCementLibrarySync( & s_MainCement, "art.rcf" ); + } + + + // + // Initialize the new movie player + // + ::radMovieInitialize2( GMA_PERSISTENT ); + + // + // Init VU0 for optimizations. + // + ::radMathInitialize(); + +#ifndef FINAL + // + // Set up exception handlers, so that when the game crashes we can + // see something. + // + if( CommandLineOptions::Get( CLO_CD_FILES_ONLY ) || + CommandLineOptions::Get( CLO_FIREWIRE ) ) + { + SetDebugHandler( 1, handleTLBChange ); + SetDebugHandler( 2, handleTLBLoadMismatch ); + SetDebugHandler( 3, handleTLBStoreMismatch ); + SetDebugHandler( 4, handleAddressLoadError ); + SetDebugHandler( 5, handleAddressStoreError ); + SetDebugHandler( 6, handleBusFetchError ); + SetDebugHandler( 7, handleBusDataError ); + + // #8 is "system call exception", #9 is "breakpoint exception". + // I don't think we need those. + + SetDebugHandler( 10, handleReservedInstruction ); + SetDebugHandler( 11, handleCoprocessor ); + SetDebugHandler( 12, handleOverflow ); + SetDebugHandler( 13, handleTrap ); + } +#endif + + HeapMgr()->PopHeap (GMA_PERSISTENT); +} + + + +//============================================================================== +// PS2Platform::InitializeMemory +//============================================================================== +// +// Description: +// +// Parameters: +// +// Return: +// +//============================================================================== +void PS2Platform::InitializeMemory() +{ + // + // Only do this once! + // + if( gMemorySystemInitialized == true ) + { + return; + } + + gMemorySystemInitialized = true; + + // + // Initialize thread system. + // + ::radThreadInitialize(); + + // + // Initialize memory system. + // + ::radMemoryInitialize(); +} + + + + +//============================================================================== +// PS2Platform::InitializePlatform +//============================================================================== +// Description: Get the PS2 ready to go. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void PS2Platform::InitializePlatform() +{ + HeapMgr()->PushHeap (GMA_PERSISTENT); + + if( CommandLineOptions::Get( CLO_SN_PROFILER ) ) + { + this->EnableSnProfiler(); + } + + InitializePure3D(); + + // Add anything here that needs to be before the + // drive is opened. + DisplaySplashScreen( Error ); // blank screen + + // + // This is SLOW so do it last. + // + InitializeFoundationDrive(); + + // + // Can only setup the controller after the IOP has been rebooted. + // + GetInputManager()->Init(); + + HeapMgr()->PopHeap (GMA_PERSISTENT); +} + + +//============================================================================== +// PS2Platform::ShutdownPlatform +//============================================================================== +// Description: Shut down the PS2. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void PS2Platform::ShutdownPlatform() +{ + ShutdownPure3D(); + ShutdownFoundation(); +} + +void PS2Platform::ResetMachine() +{ + scePadEnd(); + sceSifExitCmd(); + + char build = 0; + +#ifdef RAD_DEBUG + build = 'd'; +#elif defined RAD_TUNE + build = 't'; +#else + build = 'r'; +#endif + + char imageName[64]; + + if( CommandLineOptions::Get( CLO_CD_FILES_ONLY ) ) + { +#ifndef RAD_E3 + sprintf( imageName, "cdrom0:\\slps123.45" ); +#else + sprintf( imageName, "cdrom0:\\slps123.45" ); +#endif + LoadExecPS2( imageName, 0, NULL ); + } + else + { + char *args[] = { "hostfiles" }; +#ifndef RAD_E3 + sprintf( imageName, "hostdrive:\\srr2p%c.elf", build ); +#else + sprintf( imageName, "hostdrive:\\srr2e3p%c.elf", build ); +#endif + LoadExecPS2( imageName, 1, args ); + } +} + +//============================================================================= +// PS2Platform::LaunchDashboard +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void PS2Platform::LaunchDashboard() +{ + GetLoadingManager()->CancelPendingRequests(); + + //TODO: Make sure sounds shut down too. + GetSoundManager()->SetMasterVolume( 0.0f ); + + DisplaySplashScreen( FadeToBlack ); + + GetPresentationManager()->StopAll(); + + //Oh boy. + GameDataManager::DestroyInstance(); //Get rid of memcards + + p3d::loadManager->CancelAll(); + + SoundManager::DestroyInstance(); + + ShutdownPlatform(); + ResetMachine(); +} + + +//============================================================================= +// PS2Platform::DisplaySplashScreen +//============================================================================= +// Description: Comment +// +// Parameters: ( SplashScreen screenID, +// const char* overlayText = NULL, +// float fontScale = 1.0f, +// float textPosX = 0.0f, +// float textPosY = 0.0f, +// tColour textColour, +// int fadeFrames = 3 ) +// +// Return: void +// +//============================================================================= +void PS2Platform::DisplaySplashScreen( SplashScreen screenID, + const char* overlayText, + float fontScale, + float textPosX, + float textPosY, + tColour textColour, + int fadeFrames ) +{ + DisplaySplashScreen( NULL, overlayText, fontScale, textPosX, textPosY, textColour, fadeFrames ); +} + +//============================================================================= +// PS2Platform::DisplaySplashScreen +//============================================================================= +// Description: Comment +// +// Parameters: ( const char* textureName, +// const char* overlayText = NULL, +// float fontScale = 1.0f, +// float textPosX = 0.0f, +// float textPosY = 0.0f, +// tColour textColour, +// int fadeFrames = 3 ) +// +// Return: void +// +//============================================================================= +void PS2Platform::DisplaySplashScreen( const char* textureName, + const char* overlayText, + float fontScale, + float textPosX, + float textPosY, + tColour textColour, + int fadeFrames ) +{ + p3d::pddi->DrawSync(); + + HeapMgr()->PushHeap( GMA_TEMP ); + p3d::inventory->PushSection(); + p3d::inventory->AddSection( PS2_SECTION ); + p3d::inventory->SelectSection( PS2_SECTION ); + + P3D_UNICODE unicodeText[256]; + + // Save the current Projection mode so I can restore it later + pddiProjectionMode pm = p3d::pddi->GetProjectionMode(); + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_DEVICE); + + pddiCullMode cm = p3d::pddi->GetCullMode(); + p3d::pddi->SetCullMode(PDDI_CULL_NONE); + + + //CREATE THE FONT + tTextureFont* thisFont = NULL; + + // Convert memory buffer into a texturefont. + // + //p3d::load(gFont, DEFAULTFONT_SIZE, GMA_TEMP); + LoadMemP3DFile( gFont, DEFAULTFONT_SIZE, p3d::inventory ); + + thisFont = p3d::find<tTextureFont>("adlibn_20"); + rAssert( thisFont ); + + thisFont->AddRef(); + tShader* fontShader = thisFont->GetShader(); + //fontShader->SetInt( ) + + + p3d::AsciiToUnicode( overlayText, unicodeText, 256 ); + + // Make the missing letter into somthing I can see + // + thisFont->SetMissingLetter(p3d::ConvertCharToUnicode('j')); + + int a = 0; + + do + { + p3d::pddi->SetColourWrite(true, true, true, true); + p3d::pddi->SetClearColour( pddiColour(0,0,0) ); + p3d::pddi->BeginFrame(); + p3d::pddi->Clear(PDDI_BUFFER_COLOUR); + + //This is for fading in the font and shaders. + int bright = 255; + if (a < fadeFrames) bright = (a * 255) / fadeFrames; + if ( bright > 255 ) bright = 255; + tColour c(bright, bright, bright, 255); + + //Display font + if (overlayText != NULL) + { + tColour colour = textColour; + colour.SetAlpha( bright ); + + thisFont->SetColour( colour ); + + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_ORTHOGRAPHIC); + p3d::stack->Push(); + p3d::stack->LoadIdentity(); + + p3d::stack->Translate( textPosX, textPosY, 1.5f); + float scaleSize = 1.0f / 480.0f; //This is likely good for 528 also. + p3d::stack->Scale(scaleSize * fontScale, scaleSize* fontScale , 1.0f); + + if ( textPosX != 0.0f || textPosY != 0.0f ) + { + thisFont->DisplayText( unicodeText ); + } + else + { + thisFont->DisplayText( unicodeText, 3 ); + } + + p3d::stack->Pop(); + } + + p3d::pddi->EndFrame(); + p3d::context->SwapBuffers(); + + ++a; + + } while (a <= fadeFrames); + + p3d::pddi->SetCullMode(cm); + p3d::pddi->SetProjectionMode(pm); + + p3d::pddi->DrawSync(); + + gIgnoreLastFrameSyncCheck = true; + + //Should do this after a vsync. + thisFont->Release(); + + p3d::inventory->RemoveSectionElements(PS2_SECTION); + p3d::inventory->DeleteSection(PS2_SECTION); + p3d::inventory->PopSection(); + + gIgnoreLastFrameSyncCheck = false; + + HeapMgr()->PopHeap(GMA_TEMP); +} + + + + + + + + +//****************************************************************************** +// +// Protected Member Functions +// +//****************************************************************************** + + +//============================================================================== +// PS2Platform::InitializeFoundationDrive +//============================================================================== +// Description: Get FTech ready to go. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be initialized in a particular order. +// Consult their documentation before changing. +// +//============================================================================== +void PS2Platform::InitializeFoundationDrive() +{ + // + // No remote drives if we're only allowing files from the CD. + // + +// if( CommandLineOptions::Get( CLO_CD_FILES_ONLY ) ) +// { +// ::radDriveSetShadow( false ); +// } + + // + // Get the CDROM drive and hold it open for the life of the game. + // This is a costly operation so we only want to do it once. + // + if( CommandLineOptions::Get( CLO_CD_FILES_ONLY ) ) + { + ::radDriveOpen( &mpIRadDrive, + "CDROM:", + NormalPriority, // Default + GMA_PERSISTENT ); + + //Only care about CD drives. + mpIRadDrive->RegisterErrorHandler( this, NULL ); + } + else + { + ::radDriveOpen( &mpIRadDrive, + "HOSTDRIVE:", + NormalPriority, // Default + GMA_PERSISTENT ); + + //Only care about CD drives. + mpIRadDrive->RegisterErrorHandler( this, NULL ); + } + rAssert( mpIRadDrive != NULL ); + + // + // Set the read-write granulatity to prevent operations from + // being partitioned. + // + //const int GRANULARITY = 20 * 1024 * 1024; + //mpIRadDrive->SetReadWriteGranularity( GRANULARITY ); + +} + + +//============================================================================== +// PS2Platform::ShutdownFoundation +//============================================================================== +// Description: Shut down Foundation Tech. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be terminated in the reverse order that +// they were initialized in. +// +//============================================================================== +void PS2Platform::ShutdownFoundation() +{ + // + // Release the main cement file. + // + s_MainCement->Release(); + s_MainCement = NULL; + + // + // Release the drive we've held open since the begining. + // + mpIRadDrive->Release(); + mpIRadDrive = NULL; + +/* + spIRadMemoryHeapDefault->Release(); + spIRadMemoryHeapDefault = NULL; + spIRadMemoryHeapTemp->Release(); + spIRadMemoryHeapTemp = NULL; + spIRadMemoryHeapPersistent->Release(); + spIRadMemoryHeapPersistent = NULL; + spIRadMemoryHeapLevel->Release(); + spIRadMemoryHeapLevel = NULL; + spIRadMemoryHeapSwapA->Release(); + spIRadMemoryHeapSwapA = NULL; + spIRadMemoryHeapSwapB->Release(); + spIRadMemoryHeapSwapB = NULL; +#ifndef RAD_RELEASE + spIRadMemoryHeapDebug->Release(); + spIRadMemoryHeapDebug = NULL; +#endif // RAD_RELEASE +*/ + + // + // Shutdown the systems in the reverse order. + // + ::radDriveUnmount(); + ::radFileTerminate(); + ::radDbgWatchTerminate(); + if( CommandLineOptions::Get( CLO_MEMORY_MONITOR) ) + { + ::radMemoryMonitorTerminate(); + } + ::radDbgComTargetTerminate(); + ::radTimeTerminate(); + ::radPlatformTerminate(); + ::radMemoryTerminate(); + ::radThreadTerminate(); + ::radMovieTerminate2( ); +} + + +//============================================================================== +// PS2Platform::InitializePure3D +//============================================================================== +// Description: Get Pure3D ready to go. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void PS2Platform::InitializePure3D() +{ +MEMTRACK_PUSH_GROUP( "PS2Platform" ); +// p3d::SetMemAllocator( p3d::ALLOC_DEFAULT, GMA_PERSISTENT ); +// p3d::SetMemAllocator( p3d::ALLOC_LOADED, GMA_LEVEL ); + + // + // Initialise Pure3D platform object. + // This call differs between different platforms. The Win32 version, + // for example requires the application instance to be passed in. + // + mpPlatform = tPlatform::Create(); + rAssert( mpPlatform != NULL ); + + // + // Initialiase the Pure3D context object. + // We have to create on of these for every window, and for every PDDI + // instance we use for rendering. Since almost every application only + // uses one window and PDDI library at a time, we one need to create one + // context. + // + tContextInitData init; + + // + // These values only take effect in fullscreen mode. In windowed mode, the + // dimensions of the window define the rendering area. We'll define them + // anyway for completeness sake. + // + init.xsize = WindowSizeX; + + // + // Rendering to NTSC or PAL. + // +#ifdef PAL + init.pal = true; +#else + init.pal = false; +#endif + + //for progressive scan + if( CommandLineOptions::Get( CLO_PROGRESSIVE_SCAN ) ) + { + init.dtv480 = true; + } + + //TODO: Investigate VSync +// init.lockToVsync = true; + init.lockToVsync = false; + + // + // Create the context. + // + mpContext = mpPlatform->CreateContext( &init ); + rAssert( mpContext != NULL ); + + // + // Assign this context to the platform. + // + mpPlatform->SetActiveContext( mpContext ); + + //((pddiExtPS2Control*)p3d::pddi->GetExtension(PDDI_EXT_PS2_CONTROL))->EnableClipper(false); + //((pddiExtPS2Control*)p3d::pddi->GetExtension(PDDI_EXT_PS2_CONTROL))->ForceMFIFOSync(true); + + p3d::pddi->EnableZBuffer( true ); + + // + // This call installs chunk handlers for all the primary chunk types that + // Pure3D supports. This includes textures, materials, geometries, and the + // like. + // +// p3d::InstallDefaultLoaders(); + P3DASSERT(p3d::context); + tP3DFileHandler* p3d = new(GMA_PERSISTENT) tP3DFileHandler; + //p3d::loadManager->AddHandler(p3d, "p3d"); + p3d::context->GetLoadManager()->AddHandler(p3d, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tPNGHandler, "png"); + + if( CommandLineOptions::Get( CLO_FE_UNJOINED ) ) + { + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tBMPHandler, "bmp"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tTargaHandler, "tga"); + } + else + { + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tBMPHandler, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tPNGHandler, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tTargaHandler, "p3d"); + } + +// p3d->AddHandler(new tGeometryLoader); +// GeometryWrappedLoader* pGWL = new GeometryWrappedLoader; + GeometryWrappedLoader* pGWL = + (GeometryWrappedLoader*)GetAllWrappers()->mpLoader( AllWrappers::msGeometry ); + pGWL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pGWL ); + + StaticEntityLoader* pSEL = + (StaticEntityLoader*)GetAllWrappers()->mpLoader( AllWrappers::msStaticEntity ); + pSEL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pSEL ); + + StaticPhysLoader* pSPL = + (StaticPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msStaticPhys ); + pSPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pSPL ); + + TreeDSGLoader* pTDL = + (TreeDSGLoader*)GetAllWrappers()->mpLoader( AllWrappers::msTreeDSG ); + pTDL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pTDL ); + + FenceLoader* pFL = + (FenceLoader*)GetAllWrappers()->mpLoader( AllWrappers::msFenceEntity ); + pFL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pFL ); + + IntersectLoader* pIL = + (IntersectLoader*)GetAllWrappers()->mpLoader( AllWrappers::msIntersectDSG ); + pIL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pIL ); + + AnimCollLoader* pACL = + (AnimCollLoader*)GetAllWrappers()->mpLoader( AllWrappers::msAnimCollEntity ); + pACL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pACL ); + + AnimDSGLoader* pAnimDSGLoader = + (AnimDSGLoader*)GetAllWrappers()->mpLoader( AllWrappers::msAnimEntity ); + pAnimDSGLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimDSGLoader ); + + DynaPhysLoader* pDPL = + (DynaPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msDynaPhys ); + pDPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pDPL ); + + InstStatPhysLoader* pISPL = + (InstStatPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msInstStatPhys ); + pISPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pISPL ); + + InstStatEntityLoader* pISEL = + (InstStatEntityLoader*)GetAllWrappers()->mpLoader( AllWrappers::msInstStatEntity ); + pISEL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pISEL ); + + LocatorLoader* pLL = + (LocatorLoader*)GetAllWrappers()->mpLoader( AllWrappers::msLocator); + pLL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pLL ); + + RoadLoader* pRL = + (RoadLoader*)GetAllWrappers()->mpLoader( AllWrappers::msRoadSegment); + pRL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pRL ); + + PathLoader* pPL = + (PathLoader*)GetAllWrappers()->mpLoader( AllWrappers::msPathSegment); + pPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pPL ); + + WorldSphereLoader* pWSL = + (WorldSphereLoader*)GetAllWrappers()->mpLoader( AllWrappers::msWorldSphere); + pWSL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pWSL ); + + LensFlareLoader* pLSL = + (LensFlareLoader*)GetAllWrappers()->mpLoader( AllWrappers::msLensFlare); + pLSL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pLSL ); + + BillboardWrappedLoader* pBWL = + (BillboardWrappedLoader*)GetAllWrappers()->mpLoader( AllWrappers::msBillboard); + pBWL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pBWL ); + + InstParticleSystemLoader* pInstParticleSystemLoader = + (InstParticleSystemLoader*) GetAllWrappers()->mpLoader( AllWrappers::msInstParticleSystem); + pInstParticleSystemLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pInstParticleSystemLoader ); + + BreakableObjectLoader* pBreakableObjectLoader = + (BreakableObjectLoader*) GetAllWrappers()->mpLoader( AllWrappers::msBreakableObject); + pBreakableObjectLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pBreakableObjectLoader ); + + AnimDynaPhysLoader* pAnimDynaPhysLoader = + (AnimDynaPhysLoader*) GetAllWrappers()->mpLoader( AllWrappers::msAnimDynaPhys); + pAnimDynaPhysLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimDynaPhysLoader ); + + AnimDynaPhysWrapperLoader* pAnimWrapperLoader = + (AnimDynaPhysWrapperLoader*) GetAllWrappers()->mpLoader( AllWrappers::msAnimDynaPhysWrapper); + pAnimWrapperLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimWrapperLoader ); + + p3d->AddHandler(new(GMA_PERSISTENT) tTextureLoader); + p3d->AddHandler( new(GMA_PERSISTENT) tSetLoader ); + p3d->AddHandler(new(GMA_PERSISTENT) tShaderLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tCameraLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tGameAttrLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tLightLoader); + + p3d->AddHandler(new(GMA_PERSISTENT) tLocatorLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tLightGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tImageLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tTextureFontLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tImageFontLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tSpriteLoader); + //p3d->AddHandler(new(GMA_PERSISTENT) tBillboardQuadGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tSkeletonLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tPolySkinLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tCompositeDrawableLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tAnimationLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tFrameControllerLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tMultiControllerLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tAnimatedObjectFactoryLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tAnimatedObjectLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tParticleSystemFactoryLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tParticleSystemLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tLensFlareGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) sg::Loader); + + p3d->AddHandler(new(GMA_PERSISTENT) tExpressionGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tExpressionMixerLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tExpressionLoader); + + p3d->AddHandler(new(GMA_PERSISTENT) tVertexAnimKeyLoader); + + //ATCloader + p3d->AddHandler(new(GMA_PERSISTENT) ATCLoader); + + //p3d->AddHandler(new p3d::tIgnoreLoader); + + + tSEQFileHandler* sequencerFileHandler = new(GMA_PERSISTENT) tSEQFileHandler; + p3d::loadManager->AddHandler(sequencerFileHandler, "seq"); + + // sim lib + sim::InstallSimLoaders(); + + p3d->AddHandler(new(GMA_PERSISTENT) CameraDataLoader, SRR2::ChunkID::WALKERCAM ); + p3d->AddHandler(new(GMA_PERSISTENT) CameraDataLoader, SRR2::ChunkID::FOLLOWCAM ); + p3d->AddHandler(new(GMA_PERSISTENT) IntersectionLoader); + //p3d->AddHandler(new(GMA_PERSISTENT) RoadLoader); + p3d->AddHandler(new(GMA_PERSISTENT) RoadDataSegmentLoader); + p3d->AddHandler(new(GMA_PERSISTENT) CStatePropDataLoader); +MEMTRACK_POP_GROUP("PS2Platform"); + + p3d::context->SetClearColour(tColour(0,0,0)); + p3d::pddi->Clear(PDDI_BUFFER_ALL); + p3d::context->SwapBuffers(); + p3d::pddi->Clear(PDDI_BUFFER_ALL); +} + + +//============================================================================== +// PS2Platform::ShutdownPure3D +//============================================================================== +// Description: Clean up and shut down Pure3D. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void PS2Platform::ShutdownPure3D() +{ + // + // Clean-up the Pure3D Inventory + // + p3d::inventory->RemoveAllElements(); + p3d::inventory->DeleteAllSections(); + + // + // Clean-up the space taken by the Pure 3D context. + // + if( mpContext != NULL ) + { + mpPlatform->DestroyContext( mpContext ); + mpContext = NULL; + } + + // + // Clean-up the space taken by the Pure 3D platform. + // + if( mpPlatform != NULL ) + { + tPlatform::Destroy( mpPlatform ); + mpPlatform = NULL; + } +} + +//============================================================================== +// PS2Platform::SetProgressiveMode +//============================================================================== +// Description: Reinitialize PDDI to change progressive scan mode (480p) +// +// Parameters: boolean : true means go to 480p mode +// +// Return: None. +// +//============================================================================== +void PS2Platform::SetProgressiveMode( bool progressiveScan ) +{ + pddiDisplayInit init; + + init.xsize = WindowSizeX; + + // + // Rendering to NTSC or PAL. + // +#ifdef PAL + init.pal = true; +#else + init.pal = false; +#endif + + init.dtv480 = progressiveScan; + + init.lockToVsync = false; + + p3d::display->InitDisplay(&init); + + mProgressiveMode = progressiveScan; +} + +//============================================================================== +// PS2Platform::CheckForStartupButtons +//============================================================================== + +bool PS2Platform::CheckForStartupButtons( void ) +{ + unsigned char buffer[ 32 ]; + bool buttonsPushed = false; + + for ( int p = 0; p < 2; p++ ) + { + for ( int s = 0; s < 4; s++ ) + { + // spin until the system understands that there's a controller around. + int state = scePadStateExecCmd; + do + { + state = scePadGetState( p, s ); + } while( state != scePadStateDiscon && state != scePadStateFindCTP1 && + state != scePadStateStable && state != scePadStateError ); + + // + // Now we have a controller. + // + if ( state == scePadStateFindCTP1 || state == scePadStateStable ) + { + if ( scePadRead( p, s, buffer ) != 0 && // read success + buffer[ 0 ] == 0 && // buffer fill success + ( buffer[ 3 ] & (1<<6) ) == 0 && // X pushed + ( buffer [ 3 ] & (1<<4) ) == 0 // triangle pushed + ) + { + buttonsPushed = true; + break; + } + } + } + if ( buttonsPushed ) break; + } + + return buttonsPushed; +} + +void PS2Platform::OnControllerError(const char *msg) +{ + bool inFrame = p3d::context->InFrame(); + + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( Error, msg, 0.7f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = CTL_ERROR; + mPauseForError = true; + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->Pause( ); + } + else + { + GetSoundManager()->StopForMovie(); + } +} + +//============================================================================= +// PS2Platform::OnDriveError +//============================================================================= +// Description: Comment +// +// Parameters: ( radFileError error, const char* pDriveName, void* pUserData ) +// +// Return: bool +// +//============================================================================= +bool PS2Platform::OnDriveError( radFileError error, const char* pDriveName, void* pUserData ) +{ + bool inFrame = p3d::context->InFrame(); + + const int NUM_RADFILE_ERRORS = 13; + unsigned int errorIndex = error; + +#ifdef PAL + switch( CGuiTextBible::GetCurrentLanguage() ) + { + case Scrooby::XL_FRENCH: + { + errorIndex += 1 * NUM_RADFILE_ERRORS; + + break; + } + case Scrooby::XL_GERMAN: + { + errorIndex += 2 * NUM_RADFILE_ERRORS; + + break; + } + case Scrooby::XL_SPANISH: + { + errorIndex += 3 * NUM_RADFILE_ERRORS; + + break; + } + default: + { + break; + } + } +#endif // PAL + + rAssert( errorIndex < sizeof( ERROR_STRINGS ) / sizeof( ERROR_STRINGS[ 0 ] ) ); + + switch ( error ) + { + case Success: + { + if ( mErrorState != NONE ) + { + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( FadeToBlack ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = NONE; + mPauseForError = false; + } + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->UnPause( ); + } + else + { + GetSoundManager()->ResumeAfterMovie(); + } + return true; + break; + } + case FileNotFound: + { + if ( CommandLineOptions::Get( CLO_FILE_NOT_FOUND ) ) + { + rAssert( pUserData != NULL ); + + radFileRequest* request = static_cast<radFileRequest*>( pUserData ); + const char* fileName = request->GetFilename(); + + //Get rid of the slashes. + unsigned int i; + unsigned int lastIndex = 0; + for ( i = 0; i < strlen( fileName ); ++i ) + { + if ( fileName[ i ] == '\\' ) + { + lastIndex = i; + } + } + + unsigned int adjustedIndex = lastIndex == 0 ? lastIndex : lastIndex + 1; + + char adjustedName[32]; + strncpy( adjustedName, &fileName[adjustedIndex], ( strlen( fileName ) - lastIndex ) ); + adjustedName[ strlen( fileName ) - lastIndex ] = '\0'; + + char errorString[256]; + sprintf( errorString, "%s:\n%s", ERROR_STRINGS[errorIndex], adjustedName ); + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( Error, errorString, 1.0f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = P_ERROR; + mPauseForError = true; + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->Pause( ); + } + else + { + GetSoundManager()->StopForMovie(); + } + return true; + } + else + { + //Hmmm... This could be a hack. + error = WrongMedia; + //Fall through. + } + } + case ShellOpen: + case WrongMedia: + case NoMedia: + case HardwareFailure: + { + //This could be the wrong disc. + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( Error, ERROR_STRINGS[errorIndex], 1.0f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = P_ERROR; + mPauseForError = true; + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->Pause( ); + } + else + { + GetSoundManager()->StopForMovie(); + } + return true; + } + default: + { + //Others are not supported. + rAssert( false ); + } + } + + return false; +} + + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** + +//============================================================================== +// PS2Platform::PS2Platform +//============================================================================== +// Description: Constructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +PS2Platform::PS2Platform() : + mpPlatform( NULL ), + mpContext( NULL ) +{ +} + + +//============================================================================== +// PS2Platform::~PS2Platform +//============================================================================== +// Description: Destructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +PS2Platform::~PS2Platform() +{ +} + + +//============================================================================== +// PS2Platform::EnableSnProfiler +//============================================================================== +// Description: Prepare the SN function level profiler. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void PS2Platform::EnableSnProfiler() +{ +#ifndef RAD_RELEASE +#ifndef RAD_MW + + // + // Quadword aligned, can be 2K to 64K bytes + // + static u_long128 profdata[2048]; + + snDebugInit(); + + sceSifInitRpc( 0 ); + + // + // Load the SNProfile module + // + if( sceSifLoadModule( "host0:/usr/local/sce/iop/modules/SNProfil.irx", 0, NULL ) < 0 ) + { + rDebugString( "Can't load SNProfil.IRX module\n" ); + exit( -1 ); + } + + // + // Initialize the profiler + // + if( snProfInit( _4KHZ, profdata, sizeof(profdata) ) != 0 ) + { + // + // See SN_PRF... in LIBSN.H + // + rDebugString( "SN Profiler init failed\n" ); + } + + snProfSetFlagValue( 1 ); + +#endif +#endif +} + +#ifndef FINAL + +// +// Exception-handling functions. These functions are set to be called +// whenever the PS2 crashes on a variety of conditions. +// + +void PS2Platform::handleTLBChange( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "TLB Change Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleTLBLoadMismatch( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "TLB Load Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleTLBStoreMismatch( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "TLB Store Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleAddressLoadError( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "Address Load Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleAddressStoreError( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "Address Store Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleBusFetchError( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "Bus Fetch Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleBusDataError( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "Bus Data Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleReservedInstruction( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "Reserved Instruction Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleCoprocessor( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "Coprocessor Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleOverflow( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "Overflow Error", stat, cause, epc, bva, bpa, registers ); +} + +void PS2Platform::handleTrap( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + dumpExceptionData( "Trap Error", stat, cause, epc, bva, bpa, registers ); +} + +//============================================================================= +// PS2Platform::dumpExceptionData +//============================================================================= +// Description: Dump the parameters from an exception handler to the screen +// +// Parameters: exceptionName - string describing the exception that was set +// stat - status register +// cause - cause register? (I should look this up) +// epc - program counter +// bva - address involved in bad access or branch +// bpa - address involved in bus error +// registers - array of MIPS general-purpose registers +// +// Return: Why? +// +//============================================================================== +void PS2Platform::dumpExceptionData( const char* exceptionName, + unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ) +{ + IRadTextDisplay* textDisplay; + char buffer[50]; + int i; + unsigned int reg1, reg2; + +#ifdef RAD_PS2 + // + // Need to shut down the MFIFO for this to work properly + // + ((pddiExtPS2Control*)p3d::pddi->GetExtension(PDDI_EXT_PS2_CONTROL))->MFIFOEnable( false ); +#endif + + ::radTextDisplayGet( &textDisplay, GMA_DEFAULT ); + + textDisplay->SetBackgroundColor( 0 ); + textDisplay->SetTextColor( 0xffffffff ); + textDisplay->Clear(); + textDisplay->TextOutAt( exceptionName, 15, 1 ); + sprintf( buffer, "PC: 0x%x Address Value: 0x%x", epc, bva ); + textDisplay->TextOutAt( buffer, 15, 3 ); + sprintf( buffer, "stat: 0x%x cause: 0x%x", stat, cause ); + textDisplay->TextOutAt( buffer, 15, 5 ); + sprintf( buffer, "Bus error address: 0x%x", bpa ); + textDisplay->TextOutAt( buffer, 15, 7 ); + + // + // GPR printout + // + for( i = 0; i < 16; i++ ) + { + reg1 = (unsigned int)registers[i] & 0xffffffff; + reg2 = (unsigned int)registers[i+16] & 0xffffffff; + sprintf( buffer, "GPR%02d: 0x%08x GPR%02d: 0x%08x", i, reg1, i+16, reg2 ); + textDisplay->TextOutAt( buffer, 15, 9+i ); + } + + textDisplay->TextOutAt( ":-(", 6, 13 ); + + if ( CommandLineOptions::Get( CLO_DEMO_TEST ) || + GetCheatInputSystem()->IsCheatEnabled( CHEAT_ID_DEMO_TEST ) ) + { + char buffy[32]; + sprintf( buffy, "Demo Count: %d", GetGame()->GetDemoCount() ); + textDisplay->TextOutAt( buffy, 6, 15 ); + + unsigned int time = GetGame()->GetTime(); + unsigned int hours = time / 3600000; + unsigned int deltaTime = time % 3600000; + + unsigned int minutes = deltaTime / 60000; + deltaTime = deltaTime % 60000; + + unsigned int seconds = deltaTime / 1000; + deltaTime = deltaTime % 1000; + sprintf( buffy, "Time: %d:%d:%d.%d", hours, minutes, seconds, deltaTime ); + textDisplay->TextOutAt( buffy, 6, 17 ); + + if ( GetGameplayManager() ) + { + sprintf( buffy, "Level %d", GetGameplayManager()->GetCurrentLevelIndex() ); + textDisplay->TextOutAt( buffy, 6, 19 ); + } + } + + textDisplay->SwapBuffers(); + textDisplay->Release(); + + rReleaseBreak(); +} + +void Simpsons2MFIFODisable() +{ +#ifdef RAD_PS2 + ((pddiExtPS2Control*)p3d::pddi->GetExtension(PDDI_EXT_PS2_CONTROL))->MFIFOEnable( false ); +#endif +} + +#endif diff --git a/game/code/main/ps2platform.h b/game/code/main/ps2platform.h new file mode 100644 index 0000000..5b5df10 --- /dev/null +++ b/game/code/main/ps2platform.h @@ -0,0 +1,207 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: ps2platform.h +// +// Description: Abstracts the differences for setting up and shutting down +// the different platforms. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +#ifndef PS2PLATFORM_H +#define PS2PLATFORM_H + +//======================================== +// Nested Includes +//======================================== +#include <main/platform.h> // base class + +//======================================== +// Forward References +//======================================== +struct IRadCementLibrary; +struct IRadMemoryHeap; +class tPlatform; +class tContext; + +// +// Global function for disabling MFIFO, which we do to use radTextDisplay. +// I'm making it global because this also gets used in the heart of radSound, +// and I don't want to drag P3D dependencies in there. It's icky, and I'm +// going to ask for a fix to radTextDisplay so we don't need to do this anymore. +// +void Simpsons2MFIFODisable(); + +//============================================================================= +// +// Synopsis: Provides abstraction for setting up and closing down the PS2. +// +//============================================================================= +class PS2Platform : public Platform +{ + public: + + // Static Methods for accessing this singleton. + static PS2Platform* CreateInstance(); + static PS2Platform* GetInstance(); + static void DestroyInstance(); + + // Had to workaround our nice clean design cause FTech must be init'ed + // before anything else is done. + static void InitializeFoundation(); + static void InitializeMemory(); + + // Implement Platform interface. + virtual void InitializePlatform(); + virtual void ShutdownPlatform(); + + virtual void LaunchDashboard(); + virtual void ResetMachine(); + virtual void DisplaySplashScreen( SplashScreen screenID, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ); + + virtual void DisplaySplashScreen( const char* textureName, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ); + + virtual bool OnDriveError( radFileError error, const char* pDriveName, void* pUserData ); + virtual void OnControllerError(const char *msg); + + void SetProgressiveMode( bool progressiveScan ); + bool GetProgressiveMode() { return mProgressiveMode; } + + bool CheckForStartupButtons( void ); + + protected: + + virtual void InitializeFoundationDrive(); + virtual void ShutdownFoundation(); + + virtual void InitializePure3D(); + virtual void ShutdownPure3D(); + + private: + + // Constructors, Destructors, and Operators + PS2Platform(); + virtual ~PS2Platform(); + + // Unused Constructors, Destructors, and Operators + PS2Platform( const PS2Platform& aPlatform ); + PS2Platform& operator=( const PS2Platform& aPlatform ); + + // PS2 specific methods + void EnableSnProfiler(); + + // Crash printout routines +#ifndef FINAL + static void dumpExceptionData( const char* exceptionName, + unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleTLBChange( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleTLBLoadMismatch( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleTLBStoreMismatch( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleAddressLoadError( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleAddressStoreError( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleBusFetchError( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleBusDataError( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleReservedInstruction( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleCoprocessor( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleOverflow( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); + + static void handleTrap( unsigned int stat, + unsigned int cause, + unsigned int epc, + unsigned int bva, + unsigned int bpa, + u_long128* registers ); +#endif + + // Pointer to the one and only instance of this singleton. + static PS2Platform* spInstance; + + // Pure 3D attributes + tPlatform* mpPlatform; + tContext* mpContext; + + bool mProgressiveMode; + + static IRadCementLibrary* s_MainCement; +}; + +#endif // PS2PLATFORM_H diff --git a/game/code/main/singletons.cpp b/game/code/main/singletons.cpp new file mode 100644 index 0000000..ce6cb86 --- /dev/null +++ b/game/code/main/singletons.cpp @@ -0,0 +1,333 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: singletons.cpp +// +// Description: Create and destroy all our singletons here. +// +// History: + Created -- Darwin Chau +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +#include <raddebug.hpp> + +//======================================== +// Project Includes +//======================================== +#include <main/singletons.h> + +#include <ai/actionbuttonmanager.h> +#include <atc/atcmanager.h> +#include <camera/supercammanager.h> +#include <cards/cardgallery.h> +#include <cheats/cheatinputsystem.h> +#include <data/gamedatamanager.h> +#include <console/console.h> +#include <debug/debuginfo.h> +#include <debug/profiler.h> +#include <events/eventmanager.h> +#include <input/inputmanager.h> +#include <interiors/interiormanager.h> +#include <loading/loadingmanager.h> +#include <main/commandlineoptions.h> +#include <meta/triggervolumetracker.h> +#include <mission/missionmanager.h> +#include <mission/charactersheet/charactersheetmanager.h> +#include <mission/rewards/rewardsmanager.h> +#include <memory/srrmemory.h> +#include <mission/missionscriptloader.h> +#include <worldsim/Skidmarks/skidmarkmanager.h> +#include <presentation/mouthflapper.h> +#include <presentation/presentation.h> +#include <presentation/tutorialmanager.h> +#include <presentation/gui/guisystem.h> +#include <render/RenderFlow/renderflow.h> +#include <sound/soundmanager.h> +#include <worldsim/avatarmanager.h> +#include <worldsim/character/charactermanager.h> +#include <worldsim/worldphysicsmanager.h> +#include <worldsim/vehiclecentral.h> +#include <worldsim/coins/coinmanager.h> +#include <worldsim/coins/sparkle.h> +#include <worldsim/hitnrunmanager.h> +#include <ai/actor/actormanager.h> +#include <data/persistentworldmanager.h> +#include <worldsim/character/footprint/footprintmanager.h> +#include <memory/propstats.h> +#include <simcommon/simenvironment.hpp> + +#ifdef RAD_WIN32 +#include <data/config/gameconfigmanager.h> +#include <input/MouseCursor.h> +#endif + +//============================================================================= +// Function: void AddVariablesToWatcher +//============================================================================= +// +// Description: Adds lots of global variables to the watcher +// +// Parameters: None +// +// Returns: None +// +//============================================================================= +#ifdef DEBUGWATCH +void AddVariablesToWatcher() +{ + MouthFlapper::AddVariablesToWatcher(); +} +#endif + +//============================================================================= +// Function: CreateSingletons +//============================================================================= +// +// Description: Construct all the singletons +// +// Parameters: None +// +// Returns: None +// +//============================================================================= +void CreateSingletons() +{ + //CREATE_MEMORYTRACKER(); + + CREATE_DEBUGINFO(); + + MEMTRACK_PUSH_GROUP( "Singletons" ); + + GameDataManager* pGameDataManager = GameDataManager::CreateInstance(); + rAssert( pGameDataManager != NULL ); + +#ifdef RAD_WIN32 + GameConfigManager* pGameConfigManager = GameConfigManager::CreateInstance(); + rAssert( pGameConfigManager != NULL ); +#endif + + EventManager* pEventManager = EventManager::CreateInstance(); + rAssert( pEventManager != NULL ); + + LoadingManager* pLoadingManager = LoadingManager::CreateInstance(); + rAssert( pLoadingManager != NULL ); + + InputManager* pInputManager = InputManager::CreateInstance(); + rAssert( pInputManager != NULL ); + + SkidmarkManager* pSkidmarkManager = SkidmarkManager::CreateInstance(); + rAssert( pSkidmarkManager != NULL ); + + //AttributeTableChunk Manager, has the the info of physprops in a table + ATCManager * pATCManager =ATCManager::CreateInstance(); + rAssert(pATCManager != NULL); + + CardGallery* pCardCallery = CardGallery::CreateInstance(); + rAssert( pCardCallery != NULL ); + + //CharacterSheetManager + CharacterSheetManager* pCharacterSheetManager = CharacterSheetManager::CreateInstance(); + rAssert(pCharacterSheetManager != NULL); + + //RewardsManager + RewardsManager* pRewardsManager = RewardsManager::CreateInstance(); + rAssert(pRewardsManager); + + MEMTRACK_PUSH_GROUP( "Console" ); + + // must be around before VehicleCentral tries to tie in some shit + // ...MissionScriptLoader too + Console* pConsole = Console::CreateInstance(); + rAssert( pConsole != NULL ); + + MEMTRACK_POP_GROUP( "Console" ); + + + + // must be done before init'ing worldphysicsmanager + VehicleCentral* pVC = VehicleCentral::CreateInstance(); + rAssert(pVC != 0); + + sim::SimUnits::Initialize(); + WorldPhysicsManager* pWPM = WorldPhysicsManager::CreateInstance(); + rAssert(pWPM != 0); + + CREATE_PROFILER(); + + PresentationManager* pPM = PresentationManager::CreateInstance(); + rAssert( pPM != NULL ); + + CGuiSystem* pGuiSystem = CGuiSystem::CreateInstance(); + rAssert( pGuiSystem != NULL ); + + SoundManager* pSoundManager = + SoundManager::CreateInstance( CommandLineOptions::Get( CLO_MUTE ), + CommandLineOptions::Get( CLO_NO_MUSIC ), + CommandLineOptions::Get( CLO_NO_EFFECTS ), + CommandLineOptions::Get( CLO_NO_DIALOG ) ); + rAssert( pSoundManager != NULL ); + + MissionManager* pMM = MissionManager::CreateInstance(); + rAssert( pMM != NULL ); + + /* + HeadToHeadManager* pH2HM = HeadToHeadManager::CreateInstance(); + rAssert( pH2HM != NULL ); + */ + + MissionScriptLoader* pMSL = MissionScriptLoader::CreateInstance(); + rAssert( pMSL != NULL ); + + CharacterManager* pCM = CharacterManager::CreateInstance(); + rAssert( pCM != NULL ); + + AvatarManager* pAM = AvatarManager::CreateInstance(); + rAssert( pAM != (AvatarManager*)0 ); + + ActionButtonManager* pABM = ActionButtonManager::CreateInstance(); + rAssert( pABM != (ActionButtonManager*)0 ); + + SuperCamManager* pSCM = SuperCamManager::CreateInstance(); + rAssert( pSCM != NULL ); + + TriggerVolumeTracker::CreateInstance(); + + InteriorManager* pInteriorManager = InteriorManager::CreateInstance(); + rAssert( pInteriorManager != NULL ); + + CheatInputSystem* pCheatInputSystem = CheatInputSystem::CreateInstance(); + rAssert( pCheatInputSystem != NULL ); + + TutorialManager* pTutorialManager = TutorialManager::CreateInstance(); + rAssert( pTutorialManager != NULL ); + + ActorManager* pActorManager = ActorManager::CreateInstance(); + rAssert( pActorManager != NULL ); + + PersistentWorldManager* pPWManager = PersistentWorldManager::CreateInstance(); + rAssert( pPWManager ); + + FootprintManager* pFootprintManager = FootprintManager::CreateInstance(); + rAssert( pFootprintManager != NULL ); + + CoinManager* pCoinManager = CoinManager::CreateInstance(); + rAssert( pCoinManager ); + Sparkle* pSparkle = Sparkle::CreateInstance(); + rAssert( pSparkle ); + + HitnRunManager* pHitnRunManager = HitnRunManager::CreateInstance(); + rAssert( pHitnRunManager ); + + // + // Create The RenderFlow Instance; this creates the RenderManager. + // Create it under singletons.cpp because of co-dependency between singletons. + // + RenderFlow* pRenderFlow = RenderFlow::CreateInstance(); + rAssert( pRenderFlow ); + + +#ifndef RAD_RELEASE + if( CommandLineOptions::Get( CLO_PROP_STATS ) ) + { + PropStats::EnableTracking(); + } +#endif + + MEMTRACK_POP_GROUP("Singletons"); + + AddVariablesToWatcher(); +} + + +//============================================================================= +// Function: DestroySingletons +//============================================================================= +// +// Description: Destroy all the singletons +// +// Parameters: None +// +// Returns: None +// +//============================================================================= +void DestroySingletons() +{ + InteriorManager::DestroyInstance(); + + ActionButtonManager::DestroyInstance(); + + SuperCamManager::DestroyInstance(); + + AvatarManager::DestroyInstance(); + + CharacterManager::DestroyInstance(); + + MissionScriptLoader::DestroyInstance(); + + //HeadToHeadManager::DestroyInstance(); + + MissionManager::DestroyInstance(); + + SoundManager::DestroyInstance(); + + CGuiSystem::DestroyInstance(); + + PresentationManager::DestroyInstance(); + + WorldPhysicsManager::DestroyInstance(); + + VehicleCentral::DestroyInstance(); + + Console::DestroyInstance(); + + ATCManager::DestroyInstance(); + + CharacterSheetManager::DestroyInstance(); + + RewardsManager::DestroyInstance(); + + CardGallery::DestroyInstance(); + + TutorialManager::DestroyInstance(); + + CoinManager::DestroyInstance(); + + Sparkle::DestroyInstance(); + + CheatInputSystem::DestroyInstance(); + + HitnRunManager::DestroyInstance(); + + InputManager::DestroyInstance(); + + LoadingManager::DestroyInstance(); + + SkidmarkManager::DestroyInstance(); + + FootprintManager::DestroyInstance(); + + ActorManager::DestroyInstance(); + + PersistentWorldManager::DestroyInstance(); + + TriggerVolumeTracker::DestroyInstance(); + + RenderFlow::DestroyInstance(); + + GameDataManager::DestroyInstance(); + + EventManager::DestroyInstance(); + +#ifdef RAD_WIN32 + GameConfigManager::DestroyInstance(); +#endif + + DESTROY_PROFILER(); + + DESTROY_DEBUGINFO(); + + //DESTROY_MEMORYTRACKER(); +} diff --git a/game/code/main/singletons.h b/game/code/main/singletons.h new file mode 100644 index 0000000..80b915c --- /dev/null +++ b/game/code/main/singletons.h @@ -0,0 +1,35 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: singletons.h +// +// Description: Define all our global objects here +// +// History: + Created -- Darwin Chau +// +//============================================================================= +#ifndef SINGLETONS_H_ +#define SINGLETONS_H_ +//======================================== +// System Includes +//======================================== + +//======================================== +// Project Includes +//======================================== + +//======================================== +// Forward References +//======================================== +#ifdef DEBUGWATCH + void AddVariablesToWatcher(); +#else + inline void AddVariablesToWatcher(){}; +#endif //DEBUGWATCH +void CreateSingletons(); +void DestroySingletons(); + +//======================================== +// Constants, Typedefs and Statics +//======================================== +#endif
\ No newline at end of file diff --git a/game/code/main/tuidunaligned.cpp b/game/code/main/tuidunaligned.cpp new file mode 100644 index 0000000..e9fdb78 --- /dev/null +++ b/game/code/main/tuidunaligned.cpp @@ -0,0 +1,266 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: tuidunaligned.cpp +// +// Description: tuids won't cause your class to get overly padded +// +// History: +// +//============================================================================= + +//======================================== +// System Includes +//======================================== + +//======================================== +// Project Includes +//======================================== +#include <main/tuidunaligned.h> + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================== +// tUidUnaligned::tUidUnaligned +//============================================================================== +// Description: constructor +// +// Parameters: none +// +// Return: none +// +// Constraints: none +// +//============================================================================== +tUidUnaligned::tUidUnaligned(): + u0( 0 ), + u1( 1 ) +{ +} + +//============================================================================== +// tUidUnaligned::tUidUnaligned +//============================================================================== +// Description: copy constructor +// +// Parameters: right - the object we're copying from +// +// Return: none +// +// Constraints: none +// +//============================================================================== +tUidUnaligned::tUidUnaligned( const tUidUnaligned& right ): + u0( right.u0 ), + u1( right.u1 ) +{ +} + +//============================================================================== +// tUidUnaligned::tUidUnaligned +//============================================================================== +// Description: conversion constructor from 64 bit integers - these are meant +// to be interchangable +// +// Parameters: right - the object we're copying from +// +// Return: none +// +// Constraints: none +// +//============================================================================== +//tUidUnaligned::tUidUnaligned( const radInt64 right ) +//{ +// const unsigned int* r = reinterpret_cast< const unsigned int* >( &right ); +// u0 = r[ 0 ]; +// u1 = r[ 1 ]; +//} + +//============================================================================= +// tUidUnaligned::operator radInt64 +//============================================================================= +// Description: conversion operator to 64 bit ints +// +// Parameters: none +// +// Return: none +// +// Constraints: none +// +//============================================================================= +//tUidUnaligned::operator radInt64() +//{ +// radInt64 returnMe; +// unsigned int* r = reinterpret_cast< unsigned int* >( &returnMe ); +// r[ 0 ] = u0; +// r[ 1 ] = u1; +// return returnMe; +//} + +//============================================================================= +// tUidUnaligned::operator != +//============================================================================= +// Description: inequality operator +// +// Parameters: right - are we equal to this? +// +// Return: none +// +// Constraints: none +// +//============================================================================= +bool tUidUnaligned::operator !=( const tUidUnaligned right ) const +{ + return ! operator==( right ); +} + +//============================================================================= +// tUidUnaligned::operator != +//============================================================================= +// Description: equality operator +// +// Parameters: right - are we equal to this? +// +// Return: none +// +// Constraints: none +// +//============================================================================= +bool tUidUnaligned::operator ==( const tUidUnaligned right ) const +{ + bool returnMe = ( ( u0 == right.u0 ) && ( u1 == right.u1 ) ); + return returnMe; +} + +//============================================================================= +// tUidUnaligned::operator < +//============================================================================= +// Description: less than operator +// +// Parameters: right - are we less than this? +// +// Return: none +// +// Constraints: none +// +//============================================================================= +bool tUidUnaligned::operator <( const tUidUnaligned right ) const +{ + radInt64 thisOne; + unsigned int* t = reinterpret_cast< unsigned int* >( &thisOne ); + t[ 0 ] = u0; + t[ 1 ] = u1; + radInt64 rightOne; + unsigned int* r = reinterpret_cast< unsigned int* >( &rightOne ); + r[ 0 ] = right.u0; + r[ 1 ] = right.u1; + return thisOne < rightOne; +} + +//============================================================================= +// tUidUnaligned::operator = +//============================================================================= +// Description: assignment operator +// +// Parameters: assign the two objects +// +// Return: none +// +// Constraints: none +// +//============================================================================= +//tUidUnaligned& tUidUnaligned::operator=( const tUidUnaligned& right ) +//{ +//} + +//============================================================================= +// tUidUnaligned::operator^ +//============================================================================= +// Description: less than operator +// +// Parameters: right - are we less than this? +// +// Return: none +// +// Constraints: none +// +//============================================================================= +tUidUnaligned tUidUnaligned::operator^( const tUidUnaligned right ) const +{ + radInt64 thisOne; + unsigned int* t = reinterpret_cast< unsigned int* >( &thisOne ); + t[ 0 ] = u0; + t[ 1 ] = u1; + radInt64 rightOne; + unsigned int* r = reinterpret_cast< unsigned int* >( &rightOne ); + r[ 0 ] = right.u0; + r[ 1 ] = right.u1; + return thisOne ^ rightOne; +} + +//============================================================================= +// tUidUnaligned::operator *= +//============================================================================= +// Description: in place multiplication +// +// Parameters: right 8 what are we multiplying by +// +// Return: none +// +// Constraints: none +// +//============================================================================= +tUidUnaligned tUidUnaligned::operator*=( const radInt64 right ) +{ + radInt64 thisOne; + unsigned int* t = reinterpret_cast< unsigned int* >( &thisOne ); + t[ 0 ] = u0; + t[ 1 ] = u1; + thisOne *= right; + ( *this ) = thisOne; + return *this; +} + +//============================================================================= +// tUidUnaligned::operator & +//============================================================================= +// Description: and operator +// +// Parameters: right - what are we anding with +// +// Return: none +// +// Constraints: none +// +//============================================================================= +tUidUnaligned tUidUnaligned::operator&( const tUidUnaligned right ) const +{ + unsigned int r0 = u0 & right.u0; + unsigned int r1 = u1 & right.u1; + tUidUnaligned returnMe; + returnMe.u0 = r0; + returnMe.u1 = r1; + return returnMe; +} + + +tUidUnaligned tUidUnaligned::operator >>( const int bits ) const +{ + radInt64 returnMe; + unsigned int* t = reinterpret_cast< unsigned int* >( &returnMe ); + t[ 0 ] = u0; + t[ 1 ] = u1; + returnMe = returnMe >> bits; + return returnMe; +} diff --git a/game/code/main/tuidunaligned.h b/game/code/main/tuidunaligned.h new file mode 100644 index 0000000..ea39437 --- /dev/null +++ b/game/code/main/tuidunaligned.h @@ -0,0 +1,79 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: game.h +// +// Description: The game loop +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +#ifndef TUIDUNALIGNED_H +#define TUIDUNALIGNED_H + +//======================================== +// Forward References +//======================================== + +// +// This is a 64 bit number +// +#ifdef RAD_PS2 + typedef unsigned long radInt64; +#elif defined( RAD_WIN32 ) || defined ( RAD_XBOX ) + typedef unsigned _int64 radInt64; +#elif defined(RAD_GAMECUBE) + typedef unsigned long long radInt64; +#else + #error 'FTech requires definition of RAD_GAMECUBE, RAD_PS2, RAD_XBOX, or RAD_WIN32' +#endif + + +//============================================================================= +// +// Synopsis: tUidUnaligned +// +//============================================================================= +class tUidUnaligned +{ +public: + tUidUnaligned(); + tUidUnaligned( const tUidUnaligned& right ); + tUidUnaligned( const radInt64 right ) + { + const unsigned int* r = reinterpret_cast< const unsigned int* >( &right ); + u0 = r[ 0 ]; + u1 = r[ 1 ]; + } + operator radInt64() + { + radInt64 returnMe; + unsigned int* r = reinterpret_cast< unsigned int* >( &returnMe ); + r[ 0 ] = u0; + r[ 1 ] = u1; + return returnMe; + } + + bool operator !=( const tUidUnaligned right ) const; + bool operator ==( const tUidUnaligned right ) const; + bool operator <( const tUidUnaligned right ) const; + tUidUnaligned& operator=( const tUidUnaligned& right ) + { + u0 = right.u0; + u1 = right.u1; + return *this; + } + tUidUnaligned operator ^( const tUidUnaligned right ) const; + tUidUnaligned operator &( const tUidUnaligned right ) const; + tUidUnaligned operator *=( const radInt64 right ); + tUidUnaligned operator >>( const int bits ) const; + +protected: +private: + unsigned int u0; + unsigned int u1; +}; + +#endif // TUIDUNALIGNED_H + diff --git a/game/code/main/win32main.cpp b/game/code/main/win32main.cpp new file mode 100644 index 0000000..6c7ac62 --- /dev/null +++ b/game/code/main/win32main.cpp @@ -0,0 +1,237 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: xboxmain.cpp +// +// Description: This file contains the main enrty point to the game. +// +// History: + Based on xbox main and winmain from squidney +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +// Standard Library +#include <string.h> +// Foundation Tech +#include <raddebug.hpp> +#include <radobject.hpp> +// file reading before radtech +#include <stdio.h> + +//======================================== +// Project Includes +//======================================== +#include <main/game.h> +#include <main/win32platform.h> +#include <main/singletons.h> +#include <main/commandlineoptions.h> +#include <memory/memoryutilities.h> +#include <memory/srrmemory.h> + +//======================================== +// Forward Declarations +//======================================== +static void ProcessCommandLineArguments( LPSTR lpCmdLine ); + +static void ProcessCommandLineArgumentsFromFile(); + + +//============================================================================= +// Function: WinMain +//============================================================================= +// +// Description: Main Windows entry point. +// +// Parameters: win32 parameters +// +// Returns: win32 return. +// +//============================================================================= +int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) +{ + // + // Pick out and store command line settings. + // + CommandLineOptions::InitDefaults(); + ProcessCommandLineArguments( lpCmdLine ); + ProcessCommandLineArgumentsFromFile(); + + // + // Have to get FTech setup first so that we can use all the memory services. + // The initialize window call will fail if another Simpsons window exists. In + // this case, we exit. + // + if( !Win32Platform::InitializeWindow( hInstance ) ) + { + return 0; + } + Win32Platform::InitializeFoundation(); + + srand (Game::GetRandomSeed ()); + + + // Now disable the default heap + // +#ifndef RAD_RELEASE + tName::SetAllocator (GMA_DEBUG); + + //g_HeapActivityTracker.EnableHeapAllocs (GMA_DEFAULT, false); + //g_HeapActivityTracker.EnableHeapFrees (GMA_DEFAULT, false); +#endif + + HeapMgr()->PushHeap (GMA_PERSISTENT); + + // + // Instantiate all the singletons before doing anything else. + // + CreateSingletons(); + + // + // Construct the platform object. + // + Win32Platform* pPlatform = Win32Platform::CreateInstance( hInstance, hPrevInstance, lpCmdLine, nCmdShow ); + rAssert( pPlatform != NULL ); + + // + // Create the game object. + // + Game* pGame = Game::CreateInstance( pPlatform ); + rAssert( pGame != NULL ); + + + // + // Initialize the game. + // + pGame->Initialize(); + + HeapMgr()->PopHeap (GMA_PERSISTENT); + + // + // Run it! Control will not return from here until the game is stopped. + // + pGame->Run(); + + // + // Terminate the game (this frees all resources allocated by the game). + // + pGame->Terminate(); + + // + // Dump all the singletons. + // + DestroySingletons(); + + // + // Destroy the game object. + // + Game::DestroyInstance(); + + // + // Shutdown the platform. + // + pPlatform->ShutdownPlatform(); + + // + // Destroy the game and platform (do it in this order in case the game's + // destructor references the platform. + // + Win32Platform::DestroyInstance(); + + // As a last thing, shut down the memory. + Win32Platform::ShutdownMemory(); + + // Re-enable the default heap + // +#ifndef RAD_RELEASE + tName::SetAllocator (RADMEMORY_ALLOC_DEFAULT); +#endif + + // + // Pass any error codes back to the operating system. + // + return 0; +} + + +//============================================================================= +// Function: ProcessCommandLineArguments +//============================================================================= +// +// Description: Pick out the command line options and store them. +// +// Parameters: None. +// +// Returns: None. +// +//============================================================================= +void ProcessCommandLineArguments( LPSTR lpCmdLine ) +{ + char* argument; + argument = strtok( lpCmdLine, " " ); + + rDebugPrintf( "*************************************************************************\n" ); + rDebugPrintf( "Command Line Args:\n" ); + + // + // Pick out all the command line options and store them in GameDB. + // Also dump them to the output for handy dandy viewing. + // + int i = 0; + while( NULL != argument ) + { + rDebugPrintf( "arg%d: %s\n", i++, argument ); + + CommandLineOptions::HandleOption( argument ); + + argument = strtok( NULL, " " ); + } + + if( !CommandLineOptions::Get( CLO_ART_STATS ) ) + { + //CommandLineOptions::HandleOption( "noheaps" ); + } + + rDebugPrintf( "*************************************************************************\n" ); +} + + + +void ProcessCommandLineArgumentsFromFile() +{ +#ifndef FINAL + + //Chuck: looking for additional command line args being passed in from a file + //its for QA testing etc. + + FILE* pfile = fopen( "command.txt", "r" ); + + if (pfile != NULL) + { + int ret = fseek( pfile, 0, SEEK_END ); + rAssert( ret == 0 ); + + int len = ftell( pfile ); + rAssertMsg( len < 256, "Command line file too large to process." ); + + rewind( pfile ); + + if( len > 0 && len < 256 ) + { + char commandlinestring[256] = {0}; + + fgets( commandlinestring, 256, pfile ); + + char* argument = strtok(commandlinestring," "); + while (argument != NULL) + { + CommandLineOptions::HandleOption(argument); + argument=strtok(NULL," "); + } + } + + fclose( pfile ); + } +#endif //FINAL +} //end of Function diff --git a/game/code/main/win32platform.cpp b/game/code/main/win32platform.cpp new file mode 100644 index 0000000..ed88d08 --- /dev/null +++ b/game/code/main/win32platform.cpp @@ -0,0 +1,2286 @@ +//=========================================================================== +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// Component: Win32Platform +// +// Description: Abstracts the differences for setting up and shutting down +// the different platforms. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//=========================================================================== + +//======================================== +// System Includes +//======================================== +// Standard Lib +#include <stdlib.h> +#include <string.h> +// Pure 3D +#include <p3d/anim/compositedrawable.hpp> +#include <p3d/anim/expression.hpp> +#include <p3d/anim/multicontroller.hpp> +#include <p3d/anim/polyskin.hpp> +#include <p3d/anim/sequencer.hpp> +#include <p3d/anim/skeleton.hpp> +#include <p3d/camera.hpp> +#include <p3d/gameattr.hpp> +#include <p3d/image.hpp> +#include <p3d/imagefont.hpp> +#include <p3d/light.hpp> +#include <p3d/locator.hpp> +#include <p3d/platform.hpp> +#include <p3d/scenegraph/scenegraph.hpp> +#include <p3d/sprite.hpp> +#include <p3d/utility.hpp> +#include <p3d/texture.hpp> +#include <p3d/file.hpp> +#include <p3d/shader.hpp> +#include <p3d/matrixstack.hpp> +#include <p3d/memory.hpp> +#include <p3d/bmp.hpp> +#include <p3d/png.hpp> +#include <p3d/targa.hpp> +#include <p3d/font.hpp> +#include <p3d/texturefont.hpp> +#include <p3d/unicode.hpp> +// Pure 3D: Loader-specific +#include <render/Loaders/GeometryWrappedLoader.h> +#include <render/Loaders/StaticEntityLoader.h> +#include <render/Loaders/StaticPhysLoader.h> +#include <render/Loaders/TreeDSGLoader.h> +#include <render/Loaders/FenceLoader.h> +#include <render/Loaders/IntersectLoader.h> +#include <render/Loaders/AnimCollLoader.h> +#include <render/Loaders/AnimDSGLoader.h> +#include <render/Loaders/DynaPhysLoader.h> +#include <render/Loaders/InstStatPhysLoader.h> +#include <render/Loaders/InstStatEntityLoader.h> +#include <render/Loaders/WorldSphereLoader.h> +#include <loading/roaddatasegmentloader.h> +#include <render/Loaders/BillboardWrappedLoader.h> +#include <render/Loaders/instparticlesystemloader.h> +#include <render/Loaders/breakableobjectloader.h> +#include <render/Loaders/AnimDynaPhysLoader.h> +#include <render/Loaders/lensflareloader.h> +#include <p3d/shadow.hpp> +#include <p3d/anim/animatedobject.hpp> +#include <p3d/effects/particleloader.hpp> +#include <p3d/effects/opticloader.hpp> +#include <p3d/anim/vertexanimkey.hpp> +#include <stateprop/statepropdata.hpp> + +// Foundation Tech +#include <raddebug.hpp> +#include <radthread.hpp> +#include <radplatform.hpp> +#include <radtime.hpp> +#include <radmemorymonitor.hpp> +#include <raddebugcommunication.hpp> +#include <raddebugwatch.hpp> +#include <radfile.hpp> +#include <radmovie2.hpp> + +//This is so we can get the name of the file that's failing. +#include <../src/radfile/common/requests.hpp> + +// sim - for InstallSimLoaders +#include <simcommon/simutility.hpp> + +//======================================== +// Project Includes +//======================================== +#include <input/inputmanager.h> +#include <main/win32platform.h> +#include <main/commandlineoptions.h> +#include <main/game.h> +#include <render/RenderManager/RenderManager.h> +#include <render/RenderFlow/renderflow.h> +#include <render/Loaders/AllWrappers.h> +#include <memory/srrmemory.h> + +#include <loading/locatorloader.h> +#include <loading/cameradataloader.h> +#include <loading/roadloader.h> +#include <loading/pathloader.h> +#include <loading/intersectionloader.h> +#include <loading/roaddatasegmentloader.h> +#include <atc/atcloader.h> +#include <data/gamedatamanager.h> +#include <data/config/gameconfigmanager.h> +#include <debug/debuginfo.h> +#include <constants/srrchunks.h> +#include <gameflow/gameflow.h> +#include <sound/soundmanager.h> +#include <presentation/presentation.h> +#include <presentation/gui/guitextbible.h> +#include <cheats/cheatinputsystem.h> +#include <mission/gameplaymanager.h> + + + + +#include <radload/radload.hpp> + +#include <main/errorswin32.h> + +#define WIN32_SECTION "WIN32_SECTION" +#define TIMER_LEAVE 1 + +//#define PRINT_WINMESSAGES + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + +// Static pointer to instance of singleton. +Win32Platform* Win32Platform::spInstance = NULL; + +// Other static members. +HINSTANCE Win32Platform::mhInstance = NULL; +HWND Win32Platform::mhWnd = NULL; +HANDLE Win32Platform::mhMutex = NULL; +bool Win32Platform::mShowCursor = true; + +//The Adlib font. <sigh> +unsigned char gFont[] = +#include <font/defaultfont.h> + +// +// Define the starting resolution. +// +static const Win32Platform::Resolution StartingResolution = Win32Platform::Res_800x600; +static const int StartingBPP = 32; + +// This specifies the PDDI DLL to use. We are using directx8. +#ifdef RAD_DEBUG +static const char d3dLibraryName[] = "pddidx8d.dll"; +#endif +#ifdef RAD_TUNE +static const char d3dLibraryName[] = "pddidx8t.dll"; +#endif +#ifdef RAD_RELEASE +static const char d3dLibraryName[] = "pddidx8r.dll"; +#endif + +// Name of the application. This is the string that appears in the Window's +// title bar. +static const char ApplicationName[] = "The Simpsons: Hit & Run"; + +// The window style +static const DWORD WndStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + +// The gamma of the desktop.. needed to reset it on alt-tabs. +static WORD DesktopGammaRamp[ 3 ][ 256 ] = { 0 }; + +void LoadMemP3DFile( unsigned char* buffer, unsigned int size, tEntityStore* store ) +{ + tFileMem* file = new tFileMem(buffer,size); + file->AddRef(); + file->SetFilename("memfile.p3d"); + p3d::loadManager->GetP3DHandler()->Load( file, p3d::inventory ); + file->Release(); +} + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================== +// Win32Platform::CreateInstance +//============================================================================== +// +// Description: Creates the Win32Platform. +// +// Parameters: win32 parameters. +// +// Return: Pointer to the Win32Platform. +// +// Constraints: This is a singleton so only one instance is allowed. +// +//============================================================================== +Win32Platform* Win32Platform::CreateInstance( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) +{ +MEMTRACK_PUSH_GROUP( "Win32Platform" ); + rAssert( spInstance == NULL ); + + spInstance = new(GMA_PERSISTENT) Win32Platform( hInstance, hPrevInstance, lpCmdLine, nCmdShow ); + rAssert( spInstance ); +MEMTRACK_POP_GROUP( "Win32Platform" ); + + return spInstance; +} + +//============================================================================== +// Win32Platform::GetInstance +//============================================================================== +// +// Description: - Access point for the Win32Platform singleton. +// +// Parameters: None. +// +// Return: Pointer to the Win32Platform. +// +// Constraints: This is a singleton so only one instance is allowed. +// +//============================================================================== +Win32Platform* Win32Platform::GetInstance() +{ + rAssert( spInstance != NULL ); + + return spInstance; +} + + +//============================================================================== +// Win32Platform::DestroyInstance +//============================================================================== +// +// Description: Destroy the Win32Platform. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void Win32Platform::DestroyInstance() +{ + rAssert( spInstance != NULL ); + + delete( GMA_PERSISTENT, spInstance ); + spInstance = NULL; +} + + + +//============================================================================== +// Win32Platform::InitializeWindow +//============================================================================== +// Description: Creates the window class and window instance for the application. +// We must do this before initializing the platform. +// +// Parameters: hInstance - the handle to the instance. +// +// Return: true if successful and the program can run. +// false if another simpsons window already exists and this +// instance should terminate. +// +// Constraints: Must be initialized before the platform. +// +//============================================================================== +bool Win32Platform::InitializeWindow( HINSTANCE hInstance ) +{ + // check to see if another instance is running... + mhMutex = CreateMutex(NULL, 0, ApplicationName); + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + // simpsons is already running, so lets find the window and give it focus + HWND hwnd = FindWindow(ApplicationName, NULL); + if (hwnd != NULL) + { + // if window is minimized, restore it + WINDOWPLACEMENT wndpl; + if (GetWindowPlacement(hwnd, &wndpl) != 0) + { + if ((wndpl.showCmd == SW_MINIMIZE) || + (wndpl.showCmd == SW_SHOWMINIMIZED)) + { + ShowWindow(hwnd, SW_RESTORE); + } + } + + // activate the window + SetForegroundWindow(hwnd); + + return false; + } + } + + mhInstance = hInstance; + + // Create and resigter an object that defines the window that we will + // run our game in. + WNDCLASS Wndclass; + Wndclass.style = CS_HREDRAW | CS_VREDRAW; + Wndclass.lpfnWndProc = WndProc; + Wndclass.cbClsExtra = 0; + Wndclass.cbWndExtra = 0; + Wndclass.hInstance = mhInstance; + Wndclass.hIcon = LoadIcon( mhInstance, "IDI_SIMPSONSICON" ); + Wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + Wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + Wndclass.lpszMenuName= NULL; + Wndclass.lpszClassName = ApplicationName; + ::RegisterClass(&Wndclass); + + // Set up the window. + int x, y; + TranslateResolution( StartingResolution, x, y ); + + RECT clientRect; + clientRect.left = 0; + clientRect.top = 0; + clientRect.right = x; + clientRect.bottom = y; + + // for windowed mode, center the screen + int nScreenWidth = GetSystemMetrics(SM_CXSCREEN); + int nScreenHeight = GetSystemMetrics(SM_CYSCREEN); + + while (nScreenWidth > 1600 ) // probably multimonitor + { + nScreenWidth /= 2; + } + + // centre the window + clientRect.left = (nScreenWidth-x)/2; + clientRect.top = (nScreenHeight-y)/2; + clientRect.right += clientRect.left; + clientRect.bottom += clientRect.top; + + AdjustWindowRect(&clientRect,WndStyle,FALSE); + + // Create the game's main window. + mhWnd = ::CreateWindow(ApplicationName, + ApplicationName, + WndStyle, + clientRect.left, + clientRect.top, + clientRect.right-clientRect.left, + clientRect.bottom-clientRect.top, + NULL, + NULL, + mhInstance, + NULL); + + rAssert(mhWnd != NULL); + + ShowTheCursor( false ); + + return true; +} + +//============================================================================== +// Win32Platform::InitializeFoundation +//============================================================================== +// Description: FTech must be setup first so that all the memory services +// are ready to go before we begin allocating anything. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be initialized in a particular order. +// Consult their documentation before changing. +// +//============================================================================== +void Win32Platform::InitializeFoundation() +{ + // + // Initialize the memory heaps + // obsolete now.. the heaps initialize memory. + // + //InitializeMemory(); + + // + // Register an out-of-memory display handler in case something goes bad + // while allocating the heaps + // + ::radMemorySetOutOfMemoryCallback( PrintOutOfMemoryMessage, NULL ); + + // + // Initialize memory monitor by JamesCo. TM. + // + if( CommandLineOptions::Get( CLO_MEMORY_MONITOR ) ) + { + const int KB = 1024; + ::radMemoryMonitorInitialize( 64 * KB, GMA_DEBUG ); + } + + // Setup the memory heaps + // + HeapMgr()->PrepareHeapsStartup (); + + // Seed the heap stack + // + HeapMgr()->PushHeap (GMA_PERSISTENT); + + // + // Initilalize the platform system + // + ::radPlatformInitialize( mhWnd, mhInstance, 0 ); + + // + // Initialize the timer system + // + ::radTimeInitialize(); + + // + // Initialize the debug communication system. + // + ::radDbgComTargetInitialize( WinSocket, + radDbgComDefaultPort, // Default + NULL, // Default + GMA_DEBUG ); + + + // + // Initialize the Watcher. + // + ::radDbgWatchInitialize( "SRR2", + 32 * 16384, // 2 * Default + GMA_DEBUG ); + + // + // Initialize the file system. + // + ::radFileInitialize( 50, // Default + 32, // Default + GMA_PERSISTENT ); + + ::radLoadInitialize(); + //radLoad->SetSyncLoading( true ); + + ::radDriveMount( NULL, GMA_PERSISTENT); + + // + // Initialize the new movie player + // + ::radMovieInitialize2( GMA_PERSISTENT ); + + HeapMgr()->PopHeap (GMA_PERSISTENT); +} + +//============================================================================== +// Win32Platform::InitializeMemory +//============================================================================== +// +// Description: +// +// Parameters: +// +// Return: +// +//============================================================================== +void Win32Platform::InitializeMemory() +{ + // + // Only do this once! + // + if( gMemorySystemInitialized == true ) + { + return; + } + + gMemorySystemInitialized = true; + + // + // Initialize the thread system. + // + ::radThreadInitialize(); + + // + // Initialize the memory system. + // + ::radMemoryInitialize(); +} + +//============================================================================== +// Win32Platform::ShutdownMemory +//============================================================================== +// +// Description: +// +// Parameters: +// +// Return: +// +//============================================================================== +void Win32Platform::ShutdownMemory() +{ + if( gMemorySystemInitialized ) + { + gMemorySystemInitialized = false; + + // No shutdown the memory. This leads to bad errors when destroying + // static variables sprinkled here and there. + //::radMemoryTerminate(); + + ::radThreadTerminate(); + } +} + +//============================================================================== +// Win32Platform::InitializePlatform +//============================================================================== +// Description: Get the Win32 ready to go. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void Win32Platform::InitializePlatform() +{ + HeapMgr()->PushHeap (GMA_PERSISTENT); + + // + // Rendering is good. + // + InitializePure3D(); + + // + // Add anything here that needs to be before the drive is opened. + // + DisplaySplashScreen( Error ); // blank screen + + // + // Show the window on the screen. Must be done before initializing the input manager. + // + ShowWindow( mhWnd, mFullscreen ? SW_SHOWMAXIMIZED : SW_SHOW ); + + // + // Opening the drive is SLOW... + // + InitializeFoundationDrive(); + + // + // Initialize the controller. + // + GetInputManager()->Init(); + + // + // Register with the game config manager + // + GetGameConfigManager()->RegisterConfig( this ); + + HeapMgr()->PopHeap (GMA_PERSISTENT); +} + + +//============================================================================== +// Win32Platform::ShutdownPlatform +//============================================================================== +// Description: Shut down the PS2. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void Win32Platform::ShutdownPlatform() +{ + ShutdownPure3D(); + ShutdownFoundation(); +} + +//============================================================================= +// Win32Platform::LaunchDashboard +//============================================================================= +// Description: We use this a the emergency exit from the game if we arent in a context that suppose the transition +// to the CONTEXT_EXIT +// Parameters: () +// +// Return: void +// +//============================================================================= +void Win32Platform::LaunchDashboard() +{ + + { + //chuck I copied and pasted from the other platform's implementations + + GetLoadingManager()->CancelPendingRequests(); + //TODO: Make sure sounds shut down too. + GetSoundManager()->SetMasterVolume( 0.0f ); + + // DisplaySplashScreen( FadeToBlack ); + + GetPresentationManager()->StopAll(); + + //Shouldn't need to do this since, this singleton and the others should get destroyed once we + //retrun the main loop + //GameDataManager::DestroyInstance(); //Get rid of memcards + + p3d::loadManager->CancelAll(); + + GetSoundManager()->StopForMovie(); + + //Shouldnt need the early destruction of this singleton either + //SoundManager::DestroyInstance(); + + //Dont want to shutdown platform early either. + //ShutdownPlatform(); + //rAssertMsg( false, "Doesn't make sense for win32." ); + } +} + +//============================================================================= +// Win32Platform::ResetMachine +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void Win32Platform::ResetMachine() +{ + rAssertMsg( false, "Doesn't make sense for win32." ); +} + +//============================================================================= +// Win32Platform::DisplaySplashScreen +//============================================================================= +// Description: Comment +// +// Parameters: ( SplashScreen screenID, +// const char* overlayText = NULL, +// float fontScale = 1.0f, +// float textPosX = 0.0f, +// float textPosY = 0.0f, +// tColour textColour, +// int fadeFrames = 3 ) +// +// Return: void +// +//============================================================================= +void Win32Platform::DisplaySplashScreen( SplashScreen screenID, + const char* overlayText, + float fontScale, + float textPosX, + float textPosY, + tColour textColour, + int fadeFrames ) +{ + HeapMgr()->PushHeap( GMA_TEMP ); + + p3d::inventory->PushSection(); + p3d::inventory->AddSection( WIN32_SECTION ); + p3d::inventory->SelectSection( WIN32_SECTION ); + + P3D_UNICODE unicodeText[256]; + + // Save the current Projection mode so I can restore it later + pddiProjectionMode pm = p3d::pddi->GetProjectionMode(); + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_DEVICE); + + pddiCullMode cm = p3d::pddi->GetCullMode(); + p3d::pddi->SetCullMode(PDDI_CULL_NONE); + + + //CREATE THE FONT + tTextureFont* thisFont = NULL; + + // Convert memory buffer into a texturefont. + // + //p3d::load(gFont, DEFAULTFONT_SIZE, GMA_TEMP); + LoadMemP3DFile( gFont, DEFAULTFONT_SIZE, p3d::inventory ); + + thisFont = p3d::find<tTextureFont>("adlibn_20"); + rAssert( thisFont ); + + thisFont->AddRef(); + tShader* fontShader = thisFont->GetShader(); + //fontShader->SetInt( ) + + + p3d::AsciiToUnicode( overlayText, unicodeText, 256 ); + + // Make the missing letter into somthing I can see + // + thisFont->SetMissingLetter(p3d::ConvertCharToUnicode('j')); + + int a = 0; + + do + { + p3d::pddi->SetColourWrite(true, true, true, true); + p3d::pddi->SetClearColour( pddiColour(0,0,0) ); + p3d::pddi->BeginFrame(); + p3d::pddi->Clear(PDDI_BUFFER_COLOUR); + + //This is for fading in the font and shaders. + int bright = 255; + if (a < fadeFrames) bright = (a * 255) / fadeFrames; + if ( bright > 255 ) bright = 255; + tColour c(bright, bright, bright, 255); + + //Display font + if (overlayText != NULL) + { + tColour colour = textColour; + colour.SetAlpha( bright ); + + thisFont->SetColour( colour ); + + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_ORTHOGRAPHIC); + p3d::stack->Push(); + p3d::stack->LoadIdentity(); + + p3d::stack->Translate( textPosX, textPosY, 1.5f); + float scaleSize = 1.0f / 480.0f; //This is likely good for 528 also. + p3d::stack->Scale(scaleSize * fontScale, scaleSize* fontScale , 1.0f); + + if ( textPosX != 0.0f || textPosY != 0.0f ) + { + thisFont->DisplayText( unicodeText ); + } + else + { + thisFont->DisplayText( unicodeText, 3 ); + } + + p3d::stack->Pop(); + } + + p3d::pddi->EndFrame(); + p3d::context->SwapBuffers(); + + ++a; + + } while (a <= fadeFrames); + + p3d::pddi->SetCullMode(cm); + p3d::pddi->SetProjectionMode(pm); + + //Should do this after a vsync. + thisFont->Release(); + + p3d::inventory->RemoveSectionElements(WIN32_SECTION); + p3d::inventory->DeleteSection(WIN32_SECTION); + p3d::inventory->PopSection(); + + HeapMgr()->PopHeap( GMA_TEMP ); +} + + +//============================================================================= +// Win32Platform::DisplaySplashScreen +//============================================================================= +// Description: Comment +// +// Parameters: ( const char* textureName, +// const char* overlayText = NULL, +// float fontScale = 1.0f, +// float textPosX = 0.0f, +// float textPosY = 0.0f, +// tColour textColour, +// int fadeFrames = 3 ) +// +// Return: void +// +//============================================================================= +void Win32Platform::DisplaySplashScreen( const char* textureName, + const char* overlayText, + float fontScale, + float textPosX, + float textPosY, + tColour textColour, + int fadeFrames ) +{ +} + +void Win32Platform::OnControllerError(const char *msg) +{ + DisplaySplashScreen( Error, msg, 0.7f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + mErrorState = CTL_ERROR; + mPauseForError = true; + +} + + +//============================================================================= +// Win32Platform::OnDriveError +//============================================================================= +// Description: Comment +// +// Parameters: ( radFileError error, const char* pDriveName, void* pUserData ) +// +// Return: bool +// +//============================================================================= +bool Win32Platform::OnDriveError( radFileError error, const char* pDriveName, void* pUserData ) +{ + // First check if the error is related to loading/saving games. + // We do this here because windows has one drive for all operations. + // If the game data manager is using the drive, it handles the error. + GameDataManager* gm = GetGameDataManager(); + if( gm->IsUsingDrive() ) + { + return gm->OnDriveError( error, pDriveName, pUserData ); + } + + switch ( error ) + { + case Success: + { + if ( mErrorState != NONE ) + { + DisplaySplashScreen( FadeToBlack ); + mErrorState = NONE; + mPauseForError = false; + } + + return true; + break; + } + case FileNotFound: + { + rAssert( pUserData != NULL ); + + radFileRequest* request = static_cast<radFileRequest*>( pUserData ); + const char* fileName = request->GetFilename(); + + //Get rid of the slashes. + unsigned int i; + unsigned int lastIndex = 0; + for ( i = 0; i < strlen( fileName ); ++i ) + { + if ( fileName[ i ] == '\\' ) + { + lastIndex = i; + } + } + + unsigned int adjustedIndex = lastIndex == 0 ? lastIndex : lastIndex + 1; + + char adjustedName[32]; + strncpy( adjustedName, &fileName[adjustedIndex], ( strlen( fileName ) - lastIndex ) ); + adjustedName[ strlen( fileName ) - lastIndex ] = '\0'; + + if( strcmp( fileName, GameConfigManager::ConfigFilename ) == 0 ) + { + return false; + } + + char errorString[256]; + sprintf( errorString, "%s:\n%s", ERROR_STRINGS[error], adjustedName ); + DisplaySplashScreen( Error, errorString, 1.0f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + mErrorState = P_ERROR; + mPauseForError = true; + + return true; + } + case NoMedia: + case MediaNotFormatted: + case MediaCorrupt: + case NoFreeSpace: + case HardwareFailure: + { + //This could be the wrong disc. + DisplaySplashScreen( Error, ERROR_STRINGS[error], 1.0f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + mErrorState = P_ERROR; + mPauseForError = true; + + return true; + } + default: + { + //Others are not supported. + rAssert( false ); + } + } + + return false; +} + +//============================================================================= +// Win32Platform::SetResolution +//============================================================================= +// Description: Sets the screen resolution +// +// Parameters: res - desired resolution +// +// Returns: true if successful +// false if not supported +// +// Notes: +//============================================================================= + +bool Win32Platform::SetResolution( Resolution res, int bpp, bool fullscreen ) +{ + // Check if resolution is supported. + if( !IsResolutionSupported( res, bpp ) ) + { + return false; + } + + // Set up the new properties + mResolution = res; + mbpp = bpp; + mFullscreen = fullscreen; + + // Reinitialize the d3d context. + InitializeContext(); + + // Resize the window for the new resolution + ResizeWindow(); + + return true; +} + +//============================================================================= +// Win32Platform::GetResolution +//============================================================================= +// Description: Returns the current resolution +// +// Parameters: n/a +// +// Returns: resolution +// +// Notes: +//============================================================================= + +Win32Platform::Resolution Win32Platform::GetResolution() const +{ + return mResolution; +} + +//============================================================================= +// Win32Platform::GetBPP +//============================================================================= +// Description: Returns the current bit depth. +// +// Parameters: n/a +// +// Returns: bit depth +// +// Notes: +//============================================================================= + +int Win32Platform::GetBPP() const +{ + return mbpp; +} + +//============================================================================= +// Win32Platform::IsFullscreen +//============================================================================= +// Description: Returns true if currently in full screen mode +// +// Parameters: n/a +// +// Returns: true if in full screen, false if in window +// +// Notes: +//============================================================================= + +bool Win32Platform::IsFullscreen() const +{ + return mFullscreen; +} + +//============================================================================= +// Win32Platform::GetConfigName +//============================================================================= +// Description: Returns the name of the win32 platform's config +// +// Parameters: n/a +// +// Returns: +// +// Notes: +//============================================================================= + +const char* Win32Platform::GetConfigName() const +{ + return "System"; +} + +//============================================================================= +// Win32Platform::GetNumProperties +//============================================================================= +// Description: Returns the number of config properties +// +// Parameters: n/a +// +// Returns: +// +// Notes: +//============================================================================= + +int Win32Platform::GetNumProperties() const +{ + return 4; +} + +//============================================================================= +// Win32Platform::LoadDefaults +//============================================================================= +// Description: Loads the default configuration for the system. +// +// Parameters: n/a +// +// Returns: +// +// Notes: +//============================================================================= + +void Win32Platform::LoadDefaults() +{ +#ifdef RAD_DEBUG + SetResolution( StartingResolution, StartingBPP, !CommandLineOptions::Get( CLO_WINDOW_MODE ) ); +#else + SetResolution( StartingResolution, StartingBPP, true ); +#endif + + + GetRenderFlow()->SetGamma( 1.0f ); +} + +//============================================================================= +// Win32Platform::LoadConfig +//============================================================================= +// Description: Loads the platforms configuration +// +// Parameters: n/a +// +// Returns: +// +// Notes: +//============================================================================= + +void Win32Platform::LoadConfig( ConfigString& config ) +{ + char property[ ConfigString::MaxLength ]; + char value[ ConfigString::MaxLength ]; + + while ( config.ReadProperty( property, value ) ) + { + if( _stricmp( property, "display" ) == 0 ) + { + if( _stricmp( value, "window" ) == 0 ) + { + mFullscreen = false; + } + else if( _stricmp( value, "fullscreen" ) == 0 ) + { + mFullscreen = true; + } + } + else if( _stricmp( property, "resolution" ) == 0 ) + { + if( strcmp( value, "640x480" ) == 0 ) + { + mResolution = Res_640x480; + } + else if( strcmp( value, "800x600" ) == 0 ) + { + mResolution = Res_800x600; + } + else if( strcmp( value, "1024x768" ) == 0 ) + { + mResolution = Res_1024x768; + } + else if( strcmp( value, "1152x864" ) == 0 ) + { + mResolution = Res_1152x864; + } + else if( strcmp( value, "1280x1024" ) == 0 ) + { + mResolution = Res_1280x1024; + } + else if( strcmp( value, "1600x1200" ) == 0 ) + { + mResolution = Res_1600x1200; + } + } + else if( _stricmp( property, "bpp" ) == 0 ) + { + if( strcmp( value, "16" ) == 0 ) + { + mbpp = 16; + } + else if( strcmp( value, "32" ) == 0 ) + { + mbpp = 32; + } + } + else if( _stricmp( property, "gamma" ) == 0 ) + { + float val = (float) atof( value ); + if( val > 0 ) + { + GetRenderFlow()->SetGamma( val ); + } + } + } + + // apply the new settings. + SetResolution( mResolution, mbpp, mFullscreen ); +} + +//============================================================================= +// Win32Platform::SaveConfig +//============================================================================= +// Description: Saves the system configuration to the config string. +// +// Parameters: config string to save to +// +// Returns: +// +// Notes: +//============================================================================= + +void Win32Platform::SaveConfig( ConfigString& config ) +{ + config.WriteProperty( "display", mFullscreen ? "fullscreen" : "window" ); + + const char* res = "800x600"; + switch( mResolution ) + { + case Res_640x480: + { + res = "640x480"; + break; + } + case Res_800x600: + { + res = "800x600"; + break; + } + case Res_1024x768: + { + res = "1024x768"; + break; + } + case Res_1152x864: + { + res = "1152x864"; + break; + } + case Res_1280x1024: + { + res = "1280x1024"; + break; + } + case Res_1600x1200: + { + res = "1600x1200"; + break; + } + default: + { + rAssert( false ); + } + } + + config.WriteProperty( "resolution", res ); + + config.WriteProperty( "bpp", mbpp == 16 ? "16" : "32" ); + + char gamma[20]; + sprintf( gamma, "%f", GetRenderFlow()->GetGamma() ); + config.WriteProperty( "gamma", gamma ); +} + + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** + +//============================================================================== +// Win32Platform::Win32Platform +//============================================================================== +// Description: Constructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +Win32Platform::Win32Platform( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) : + mpPlatform( NULL ), + mpContext( NULL ), + mResolution( StartingResolution ), + mbpp( StartingBPP ) +{ + mhInstance = hInstance; + mFullscreen = false; + + mScreenWidth = GetSystemMetrics(SM_CXSCREEN); + mScreenHeight = GetSystemMetrics(SM_CYSCREEN); + + while (mScreenWidth > 1600 ) // probably multimonitor + { + mScreenWidth /= 2; + } +} + + +//============================================================================== +// Win32Platform::~Win32Platform +//============================================================================== +// Description: Destructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +Win32Platform::~Win32Platform() +{ + HeapManager::DestroyInstance(); + + CloseHandle( mhMutex ); +} + +//============================================================================== +// Win32Platform::InitializeFoundationDrive +//============================================================================== +// Description: Get FTech ready to go. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be initialized in a particular order. +// Consult their documentation before changing. +// +//============================================================================== +void Win32Platform::InitializeFoundationDrive() +{ + // + // Get the default drive and hold it open for the life of the game. + // This is a costly operation so we only want to do it once. + // + + char defaultDrive[ radFileDrivenameMax + 1 ]; + + ::radGetDefaultDrive( defaultDrive ); + + ::radDriveOpenSync( &mpIRadDrive, + defaultDrive, + NormalPriority, // Default + GMA_PERSISTENT ); + + rAssert( mpIRadDrive != NULL ); + + mpIRadDrive->RegisterErrorHandler( this, NULL ); +} + + +//============================================================================== +// Win32Platform::ShutdownFoundation +//============================================================================== +// Description: Shut down Foundation Tech. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be terminated in the reverse order that +// they were initialized in. +// +//============================================================================== +void Win32Platform::ShutdownFoundation() +{ + // + // Release the drive we've held open since the begining. + // + mpIRadDrive->Release(); + mpIRadDrive = NULL; + + // + // Shutdown the systems in the reverse order. + // + ::radMovieTerminate2(); + ::radDriveUnmount( NULL ); + ::radLoadTerminate(); + ::radFileTerminate(); + ::radDbgWatchTerminate(); + if( CommandLineOptions::Get( CLO_MEMORY_MONITOR ) ) + { + ::radMemoryMonitorTerminate(); + } + ::radDbgComTargetTerminate(); + ::radTimeTerminate(); + ::radPlatformTerminate(); +} + + +//============================================================================== +// Win32Platform::InitializePure3D +//============================================================================== +// Description: Get Pure3D ready to go. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void Win32Platform::InitializePure3D() +{ +MEMTRACK_PUSH_GROUP( "Win32Platform" ); + // p3d::SetMemAllocator( p3d::ALLOC_DEFAULT, GMA_PERSISTENT ); + // p3d::SetMemAllocator( p3d::ALLOC_LOADED, GMA_LEVEL ); + + // + // Initialise Pure3D platform object. + // This call differs between different platforms. The Win32 version, + // for example requires the application instance to be passed in. + // + mpPlatform = tPlatform::Create( mhInstance ); + rAssert( mpPlatform != NULL ); + + // + // Initialize the d3d context. + // + InitializeContext(); + + // + // This call installs chunk handlers for all the primary chunk types that + // Pure3D supports. This includes textures, materials, geometries, and the + // like. + // + // p3d::InstallDefaultLoaders(); + P3DASSERT(p3d::context); + tP3DFileHandler* p3d = new(GMA_PERSISTENT) tP3DFileHandler; + // p3d::loadManager->AddHandler(p3d, "p3d"); + p3d::context->GetLoadManager()->AddHandler(p3d, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tPNGHandler, "png"); + + if( CommandLineOptions::Get( CLO_FE_UNJOINED ) ) + { + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tBMPHandler, "bmp"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tTargaHandler, "tga"); + } + else + { + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tBMPHandler, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tPNGHandler, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tTargaHandler, "p3d"); + } + + // p3d->AddHandler(new tGeometryLoader); + // GeometryWrappedLoader* pGWL = new GeometryWrappedLoader; + GeometryWrappedLoader* pGWL = + (GeometryWrappedLoader*)GetAllWrappers()->mpLoader( AllWrappers::msGeometry ); + pGWL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pGWL ); + + StaticEntityLoader* pSEL = + (StaticEntityLoader*)GetAllWrappers()->mpLoader( AllWrappers::msStaticEntity ); + pSEL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pSEL ); + + StaticPhysLoader* pSPL = + (StaticPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msStaticPhys ); + pSPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pSPL ); + + TreeDSGLoader* pTDL = + (TreeDSGLoader*)GetAllWrappers()->mpLoader( AllWrappers::msTreeDSG ); + pTDL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pTDL ); + + FenceLoader* pFL = + (FenceLoader*)GetAllWrappers()->mpLoader( AllWrappers::msFenceEntity ); + pFL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pFL ); + + IntersectLoader* pIL = + (IntersectLoader*)GetAllWrappers()->mpLoader( AllWrappers::msIntersectDSG ); + pIL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pIL ); + + AnimCollLoader* pACL = + (AnimCollLoader*)GetAllWrappers()->mpLoader( AllWrappers::msAnimCollEntity ); + pACL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pACL ); + + AnimDSGLoader* pAnimDSGLoader = + (AnimDSGLoader*)GetAllWrappers()->mpLoader( AllWrappers::msAnimEntity ); + pAnimDSGLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimDSGLoader ); + + + DynaPhysLoader* pDPL = + (DynaPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msDynaPhys ); + pDPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pDPL ); + + InstStatPhysLoader* pISPL = + (InstStatPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msInstStatPhys ); + pISPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pISPL ); + + InstStatEntityLoader* pISEL = + (InstStatEntityLoader*)GetAllWrappers()->mpLoader( AllWrappers::msInstStatEntity ); + pISEL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pISEL ); + + LocatorLoader* pLL = + (LocatorLoader*)GetAllWrappers()->mpLoader( AllWrappers::msLocator); + pLL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pLL ); + + RoadLoader* pRL = + (RoadLoader*)GetAllWrappers()->mpLoader( AllWrappers::msRoadSegment); + pRL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pRL ); + + PathLoader* pPL = + (PathLoader*)GetAllWrappers()->mpLoader( AllWrappers::msPathSegment); + pPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pPL ); + + WorldSphereLoader* pWSL = + (WorldSphereLoader*)GetAllWrappers()->mpLoader( AllWrappers::msWorldSphere); + pWSL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pWSL ); + + LensFlareLoader* pLSL = + (LensFlareLoader*)GetAllWrappers()->mpLoader( AllWrappers::msLensFlare); + pLSL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pLSL ); + + BillboardWrappedLoader* pBWL = + (BillboardWrappedLoader*)GetAllWrappers()->mpLoader( AllWrappers::msBillboard); + pBWL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pBWL ); + + + InstParticleSystemLoader* pInstParticleSystemLoader = + (InstParticleSystemLoader*) GetAllWrappers()->mpLoader( AllWrappers::msInstParticleSystem); + pInstParticleSystemLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pInstParticleSystemLoader ); + + BreakableObjectLoader* pBreakableObjectLoader = + (BreakableObjectLoader*) GetAllWrappers()->mpLoader( AllWrappers::msBreakableObject); + pBreakableObjectLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pBreakableObjectLoader ); + + AnimDynaPhysLoader* pAnimDynaPhysLoader = + (AnimDynaPhysLoader*) GetAllWrappers()->mpLoader( AllWrappers::msAnimDynaPhys); + pAnimDynaPhysLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimDynaPhysLoader ); + + AnimDynaPhysWrapperLoader* pAnimWrapperLoader = + (AnimDynaPhysWrapperLoader*) GetAllWrappers()->mpLoader( AllWrappers::msAnimDynaPhysWrapper); + pAnimWrapperLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimWrapperLoader ); + + p3d->AddHandler(new(GMA_PERSISTENT) tTextureLoader); + p3d->AddHandler( new(GMA_PERSISTENT) tSetLoader ); + p3d->AddHandler(new(GMA_PERSISTENT) tShaderLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tCameraLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tGameAttrLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tLightLoader); + + p3d->AddHandler(new(GMA_PERSISTENT) tLocatorLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tLightGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tImageLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tTextureFontLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tImageFontLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tSpriteLoader); + //p3d->AddHandler(new(GMA_PERSISTENT) tBillboardQuadGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tSkeletonLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tPolySkinLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tCompositeDrawableLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tVertexAnimKeyLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tAnimationLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tFrameControllerLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tMultiControllerLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tAnimatedObjectFactoryLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tAnimatedObjectLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tParticleSystemFactoryLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tParticleSystemLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tLensFlareGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) sg::Loader); + + p3d->AddHandler(new(GMA_PERSISTENT) tExpressionGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tExpressionMixerLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tExpressionLoader); + + //ATCloader, hope this doesnt blow up + p3d->AddHandler(new(GMA_PERSISTENT) ATCLoader); + + //p3d->AddHandler(new p3d::tIgnoreLoader); + + tSEQFileHandler* sequencerFileHandler = new(GMA_PERSISTENT) tSEQFileHandler; + p3d::loadManager->AddHandler(sequencerFileHandler, "seq"); + + // sim lib + sim::InstallSimLoaders(); + + p3d->AddHandler(new(GMA_PERSISTENT) CameraDataLoader, SRR2::ChunkID::FOLLOWCAM); + p3d->AddHandler(new(GMA_PERSISTENT) CameraDataLoader, SRR2::ChunkID::WALKERCAM); + p3d->AddHandler(new(GMA_PERSISTENT) IntersectionLoader); + //p3d->AddHandler(new(GMA_PERSISTENT) RoadLoader); + p3d->AddHandler(new(GMA_PERSISTENT) RoadDataSegmentLoader); + p3d->AddHandler(new(GMA_PERSISTENT) CStatePropDataLoader); +MEMTRACK_POP_GROUP( "Win32Platform" ); +} + + +//============================================================================== +// Win32Platform::ShutdownPure3D +//============================================================================== +// Description: Clean up and shut down Pure3D. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void Win32Platform::ShutdownPure3D() +{ + // + // Clean-up the Pure3D Inventory + // + p3d::inventory->RemoveAllElements(); + p3d::inventory->DeleteAllSections(); + + // + // Clean-up the space taken by the Pure 3D context. + // + if( mpContext != NULL ) + { + mpPlatform->DestroyContext( mpContext ); + mpContext = NULL; + } + + // + // Clean-up the space taken by the Pure 3D platform. + // + if( mpPlatform != NULL ) + { + tPlatform::Destroy( mpPlatform ); + mpPlatform = NULL; + } +} + +//============================================================================== +// Win32Platform::InitializeContext +//============================================================================== +// Description: Initializes the d3d context for this application according to +// the class' display settings - resolution, bpp, fullscreen. +// +// Parameters: n/a +// +// Return: n/a +// +//============================================================================== + +void Win32Platform::InitializeContext() +{ + tContextInitData init; + + // + // This is the window we want to render into. + // + init.hwnd = mhWnd; + + // + // Set the fullscreen/window mode. + // + init.displayMode = mFullscreen ? PDDI_DISPLAY_FULLSCREEN : PDDI_DISPLAY_WINDOW; + + // + // This the name of the PDDI we will be using for rendering + // + strncpy(init.PDDIlib, d3dLibraryName, 128); + + // + // All applications should supply PDDI_BUFFER_COLOUR. PDDI_BUFFER_DEPTH + // specifies that we also want to allocate a Z-buffer. + // + init.bufferMask = PDDI_BUFFER_COLOUR | PDDI_BUFFER_DEPTH; + init.enableSnapshot = false; + + // + // These values only take effect in fullscreen mode. In windowed mode, the + // dimensions of the window define the rendering area. We'll define them + // anyway for completeness sake. + // + TranslateResolution( mResolution, init.xsize, init.ysize ); + + // + // Depth of the rendering buffer. Again, this value only works in + // fullscreen mode. In window mode, the depth of the desktop is used. + // This value should be either 16 or 32. + // + init.bpp = mbpp; + + init.lockToVsync = false; + + if( mpContext == NULL ) + { + // Create the context + mpContext = mpPlatform->CreateContext( &init ); + rAssert( mpContext != NULL ); + + // + // Assign this context to the platform. + // + mpPlatform->SetActiveContext( mpContext ); + p3d::pddi->EnableZBuffer( true ); + } + else + { + // Update the display settings. + mpContext->GetDisplay()->InitDisplay( &init ); + } +} + +//============================================================================== +// Win32Platform::TranslateResolution +//============================================================================== +// Description: translates resolution enums to x and y +// +// Parameters: resolution - the res enum +// x - corresponding width +// y - corresponding height +// +// Return: N/A. +// +//============================================================================== + +void Win32Platform::TranslateResolution( Resolution res, int&x, int&y ) +{ + switch( res ) + { + case Res_640x480: + { + x = 640; + y = 480; + break; + } + case Res_800x600: + { + x = 800; + y = 600; + break; + } + case Res_1024x768: + { + x = 1024; + y = 768; + break; + } + case Res_1152x864: + { + x = 1152; + y = 864; + break; + } + case Res_1280x1024: + { + x = 1280; + y = 1024; + break; + } + case Res_1600x1200: + { + x = 1600; + y = 1200; + break; + } + default: + { + rAssert( false ); + } + } +} + +//============================================================================== +// Win32Platform::IsResolutionSupported +//============================================================================== +// Description: Determines if a resolution is supported on this pc +// +// Parameters: resolution - the res enum +// +// Return: true if supported. +// +//============================================================================== + +bool Win32Platform::IsResolutionSupported( Resolution res, int bpp ) const +{ + int x,y; + + TranslateResolution( res, x, y ); + + // Get the display info for the device + pddiDisplayInfo* displays = NULL; + int num_adapters = mpContext->GetDevice()->GetDisplayInfo( &displays ); + rAssert( num_adapters > 0 ); + + // Go through the supported modes and see if we can do it. + // Ignore the refresh rate - directx uses default. + for( int i = 0; i < displays[0].nDisplayModes; i++ ) + { + if( displays[0].modeInfo[i].width == x && + displays[0].modeInfo[i].height == y && + displays[0].modeInfo[i].bpp == bpp ) + { + return true; + } + } + + return false; +} + +//============================================================================== +// Win32Platform::TrackMouseEvent +//============================================================================== +// Description: Determines if a resolution is supported on this pc +// +// Parameters: pMouseEventTracker - the tracker +// +// Return: true if succeeded in creating a timer. +// +//============================================================================== +BOOL Win32Platform::TrackMouseEvent( MOUSETRACKER* pMouseEventTracker ) +{ + if ( !pMouseEventTracker || pMouseEventTracker->cbSize < sizeof(MOUSETRACKER) ) + return false; + + if( !IsWindow( pMouseEventTracker->hwndTrack ) ) + return false; + + if( !(pMouseEventTracker->dwFlags & TIMER_LEAVE) ) + return false; + + return SetTimer( pMouseEventTracker->hwndTrack, + pMouseEventTracker->dwFlags, + 100, (TIMERPROC)TrackMouseTimerProc ); +} + +//============================================================================= +// Win32Platform::ResizeWindow +//============================================================================= +// Description: Resizes the app's window based on the current resolution. +// +// Parameters: n/a +// +// Returns: n/a +// +// Notes: +//============================================================================= + +void Win32Platform::ResizeWindow() +{ + // If fullscreen, no need to change the window size. + if( mFullscreen ) + { + return; + } + + int x,y,cx,cy; + RECT clientRect; + + TranslateResolution( mResolution, cx, cy ); + + if( cx < mScreenWidth ) // if the window fits on the desktop + { + x = ( mScreenWidth - cx ) / 2; + y = ( mScreenHeight - cy ) / 2; + + // Adjust the rectangle for the title bar and borders + clientRect.left = x; + clientRect.top = y; + clientRect.right = x+cx; + clientRect.bottom = y+cy; + + AdjustWindowRect(&clientRect,WndStyle,FALSE); + } + else // if the window is bigger than the client area + { + clientRect.left = 0; + clientRect.top = 0; + clientRect.right = cx; + clientRect.bottom = cy; + } + + SetWindowPos( mhWnd, + HWND_TOP, + clientRect.left, + clientRect.top, + clientRect.right-clientRect.left, + clientRect.bottom-clientRect.top, + 0 ); + ShowWindow( mhWnd, SW_SHOW ); +} + +//============================================================================= +// Win32Platform::ShowTheCursor +//============================================================================= +// Description: Shows or hides the cursor. Wrapper for the windows ShowCursor +// function, except it doesn't keep a counter for the number of +// shows/hides. +// +// Parameters: show - show cursor +// +// Returns: n/a +// +// Notes: +//============================================================================= + +void Win32Platform::ShowTheCursor( bool show ) +{ + if( mShowCursor != show ) + { + mShowCursor = show; + ShowCursor( mShowCursor ); + } +} + +//============================================================================= +// GetMessageName +//============================================================================= +// Description: Prints the name of windows messages. +// +// Parameters: message - message id +// +// Returns: string name +// +// Notes: +//============================================================================= + +#if defined( PRINT_WINMESSAGES ) && defined( RAD_DEBUG ) +static const char* GetMessageName( UINT message ) +{ + switch ( message ) + { + case 0x0000: return "WM_NULL"; + case 0x0001: return "WM_CREATE"; + case 0x0002: return "WM_DESTROY"; + case 0x0003: return "WM_MOVE"; + case 0x0005: return "WM_SIZE"; + case 0x0006: return "WM_ACTIVATE"; + case 0x0007: return "WM_SETFOCUS"; + case 0x0008: return "WM_KILLFOCUS"; + case 0x000A: return "WM_ENABLE"; + case 0x000B: return "WM_SETREDRAW"; + case 0x000C: return "WM_SETTEXT"; + case 0x000D: return "WM_GETTEXT"; + case 0x000E: return "WM_GETTEXTLENGTH"; + case 0x000F: return "WM_PAINT"; + case 0x0010: return "WM_CLOSE"; + case 0x0011: return "WM_QUERYENDSESSION"; + case 0x0013: return "WM_QUERYOPEN"; + case 0x0016: return "WM_ENDSESSION"; + case 0x0012: return "WM_QUIT"; + case 0x0014: return "WM_ERASEBKGND"; + case 0x0015: return "WM_SYSCOLORCHANGE"; + case 0x0018: return "WM_SHOWWINDOW"; + case 0x001A: return "WM_WININICHANGE"; + case 0x001B: return "WM_DEVMODECHANGE"; + case 0x001C: return "WM_ACTIVATEAPP"; + case 0x001D: return "WM_FONTCHANGE"; + case 0x001E: return "WM_TIMECHANGE"; + case 0x001F: return "WM_CANCELMODE"; + case 0x0020: return "WM_SETCURSOR"; + case 0x0021: return "WM_MOUSEACTIVATE"; + case 0x0022: return "WM_CHILDACTIVATE"; + case 0x0023: return "WM_QUEUESYNC"; + case 0x0024: return "WM_GETMINMAXINFO"; + case 0x0026: return "WM_PAINTICON"; + case 0x0027: return "WM_ICONERASEBKGND"; + case 0x0028: return "WM_NEXTDLGCTL"; + case 0x002A: return "WM_SPOOLERSTATUS"; + case 0x002B: return "WM_DRAWITEM"; + case 0x002C: return "WM_MEASUREITEM"; + case 0x002D: return "WM_DELETEITEM"; + case 0x002E: return "WM_VKEYTOITEM"; + case 0x002F: return "WM_CHARTOITEM"; + case 0x0030: return "WM_SETFONT"; + case 0x0031: return "WM_GETFONT"; + case 0x0032: return "WM_SETHOTKEY"; + case 0x0033: return "WM_GETHOTKEY"; + case 0x0037: return "WM_QUERYDRAGICON"; + case 0x0039: return "WM_COMPAREITEM"; + case 0x0041: return "WM_COMPACTING"; + case 0x0044: return "WM_COMMNOTIFY"; + case 0x0046: return "WM_WINDOWPOSCHANGING"; + case 0x0047: return "WM_WINDOWPOSCHANGED"; + case 0x0048: return "WM_POWER"; + case 0x004A: return "WM_COPYDATA"; + case 0x004B: return "WM_CANCELJOURNAL"; + case 0x004E: return "WM_NOTIFY"; + case 0x0050: return "WM_INPUTLANGCHANGEREQUEST"; + case 0x0051: return "WM_INPUTLANGCHANGE"; + case 0x0052: return "WM_TCARD"; + case 0x0053: return "WM_HELP"; + case 0x0054: return "WM_USERCHANGED"; + case 0x0055: return "WM_NOTIFYFORMAT"; + case 0x007B: return "WM_CONTEXTMENU"; + case 0x007C: return "WM_STYLECHANGING"; + case 0x007D: return "WM_STYLECHANGED"; + case 0x007E: return "WM_DISPLAYCHANGE"; + case 0x007F: return "WM_GETICON"; + case 0x0080: return "WM_SETICON"; + case 0x0081: return "WM_NCCREATE"; + case 0x0082: return "WM_NCDESTROY"; + case 0x0083: return "WM_NCCALCSIZE"; + case 0x0084: return "WM_NCHITTEST"; + case 0x0085: return "WM_NCPAINT"; + case 0x0086: return "WM_NCACTIVATE"; + case 0x0087: return "WM_GETDLGCODE"; + case 0x0088: return "WM_SYNCPAINT"; + case 0x00A0: return "WM_NCMOUSEMOVE"; + case 0x00A1: return "WM_NCLBUTTONDOWN"; + case 0x00A2: return "WM_NCLBUTTONUP"; + case 0x00A3: return "WM_NCLBUTTONDBLCLK"; + case 0x00A4: return "WM_NCRBUTTONDOWN"; + case 0x00A5: return "WM_NCRBUTTONUP"; + case 0x00A6: return "WM_NCRBUTTONDBLCLK"; + case 0x00A7: return "WM_NCMBUTTONDOWN"; + case 0x00A8: return "WM_NCMBUTTONUP"; + case 0x00A9: return "WM_NCMBUTTONDBLCLK"; + case 0x00AB: return "WM_NCXBUTTONDOWN"; + case 0x00AC: return "WM_NCXBUTTONUP"; + case 0x00AD: return "WM_NCXBUTTONDBLCLK"; + case 0x00FF: return "WM_INPUT"; + case 0x0100: return "WM_KEYDOWN"; + case 0x0101: return "WM_KEYUP"; + case 0x0102: return "WM_CHAR"; + case 0x0103: return "WM_DEADCHAR"; + case 0x0104: return "WM_SYSKEYDOWN"; + case 0x0105: return "WM_SYSKEYUP"; + case 0x0106: return "WM_SYSCHAR"; + case 0x0107: return "WM_SYSDEADCHAR"; + case 0x0109: return "WM_KEYLAST"; + case 0xFFFF: return "UNICODE_NOCHAR"; + case 0x0108: return "WM_KEYLAST"; + case 0x010D: return "WM_IME_STARTCOMPOSITION"; + case 0x010E: return "WM_IME_ENDCOMPOSITION"; + case 0x010F: return "WM_IME_KEYLAST"; + case 0x0110: return "WM_INITDIALOG"; + case 0x0111: return "WM_COMMAND"; + case 0x0112: return "WM_SYSCOMMAND"; + case 0x0113: return "WM_TIMER"; + case 0x0114: return "WM_HSCROLL"; + case 0x0115: return "WM_VSCROLL"; + case 0x0116: return "WM_INITMENU"; + case 0x0117: return "WM_INITMENUPOPUP"; + case 0x011F: return "WM_MENUSELECT"; + case 0x0120: return "WM_MENUCHAR"; + case 0x0121: return "WM_ENTERIDLE"; + case 0x0122: return "WM_MENURBUTTONUP"; + case 0x0123: return "WM_MENUDRAG"; + case 0x0124: return "WM_MENUGETOBJECT"; + case 0x0125: return "WM_UNINITMENUPOPUP"; + case 0x0126: return "WM_MENUCOMMAND"; + case 0x0127: return "WM_CHANGEUISTATE"; + case 0x0128: return "WM_UPDATEUISTATE"; + case 0x0129: return "WM_QUERYUISTATE"; + case 0x0132: return "WM_CTLCOLORMSGBOX"; + case 0x0133: return "WM_CTLCOLOREDIT"; + case 0x0134: return "WM_CTLCOLORLISTBOX"; + case 0x0135: return "WM_CTLCOLORBTN"; + case 0x0136: return "WM_CTLCOLORDLG"; + case 0x0137: return "WM_CTLCOLORSCROLLBAR"; + case 0x0138: return "WM_CTLCOLORSTATIC"; + case 0x0200: return "WM_MOUSEMOVE"; + case 0x0201: return "WM_LBUTTONDOWN"; + case 0x0202: return "WM_LBUTTONUP"; + case 0x0203: return "WM_LBUTTONDBLCLK"; + case 0x0204: return "WM_RBUTTONDOWN"; + case 0x0205: return "WM_RBUTTONUP"; + case 0x0206: return "WM_RBUTTONDBLCLK"; + case 0x0207: return "WM_MBUTTONDOWN"; + case 0x0208: return "WM_MBUTTONUP"; + case 0x0209: return "WM_MBUTTONDBLCLK"; + case 0x020A: return "WM_MOUSEWHEEL"; + case 0x020B: return "WM_XBUTTONDOWN"; + case 0x020C: return "WM_XBUTTONUP"; + case 0x020D: return "WM_MOUSELAST"; + case 0x0210: return "WM_PARENTNOTIFY"; + case 0x0211: return "WM_ENTERMENULOOP"; + case 0x0212: return "WM_EXITMENULOOP"; + case 0x0213: return "WM_NEXTMENU"; + case 0x0214: return "WM_SIZING"; + case 0x0215: return "WM_CAPTURECHANGED"; + case 0x0216: return "WM_MOVING"; + case 0x0218: return "WM_POWERBROADCAST"; + case 0x0219: return "WM_DEVICECHANGE"; + case 0x0220: return "WM_MDICREATE"; + case 0x0221: return "WM_MDIDESTROY"; + case 0x0222: return "WM_MDIACTIVATE"; + case 0x0223: return "WM_MDIRESTORE"; + case 0x0224: return "WM_MDINEXT"; + case 0x0225: return "WM_MDIMAXIMIZE"; + case 0x0226: return "WM_MDITILE"; + case 0x0227: return "WM_MDICASCADE"; + case 0x0228: return "WM_MDIICONARRANGE"; + case 0x0229: return "WM_MDIGETACTIVE"; + case 0x0230: return "WM_MDISETMENU"; + case 0x0231: return "WM_ENTERSIZEMOVE"; + case 0x0232: return "WM_EXITSIZEMOVE"; + case 0x0233: return "WM_DROPFILES"; + case 0x0234: return "WM_MDIREFRESHMENU"; + case 0x0281: return "WM_IME_SETCONTEXT"; + case 0x0282: return "WM_IME_NOTIFY"; + case 0x0283: return "WM_IME_CONTROL"; + case 0x0284: return "WM_IME_COMPOSITIONFULL"; + case 0x0285: return "WM_IME_SELECT"; + case 0x0286: return "WM_IME_CHAR"; + case 0x0288: return "WM_IME_REQUEST"; + case 0x0290: return "WM_IME_KEYDOWN"; + case 0x0291: return "WM_IME_KEYUP"; + case 0x02A1: return "WM_MOUSEHOVER"; + case 0x02A3: return "WM_MOUSELEAVE"; + case 0x02A0: return "WM_NCMOUSEHOVER"; + case 0x02A2: return "WM_NCMOUSELEAVE"; + case 0x02B1: return "WM_WTSSESSION_CHANGE"; + case 0x02c0: return "WM_TABLET_FIRST"; + case 0x02df: return "WM_TABLET_LAST"; + case 0x0300: return "WM_CUT"; + case 0x0301: return "WM_COPY"; + case 0x0302: return "WM_PASTE"; + case 0x0303: return "WM_CLEAR"; + case 0x0304: return "WM_UNDO"; + case 0x0305: return "WM_RENDERFORMAT"; + case 0x0306: return "WM_RENDERALLFORMATS"; + case 0x0307: return "WM_DESTROYCLIPBOARD"; + case 0x0308: return "WM_DRAWCLIPBOARD"; + case 0x0309: return "WM_PAINTCLIPBOARD"; + case 0x030A: return "WM_VSCROLLCLIPBOARD"; + case 0x030B: return "WM_SIZECLIPBOARD"; + case 0x030C: return "WM_ASKCBFORMATNAME"; + case 0x030D: return "WM_CHANGECBCHAIN"; + case 0x030E: return "WM_HSCROLLCLIPBOARD"; + case 0x030F: return "WM_QUERYNEWPALETTE"; + case 0x0310: return "WM_PALETTEISCHANGING"; + case 0x0311: return "WM_PALETTECHANGED"; + case 0x0312: return "WM_HOTKEY"; + case 0x0317: return "WM_PRINT"; + case 0x0318: return "WM_PRINTCLIENT"; + case 0x0319: return "WM_APPCOMMAND"; + case 0x031A: return "WM_THEMECHANGED"; + case 0x0358: return "WM_HANDHELDFIRST"; + case 0x035F: return "WM_HANDHELDLAST"; + case 0x0360: return "WM_AFXFIRST"; + case 0x0380: return "WM_PENWINFIRST"; + case 0x038F: return "WM_PENWINLAST"; + case 0x8000: return "WM_APP"; + default: return "UNKNOWN MESSAGE"; + } +} +#endif + +void Win32Platform::TrackMouseTimerProc( HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime ) +{ + RECT clientRect; + POINT point; + + GetClientRect( hWnd, &clientRect ); + MapWindowPoints( hWnd, NULL, (LPPOINT)&clientRect, 2 ); + GetCursorPos( &point ); + if( !PtInRect( &clientRect, point ) || (WindowFromPoint(point) != hWnd ) ) + { + if( !KillTimer( hWnd, idEvent ) ) + { + rDebugPrintf( "Couldn't kill the timer" ); + } + + PostMessage( hWnd, WM_MOUSELEAVE, 0, 0 ); + } + else + { + GetInputManager()->GetFEMouse()->getCursor()->SetVisible( true ); + } +} + +//============================================================================= +// Win32Platform::WndProc +//============================================================================= +// Description: The windows os messaging callback for the game. +// Routes messages to pure3d. +// +// Parameters: hwnd - handle for window +// message - message ID +// wParam - word parameter +// lParam - long parameter +// +// Returns: windows result +// +// Notes: +//============================================================================= + +LRESULT Win32Platform::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +#if defined( PRINT_WINMESSAGES ) && defined( RAD_DEBUG ) + rDebugPrintf( "Windows Message: 0x%08x (%s) [0x%08x, 0x%08x]\n", message, GetMessageName(message), wParam, lParam ); +#endif + MOUSETRACKER mouseEventTracker; + static bool bMouseInWindow; // A flag to poll if you want to check if the mouse is in the clientwindow. + + // + // Under Win32, Pure3D needs to get a crack at the Windows messages so + // it can detect window moving, resizing, and activation. + // + p3d::platform->ProcessWindowsMessage(hwnd, message, wParam, lParam); + + switch(message) + { + case WM_ACTIVATEAPP: + { + InputManager* pInputManager = GetInputManager(); + + if( spInstance != NULL && spInstance->mpContext != NULL ) + { + if( wParam ) // Window is being shown (in focus) + { + RenderFlow* rf = GetRenderFlow(); + + rf->SetGamma( rf->GetGamma() ); + if( pInputManager ) + { + //GetInputManager()->SetRumbleForDevice(0, true); + //rDebugPrintf("Force Effects Started!!! \n"); + } + } + else // Window is being hidden (not in focus) + { + SetDeviceGammaRamp( GetDC( GetDesktopWindow( ) ), DesktopGammaRamp ); + if( pInputManager ) + { + //GetInputManager()->SetRumbleForDevice(0, false); + //rDebugPrintf("Force Effects Stopped!!! \n"); + } + } + + if( GetInputManager() != NULL ) + { + GetInputManager()->GetFEMouse()->SetInGameOverride( !wParam ); + } + } + + break; + } + + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + { + //Ignore Alt and F10 keys. + switch(wParam) + { + case VK_MENU: + return 0; + case VK_F10: + return 0; + default: break; + } + } + case WM_SHOWWINDOW: + { + break; + } + + case WM_CREATE: + { + GetDeviceGammaRamp( GetDC( GetDesktopWindow( ) ), DesktopGammaRamp ); + bMouseInWindow = false; + break; + } + + case WM_DESTROY: + PostQuitMessage(0); + break; + case WM_MOUSELEAVE: + bMouseInWindow = false; + GetInputManager()->GetFEMouse()->getCursor()->SetVisible( false ); + break; + + case WM_NCMOUSEMOVE: + { + POINT pPoint; + GetCursorPos( &pPoint ); + + // Convert the absolute screen coordinates from windows to client window absolute coordinates. + ScreenToClient( hwnd, &pPoint ); + + RECT clientRect; + GetClientRect( hwnd, &clientRect ); + + GetInputManager()->GetFEMouse()->Move( pPoint.x, pPoint.y, clientRect.right, clientRect.bottom ); + + ShowTheCursor( true ); + break; + } + case WM_MOUSEMOVE: + { + POINT pPoint; + pPoint.x = LOWORD(lParam); + pPoint.y = HIWORD(lParam); + + // For some reason beyond my comprehension WM_MOUSEMOVE seems to be getting called regardless if the + // mouse moved or not. So let the FEMouse determine if we moved. + FEMouse* pFEMouse = GetInputManager()->GetFEMouse(); + if( pFEMouse->DidWeMove( pPoint.x, pPoint.y ) ) + { + RECT clientRect; + GetClientRect( hwnd, &clientRect ); + pFEMouse->Move( pPoint.x, pPoint.y, clientRect.right, clientRect.bottom ); + } + + ShowTheCursor( false ); + + if( !bMouseInWindow ) + { + bMouseInWindow = true; + mouseEventTracker.cbSize = sizeof(MOUSETRACKER); + mouseEventTracker.dwFlags = TIMER_LEAVE; + mouseEventTracker.hwndTrack = hwnd; + if( !TrackMouseEvent( &mouseEventTracker ) ) + { + rDebugPrintf( "TrackMouseEvent Failed" ); + } + } + + break; + } + + case WM_LBUTTONDOWN: + { + GetInputManager()->GetFEMouse()->ButtonDown( BUTTON_LEFT ); + // rDebugPrintf("LEFT MOUSE BUTTON PRESSED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \n"); + break; + } + case WM_LBUTTONUP: + { + GetInputManager()->GetFEMouse()->ButtonUp( BUTTON_LEFT ); + break; + } + case WM_SYSCOMMAND: + { + switch (wParam) + { + case SC_SCREENSAVE: // Screensaver Trying To Start? + case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? + return 0; + } + break; + } + + // PDDI will sent this message to enable or disable rendering in response to an + // application level window event. For example, if the user clicks away from + // the rendering window, or uses ALT-TAB to select another application, PDDI + // will tell sent a WM_PDDI_DRAW_ENABLE(0) message. When the application + // regains focus, WM_PDDI_DRAW_ENABLE(1) will be sent. + case WM_PDDI_DRAW_ENABLE: + //GetApplication()->EnableRendering(wParam == 1); + break; + + case WM_CHAR: + { + break; + } + default: + break; + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + diff --git a/game/code/main/win32platform.h b/game/code/main/win32platform.h new file mode 100644 index 0000000..9be1e57 --- /dev/null +++ b/game/code/main/win32platform.h @@ -0,0 +1,176 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// Component: Win32Platform +// +// Description: Abstracts the differences for setting up and shutting down +// the different platforms. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +#ifndef WIN32PLATFORM_H +#define WIN32PLATFORM_H + +//======================================== +// System Includes +//======================================== + +#include <windows.h> + +//======================================== +// Nested Includes +//======================================== +#include "platform.h" // base class +#include <data/config/gameconfig.h> // interface + +//======================================== +// Forward References +//======================================== +struct IRadMemoryHeap; +class tPlatform; +class tContext; + + +struct MOUSETRACKER +{ + DWORD cbSize; + DWORD dwFlags; + HWND hwndTrack; +}; + +//============================================================================= +// +// Synopsis: Provides abstraction for setting up and closing a win32 exe. +// +//============================================================================= +class Win32Platform : public Platform, public GameConfigHandler +{ +public: + + enum Resolution + { + Res_640x480 = 0, + Res_800x600, + Res_1024x768, + Res_1152x864, + Res_1280x1024, + Res_1600x1200 + }; + +public: + + // Static Methods for accessing this singleton. + static Win32Platform* CreateInstance( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ); + static Win32Platform* GetInstance(); + static void DestroyInstance(); + + // Had to workaround our nice clean design cause FTech must be init'ed + // before anything else is done. + static bool InitializeWindow( HINSTANCE hInstance ); + static void InitializeFoundation(); + static void InitializeMemory(); + static void ShutdownMemory(); + + // Implement Platform interface. + virtual void InitializePlatform(); + virtual void ShutdownPlatform(); + + virtual void LaunchDashboard(); + virtual void ResetMachine(); + + virtual void DisplaySplashScreen( SplashScreen screenID, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ); + + virtual void DisplaySplashScreen( const char* textureName, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ); + + virtual bool OnDriveError( radFileError error, const char* pDriveName, void* pUserData ); + virtual void OnControllerError(const char *msg); + + HWND GetHwnd() const { return mhWnd; } + + // Set the resolution of the display, or increase the size of the window. + // Returns true if the change was successful, false if resolution is not supported. + bool SetResolution( Resolution res, int bpp, bool fullscreen ); + + Resolution GetResolution() const; + int GetBPP() const; + bool IsFullscreen() const; + + // Implementation of the GameConfigHandler interface + virtual const char* GetConfigName() const; + virtual int GetNumProperties() const; + virtual void LoadDefaults(); + virtual void LoadConfig( ConfigString& config ); + virtual void SaveConfig( ConfigString& config ); + +private: + + // Constructors, Destructors, and Operators + Win32Platform( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ); + virtual ~Win32Platform(); + + // Unused Constructors, Destructors, and Operators + Win32Platform( const Win32Platform& aPlatform ); + Win32Platform& operator=( const Win32Platform& aPlatform ); + + // Methods from Platform + virtual void InitializeFoundationDrive(); + virtual void ShutdownFoundation(); + + virtual void InitializePure3D(); + virtual void ShutdownPure3D(); + + // Initializes the d3d context + void InitializeContext(); + + // Resolution related methods + static void TranslateResolution( Resolution res, int&x, int&y ); + bool IsResolutionSupported( Resolution res, int bpp ) const; + + // Mouse tracking method + static TrackMouseEvent( MOUSETRACKER* pMouseEventTracker ); + static void CALLBACK TrackMouseTimerProc( HWND hWnd, UINT uMsg, UINT idEvent,DWORD dwTime ); + + // Windows methods. + void ResizeWindow(); + static void ShowTheCursor( bool show ); + static LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); + +private: + + // Pointer to the one and only instance of this singleton. + static Win32Platform* spInstance; + + // Private Attributes + // Had to make these static because of the initialization order problem. + static HINSTANCE mhInstance; + static HWND mhWnd; + static HANDLE mhMutex; + static bool mShowCursor; + + // Pure 3D attributes + tPlatform* mpPlatform; + tContext* mpContext; + + // window properties. + Resolution mResolution; + int mbpp; + bool mFullscreen; + int mScreenWidth; + int mScreenHeight; +}; + +#endif // WIN32PLATFORM_H diff --git a/game/code/main/xboxmain.cpp b/game/code/main/xboxmain.cpp new file mode 100644 index 0000000..fca821a --- /dev/null +++ b/game/code/main/xboxmain.cpp @@ -0,0 +1,236 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: xboxmain.cpp +// +// Description: This file contains the main enrty point to the game. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +// Standard Library +#include <string.h> +// Foundation Tech +#include <raddebug.hpp> +#include <radobject.hpp> + +//======================================== +// Project Includes +//======================================== +#include <main/game.h> +#include <main/xboxplatform.h> +#include <main/singletons.h> +#include <main/commandlineoptions.h> +#include <memory/memoryutilities.h> +#include <memory/srrmemory.h> + +//======================================== +// Forward Declarations +//======================================== +static void ProcessCommandLineArguments(); + +static void ProcessCommandLineArgumentsFromFile(); + + +//============================================================================= +// Function: main +//============================================================================= +// +// Description: Main entry point. +// +// Parameters: None. +// +// Returns: None. +// +//============================================================================= +void main() +{ + // + // Pick out and store command line settings. + // + CommandLineOptions::InitDefaults(); + ProcessCommandLineArguments(); + + // + // Have to get FTech setup first so that we can use all the memory services. + // + XboxPlatform::InitializeFoundation(); + + srand (Game::GetRandomSeed ()); + + + // Now disable the default heap + // +#ifndef RAD_RELEASE + tName::SetAllocator (GMA_DEBUG); + + //g_HeapActivityTracker.EnableHeapAllocs (GMA_DEFAULT, false); + //g_HeapActivityTracker.EnableHeapFrees (GMA_DEFAULT, false); +#endif + + HeapMgr()->PushHeap (GMA_PERSISTENT); + + //Process any commandline options from the command.txt file + ProcessCommandLineArgumentsFromFile(); + + + // + // Instantiate all the singletons before doing anything else. + // + CreateSingletons(); + + // + // Construct the platform object. + // + XboxPlatform* pPlatform = XboxPlatform::CreateInstance(); + rAssert( pPlatform != NULL ); + + // + // Create the game object. + // + Game* pGame = Game::CreateInstance( pPlatform ); + rAssert( pGame != NULL ); + + + // + // Initialize the game. + // + pGame->Initialize(); + + HeapMgr()->PopHeap (GMA_PERSISTENT); + + // + // Run it! Control will not return from here until the game is stopped. + // + pGame->Run(); + + // + // Terminate the game (this frees all resources allocated by the game). + // + pGame->Terminate(); + + // + // Destroy the game object. + // + Game::DestroyInstance(); + + // + // Destroy the game and platform (do it in this order in case the game's + // destructor references the platform. + // + XboxPlatform::DestroyInstance(); + + // + // Show some debug output + // +#ifdef RAD_DEBUG + radObject::DumpObjects(); +#endif; + + // + // Dump all the singletons. + // + DestroySingletons(); +} + + +//============================================================================= +// Function: ProcessCommandLineArguments +//============================================================================= +// +// Description: Pick out the command line options and store them. +// +// Parameters: None. +// +// Returns: None. +// +//============================================================================= +void ProcessCommandLineArguments() +{ + // + // None of this gets into the shipping code. + // +#ifndef FINAL + + DWORD dwLaunchMethod; + LAUNCH_DATA launchData; + + XGetLaunchInfo( &dwLaunchMethod, &launchData ); + + if( LDT_FROM_DEBUGGER_CMDLINE == dwLaunchMethod ) + { + LD_FROM_DEBUGGER_CMDLINE* pCmdLine = (LD_FROM_DEBUGGER_CMDLINE*)&launchData; + + char* argument; + argument = strtok( pCmdLine->szCmdLine, " " ); + + rDebugPrintf( "*************************************************************************\n" ); + rDebugPrintf( "Command Line Args:\n" ); + + // + // Pick out all the command line options and store them in GameDB. + // Also dump them to the output for handy dandy viewing. + // + int i = 0; + while( NULL != argument ) + { + rDebugPrintf( "arg%d: %s\n", i++, argument ); + + CommandLineOptions::HandleOption( argument ); + + argument = strtok( NULL, " " ); + } + + if( !CommandLineOptions::Get( CLO_ART_STATS ) ) + { + //CommandLineOptions::HandleOption( "noheaps" ); + } + + + + + + rDebugPrintf( "*************************************************************************\n" ); + } + +#endif // FINAL +} + + + +void ProcessCommandLineArgumentsFromFile() +{ +#ifndef FINAL + + //Chuck: looking for additional command line args being passed in from a file + //its for QA testing etc. + + IRadFile* pfile =NULL; + + ::radFileOpenSync(&pfile,"command.txt", false, OpenExisting ); + + if (pfile != NULL) + { + char commandlinestring [256]; + memset( commandlinestring, 0, sizeof( commandlinestring ) ); + + unsigned int fileSize = 0; + pfile->GetSizeSync( &fileSize ); + pfile->ReadSync(commandlinestring, fileSize); + + //QA created the command line file and wants to pass additional arguements + + char* argument = strtok(commandlinestring," "); + while (argument != NULL) + { + CommandLineOptions::HandleOption(argument); + argument=strtok(NULL," "); + } + pfile->Release(); + } +#endif //FINAL +} //end of Function diff --git a/game/code/main/xboxplatform.cpp b/game/code/main/xboxplatform.cpp new file mode 100644 index 0000000..e71c7d0 --- /dev/null +++ b/game/code/main/xboxplatform.cpp @@ -0,0 +1,1315 @@ +//=========================================================================== +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// Component: XboxPlatform +// +// Description: Abstracts the differences for setting up and shutting down +// the different platforms. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//=========================================================================== + +//======================================== +// System Includes +//======================================== +// Standard Lib +#include <stdlib.h> +#include <string.h> +// Pure 3D +#include <p3d/anim/compositedrawable.hpp> +#include <p3d/anim/expression.hpp> +#include <p3d/anim/multicontroller.hpp> +#include <p3d/anim/polyskin.hpp> +#include <p3d/anim/sequencer.hpp> +#include <p3d/anim/skeleton.hpp> +#include <p3d/camera.hpp> +#include <p3d/gameattr.hpp> +#include <p3d/image.hpp> +#include <p3d/imagefont.hpp> +#include <p3d/light.hpp> +#include <p3d/locator.hpp> +#include <p3d/platform.hpp> +#include <p3d/scenegraph/scenegraph.hpp> +#include <p3d/sprite.hpp> +#include <p3d/utility.hpp> +#include <p3d/texture.hpp> +#include <p3d/file.hpp> +#include <p3d/shader.hpp> +#include <p3d/matrixstack.hpp> +#include <p3d/memory.hpp> +#include <p3d/bmp.hpp> +#include <p3d/png.hpp> +#include <p3d/targa.hpp> +#include <p3d/font.hpp> +#include <p3d/texturefont.hpp> +#include <p3d/unicode.hpp> +// Pure 3D: Loader-specific +#include <render/Loaders/GeometryWrappedLoader.h> +#include <render/Loaders/StaticEntityLoader.h> +#include <render/Loaders/StaticPhysLoader.h> +#include <render/Loaders/TreeDSGLoader.h> +#include <render/Loaders/FenceLoader.h> +#include <render/Loaders/IntersectLoader.h> +#include <render/Loaders/AnimCollLoader.h> +#include <render/Loaders/AnimDSGLoader.h> +#include <render/Loaders/DynaPhysLoader.h> +#include <render/Loaders/InstStatPhysLoader.h> +#include <render/Loaders/InstStatEntityLoader.h> +#include <render/Loaders/WorldSphereLoader.h> +#include <loading/roaddatasegmentloader.h> +#include <render/Loaders/BillboardWrappedLoader.h> +#include <render/Loaders/instparticlesystemloader.h> +#include <render/Loaders/breakableobjectloader.h> +#include <render/Loaders/AnimDynaPhysLoader.h> +#include <render/Loaders/lensflareloader.h> +#include <p3d/shadow.hpp> +#include <p3d/anim/animatedobject.hpp> +#include <p3d/effects/particleloader.hpp> +#include <p3d/effects/opticloader.hpp> +#include <p3d/anim/vertexanimkey.hpp> +#include <stateprop/statepropdata.hpp> + +// Foundation Tech +#include <raddebug.hpp> +#include <radthread.hpp> +#include <radplatform.hpp> +#include <radtime.hpp> +#include <radmemorymonitor.hpp> +#include <raddebugcommunication.hpp> +#include <raddebugwatch.hpp> +#include <radfile.hpp> +#include <radmovie2.hpp> + +//This is so we can get the name of the file that's failing. +#include <../src/radfile/common/requests.hpp> + +// sim - for InstallSimLoaders +#include <simcommon/simutility.hpp> + +// To turn off movies during an error. +#include <presentation/fmvplayer/fmvplayer.h> +#include <presentation/presentation.h> +#include <presentation/language.h> + +//======================================== +// Project Includes +//======================================== +#include <input/inputmanager.h> +#include <main/xboxplatform.h> +#include <main/commandlineoptions.h> +#include <main/game.h> +#include <render/RenderManager/RenderManager.h> +#include <render/Loaders/AllWrappers.h> +#include <memory/srrmemory.h> + +#include <loading/locatorloader.h> +#include <loading/cameradataloader.h> +#include <loading/roadloader.h> +#include <loading/pathloader.h> +#include <loading/intersectionloader.h> +#include <loading/roaddatasegmentloader.h> +#include <atc/atcloader.h> +#include <debug/debuginfo.h> +#include <constants/srrchunks.h> + +#include <radload/radload.hpp> + +#include <main/errorsxbox.h> + +#include <sound/soundmanager.h> + +#include <presentation/presentation.h> +#include <presentation/gui/guitextbible.h> +#include <data/gamedatamanager.h> + +#define XBOX_SECTION "XBOX_SECTION" + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + +// Static pointer to instance of singleton. +XboxPlatform* XboxPlatform::spInstance = NULL; + +//The Adlib font. <sigh> +unsigned char gFont[] = +#include <font/defaultfont.h> + +// +// The depth of the rendering area. This value only has an effect +// when Pure3D has taken over the entire display. When running in +// a window on the desktop, Pure3D uses the same bit depth as the +// desktop. Pure3D only supports 16, and 32 rendering depths. +// +static const int WindowBPP = 32; + +void LoadMemP3DFile( unsigned char* buffer, unsigned int size, tEntityStore* store ) +{ + tFileMem* file = new tFileMem(buffer,size); + file->AddRef(); + file->SetFilename("memfile.p3d"); + p3d::loadManager->GetP3DHandler()->Load( file, p3d::inventory ); + file->Release(); +} + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================== +// XboxPlatform::CreateInstance +//============================================================================== +// +// Description: Creates the XboxPlatform. +// +// Parameters: None. +// +// Return: Pointer to the XboxPlatform. +// +// Constraints: This is a singleton so only one instance is allowed. +// +//============================================================================== +XboxPlatform* XboxPlatform::CreateInstance() +{ +MEMTRACK_PUSH_GROUP( "XboxPlatform" ); + rAssert( spInstance == NULL ); + + spInstance = new(GMA_PERSISTENT) XboxPlatform; + rAssert( spInstance ); +MEMTRACK_POP_GROUP( "XboxPlatform" ); + + return spInstance; +} + +//============================================================================== +// XboxPlatform::GetInstance +//============================================================================== +// +// Description: - Access point for the XboxPlatform singleton. +// +// Parameters: None. +// +// Return: Pointer to the XboxPlatform. +// +// Constraints: This is a singleton so only one instance is allowed. +// +//============================================================================== +XboxPlatform* XboxPlatform::GetInstance() +{ + rAssert( spInstance != NULL ); + + return spInstance; +} + + +//============================================================================== +// XboxPlatform::DestroyInstance +//============================================================================== +// +// Description: Destroy the XboxPlatform. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void XboxPlatform::DestroyInstance() +{ + rAssert( spInstance != NULL ); + + delete( GMA_PERSISTENT, spInstance ); + spInstance = NULL; +} + + + +//============================================================================== +// XboxPlatform::InitializeFoundation +//============================================================================== +// Description: FTech must be setup first so that all the memory services +// are ready to go before we begin allocating anything. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be initialized in a particular order. +// Consult their documentation before changing. +// +//============================================================================== +void XboxPlatform::InitializeFoundation() +{ + // + // Initialize the memory heaps + // + XboxPlatform::InitializeMemory(); + +#ifndef FINAL + // + // Register an out-of-memory display handler in case something goes bad + // while allocating the heaps + // + ::radMemorySetOutOfMemoryCallback( PrintOutOfMemoryMessage, NULL ); +#endif + + // + // Initialize memory monitor by JamesCo. TM. + // + if( CommandLineOptions::Get( CLO_MEMORY_MONITOR ) ) + { + const int KB = 1024; + ::radMemoryMonitorInitialize( 64 * KB, GMA_DEBUG ); + } + + // Setup the memory heaps + // + HeapMgr()->PrepareHeapsStartup (); + + // Seed the heap stack + // + HeapMgr()->PushHeap (GMA_PERSISTENT); + + // + // Initilalize the platform system + // + ::radPlatformInitialize(); + + // + // Initialize the timer system + // + ::radTimeInitialize(); + + // + // Initialize the debug communication system. + // + ::radDbgComTargetInitialize( WinSocket, + radDbgComDefaultPort, // Default + NULL, // Default + GMA_DEBUG ); + + + // + // Initialize the Watcher. + // + ::radDbgWatchInitialize( "SRR2", + 32 * 16384, // 2 * Default + GMA_DEBUG ); + + // + // Initialize the file system. + // + ::radFileInitialize( 50, // Default + 32, // Default + GMA_PERSISTENT ); + + ::radLoadInitialize(); + //radLoad->SetSyncLoading( true ); + + ::radDriveMount(0, GMA_PERSISTENT); + + // + // Initialize the new movie player + // + ::radMovieInitialize2( GMA_PERSISTENT ); + + HeapMgr()->PopHeap (GMA_PERSISTENT); +} + +//============================================================================== +// XboxPlatform::InitializeMemory +//============================================================================== +// +// Description: +// +// Parameters: +// +// Return: +// +//============================================================================== +void XboxPlatform::InitializeMemory() +{ + // + // Only do this once! + // + if( gMemorySystemInitialized == true ) + { + return; + } + + gMemorySystemInitialized = true; + + // + // Initialize the thread system. + // + ::radThreadInitialize(); + + // + // Initialize the memory system. + // + ::radMemoryInitialize(); +} + + + + +//============================================================================== +// XboxPlatform::InitializePlatform +//============================================================================== +// Description: Get the Xbox ready to go. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void XboxPlatform::InitializePlatform() +{ + HeapMgr()->PushHeap (GMA_PERSISTENT); + + // + // Rendering is good. + // + InitializePure3D(); + + // + // Add anything here that needs to be before the drive is opened. + // + DisplaySplashScreen( Error ); // blank screen + + // + // Opening the drive is SLOW... + // + InitializeFoundationDrive(); + + // + // Initialize the controller. + // + GetInputManager()->Init(); + +#ifndef RAD_RELEASE + + // + // Display Title IP address. + // + XNADDR addr; + XNetGetTitleXnAddr( &addr ); + + const int BUFFER_SIZE = 256; + char ip[BUFFER_SIZE]; + XNetInAddrToString( addr.ina, ip, BUFFER_SIZE ); + rDebugString( ip ); + rDebugString( "\n" ); + +#endif // FINAL + + HeapMgr()->PopHeap (GMA_PERSISTENT); + +} + + +//============================================================================== +// XboxPlatform::ShutdownPlatform +//============================================================================== +// Description: Shut down the PS2. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void XboxPlatform::ShutdownPlatform() +{ + ShutdownPure3D(); + ShutdownFoundation(); +} + +//============================================================================= +// XboxPlatform::ResetMachine +//============================================================================= +// Description: resets the xbox +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void XboxPlatform::ResetMachine() +{ + DWORD dwLaunchMethod; + LAUNCH_DATA launchData; + + XGetLaunchInfo( &dwLaunchMethod, &launchData ); + + char build = 0; + +#ifdef RAD_DEBUG + build = 'd'; +#elif defined RAD_TUNE + build = 't'; +#else + build = 'r'; +#endif + + char imageName[64]; + + sprintf( imageName, "D:\\srr2x%c.xbe", build ); + + XLaunchNewImage( imageName, &launchData ); + + //If it failed, try launching default.xbe + XLaunchNewImage( "D:\\default.xbe", &launchData ); + + // + // The game exits, we should never reach this point + // + rAssertMsg( false, "What, you're still here?" ); +} +//============================================================================= +// XboxPlatform::LaunchDashboard +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void XboxPlatform::LaunchDashboard() +{ + + + GetLoadingManager()->CancelPendingRequests(); + + //TODO: Make sure sounds shut down too. + GetSoundManager()->SetMasterVolume( 0.0f ); + + DisplaySplashScreen( FadeToBlack ); + + GetPresentationManager()->StopAll(); + + //Oh boy. + GameDataManager::DestroyInstance(); //Get rid of memcards + + + p3d::loadManager->CancelAll(); + + SoundManager::DestroyInstance(); + + ShutdownPlatform(); + /* ResetMachine();*/ // want to go to dashboard instead + + LD_LAUNCH_DASHBOARD dashboardInfo; + + dashboardInfo.dwReason = XLD_LAUNCH_DASHBOARD_MEMORY; + dashboardInfo.dwContext = 0; + dashboardInfo.dwParameter1 = 'U'; // go directly to hard disk save game menu + dashboardInfo.dwParameter2 = 3; // number of blocks required for a single save game + + XLaunchNewImage( NULL, reinterpret_cast<PLAUNCH_DATA>(&dashboardInfo) ); + + // + // The game exits, we should never reach this point + // + rAssertMsg( false, "What, you're still here?" ); + +} + + +//============================================================================= +// XboxPlatform::DisplaySplashScreen +//============================================================================= +// Description: Comment +// +// Parameters: ( SplashScreen screenID, +// const char* overlayText = NULL, +// float fontScale = 1.0f, +// float textPosX = 0.0f, +// float textPosY = 0.0f, +// tColour textColour, +// int fadeFrames = 3 ) +// +// Return: void +// +//============================================================================= +void XboxPlatform::DisplaySplashScreen( SplashScreen screenID, + const char* overlayText, + float fontScale, + float textPosX, + float textPosY, + tColour textColour, + int fadeFrames ) +{ + HeapMgr()->PushHeap( GMA_TEMP ); + + p3d::inventory->PushSection(); + p3d::inventory->AddSection( XBOX_SECTION ); + p3d::inventory->SelectSection( XBOX_SECTION ); + + P3D_UNICODE unicodeText[256]; + + // Save the current Projection mode so I can restore it later + pddiProjectionMode pm = p3d::pddi->GetProjectionMode(); + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_DEVICE); + + pddiCullMode cm = p3d::pddi->GetCullMode(); + p3d::pddi->SetCullMode(PDDI_CULL_NONE); + + + //CREATE THE FONT + tTextureFont* thisFont = NULL; + + // Convert memory buffer into a texturefont. + // + //p3d::load(gFont, DEFAULTFONT_SIZE, GMA_TEMP); + LoadMemP3DFile( gFont, DEFAULTFONT_SIZE, p3d::inventory ); + + thisFont = p3d::find<tTextureFont>("adlibn_20"); + rAssert( thisFont ); + + thisFont->AddRef(); + tShader* fontShader = thisFont->GetShader(); + //fontShader->SetInt( ) + + + p3d::AsciiToUnicode( overlayText, unicodeText, 256 ); + + // Make the missing letter into somthing I can see + // + thisFont->SetMissingLetter(p3d::ConvertCharToUnicode('j')); + + int a = 0; + + do + { + p3d::pddi->SetColourWrite(true, true, true, true); + p3d::pddi->SetClearColour( pddiColour(0,0,0) ); + p3d::pddi->BeginFrame(); + p3d::pddi->Clear(PDDI_BUFFER_COLOUR); + + //This is for fading in the font and shaders. + int bright = 255; + if (a < fadeFrames) bright = (a * 255) / fadeFrames; + if ( bright > 255 ) bright = 255; + tColour c(bright, bright, bright, 255); + + //Display font + if (overlayText != NULL) + { + tColour colour = textColour; + colour.SetAlpha( bright ); + + thisFont->SetColour( colour ); + + p3d::pddi->SetProjectionMode(PDDI_PROJECTION_ORTHOGRAPHIC); + p3d::stack->Push(); + p3d::stack->LoadIdentity(); + + p3d::stack->Translate( textPosX, textPosY, 1.5f); + float scaleSize = 1.0f / 480.0f; //This is likely good for 528 also. + p3d::stack->Scale(scaleSize * fontScale, scaleSize* fontScale , 1.0f); + + if ( textPosX != 0.0f || textPosY != 0.0f ) + { + thisFont->DisplayText( unicodeText ); + } + else + { + thisFont->DisplayText( unicodeText, 3 ); + } + + p3d::stack->Pop(); + } + + p3d::pddi->EndFrame(); + p3d::context->SwapBuffers(); + + ++a; + + } while (a <= fadeFrames); + + // [ps]: flush out this screen now. + if ( screenID == FadeToBlack ) + { + p3d::pddi->Clear(PDDI_BUFFER_ALL); + } + + p3d::pddi->SetCullMode(cm); + p3d::pddi->SetProjectionMode(pm); + + //Should do this after a vsync. + thisFont->Release(); + + p3d::inventory->RemoveSectionElements(XBOX_SECTION); + p3d::inventory->DeleteSection(XBOX_SECTION); + p3d::inventory->PopSection(); + + HeapMgr()->PopHeap( GMA_TEMP ); +} + + +//============================================================================= +// XboxPlatform::DisplaySplashScreen +//============================================================================= +// Description: Comment +// +// Parameters: ( const char* textureName, +// const char* overlayText = NULL, +// float fontScale = 1.0f, +// float textPosX = 0.0f, +// float textPosY = 0.0f, +// tColour textColour, +// int fadeFrames = 3 ) +// +// Return: void +// +//============================================================================= +void XboxPlatform::DisplaySplashScreen( const char* textureName, + const char* overlayText, + float fontScale, + float textPosX, + float textPosY, + tColour textColour, + int fadeFrames ) +{ +} + + +//============================================================================= +// XboxPlatform::OnDriveError +//============================================================================= +// Description: Comment +// +// Parameters: ( radFileError error, const char* pDriveName, void* pUserData ) +// +// Return: bool +// +//============================================================================= +bool XboxPlatform::OnDriveError( radFileError error, const char* pDriveName, void* pUserData ) +{ + bool inFrame = p3d::context->InFrame(); + + const int NUM_RADFILE_ERRORS = 13; + unsigned int errorIndex = error; + +#ifdef PAL + switch( CGuiTextBible::GetCurrentLanguage() ) + { + case Scrooby::XL_FRENCH: + { + errorIndex += 1 * NUM_RADFILE_ERRORS; + + break; + } + case Scrooby::XL_GERMAN: + { + errorIndex += 2 * NUM_RADFILE_ERRORS; + + break; + } + case Scrooby::XL_SPANISH: + { + errorIndex += 3 * NUM_RADFILE_ERRORS; + + break; + } + default: + { + if ( !CGuiTextBible::IsTextBibleLoaded() ) + { + switch ( Language::GetHardwareLanguage() ) + { + case Language::FRENCH: + { + errorIndex += 1 * NUM_RADFILE_ERRORS; + break; + } + case Language::GERMAN: + { + errorIndex += 2 * NUM_RADFILE_ERRORS; + break; + } + case Language::SPANISH: + { + errorIndex += 3 * NUM_RADFILE_ERRORS; + break; + } + } + } + break; + } + } +#endif // PAL + + rAssert( errorIndex < sizeof( ERROR_STRINGS ) / sizeof( ERROR_STRINGS[ 0 ] ) ); + + switch ( error ) + { + case Success: + { + if ( mErrorState != NONE ) + { + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( FadeToBlack ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = NONE; + mPauseForError = false; + } + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->UnPause( ); + } + else + { + GetSoundManager()->ResumeAfterMovie(); + } + return true; + break; + } + case FileNotFound: + { + if ( CommandLineOptions::Get( CLO_FILE_NOT_FOUND ) ) + { + rAssert( pUserData != NULL ); + + radFileRequest* request = static_cast<radFileRequest*>( pUserData ); + const char* fileName = request->GetFilename(); + + //Get rid of the slashes. + unsigned int i; + unsigned int lastIndex = 0; + for ( i = 0; i < strlen( fileName ); ++i ) + { + if ( fileName[ i ] == '\\' ) + { + lastIndex = i; + } + } + + unsigned int adjustedIndex = lastIndex == 0 ? lastIndex : lastIndex + 1; + + char adjustedName[32]; + strncpy( adjustedName, &fileName[adjustedIndex], ( strlen( fileName ) - lastIndex ) ); + adjustedName[ strlen( fileName ) - lastIndex ] = '\0'; + + char errorString[256]; + sprintf( errorString, "%s:\n%s", ERROR_STRINGS[errorIndex], adjustedName ); + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( Error, errorString, 1.0f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = P_ERROR; + mPauseForError = true; + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->Pause( ); + } + else + { + GetSoundManager()->StopForMovie(); + } + return true; + } + else + { + error = HardwareFailure; + //Fall through. + } + } + case ShellOpen: + case WrongMedia: + case NoMedia: + case HardwareFailure: + { + //This could be the wrong disc. + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( Error, ERROR_STRINGS[errorIndex], 1.0f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = P_ERROR; + mPauseForError = true; + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->Pause( ); + } + else + { + GetSoundManager()->StopForMovie(); + } + return true; + } + default: + { + //Others are not supported. + rAssert( false ); + } + } + + return false; +} + +void XboxPlatform::OnControllerError(const char *msg) +{ + bool inFrame = p3d::context->InFrame(); + + if ( inFrame ) p3d::context->EndFrame( true ); + DisplaySplashScreen( Error, msg, 0.7f, 0.0f, 0.0f, tColour(255, 255, 255), 0 ); + if ( inFrame ) p3d::context->BeginFrame( ); + mErrorState = CTL_ERROR; + mPauseForError = true; + + if ( GetPresentationManager()->GetFMVPlayer()->IsPlaying() ) + { + GetPresentationManager()->GetFMVPlayer()->Pause( ); + } + else + { + GetSoundManager()->StopForMovie(); + } +} + + +//****************************************************************************** +// +// Protected Member Functions +// +//****************************************************************************** + + +//============================================================================== +// XboxPlatform::InitializeFoundationDrive +//============================================================================== +// Description: Get FTech ready to go. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be initialized in a particular order. +// Consult their documentation before changing. +// +//============================================================================== +void XboxPlatform::InitializeFoundationDrive() +{ + // + // No shadow drive on the Xbox. + // +// ::radDriveSetShadow( false ); + + // + // Get the CDROM drive and hold it open for the life of the game. + // This is a costly operation so we only want to do it once. + // + + ::radDriveOpen( &mpIRadDrive, + "D:", + NormalPriority, // Default + GMA_PERSISTENT ); + + rAssert( mpIRadDrive != NULL ); + + mpIRadDrive->RegisterErrorHandler( this, NULL ); + + // + // Set the read-write granulatity to prevent operations from + // being partitioned. + // +// const int GRANULARITY = 20 * 1024 * 1024; +// mpIRadDrive->SetReadWriteGranularity( GRANULARITY ); +} + + +//============================================================================== +// XboxPlatform::ShutdownFoundation +//============================================================================== +// Description: Shut down Foundation Tech. +// +// Parameters: None. +// +// Return: None. +// +// Constraints: The FTech systems must be terminated in the reverse order that +// they were initialized in. +// +//============================================================================== +void XboxPlatform::ShutdownFoundation() +{ + // + // Release the drive we've held open since the begining. + // + mpIRadDrive->Release(); + mpIRadDrive = NULL; + + // + // Shutdown the systems in the reverse order. + // + ::radMovieTerminate2(); + ::radDriveUnmount(); + ::radLoadTerminate(); + ::radFileTerminate(); + ::radDbgWatchTerminate(); + if( CommandLineOptions::Get( CLO_MEMORY_MONITOR ) ) + { + ::radMemoryMonitorTerminate(); + } + ::radDbgComTargetTerminate(); + ::radTimeTerminate(); + ::radPlatformTerminate(); + ::radMemoryTerminate(); + ::radThreadTerminate(); +} + + +//============================================================================== +// XboxPlatform::InitializePure3D +//============================================================================== +// Description: Get Pure3D ready to go. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void XboxPlatform::InitializePure3D() +{ +MEMTRACK_PUSH_GROUP( "XboxPlatform" ); +// p3d::SetMemAllocator( p3d::ALLOC_DEFAULT, GMA_PERSISTENT ); +// p3d::SetMemAllocator( p3d::ALLOC_LOADED, GMA_LEVEL ); + + // + // Initialise Pure3D platform object. + // This call differs between different platforms. The Win32 version, + // for example requires the application instance to be passed in. + // + mpPlatform = tPlatform::Create(); + rAssert( mpPlatform != NULL ); + + // + // Initialiase the Pure3D context object. + // We have to create on of these for every window, and for every PDDI + // instance we use for rendering. Since almost every application only + // uses one window and PDDI library at a time, we one need to create one + // context. + // + tContextInitData init; + + // + // All applications should supply PDDI_BUFFER_COLOUR. PDDI_BUFFER_DEPTH + // specifies that we also want to allocate a Z-buffer. Some applications + // may want to also specifiy PDDI_BUFFER_STENCIL to allocate a stencil + // buffer. + // + init.bufferMask = PDDI_BUFFER_COLOUR | PDDI_BUFFER_DEPTH | PDDI_BUFFER_STENCIL; + init.enableSnapshot = true; + + // + // These values only take effect in fullscreen mode. In windowed mode, the + // dimensions of the window define the rendering area. We'll define them + // anyway for completeness sake. + // + // +// init.xsize = 1920; +// init.ysize = 1080; + init.xsize = 720; + init.ysize = 480; + init.allowWidescreen = true; + init.allowHDTV = true; + + // + // Depth of the rendering buffer. Again, this value only works in + // fullscreen mode. In window mode, the depth of the desktop is used. + // This value should be either 16 or 32. Depths of 4, 8, and 24 are not + // supported by most 3D hardware, and not by Pure3D. + // + init.bpp = WindowBPP; + + // + // Select anti-aliasing mode. + // +// init.antiAlias = tContextInitData::NONE; + init.antiAlias = tContextInitData::MULTISAMPLE_2_QUINCUNX; +// init.antiAlias = tContextInitData::MULTISAMPLE_4_GAUSSIAN; + + //TODO: Investigate VSync +// init.lockToVsync = true; + init.lockToVsync = false; + + // + // Create the context. + // + mpContext = mpPlatform->CreateContext( &init ); + rAssert( mpContext != NULL ); + + // + // Assign this context to the platform. + // + mpPlatform->SetActiveContext( mpContext ); + p3d::pddi->EnableZBuffer( true ); + + // + // This call installs chunk handlers for all the primary chunk types that + // Pure3D supports. This includes textures, materials, geometries, and the + // like. + // +// p3d::InstallDefaultLoaders(); + P3DASSERT(p3d::context); + tP3DFileHandler* p3d = new(GMA_PERSISTENT) tP3DFileHandler; +// p3d::loadManager->AddHandler(p3d, "p3d"); + p3d::context->GetLoadManager()->AddHandler(p3d, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tPNGHandler, "png"); + + if( CommandLineOptions::Get( CLO_FE_UNJOINED ) ) + { + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tBMPHandler, "bmp"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tTargaHandler, "tga"); + } + else + { + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tBMPHandler, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tPNGHandler, "p3d"); + p3d::context->GetLoadManager()->AddHandler(new(GMA_PERSISTENT) tTargaHandler, "p3d"); + } + +// p3d->AddHandler(new tGeometryLoader); +// GeometryWrappedLoader* pGWL = new GeometryWrappedLoader; + GeometryWrappedLoader* pGWL = + (GeometryWrappedLoader*)GetAllWrappers()->mpLoader( AllWrappers::msGeometry ); + pGWL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pGWL ); + + StaticEntityLoader* pSEL = + (StaticEntityLoader*)GetAllWrappers()->mpLoader( AllWrappers::msStaticEntity ); + pSEL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pSEL ); + + StaticPhysLoader* pSPL = + (StaticPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msStaticPhys ); + pSPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pSPL ); + + TreeDSGLoader* pTDL = + (TreeDSGLoader*)GetAllWrappers()->mpLoader( AllWrappers::msTreeDSG ); + pTDL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pTDL ); + + FenceLoader* pFL = + (FenceLoader*)GetAllWrappers()->mpLoader( AllWrappers::msFenceEntity ); + pFL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pFL ); + + IntersectLoader* pIL = + (IntersectLoader*)GetAllWrappers()->mpLoader( AllWrappers::msIntersectDSG ); + pIL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pIL ); + + AnimCollLoader* pACL = + (AnimCollLoader*)GetAllWrappers()->mpLoader( AllWrappers::msAnimCollEntity ); + pACL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pACL ); + + AnimDSGLoader* pAnimDSGLoader = + (AnimDSGLoader*)GetAllWrappers()->mpLoader( AllWrappers::msAnimEntity ); + pAnimDSGLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimDSGLoader ); + + + DynaPhysLoader* pDPL = + (DynaPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msDynaPhys ); + pDPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pDPL ); + + InstStatPhysLoader* pISPL = + (InstStatPhysLoader*)GetAllWrappers()->mpLoader( AllWrappers::msInstStatPhys ); + pISPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pISPL ); + + InstStatEntityLoader* pISEL = + (InstStatEntityLoader*)GetAllWrappers()->mpLoader( AllWrappers::msInstStatEntity ); + pISEL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pISEL ); + + LocatorLoader* pLL = + (LocatorLoader*)GetAllWrappers()->mpLoader( AllWrappers::msLocator); + pLL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pLL ); + + RoadLoader* pRL = + (RoadLoader*)GetAllWrappers()->mpLoader( AllWrappers::msRoadSegment); + pRL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pRL ); + + PathLoader* pPL = + (PathLoader*)GetAllWrappers()->mpLoader( AllWrappers::msPathSegment); + pPL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pPL ); + + WorldSphereLoader* pWSL = + (WorldSphereLoader*)GetAllWrappers()->mpLoader( AllWrappers::msWorldSphere); + pWSL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pWSL ); + + LensFlareLoader* pLSL = + (LensFlareLoader*)GetAllWrappers()->mpLoader( AllWrappers::msLensFlare); + pLSL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pLSL ); + + BillboardWrappedLoader* pBWL = + (BillboardWrappedLoader*)GetAllWrappers()->mpLoader( AllWrappers::msBillboard); + pBWL->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pBWL ); + + + InstParticleSystemLoader* pInstParticleSystemLoader = + (InstParticleSystemLoader*) GetAllWrappers()->mpLoader( AllWrappers::msInstParticleSystem); + pInstParticleSystemLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pInstParticleSystemLoader ); + + BreakableObjectLoader* pBreakableObjectLoader = + (BreakableObjectLoader*) GetAllWrappers()->mpLoader( AllWrappers::msBreakableObject); + pBreakableObjectLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pBreakableObjectLoader ); + + AnimDynaPhysLoader* pAnimDynaPhysLoader = + (AnimDynaPhysLoader*) GetAllWrappers()->mpLoader( AllWrappers::msAnimDynaPhys); + pAnimDynaPhysLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimDynaPhysLoader ); + + AnimDynaPhysWrapperLoader* pAnimWrapperLoader = + (AnimDynaPhysWrapperLoader*) GetAllWrappers()->mpLoader( AllWrappers::msAnimDynaPhysWrapper); + pAnimWrapperLoader->SetRegdListener( GetRenderManager(), 0 ); + p3d->AddHandler( pAnimWrapperLoader ); + + p3d->AddHandler(new(GMA_PERSISTENT) tTextureLoader); + p3d->AddHandler( new(GMA_PERSISTENT) tSetLoader ); + p3d->AddHandler(new(GMA_PERSISTENT) tShaderLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tCameraLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tGameAttrLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tLightLoader); + + p3d->AddHandler(new(GMA_PERSISTENT) tLocatorLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tLightGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tImageLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tTextureFontLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tImageFontLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tSpriteLoader); + //p3d->AddHandler(new(GMA_PERSISTENT) tBillboardQuadGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tSkeletonLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tPolySkinLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tCompositeDrawableLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tVertexAnimKeyLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tAnimationLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tFrameControllerLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tMultiControllerLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tAnimatedObjectFactoryLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tAnimatedObjectLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tParticleSystemFactoryLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tParticleSystemLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tLensFlareGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) sg::Loader); + + p3d->AddHandler(new(GMA_PERSISTENT) tExpressionGroupLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tExpressionMixerLoader); + p3d->AddHandler(new(GMA_PERSISTENT) tExpressionLoader); + + //ATCloader, hope this doesnt blow up + p3d->AddHandler(new(GMA_PERSISTENT) ATCLoader); + + //p3d->AddHandler(new p3d::tIgnoreLoader); + + tSEQFileHandler* sequencerFileHandler = new(GMA_PERSISTENT) tSEQFileHandler; + p3d::loadManager->AddHandler(sequencerFileHandler, "seq"); + + // sim lib + sim::InstallSimLoaders(); + + p3d->AddHandler(new(GMA_PERSISTENT) CameraDataLoader, SRR2::ChunkID::FOLLOWCAM); + p3d->AddHandler(new(GMA_PERSISTENT) CameraDataLoader, SRR2::ChunkID::WALKERCAM); + p3d->AddHandler(new(GMA_PERSISTENT) IntersectionLoader); + //p3d->AddHandler(new(GMA_PERSISTENT) RoadLoader); + p3d->AddHandler(new(GMA_PERSISTENT) RoadDataSegmentLoader); + p3d->AddHandler(new(GMA_PERSISTENT) CStatePropDataLoader); +MEMTRACK_POP_GROUP( "XboxPlatform" ); +} + + +//============================================================================== +// XboxPlatform::ShutdownPure3D +//============================================================================== +// Description: Clean up and shut down Pure3D. +// +// Parameters: None. +// +// Return: None. +// +//============================================================================== +void XboxPlatform::ShutdownPure3D() +{ + // + // Clean-up the Pure3D Inventory + // + p3d::inventory->RemoveAllElements(); + p3d::inventory->DeleteAllSections(); + + // + // Clean-up the space taken by the Pure 3D context. + // + if( mpContext != NULL ) + { + mpPlatform->DestroyContext( mpContext ); + mpContext = NULL; + } + + // + // Clean-up the space taken by the Pure 3D platform. + // + if( mpPlatform != NULL ) + { + tPlatform::Destroy( mpPlatform ); + mpPlatform = NULL; + } +} + + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** + +//============================================================================== +// XboxPlatform::XboxPlatform +//============================================================================== +// Description: Constructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +XboxPlatform::XboxPlatform() : + mpPlatform( NULL ), + mpContext( NULL ) +{ +} + + +//============================================================================== +// XboxPlatform::~XboxPlatform +//============================================================================== +// Description: Destructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +XboxPlatform::~XboxPlatform() +{ +} + + diff --git a/game/code/main/xboxplatform.h b/game/code/main/xboxplatform.h new file mode 100644 index 0000000..1465716 --- /dev/null +++ b/game/code/main/xboxplatform.h @@ -0,0 +1,99 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// Component: XboxPlatform +// +// Description: Abstracts the differences for setting up and shutting down +// the different platforms. +// +// History: + Stolen and cleaned up from Svxy -- Darwin Chau +// +//============================================================================= + +#ifndef XBOXPLATFORM_H +#define XBOXPLATFORM_H + +//======================================== +// Nested Includes +//======================================== +#include "platform.h" // base class + +//======================================== +// Forward References +//======================================== +struct IRadMemoryHeap; +class tPlatform; +class tContext; + +//============================================================================= +// +// Synopsis: Provides abstraction for setting up and closing down the XBox. +// +//============================================================================= +class XboxPlatform : public Platform +{ + public: + + // Static Methods for accessing this singleton. + static XboxPlatform* CreateInstance(); + static XboxPlatform* GetInstance(); + static void DestroyInstance(); + + // Had to workaround our nice clean design cause FTech must be init'ed + // before anything else is done. + static void InitializeFoundation(); + static void InitializeMemory(); + + // Implement Platform interface. + virtual void InitializePlatform(); + virtual void ShutdownPlatform(); + + virtual void LaunchDashboard(); + virtual void ResetMachine(); + virtual void DisplaySplashScreen( SplashScreen screenID, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ); + + virtual void DisplaySplashScreen( const char* textureName, + const char* overlayText = NULL, + float fontScale = 1.0f, + float textPosX = 0.0f, + float textPosY = 0.0f, + tColour textColour = tColour( 255,255,255 ), + int fadeFrames = 3 ); + + virtual bool OnDriveError( radFileError error, const char* pDriveName, void* pUserData ); + virtual void OnControllerError(const char *msg); + + + protected: + + virtual void InitializeFoundationDrive(); + virtual void ShutdownFoundation(); + + virtual void InitializePure3D(); + virtual void ShutdownPure3D(); + + private: + + // Constructors, Destructors, and Operators + XboxPlatform(); + virtual ~XboxPlatform(); + + // Unused Constructors, Destructors, and Operators + XboxPlatform( const XboxPlatform& aPlatform ); + XboxPlatform& operator=( const XboxPlatform& aPlatform ); + + // Pointer to the one and only instance of this singleton. + static XboxPlatform* spInstance; + + // Pure 3D attributes + tPlatform* mpPlatform; + tContext* mpContext; +}; + +#endif // XBOXPLATFORM_H |