mirror of
https://github.com/open-goal/jak-project
synced 2026-07-07 22:22:21 -04:00
game: windowed mode related fixes (#1778)
* game: restore windowed mode settings properly * game: use the game version for saving settings/saves * game: prevent windowed mode from being auto-centered on initial init * game: save and restore window coordinates * lint: formatting
This commit is contained in:
@@ -33,8 +33,8 @@
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Assert.h"
|
||||
#include <common/log/log.h>
|
||||
|
||||
namespace file_util {
|
||||
fs::path get_user_home_dir() {
|
||||
@@ -66,14 +66,14 @@ fs::path get_user_config_dir() {
|
||||
return config_base_path / "OpenGOAL";
|
||||
}
|
||||
|
||||
fs::path get_user_settings_dir() {
|
||||
// TODO - jak2
|
||||
return get_user_config_dir() / "jak1" / "settings";
|
||||
fs::path get_user_settings_dir(GameVersion game_version) {
|
||||
auto game_version_name = game_version_names[game_version];
|
||||
return get_user_config_dir() / game_version_name / "settings";
|
||||
}
|
||||
|
||||
fs::path get_user_memcard_dir() {
|
||||
// TODO - jak2
|
||||
return get_user_config_dir() / "jak1" / "saves";
|
||||
fs::path get_user_memcard_dir(GameVersion game_version) {
|
||||
auto game_version_name = game_version_names[game_version];
|
||||
return get_user_config_dir() / game_version_name / "saves";
|
||||
}
|
||||
|
||||
struct {
|
||||
|
||||
@@ -22,14 +22,15 @@
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/versions.h"
|
||||
|
||||
namespace fs = ghc::filesystem;
|
||||
|
||||
namespace file_util {
|
||||
fs::path get_user_home_dir();
|
||||
fs::path get_user_config_dir();
|
||||
fs::path get_user_settings_dir();
|
||||
fs::path get_user_memcard_dir();
|
||||
fs::path get_user_settings_dir(GameVersion game_version);
|
||||
fs::path get_user_memcard_dir(GameVersion game_version);
|
||||
fs::path get_jak_project_dir();
|
||||
|
||||
bool create_dir_if_needed(const fs::path& path);
|
||||
|
||||
@@ -5,9 +5,17 @@
|
||||
|
||||
#include "display.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "common/util/json_util.h"
|
||||
|
||||
#include "game/runtime.h"
|
||||
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
/*
|
||||
********************************
|
||||
@@ -61,6 +69,35 @@ int GfxDisplay::height() {
|
||||
return h;
|
||||
}
|
||||
|
||||
void GfxDisplay::save_display_settings() {
|
||||
nlohmann::json json;
|
||||
json["window_xpos"] = m_last_windowed_xpos;
|
||||
json["window_ypos"] = m_last_windowed_ypos;
|
||||
std::string file_path =
|
||||
(file_util::get_user_settings_dir(g_game_version) / "display-settings.json").string();
|
||||
file_util::write_text_file(file_path, json.dump(2));
|
||||
}
|
||||
|
||||
void GfxDisplay::restore_display_settings() {
|
||||
try {
|
||||
std::string file_path =
|
||||
(file_util::get_user_settings_dir(g_game_version) / "display-settings.json").string();
|
||||
if (!file_util::file_exists(file_path)) {
|
||||
return;
|
||||
}
|
||||
auto raw = file_util::read_text_file(file_path);
|
||||
auto json = parse_commented_json(raw, "display-settings.json");
|
||||
if (json.contains("window_xpos")) {
|
||||
m_last_windowed_xpos = json.at("window_xpos").get<int>();
|
||||
}
|
||||
if (json.contains("window_ypos")) {
|
||||
m_last_windowed_ypos = json.at("window_ypos").get<int>();
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
********************************
|
||||
* DISPLAY
|
||||
@@ -93,6 +130,8 @@ int InitMainDisplay(int width,
|
||||
return 1;
|
||||
}
|
||||
set_main_display(display);
|
||||
// Restore window settings
|
||||
display->restore_display_settings();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -108,6 +147,8 @@ void KillDisplay(std::shared_ptr<GfxDisplay> display) {
|
||||
}
|
||||
|
||||
if (GetMainDisplay() == display) {
|
||||
// Save the main display's position to a file so it can be restored upon re-opening
|
||||
display->save_display_settings();
|
||||
// killing the main display, kill all children displays too!
|
||||
while (g_displays.size() > 1) {
|
||||
KillDisplay(g_displays.at(1));
|
||||
|
||||
+12
-3
@@ -28,12 +28,13 @@ class GfxDisplay {
|
||||
// next mode
|
||||
GfxDisplayMode m_fullscreen_target_mode = GfxDisplayMode::Windowed;
|
||||
// current mode (start as -1 to force an initial fullscreen update)
|
||||
GfxDisplayMode m_fullscreen_mode = (GfxDisplayMode)-1;
|
||||
GfxDisplayMode m_fullscreen_mode = GfxDisplayMode::ForceUpdate;
|
||||
// previous mode (last frame)
|
||||
GfxDisplayMode m_last_fullscreen_mode = GfxDisplayMode::Windowed;
|
||||
|
||||
int m_last_windowed_xpos = 0;
|
||||
int m_last_windowed_ypos = 0;
|
||||
// move it a bit away from the top, or the title bar can be hidden
|
||||
int m_last_windowed_xpos = 50;
|
||||
int m_last_windowed_ypos = 50;
|
||||
int m_last_windowed_width = 640;
|
||||
int m_last_windowed_height = 480;
|
||||
|
||||
@@ -84,6 +85,14 @@ class GfxDisplay {
|
||||
|
||||
int width();
|
||||
int height();
|
||||
|
||||
struct DisplaySettings {
|
||||
int window_xpos;
|
||||
int window_ypos;
|
||||
};
|
||||
|
||||
void save_display_settings();
|
||||
void restore_display_settings();
|
||||
};
|
||||
|
||||
namespace Display {
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ class GfxDisplay;
|
||||
|
||||
// enum for rendering pipeline
|
||||
enum class GfxPipeline { Invalid = 0, OpenGL };
|
||||
enum GfxDisplayMode { Windowed = 0, Fullscreen = 1, Borderless = 2 };
|
||||
enum GfxDisplayMode { ForceUpdate = -1, Windowed = 0, Fullscreen = 1, Borderless = 2 };
|
||||
|
||||
// module for the different rendering pipelines
|
||||
struct GfxRendererModule {
|
||||
|
||||
@@ -371,14 +371,18 @@ void GLDisplay::on_cursor_position(GLFWwindow* window, double xposition, double
|
||||
}
|
||||
|
||||
void GLDisplay::on_window_pos(GLFWwindow* /*window*/, int xpos, int ypos) {
|
||||
if (m_fullscreen_target_mode == GfxDisplayMode::Windowed) {
|
||||
// only change them on a legit change, not on the initial update
|
||||
if (m_fullscreen_mode != GfxDisplayMode::ForceUpdate &&
|
||||
m_fullscreen_target_mode == GfxDisplayMode::Windowed) {
|
||||
m_last_windowed_xpos = xpos;
|
||||
m_last_windowed_ypos = ypos;
|
||||
}
|
||||
}
|
||||
|
||||
void GLDisplay::on_window_size(GLFWwindow* /*window*/, int width, int height) {
|
||||
if (m_fullscreen_target_mode == GfxDisplayMode::Windowed) {
|
||||
// only change them on a legit change, not on the initial update
|
||||
if (m_fullscreen_mode != GfxDisplayMode::ForceUpdate &&
|
||||
m_fullscreen_target_mode == GfxDisplayMode::Windowed) {
|
||||
m_last_windowed_width = width;
|
||||
m_last_windowed_height = height;
|
||||
}
|
||||
@@ -556,11 +560,13 @@ void GLDisplay::update_fullscreen(GfxDisplayMode mode, int screen) {
|
||||
|
||||
glfwSetWindowMonitor(m_window, NULL, x, y, width, height, GLFW_DONT_CARE);
|
||||
|
||||
// these might have changed
|
||||
m_last_windowed_width = width;
|
||||
m_last_windowed_height = height;
|
||||
m_last_windowed_xpos = x;
|
||||
m_last_windowed_ypos = y;
|
||||
// these might have changed, only store them on a legit change, not on the initial update
|
||||
if (m_last_fullscreen_mode != GfxDisplayMode::ForceUpdate) {
|
||||
m_last_windowed_width = width;
|
||||
m_last_windowed_height = height;
|
||||
m_last_windowed_xpos = x;
|
||||
m_last_windowed_ypos = y;
|
||||
}
|
||||
} break;
|
||||
case GfxDisplayMode::Fullscreen: {
|
||||
// fullscreen
|
||||
@@ -584,6 +590,9 @@ void GLDisplay::update_fullscreen(GfxDisplayMode mode, int screen) {
|
||||
glfwSetWindowMonitor(m_window, NULL, x, y, vmode->width, vmode->height, GLFW_DONT_CARE);
|
||||
#endif
|
||||
} break;
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,8 +69,9 @@ class GLDisplay : public GfxDisplay {
|
||||
};
|
||||
|
||||
struct DisplayState {
|
||||
s32 window_pos_x = 0;
|
||||
s32 window_pos_y = 0;
|
||||
// move it a bit away from the top by default
|
||||
s32 window_pos_x = 50;
|
||||
s32 window_pos_y = 50;
|
||||
int window_size_width = 640, window_size_height = 480;
|
||||
float window_scale_x = 1.f, window_scale_y = 1.f;
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ u32 mc_checksum(Ptr<u8> data, s32 size) {
|
||||
* PC port function that returns whether a given bank ID's file exists or not.
|
||||
*/
|
||||
bool file_is_present(int id, int bank = 0) {
|
||||
auto bankname = file_util::get_user_memcard_dir() / filename[4 + id * 2 + bank];
|
||||
auto bankname = file_util::get_user_memcard_dir(g_game_version) / filename[4 + id * 2 + bank];
|
||||
if (!fs::exists(bankname) || fs::file_size(bankname) < BANK_TOTAL_SIZE) {
|
||||
// file doesn't exist, or size is bad. we do not want to open files that will crash on read!
|
||||
return false;
|
||||
@@ -146,13 +146,14 @@ void pc_update_card() {
|
||||
// int highest_save_count = 0;
|
||||
mc_last_file = -1;
|
||||
for (s32 file = 0; file < 4; file++) {
|
||||
auto bankname = file_util::get_user_memcard_dir() / filename[4 + file * 2];
|
||||
auto bankname = file_util::get_user_memcard_dir(g_game_version) / filename[4 + file * 2];
|
||||
mc_files[file].present = file_is_present(file);
|
||||
if (mc_files[file].present) {
|
||||
auto bankdata = file_util::read_binary_file(bankname.string());
|
||||
auto header1 = reinterpret_cast<McHeader*>(bankdata.data());
|
||||
if (file_is_present(file, 1)) {
|
||||
auto bankname2 = file_util::get_user_memcard_dir() / filename[1 + 4 + file * 2];
|
||||
auto bankname2 =
|
||||
file_util::get_user_memcard_dir(g_game_version) / filename[1 + 4 + file * 2];
|
||||
auto bankdata2 = file_util::read_binary_file(bankname2.string());
|
||||
auto header2 = reinterpret_cast<McHeader*>(bankdata2.data());
|
||||
|
||||
@@ -189,7 +190,7 @@ void pc_game_save_synch() {
|
||||
Timer mc_timer;
|
||||
mc_timer.start();
|
||||
pc_update_card();
|
||||
auto path = file_util::get_user_memcard_dir() / filename[0];
|
||||
auto path = file_util::get_user_memcard_dir(g_game_version) / filename[0];
|
||||
file_util::create_dir_if_needed_for_file(path.string());
|
||||
|
||||
// cd_reprobe_save //
|
||||
@@ -211,7 +212,8 @@ void pc_game_save_synch() {
|
||||
// file*2 + p4 is the bank (2 banks per file, p4 is 0 or 1 to select the bank)
|
||||
// 4 is the first bank file
|
||||
mc_print("open {} for saving", filename[op.param2 * 2 + 4 + p4]);
|
||||
auto save_path = file_util::get_user_memcard_dir() / filename[op.param2 * 2 + 4 + p4];
|
||||
auto save_path =
|
||||
file_util::get_user_memcard_dir(g_game_version) / filename[op.param2 * 2 + 4 + p4];
|
||||
file_util::create_dir_if_needed_for_file(save_path.string());
|
||||
auto fd = file_util::open_file(save_path.string().c_str(), "wb");
|
||||
mc_print("synchronous save file open took {:.2f}ms\n", mc_timer.getMs());
|
||||
@@ -281,11 +283,12 @@ void pc_game_load_open_file(FILE* fd) {
|
||||
if (fclose(fd) == 0) {
|
||||
// cb_closedload //
|
||||
// added : check if aux bank exists
|
||||
if (p2 < 1 &&
|
||||
fs::exists(file_util::get_user_memcard_dir() / filename[op.param2 * 2 + 4 + p2 + 1])) {
|
||||
if (p2 < 1 && fs::exists(file_util::get_user_memcard_dir(g_game_version) /
|
||||
filename[op.param2 * 2 + 4 + p2 + 1])) {
|
||||
p2++;
|
||||
mc_print("reading next save bank {}", filename[op.param2 * 2 + 4 + p2]);
|
||||
auto new_bankname = file_util::get_user_memcard_dir() / filename[op.param2 * 2 + 4 + p2];
|
||||
auto new_bankname =
|
||||
file_util::get_user_memcard_dir(g_game_version) / filename[op.param2 * 2 + 4 + p2];
|
||||
auto new_fd = file_util::open_file(new_bankname.string().c_str(), "rb");
|
||||
pc_game_load_open_file(new_fd);
|
||||
} else {
|
||||
@@ -402,7 +405,7 @@ void pc_game_load_synch() {
|
||||
p2 = 0;
|
||||
mc_print("opening save file {}", filename[op.param2 * 2 + 4]);
|
||||
|
||||
auto path = file_util::get_user_memcard_dir() / filename[op.param2 * 2 + 4];
|
||||
auto path = file_util::get_user_memcard_dir(g_game_version) / filename[op.param2 * 2 + 4];
|
||||
auto fd = file_util::open_file(path.string().c_str(), "rb");
|
||||
pc_game_load_open_file(fd);
|
||||
|
||||
|
||||
@@ -677,8 +677,7 @@ void InitMachine_PCPort() {
|
||||
auto user_dir_path = file_util::get_user_config_dir();
|
||||
intern_from_c("*pc-user-dir-base-path*")->value =
|
||||
make_string_from_c(user_dir_path.string().c_str());
|
||||
// TODO - we will eventually need a better way to know what game we are playing
|
||||
auto settings_path = file_util::get_user_settings_dir();
|
||||
auto settings_path = file_util::get_user_settings_dir(g_game_version);
|
||||
intern_from_c("*pc-settings-folder*")->value = make_string_from_c(settings_path.string().c_str());
|
||||
intern_from_c("*pc-settings-built-sha*")->value = make_string_from_c(GIT_VERSION);
|
||||
}
|
||||
|
||||
@@ -521,8 +521,7 @@ void InitMachine_PCPort() {
|
||||
auto user_dir_path = file_util::get_user_config_dir();
|
||||
intern_from_c("*pc-user-dir-base-path*")->value() =
|
||||
make_string_from_c(user_dir_path.string().c_str());
|
||||
// TODO - we will eventually need a better way to know what game we are playing
|
||||
auto settings_path = file_util::get_user_settings_dir();
|
||||
auto settings_path = file_util::get_user_settings_dir(g_game_version);
|
||||
intern_from_c("*pc-settings-folder*")->value() =
|
||||
make_string_from_c(settings_path.string().c_str());
|
||||
intern_from_c("*pc-settings-built-sha*")->value() = make_string_from_c(GIT_VERSION);
|
||||
|
||||
@@ -48,18 +48,18 @@
|
||||
;;;; updates
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
|
||||
(defmethod set-display-mode! pc-settings ((obj pc-settings) (mode symbol))
|
||||
"sets the game's display mode"
|
||||
|
||||
;; change the display mode.
|
||||
(set! (-> obj display-mode) mode)
|
||||
;; if windowed mode, set the size properly
|
||||
(when (= (-> obj display-mode) 'windowed)
|
||||
(pc-set-window-size (max PC_MIN_WIDTH (-> obj win-width)) (max PC_MIN_HEIGHT (-> obj win-height))))
|
||||
0)
|
||||
|
||||
(defmethod set-size! pc-settings ((obj pc-settings) (width int) (height int))
|
||||
"sets the size of the display window"
|
||||
(format #t "Setting size to ~D x ~D~%" width height)
|
||||
(format 0 "Setting ~A size to ~D x ~D~%" (-> obj display-mode) width height)
|
||||
(cond
|
||||
((= 'windowed (-> obj display-mode))
|
||||
(set! (-> obj win-width) width)
|
||||
@@ -73,7 +73,6 @@
|
||||
)
|
||||
(none))
|
||||
|
||||
|
||||
(defmethod set-aspect! pc-settings ((obj pc-settings) (aw int) (ah int))
|
||||
"set the aspect ratio used for rendering. this forces native widescreen and takes width and height ratios."
|
||||
(let ((aspect (/ (the float aw) (the float ah))))
|
||||
@@ -916,6 +915,10 @@
|
||||
|
||||
(format 0 "pc settings file read: ~A~%" filename)
|
||||
|
||||
;; restore the windowed mode resolution properly
|
||||
(when (= (-> obj display-mode) 'windowed)
|
||||
(pc-set-window-size (max PC_MIN_WIDTH (-> obj win-width)) (max PC_MIN_HEIGHT (-> obj win-height))))
|
||||
|
||||
#t
|
||||
)
|
||||
|
||||
@@ -932,13 +935,13 @@
|
||||
(format file "(settings #x~X~%" (-> obj version))
|
||||
|
||||
(format file " (fps ~D)~%" (-> obj target-fps))
|
||||
(format file " (game-size ~D ~D)~%" (-> obj width) (-> obj height))
|
||||
(format file " (msaa ~D)~%" (-> obj gfx-msaa))
|
||||
(format file " (window-size ~D ~D)~%" (-> obj win-width) (-> obj win-height))
|
||||
(format file " (aspect-state ~A ~D ~D ~A)~%" (-> *setting-control* default aspect-ratio)
|
||||
(-> obj aspect-custom-x) (-> obj aspect-custom-y)
|
||||
(-> obj aspect-ratio-auto?))
|
||||
(format file " (display-mode ~A)~%" (-> obj display-mode))
|
||||
(format file " (window-size ~D ~D)~%" (-> obj win-width) (-> obj win-height))
|
||||
(format file " (game-size ~D ~D)~%" (-> obj width) (-> obj height))
|
||||
(format file " (monitor ~D)~%" (-> obj monitor))
|
||||
(format file " (letterbox ~A)~%" (-> obj letterbox?))
|
||||
(format file " (vsync ~A)~%" (-> obj vsync?))
|
||||
|
||||
Reference in New Issue
Block a user