2012-01-31 22:35:15 +00:00
|
|
|
/*
|
2012-01-31 22:40:40 +00:00
|
|
|
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
|
2012-01-31 22:35:15 +00:00
|
|
|
Copyright (C) 2009 Id Software, Inc.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import "doomAppDelegate.h"
|
|
|
|
#import "EAGLView.h"
|
|
|
|
#import <AudioToolbox/AudioServices.h>
|
|
|
|
#include "../doomiphone.h"
|
2012-01-31 22:40:40 +00:00
|
|
|
#import <QuartzCore/CADisplayLink.h>
|
|
|
|
#import "SettingsMenuView.h"
|
|
|
|
#import "ControlsMenuView.h"
|
|
|
|
#include "IBGlue.h"
|
|
|
|
#import "MapMenuView.h"
|
2012-01-31 22:35:15 +00:00
|
|
|
|
|
|
|
@interface UIApplication (Private)
|
|
|
|
|
|
|
|
- (void)setSystemVolumeHUDEnabled:(BOOL)enabled forAudioCategory:(NSString *)category;
|
|
|
|
- (void)setSystemVolumeHUDEnabled:(BOOL)enabled;
|
|
|
|
|
|
|
|
- (void)runFrame;
|
|
|
|
- (void)asyncTic;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
char iphoneDocDirectory[1024];
|
|
|
|
char iphoneAppDirectory[1024];
|
|
|
|
|
|
|
|
|
|
|
|
@implementation gameAppDelegate
|
|
|
|
|
|
|
|
@synthesize window;
|
|
|
|
@synthesize glView;
|
2012-01-31 22:40:40 +00:00
|
|
|
@synthesize displayLink;
|
2012-01-31 22:35:15 +00:00
|
|
|
|
|
|
|
extern EAGLContext *context;
|
|
|
|
|
2012-01-31 22:40:40 +00:00
|
|
|
gameAppDelegate * gAppDelegate = NULL;
|
|
|
|
|
2012-01-31 22:35:15 +00:00
|
|
|
NSTimer *animationTimer;
|
2012-01-31 22:40:40 +00:00
|
|
|
bool inBackgroundProcess = false;
|
2012-01-31 22:35:15 +00:00
|
|
|
|
|
|
|
touch_t sysTouches[MAX_TOUCHES];
|
|
|
|
touch_t gameTouches[MAX_TOUCHES];
|
|
|
|
pthread_mutex_t eventMutex; // used to sync between game and event threads
|
2012-01-31 22:40:40 +00:00
|
|
|
bool firstRun = true;
|
2012-01-31 22:35:15 +00:00
|
|
|
|
|
|
|
pthread_t gameThreadHandle;
|
|
|
|
volatile boolean startupCompleted;
|
|
|
|
void *GameThread( void *args ) {
|
|
|
|
if ( ![EAGLContext setCurrentContext:context]) {
|
|
|
|
printf( "Couldn't setCurrentContext for game thread\n" );
|
|
|
|
exit( 1 );
|
|
|
|
}
|
|
|
|
|
2012-01-31 22:40:40 +00:00
|
|
|
while( inBackgroundProcess ) {
|
|
|
|
usleep( 1000 );
|
|
|
|
}
|
|
|
|
|
2012-01-31 22:35:15 +00:00
|
|
|
printf( "original game thread priority: %f\n", (float)[NSThread threadPriority] );
|
|
|
|
[NSThread setThreadPriority: 0.5];
|
|
|
|
printf( "new game thread priority: %f\n", (float)[NSThread threadPriority] );
|
2012-01-31 22:40:40 +00:00
|
|
|
|
2012-01-31 22:35:15 +00:00
|
|
|
iphoneStartup();
|
|
|
|
|
|
|
|
// make sure one frame has been run before setting
|
|
|
|
// startupCompleted, so we don't get one grey frame
|
|
|
|
iphoneFrame();
|
|
|
|
|
|
|
|
startupCompleted = TRUE; // OK to start touch / accel callbacks
|
|
|
|
while( 1 ) {
|
2012-01-31 22:40:40 +00:00
|
|
|
|
|
|
|
// we are in the background.. dont do anything.
|
|
|
|
if( inBackgroundProcess ) {
|
|
|
|
usleep( 1000 );
|
|
|
|
}
|
2012-01-31 22:35:15 +00:00
|
|
|
iphoneFrame();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)asyncTic {
|
|
|
|
iphoneAsyncTic();
|
|
|
|
[ self restartAccelerometerIfNeeded];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)runFrame {
|
2012-01-31 22:40:40 +00:00
|
|
|
iphoneAsyncTic();
|
2012-01-31 22:35:15 +00:00
|
|
|
iphoneFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)applicationDidFinishLaunching:(UIApplication *)application {
|
2012-01-31 22:40:40 +00:00
|
|
|
inBackgroundProcess = false;
|
2012-01-31 22:35:15 +00:00
|
|
|
application.statusBarHidden = YES;
|
|
|
|
application.statusBarOrientation = UIInterfaceOrientationLandscapeLeft;
|
2012-01-31 22:40:40 +00:00
|
|
|
gAppDelegate = self;
|
|
|
|
|
2012-01-31 22:35:15 +00:00
|
|
|
// get the documents directory, where we will write configs and save games
|
|
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
|
|
|
NSString *documentsDirectory = [paths objectAtIndex:0];
|
|
|
|
[documentsDirectory getCString: iphoneDocDirectory
|
|
|
|
maxLength: sizeof( iphoneDocDirectory ) - 1
|
|
|
|
encoding: NSASCIIStringEncoding ];
|
|
|
|
|
|
|
|
// get the app directory, where our data files live
|
|
|
|
// this gives something like:
|
|
|
|
// /var/mobile/Applications/71355F9F-6400-4267-B07D-E7980764F5A8/Applications
|
|
|
|
// when what we want is:
|
|
|
|
// /var/mobile/Applications/71355F9F-6400-4267-B07D-E7980764F5A8/doom.app
|
|
|
|
// so we get that in main() from argv[0]
|
|
|
|
#if 0
|
|
|
|
paths = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES);
|
|
|
|
NSString *appDirectory = [paths objectAtIndex:0];
|
|
|
|
|
|
|
|
static char iphoneAppDirectoryFromAPI[1024];
|
|
|
|
[appDirectory getCString: iphoneAppDirectoryFromAPI
|
|
|
|
maxLength: sizeof( iphoneAppDirectoryFromAPI ) - 1
|
|
|
|
encoding: NSASCIIStringEncoding ];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// disable screen dimming
|
|
|
|
[UIApplication sharedApplication].idleTimerDisabled = YES;
|
|
|
|
|
2012-01-31 22:40:40 +00:00
|
|
|
// Add the Main Menu as the SubView
|
|
|
|
[self MainMenu];
|
|
|
|
|
2012-01-31 22:35:15 +00:00
|
|
|
// start the flow of accelerometer events
|
|
|
|
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
|
|
|
|
accelerometer.delegate = self;
|
2012-01-31 22:40:40 +00:00
|
|
|
accelerometer.updateInterval = 1.0f / 30.0f;
|
2012-01-31 22:35:15 +00:00
|
|
|
|
|
|
|
// use this mutex for coordinating touch handling between
|
|
|
|
// the run loop thread and the game thread
|
|
|
|
if ( pthread_mutex_init( &eventMutex, NULL ) == -1 ) {
|
|
|
|
perror( "pthread_mutex_init" );
|
|
|
|
}
|
|
|
|
|
|
|
|
// use this semaphore for signaling from the async cmd generation thread that
|
|
|
|
// the game / draw thread can wake up
|
|
|
|
|
|
|
|
// sem_init is unimplemented on iPhone
|
|
|
|
//if ( sem_init( &ticSemaphore, 0, 0 ) == -1 ) {
|
|
|
|
// perror( "sem_init" );
|
|
|
|
//}
|
|
|
|
ticSemaphore = sem_open( "ticSemaphore", O_CREAT, S_IRWXU, 0 );
|
|
|
|
if ( ticSemaphore == SEM_FAILED ) {
|
|
|
|
perror( "sem_open" );
|
|
|
|
}
|
|
|
|
|
|
|
|
// we want the main (event/async) thread to be as high a priority as possible
|
|
|
|
// so the game/render thread will be interrupted immediately.
|
|
|
|
// It looks like the default scheduling on iPhone is already what we want --
|
|
|
|
// the main thread is at 1.0, and new threads are at 0.5.
|
|
|
|
printf( "original event thread priority: %f\n", (float)[NSThread threadPriority] );
|
|
|
|
[NSThread setThreadPriority: 1.0];
|
|
|
|
printf( "new event thread priority: %f\n", (float)[NSThread threadPriority] );
|
|
|
|
|
2012-01-31 22:40:40 +00:00
|
|
|
// do all the game startup work
|
2012-01-31 22:35:15 +00:00
|
|
|
iphoneStartup();
|
2012-01-31 22:40:40 +00:00
|
|
|
|
|
|
|
int animationFrameInterval = 2;
|
|
|
|
CADisplayLink *aDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(runFrame)];
|
|
|
|
[aDisplayLink setFrameInterval:animationFrameInterval];
|
|
|
|
[aDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
|
|
|
self.displayLink = aDisplayLink;
|
|
|
|
aDisplayLink.paused = YES;
|
|
|
|
|
|
|
|
|
|
|
|
startupCompleted = TRUE; // OK to start touch / accel callbacks
|
2012-01-31 22:35:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)applicationWillResignActive:(UIApplication *)application {
|
2012-01-31 22:40:40 +00:00
|
|
|
displayLink.paused = YES;
|
|
|
|
inBackgroundProcess = YES;
|
|
|
|
iphonePauseMusic();
|
|
|
|
iphoneShutdown();
|
2012-01-31 22:35:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
2012-01-31 22:40:40 +00:00
|
|
|
displayLink.paused = NO;
|
|
|
|
inBackgroundProcess = NO;
|
|
|
|
|
|
|
|
if( IBMenuVisible && !firstRun ) {
|
|
|
|
iphonePlayMusic( "intro" );
|
|
|
|
}
|
|
|
|
|
|
|
|
firstRun = false;
|
2012-01-31 22:35:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)applicationWillTerminate:(UIApplication *)application {
|
2012-01-31 22:40:40 +00:00
|
|
|
iphoneStopMusic();
|
2012-01-31 22:35:15 +00:00
|
|
|
iphoneShutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
|
|
|
|
Com_Printf( "applicationDidReceiveMemoryWarning\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
[window release];
|
|
|
|
[glView release];
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)restartAccelerometerIfNeeded {
|
|
|
|
|
|
|
|
// I have no idea why this seems to happen sometimes...
|
|
|
|
if ( SysIphoneMilliseconds() - lastAccelUpdateMsec > 1000 ) {
|
|
|
|
static int count;
|
|
|
|
if ( ++count < 100 ) {
|
|
|
|
printf( "Restarting accelerometer updates.\n" );
|
|
|
|
}
|
|
|
|
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
|
|
|
|
accelerometer.delegate = self;
|
|
|
|
accelerometer.updateInterval = 0.01;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
|
|
|
|
{
|
|
|
|
float acc[4];
|
|
|
|
acc[0] = acceleration.x;
|
|
|
|
acc[1] = acceleration.y;
|
|
|
|
acc[2] = acceleration.z;
|
|
|
|
acc[3] = acceleration.timestamp;
|
|
|
|
iphoneTiltEvent( acc );
|
|
|
|
lastAccelUpdateMsec = SysIphoneMilliseconds();
|
|
|
|
}
|
|
|
|
|
2012-01-31 22:40:40 +00:00
|
|
|
- (void) PrepareForViewSwap {
|
|
|
|
|
|
|
|
[ mainMenuViewController.view removeFromSuperview ];
|
|
|
|
[ mapMenuViewController.view removeFromSuperview ];
|
|
|
|
[ creditsMenuViewController.view removeFromSuperview ];
|
|
|
|
[ legalMenuViewController.view removeFromSuperview ];
|
|
|
|
[ settingsMenuViewController.view removeFromSuperview ];
|
|
|
|
[ controlsMenuViewController.view removeFromSuperview ];
|
|
|
|
[ episodeMenuViewController.view removeFromSuperview ];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) ResumeGame {
|
|
|
|
|
|
|
|
ResumeGame();
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview:glView];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
|
|
|
|
displayLink.paused = NO;
|
|
|
|
IBMenuVisible = NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) MainMenu {
|
|
|
|
|
|
|
|
[self PrepareForViewSwap];
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview: mainMenuViewController.view];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
iphonePauseMusic();
|
|
|
|
|
|
|
|
displayLink.paused = YES;
|
|
|
|
IBMenuVisible = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DemoGame {
|
|
|
|
|
|
|
|
StartDemoGame( false );
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview:glView];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
|
|
|
|
displayLink.paused = NO;
|
|
|
|
IBMenuVisible = NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) NewGame {
|
|
|
|
|
|
|
|
[self PrepareForViewSwap];
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview: episodeMenuViewController.view];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
|
|
|
|
displayLink.paused = YES;
|
|
|
|
IBMenuVisible = YES;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) playMap: (int) dataset: (int) episode: (int) map: (int) skill {
|
|
|
|
mapStart_t startmap;
|
|
|
|
|
|
|
|
startmap.map = map;
|
|
|
|
startmap.episode = episode;
|
|
|
|
startmap.dataset = dataset;
|
|
|
|
startmap.skill = skill;
|
|
|
|
|
|
|
|
StartSinglePlayerGame( startmap );
|
|
|
|
|
|
|
|
[self HideIB];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) CreditsMenu {
|
|
|
|
|
|
|
|
[self PrepareForViewSwap];
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview: creditsMenuViewController.view];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
|
|
|
|
displayLink.paused = YES;
|
|
|
|
IBMenuVisible = YES;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) LegalMenu {
|
|
|
|
|
|
|
|
[self PrepareForViewSwap];
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview: legalMenuViewController.view];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
|
|
|
|
displayLink.paused = YES;
|
|
|
|
IBMenuVisible = YES;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GotoSupport {
|
|
|
|
|
|
|
|
SysIPhoneOpenURL("http://www.idsoftware.com/doom-classic/index.html");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) idSoftwareApps {
|
|
|
|
|
|
|
|
SysIPhoneOpenURL("http://itunes.com/apps/idsoftware");
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) ControlsMenu {
|
|
|
|
|
|
|
|
[self PrepareForViewSwap];
|
|
|
|
|
|
|
|
ControlsMenuView * menu = controlsMenuViewController.view;
|
|
|
|
[ menu SetOptions];
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview: controlsMenuViewController.view];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
|
|
|
|
displayLink.paused = YES;
|
|
|
|
IBMenuVisible = YES;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) SettingsMenu {
|
|
|
|
|
|
|
|
[self PrepareForViewSwap];
|
|
|
|
|
|
|
|
SettingsMenuView * menu = settingsMenuViewController.view;
|
|
|
|
[ menu resetSwitches];
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview: settingsMenuViewController.view];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
|
|
|
|
displayLink.paused = YES;
|
|
|
|
IBMenuVisible = YES;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) HUDLayout {
|
|
|
|
|
|
|
|
menuState = IPM_HUDEDIT;
|
|
|
|
|
|
|
|
[self HideIB];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) HideIB {
|
|
|
|
|
|
|
|
[self PrepareForViewSwap];
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview:glView];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
|
|
|
|
displayLink.paused = NO;
|
|
|
|
IBMenuVisible = NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) SelectEpisode: (int) episode {
|
|
|
|
|
|
|
|
[self PrepareForViewSwap];
|
|
|
|
|
|
|
|
[ (MapMenuView*)mapMenuViewController.view setEpisode: episode ];
|
|
|
|
|
|
|
|
// Switch to the Game View.
|
|
|
|
[window addSubview: mapMenuViewController.view];
|
|
|
|
[window makeKeyAndVisible];
|
|
|
|
|
|
|
|
displayLink.paused = YES;
|
|
|
|
IBMenuVisible = YES;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-01-31 22:35:15 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|