// redriver2_psxpc.cpp // #include #include "platform.h" #include "driver2.h" #include "C/main.h" #include "C/system.h" #include "C/gamesnd.h" #include "C/camera.h" #include "C/cars.h" #include "C/civ_ai.h" #include "C/mission.h" #include "C/cutscene.h" #include "C/glaunch.h" #include "C/loadview.h" #include "C/overlay.h" #include "C/players.h" #include "utils/ini.h" #include #include #include #include "PSYX_GLOBALS.H" int(*GPU_printf)(const char *fmt, ...); bool CtrlModifier; bool ShiftModifier; bool AltModifier; void CheckModifierKeys(int nKey, bool down) { switch (nKey) { case SDL_SCANCODE_LCTRL: CtrlModifier = down; break; case SDL_SCANCODE_LSHIFT: ShiftModifier = down; break; case SDL_SCANCODE_LALT: AltModifier = down; break; } } extern int gDrawDistance; int cursorX, cursorY, cursorOldX, cursorOldY; extern int g_FreeCameraEnabled; void FreeCameraMouseHandler(int x, int y) { if (g_FreeCameraEnabled) { extern SVECTOR g_FreeCameraRotation; int width, height; PsyX_GetScreenSize(width, height); cursorX = x; cursorY = y; PsyX_SetCursorPosition(width / 2, height / 2); g_FreeCameraRotation.vy -= cursorX - cursorOldX; g_FreeCameraRotation.vx += cursorY - cursorOldY; cursorX = width / 2; cursorY = height / 2; cursorOldX = cursorX; cursorOldY = cursorY; } } void FreeCameraKeyboardHandler(int nKey, bool down) { if (g_FreeCameraEnabled) { extern int g_FreeCameraControls; if (nKey == SDL_SCANCODE_W) { if (down) g_FreeCameraControls |= 0x1; else g_FreeCameraControls &= ~0x1; } else if (nKey == SDL_SCANCODE_S) { if (down) g_FreeCameraControls |= 0x2; else g_FreeCameraControls &= ~0x2; } else if (nKey == SDL_SCANCODE_A) { if (down) g_FreeCameraControls |= 0x4; else g_FreeCameraControls &= ~0x4; } else if (nKey == SDL_SCANCODE_D) { if (down) g_FreeCameraControls |= 0x8; else g_FreeCameraControls &= ~0x8; } } if(!down) return; if (nKey == SDL_SCANCODE_F7) { g_FreeCameraEnabled ^= 1; printf("Free camera: %s\n", g_FreeCameraEnabled ? "ON" : "OFF"); } } int gShowCollisionDebug = 0; #if defined(DEBUG_OPTIONS) || defined(_DEBUG) extern int gDisplayPosition; extern int gDisplayDrawStats; int gStopCivCars = 0; extern void FunkUpDaBGMTunez(int funk); void GameDebugKeys(int nKey, bool down) { CheckModifierKeys(nKey, down); FreeCameraKeyboardHandler(nKey, down); if (!down) return; if (nKey == SDL_SCANCODE_1) { gDisplayPosition ^= 1; printf("Position display %s\n", gDisplayPosition ? "ON" : "OFF"); } else if (nKey == SDL_SCANCODE_2) { gShowCollisionDebug++; gShowCollisionDebug %= 5; printf("Collision debug: %d\n", gShowCollisionDebug); } else if (nKey == SDL_SCANCODE_3) { gDisplayDrawStats ^= 1; printf("Stats %s\n", gDisplayDrawStats ? "ON" : "OFF"); } else if (nKey == SDL_SCANCODE_BACKSPACE) { extern int FastForward; FastForward = 1; } #ifdef _DEBUG else if (nKey == SDL_SCANCODE_0) { gStopCivCars ^= 1; printf("Civ cars stop %s\n", gStopCivCars ? "ON" : "OFF"); } else if (nKey == SDL_SCANCODE_PAGEUP) { player[0].cameraCarId++; if (player[0].cameraCarId > MAX_CARS - 1) player[0].cameraCarId = MAX_CARS - 1; printf("Car on camera: %d\n", player[0].cameraCarId); } else if (nKey == SDL_SCANCODE_PAGEDOWN) { player[0].cameraCarId--; if (player[0].cameraCarId < 0) player[0].cameraCarId = 0; printf("Car on camera: %d\n", player[0].cameraCarId); } else if (nKey == SDL_SCANCODE_KP_DIVIDE) { FunkUpDaBGMTunez(0); } else if (nKey == SDL_SCANCODE_KP_MULTIPLY) { FunkUpDaBGMTunez(1); extern void CreateRoadblock(); CreateRoadblock(); } else if (nKey == SDL_SCANCODE_KP_PLUS) { extern LEAD_PARAMETERS LeadValues; static bool already = false; static bool leadReady = false; static int lastmodel = 1; /* ---- LEAD VALUES ---- 500 1000 428 21 885 10 487 2 700 350 1731 30 320 7 225 3 */ // Find the clue LeadValues.tEnd = 500; LeadValues.tAvelLimit = 1000; LeadValues.tDist = 428; LeadValues.tDistMul = 21; LeadValues.tWidth = 885; LeadValues.tWidthMul = 10; LeadValues.tWidth80 = 487; LeadValues.tWidth80Mul = 2; LeadValues.hEnd = 700; LeadValues.dEnd = 350; LeadValues.hDist = 1731; LeadValues.hDistMul = 30; LeadValues.hWidth = 320; LeadValues.hWidthMul = 7; LeadValues.hWidth80 = 225; LeadValues.hWidth80Mul = 3; CAR_DATA *pCar = &car_data[player[0].playerCarId]; LONGVECTOR4 startpos = { pCar->hd.where.t[0], pCar->hd.where.t[1], pCar->hd.where.t[2], }; int dir = pCar->hd.direction; int offset = 1000 + (pCar->hd.speed * 36); int heading = (((dir + 512) & 0xfff) >> 10) + 2 & 3; int which = (heading & 1) ? 0 : 2; int model = lastmodel; int palette = 1; if (ShiftModifier) { // force a special car model = MissionHeader->residentModels[4]; palette = 0; lastmodel = model; } else { for (int i = 0; i < 5; i++) { // horrible randomness int newmodel = MissionHeader->residentModels[i]; if (newmodel == 0 || newmodel == lastmodel) continue; if (newmodel != model) { int tmp = CameraCnt % (newmodel + 1); if (tmp & 4) { // rare chance of spawning special car model = MissionHeader->residentModels[4]; palette = 0; lastmodel = model; break; } else if (tmp & 3) { model = newmodel; palette = CameraCnt % 6; lastmodel = model; break; } } } } // add a little more room if (model > 4) offset += 250; // spawn it in front of us if (ABS(dir) >= 750) { if ((heading >> 1) != 1) offset = -offset; } startpos[which] += offset; int slot = CreateStationaryCivCar(dir, 0, 0, &startpos, model, palette, 0); if (slot == -1) { slot = PingInCivCar(15900); slot--; } if (slot != -1) { char playerid = 0xff; InitPlayer((PLAYER *)(player + 1), &car_data[slot], 4, dir, &startpos, model, palette, &playerid); already = true; } else { requestStationaryCivCar = 1; } } else if (nKey == SDL_SCANCODE_KP_MINUS) { PingOutAllCivCarsAndCopCars(); } #endif } #endif #ifndef USE_CRT_MALLOC char g_Overlay_buffer[0x50000]; // 0x1C0000 char g_Frontend_buffer[0x60000]; // 0xFB400 char g_Other_buffer[0x50000]; // 0xF3000 char g_Other_buffer2[0x50000]; // 0xE7000 OTTYPE g_OT1[OTSIZE]; // 0xF3000 OTTYPE g_OT2[OTSIZE]; // 0xF7200 char g_PrimTab1[PRIMTAB_SIZE]; // 0xFB400 char g_PrimTab2[PRIMTAB_SIZE]; // 0x119400 char g_SBank_buffer[0x50000]; // 0x180000 char g_Replay_buffer[0x50000]; // 0x1fABBC #endif void ParseKeyboardMappings(ini_t* config, char* section, PsyXKeyboardMapping& outMapping) { extern PsyXKeyboardMapping g_keyboard_mapping; const char* str; str = ini_get(config, section, "square"); outMapping.kc_square = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_square); str = ini_get(config, section, "circle"); outMapping.kc_circle = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_circle); str = ini_get(config, section, "triangle"); outMapping.kc_triangle = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_triangle); str = ini_get(config, section, "cross"); outMapping.kc_cross = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_cross); str = ini_get(config, section, "l1"); outMapping.kc_l1 = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_l1); str = ini_get(config, section, "l2"); outMapping.kc_l2 = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_l2); str = ini_get(config, section, "l3"); outMapping.kc_l3 = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_l3); str = ini_get(config, section, "r1"); outMapping.kc_r1 = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_r1); str = ini_get(config, section, "r2"); outMapping.kc_r2 = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_r2); str = ini_get(config, section, "r3"); outMapping.kc_r3 = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_r3); str = ini_get(config, section, "up"); outMapping.kc_dpad_up = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_dpad_up); str = ini_get(config, section, "down"); outMapping.kc_dpad_down = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_dpad_down); str = ini_get(config, section, "left"); outMapping.kc_dpad_left = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_dpad_left); str = ini_get(config, section, "right"); outMapping.kc_dpad_right = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_dpad_right); str = ini_get(config, section, "select"); outMapping.kc_select = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_select); str = ini_get(config, section, "start"); outMapping.kc_start = PsyX_LookupKeyboardMapping(str, g_keyboard_mapping.kc_start); } void ParseControllerMappings(ini_t* config, char* section, PsyXControllerMapping& outMapping) { extern PsyXControllerMapping g_controller_mapping; const char* str; str = ini_get(config, section, "square"); outMapping.gc_square = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_square); str = ini_get(config, section, "circle"); outMapping.gc_circle = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_circle); str = ini_get(config, section, "triangle"); outMapping.gc_triangle = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_triangle); str = ini_get(config, section, "cross"); outMapping.gc_cross = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_cross); str = ini_get(config, section, "l1"); outMapping.gc_l1 = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_l1); str = ini_get(config, section, "l2"); outMapping.gc_l2 = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_l2); str = ini_get(config, section, "l3"); outMapping.gc_l3 = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_l3); str = ini_get(config, section, "r1"); outMapping.gc_r1 = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_r1); str = ini_get(config, section, "r2"); outMapping.gc_r2 = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_r2); str = ini_get(config, section, "r3"); outMapping.gc_r3 = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_r3); str = ini_get(config, section, "up"); outMapping.gc_dpad_up = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_dpad_up); str = ini_get(config, section, "down"); outMapping.gc_dpad_down = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_dpad_down); str = ini_get(config, section, "left"); outMapping.gc_dpad_left = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_dpad_left); str = ini_get(config, section, "right"); outMapping.gc_dpad_right = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_dpad_right); str = ini_get(config, section, "select"); outMapping.gc_select = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_select); str = ini_get(config, section, "start"); outMapping.gc_start = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_start); str = ini_get(config, section, "axis_left_x"); outMapping.gc_axis_left_x = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_axis_left_x); str = ini_get(config, section, "axis_left_y"); outMapping.gc_axis_left_y = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_axis_left_y); str = ini_get(config, section, "axis_right_x"); outMapping.gc_axis_right_x = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_axis_right_x); str = ini_get(config, section, "axis_right_y"); outMapping.gc_axis_right_y = PsyX_LookupGameControllerMapping(str, g_controller_mapping.gc_axis_right_y); } PsyXKeyboardMapping g_kbGameMappings = { 0x123 }; PsyXKeyboardMapping g_kbMenuMappings = { 0x456 }; PsyXControllerMapping g_gcGameMappings = { 0x321 }; PsyXControllerMapping g_gcMenuMappings = { 0x654 }; void SwitchMappings(int menu) { extern PsyXKeyboardMapping g_keyboard_mapping; extern PsyXControllerMapping g_controller_mapping; if(menu) { g_keyboard_mapping = g_kbMenuMappings; g_controller_mapping = g_gcMenuMappings; } else { g_keyboard_mapping = g_kbGameMappings; g_controller_mapping = g_gcGameMappings; } } int main(int argc, char** argv) { ini_t* config; #ifdef USE_CRT_MALLOC _overlay_buffer = (char*)malloc(0x50000); // 0x1C0000 _frontend_buffer = (char*)malloc(0x60000); // 0xFB400 _other_buffer = (char*)malloc(0x50000); // 0xF3000 _other_buffer2 = (char*)malloc(0x50000); // 0xE7000 _OT1 = (OTTYPE*)malloc(OTSIZE * sizeof(OTTYPE)); // 0xF3000 _OT2 = (OTTYPE*)malloc(OTSIZE * sizeof(OTTYPE)); // 0xF7200 _primTab1 = (char*)malloc(PRIMTAB_SIZE); // 0xFB400 _primTab2 = (char*)malloc(PRIMTAB_SIZE); // 0x119400 _sbank_buffer = (char*)malloc(0x80000); // 0x180000 _replay_buffer = (char*)malloc(0x50000); // 0x1fabbc #else _overlay_buffer = g_Overlay_buffer; // 0x1C0000 _frontend_buffer = g_Frontend_buffer; // 0xFB400 _other_buffer = g_Other_buffer; // 0xF3000 _other_buffer2 = g_Other_buffer2; // 0xE7000 _OT1 = g_OT1; // 0xF3000 _OT2 = g_OT2; // 0xF7200 _primTab1 = g_PrimTab1; // 0xFB400 _primTab2 = g_PrimTab2; // 0x119400 _sbank_buffer = g_SBank_buffer; // 0x180000 _replay_buffer = g_Replay_buffer; // 0x1fABBC #endif #if defined(DEBUG_OPTIONS) || defined(_DEBUG) GPU_printf = printf; #endif // _DEBUG #if 0 // defined(__EMSCRIPTEN__) // mount the current folder as a NODEFS instance // inside of emscripten EM_ASM( FS.mkdir('/working'); FS.mount(NODEFS, {}, '/working1'); ); #endif const char* configFilename = "config.ini"; const char* cdImageFileName = NULL; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-ini")) { i++; configFilename = argv[i]; } else if(!strcmp(argv[i], "-cdimage")) { i++; cdImageFileName = argv[i]; } } config = ini_load("config.ini"); // best distance gDrawDistance = 600; int windowWidth = 800; int windowHeight = 600; int fullScreen = 0; int enableFreecamera = 0; extern int gUserLanguage; if (config) { extern int gDisableChicagoBridges; extern int gContentOverride; int newScrZ = gCameraDefaultScrZ; const char* dataFolderStr = ini_get(config, "fs", "dataFolder"); const char* userReplaysStr = ini_get(config, "game", "userChases"); if(!cdImageFileName) cdImageFileName = ini_get(config, "cdfs", "image"); InitUserReplays(userReplaysStr); // configure Psy-X pads ini_sget(config, "pad", "pad1device", "%d", &g_controllerToSlotMapping[0]); ini_sget(config, "pad", "pad2device", "%d", &g_controllerToSlotMapping[1]); // configure Psy-X renderer ini_sget(config, "render", "windowWidth", "%d", &windowWidth); ini_sget(config, "render", "windowHeight", "%d", &windowHeight); ini_sget(config, "render", "fullscreen", "%d", &fullScreen); ini_sget(config, "render", "pgxpTextureMapping", "%d", &g_pgxpTextureCorrection); ini_sget(config, "render", "pgxpZbuffer", "%d", &g_pgxpZBuffer); ini_sget(config, "render", "bilinearFiltering", "%d", &g_bilinearFiltering); // configure host game ini_sget(config, "game", "drawDistance", "%d", &gDrawDistance); ini_sget(config, "game", "disableChicagoBridges", "%d", &gDisableChicagoBridges); ini_sget(config, "game", "fieldOfView", "%d", &newScrZ); ini_sget(config, "game", "freeCamera", "%d", &enableFreecamera); ini_sget(config, "game", "driver1music", "%d", &gDriver1Music); ini_sget(config, "game", "widescreenOverlays", "%d", &gWidescreenOverlayAlign); ini_sget(config, "game", "fastLoadingScreens", "%d", &gFastLoadingScreens); ini_sget(config, "game", "languageId", "%d", &gUserLanguage); ini_sget(config, "game", "overrideContent", "%d", &gContentOverride); gCameraDefaultScrZ = MAX(MIN(newScrZ, 384), 128); if (dataFolderStr) { strcpy(gDataFolder, dataFolderStr); int len = strlen(gDataFolder); if (gDataFolder[len - 1] != '\\') { gDataFolder[len] = '\\'; gDataFolder[len + 1] = '\0'; } } #if defined(DEBUG_OPTIONS) int unlockAll = 0; ini_sget(config, "game", "unlockAll", "%d", &unlockAll); if (unlockAll) { gFurthestMission = 40; AvailableCheats.cheat5 = 1; AvailableCheats.cheat6 = 1; AvailableCheats.cheat7 = 1; AvailableCheats.cheat8 = 1; AvailableCheats.cheat2 = 1; AvailableCheats.cheat11 = 1; AvailableCheats.cheat1 = 1; AvailableCheats.cheat3 = 1; AvailableCheats.cheat4 = 1; } #endif } #ifndef _DEBUG if (enableFreecamera) { gameDebugKeys = FreeCameraKeyboardHandler; gameDebugMouse = FreeCameraMouseHandler; } #else gameDebugKeys = GameDebugKeys; gameDebugMouse = FreeCameraMouseHandler; #endif PsyX_Initialise("REDRIVER2", windowWidth, windowHeight, fullScreen); // configure Psy-X CD image reader if (cdImageFileName) PsyX_CDFS_Init(cdImageFileName); if (config) { ParseKeyboardMappings(config, "kbcontrols_game", g_kbGameMappings); ParseKeyboardMappings(config, "kbcontrols_menu", g_kbMenuMappings); ParseControllerMappings(config, "controls_game", g_gcGameMappings); ParseControllerMappings(config, "controls_menu", g_gcMenuMappings); ini_free(config); } // start with menu mapping SwitchMappings(1); redriver2_main(argc, argv); DeinitStringMng(); PsyX_Shutdown(); return 0; }