initial support for engine protocol
authorkoda
Sun, 10 Jan 2010 00:52:20 +0000 (2010-01-10)
changeset 2691 c0da3a98c01c
parent 2690 8e83c7e31720
child 2692 ce9992075118
initial support for engine protocol
cocoaTouch/SDLOverrides/SDL_uikitappdelegate.h
cocoaTouch/SDLOverrides/SDL_uikitappdelegate.m
cocoaTouch/gameSetup.h
cocoaTouch/gameSetup.m
cocoaTouch/otherSrc/PascalImports.h
hedgewars/PascalExports.pas
hedgewars/hwengine.pas
hedgewars/uIO.pas
hedgewars/uMisc.pas
--- a/cocoaTouch/SDLOverrides/SDL_uikitappdelegate.h	Sat Jan 09 01:34:23 2010 +0000
+++ b/cocoaTouch/SDLOverrides/SDL_uikitappdelegate.h	Sun Jan 10 00:52:20 2010 +0000
@@ -37,4 +37,6 @@
 +(SDLUIKitDelegate *)sharedAppDelegate;
 -(void) startSDLgame;
 
+int forward_argc;
+char **forward_argv;
 @end
--- a/cocoaTouch/SDLOverrides/SDL_uikitappdelegate.m	Sat Jan 09 01:34:23 2010 +0000
+++ b/cocoaTouch/SDLOverrides/SDL_uikitappdelegate.m	Sun Jan 10 00:52:20 2010 +0000
@@ -20,19 +20,19 @@
  slouken@libsdl.org, vittorio.giovara@gmail.com
 */
 
+#import <pthread.h>
 #import "SDL_uikitappdelegate.h"
 #import "SDL_uikitopenglview.h"
 #import "SDL_events_c.h"
 #import "jumphack.h"
 #import "SDL_video.h"
+#import "gameSetup.h"
 
 #ifdef main
 #undef main
 #endif
 
 extern int SDL_main(int argc, char *argv[]);
-static int forward_argc;
-static char **forward_argv;
 
 int main (int argc, char **argv) {
 	int i;
@@ -62,10 +62,17 @@
 	return (SDLUIKitDelegate *)[[UIApplication sharedApplication] delegate];
 }
 
