Esempio n. 1
0
void IN_StartupJoystick (void)
{
	int i;
	int nummappings;
	char controllerdb[MAX_OSPATH];
	SDL_GameController *gamecontroller;
	
	if (COM_CheckParm("-nojoy"))
		return;
	
	if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1 )
	{
		Con_Warning("could not initialize SDL Game Controller\n");
		return;
	}
	
	// Load additional SDL2 controller definitions from gamecontrollerdb.txt
	q_snprintf (controllerdb, sizeof(controllerdb), "%s/gamecontrollerdb.txt", com_basedir);
	nummappings = SDL_GameControllerAddMappingsFromFile(controllerdb);
	if (nummappings > 0)
		Con_Printf("%d mappings loaded from gamecontrollerdb.txt\n", nummappings);
	
	// Also try host_parms->userdir
	if (host_parms->userdir != host_parms->basedir)
	{
		q_snprintf (controllerdb, sizeof(controllerdb), "%s/gamecontrollerdb.txt", host_parms->userdir);
		nummappings = SDL_GameControllerAddMappingsFromFile(controllerdb);
		if (nummappings > 0)
			Con_Printf("%d mappings loaded from gamecontrollerdb.txt\n", nummappings);
	}

	for (i = 0; i < SDL_NumJoysticks(); i++)
	{
		const char *joyname = SDL_JoystickNameForIndex(i);
		if ( SDL_IsGameController(i) )
		{
			const char *controllername = SDL_GameControllerNameForIndex(i);
			gamecontroller = SDL_GameControllerOpen(i);
			if (gamecontroller)
			{
				Con_Printf("detected controller: %s\n", controllername != NULL ? controllername : "NULL");
				
				joy_active_instaceid = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller));
				joy_active_controller = gamecontroller;
				break;
			}
			else
			{
				Con_Warning("failed to open controller: %s\n", controllername != NULL ? controllername : "NULL");
			}
		}
		else
		{
			Con_Warning("joystick missing controller mappings: %s\n", joyname != NULL ? joyname : "NULL" );
		}
	}
}
Esempio n. 2
0
ControllerMgr::ControllerMgr() :
    m_KBCtrl(),
    m_GameCtrl(),
    m_MenuCtrl(m_GameCtrl)
{
    m_GameCtrl.Add(&m_KBCtrl);

    std::string mappings = Resources::Map("gamecontrollerdb.txt");
    if(SDL_GameControllerAddMappingsFromFile(mappings.c_str())<0 ) {
        log_errorf("Couldn't load %s. Some controllers might not work.\n",mappings.c_str());
    }

    // scan for already-attached controllers
    int i;
    for(i=0; i<SDL_NumJoysticks(); ++i)
    {
        if (!SDL_IsGameController(i)) {
//            printf("joy %d is not controller\n",i);
            continue;
        }
        SDLController* c = new SDLController(i);
        m_Attached.push_back(c);
        m_GameCtrl.Add(c);
//        printf("Found controller: %d\n",c->InstanceID());
        break;
    }
}
Esempio n. 3
0
inline int add_controller_mapping_from_file(const std::string& filename) {
    int result = SDL_GameControllerAddMappingsFromFile(filename.c_str());
    if(result == -1) {
        GUM_ERROR_HANDLER(result);
    }
    return result;
}
Esempio n. 4
0
void JoyInit(CArray *joys)
{
	char buf[CDOGS_PATH_MAX];
	GetDataFilePath(buf, "data/gamecontrollerdb.txt");
	if (SDL_GameControllerAddMappingsFromFile(buf) == -1)
	{
		LOG(LM_INPUT, LL_ERROR, "cannot load controller mappings file: %s",
			SDL_GetError());
	}
	GetDataFilePath(buf, "data/gamecontrollerbuttondb.txt");
	if (SDLJBN_AddMappingsFromFile(buf) == -1)
	{
		LOG(LM_INPUT, LL_ERROR, "cannot load button mappings file: %s",
			SDLJBN_GetError());
	}

	CArrayInit(joys, sizeof(Joystick));

	// Detect all current controllers
	const int n = SDL_NumJoysticks();
	LOG(LM_INPUT, LL_INFO, "%d controllers found", n);
	if (n == 0)
	{
		return;
	}
	for (int i = 0; i < n; i++)
	{
		JoyAdded(i);
	}
}
Esempio n. 5
0
void load_mappings(const char* filename) {
    int result = SDL_GameControllerAddMappingsFromFile(filename);
    if (result == -1) {
        printf("Error loading controller mappings\n");
    }
    else {
        printf("Loaded %d controller mappings\n", result);
    }
}
Esempio n. 6
0
/*
 * Add controller mappings from the specified file
 */
