diff --git a/README.md b/README.md index eb5fc54..755dcbc 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ served by the RomM stack (`roms.ginnoir.com`) — deployed from `homelabstack` | `scripts/romhack-apply.py` | Apply a single IPS/BPS/UPS patch to a base ROM with checksum verification. | | `scripts/romhack-pc-migrate.py` | Place the PC/Windows fan-games (RPG-Maker/Essentials) from the scrape staging tree into RomM's `windows` platform so RomM catalogs + serves them like the console hacks. Dry-run default; `--apply` copies, repackaging `.rar`→`.zip`. Runs on valhalla. | | `scripts/launch-pc-hack.ps1` | Playnite custom-emulator launcher for the PC hacks: finds `Game.exe` in the RomM-downloaded folder, sets CWD, runs it. Runs on the Windows client. | +| `scripts/setup-playnite-pc-hack.ps1` | One-shot Playnite setup: registers the custom emulator + RomM `pc_windows` mapping (AutoExtract, download dir). Playnite must be closed. | | `scripts/build-vault-mocs.py` | Regenerate the vault's static MOC tables + header counts (Index/Platforms/Bases) from the notes. Read-only on `Hacks/*.md`. Re-run after any note change. | | `scripts/scrape_match.py` | Match the Discord-scrape `metadata.json` entries to vault notes → `.scrape/_match_report.json` (curated-overlap / discord-match / unmatched). | | `scripts/enrich_vault.py` | Synthesize the scrape into notes: `backfill` (frontmatter for imports), `merge` (scrape into curated), `create` (new notes), `rebuild` (normalize import bodies). `--apply` writes; default dry-runs to `.scrape/_preview/`. | diff --git a/scripts/setup-playnite-pc-hack.ps1 b/scripts/setup-playnite-pc-hack.ps1 new file mode 100644 index 0000000..63f6ff2 --- /dev/null +++ b/scripts/setup-playnite-pc-hack.ps1 @@ -0,0 +1,127 @@ +<# +.SYNOPSIS + Configure Playnite + RomM plugin for Pokémon PC hacks (windows / pc_windows). + + Playnite must be fully closed before running. +#> +$ErrorActionPreference = 'Stop' + +$PlayniteDir = Join-Path $env:LOCALAPPDATA 'Playnite' +$LiteDbDll = Join-Path $PlayniteDir 'LiteDB.dll' +$EmuDb = Join-Path $PlayniteDir 'library\emulators.db' +$RommConfig = Join-Path $PlayniteDir 'ExtensionsData\9700aa21-447d-41b4-a989-acd38f407d9f\config.json' +$Launcher = 'C:\Users\MattC\Documents\pokemon\scripts\launch-pc-hack.ps1' +$DestPath = 'C:\Users\MattC\roms\windows' +$EmuName = 'Pokemon PC Hack Launcher' +$PlatformSpec = 'pc_windows' +$ProfileName = 'Default' +$ProfileId = [guid]::NewGuid().ToString() + +if (Get-Process -Name 'Playnite*' -ErrorAction SilentlyContinue) { + throw 'Close Playnite completely, then re-run this script.' +} +foreach ($p in @($LiteDbDll, $Launcher, $RommConfig)) { + if (-not (Test-Path $p)) { throw "Missing: $p" } +} + +$pwshCmd = Get-Command pwsh -ErrorAction SilentlyContinue +if ($pwshCmd) { $pwsh = $pwshCmd.Source } else { $pwsh = (Get-Command powershell).Source } + +Add-Type -Path $LiteDbDll + +$installDir = Split-Path -Parent $Launcher +$arguments = "-ExecutionPolicy Bypass -File `"$Launcher`" `"{ImagePath}`"" + +function New-BsonArray([object[]]$items) { + $list = New-Object 'System.Collections.Generic.List[LiteDB.BsonValue]' + foreach ($item in $items) { + if ($item -is [LiteDB.BsonDocument]) { $list.Add($item) } + elseif ($item -is [LiteDB.BsonValue]) { $list.Add($item) } + else { $list.Add([LiteDB.BsonValue]$item) } + } + return [LiteDB.BsonArray]::new($list) +} + +$profileDoc = [LiteDB.BsonDocument]::new() +$profileDoc['_id'] = [LiteDB.BsonValue][guid]::Parse($ProfileId) +$profileDoc['Name'] = $ProfileName +$profileDoc['Platforms'] = New-BsonArray @($PlatformSpec) +$profileDoc['ImageExtensions'] = New-BsonArray @('zip') +$profileDoc['Executable'] = $pwsh +$profileDoc['Arguments'] = $arguments +$profileDoc['WorkingDirectory'] = '{InstallDir}' +$profileDoc['UseShellExecute'] = $false +$profileDoc['OverrideDefaultArgs'] = $false +$profileDoc['ScriptStartup'] = $false +$profileDoc['ScriptGameImport'] = $false +$profileDoc['TrackingMode'] = 0 +$profileDoc['TrackingPath'] = $null + +$db = [LiteDB.LiteDatabase]::new("Filename=$EmuDb") +try { + $col = $db.GetCollection('Emulator') + $existing = $col.FindOne([LiteDB.Query]::EQ('Name', $EmuName)) + if ($existing) { + $emuDoc = $existing + $emuId = $existing['_id'].AsGuid.ToString() + if ($emuId -eq '00000000-0000-0000-0000-000000000000') { + $emuId = $existing['_id'].AsString + } + $profiles = $emuDoc['CustomProfiles'].AsArray + if ($profiles.Count -gt 0) { + $p0 = $profiles[0] + if ($p0['_id'].IsGuid) { $ProfileId = $p0['_id'].AsGuid.ToString() } + else { $ProfileId = $p0['_id'].AsString } + $profileDoc['_id'] = [LiteDB.BsonValue][guid]::Parse($ProfileId) + } + Write-Host "Updating existing emulator '$EmuName' ($emuId)" + } else { + $emuId = [guid]::NewGuid().ToString() + $emuDoc = [LiteDB.BsonDocument]::new() + $emuDoc['_id'] = [LiteDB.BsonValue][guid]::Parse($emuId) + $profileDoc['_id'] = [LiteDB.BsonValue][guid]::Parse($ProfileId) + Write-Host "Creating emulator '$EmuName' ($emuId)" + } + + $emuDoc['Name'] = $EmuName + $emuDoc['InstallDir'] = $installDir + $emuDoc['BuiltInConfigId'] = $null + $profilesList = New-Object 'System.Collections.Generic.List[LiteDB.BsonValue]' + $profilesList.Add($profileDoc) + $emuDoc['CustomProfiles'] = [LiteDB.BsonArray]::new($profilesList) + $col.Upsert($emuDoc) | Out-Null +} finally { + $db.Dispose() +} + +$cfg = Get-Content -Raw $RommConfig | ConvertFrom-Json +$mapping = $cfg.Mappings | Where-Object { $_.PlatformId -eq $PlatformSpec } | Select-Object -First 1 +if ($mapping) { + $mapping.EmulatorId = $emuId + $mapping.EmulatorProfileId = $ProfileId + $mapping.DestinationPath = $DestPath + $mapping.AutoExtract = $true + $mapping.Enabled = $true + $mapping.SyncSaves = $false + Write-Host 'Updated RomM mapping for pc_windows.' +} else { + $cfg.Mappings += [pscustomobject]@{ + MappingId = [guid]::NewGuid() + Enabled = $true + AutoExtract = $true + UseM3u = $false + SyncSaves = $false + SaveStrategy = 0 + SaveDirOverride = $null + EmulatorId = $emuId + EmulatorProfileId = $ProfileId + PlatformId = $PlatformSpec + DestinationPath = $DestPath + } + Write-Host 'Added RomM mapping for pc_windows.' +} + +New-Item -ItemType Directory -Force -Path $DestPath | Out-Null +$cfg | ConvertTo-Json -Depth 8 -Compress | Set-Content -Encoding UTF8 $RommConfig +Write-Host "Playnite configured. ROM download dir: $DestPath" +Write-Host "Open Playnite -> Menu -> Library -> Import RomM library (windows games)."