+
 - (void) startSDLgame {
+	pthread_t threadID;
 
+	pthread_create (&threadID, NULL, (void *) (*engineProtocolThread), NULL);
+	pthread_detach (threadID);
+
+	setupArgsForLocalPlay();
+	
 	/* run the user's application, passing argc and argv */
-	NSLog(@"Game is launching");
+	NSLog(@"Game is launching...");
 	SDL_main(forward_argc, forward_argv);
 	// can't reach here yet
 	NSLog(@"Game exited");
@@ -87,6 +94,9 @@
 	
 	[window addSubview:controller.view];
 	[window makeKeyAndVisible];
+	
+	// REMOVE ME when you're done with reverse engineering the protocol
+	[self performSelector:@selector(startSDLgame)];
 }
 
 -(void) applicationWillTerminate:(UIApplication *)application {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cocoaTouch/gameSetup.h	Sun Jan 10 00:52:20 2010 +0000
@@ -0,0 +1,19 @@
+//
+//  gameSetup.h
+//  hwengine
+//
+//  Created by Vittorio on 10/01/10.
+//  Copyright 2010 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface gameSetup : NSObject {
+
+}
+
+@end
+
+void engineProtocolThread ();
+void setupArgsForLocalPlay();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cocoaTouch/gameSetup.m	Sun Jan 10 00:52:20 2010 +0000
@@ -0,0 +1,162 @@
+//
+//  gameSetup.m
+//  hwengine
+//
+//  Created by Vittorio on 10/01/10.
+//  Copyright 2010 __MyCompanyName__. All rights reserved.
+//
+
+#import <pthread.h>
+#import "SDL_uikitappdelegate.h"
+#import "gameSetup.h"
+#import "SDL_net.h"
+#import "PascalImports.h"
+
+#define IPC_PORT 51342
+#define IPC_PORT_STR "51342"
+#define BUFFER_SIZE 256
+
+
+@implementation gameSetup
+
+void engineProtocolThread () {
+	TCPsocket sd, csd; /* Socket descriptor, Client socket descriptor */
+	IPaddress ip;
+	int idx, eProto;
+	BOOL serverQuit, clientQuit;
+	char buffer[BUFFER_SIZE], string[BUFFER_SIZE];
+	Uint8 msgSize;
+	Uint16 gameTicks;
+	
+	if (SDLNet_Init() < 0) {
+		fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
+		exit(EXIT_FAILURE);
+	}
+	
+	/* Resolving the host using NULL make network interface to listen */
+	if (SDLNet_ResolveHost(&ip, NULL, IPC_PORT) < 0) {
+		fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
+		exit(EXIT_FAILURE);
+	}
+	
+	/* Open a connection with the IP provided (listen on the host's port) */
+	if (!(sd = SDLNet_TCP_Open(&ip))) {
+		fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
+		exit(EXIT_FAILURE);
+	}
+	
+	NSLog(@"engineProtocolThread - Waiting for a client");
+	
+	serverQuit = NO;
+	while (!serverQuit) {
+		
+		/* This check the sd if there is a pending connection.
+		 * If there is one, accept that, and open a new socket for communicating */
+		if ((csd = SDLNet_TCP_Accept(sd))) {
+			
+			NSLog(@"engineProtocolThread - Client found");
+			
+			//first byte of the command alwayas contain the size of the command
+			SDLNet_TCP_Recv(csd, &msgSize, sizeof(Uint8));
+			
+			SDLNet_TCP_Recv(csd, buffer, msgSize);
+			gameTicks = SDLNet_Read16(&buffer[msgSize - 2]);
+			NSLog(@"engineProtocolThread - %d: received [%s]", gameTicks, buffer);
+			
+			if ('C' == buffer[0]) {
+				NSLog(@"engineProtocolThread - Client found and connected");
+				clientQuit = NO;
+			} else {
+				NSLog(@"engineProtocolThread - wrong Connected message, closing");
+				clientQuit = YES;
+			}
+			
+			while (!clientQuit){
+				/* Now we can communicate with the client using csd socket
+				 * sd will remain opened waiting other connections */
+				idx = 0;
+				msgSize = 0;
+				memset(buffer, 0, BUFFER_SIZE);
+				memset(string, 0, BUFFER_SIZE);
+				SDLNet_TCP_Recv(csd, &msgSize, sizeof(Uint8));
+			
+				SDLNet_TCP_Recv(csd, buffer, msgSize);
+				gameTicks = SDLNet_Read16(&buffer[msgSize - 2]);
+				NSLog(@"engineProtocolThread - %d: received [%s]", gameTicks, buffer);
+				
+				switch (buffer[0]) {
+					case '?':
+						NSLog(@"Ping? Pong!");
+						string[idx++] = 0x01;
+						string[idx++] = '!';
+						
+						SDLNet_TCP_Send(csd, string, idx);
+						break;
+					case 'E':
+						NSLog(@"ERROR - last console line: [%s]", buffer);
+						clientQuit = YES;
+						break;
+					default:
+						sscanf(buffer, "%*s %d", &eProto);
+						if (HW_protoVer() == eProto) {
+							NSLog(@"Setting protocol version %s", buffer);
+						} else {
+							NSLog(@"ERROR - wrong protocol number: [%s] - expecting %d", buffer, eProto);
+							clientQuit = YES;
+						}
+						
+						break;
+				} 
+				
+				/*
+				 // Terminate this connection 
+				 if(strcmp(buffer, "exit") == 0)	{
+				 quit2 = 1;
+				 printf("Terminate connection\n");
+				 }
+				 // Quit the thread
+				 if(strcmp(buffer, "quit") == 0)	{
+				 quit2 = 1;
+				 quit = 1;
+				 printf("Quit program\n");
+				 }
+				 */
+			}
+		}
+		
+		/* Close the client socket */
+		SDLNet_TCP_Close(csd);
+	}
+
+	SDLNet_TCP_Close(sd);
+	SDLNet_Quit();
+
+	pthread_exit(NULL);
+}
+
+void setupArgsForLocalPlay() {
+	forward_argc = 18;
+	forward_argv = (char **)realloc(forward_argv, forward_argc * sizeof(char *));
+	//forward_argv[i] = malloc( (strlen(argv[i])+1) * sizeof(char));
+	forward_argv[ 1] = forward_argv[0];	// (UNUSED)
+	forward_argv[ 2] = "320";			// cScreenWidth (NO EFFECT)
+	forward_argv[ 3] = "480";			// cScreenHeight (NO EFFECT)
+	forward_argv[ 4] = "32";			// cBitsStr
+	forward_argv[ 5] = IPC_PORT_STR;	// ipcPort; <- (MAIN TODO)
+	forward_argv[ 6] = "1";				// cFullScreen (NO EFFECT)
+	forward_argv[ 7] = "0";				// isSoundEnabled (TOSET)
+	forward_argv[ 8] = "1";				// cVSyncInUse (UNUSED)
+	forward_argv[ 9] = "en.txt";		// cLocaleFName (TOSET)
+	forward_argv[10] = "100";			// cInitVolume (TOSET)
+	forward_argv[11] = "8";				// cTimerInterval
+	forward_argv[12] = "Data";			// PathPrefix
+	forward_argv[13] = "1";				// cShowFPS (TOSET?)
+	forward_argv[14] = "0";				// cAltDamage (TOSET)
+	forward_argv[15] = "Koda";			// UserNick (DecodeBase64(ParamStr(15)) FTW) <- TODO
+	forward_argv[16] = "0";				// isMusicEnabled (TOSET)
+	forward_argv[17] = "0";				// cReducedQuality
+
+	return;
+}
+
+@end
--- a/cocoaTouch/otherSrc/PascalImports.h	Sat Jan 09 01:34:23 2010 +0000
+++ b/cocoaTouch/otherSrc/PascalImports.h	Sun Jan 10 00:52:20 2010 +0000
@@ -18,6 +18,8 @@
 	 * that you want to use
 	 */
 	