void S2D_AddControllerMappingsFromFile(const char *path) {
  if (!S2D_FileExists(path)) {
    S2D_Log(S2D_WARN, "Controller mappings file not found: %s", path);
    return;
  }

  int mappings_added = SDL_GameControllerAddMappingsFromFile(path);
  if (mappings_added == -1) {
    S2D_Error("SDL_GameControllerAddMappingsFromFile", SDL_GetError());
  } else {
    S2D_Log(S2D_INFO, "Added %i controller mapping(s)", mappings_added);
  }
}
Esempio n. 7
0
bool Input::init(const std::string& inputDBFilename)
{
	m_Keyboard = new Keyboard();
	m_Mouse = new Mouse();
	SDL_GameControllerAddMappingsFromFile(inputDBFilename.c_str());
	int numOfJoypads = SDL_NumJoysticks();
	for (int i = 0; i < numOfJoypads; i++)
	{
		//Is the joypad able to use the new controller interface
		if (SDL_IsGameController(i))
		{
			SDL_GameController *controller = SDL_GameControllerOpen(i);
			Joypad * joypad = new Joypad(controller);
			m_AttachedJoypads.push_back(joypad);
		}
	}

	return true;
}
Esempio n. 8
0
void initGameControllers()
{
	SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");

	int c = 0;
	bool found = false; //TODO: Bugger this and implement multi-controller support.
	game_controller = new GameController();
	for (c = 0; c < SDL_NumJoysticks() && !found; ++c)   //TODO: Bugger this and implement multi-controller support on a player-by-player basis.
	{
		if (SDL_IsGameController(c) && game_controller->open(c))
		{
			printlog("(Device %d successfully initialized as game controller.)\n", c);
			found = true; //TODO: Bugger this and implement multi-controller support.
		}
		else
		{
			printlog("Info: device %d is not a game controller! Joysticks are not supported.\n", c);
		}
	}
	if (!found)
	{
		printlog("Info: No game controller detected!");
	}
}
int main(int argc, char *argv[]) {
  int i;
  int nController = 0;
  int retcode = 0;
  char guid[64];
  SDL_GameController *gamecontroller;

  /* Enable standard application logging */
  SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

  /* Initialize SDL (Note: video is required to start event loop) */
  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) <
      0) {
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n",
                 SDL_GetError());
    return 1;
  }

  SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");

  /* Print information about the controller */
  for (i = 0; i < SDL_NumJoysticks(); ++i) {
    const char *name;
    const char *description;

    SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), guid, sizeof(guid));

    if (SDL_IsGameController(i)) {
      nController++;
      name = SDL_GameControllerNameForIndex(i);
      description = "Controller";
    } else {
      name = SDL_JoystickNameForIndex(i);
      description = "Joystick";
    }
    SDL_Log("%s %d: %s (guid %s)\n", description, i, name ? name : "Unknown",
            guid);
  }
  SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n",
          nController, SDL_NumJoysticks());

  if (argv[1]) {
    SDL_bool reportederror = SDL_FALSE;
    SDL_bool keepGoing = SDL_TRUE;
    SDL_Event event;
    int device = atoi(argv[1]);
    if (device >= SDL_NumJoysticks()) {
      SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
                   "%i is an invalid joystick index.\n", device);
      retcode = 1;
    } else {
      SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(device), guid,
                                sizeof(guid));
      SDL_Log("Attempting to open device %i, guid %s\n", device, guid);
      gamecontroller = SDL_GameControllerOpen(device);

      /* - this requires SDL 2.0.4
if (gamecontroller != NULL) {
SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller)))
== gamecontroller);
}
*/

      while (keepGoing) {
        if (gamecontroller == NULL) {
          if (!reportederror) {
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
                         "Couldn't open gamecontroller %d: %s\n", device,
                         SDL_GetError());
            retcode = 1;
            keepGoing = SDL_FALSE;
            reportederror = SDL_TRUE;
          }
        } else {
          reportederror = SDL_FALSE;
          keepGoing = WatchGameController(gamecontroller);
          SDL_GameControllerClose(gamecontroller);
        }

        gamecontroller = NULL;
        if (keepGoing) {
          SDL_Log("Waiting for attach\n");
        }
        while (keepGoing) {
          SDL_WaitEvent(&event);
          if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN) ||
              (event.type == SDL_MOUSEBUTTONDOWN)) {
            keepGoing = SDL_FALSE;
          } else if (event.type == SDL_CONTROLLERDEVICEADDED) {
            gamecontroller = SDL_GameControllerOpen(event.cdevice.which);
            /* - this requires SDL 2.0.4
            if (gamecontroller != NULL) {
                SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller)))
            == gamecontroller);
            }
            */
            break;
          }
        }
      }
    }
  }

  SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK |
                    SDL_INIT_GAMECONTROLLER);

  return retcode;
}
Esempio n. 10
0
void SdlManager::TryLoadControllerMappingsFromFile(const char* fileName)
{
	SDL_GameControllerAddMappingsFromFile(fileName);
}
Esempio n. 11
0
	s32 proc()
	{
#if _WIN32
		SetProcessDPIAware();
#endif

#if defined(__APPLE__)
		SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
#endif

		// Initialize SDL
		if (SDL_Init(
			SDL_INIT_VIDEO
			| SDL_INIT_EVENTS
			| SDL_INIT_GAMECONTROLLER
			| SDL_INIT_HAPTIC
			| SDL_INIT_TIMER
			| SDL_INIT_JOYSTICK
		) < 0)
		{
			fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError());
			return -1;
		}

		Loader::data_directory = SDL_GetPrefPath("HelveticaScenario", "Yearning");

		SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");

		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
		SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);

		{
			SDL_DisplayMode display;
			SDL_GetDesktopDisplayMode(0, &display);
			Loader::settings_load(display.w, display.h);
		}

		if (SDL_SetRelativeMouseMode(SDL_TRUE) != 0)
		{
			fprintf(stderr, "Failed to set relative mouse mode: %s\n", SDL_GetError());
			return -1;
		}

		window = SDL_CreateWindow
		(
			"The Yearning",
			0,
			0,
			Settings::width, Settings::height,
			SDL_WINDOW_OPENGL
			| SDL_WINDOW_SHOWN
			| SDL_WINDOW_INPUT_GRABBED
			| SDL_WINDOW_INPUT_FOCUS
			| SDL_WINDOW_MOUSE_FOCUS
			| SDL_WINDOW_MOUSE_CAPTURE
			| SDL_WINDOW_ALLOW_HIGHDPI
			| (Settings::fullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_BORDERLESS)
		);

