Initial SDL-Linux port

This commit is contained in:
Nathan Fulton 2016-08-31 09:05:20 -04:00
parent 5b5917fbab
commit bec7aea014
12 changed files with 479 additions and 10 deletions

View File

@ -1,6 +1,7 @@
#include "base/misc.h"
#include <ctype.h>
#include <string>
#include <cstring>
namespace base {

View File

@ -297,21 +297,27 @@ bool ChooseServerForm::RequestInfos() {
}
// Don't show servers to disallowed client platforms
#if defined(__MACOSX__)
#if defined(__MACOSX__)
if (info.disallow.find("mac") != std::string::npos) {
continue;
}
#endif
#if defined(__ANDROID__)
#elif defined(DARWIN)
if (info.disallow.find("darwin") != std::string::npos) {
continue;
}
#elif defined(__LINUX__)
if (info.disallow.find("linux") != std::string::npos) {
continue;
}
#elif defined(__ANDROID__)
if (info.disallow.find("android") != std::string::npos) {
continue;
}
#endif
#if defined(IPHONE) || defined(__IPHONEOS__)
#elif defined(IPHONE) || defined(__IPHONEOS__)
if (info.disallow.find("iphone") != std::string::npos) {
continue;
}
#endif
#endif
// If there is an info with this name that matches the protocol,
// keep it and discard the new info

View File

@ -3,6 +3,7 @@
#include "base/format.h"
#include <unistd.h>
#include <stdlib.h>
#include <cstring>
namespace wi {
@ -173,7 +174,7 @@ void HttpPackInfoManager::OnError(HttpRequest *preq, const char *pszError) {
}
}
bool HttpPackInfoManager::FinishInstall() {
bool HttpPackInfoManager::FinishInstall() {
if (tempfile_ == NULL) {
return false;
}

View File

@ -218,6 +218,7 @@ bool ProcessSdlEvent(base::Message *pmsg, Event *pevt)
SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH can be used to process mouse events
separately from touch events (it's a shame a similar hint doesn't exist for
other platforms). Thus, Android can process both input event types.
- Linux... We'll try only processing SDL_MOUSE events for now.
*/
#if defined(__IPHONEOS__) || defined(__ANDROID__)
@ -292,7 +293,7 @@ bool ProcessSdlEvent(base::Message *pmsg, Event *pevt)
break;
#endif
#if defined(__MACOSX__) || defined(__ANDROID__)
#if defined(__MACOSX__) || defined(__ANDROID__) || defined(__LINUX__)
case SDL_MOUSEBUTTONDOWN:
pevt->eType = penDownEvent;
pevt->x = event.button.x;

View File

@ -4,7 +4,7 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syslimits.h>
#include <limits.h>
#include <sys/time.h>
#include <stdio.h>
#include <SDL.h>

View File

@ -0,0 +1,220 @@
#include "game/sdl/linux/linuxchatcontroller.h"
#include "game/sdl/hosthelpers.h"
#include "game/sdl/sdlhttpservice.h"
#include "base/thread.h"
#include <sys/utsname.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <net/if.h>
#include <limits.h>
#include <stdio.h>
#include <pwd.h>
namespace wi {
char gszLinuxGamesDir[PATH_MAX]; // /home/[user]/Games
char gszHomeDir[PATH_MAX]; // /home/[user]/Games/WarfareIncorporated
char gszMainDataDir[PATH_MAX]; // data files directory
char gszTempDir[PATH_MAX]; // temp file directory
char gszMissionPacksDir[PATH_MAX]; // downloaded mission packs
char gszMissionPackInfosDir[PATH_MAX];
char gszSaveGamesDir[PATH_MAX]; // saved games
char gszPrefsFilename[PATH_MAX]; // game prefs
char gszCompletesDir[PATH_MAX]; // for "mission completed" tracking
HttpService *gphttp;
IChatController *gpchat;
bool HostHelpers::Init() {
// Get the user's home directory
struct passwd *pw = getpwuid(getuid());
const char *linuxHomeDir = pw->pw_dir;
// Add a Games folder to it
sprintf(gszLinuxGamesDir, "%s/Games", linuxHomeDir);
// By HomeDir we are refering to the game's home dir and not the user's home dir
sprintf(gszHomeDir, "%s/HostileTakeover", gszLinuxGamesDir);
// MainDataDir is where htdata.pdb and htsfx.pdb are stored
// Linux players should run install.sh to copy the database files this location
sprintf(gszMainDataDir, "%s", gszHomeDir);
sprintf(gszTempDir, "%s/tmp", gszHomeDir);
sprintf(gszMissionPacksDir, "%s/MissionPacks", gszHomeDir);
sprintf(gszMissionPackInfosDir, "%s/MissionPackInfos", gszHomeDir);
sprintf(gszSaveGamesDir, "%s/SaveGames", gszHomeDir);
sprintf(gszCompletesDir, "%s/Completes/", gszHomeDir);
sprintf(gszPrefsFilename, "%s/prefs.bin", gszHomeDir);
// Make the directories
mkdir(gszLinuxGamesDir, 0755);
mkdir(gszHomeDir, 0755);
mkdir(gszMissionPacksDir, 0755);
mkdir(gszMissionPackInfosDir, 0755);
mkdir(gszSaveGamesDir, 0755);
mkdir(gszCompletesDir, 0755);
mkdir(gszTempDir, 0755);
extern HttpService *gphttp;
gphttp = (HttpService *)new SdlHttpService();
gpchat = NULL;
return true;
}
void HostHelpers::Cleanup() {
delete gphttp;
}
const char *HostHelpers::GetMainDataDir() {
return gszMainDataDir;
}
const char *HostHelpers::GetTempDir() {
return gszTempDir;
}
const char *HostHelpers::GetMissionPacksDir() {
return gszMissionPacksDir;
}
const char *HostHelpers::GetMissionPackInfosDir() {
return gszMissionPackInfosDir;
}
const char *HostHelpers::GetSaveGamesDir() {
return gszSaveGamesDir;
}
const char *HostHelpers::GetCompletesDir() {
return gszCompletesDir;
}
const char *HostHelpers::GetPrefsFilename() {
return gszPrefsFilename;
}
void HostHelpers::OpenUrl(const char *pszUrl) {
Log("HostHelpers::OpenUrl not implemented yet");
}
void HostHelpers::Log(const char *pszFormat, va_list va)
{
#if 0
LOGX() << base::Log::vFormat(pszFormat, va);
#endif
char sz[512];
vsnprintf(sz, sizeof(sz), pszFormat, va);
printf("%s\n", sz);
}
void HostHelpers::Log(const char *pszFormat, ...)
{
va_list va;
va_start(va, pszFormat);
Log(pszFormat, va);
va_end(va);
}
void HostHelpers::MessageBox(const char *pszFormat, va_list va)
{
Log(pszFormat, va);
}
void HostHelpers::Break()
{
Log("BREAK!!");
}
void HostHelpers::GetSurfaceProperties(SurfaceProperties *pprops)
{
int cxScreen, cyScreen;
cxScreen = 800;
cyScreen = 600;
pprops->cxWidth = cxScreen;
pprops->cyHeight = cyScreen;
pprops->cbxPitch = 1;
pprops->cbyPitch = pprops->cxWidth;
pprops->ffFormat = wi::kfDirect8;
}
bool HostHelpers::IsExiting()
{
#if 0
return [g_appDelegate isExiting];
#else
Log("HostHelpers::IsExitig not implemented yet");
return false;
#endif
}
const char *HostHelpers::GetUdid()
{
// Use the Mac Address for the DID (doesn't work on Mac)
#ifndef DARWIN
#define MAC_STRING_LENGTH 13
char *ret = (char *)malloc(MAC_STRING_LENGTH);
struct ifreq s;
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
strcpy(s.ifr_name, "eth0");
if (fd >= 0 && ret && 0 == ioctl(fd, SIOCGIFHWADDR, &s)) {
int i;
for (i = 0; i < 6; ++i)
snprintf(ret+i*2,MAC_STRING_LENGTH-i*2,"%02x",(unsigned char) s.ifr_addr.sa_data[i]);
} else {
LOG() << "malloc/socket/ioctl failed";
}
return (const char *)ret;
#else
static char gszUdid[20];
char *pch = gszUdid;
if (*pch == 0) {
for (int i = 0; i < 19; i++)
*pch++ = '0' + GetAsyncRandom() % 10;
*pch = 0;
}
return gszUdid;
#endif
}
void HostHelpers::InitiateAsk(const char *title, int max, const char *def,
int keyboard, bool secure)
{
Log("HostHelpers::InitiateAsk not implemented yet");
}
void HostHelpers::GetAskString(char *psz, int cb)
{
Log("HostHelpers::GetAskString not implemented yet");
}
IChatController *HostHelpers::GetChatController()
{
if (gpchat == NULL) {
gpchat = new wi::LinuxChatController();
}
return gpchat;
}
void HostHelpers::InitiateWebView(const char *title, const char *url) {
Log("HostHelpers::InitiateWebView not implemented yet");
}
const char *HostHelpers::GetPlatformString() {
static struct utsname systemInfo;
uname(&systemInfo);
return systemInfo.sysname;
}
} // namespace wi

22
game/sdl/linux/install.sh Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
HT_ROOT=$SCRIPT_DIR/../../..
echo "mkdir ~/Games"
mkdir ~/Games
echo "mkdir ~/Games/HostileTakeover"
mkdir ~/Games/HostileTakeover
# If release build, htdata832.pdb needs to be marked
cp $HT_ROOT/game/htdata832.pdb ~/Games/HostileTakeover
cp $HT_ROOT/game/htsfx.pdb ~/Games/HostileTakeover
if [ "$(uname -s)" == "Darwin" ]; then
cp -r $HT_ROOT/game/sdl/SDL2/osx/SDL2.framework ~/Games/HostileTakeover
else
echo "sudo password may be required to download and install the SDL2 library..."
sudo apt-get updates
sudo apt-get install libsdl2-dev
fi

View File

@ -0,0 +1,58 @@
#include "linuxchatcontroller.h"
#include "game/sdl/hosthelpers.h"
namespace wi {
IChatControllerCallback *pcccb_;
wi::LinuxChatController *chatc_;
LinuxChatController::LinuxChatController() {
}
void LinuxChatController::Clear() {
}
void LinuxChatController::AddChat(const char *player, const char *chat) {
}
void LinuxChatController::Show(bool fShow) {
}
void LinuxChatController::SetTitle(const char *title) {
}
const char *LinuxChatController::GetTitle() {
}
IChatControllerCallback *LinuxChatController::SetCallback(
IChatControllerCallback *pcccb) {
IChatControllerCallback *old = pcccb_;
pcccb_ = pcccb;
return old;
}
void LinuxChatController::OnMessage(base::Message *pmsg) {
switch (pmsg->id) {
case kidmOnDismissed:
if (pcccb_ != NULL) {
pcccb_->OnChatDismissed();
}
break;
case kidmOnSend:
if (pcccb_ != NULL) {
ChatParams *params = (ChatParams *)pmsg->data;
pcccb_->OnChatSend(params->chat.c_str());
delete params;
}
break;
case kidmOnPlayers:
if (pcccb_ != NULL) {
pcccb_->OnPlayers();
}
break;
}
}
} // namespace wi

View File

@ -0,0 +1,39 @@
#ifndef __LINUXCHATCONTROLLER_H__
#define __LINUXCHATCONTROLLER_H__
#include <string>
#include "game/sdl/hosthelpers.h"
#include "base/thread.h"
#include "game/chatcontroller.h"
#define kidmOnSend 1
#define kidmOnDismissed 2
#define kidmOnPlayers 3
namespace wi {
struct ChatParams : base::MessageData {
ChatParams(const std::string& chat) : chat(chat) {}
std::string chat;
};
// Game thread c++ interface to the ChatViewController
class LinuxChatController : public IChatController, public base::MessageHandler {
public:
LinuxChatController();
void Clear();
void AddChat(const char *player, const char *chat);
void Show(bool fShow);
void SetTitle(const char *title);
const char *GetTitle();
IChatControllerCallback *SetCallback(IChatControllerCallback *pcccb);
private:
// MessageHandler
virtual void OnMessage(base::Message *pmsg);
};
} // namespace wi
#endif // __LINUXCHATCONTROLLER_H__

117
game/sdl/linux/makefile Normal file
View File

@ -0,0 +1,117 @@
BINARY = HostileTakeover
HTROOT := ../../..
CC = gcc
CXX = g++
LD = g++
CPPFLAGS += -w -Wno-write-strings -fsigned-char \
-I../../../base -I../../../mpshared -I../../../inc \
-I../SDL2/include -I../curl/include -I../../../ -I../../ -I../ \
-D__LINUX__ -DSDL -DMULTIPLAYER -DTRACKSTATE
ifeq ($(REL),1)
OUTDIR = release
CPPFLAGS += -O2
else
CPPFLAGS += -g -O0 -DDEV_BUILD -DDEBUG_LOGGING -DDEBUG
OUTDIR = debug
endif
ifeq ($(shell uname), Darwin)
LDFLAGS += -F/System/Library/Frameworks -framework cocoa -framework foundation \
-F../SDL2/osx -framework SDL2 -fobjc-link-runtime -framework SDL2 \
-rpath ~/Games/HostileTakeover -lcurl -lpthread
CPPFLAGS += -DDARWIN
else
LDFLAGS += -lSDL2 -lcurl -lpthread
endif
# For each source directory:
# wildcard to get all the .cpp or .c files
# notdir to remove the path from the file paths
# basename to remove the suffix from the file name
# filter-out to remove any unwanted source files
GAME_FILES := $(wildcard $(HTROOT)/game/*.cpp)
GAME_FILES := $(notdir $(GAME_FILES))
GAME_FILES := $(basename $(GAME_FILES))
GAME_FILES := $(filter-out SocTransport miscgraphics \
hashtablecode filepdbreader DebugHelpers, $(GAME_FILES))
BASE_FILES := $(wildcard $(HTROOT)/base/*.cpp)
BASE_FILES := $(notdir $(BASE_FILES))
BASE_FILES := $(basename $(BASE_FILES))
BASE_FILES := $(filter-out epollserver stdindispatcher, $(BASE_FILES))
MPSHARED_FILES := $(wildcard $(HTROOT)/mpshared/*.cpp)
MPSHARED_FILES := $(notdir $(MPSHARED_FILES))
MPSHARED_FILES := $(basename $(MPSHARED_FILES))
INC_FILES := rip
YAJL_C_FILES := $(wildcard $(HTROOT)/yajl/src/*.c)
YAJL_C_FILES := $(notdir $(YAJL_C_FILES))
YAJL_C_FILES := $(basename $(YAJL_C_FILES))
YAJL_CPP_FILES := $(wildcard $(HTROOT)/yajl/wrapper/*.cpp)
YAJL_CPP_FILES := $(notdir $(YAJL_CPP_FILES))
YAJL_CPP_FILES := $(basename $(YAJL_CPP_FILES))
YAJL_CPP_FILES := $(filter-out jsonbuilder_test, $(YAJL_CPP_FILES))
SDL_FILES = $(wildcard $(HTROOT)/game/sdl/*.cpp)
SDL_FILES := $(notdir $(SDL_FILES))
SDL_FILES := $(basename $(SDL_FILES))
LINUX_FILES = $(wildcard $(HTROOT)/game/sdl/linux/*.cpp)
LINUX_FILES := $(notdir $(LINUX_FILES))
LINUX_FILES := $(basename $(LINUX_FILES))
all: before_make $(OUTDIR)/$(BINARY)
before_make:
test -d $(OUTDIR) || mkdir -p $(OUTDIR)
test -d $(OUTDIR)/game || mkdir -p $(OUTDIR)/game
test -d $(OUTDIR)/base || mkdir -p $(OUTDIR)/base
test -d $(OUTDIR)/mpshared || mkdir -p $(OUTDIR)/mpshared
test -d $(OUTDIR)/inc || mkdir -p $(OUTDIR)/inc
test -d $(OUTDIR)/yajl || mkdir -p $(OUTDIR)/yajl
test -d $(OUTDIR)/sdl || mkdir -p $(OUTDIR)/sdl
test -d $(OUTDIR)/linux || mkdir -p $(OUTDIR)/linux
clean:
rm -rf $(OUTDIR)/*
$(OUTDIR)/$(BINARY): \
$(GAME_FILES:%=$(OUTDIR)/game/%.o) \
$(BASE_FILES:%=$(OUTDIR)/base/%.o) \
$(MPSHARED_FILES:%=$(OUTDIR)/mpshared/%.o) \
$(INC_FILES:%=$(OUTDIR)/inc/%.o) \
$(YAJL_CPP_FILES:%=$(OUTDIR)/yajl/%.o) \
$(YAJL_C_FILES:%=$(OUTDIR)/yajl/%.o) \
$(SDL_FILES:%=$(OUTDIR)/sdl/%.o) \
$(LINUX_FILES:%=$(OUTDIR)/linux/%.o)
$(LD) -o $@ $^ $(LDFLAGS)
$(GAME_FILES:%=$(OUTDIR)/game/%.o): $(GAME_FILES:%=../../%.cpp)
$(CXX) $(CPPFLAGS) -c $(<D)/$(*F).cpp -o $@
$(BASE_FILES:%=$(OUTDIR)/base/%.o): $(BASE_FILES:%=../../../base/%.cpp)
$(CXX) $(CPPFLAGS) -c $(<D)/$(*F).cpp -o $@
$(MPSHARED_FILES:%=$(OUTDIR)/mpshared/%.o): $(MPSHARED_FILES:%=../../../mpshared/%.cpp)
$(CXX) $(CPPFLAGS) -c $(<D)/$(*F).cpp -o $@
$(INC_FILES:%=$(OUTDIR)/inc/%.o): $(INC_FILES:%=../../../inc/%.cpp)
$(CXX) $(CPPFLAGS) -c $(<D)/$(*F).cpp -o $@
$(YAJL_CPP_FILES:%=$(OUTDIR)/yajl/%.o): $(YAJL_CPP_FILES:%=../../../yajl/wrapper/%.cpp)
$(CXX) $(CPPFLAGS) -c $(<D)/$(*F).cpp -o $@
$(YAJL_C_FILES:%=$(OUTDIR)/yajl/%.o): $(YAJL_C_FILES:%=../../../yajl/src/%.c)
$(CC) $(CPPFLAGS) -c $(<D)/$(*F).c -o $@
$(SDL_FILES:%=$(OUTDIR)/sdl/%.o): $(SDL_FILES:%=../%.cpp)
$(CXX) $(CPPFLAGS) -c $(<D)/$(*F).cpp -o $@
$(LINUX_FILES:%=$(OUTDIR)/linux/%.o): $(LINUX_FILES:%=%.cpp)
$(CXX) $(CPPFLAGS) -c $(<D)/$(*F).cpp -o $@

View File

@ -23,7 +23,11 @@ static void quit(int rc)
extern "C"
#endif
#ifdef __LINUX__
int main (int argc, char *argv[])
#else
int SDL_main(int argc, char *argv[])
#endif
{
// Create the main thread
base::Thread *main_thread = new base::Thread();

View File

@ -2,7 +2,7 @@
#include "game/mempdbreader.h"
#include "inc/rip.h"
#include <string.h>
#include <sys/syslimits.h>
#include <limits.h>
namespace wi {