<# .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)."