#if defined(__APPLE__)
		SDL_SetWindowGrab(window, SDL_TRUE);
#endif

		// Open a window and create its OpenGL context
		if (!window)
		{
			fprintf(stderr, "Failed to open SDL window. Most likely your GPU is out of date! %s\n", SDL_GetError());
			SDL_Quit();
			return -1;
		}

		SDL_GLContext context = SDL_GL_CreateContext(window);
		if (!context)
		{
			fprintf(stderr, "Failed to create GL context: %s\n", SDL_GetError());
			return -1;
		}

		if (SDL_GL_SetSwapInterval(Settings::vsync ? 1 : 0) != 0)
		{
			fprintf(stderr, "Failed to set OpenGL swap interval: %s\n", SDL_GetError());
			return -1;
		}

		{
			glewExperimental = true; // Needed for core profile

			GLenum glew_result = glewInit();
			if (glew_result != GLEW_OK)
			{
				fprintf(stderr, "Failed to initialize GLEW: %s\n", glewGetErrorString(glew_result));
				return -1;
			}
		}

		glGetError(); // Clear initial error caused by GLEW

		render_init();

		// Launch threads

		Sync<LoopSync> render_sync;

		LoopSwapper swapper_render_update = render_sync.swapper(0);
		LoopSwapper swapper_render = render_sync.swapper(1);

		Sync<PhysicsSync, 1> physics_sync;

		PhysicsSwapper swapper_physics = physics_sync.swapper();
		PhysicsSwapper swapper_physics_update = physics_sync.swapper();

		std::thread thread_physics(Physics::loop, &swapper_physics);

		std::thread thread_update(Loop::loop, &swapper_render_update, &swapper_physics_update);

		std::thread thread_ai(AI::loop);

		LoopSync* sync = swapper_render.get();

		r64 last_time = SDL_GetTicks() / 1000.0;

		b8 has_focus = true;

		SDL_PumpEvents();

		const u8* sdl_keys = SDL_GetKeyboardState(0);

		refresh_controllers();

		while (true)
		{
			render(sync);

			// Swap buffers
			SDL_GL_SwapWindow(window);

			SDL_PumpEvents();

			memcpy(sync->input.keys, sdl_keys, sizeof(sync->input.keys));

			sync->input.keys[(s32)KeyCode::MouseWheelDown] = false;
			sync->input.keys[(s32)KeyCode::MouseWheelUp] = false;

			SDL_Event sdl_event;
			while (SDL_PollEvent(&sdl_event))
			{
				if (sdl_event.type == SDL_QUIT)
					sync->quit = true;
				else if (sdl_event.type == SDL_MOUSEWHEEL)
				{ 
					b8 up = sdl_event.wheel.y > 0;
					if (sdl_event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
						up = !up;
					if (up)
						sync->input.keys[(s32)KeyCode::MouseWheelUp] = true;
					else
						sync->input.keys[(s32)KeyCode::MouseWheelDown] = true;
				} 
				else if (sdl_event.type == SDL_JOYDEVICEADDED
					|| sdl_event.type == SDL_JOYDEVICEREMOVED)
					refresh_controllers();
				else if (sdl_event.type == SDL_WINDOWEVENT)
				{
					if (sdl_event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
						has_focus = true;
					else if (sdl_event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
						has_focus = false;
				}
			}

			sync->input.focus = has_focus;

			s32 mouse_buttons = SDL_GetRelativeMouseState(&sync->input.cursor_x, &sync->input.cursor_y);

			sync->input.keys[(s32)KeyCode::MouseLeft] = mouse_buttons & (1 << 0);
			sync->input.keys[(s32)KeyCode::MouseMiddle] = mouse_buttons & (1 << 1);
			sync->input.keys[(s32)KeyCode::MouseRight] = mouse_buttons & (1 << 2);

			s32 active_gamepads = 0;
			for (s32 i = 0; i < MAX_GAMEPADS; i++)
			{
				SDL_GameController* controller = controllers[i];
				Gamepad* gamepad = &sync->input.gamepads[i];
				gamepad->active = controller != 0;
				gamepad->btns = 0;
				if (gamepad->active)
				{
					gamepad->left_x = (r32)SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) / 32767.0f;
					gamepad->left_y = (r32)SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) / 32767.0f;
					gamepad->right_x = (r32)SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) / 32767.0f;
					gamepad->right_y = (r32)SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) / 32767.0f;
					gamepad->left_trigger = (r32)SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) / 32767.0f;
					gamepad->right_trigger = (r32)SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) / 32767.0f;
					if (gamepad->left_trigger > 0.5f)
						gamepad->btns |= Gamepad::Btn::LeftTrigger;
					if (gamepad->right_trigger > 0.5f)
						gamepad->btns |= Gamepad::Btn::RightTrigger;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_LEFTSHOULDER))
						gamepad->btns |= Gamepad::Btn::LeftShoulder;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER))
						gamepad->btns |= Gamepad::Btn::RightShoulder;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_LEFTSTICK))
						gamepad->btns |= Gamepad::Btn::LeftClick;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_RIGHTSTICK))
						gamepad->btns |= Gamepad::Btn::RightClick;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_A))
						gamepad->btns |= Gamepad::Btn::A;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_B))
						gamepad->btns |= Gamepad::Btn::B;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_X))
						gamepad->btns |= Gamepad::Btn::X;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_Y))
						gamepad->btns |= Gamepad::Btn::Y;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_BACK))
						gamepad->btns |= Gamepad::Btn::Back;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_START))
						gamepad->btns |= Gamepad::Btn::Start;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_UP))
						gamepad->btns |= Gamepad::Btn::DUp;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN))
						gamepad->btns |= Gamepad::Btn::DDown;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT))
						gamepad->btns |= Gamepad::Btn::DLeft;
					if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
						gamepad->btns |= Gamepad::Btn::DRight;
					if (gamepad->rumble > 0.0f)
						SDL_HapticRumblePlay(haptics[i], gamepad->rumble, 33);
					gamepad->rumble = 0.0f;
					active_gamepads++;
				}
				else
				{
					gamepad->left_x = 0.0f;
					gamepad->left_y = 0.0f;
					gamepad->right_x = 0.0f;
					gamepad->right_y = 0.0f;
					gamepad->left_trigger = 0.0f;
					gamepad->right_trigger = 0.0f;
					gamepad->rumble = 0.0f;
				}
			}

			SDL_GetWindowSize(window, &sync->input.width, &sync->input.height);

			r64 time = (SDL_GetTicks() / 1000.0);
			sync->time.total = (r32)time;
			sync->time.delta = vi_min((r32)(time - last_time), 0.25f);
			last_time = time;

			b8 quit = sync->quit;

			sync = swapper_render.swap<SwapType_Read>();

			if (quit || sync->quit)
				break;
		}

		AI::quit();

		thread_update.join();
		thread_physics.join();
		thread_ai.join();

		SDL_GL_DeleteContext(context);
		SDL_DestroyWindow(window);

		// SDL sucks
		for (s32 i = 0; i < MAX_GAMEPADS; i++)
		{
			if (haptics[i])
				SDL_HapticClose(haptics[i]);
		}

		SDL_Quit();

		return 0;
	}
