* Dialog box rendering was off a few pixels due to me forgetting to remove some tests I did, fixed * Black at index 255 and white at index 0 is now forced during bmp loading. Windows does it, photoshop doesn't, but older versions of Dink (directx) seemed to do it so going with that * Invalid sprite sent to freeze/unfreeze will no longer crash the game (bug was also in original 1.08) * Added hardening to check valid input on many script functions, will stop "sometimes" crashes based on bad scripting as well as log them * Crash logging should show correct function names. I mean it this time! - Some mobile related files added now that I'm starting to work on that side too git-svn-id: svn://rtsoft.com/rtsvn/projects/RTDink@1512 353e56fe-9613-0410-8469-b96ad8e6f29c
1091 lines
26 KiB
C++
1091 lines
26 KiB
C++
/*
|
|
* App.cpp
|
|
* Created by Seth Robinson on 3/6/09.
|
|
* For license info, check the license.txt file that should have come with this.
|
|
*
|
|
*/
|
|
#include "PlatformPrecomp.h"
|
|
#include "App.h"
|
|
#include "GUI/MainMenu.h"
|
|
#include "Entity/EntityUtils.h"//create the classes that our globally library expects to exist somewhere.
|
|
#include "dink/dink.h"
|
|
#include "GUI/GameMenu.h"
|
|
#include "util/archive/TarHandler.h"
|
|
#include "Renderer/SoftSurface.h"
|
|
#include "GUI/BrowseMenu.h"
|
|
#include "Entity/SliderComponent.h"
|
|
#include "GUI/OptionsMenu.h"
|
|
#include "FileSystem/FileSystemZip.h"
|
|
#include "Entity/ArcadeInputComponent.h"
|
|
#include "GUI/ExpiredMenu.h"
|
|
#include <time.h>
|
|
#include "Gamepad/GamepadManager.h"
|
|
#include "Gamepad/GamepadProvideriCade.h"
|
|
|
|
#ifdef WINAPI
|
|
|
|
extern int g_winVideoScreenX;
|
|
extern int g_winVideoScreenY;
|
|
extern bool g_bUseBorderlessFullscreenOnWindows;
|
|
void AddText(const char *tex, const char *filename);
|
|
|
|
#include "StackWalker/StackUtils.h"
|
|
extern bool g_bIsFullScreen;
|
|
#endif
|
|
|
|
extern bool g_script_debug_mode;
|
|
extern Surface g_transitionSurf;
|
|
|
|
#ifdef RT_MOGA_ENABLED
|
|
#include "Gamepad/GamepadProviderMoga.h"
|
|
#endif
|
|
|
|
#ifdef RT_CHARTBOOST_ENABLED
|
|
#include "Ad/AdProviderChartBoost.h"
|
|
#endif
|
|
|
|
#ifdef RT_IOS_60BEAT_GAMEPAD_SUPPORT
|
|
#include "Gamepad/GamepadProvider60Beat.h"
|
|
#endif
|
|
|
|
//#define FORCE_DMOD_SUPPORT
|
|
|
|
MessageManager g_messageManager;
|
|
MessageManager * GetMessageManager() {return &g_messageManager;}
|
|
|
|
FileManager g_fileManager;
|
|
FileManager * GetFileManager() {return &g_fileManager;}
|
|
|
|
GamepadManager g_gamepadManager;
|
|
GamepadManager * GetGamepadManager() {return &g_gamepadManager;}
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#if TARGET_OS_IPHONE == 1
|
|
//it's an iPhone or iPad
|
|
//#include "Audio/AudioManagerOS.h"
|
|
//AudioManagerOS g_audioManager;
|
|
//#include "Audio/AudioManagerDenshion.h"
|
|
|
|
//AudioManagerDenshion g_audioManager;
|
|
|
|
#include "Audio/AudioManagerFMODStudio.h"
|
|
AudioManagerFMOD g_audioManager;
|
|
#else
|
|
//it's being compiled as a native OSX app
|
|
#include "Audio/AudioManagerFMODStudio.h"
|
|
AudioManagerFMOD g_audioManager; //dummy with no sound
|
|
|
|
//in theory, CocosDenshion should work for the Mac builds, but right now it seems to want a big chunk of
|
|
//Cocos2d included so I'm not fiddling with it for now
|
|
|
|
//#include "Audio/AudioManagerDenshion.h"
|
|
//AudioManagerDenshion g_audioManager;
|
|
#endif
|
|
|
|
#else
|
|
|
|
#if defined RT_WEBOS || defined RTLINUX
|
|
#include "Audio/AudioManagerSDL.h"
|
|
AudioManagerSDL g_audioManager; //sound in windows and WebOS
|
|
//AudioManager g_audioManager; //to disable sound
|
|
#elif defined ANDROID_NDK
|
|
#include "Audio/AudioManagerAndroid.h"
|
|
AudioManagerAndroid g_audioManager; //sound for android
|
|
#elif defined PLATFORM_BBX
|
|
#include "Audio/AudioManagerBBX.h"
|
|
//AudioManager g_audioManager; //to disable sound
|
|
AudioManagerBBX g_audioManager;
|
|
#elif defined PLATFORM_HTML5
|
|
#include "Audio/AudioManagerSDL.h"
|
|
//AudioManager g_audioManager; //to disable sound
|
|
AudioManagerSDL g_audioManager;
|
|
|
|
#elif defined PLATFORM_FLASH
|
|
//AudioManager g_audioManager; //to disable sound
|
|
#include "Audio/AudioManagerFlash.h"
|
|
AudioManagerFlash g_audioManager;
|
|
#else
|
|
|
|
//in windows
|
|
//AudioManager g_audioManager; //to disable sound
|
|
|
|
#ifdef RT_FLASH_TEST
|
|
#include "Audio/AudioManagerFlash.h"
|
|
AudioManagerFlash g_audioManager;
|
|
#else
|
|
// #include "Audio/AudioManagerAudiere.h"
|
|
// AudioManagerAudiere g_audioManager; //Use Audiere for audio
|
|
|
|
#include "Gamepad/GamepadProviderDirectX.h"
|
|
#include "Audio/AudioManagerFMODStudio.h"
|
|
|
|
AudioManagerFMOD g_audioManager; //if we wanted FMOD sound in windows
|
|
#endif
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ANDROID_NDK
|
|
void SetPreferSDCardForStorage(bool bNew);
|
|
#endif
|
|
|
|
AudioManager * GetAudioManager(){return &g_audioManager;}
|
|
|
|
App *g_pApp = NULL;
|
|
BaseApp * GetBaseApp()
|
|
{
|
|
if (!g_pApp)
|
|
{
|
|
g_pApp = new App;
|
|
}
|
|
|
|
return g_pApp;
|
|
}
|
|
|
|
App * GetApp()
|
|
{
|
|
return g_pApp;
|
|
}
|
|
|
|
const char * GetAppName()
|
|
{
|
|
|
|
#ifdef WINAPI
|
|
|
|
if (GetApp())
|
|
{
|
|
static char name[64];
|
|
sprintf(name, "Dink Smallwood HD %s", GetApp()->GetVersionString().c_str());
|
|
return name;
|
|
}
|
|
#endif
|
|
|
|
return "Dink Smallwood HD";
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
App::App()
|
|
{
|
|
m_logFileHandle = NULL;
|
|
|
|
http://www.rtsoft.com
|
|
|
|
m_bGhostMode = false;
|
|
#ifdef ANDROID_NDK
|
|
SetPreferSDCardForStorage(true);
|
|
#endif
|
|
|
|
m_bDidPostInit = false;
|
|
m_bHasDMODSupport = true;
|
|
//for mobiles
|
|
m_version = 1.83f;
|
|
m_versionString = "V1.8.3";
|
|
m_build = 1;
|
|
m_bCheatsEnabled = false;
|
|
|
|
//for Win/mac
|
|
m_desktopVersion = m_version;
|
|
m_desktopVersionString = m_versionString;
|
|
m_desktopBuild = 1;
|
|
m_bForceAspectRatio = true;
|
|
|
|
}
|
|
|
|
App::~App()
|
|
{
|
|
|
|
assert(m_logFileHandle);
|
|
if (m_logFileHandle)
|
|
fclose(m_logFileHandle);
|
|
|
|
|
|
//L_ParticleSystem::deinit();
|
|
}
|
|
|
|
|
|
void App::AddIcadeProvider()
|
|
{
|
|
GamepadProvider * pProv = GetGamepadManager()->AddProvider(new GamepadProvideriCade); //use iCade, this actually should work with any platform...
|
|
GetBaseApp()->SetAllowScreenDimming(false);
|
|
if (pProv)
|
|
{
|
|
pProv->m_sig_failed_to_connect.connect(1, boost::bind(&App::OniCadeDisconnected, this, _1));
|
|
}
|
|
}
|
|
|
|
bool App::GetForceAspectRatio()
|
|
{
|
|
return m_bForceAspectRatio;
|
|
}
|
|
|
|
bool App::UseClassicEscapeMenu()
|
|
{
|
|
if (GetEmulatedPlatformID() == PLATFORM_ID_WINDOWS)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void App::OniCadeDisconnected(GamepadProvider *pProvider)
|
|
{
|
|
LogMsg("Dealing with icade disconnect");
|
|
GetGamepadManager()->RemoveProviderByName("iCade");
|
|
GetApp()->RemoveAndroidKeyboardKeys();
|
|
|
|
GetApp()->GetVar("check_icade")->Set(uint32(0));
|
|
|
|
Entity *pOptions = GetEntityRoot()->GetEntityByName("OptionsMenu");
|
|
if (pOptions)
|
|
{
|
|
LogMsg("Found options");
|
|
Entity *pCheckBox = pOptions->GetEntityByName("check_icade");
|
|
if (pCheckBox)
|
|
{
|
|
LogMsg("Found checkbox");
|
|
SetCheckBoxChecked(pCheckBox, false, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool App::DoesCommandLineParmExist(string parm)
|
|
{
|
|
vector<string> parms = GetBaseApp()->GetCommandLineParms();
|
|
parm = ToLowerCaseString(parm);
|
|
|
|
for (int i = 0; i < parms.size(); i++)
|
|
{
|
|
if (ToLowerCaseString(parms[i]) == parm) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool App::Init()
|
|
{
|
|
|
|
#ifdef WINAPI
|
|
InitUnhandledExceptionFilter();
|
|
#endif
|
|
|
|
|
|
//GetBaseApp()->SetDisableSubPixelBlits(true);
|
|
|
|
SetDefaultButtonStyle(Button2DComponent::BUTTON_STYLE_CLICK_ON_TOUCH_RELEASE);
|
|
SetManualRotationMode(false);
|
|
|
|
bool bScaleScreenActive = true; //if true, we'll stretch every screen to the coords below
|
|
int scaleToX = 480;
|
|
int scaleToY = 320;
|
|
|
|
if (IsTabletSize() || IsDesktop())
|
|
{
|
|
scaleToX = 1024;
|
|
scaleToY = 768;
|
|
}
|
|
|
|
|
|
/*
|
|
if (IsIphoneSize || IsIphone4Size || IsIPADSize)
|
|
{
|
|
bScaleScreenActive = false;
|
|
}
|
|
*/
|
|
|
|
switch (GetEmulatedPlatformID())
|
|
{
|
|
//special handling for certain platforms to tweak the video settings
|
|
|
|
case PLATFORM_ID_WEBOS:
|
|
//if we do this, everything will be stretched/zoomed to fit the screen
|
|
if (IsIPADSize)
|
|
{
|
|
//doesn't need rotation
|
|
SetLockedLandscape(false); //because it's set in the app manifest, we don't have to rotate ourselves
|
|
SetupScreenInfo(GetPrimaryGLX(), GetPrimaryGLY(), ORIENTATION_PORTRAIT);
|
|
if (bScaleScreenActive)
|
|
SetupFakePrimaryScreenSize(scaleToX,scaleToY); //game will think it's this size, and will be scaled up
|
|
}
|
|
else
|
|
{
|
|
//but the phones do
|
|
SetLockedLandscape(true); //we don't allow portrait mode for this game
|
|
if (bScaleScreenActive)
|
|
SetupFakePrimaryScreenSize(scaleToX,scaleToY); //game will think it's this size, and will be scaled up
|
|
}
|
|
|
|
break;
|
|
|
|
case PLATFORM_ID_IOS:
|
|
SetLockedLandscape(true); //we stay in portrait but manually rotate, gives better fps on older devices
|
|
if (bScaleScreenActive)
|
|
SetupFakePrimaryScreenSize(scaleToX,scaleToY); //game will think it's this size, and will be scaled up
|
|
break;
|
|
|
|
default:
|
|
|
|
//Default settings for other platforms
|
|
|
|
SetLockedLandscape(false); //we don't allow portrait mode for this game
|
|
SetupScreenInfo(GetPrimaryGLX(), GetPrimaryGLY(), ORIENTATION_PORTRAIT);
|
|
if (bScaleScreenActive)
|
|
SetupFakePrimaryScreenSize(scaleToX,scaleToY); //game will think it's this size, and will be scaled up
|
|
}
|
|
|
|
|
|
//L_ParticleSystem::init(2000);
|
|
SetInputMode(INPUT_MODE_SEPARATE_MOVE_TOUCHES); //this game has so much move touching, I handle them separately for performance reasons
|
|
|
|
if (m_bInitted)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (!BaseApp::Init())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
LogMsg("Initializing Dink HD %s", GetVersionString().c_str());
|
|
|
|
vector<string> parm = GetBaseApp()->GetCommandLineParms();
|
|
|
|
string parms;
|
|
for (int i = 0; i < parm.size(); i++)
|
|
{
|
|
if (i != 0) parms += " ";
|
|
parms += parm[i];
|
|
}
|
|
|
|
if (!parm.empty())
|
|
{
|
|
string text = string("Run with parms: " + string(parms) + "\r\n\r\n");
|
|
|
|
#ifdef WINAPI
|
|
OutputDebugString(text.c_str());
|
|
#endif
|
|
AddTextToLog(text.c_str(), (GetSavePath() + "log.txt").c_str());
|
|
}
|
|
|
|
|
|
m_adManager.Init();
|
|
|
|
#ifdef RT_CHARTBOOST_ENABLED
|
|
AdProviderChartBoost *pProvider = new AdProviderChartBoost;
|
|
|
|
#ifdef PLATFORM_ANDROID
|
|
assert(!"No longer using chartboost!");
|
|
|
|
pProvider->SetupInfo("", ""); //Dink HD Android
|
|
|
|
#else
|
|
|
|
pProvider->SetupInfo("", ""); //Dink HD iOS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
m_adManager.AddProvider(pProvider);
|
|
pProvider->CacheShowInterstitial();
|
|
// pProvider->CacheShowMoreApps();
|
|
|
|
m_adManager.GetProviderByType(AD_PROVIDER_CHARTBOOST)->ShowInterstitial();
|
|
//m_adManager.GetProviderByType(AD_PROVIDER_CHARTBOOST)->ShowMoreApps();
|
|
#endif
|
|
|
|
LogMsg("Save path is %s", GetSavePath().c_str());
|
|
|
|
if (GetEmulatedPlatformID() == PLATFORM_ID_HTML5)
|
|
{
|
|
g_dglo.m_bUsingDinkPak = true;
|
|
}
|
|
|
|
|
|
|
|
if (g_dglo.m_bUsingDinkPak)
|
|
{
|
|
FileSystemZip *pFileSystem = new FileSystemZip();
|
|
if (!pFileSystem->Init(GetBaseAppPath()+ "dink/dink.pak"))
|
|
{
|
|
LogMsg("Error finding APK file to load resources");
|
|
}
|
|
|
|
//pFileSystem->SetRootDirectory("dink");
|
|
|
|
GetFileManager()->MountFileSystem(pFileSystem);
|
|
|
|
}
|
|
|
|
if (GetPlatformID() != PLATFORM_ID_ANDROID)
|
|
{
|
|
/*
|
|
FileSystemZip *pFileSystem = new FileSystemZip();
|
|
if (!pFileSystem->Init(GetBaseAppPath()+ "dink/dink.pak"))
|
|
{
|
|
LogMsg("Error finding APK file to load resources");
|
|
}
|
|
|
|
GetFileManager()->MountFileSystem(pFileSystem);
|
|
*/
|
|
/*
|
|
vector<string> contents = pFileSystem->GetContents();
|
|
LogMsg("Listing all %d files.", contents.size());
|
|
|
|
for (int i=0; i < contents.size(); i++)
|
|
{
|
|
LogMsg("%s", contents[i].c_str());
|
|
}
|
|
*/
|
|
|
|
RemoveFile(GetDMODRootPath()+"temp.dmod");
|
|
RemoveFile("temp.dmod");
|
|
}
|
|
|
|
|
|
switch (GetPlatformID())
|
|
{
|
|
case PLATFORM_ID_WINDOWS:
|
|
case PLATFORM_ID_BBX:
|
|
case PLATFORM_ID_WEBOS:
|
|
case PLATFORM_ID_HTML5:
|
|
CreateDirectoryRecursively("", GetDMODRootPath());
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
CreateAppCacheDirIfNeeded();
|
|
break;
|
|
}
|
|
|
|
|
|
if (IsLargeScreen())
|
|
{
|
|
if (!GetFont(FONT_SMALL)->Load("interface/font_normalx2.rtfont")) return false;
|
|
if (!GetFont(FONT_LARGE)->Load("interface/font_bigx2.rtfont")) return false;
|
|
} else
|
|
{
|
|
if (!GetFont(FONT_SMALL)->Load("interface/font_normal.rtfont")) return false;
|
|
if (!GetFont(FONT_LARGE)->Load("interface/font_big.rtfont")) return false;
|
|
}
|
|
|
|
//GetFont(FONT_SMALL)->SetSmoothing(false);
|
|
#ifndef FORCE_DMOD_SUPPORT
|
|
|
|
if (GetEmulatedPlatformID() == PLATFORM_ID_IOS)
|
|
{
|
|
//m_bHasDMODSupport = false;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
GetBaseApp()->SetFPSVisible(true);
|
|
#endif
|
|
|
|
bool bFileExisted;
|
|
m_varDB.Load("save.dat", &bFileExisted);
|
|
|
|
GetApp()->GetVarWithDefault("smoothing",uint32(0))->GetUINT32();
|
|
|
|
GetApp()->GetVarWithDefault("buttons",uint32(0));
|
|
|
|
GetApp()->GetVarWithDefault("music_vol",1.0f)->GetFloat();
|
|
GetApp()->GetVarWithDefault("gui_transparency",0.35f)->GetFloat();
|
|
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
GetApp()->GetVarWithDefault("checkerboard_fix", uint32(1)); //default to on for Windows
|
|
|
|
//If you don't have directx, just comment out this and remove the dx lib dependency, directx is only used for the
|
|
//gamepad input on windows
|
|
GetGamepadManager()->AddProvider(new GamepadProviderDirectX); //use directx joysticks
|
|
#endif
|
|
|
|
#ifdef RT_MOGA_ENABLED
|
|
GetGamepadManager()->AddProvider( new GamepadProviderMoga);
|
|
GetBaseApp()->SetAllowScreenDimming(false);
|
|
#endif
|
|
|
|
if (GetVar("check_icade")->GetUINT32() != 0)
|
|
{
|
|
AddIcadeProvider();
|
|
}
|
|
|
|
#if defined(PLATFORM_IOS) && defined(RT_IOS_60BEAT_GAMEPAD_SUPPORT)
|
|
//startup the 60beat gamepad stuff.. really, we should only do this if they've checked to use it in options
|
|
//or such because their driver may slow us down.. unsure
|
|
if (GetVar("check_60beat")->GetUINT32() != 0)
|
|
{
|
|
//startup the 60beat gamepad stuff
|
|
GetGamepadManager()->AddProvider(new GamepadProvider60Beat);
|
|
GetBaseApp()->SetAllowScreenDimming(false);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
if (GetEmulatedPlatformID() == PLATFORM_ID_WINDOWS || GetEmulatedPlatformID() == PLATFORM_ID_OSX || GetEmulatedPlatformID() == PLATFORM_ID_HTML5)
|
|
{
|
|
//should we draw that onscreen GUI stuff for Dink?
|
|
m_bUsingTouchScreen = false;
|
|
} else
|
|
{
|
|
m_bUsingTouchScreen = true;
|
|
}
|
|
|
|
if (IsIPADSize && GetEmulatedPlatformID() != PLATFORM_ID_WEBOS)
|
|
{
|
|
GetApp()->GetVarWithDefault("fpsLimit", Variant(uint32(VIDEO_FPS_LIMIT_OFF)))->GetUINT32();
|
|
}
|
|
|
|
UpdateVideoSettings();
|
|
//preload audio
|
|
|
|
|
|
if (GetEmulatedPlatformID() == PLATFORM_ID_IOS)
|
|
{
|
|
//use our own DLS, as iPhone/iPad don't have any midi system
|
|
g_audioManager.SetDLS("dink/midi/TimGM6mbTiny.dls");
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#endif
|
|
#ifdef _WIN32
|
|
|
|
//temporary while I make movies
|
|
//GetApp()->SetCheatsEnabled(true);
|
|
#endif
|
|
|
|
GetApp()->SetCheatsEnabled(true);
|
|
|
|
bool bSound = m_varDB.GetVarWithDefault("sound", uint32(1))->GetUINT32() != 0;
|
|
GetAudioManager()->SetSoundEnabled(bSound);
|
|
|
|
//GetAudioManager()->SetMusicEnabled(!GetApp()->GetVar("musicDisabled")->GetUINT32());
|
|
GetAudioManager()->SetMusicVol(GetApp()->GetVar("music_vol")->GetFloat());
|
|
GetAudioManager()->Preload("audio/click.wav");
|
|
InitDinkPaths(GetBaseAppPath(), "dink", "");
|
|
|
|
|
|
GetBaseApp()->m_sig_pre_enterbackground.connect(1, boost::bind(&App::OnPreEnterBackground, this, _1));
|
|
|
|
|
|
GetBaseApp()->m_sig_loadSurfaces.connect(1, boost::bind(&App::OnLoadSurfaces, this));
|
|
|
|
//when screen size changes we'll unload surfaces
|
|
GetBaseApp()->m_sig_unloadSurfaces.connect(1, boost::bind(&App::OnUnloadSurfaces, this));
|
|
|
|
#ifdef WINAPI
|
|
int videox = GetApp()->GetVarWithDefault("video_x", uint32(640))->GetUINT32();
|
|
int videoy = GetApp()->GetVarWithDefault("video_y", uint32(480))->GetUINT32();
|
|
int fullscreen = GetApp()->GetVarWithDefault("fullscreen", uint32(1))->GetUINT32();
|
|
bool borderlessfullscreen = GetApp()->GetVarWithDefault("fullscreen", uint32(0))->GetUINT32();
|
|
|
|
if (DoesCommandLineParmExist("-window") || DoesCommandLineParmExist("-windowed"))
|
|
{
|
|
fullscreen = false;
|
|
GetApp()->GetVar("fullscreen")->Set(uint32(0));
|
|
}
|
|
|
|
if (DoesCommandLineParmExist("-debug") )
|
|
{
|
|
g_script_debug_mode = true;
|
|
}
|
|
|
|
if (fullscreen && g_bUseBorderlessFullscreenOnWindows)
|
|
{
|
|
LogMsg("Setting fullscreen...");
|
|
//GetMessageManager()->SendGUI(MESSAGE_TYPE_GUI_TOGGLE_FULLSCREEN, 0, 0); //lParam holds a lot of random data about the press, look it up if
|
|
g_bIsFullScreen = false; //because we're using toggle..
|
|
OnFullscreenToggleRequest();
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
if (videox != 0 && videoy != 0)
|
|
{
|
|
//remember old setup
|
|
SetVideoMode(videox, videoy, false, 0);
|
|
}
|
|
*/
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
void App::OnPreEnterBackground(VariantList *pVList)
|
|
{
|
|
SaveAllData();
|
|
}
|
|
|
|
void App::OnExitApp(VariantList *pVarList)
|
|
{
|
|
LogMsg("Exiting the app");
|
|
|
|
OSMessage o;
|
|
o.m_type = OSMessage::MESSAGE_FINISH_APP;
|
|
GetBaseApp()->AddOSMessage(o);
|
|
}
|
|
|
|
void App::Kill()
|
|
{
|
|
|
|
if (!IsInBackground())
|
|
{
|
|
SaveAllData();
|
|
}
|
|
|
|
finiObjects();
|
|
|
|
BaseApp::Kill();
|
|
g_pApp = NULL; //make sure nobody elses access this
|
|
}
|
|
|
|
|
|
void App::RemoveAndAttachAllAvailableGamepads()
|
|
{
|
|
ArcadeInputComponent *pComp = (ArcadeInputComponent*) GetEntityRoot()->GetComponentByName("ArcadeInput");
|
|
assert(pComp);
|
|
|
|
for (int i=0; i < GetGamepadManager()->GetGamepadCount(); i++)
|
|
{
|
|
Gamepad *pPad = GetGamepadManager()->GetGamepad((eGamepadID)i);
|
|
pPad->ConnectToArcadeComponent(pComp, true, true);
|
|
|
|
//if we cared about the analog sticks too, we'd do this:
|
|
//pPad->m_sig_left_stick.connect(1, boost::bind(&OnGamepadStickUpdate, this, _1));
|
|
//pPad->m_sig_right_stick.connect(1, boost::bind(&OnGamepadStickUpdate, this, _1));
|
|
}
|
|
}
|
|
|
|
void App::RemoveAndroidKeyboardKeys()
|
|
{
|
|
ArcadeInputComponent *pComp = (ArcadeInputComponent*) GetEntityRoot()->GetComponentByName("ArcadeInput");
|
|
//first clear out all old ones to be safe
|
|
VariantList vList((string)"Keyboard");
|
|
pComp->GetFunction("RemoveKeyBindingsStartingWith")->sig_function(&vList);
|
|
}
|
|
|
|
void App::AddDroidKeyboardKeys()
|
|
{
|
|
if (GetEmulatedPlatformID() == PLATFORM_ID_ANDROID)
|
|
{
|
|
|
|
|
|
ArcadeInputComponent *pComp = (ArcadeInputComponent*) GetEntityRoot()->GetComponentByName("ArcadeInput");
|
|
|
|
RemoveAndroidKeyboardKeys();
|
|
|
|
//I think the ASWZ binding thing is for the control pad on the xperia play??
|
|
|
|
AddKeyBinding(pComp, "KeyboardLeft",'A', VIRTUAL_KEY_DIR_LEFT);
|
|
AddKeyBinding(pComp, "KeyboardRight",'S', VIRTUAL_KEY_DIR_RIGHT);
|
|
AddKeyBinding(pComp, "KeyboardUp", 'W', VIRTUAL_KEY_DIR_UP);
|
|
AddKeyBinding(pComp, "KeyboardDown", 'Z', VIRTUAL_KEY_DIR_DOWN);
|
|
AddKeyBinding(pComp, "KeyboardAltMagic", 8, VIRTUAL_KEY_GAME_MAGIC);
|
|
|
|
AddKeyBinding(pComp, "KeyboardInventory", 'I', VIRTUAL_KEY_GAME_INVENTORY);
|
|
AddKeyBinding(pComp, "KeyboardAltTalk", 13, VIRTUAL_KEY_GAME_TALK);
|
|
AddKeyBinding(pComp, "KeyboardFire", VIRTUAL_KEY_DIR_CENTER, VIRTUAL_KEY_GAME_FIRE);
|
|
AddKeyBinding(pComp, "KeyboardFire2", 'X', VIRTUAL_KEY_GAME_FIRE);
|
|
// AddKeyBinding(pComp, "KeyboardAltFire", VIRTUAL_KEY_SHIFT, VIRTUAL_KEY_GAME_FIRE);
|
|
}
|
|
}
|
|
|
|
void App::Update()
|
|
{
|
|
BaseApp::Update();
|
|
m_adManager.Update();
|
|
g_gamepadManager.Update();
|
|
|
|
if (!m_bDidPostInit)
|
|
{
|
|
m_bDidPostInit = true;
|
|
m_special = GetSystemData() != C_PIRATED_NO;
|
|
|
|
//build a GUI node
|
|
Entity *pGUIEnt = GetEntityRoot()->AddEntity(new Entity("GUI"));
|
|
|
|
#ifdef RT_EXPIRING
|
|
time_t rawtime, expiretime;
|
|
time(&rawtime);
|
|
|
|
expiretime = 1290050035 + ((3600)*24)*8; //expire in 8 days from Nov 18
|
|
bool bExpired = expiretime < rawtime;
|
|
|
|
if (bExpired)
|
|
{
|
|
ExpiredMenuCreate(pGUIEnt);
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
ArcadeInputComponent *pComp = (ArcadeInputComponent*) GetEntityRoot()->AddComponent(new ArcadeInputComponent);
|
|
|
|
RemoveAndAttachAllAvailableGamepads();
|
|
|
|
//add key bindings, I may want to move these later if I add a custom key config...
|
|
|
|
AddKeyBinding(pComp, "Left", VIRTUAL_KEY_DIR_LEFT, VIRTUAL_KEY_DIR_LEFT);
|
|
AddKeyBinding(pComp, "Right", VIRTUAL_KEY_DIR_RIGHT, VIRTUAL_KEY_DIR_RIGHT);
|
|
AddKeyBinding(pComp, "Up", VIRTUAL_KEY_DIR_UP, VIRTUAL_KEY_DIR_UP);
|
|
AddKeyBinding(pComp, "Down", VIRTUAL_KEY_DIR_DOWN, VIRTUAL_KEY_DIR_DOWN);
|
|
AddKeyBinding(pComp, "Talk", ' ', VIRTUAL_KEY_GAME_TALK);
|
|
|
|
AddKeyBinding(pComp, "GamePadInventory", VIRTUAL_DPAD_SELECT, VIRTUAL_KEY_GAME_INVENTORY);
|
|
AddKeyBinding(pComp, "GamePadInventory2", VIRTUAL_DPAD_BUTTON_UP, VIRTUAL_KEY_GAME_INVENTORY);
|
|
AddKeyBinding(pComp, "GamePadEscape", VIRTUAL_DPAD_START, VIRTUAL_KEY_BACK, true);
|
|
AddKeyBinding(pComp, "GamePadFire", VIRTUAL_DPAD_BUTTON_DOWN, VIRTUAL_KEY_GAME_FIRE);
|
|
AddKeyBinding(pComp, "GamePadTalk", VIRTUAL_DPAD_BUTTON_RIGHT, VIRTUAL_KEY_GAME_TALK);
|
|
AddKeyBinding(pComp, "GamePadMagic", VIRTUAL_DPAD_BUTTON_LEFT, VIRTUAL_KEY_GAME_MAGIC);
|
|
|
|
AddKeyBinding(pComp, "GamePadSpeedup", VIRTUAL_DPAD_LBUTTON, 'M', true);
|
|
AddKeyBinding(pComp, "GamePadSpeedup2", VIRTUAL_DPAD_RBUTTON, 9);
|
|
|
|
AddKeyBinding(pComp, "GamePadInventory3", VIRTUAL_DPAD_LTRIGGER, VIRTUAL_KEY_GAME_INVENTORY);
|
|
AddKeyBinding(pComp, "GamePadPause", VIRTUAL_DPAD_RTRIGGER, VIRTUAL_KEY_BACK, true);
|
|
|
|
|
|
//if (IsDesktop())
|
|
{
|
|
AddKeyBinding(pComp, "Inventory", 13, VIRTUAL_KEY_GAME_INVENTORY);
|
|
AddKeyBinding(pComp, "Magic", VIRTUAL_KEY_SHIFT, VIRTUAL_KEY_GAME_MAGIC);
|
|
AddKeyBinding(pComp, "Fire", VIRTUAL_KEY_CONTROL, VIRTUAL_KEY_GAME_FIRE);
|
|
AddKeyBinding(pComp, "Speedup", 9, 9); //handle tab
|
|
AddKeyBinding(pComp, "Quicksave", VIRTUAL_KEY_F1, VIRTUAL_KEY_F1);
|
|
AddKeyBinding(pComp, "Quickload", VIRTUAL_KEY_F8, VIRTUAL_KEY_F8);
|
|
}
|
|
|
|
if (GetVar("check_icade")->GetUINT32() == 0)
|
|
{
|
|
|
|
AddDroidKeyboardKeys();
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
// BrowseMenuCreate(pGUIEnt);
|
|
MainMenuCreate(pGUIEnt);
|
|
#else
|
|
MainMenuCreate(pGUIEnt);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
|
|
CheckForHotkeys();
|
|
}
|
|
}
|
|
|
|
void App::Draw()
|
|
{
|
|
BaseApp::Draw();
|
|
}
|
|
|
|
void App::OnScreenSizeChange()
|
|
{
|
|
#ifdef _DEBUG
|
|
LogMsg("Got OnScreenSizeChange");
|
|
#endif
|
|
|
|
BaseApp::OnScreenSizeChange();
|
|
if (GetPrimaryGLX() != 0)
|
|
{
|
|
SetupOrtho();
|
|
DinkOnForeground(); //rebuild lost surfaces
|
|
|
|
if (GetDinkGameState() != DINK_GAME_STATE_PLAYING)
|
|
{
|
|
PrepareForGL();
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef WINAPI
|
|
GetApp()->GetVar("fullscreen")->Set(uint32(g_bIsFullScreen));
|
|
GetApp()->GetVar("videox")->Set(uint32(GetPrimaryGLX()));
|
|
GetApp()->GetVar("videoy")->Set(uint32(GetPrimaryGLY()));
|
|
//GetApp()->GetVarWithDefault("borderless_fullscreen", uint32(g_bUseBorderlessFullscreenOnWindows))->Set(uint32(0));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
void App::GetServerInfo( string &server, uint32 &port )
|
|
{
|
|
#if defined (_DEBUG) && defined(WIN32)
|
|
// server = "localhost";
|
|
// port = 8080;
|
|
|
|
server = "rtsoft.com";
|
|
port = 80;
|
|
|
|
#else
|
|
|
|
server = "rtsoft.com";
|
|
port = 80;
|
|
#endif
|
|
}
|
|
|
|
int App::GetSpecial()
|
|
{
|
|
return m_special; //1 means pirated copy
|
|
}
|
|
|
|
Variant * App::GetVar( const string &keyName )
|
|
{
|
|
return GetShared()->GetVar(keyName);
|
|
}
|
|
|
|
std::string App::GetVersionString()
|
|
{
|
|
if (IsDesktop()) return m_desktopVersionString;
|
|
return m_versionString;
|
|
}
|
|
|
|
float App::GetVersion()
|
|
{
|
|
if (IsDesktop()) return m_desktopVersion;
|
|
return m_version;
|
|
}
|
|
|
|
int App::GetBuild()
|
|
{
|
|
if (IsDesktop()) return m_desktopBuild;
|
|
return m_build;
|
|
}
|
|
|
|
void App::OnMemoryWarning()
|
|
{
|
|
BaseApp::OnMemoryWarning();
|
|
|
|
GetAudioManager()->KillCachedSounds(false, true, 0, 1, false);
|
|
DinkUnloadUnusedGraphicsByUsageTime(100); //unload anything not used in the last second
|
|
}
|
|
|
|
void App::UpdateVideoSettings()
|
|
{
|
|
eVideoFPS v = (eVideoFPS)GetApp()->GetVarWithDefault("fpsLimit", Variant(uint32(VIDEO_FPS_LIMIT_OFF)))->GetUINT32();
|
|
OSMessage o;
|
|
o.m_type = OSMessage::MESSAGE_SET_FPS_LIMIT;
|
|
|
|
switch (v)
|
|
{
|
|
case VIDEO_FPS_LIMIT_ON:
|
|
o.m_x = 30;
|
|
break;
|
|
|
|
case VIDEO_FPS_LIMIT_OFF:
|
|
o.m_x = 2000;
|
|
break;
|
|
}
|
|
|
|
GetBaseApp()->AddOSMessage(o);
|
|
};
|
|
|
|
void App::SaveAllData()
|
|
{
|
|
|
|
if (GetDinkGameState() == DINK_GAME_STATE_PLAYING)
|
|
{
|
|
// SaveState(GetSavePath()+"state.dat");
|
|
SaveState(g_dglo.m_savePath+"continue_state.dat");
|
|
WriteLastPathSaved(g_dglo.m_savePath); //so we know what to reload
|
|
}
|
|
|
|
//GetAudioManager()->StopMusic();
|
|
m_varDB.Save("save.dat");
|
|
}
|
|
|
|
void App::OnEnterBackground()
|
|
{
|
|
//SaveAllData();
|
|
// DinkUnloadGraphicsCache();
|
|
|
|
|
|
/*
|
|
//I don't think we really need to uncache everything. If low memory is a problem we could though..
|
|
|
|
GetAudioManager()->KillCachedSounds(false, true, 0, 1, false);
|
|
LogMsg("Unloading some graphics");
|
|
DinkUnloadUnusedGraphicsByUsageTime(0); //unload anything not used in the last second
|
|
*/
|
|
|
|
BaseApp::OnEnterBackground();
|
|
}
|
|
|
|
void App::OnEnterForeground()
|
|
{
|
|
if (GetPrimaryGLX() == 0) return; //not ready, probably minimized on Windows
|
|
|
|
BaseApp::OnEnterForeground();
|
|
|
|
}
|
|
|
|
bool App::GetIconsOnLeft()
|
|
{
|
|
return GetShared()->GetVar("buttons")->GetUINT32() != 0;
|
|
}
|
|
|
|
//below is a sort of hack that allows "release" builds on windows to override the settings of whatever the shared main.cpp is telling
|
|
//us for window sizes
|
|
#ifdef _WINDOWS_
|
|
#include "win/app/main.h"
|
|
#endif
|
|
|
|
|
|
|
|
bool App::OnPreInitVideo()
|
|
{
|
|
if (!BaseApp::OnPreInitVideo()) return false;
|
|
|
|
#ifdef PLATFORM_HTML5
|
|
g_winVideoScreenX = 1024;
|
|
g_winVideoScreenY = 768;
|
|
#endif
|
|
|
|
//#if !defined(_DEBUG) && defined(WINAPI)
|
|
#ifdef WINAPI
|
|
|
|
#ifdef RT_SCRIPT_BUILD
|
|
|
|
SetEmulatedPlatformID(PLATFORM_ID_WINDOWS);
|
|
g_winVideoScreenX = 1024;
|
|
g_winVideoScreenY = 768;
|
|
|
|
#endif
|
|
|
|
// g_winVideoScreenX = 800;
|
|
// g_winVideoScreenY = 1280;
|
|
|
|
//windows only
|
|
|
|
|
|
|
|
VariantDB temp;
|
|
temp.Load("save.dat");
|
|
Variant *pVarX = temp.GetVarIfExists("videox");
|
|
Variant *pVarY = temp.GetVarIfExists("videoy");
|
|
if (pVarX && pVarY && pVarX->GetUINT32() != 0 && pVarY->GetUINT32() != 0)
|
|
{
|
|
|
|
g_winVideoScreenX = pVarX->GetUINT32();
|
|
g_winVideoScreenY = pVarY->GetUINT32();
|
|
}
|
|
|
|
g_bIsFullScreen = temp.GetVarWithDefault("fullscreen", uint32(1))->GetUINT32();
|
|
|
|
if (DoesCommandLineParmExist("-window") || DoesCommandLineParmExist("-windowed"))
|
|
{
|
|
g_bIsFullScreen = false;
|
|
GetApp()->GetVar("fullscreen")->Set(uint32(0));
|
|
}
|
|
|
|
g_bUseBorderlessFullscreenOnWindows = temp.GetVarWithDefault("borderless_fullscreen", uint32(0))->GetUINT32() != 0;
|
|
|
|
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
//for palm webos and android
|
|
const char * GetBundlePrefix()
|
|
{
|
|
|
|
char * bundlePrefix = "com.rtsoft.";
|
|
return bundlePrefix;
|
|
}
|
|
|
|
//applicable to Palm WebOS builds only
|
|
const char * GetBundleName()
|
|
{
|
|
char * bundleName = "rtdink";
|
|
return bundleName;
|
|
}
|
|
|
|
void App::OnMessage( Message &m )
|
|
{
|
|
m_adManager.OnMessage(m); //gives the AdManager a way to handle messages
|
|
BaseApp::OnMessage(m);
|
|
}
|
|
|
|
|
|
void App::OnLoadSurfaces()
|
|
{
|
|
LogMsg("Reloading dink engine surfaces");
|
|
DinkOnForeground();
|
|
|
|
}
|
|
|
|
void App::OnUnloadSurfaces()
|
|
{
|
|
LogMsg("Unloading dink engine surfaces");
|
|
DinkUnloadUnusedGraphicsByUsageTime(0);
|
|
|
|
//g_transitionSurf.Kill();
|
|
}
|
|
|
|
void App::AddTextToLog(const char *tex, const char *filename)
|
|
{
|
|
if (strlen(tex) < 1) return;
|
|
|
|
if (m_logFileHandle == NULL)
|
|
{
|
|
|
|
//open 'er up
|
|
m_logFileHandle = fopen(filename, "wb");
|
|
if (!m_logFileHandle)
|
|
{
|
|
assert(!"huh?");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!m_logFileHandle) return;
|
|
fwrite(tex, strlen(tex), 1, m_logFileHandle);
|
|
|
|
}
|
|
|
|
//our custom LogMsg that isn't slow as shit
|
|
void LogMsg(const char* traceStr, ...)
|
|
{
|
|
va_list argsVA;
|
|
const int logSize = 1024 * 10;
|
|
char buffer[logSize];
|
|
memset((void*)buffer, 0, logSize);
|
|
|
|
va_start(argsVA, traceStr);
|
|
vsnprintf_s(buffer, logSize, logSize, traceStr, argsVA);
|
|
va_end(argsVA);
|
|
|
|
|
|
OutputDebugString(buffer);
|
|
OutputDebugString("\n");
|
|
|
|
if (IsBaseAppInitted())
|
|
{
|
|
GetBaseApp()->GetConsole()->AddLine(buffer);
|
|
strcat(buffer, "\r\n");
|
|
//OutputDebugString( (string("writing to ")+GetSavePath()+"log.txt\n").c_str());
|
|
|
|
//this is the slow part. Or was...
|
|
|
|
|
|
|
|
GetApp()->AddTextToLog(buffer, (GetSavePath() + "log.txt").c_str());
|
|
}
|
|
|
|
}
|