+	int HW_protoVer(void);
+	
 	void HW_click(void);
 	void HW_zoomIn(void);
 	void HW_zoomOut(void);
--- a/hedgewars/PascalExports.pas	Sat Jan 09 01:34:23 2010 +0000
+++ b/hedgewars/PascalExports.pas	Sun Jan 10 00:52:20 2010 +0000
@@ -15,11 +15,16 @@
 interface
 uses uKeys, uConsole;
 
+{$INCLUDE "proto.inc"}
+
 {$IFDEF IPHONEOS}
 // called by pascal code, they deal with the objc code
 function  IPH_getDocumentsPath: PChar; cdecl; external;
 procedure IPH_showControls; cdecl; external;
 
+// retrieve protocol information
+function  HW_protoVer: LongInt; cdecl; export;
+
 // called by the touch functions (SDL_uikitview.m)
 // they emulate user interaction from mouse or keyboard
 procedure HW_click; cdecl; export;
@@ -40,6 +45,11 @@
 implementation
 
 {$IFDEF IPHONEOS}
+function HW_protoVer: LongInt; cdecl; export;
+begin
+	HW_protoVer:= cNetProtoVersion;
+end;
+
 procedure HW_click; cdecl; export;
 begin
 	WriteLnToConsole('HW - left click');
--- a/hedgewars/hwengine.pas	Sat Jan 09 01:34:23 2010 +0000
+++ b/hedgewars/hwengine.pas	Sun Jan 10 00:52:20 2010 +0000
@@ -236,6 +236,7 @@
 
 /////////////////////
 procedure DisplayUsage;
+var i: LongInt;
 begin
 	WriteLn('Wrong argument format: correct configurations is');
 	WriteLn();
@@ -249,6 +250,9 @@
 	WriteLn(' --set-everything [screen height] [screen width] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]');
 	WriteLn();
 	WriteLn('Read documentation online at http://www.hedgewars.org/node/1465 for more information');
+	Write('parsed command: ');
+	for i:=0 to ParamCount do Write(ParamStr(i) + ' ');
+	WriteLn();
 	halt(1);
 end;
 
--- a/hedgewars/uIO.pas	Sat Jan 09 01:34:23 2010 +0000
+++ b/hedgewars/uIO.pas	Sun Jan 10 00:52:20 2010 +0000
@@ -158,7 +158,7 @@
 		begin
 		buf[0]:= i;
 		ss:= ss + s;
-		while (Length(ss) > 1)and(Length(ss) > byte(ss[1])) do
+		while (Length(ss) > 1) and (Length(ss) > byte(ss[1])) do
 			begin
 			ParseIPCCommand(copy(ss, 2, byte(ss[1])));
 			Delete(ss, 1, Succ(byte(ss[1])))
@@ -205,7 +205,7 @@
 	SendEmptyPacketTicks:= 0;
 	if s[0]>#251 then s[0]:= #251;
 	SDLNet_Write16(GameTicks, @s[Succ(byte(s[0]))]);
-	{$IFDEF DEBUGFILE}AddFileLog('IPC send: '+s[1]);{$ENDIF}
+	{$IFDEF DEBUGFILE}AddFileLog('IPC send: '+ s[1]);{$ENDIF}
 	inc(s[0], 2);
 	SDLNet_TCP_Send(IPCSock, @s, Succ(byte(s[0])))
 	end
--- a/hedgewars/uMisc.pas	Sat Jan 09 01:34:23 2010 +0000
+++ b/hedgewars/uMisc.pas	Sun Jan 10 00:52:20 2010 +0000
@@ -595,6 +595,7 @@
 	ParamStr(1)
 {$ENDIF}
 	+ '/debug' + inttostr(i) + '.txt');
+//	f:= stderr;
 	rewrite(f);
 	if IOResult = 5 then
 	begin