Esempio n. 12
0
int main(int argc, char *argv[]) {
    // Get path
    char *ip = NULL;
    unsigned short connect_port = 0;
    unsigned short listen_port = 0;
    int net_mode = NET_MODE_NONE;
    int ret = 0;

    // Path manager
    if(pm_init() != 0) {
        err_msgbox(pm_get_errormsg());
        return 1;
    }

    // Check arguments
    if(argc >= 2) {
        if(strcmp(argv[1], "-v") == 0) {
            printf("OpenOMF v%d.%d.%d\n", V_MAJOR, V_MINOR, V_PATCH);
            printf("Source available at https://github.com/omf2097/ under MIT License\n");
            printf("(C) 2097 Tuomas Virtanen, Andrew Thompson, Hunter and others\n");
            goto exit_0;
        } else if(strcmp(argv[1], "-h") == 0) {
            printf("Arguments:\n");
            printf("-h              Prints this help\n");
            printf("-c [ip] [port]  Connect to server\n");
            printf("-l [port]       Start server\n");
            goto exit_0;
        } else if(strcmp(argv[1], "-c") == 0) {
            if(argc >= 3) {
                ip = strcpy(malloc(strlen(argv[2])+1), argv[2]);
            }
            if(argc >= 4) {
                connect_port = atoi(argv[3]);
            }
            net_mode = NET_MODE_CLIENT;
        } else if(strcmp(argv[1], "-l") == 0) {
            if(argc >= 3) {
                listen_port = atoi(argv[2]);
            }
            net_mode = NET_MODE_SERVER;
        }
    }

    // Init log
#if defined(DEBUGMODE) || defined(STANDALONE_SERVER)
    if(log_init(0)) {
        err_msgbox("Error while initializing log!");
        goto exit_0;
    }
#else
    if(log_init(pm_get_local_path(LOG_PATH))) {
        err_msgbox("Error while initializing log '%s'!", pm_get_local_path(LOG_PATH));
        goto exit_0;
    }
#endif

    // Simple header
    INFO("Starting OpenOMF v%d.%d.%d", V_MAJOR, V_MINOR, V_PATCH);

    // Dump pathmanager log
    pm_log();

    // Random seed
    rand_seed(time(NULL));

    // Init stringparser
    sd_stringparser_lib_init();

    // Init config
    if(settings_init(pm_get_local_path(CONFIG_PATH))) {
        err_msgbox("Failed to initialize settings file");
        goto exit_1;
    }
    settings_load();

    // Find plugins and make sure they are valid
    plugins_init();

    // Network game override stuff
    if(ip) {
        DEBUG("Connect IP overridden to %s", ip);
        settings_get()->net.net_connect_ip = ip;
    }
    if(connect_port > 0 && connect_port < 0xFFFF) {
        DEBUG("Connect Port overridden to %u", connect_port&0xFFFF);
        settings_get()->net.net_connect_port = connect_port;
    }
    if(listen_port > 0 && listen_port < 0xFFFF) {
        DEBUG("Listen Port overridden to %u", listen_port&0xFFFF);
        settings_get()->net.net_listen_port = listen_port;
    }

    // Init SDL2
    unsigned int sdl_flags = SDL_INIT_TIMER;
#ifndef STANDALONE_SERVER
    sdl_flags |= SDL_INIT_VIDEO;
#endif
    if(SDL_Init(sdl_flags)) {
        err_msgbox("SDL2 Initialization failed: %s", SDL_GetError());
        goto exit_2;
    }
    SDL_version sdl_linked;
    SDL_GetVersion(&sdl_linked);
    INFO("Found SDL v%d.%d.%d", sdl_linked.major, sdl_linked.minor, sdl_linked.patch);
    INFO("Running on platform: %s", SDL_GetPlatform());

#ifndef STANDALONE_SERVER
    if(SDL_InitSubSystem(SDL_INIT_JOYSTICK|SDL_INIT_GAMECONTROLLER|SDL_INIT_HAPTIC)) {
        err_msgbox("SDL2 Initialization failed: %s", SDL_GetError());
        goto exit_2;
    }

    // Attempt to find gamecontrollerdb.txt, either from resources or from
    // built-in header
    SDL_RWops *rw = SDL_RWFromConstMem(gamecontrollerdb, strlen(gamecontrollerdb));
    SDL_GameControllerAddMappingsFromRW(rw, 1);
    char *gamecontrollerdbpath = malloc(128);
    snprintf(gamecontrollerdbpath, 128, "%s/gamecontrollerdb.txt", pm_get_local_path(RESOURCE_PATH));
    int mappings_loaded = SDL_GameControllerAddMappingsFromFile(gamecontrollerdbpath);
    if (mappings_loaded > 0) {
        DEBUG("loaded %d mappings from %s", mappings_loaded, gamecontrollerdbpath);
    }
    free(gamecontrollerdbpath);

    // Load up joysticks
    INFO("Found %d joysticks attached", SDL_NumJoysticks());
    SDL_Joystick *joy;
    char guidstr[33];
    for (int i = 0; i < SDL_NumJoysticks(); i++) {
        joy = SDL_JoystickOpen(i);
        if (joy) {
            SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy);
            SDL_JoystickGetGUIDString(guid, guidstr, 33);
            INFO("Opened Joystick %d", i);
            INFO(" * Name:              %s", SDL_JoystickNameForIndex(i));
            INFO(" * Number of Axes:    %d", SDL_JoystickNumAxes(joy));
            INFO(" * Number of Buttons: %d", SDL_JoystickNumButtons(joy));
            INFO(" * Number of Balls:   %d", SDL_JoystickNumBalls(joy));
            INFO(" * Number of Hats:    %d", SDL_JoystickNumHats(joy));
            INFO(" * GUID          :    %s", guidstr);
        } else {
            INFO("Joystick %d is unsupported", i);
        }

        if (SDL_JoystickGetAttached(joy)) {
            SDL_JoystickClose(joy);
        }
    }

    // Init libDumb
    dumb_register_stdfiles();
#endif

    // Init enet
    if(enet_initialize() != 0) {
        err_msgbox("Failed to initialize enet");
        goto exit_3;
    }

    // Initialize engine
    if(engine_init()) {
        err_msgbox("Failed to initialize game engine.");
        goto exit_4;
    }

    // Run
    engine_run(net_mode);

    // Close everything
    engine_close();
exit_4:
    enet_deinitialize();
exit_3:
    SDL_Quit();
exit_2:
    dumb_exit();
    settings_save();
    settings_free();
exit_1:
    sd_stringparser_lib_deinit();
    INFO("Exit.");
    log_close();
exit_0:
    if (ip) {
        free(ip);
    }
    plugins_close();
    pm_free();
    return ret;
}