mirror of
https://github.com/drakmor/ShadowMountPlus.git
synced 2026-10-18 20:59:59 -05:00
Fixing exFAT image builds in Windows
This commit is contained in:
1 parent
eb2a4c1036
commit
1bc6477ea7
2 files changed
+22
-39
No files matched your search
+14
-33
@@ -3,7 +3,7 @@
|
||||
PURPOSE
|
||||
-------
|
||||
Create a RAW image file, mount it via OSFMount as a logical volume,
|
||||
auto-select FAT32/exFAT by image size, and either:
|
||||
format it as exFAT, and either:
|
||||
- format + copy + dismount (default), or
|
||||
- create + mount only for manual steps.
|
||||
|
||||
@@ -45,11 +45,10 @@
|
||||
NOTES
|
||||
-----
|
||||
- This script does NOT auto-elevate. Start PowerShell as Administrator.
|
||||
- FS selection is automatic by image size:
|
||||
* < 4 GB -> FAT32, cluster 65536
|
||||
* >= 4 GB -> exFAT, cluster auto-selected:
|
||||
- large-file sets: 65536
|
||||
- small/mixed-file sets: 32768
|
||||
- Filesystem is always exFAT.
|
||||
- Cluster size is auto-selected:
|
||||
- large-file sets: 65536
|
||||
- small/mixed-file sets: 32768
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
@@ -245,11 +244,9 @@ function Dismount-OsfVolume([string]$osfPath, [string]$mountPoint, [int]$maxAtte
|
||||
return $false
|
||||
}
|
||||
|
||||
function Invoke-FormatVolume([string]$driveLetter, [string]$fileSystem, [int]$clusterSize, [string]$label) {
|
||||
function Invoke-FormatVolume([string]$driveLetter, [int]$clusterSize, [string]$label) {
|
||||
$target = "${driveLetter}:"
|
||||
if ($fileSystem -notin @("FAT32", "exFAT")) {
|
||||
throw "Unsupported file system '$fileSystem'. Expected FAT32 or exFAT."
|
||||
}
|
||||
$fileSystem = "exFAT"
|
||||
$clusterArg = Format-AllocationUnitArg -clusterSize $clusterSize
|
||||
$attempts = @(
|
||||
@{ Name = "$fileSystem quick with requested allocation unit"; Args = @($target, "/FS:$fileSystem", "/A:$clusterArg", "/Q", "/V:$label", "/X", "/Y") }
|
||||
@@ -311,40 +308,23 @@ if (Test-Path $ImagePath) {
|
||||
|
||||
[Int64]$expectedBytes = 0
|
||||
[string]$osfSizeArg = $null
|
||||
[Int64]$FsSwitchThresholdBytes = 4GB
|
||||
[int]$Fat32ClusterSize = 65536
|
||||
[int]$ExfatClusterSize = 65536
|
||||
[int]$ExfatClusterSize = Get-OptimalExfatClusterSize -dir $SourceDir
|
||||
[bool]$sizeProvided = -not [string]::IsNullOrWhiteSpace($Size)
|
||||
[string]$TargetFs = ""
|
||||
[int]$TargetClusterSize = 0
|
||||
[int]$TargetClusterSize = $ExfatClusterSize
|
||||
|
||||
if (-not $sizeProvided) {
|
||||
Write-Host "[Info] Size not provided. Computing an optimal image size from '$SourceDir'..."
|
||||
$fat32Candidate = Get-OptimalImageSizeBytes -dir $SourceDir -clusterBytes $Fat32ClusterSize
|
||||
if ($fat32Candidate -lt $FsSwitchThresholdBytes) {
|
||||
$expectedBytes = $fat32Candidate
|
||||
} else {
|
||||
$ExfatClusterSize = Get-OptimalExfatClusterSize -dir $SourceDir
|
||||
$expectedBytes = Get-OptimalImageSizeBytes -dir $SourceDir -clusterBytes $ExfatClusterSize
|
||||
}
|
||||
$expectedBytes = Get-OptimalImageSizeBytes -dir $SourceDir -clusterBytes $TargetClusterSize
|
||||
$osfSizeArg = "$expectedBytes"
|
||||
} else {
|
||||
$expectedBytes = Parse-SizeToBytes $Size
|
||||
$osfSizeArg = $Size
|
||||
}
|
||||
|
||||
if ($expectedBytes -lt $FsSwitchThresholdBytes) {
|
||||
$TargetFs = "FAT32"
|
||||
$TargetClusterSize = $Fat32ClusterSize
|
||||
} else {
|
||||
$TargetFs = "exFAT"
|
||||
$ExfatClusterSize = Get-OptimalExfatClusterSize -dir $SourceDir
|
||||
$TargetClusterSize = $ExfatClusterSize
|
||||
}
|
||||
if (-not $sizeProvided) {
|
||||
Write-Host "[Info] Computed image size: $(Format-Bytes $expectedBytes) ($expectedBytes bytes)."
|
||||
}
|
||||
Write-Host "[Info] Selected filesystem: $TargetFs (cluster=$TargetClusterSize) for image size $(Format-Bytes $expectedBytes)."
|
||||
Write-Host "[Info] Selected filesystem: exFAT (cluster=$TargetClusterSize) for image size $(Format-Bytes $expectedBytes)."
|
||||
|
||||
$osf = Find-OSFMountCom
|
||||
|
||||
@@ -380,8 +360,8 @@ try {
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "[2/4] Formatting $dest as $TargetFs (cluster=$TargetClusterSize, label='$Label') via format.com ..."
|
||||
Invoke-FormatVolume -driveLetter $DriveLetter -fileSystem $TargetFs -clusterSize $TargetClusterSize -label $Label
|
||||
Write-Host "[2/4] Formatting $dest as exFAT (cluster=$TargetClusterSize, label='$Label') via format.com ..."
|
||||
Invoke-FormatVolume -driveLetter $DriveLetter -clusterSize $TargetClusterSize -label $Label
|
||||
|
||||
if (-not (Test-Path $dest)) { throw "Drive $dest is not accessible after formatting." }
|
||||
|
||||
@@ -390,6 +370,7 @@ try {
|
||||
$SourceDir, $dest,
|
||||
"/E", "/COPY:DAT", "/DCOPY:DAT",
|
||||
"/R:1", "/W:1",
|
||||
"/NFL", "/NDL",
|
||||
"/ETA"
|
||||
)
|
||||
& robocopy.exe @roboArgs
|
||||
|
||||
@@ -17,19 +17,19 @@
|
||||
|
||||
| Extension | Mounted FS | Attach backend | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| `.exfat` | `exfatfs` | `LVD` or `MD` (configurable) | Stable |
|
||||
| `.ffpkg` | `ufs` | `LVD` or `MD` (configurable) | High performance |
|
||||
| `.exfat` | `exfatfs` | `LVD` or `MD` (configurable) | Optimal |
|
||||
| `.ffpkg` | `ufs` | `LVD` or `MD` (configurable) | Legacy |
|
||||
| `.ffpfs` | `pfs` | `LVD` | Experimental |
|
||||
|
||||
Notes:
|
||||
- Backend, read-only mode, and sector size can be configured via `/data/shadowmount/config.ini`.
|
||||
- Debug logging is enabled by default (`debug=1`) and writes to console plus `/data/shadowmount/debug.log` (set `debug=0` to disable).
|
||||
- **On 4.xx firmware, shutting down the console may not work correctly when using image files.**
|
||||
- **exFAT is the preferred image filesystem, including on 4.xx firmware, with no known reboot/shutdown issues in typical use.**
|
||||
|
||||
## Recommended FS choice
|
||||
|
||||
- Prefer **UFS (`.ffpkg`)** for games that work correctly on UFS: it is generally more performant (~1.5-2.5 x exFAT).
|
||||
- Use **exFAT (`.exfat`)** for games that only work from external-disk style layouts, because exFAT is case-insensitive.
|
||||
- Prefer **exFAT (`.exfat`)** in most cases: it is generally more performant, case-insensitive, and does not have reboot/shutdown issues in typical use.
|
||||
- Use **UFS (`.ffpkg`)** only when specifically needed for compatibility with your game/setup.
|
||||
|
||||
## Runtime config (`/data/shadowmount/config.ini`)
|
||||
|
||||
@@ -148,7 +148,9 @@ FreeBSD:
|
||||
|
||||
Windows:
|
||||
- You can create UFS2 images with **UFS2Tool** https://github.com/SvenGDK/UFS2Tool.
|
||||
- Recommended output format for this project is `.ffpkg`.
|
||||
- Example:
|
||||
- `UFS2Tool.exe newfs -O 2 -b 32768 -f 4096 -m 0 -i 262144 -D ./APPXXXX ./PPSA12345.ffpkg`
|
||||
|
||||
|
||||
## Installation and usage
|
||||
|
||||
|
||||
Reference in new issue
Block a user