# HG changeset patch # User nemo # Date 1321208824 18000 # Node ID bc157c3dac43f0a9724ec09177b94641e62eb5ed # Parent 52cb4807a78ccfef9cd1a016f22b4419c28e5860# Parent eca20f8990e2662bda072628569c2003745458a1 Merge .17 and trunk diff -r eca20f8990e2 -r bc157c3dac43 CMakeLists.txt --- a/CMakeLists.txt Sun Nov 13 13:18:56 2011 -0500 +++ b/CMakeLists.txt Sun Nov 13 13:27:04 2011 -0500 @@ -12,7 +12,7 @@ #detect Mercurial revision (if present) -set(version_suffix "") #UNSET THIS VARIABLE AT RELEASE TIME +set(version_suffix "-dev") #UNSET THIS VARIABLE AT RELEASE TIME set(HGCHANGED "") IF(version_suffix MATCHES "-dev") set(HW_DEV true) @@ -42,7 +42,7 @@ set(CPACK_PACKAGE_VERSION_MAJOR 0) set(CPACK_PACKAGE_VERSION_MINOR 9) set(CPACK_PACKAGE_VERSION_PATCH 17${version_suffix}) -set(HEDGEWARS_PROTO_VER 41) +set(HEDGEWARS_PROTO_VER 40) set(HEDGEWARS_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") diff -r eca20f8990e2 -r bc157c3dac43 hedgewars/uLandGraphics.pas --- a/hedgewars/uLandGraphics.pas Sun Nov 13 13:18:56 2011 -0500 +++ b/hedgewars/uLandGraphics.pas Sun Nov 13 13:27:04 2011 -0500 @@ -233,7 +233,7 @@ begin by:= t div 2; bx:= i div 2; end; - if ((Land[t, i] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and not disableLandBack then + if ((Land[t, i] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then begin inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) @@ -255,7 +255,7 @@ begin by:= t div 2; bx:= i div 2; end; - if ((Land[t, i] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and not disableLandBack then + if ((Land[t, i] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then begin inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) @@ -277,7 +277,7 @@ begin by:= t div 2; bx:= i div 2; end; - if ((Land[t, i] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and not disableLandBack then + if ((Land[t, i] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then begin inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) @@ -298,7 +298,7 @@ begin by:= t div 2; bx:= i div 2; end; - if ((Land[t, i] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and not disableLandBack then + if ((Land[t, i] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and not (disableLandBack) then begin inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) @@ -468,7 +468,7 @@ begin by:= ty div 2; bx:= tx div 2; end; - if ((Land[ty, tx] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and not disableLandBack then + if ((Land[ty, tx] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then LandPixels[by, bx]:= LandBackPixel(tx, ty) else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 @@ -588,7 +588,7 @@ begin by:= ty div 2; bx:= tx div 2; end; - if ((Land[ty, tx] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and not disableLandBack then + if ((Land[ty, tx] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then LandPixels[by, bx]:= LandBackPixel(tx, ty) else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0; diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h --- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h Sun Nov 13 13:27:04 2011 -0500 @@ -22,21 +22,15 @@ #import #import "SDL_net.h" -@protocol EngineProtocolDelegate - --(void) gameHasEndedWithStats:(NSArray *)stats; - -@end @interface EngineProtocolNetwork : NSObject { - id delegate; - + NSArray *statsArray; NSOutputStream *stream; TCPsocket csd; NSInteger enginePort; } -@property (nonatomic,assign) id delegate; +@property (nonatomic,assign) NSArray *statsArray; @property (nonatomic,retain) NSOutputStream *stream; @property (assign) TCPsocket csd; @property (assign) NSInteger enginePort; @@ -44,11 +38,10 @@ -(id) init; -+(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary; +-(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary; +(NSInteger) activeEnginePort; -(void) engineProtocol:(id) object; --(void) gameHasEndedWithStats:(NSArray *)stats; -(int) sendToEngine:(NSString *)string; -(int) sendToEngineNoSave:(NSString *)string; diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m --- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m Sun Nov 13 13:27:04 2011 -0500 @@ -28,12 +28,11 @@ static NSInteger activeEnginePort; @implementation EngineProtocolNetwork -@synthesize delegate, stream, csd, enginePort; +@synthesize statsArray, stream, csd, enginePort; -(id) init { if (self = [super init]) { - self.delegate = nil; - + self.statsArray = nil; self.csd = NULL; self.stream = nil; self.enginePort = [HWUtils randomPort]; @@ -42,31 +41,22 @@ return self; } --(void) gameHasEndedWithStats:(NSArray *)stats { - if (self.delegate != nil && [self.delegate respondsToSelector:@selector(gameHasEndedWithStats:)]) - [self.delegate gameHasEndedWithStats:stats]; - else - DLog(@"Error! delegate == nil"); -} - -(void) dealloc { - self.delegate = nil; + releaseAndNil(statsArray); releaseAndNil(stream); [super dealloc]; } #pragma mark - #pragma mark Spawner functions -+(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary { - id proto = [[self alloc] init]; - [proto setStream: (onSaveFile) ? [[NSOutputStream alloc] initToFileAtPath:onSaveFile append:YES] : nil]; - [[proto stream] open]; +-(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary { + self.stream = (onSaveFile) ? [[NSOutputStream alloc] initToFileAtPath:onSaveFile append:YES] : nil; + [self.stream open]; // +detachNewThreadSelector retain/release self automatically [NSThread detachNewThreadSelector:@selector(engineProtocol:) - toTarget:proto + toTarget:self withObject:dictionary]; - [proto release]; } +(NSInteger) activeEnginePort { @@ -232,7 +222,7 @@ -(void) engineProtocol:(id) object { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSDictionary *gameConfig = (NSDictionary *)object; - NSMutableArray *statsArray = nil; + NSMutableArray *tempStats = nil; TCPsocket sd; IPaddress ip; int eProto; @@ -347,10 +337,10 @@ } break; case 'i': - if (statsArray == nil) { - statsArray = [[NSMutableArray alloc] initWithCapacity:10 - 2]; + if (tempStats == nil) { + tempStats = [[NSMutableArray alloc] initWithCapacity:10 - 2]; NSMutableArray *ranking = [[NSMutableArray alloc] initWithCapacity:4]; - [statsArray insertObject:ranking atIndex:0]; + [tempStats insertObject:ranking atIndex:0]; [ranking release]; } NSString *tempStr = [NSString stringWithUTF8String:&buffer[2]]; @@ -359,16 +349,16 @@ int index = [arg length] + 3; switch (buffer[1]) { case 'r': // winning team - [statsArray insertObject:[NSString stringWithUTF8String:&buffer[2]] atIndex:1]; + [tempStats insertObject:[NSString stringWithUTF8String:&buffer[2]] atIndex:1]; break; case 'D': // best shot - [statsArray addObject:[NSString stringWithFormat:@"The best shot award won by %s (with %@ points)", &buffer[index], arg]]; + [tempStats addObject:[NSString stringWithFormat:@"The best shot award won by %s (with %@ points)", &buffer[index], arg]]; break; case 'k': // best hedgehog - [statsArray addObject:[NSString stringWithFormat:@"The best killer is %s with %@ kills in a turn", &buffer[index], arg]]; + [tempStats addObject:[NSString stringWithFormat:@"The best killer is %s with %@ kills in a turn", &buffer[index], arg]]; break; case 'K': // number of hogs killed - [statsArray addObject:[NSString stringWithFormat:@"%@ hedgehog(s) were killed during this round", arg]]; + [tempStats addObject:[NSString stringWithFormat:@"%@ hedgehog(s) were killed during this round", arg]]; break; case 'H': // team health/graph break; @@ -376,16 +366,16 @@ // still WIP in statsPage.cpp break; case 'P': // teams ranking - [[statsArray objectAtIndex:0] addObject:tempStr]; + [[tempStats objectAtIndex:0] addObject:tempStr]; break; case 's': // self damage - [statsArray addObject:[NSString stringWithFormat:@"%s thought it's good to shoot his own hedgehogs with %@ points", &buffer[index], arg]]; + [tempStats addObject:[NSString stringWithFormat:@"%s thought it's good to shoot his own hedgehogs with %@ points", &buffer[index], arg]]; break; case 'S': // friendly fire - [statsArray addObject:[NSString stringWithFormat:@"%s killed %@ of his own hedgehogs", &buffer[index], arg]]; + [tempStats addObject:[NSString stringWithFormat:@"%s killed %@ of his own hedgehogs", &buffer[index], arg]]; break; case 'B': // turn skipped - [statsArray addObject:[NSString stringWithFormat:@"%s was scared and skipped turn %@ times", &buffer[index], arg]]; + [tempStats addObject:[NSString stringWithFormat:@"%s was scared and skipped turn %@ times", &buffer[index], arg]]; break; default: DLog(@"Unhandled stat message, see statsPage.cpp"); @@ -393,12 +383,15 @@ } break; case 'q': - // game ended, can remove the savefile and present the statistics of the match + // game ended and match finished, statsArray is full of delicious statistics [HWUtils setGameStatus:gsEnded]; - [self gameHasEndedWithStats:statsArray]; + self.statsArray = [[NSArray arrayWithArray:tempStats] retain]; + // closing connection here would trigger a "IPC connection lost" error, so we have to wait until recv fails break; case 'Q': - // game exited but not completed, nothing to do (just don't save the message) + // game exited but not completed, skip this message in the savefile + [HWUtils setGameStatus:gsInterrupted]; + // same here, don't set clientQuit to YES break; default: [self dumpRawData:buffer ofSize:msgSize]; @@ -406,9 +399,10 @@ } } DLog(@"Engine exited, ending thread"); + [self.stream close]; [self.stream release]; - [statsArray release]; + [tempStats release]; // Close the client socket SDLNet_TCP_Close(csd); diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/GameConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.m Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.m Sun Nov 13 13:27:04 2011 -0500 @@ -223,6 +223,7 @@ script,@"mission_command", nil]; + [GameInterfaceBridge registerCallingController:self]; [GameInterfaceBridge startLocalGame:gameDictionary]; [gameDictionary release]; } diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h --- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h Sun Nov 13 13:27:04 2011 -0500 @@ -21,15 +21,22 @@ #import +@class EngineProtocolNetwork; @interface GameInterfaceBridge : NSObject { UIView *blackView; + NSString *savePath; + EngineProtocolNetwork *proto; } @property (nonatomic,retain) UIView *blackView; +@property (nonatomic,retain) NSString *savePath; +@property (nonatomic,retain) EngineProtocolNetwork *proto; +(void) startLocalGame:(NSDictionary *)withOptions; +(void) startSaveGame:(NSString *)atPath; +(void) startMissionGame:(NSString *)withScript; ++(void) registerCallingController:(UIViewController *)controller; + @end diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m --- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m Sun Nov 13 13:27:04 2011 -0500 @@ -26,16 +26,22 @@ #import "AudioManagerController.h" #import "ObjcExports.h" +static UIViewController *callingController; + @implementation GameInterfaceBridge -@synthesize blackView; +@synthesize blackView, savePath, proto; #pragma mark - #pragma mark Instance methods for engine interaction // prepares the controllers for hosting a game --(void) earlyEngineLaunch:(NSString *)pathOrNil withOptions:(NSDictionary *)optionsOrNil { +-(void) earlyEngineLaunch:(NSDictionary *)optionsOrNil { [self retain]; [AudioManagerController stopBackgroundMusic]; - [EngineProtocolNetwork spawnThread:pathOrNil withOptions:optionsOrNil]; + + EngineProtocolNetwork *engineProtocol = [[EngineProtocolNetwork alloc] init]; + self.proto = engineProtocol; + [engineProtocol release]; + [self.proto spawnThread:self.savePath withOptions:optionsOrNil]; // add a black view hiding the background CGRect theFrame = [[UIScreen mainScreen] bounds]; @@ -53,15 +59,19 @@ // keep track of uncompleted games NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:pathOrNil forKey:@"savedGamePath"]; + [userDefaults setObject:self.savePath forKey:@"savedGamePath"]; [userDefaults synchronize]; // let's launch the engine using this -perfomSelector so that the runloop can deal with queued messages first - [self performSelector:@selector(engineLaunch:) withObject:pathOrNil afterDelay:0.1f]; + [self performSelector:@selector(engineLaunch) withObject:nil afterDelay:0.1f]; } // cleans up everything -(void) lateEngineLaunch { + // notify views below that they are getting the spotlight again + [[[HedgewarsAppDelegate sharedAppDelegate] uiwindow] makeKeyAndVisible]; + [callingController viewWillAppear:YES]; + // remove completed games notification NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setObject:@"" forKey:@"savedGamePath"]; @@ -78,16 +88,36 @@ // the overlay is not needed any more and can be removed [[OverlayViewController mainOverlay] removeOverlay]; + // engine thread *should* be done by now + NSArray *stats = self.proto.statsArray; + if (stats != nil) { + StatsPageViewController *statsPage = [[StatsPageViewController alloc] initWithStyle:UITableViewStyleGrouped]; + statsPage.statsArray = stats; + statsPage.modalTransitionStyle = UIModalTransitionStyleCoverVertical; + if ([statsPage respondsToSelector:@selector(setModalPresentationStyle:)]) + statsPage.modalPresentationStyle = UIModalPresentationPageSheet; + + [callingController presentModalViewController:statsPage animated:YES]; + [statsPage release]; + } + [stats release]; // we retained the array before + + // can remove the savefile if the replay has ended + if ([HWUtils gameType] == gtSave) + [[NSFileManager defaultManager] removeItemAtPath:self.savePath error:nil]; + // restart music and we're done [AudioManagerController playBackgroundMusic]; + [HWUtils setGameStatus:gsNone]; + [HWUtils setGameType:gtNone]; [self release]; } // main routine for calling the actual game engine --(void) engineLaunch:(NSString *)pathOrNil { +-(void) engineLaunch { const char *gameArgs[11]; CGFloat width, height; - NSInteger enginePort = [EngineProtocolNetwork activeEnginePort]; + NSInteger enginePort = self.proto.enginePort; CGFloat screenScale = [[UIScreen mainScreen] safeScale]; NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",enginePort]; NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt",[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]]; @@ -139,7 +169,7 @@ gameArgs[ 7] = [[[settings objectForKey:@"music"] stringValue] UTF8String]; //isMusicEnabled gameArgs[ 8] = [[[settings objectForKey:@"alternate"] stringValue] UTF8String]; //cAltDamage gameArgs[ 9] = [rotation UTF8String]; //rotateQt - gameArgs[10] = ([HWUtils gameType] == gtSave) ? [pathOrNil UTF8String] : NULL; //recordFileName + gameArgs[10] = ([HWUtils gameType] == gtSave) ? [self.savePath UTF8String] : NULL; //recordFileName [verticalSize release]; [horizontalSize release]; @@ -154,12 +184,24 @@ [self lateEngineLaunch]; } +-(void) dealloc { + releaseAndNil(blackView); + releaseAndNil(savePath); + releaseAndNil(proto); + [super dealloc]; +} + #pragma mark - #pragma mark Class methods for setting up the engine from outsite ++(void) registerCallingController:(UIViewController *)controller { + callingController = controller; +} + +(void) startGame:(TGameType) type atPath:(NSString *)path withOptions:(NSDictionary *)config { [HWUtils setGameType:type]; id bridge = [[self alloc] init]; - [bridge earlyEngineLaunch:path withOptions:config]; + [bridge setSavePath:path]; + [bridge earlyEngineLaunch:config]; [bridge release]; } @@ -190,27 +232,5 @@ [missionLine release]; } -/* --(void) gameHasEndedWithStats:(NSArray *)stats { - // wrap this around a retain/realse to prevent being deallocated too soon - [self retain]; - // display stats page if there is something to display - if (stats != nil) { - StatsPageViewController *statsPage = [[StatsPageViewController alloc] initWithStyle:UITableViewStyleGrouped]; - statsPage.statsArray = stats; - statsPage.modalTransitionStyle = UIModalTransitionStyleCoverVertical; - if ([statsPage respondsToSelector:@selector(setModalPresentationStyle:)]) - statsPage.modalPresentationStyle = UIModalPresentationPageSheet; - - [self.parentController presentModalViewController:statsPage animated:YES]; - [statsPage release]; - } - - // can remove the savefile if the replay has ended - if ([HWUtils gameType] == gtSave) - [[NSFileManager defaultManager] removeItemAtPath:self.savePath error:nil]; - [self release]; -} -*/ @end diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/HWUtils.h --- a/project_files/HedgewarsMobile/Classes/HWUtils.h Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/HWUtils.h Sun Nov 13 13:27:04 2011 -0500 @@ -22,7 +22,7 @@ #import typedef enum {gtNone, gtLocal, gtSave, gtMission, gtNet} TGameType; -typedef enum {gsNone, gsLoading, gsInGame, gsEnded} TGameStatus; +typedef enum {gsNone, gsLoading, gsInGame, gsInterrupted, gsEnded} TGameStatus; @interface HWUtils : NSObject { diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/MainMenuViewController.m --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Sun Nov 13 13:27:04 2011 -0500 @@ -27,7 +27,6 @@ #import "SavedGamesViewController.h" #import "RestoreViewController.h" #import "MissionTrainingViewController.h" -#import "GameInterfaceBridge.h" #import "Appirater.h" #import "ServerProtocolNetwork.h" @@ -114,7 +113,6 @@ // prompt for restoring any previous game NSString *saveString = [userDefaults objectForKey:@"savedGamePath"]; if (saveString != nil && [saveString isEqualToString:@""] == NO) { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(launchRestoredGame) name:@"launchRestoredGame" object:nil]; if (self.restoreViewController == nil) { NSString *xibName = [@"RestoreViewController-" stringByAppendingString:(IS_IPAD() ? @"iPad" : @"iPhone")]; RestoreViewController *restored = [[RestoreViewController alloc] initWithNibName:xibName bundle:nil]; @@ -235,12 +233,6 @@ } #pragma mark - --(void) launchRestoredGame { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [GameInterfaceBridge startSaveGame:[[NSUserDefaults standardUserDefaults] objectForKey:@"savedGamePath"]]; -} - -#pragma mark - -(void) viewDidUnload { self.gameConfigViewController = nil; self.settingsViewController = nil; diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m --- a/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m Sun Nov 13 13:27:04 2011 -0500 @@ -74,6 +74,7 @@ [AudioManagerController playBackSound]; [[self parentViewController] dismissModalViewControllerAnimated:YES]; } else { + [GameInterfaceBridge registerCallingController:self]; [GameInterfaceBridge startMissionGame:self.missionName]; } } diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/RestoreViewController.m --- a/project_files/HedgewarsMobile/Classes/RestoreViewController.m Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/RestoreViewController.m Sun Nov 13 13:27:04 2011 -0500 @@ -36,7 +36,8 @@ if (theButton.tag != 0) { [AudioManagerController playClickSound]; - [[NSNotificationCenter defaultCenter] postNotificationName:@"launchRestoredGame" object:nil]; + [GameInterfaceBridge registerCallingController:self.parentViewController]; + [GameInterfaceBridge startSaveGame:[[NSUserDefaults standardUserDefaults] objectForKey:@"savedGamePath"]]; } else { [AudioManagerController playBackSound]; [defaults setObject:@"" forKey:@"savedGamePath"]; diff -r eca20f8990e2 -r bc157c3dac43 project_files/HedgewarsMobile/Classes/SavedGamesViewController.m --- a/project_files/HedgewarsMobile/Classes/SavedGamesViewController.m Sun Nov 13 13:18:56 2011 -0500 +++ b/project_files/HedgewarsMobile/Classes/SavedGamesViewController.m Sun Nov 13 13:27:04 2011 -0500 @@ -189,6 +189,7 @@ self.numberOfItems++; [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone]; + [GameInterfaceBridge registerCallingController:self]; [GameInterfaceBridge startSaveGame:currentFilePath]; [currentFilePath release]; } diff -r eca20f8990e2 -r bc157c3dac43 tools/PascalParser.hs --- a/tools/PascalParser.hs Sun Nov 13 13:18:56 2011 -0500 +++ b/tools/PascalParser.hs Sun Nov 13 13:27:04 2011 -0500 @@ -23,7 +23,7 @@ data TypesAndVars = TypesAndVars [TypeVarDeclaration] deriving Show data TypeVarDeclaration = TypeDeclaration Identifier TypeDecl - | VarDeclaration Bool ([Identifier], TypeDecl) (Maybe Expression) + | VarDeclaration Bool ([Identifier], TypeDecl) (Maybe InitExpression) | FunctionDeclaration Identifier TypeDecl (Maybe Phrase) deriving Show data TypeDecl = SimpleType Identifier @@ -49,7 +49,7 @@ | WhileCycle Expression Phrase | RepeatCycle Expression [Phrase] | ForCycle Identifier Expression Expression Phrase - | WithBlock Expression Phrase + | WithBlock Reference Phrase | Phrases [Phrase] | SwitchCase Expression [(Expression, Phrase)] (Maybe Phrase) | Assignment Reference Expression @@ -61,17 +61,32 @@ | StringLiteral String | CharCode String | NumberLiteral String + | FloatLiteral String | HexNumber String | Reference Reference | Null deriving Show data Reference = ArrayElement [Expression] Reference | FunCall [Expression] Reference + | BuiltInFunCall [Expression] Reference | SimpleReference Identifier | Dereference Reference | RecordField Reference Reference | Address Reference deriving Show +data InitExpression = InitBinOp String InitExpression InitExpression + | InitPrefixOp String InitExpression + | InitReference Identifier + | InitArray [InitExpression] + | InitRecord [(Identifier, InitExpression)] + | InitFloat String + | InitNumber String + | InitHexNumber String + | InitString String + | InitChar String + | InitNull + deriving Show + pascalLanguageDef = emptyDef @@ -88,7 +103,8 @@ , "type", "var", "const", "out", "array", "packed" , "procedure", "function", "with", "for", "to" , "downto", "div", "mod", "record", "set", "nil" - , "string", "shortstring" + , "string", "shortstring", "succ", "pred", "low" + , "high" ] , reservedOpNames= [] , caseSensitive = False @@ -183,7 +199,7 @@ init <- option Nothing $ do char '=' comments - e <- expression + e <- initExpression comments return (Just e) return $ VarDeclaration False (ids, t) init @@ -204,7 +220,7 @@ return () char '=' comments - e <- expression + e <- initExpression comments return $ VarDeclaration False ([i], UnknownType) (Just e) @@ -213,9 +229,9 @@ , try (string "shortstring") >> return String , arrayDecl , recordDecl + , sequenceDecl >>= return . Sequence + , try (identifier pas) >>= return . SimpleType . Identifier , rangeDecl >>= return . RangeType - , sequenceDecl >>= return . Sequence - , identifier pas >>= return . SimpleType . Identifier ] "type declaration" where arrayDecl = do @@ -336,7 +352,7 @@ liftM Just functionBody else return Nothing - return $ [FunctionDeclaration i ret Nothing] + return $ [FunctionDeclaration i ret b] program = do string "program" @@ -371,6 +387,8 @@ where term = comments >> choice [ parens pas $ expression + , try $ integer pas >>= \i -> notFollowedBy (char '.') >> (return . NumberLiteral . show) i + , try $ float pas >>= return . FloatLiteral . show , try $ integer pas >>= return . NumberLiteral . show , stringLiteral pas >>= return . StringLiteral , char '#' >> many digit >>= return . CharCode @@ -400,8 +418,8 @@ , Infix (try $ string "or" >> return (BinOp "or")) AssocLeft , Infix (try $ string "xor" >> return (BinOp "xor")) AssocLeft ] - , [ Infix (try $ string "shl" >> return (BinOp "and")) AssocNone - , Infix (try $ string "shr" >> return (BinOp "or")) AssocNone + , [ Infix (try $ string "shl" >> return (BinOp "shl")) AssocNone + , Infix (try $ string "shr" >> return (BinOp "shr")) AssocNone ] , [Prefix (try (string "not") >> return (PrefixOp "not"))] ] @@ -459,12 +477,12 @@ withBlock = do try $ string "with" comments - e <- expression + r <- reference comments string "do" comments o <- phrase - return $ WithBlock e o + return $ WithBlock r o repeatCycle = do try $ string "repeat" @@ -543,3 +561,54 @@ char ';' comments return u + +initExpression = buildExpressionParser table term "initialization expression" + where + term = comments >> choice [ + try $ parens pas (commaSep pas $ initExpression) >>= return . InitArray + , parens pas (semiSep pas $ recField) >>= return . InitRecord + , try $ integer pas >>= \i -> notFollowedBy (char '.') >> (return . InitNumber . show) i + , try $ float pas >>= return . InitFloat . show + , stringLiteral pas >>= return . InitString + , char '#' >> many digit >>= return . InitChar + , char '$' >> many hexDigit >>= return . InitHexNumber + , try $ string "nil" >> return InitNull + , iD >>= return . InitReference + ] + + recField = do + i <- iD + spaces + char ':' + spaces + e <- initExpression + spaces + return (i ,e) + + table = [ + [ Infix (char '*' >> return (InitBinOp "*")) AssocLeft + , Infix (char '/' >> return (InitBinOp "/")) AssocLeft + , Infix (try (string "div") >> return (InitBinOp "div")) AssocLeft + , Infix (try (string "mod") >> return (InitBinOp "mod")) AssocLeft + ] + , [ Infix (char '+' >> return (InitBinOp "+")) AssocLeft + , Infix (char '-' >> return (InitBinOp "-")) AssocLeft + , Prefix (char '-' >> return (InitPrefixOp "-")) + ] + , [ Infix (try (string "<>") >> return (InitBinOp "<>")) AssocNone + , Infix (try (string "<=") >> return (InitBinOp "<=")) AssocNone + , Infix (try (string ">=") >> return (InitBinOp ">=")) AssocNone + , Infix (char '<' >> return (InitBinOp "<")) AssocNone + , Infix (char '>' >> return (InitBinOp ">")) AssocNone + , Infix (char '=' >> return (InitBinOp "=")) AssocNone + ] + , [ Infix (try $ string "and" >> return (InitBinOp "and")) AssocLeft + , Infix (try $ string "or" >> return (InitBinOp "or")) AssocLeft + , Infix (try $ string "xor" >> return (InitBinOp "xor")) AssocLeft + ] + , [ Infix (try $ string "shl" >> return (InitBinOp "and")) AssocNone + , Infix (try $ string "shr" >> return (InitBinOp "or")) AssocNone + ] + , [Prefix (try (string "not") >> return (InitPrefixOp "not"))] + ] + \ No newline at end of file diff -r eca20f8990e2 -r bc157c3dac43 tools/pas2c.hs --- a/tools/pas2c.hs Sun Nov 13 13:18:56 2011 -0500 +++ b/tools/pas2c.hs Sun Nov 13 13:27:04 2011 -0500 @@ -4,8 +4,16 @@ import Text.PrettyPrint.HughesPJ import Data.Maybe import Data.Char +import Text.Parsec.String +pas2C :: String -> IO String +pas2C fileName = do + ptree <- parseFromFile pascalUnit fileName + case ptree of + (Left a) -> return (show a) + (Right a) -> (return . render . pascal2C) a + pascal2C :: PascalUnit -> Doc pascal2C (Unit unitName interface implementation init fin) = implementation2C implementation @@ -21,17 +29,38 @@ tvar2C :: TypeVarDeclaration -> Doc tvar2C (FunctionDeclaration (Identifier name) returnType Nothing) = type2C returnType <+> text (name ++ "();") - - tvar2C (FunctionDeclaration (Identifier name) returnType (Just phrase)) = type2C returnType <+> text (name ++ "()") $$ phrase2C phrase -tvar2C _ = empty +tvar2C (TypeDeclaration (Identifier i) t) = text "type" <+> text i <+> type2C t <> text ";" +tvar2C (VarDeclaration isConst (ids, t) mInitExpr) = + if isConst then text "const" else empty + <+> + type2C t + <+> + (hsep . punctuate (char ',') . map (\(Identifier i) -> text i) $ ids) + <+> + initExpr mInitExpr + <> + text ";" + where + initExpr Nothing = empty + initExpr (Just e) = text "=" <+> initExpr2C e + +initExpr2C :: InitExpression -> Doc +initExpr2C _ = text "<>" type2C :: TypeDecl -> Doc type2C UnknownType = text "void" -type2C _ = text "<>" +type2C String = text "string" +type2C (SimpleType (Identifier i)) = text i +type2C (PointerTo t) = type2C t <> text "*" +type2C (RecordType tvs) = text "{" $+$ (nest 4 . vcat . map tvar2C $ tvs) $+$ text "}" +type2C (RangeType r) = text "<>" +type2C (Sequence ids) = text "<>" +type2C (ArrayDecl r t) = text "<>" + phrase2C :: Phrase -> Doc phrase2C (Phrases p) = text "{" $+$ (nest 4 . vcat . map phrase2C $ p) $+$ text "}" @@ -46,15 +75,18 @@ where case2C :: (Expression, Phrase) -> Doc case2C (e, p) = text "case" <+> parens (expr2C e) <> char ':' <> nest 4 (phrase2C p $+$ text "break;") -{- - | RepeatCycle Expression Phrase - | ForCycle - -} -phrase2C _ = empty +phrase2C (WithBlock ref p) = text "namespace" <> parens (ref2C ref) $$ (phrase2C $ wrapPhrase p) +phrase2C (ForCycle (Identifier i) e1 e2 p) = + text "for" <> (parens . hsep . punctuate (char ';') $ [text i <+> text "=" <+> expr2C e1, text i <+> text "<=" <+> expr2C e2, text "++" <> text i]) + $$ + phrase2C (wrapPhrase p) +phrase2C (RepeatCycle e p) = text "do" <+> phrase2C (Phrases p) <+> text "while" <> parens (text "!" <> parens (expr2C e)) + wrapPhrase p@(Phrases _) = p wrapPhrase p = Phrases [p] + expr2C :: Expression -> Doc expr2C (Expression s) = text s expr2C (BinOp op expr1 expr2) = parens $ (expr2C expr1) <+> op2C op <+> (expr2C expr2) @@ -79,6 +111,7 @@ ref2C (FunCall params ref) = ref2C ref <> parens (hsep . punctuate (char ',') . map expr2C $ params) ref2C (Address ref) = text "&" <> ref2C ref + op2C "or" = text "|" op2C "and" = text "&" op2C "not" = text "!"