mirror of
https://github.com/drakmor/ShadowMountPlus.git
synced 2026-10-19 13:19:59 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3530d8d88e | ||
|
|
4dafdde002 | ||
|
|
8566c0294c | ||
|
|
56dd338abd | ||
|
|
090723879c | ||
|
|
16873e01f2 |
No files matched your search
@@ -61,8 +61,6 @@ Supported keys (all optional):
|
||||
- `image_rw=<image_filename>` (repeatable; force read-write mode for this image filename)
|
||||
- `image_sector=<image_filename>:<sector_size>` (repeatable; force sector size for this image filename)
|
||||
- `scan_depth=<1..2>` (`1` = scan only first-level subfolders, `2` = also scan one additional nested level; default: `1`)
|
||||
- `watch_subdirs=1|0` (`1` keeps vnode watchers on scan root subdirectories; default: `0`)
|
||||
- `watch_image_files=1|0` (`1` keeps vnode watchers on discovered image files; default: `1`)
|
||||
- `recursive_scan=1|0` (deprecated compatibility key; `1` forces `scan_depth=2`)
|
||||
- `scan_interval_seconds=<1..3600>` (full scan loop interval; default: `15`)
|
||||
- `stability_wait_seconds=<0..3600>` (minimum source age before processing; default: `10`)
|
||||
@@ -126,7 +124,7 @@ Backport overlay behavior:
|
||||
- The `backports` folder is ignored during normal game scanning.
|
||||
- A backport is applied automatically to the matching mounted game from any configured scan path.
|
||||
- If multiple scan paths provide the same title backport, the game's own scan path wins; otherwise scan path order is used.
|
||||
- If `/mnt/sandbox/<TITLE_ID>_XXX/app0/fakelib` exists while the game is running, ShadowMount+ mounts it into that game's sandbox `common/lib`.
|
||||
- If `/mnt/sandbox/<TITLE_ID>_XXX/app0/fakelib2` exists while the game is running, ShadowMount+ mounts it into that game's sandbox `common/lib`; otherwise it falls back to `app0/fakelib`.
|
||||
- If `global_fakelib=1` and `global_fakelib_path` exists as a directory, ShadowMount+ also mounts that folder into the same sandbox `common/lib`.
|
||||
- When both global and per-game fakelib exist, the default gives the game's own `fakelib` priority by mounting `/data/shadowmount/fakelib` first and then the game-specific fakelib.
|
||||
- `global_fakelib_priority=global` reverses that priority.
|
||||
@@ -209,7 +207,7 @@ mkpfs pack folder --verify --no-compress --no-adjust-output-file-extension --ver
|
||||
'./pfs_image.dat'
|
||||
```
|
||||
|
||||
Then pack the nested image into a compressed PFS container:
|
||||
Then pack the nested image (**pfs_image.dat**) into a compressed PFS container:
|
||||
|
||||
```bash
|
||||
mkpfs pack file --verify --version PS5 --inode-bits 32 \
|
||||
|
||||
+1
-13
@@ -45,18 +45,6 @@
|
||||
# Default: 1
|
||||
# scan_depth=1
|
||||
|
||||
# Directory watcher granularity:
|
||||
# 1 -> keep vnode watchers on scan root subdirectories
|
||||
# 0 -> watch only scan roots/parents and rely on targeted/full scans for children
|
||||
# Default: 0
|
||||
# watch_subdirs=0
|
||||
|
||||
# Image file watcher granularity:
|
||||
# 1 -> keep vnode watchers on discovered image files
|
||||
# 0 -> detect image file changes through targeted/full scans
|
||||
# Default: 1
|
||||
# watch_image_files=1
|
||||
|
||||
# Legacy compatibility:
|
||||
# recursive_scan=1 forces scan_depth=2
|
||||
# Default: disabled
|
||||
@@ -79,7 +67,7 @@
|
||||
# ufs_backend=lvd
|
||||
|
||||
# Sandbox fakelib backport watcher:
|
||||
# 1/true/yes/on -> mount /mnt/sandbox/<TITLE_ID>_XXX/app0/fakelib into common/lib
|
||||
# 1/true/yes/on -> mount app0/fakelib2 when present, otherwise app0/fakelib, into common/lib
|
||||
# 0/false/no/off -> disable fakelib watcher
|
||||
# Default: 1
|
||||
# backport_fakelib=1
|
||||
|
||||
@@ -116,8 +116,6 @@ typedef struct runtime_config {
|
||||
bool kstuff_game_auto_toggle;
|
||||
bool kstuff_crash_detection_enabled;
|
||||
bool legacy_recursive_scan_forced;
|
||||
bool watch_subdirs;
|
||||
bool watch_image_files;
|
||||
char global_fakelib_path[MAX_PATH];
|
||||
uint32_t global_fakelib_exclude_title_count;
|
||||
char global_fakelib_exclude_title_ids[MAX_FAKELIB_EXCLUDE_RULES][MAX_TITLE_ID];
|
||||
|
||||
@@ -257,8 +257,6 @@ static void init_runtime_config_defaults(runtime_config_state_t *state) {
|
||||
state->cfg.kstuff_game_auto_toggle = true;
|
||||
state->cfg.kstuff_crash_detection_enabled = true;
|
||||
state->cfg.legacy_recursive_scan_forced = false;
|
||||
state->cfg.watch_subdirs = false;
|
||||
state->cfg.watch_image_files = true;
|
||||
(void)strlcpy(state->cfg.global_fakelib_path, DEFAULT_GLOBAL_FAKELIB_PATH,
|
||||
sizeof(state->cfg.global_fakelib_path));
|
||||
state->cfg.scan_depth = DEFAULT_SCAN_DEPTH;
|
||||
@@ -1243,24 +1241,6 @@ static config_load_status_t load_runtime_config_state(runtime_config_state_t *st
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcasecmp(key, "watch_subdirs") == 0) {
|
||||
if (!parse_bool_ini(value, &bval)) {
|
||||
log_debug(" [CFG] invalid bool at line %d: %s=%s", line_no, key, value);
|
||||
continue;
|
||||
}
|
||||
state->cfg.watch_subdirs = bval;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcasecmp(key, "watch_image_files") == 0) {
|
||||
if (!parse_bool_ini(value, &bval)) {
|
||||
log_debug(" [CFG] invalid bool at line %d: %s=%s", line_no, key, value);
|
||||
continue;
|
||||
}
|
||||
state->cfg.watch_image_files = bval;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcasecmp(key, "backport_fakelib") == 0) {
|
||||
if (!parse_bool_ini(value, &bval)) {
|
||||
log_debug(" [CFG] invalid bool at line %d: %s=%s", line_no, key, value);
|
||||
@@ -1508,7 +1488,6 @@ static config_load_status_t load_runtime_config_state(runtime_config_state_t *st
|
||||
"legacy_recursive_scan_forced=%d backport_fakelib=%d "
|
||||
"global_fakelib=%d global_fakelib_priority=%s "
|
||||
"global_fakelib_path=%s global_fakelib_exclude=%u "
|
||||
"watch_subdirs=%d watch_image_files=%d "
|
||||
"kstuff_game_auto_toggle=%d kstuff_crash_detection=%d "
|
||||
"kstuff_pause_delay_image_s=%u kstuff_pause_delay_direct_s=%u "
|
||||
"exfat_backend=%s ufs_backend=%s "
|
||||
@@ -1526,8 +1505,6 @@ static config_load_status_t load_runtime_config_state(runtime_config_state_t *st
|
||||
state->cfg.global_fakelib_mount_first ? "game" : "global",
|
||||
state->cfg.global_fakelib_path,
|
||||
state->cfg.global_fakelib_exclude_title_count,
|
||||
state->cfg.watch_subdirs ? 1 : 0,
|
||||
state->cfg.watch_image_files ? 1 : 0,
|
||||
state->cfg.kstuff_game_auto_toggle ? 1 : 0,
|
||||
state->cfg.kstuff_crash_detection_enabled ? 1 : 0,
|
||||
state->cfg.kstuff_pause_delay_image_seconds,
|
||||
|
||||
+8
-2
@@ -125,11 +125,17 @@ static bool resolve_sandbox_context(const char *title_id,
|
||||
return false;
|
||||
|
||||
char source_path[MAX_PATH];
|
||||
snprintf(source_path, sizeof(source_path), "/mnt/sandbox/%s/app0/fakelib",
|
||||
snprintf(source_path, sizeof(source_path), "/mnt/sandbox/%s/app0/fakelib2",
|
||||
sandbox_id);
|
||||
struct stat st;
|
||||
if (stat(source_path, &st) == 0 && S_ISDIR(st.st_mode))
|
||||
if (stat(source_path, &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||
(void)strlcpy(game_source_path, source_path, MAX_PATH);
|
||||
} else {
|
||||
snprintf(source_path, sizeof(source_path), "/mnt/sandbox/%s/app0/fakelib",
|
||||
sandbox_id);
|
||||
if (stat(source_path, &st) == 0 && S_ISDIR(st.st_mode))
|
||||
(void)strlcpy(game_source_path, source_path, MAX_PATH);
|
||||
}
|
||||
|
||||
char sandbox_root[MAX_PATH];
|
||||
snprintf(sandbox_root, sizeof(sandbox_root), "/mnt/sandbox/%s", sandbox_id);
|
||||
|
||||
@@ -78,7 +78,9 @@ static bool consume_active_game_title(pid_t pid,
|
||||
}
|
||||
|
||||
static bool is_supported_title_id(const char *title_id) {
|
||||
return strncmp(title_id, "PPSA", 4) == 0 || strncmp(title_id, "CUSA", 4) == 0;
|
||||
return strncmp(title_id, "PPSA", 4) == 0 ||
|
||||
strncmp(title_id, "CUSA", 4) == 0 ||
|
||||
strncmp(title_id, "FAKE", 4) == 0;
|
||||
}
|
||||
|
||||
static uint64_t min_nonzero_u64(uint64_t a, uint64_t b) {
|
||||
|
||||
+20
-43
@@ -240,12 +240,7 @@ static bool fakelib_runtime_config_changed(const runtime_config_t *old_cfg,
|
||||
static uint32_t scanner_config_topology_hash(void) {
|
||||
uint32_t hash = 2166136261u;
|
||||
int scan_path_count = get_scan_path_count();
|
||||
uint32_t values[] = {
|
||||
runtime_config()->scan_depth,
|
||||
runtime_config()->watch_subdirs ? 1u : 0u,
|
||||
runtime_config()->watch_image_files ? 1u : 0u,
|
||||
(uint32_t)scan_path_count,
|
||||
};
|
||||
uint32_t values[] = {runtime_config()->scan_depth, (uint32_t)scan_path_count};
|
||||
|
||||
for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
|
||||
for (unsigned shift = 0; shift < 32u; shift += 8u) {
|
||||
@@ -589,7 +584,6 @@ static bool resolve_watch_tree_rebuild_target(const scanner_watch_entry_t *entry
|
||||
typedef struct {
|
||||
int kq;
|
||||
int scan_root_index;
|
||||
bool watch_subdirs;
|
||||
} register_watch_tree_ctx_t;
|
||||
|
||||
static sm_scan_tree_dir_visit_t register_watch_directory_visit(
|
||||
@@ -598,11 +592,9 @@ static sm_scan_tree_dir_visit_t register_watch_directory_visit(
|
||||
scanner_watch_kind_t kind =
|
||||
(depth_from_root == 0u) ? SCANNER_WATCH_SCAN_ROOT
|
||||
: SCANNER_WATCH_SCAN_SUBDIR;
|
||||
if (depth_from_root == 0u || ctx->watch_subdirs) {
|
||||
if (!register_scanner_watch_entry(ctx->kq, ctx->scan_root_index, dir_path,
|
||||
kind, (uint8_t)depth_from_root)) {
|
||||
return SM_SCAN_TREE_DIR_ABORT;
|
||||
}
|
||||
if (!register_scanner_watch_entry(ctx->kq, ctx->scan_root_index, dir_path, kind,
|
||||
(uint8_t)depth_from_root)) {
|
||||
return SM_SCAN_TREE_DIR_ABORT;
|
||||
}
|
||||
|
||||
return SM_SCAN_TREE_DIR_DESCEND;
|
||||
@@ -645,28 +637,19 @@ static bool rebuild_scan_root_watch_tree(int kq, int scan_root_index) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const runtime_config_t *cfg = runtime_config();
|
||||
if (!cfg->watch_subdirs && !cfg->watch_image_files) {
|
||||
if (!register_scanner_watch_entry(kq, scan_root_index, scan_root,
|
||||
SCANNER_WATCH_SCAN_ROOT, 0u)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
unsigned int scan_depth = get_scan_depth_for_root(scan_root);
|
||||
register_watch_tree_ctx_t walk_ctx = {
|
||||
.kq = kq,
|
||||
.scan_root_index = scan_root_index,
|
||||
.watch_subdirs = cfg->watch_subdirs,
|
||||
};
|
||||
sm_scan_tree_callbacks_t callbacks = {
|
||||
.on_directory = register_watch_directory_visit,
|
||||
.on_image_file =
|
||||
cfg->watch_image_files ? register_watch_image_visit : NULL,
|
||||
};
|
||||
if (!sm_scan_tree_walk(scan_root, scan_root, 0u, scan_depth, &callbacks,
|
||||
&walk_ctx)) {
|
||||
return false;
|
||||
}
|
||||
unsigned int scan_depth = get_scan_depth_for_root(scan_root);
|
||||
|
||||
register_watch_tree_ctx_t walk_ctx = {
|
||||
.kq = kq,
|
||||
.scan_root_index = scan_root_index,
|
||||
};
|
||||
sm_scan_tree_callbacks_t callbacks = {
|
||||
.on_directory = register_watch_directory_visit,
|
||||
.on_image_file = register_watch_image_visit,
|
||||
};
|
||||
if (!sm_scan_tree_walk(scan_root, scan_root, 0u, scan_depth, &callbacks,
|
||||
&walk_ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char backport_root[MAX_PATH];
|
||||
@@ -707,15 +690,10 @@ static bool rebuild_scan_root_watch_subtree(int kq, int scan_root_index,
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int scan_depth = get_scan_depth_for_root(scan_root);
|
||||
|
||||
if (!remove_scan_root_watch_entries_for_path(scan_root_index, rebuild_path))
|
||||
return false;
|
||||
const runtime_config_t *cfg = runtime_config();
|
||||
if (!cfg->watch_subdirs && !cfg->watch_image_files) {
|
||||
clear_scan_root_watch_tree_state(scan_root_index);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int scan_depth = get_scan_depth_for_root(scan_root);
|
||||
if (rebuild_depth > scan_depth) {
|
||||
clear_scan_root_watch_tree_state(scan_root_index);
|
||||
return true;
|
||||
@@ -724,11 +702,10 @@ static bool rebuild_scan_root_watch_subtree(int kq, int scan_root_index,
|
||||
register_watch_tree_ctx_t walk_ctx = {
|
||||
.kq = kq,
|
||||
.scan_root_index = scan_root_index,
|
||||
.watch_subdirs = cfg->watch_subdirs,
|
||||
};
|
||||
sm_scan_tree_callbacks_t callbacks = {
|
||||
.on_directory = register_watch_directory_visit,
|
||||
.on_image_file = cfg->watch_image_files ? register_watch_image_visit : NULL,
|
||||
.on_image_file = register_watch_image_visit,
|
||||
};
|
||||
if (!sm_scan_tree_walk(scan_root, rebuild_path, rebuild_depth,
|
||||
scan_depth - rebuild_depth, &callbacks, &walk_ctx)) {
|
||||
|
||||
Reference in new issue
Block a user