Skip to content

Instantly share code, notes, and snippets.

@dinhani
Last active October 17, 2024 19:27
Show Gist options
  • Save dinhani/3ce1bf3b47fb3de283f7ba5e35e02dea to your computer and use it in GitHub Desktop.
Save dinhani/3ce1bf3b47fb3de283f7ba5e35e02dea to your computer and use it in GitHub Desktop.
LaunchBox to Playnite data
# ------------------------------------------------------------------------------
# Connect
# ------------------------------------------------------------------------------
# $PlayniteRunspace = Get-Runspace -Name 'PSInteractive'
# $PlayniteApi = $PlayniteRunspace.SessionStateProxy.GetVariable('PlayniteApi')
# D:\codigos\automacoes\jogos\launchbox-to-playnite.ps1
# ------------------------------------------------------------------------------
# Constants
# ------------------------------------------------------------------------------
$LAUNCHBOX_DIR = "C:/_emu/launchbox"
$LAUNCHBOX_IMAGE_CACHE_DIR = "C:/_emu/launchbox/Images/Cache-LB"
$PLAYNITE_IMAGES_DIR = "C:/_emu/playnite/library/files-launchbox"
# ------------------------------------------------------------------------------
# Functions
# ------------------------------------------------------------------------------
# Returns the platform directory name based on the platform name.
function PlatformDir {
param(
[Parameter(Mandatory = $true)]
[string]$PlatformName
)
$dir = $PlatformName.ToLower() -replace '\s+', '-'
switch ($dir) {
"3do-interactive-multiplayer" { return "3do" }
default { return $dir }
}
}
# Returns the image filename based on the game title.
function GameImage {
param(
[Parameter(Mandatory = $true)]
[string]$GameTitle
)
return $GameTitle.Replace("'", "_").Replace(":", "_").Replace("?", "_").Replace("<", "_").Replace(">", "_").Replace(" - ", "_")
}
# Copies a file if source exists and destination does not.
function CopyIfPossible {
param(
[Parameter(Mandatory = $true)]
[string]$Source,
[Parameter(Mandatory = $true)]
[string]$Destination
)
try {
if (-not (Test-Path -LiteralPath $Source)) {
return $false
}
if (Test-Path -LiteralPath $Destination) {
return $false
}
New-Item -ItemType File -Path $Destination -Force | Out-Null
Copy-Item -Path $Source -Destination $Destination -Force
return $true
}
catch {
Write-Error "Error copying file: $_"
return $false
}
}
# ------------------------------------------------------------------------------
# Reference data
# ------------------------------------------------------------------------------
$AGE_RATINGS = @{}
$PlayniteApi.Database.AgeRatings | ForEach-Object { $AGE_RATINGS[$_.Name] = $_ }
$COMPANIES = @{}
$PlayniteApi.Database.Companies | ForEach-Object { $COMPANIES[$_.Name] = $_ }
$EMULATORS = @{}
$PlayniteApi.Database.Emulators | ForEach-Object { $EMULATORS[$_.Name] = $_ }
$EMULATORS_SPECS = @{}
$PlayniteApi.Emulation.Emulators | ForEach-Object { $EMULATORS_SPECS[$_.Name] = $_ }
$FEATURES = @{}
$PlayniteApi.Database.Features | ForEach-Object { $FEATURES[$_.Name] = $_ }
$GAMES = @{}
$PlayniteApi.Database.Games | ForEach-Object { $GAMES[$_.GameId] = $_ }
$GENRES = @{}
$PlayniteApi.Database.Genres | ForEach-Object { $GENRES[$_.Name] = $_ }
$PLATFORMS = @{}
$PlayniteApi.Database.Platforms | ForEach-Object { $PLATFORMS[$_.Name] = $_ }
$PLATFORMS_SPECS = @{}
$PlayniteApi.Emulation.Platforms | ForEach-Object { $PLATFORMS_SPECS[$_.Name] = $_ }
$PLATFORMS_SPECS["Super Nintendo Entertainment System"] = ($PlayniteApi.Emulation.Platforms | Where-Object Id -eq "nintendo_super_nes")[0]
$REGIONS = @{}
$PlayniteApi.Database.Regions | ForEach-Object { $REGIONS[$_.Name] = $_ }
$SERIES = @{}
$PlayniteApi.Database.Series | ForEach-Object { $SERIES[$_.Name] = $_ }
$TAGS = @{}
$PlayniteApi.Database.Tags | ForEach-Object { $TAGS[$_.Name] = $_ }
# ------------------------------------------------------------------------------
# Import Emulators
# ------------------------------------------------------------------------------
[xml]$emulatorsXml = Get-Content "$LAUNCHBOX_DIR/Data/Emulators.xml" -Encoding UTF8
$emulatorsXml.LaunchBox.Emulator | ForEach-Object {
$emulatorXml = $_
Write-Host "Emulator: $($emulatorXml.Title)"
# get emulator
$emulator = $EMULATORS[$emulatorXml.Title]
if ($emulator -eq $null) {
$emulator = New-Object Playnite.SDK.Models.Emulator
$new = $true
}
else {
$new = $false
}
# fill emulator info
$emulator.Name = $emulatorXml.Title
$emulator.InstallDir = [System.IO.Path]::GetDirectoryName($emulatorXml.ApplicationPath)
$emulator.BuiltInConfigId = $EMULATORS_SPECS[$emulator.Name].Id
$emulator.BuiltinProfiles = New-Object System.Collections.Generic.List[Playnite.SDK.Models.BuiltInEmulatorProfile]
$EMULATORS_SPECS[$emulator.Name].Profiles | ForEach-Object {
$refProfile = $_
$emulatorProfile = New-Object Playnite.SDK.Models.BuiltInEmulatorProfile
$emulatorProfile.Name = $refProfile.Name
$emulatorProfile.BuiltInProfileName = $refProfile.Name
$emulator.BuiltinProfiles.Add($emulatorProfile)
}
# save emulator
if ($new) {
$PlayniteApi.Database.Emulators.Add($emulator)
}
else {
$PlayniteApi.Database.Emulators.Update($emulator)
}
$EMULATORS[$emulator.Name] = $PlayniteApi.Database.Emulators.Get($emulator.ID)
}
# ------------------------------------------------------------------------------
# Import Games
# ------------------------------------------------------------------------------
Get-ChildItem "$LAUNCHBOX_DIR/Data/Platforms" | ForEach-Object {
Write-Host "Platform: $($_.FullName)"
[xml]$platformXml = Get-Content $_.FullName -Encoding UTF8
$platformXml.launchbox.Game | Sort-Object -Property Title | ForEach-Object {
$gameXml = $_
# ----------------------------------------------------------------------
# Game
# ----------------------------------------------------------------------
$game = $GAMES[$gameXml.ID]
if ($game -eq $null) {
$game = New-Object Playnite.SDK.Models.Game
$new = $true
}
else {
$new = $false
}
$game.GameId = $gameXml.ID
# ----------------------------------------------------------------------
# Images (disabled because Playnite delete files on game deletion)
# ----------------------------------------------------------------------
# create game images dir for game
$gameImages = "$PLAYNITE_IMAGES_DIR/$($game.GameId)"
New-Item -Path $gameImages -ItemType Directory -Force | Out-Null
$coverSource = Join-Path $LAUNCHBOX_IMAGE_CACHE_DIR ".Boxes-$($game.GameId)-372-745"
$coverTarget = Join-Path $gameImages "cover"
if (CopyIfPossible "$coverSource.jpg" "$coverTarget.jpg") {
$game.CoverImage = "$coverTarget.jpg"
}
elseif (CopyIfPossible "$coverSource.png" "$coverTarget.png") {
$game.CoverImage = "$coverTarget.png"
}
$backgroundSource = Join-Path $LAUNCHBOX_IMAGE_CACHE_DIR ".Screenshots-$($game.GameId)-372-745"
$backgroundTarget = Join-Path $gameImages "background"
if (CopyIfPossible "$backgroundSource.jpg" "$backgroundTarget.jpg") {
$game.BackgroundImage = "$backgroundTarget.jpg"
}
elseif (CopyIfPossible "$backgroundSource.png" "$backgroundTarget.png") {
$game.BackgroundImage = "$backgroundTarget.png"
}
# ----------------------------------------------------------------------
# ROMs
# ----------------------------------------------------------------------
$gamePath = $gameXml.ApplicationPath
$game.Roms = New-Object System.Collections.Generic.List[Playnite.SDK.Models.GameRom]
$rom = New-Object Playnite.SDK.Models.GameRom -ArgumentList $gameXml.Region, $gamePath
$game.Roms.Add($rom)
# ----------------------------------------------------------------------
# Links
# ----------------------------------------------------------------------
$game.Links = New-Object System.Collections.Generic.List[Playnite.SDK.Models.Link]
if (-not [string]::IsNullOrEmpty($gameXml.WikipediaURL)) {
$linkWikipedia = New-Object Playnite.SDK.Models.Link -ArgumentList Wikipedia, $gameXml.WikipediaURL
$game.Links.Add($linkWikipedia)
}
if (-not [string]::IsNullOrEmpty($gameXml.VideoUrl)) {
$linkVideo = New-Object Playnite.SDK.Models.Link -ArgumentList Video, $gameXml.VideoUrl
$game.Links.Add($linkVideo)
}
# ----------------------------------------------------------------------
# Platform
# ----------------------------------------------------------------------
$platformName = $gameXml.Platform
if ($PLATFORMS[$platformName] -eq $null) {
Write-Warning "Creating platform: $platformName"
$platform = New-Object Playnite.SDK.Models.Platform
$platform.Id = [System.Guid]::NewGuid()
$platform.Name = $platformName
$platform.SpecificationId = $PLATFORMS_SPECS[$platformName].Id
$PlayniteApi.Database.Platforms.Add($platform)
$PLATFORMS[$platformName] = $PlayniteApi.Database.Platforms.Get($platform.Id)
}
$game.PlatformIds = $PLATFORMS[$platformName].Id
# ----------------------------------------------------------------------
# Release Date
# ----------------------------------------------------------------------
$releaseDate = $gameXml.ReleaseDate
if (-not [string]::IsNullOrEmpty($releaseDate)) {
$game.ReleaseDate = [datetime]::Parse($releaseDate)
}
# ----------------------------------------------------------------------
# Genre
# ----------------------------------------------------------------------
$game.GenreIds = New-Object System.Collections.Generic.List[System.Guid]
$gameXml.Genre -Split "; " | ForEach-Object {
$genreName = $_
if ($genreName -eq "") {
return
}
if ($GENRES[$genreName] -eq $null) {
Write-Warning "Creating genre: $genreName"
$GENRES[$genreName] = $PlayniteApi.Database.Genres.Add($genreName)
}
$game.GenreIds.Add($GENRES[$genreName].Id)
}
# ----------------------------------------------------------------------
# Features
# ----------------------------------------------------------------------
$game.FeatureIds = New-Object System.Collections.Generic.List[System.Guid]
# PlayMode
$gameXml.PlayMode -Split "; " | ForEach-Object {
$playmodeName = $_
if ($playmodeName -eq "") {
return
}
if ($FEATURES[$playmodeName] -eq $null) {
Write-Warning "Creating feature: $playmodeName"
$FEATURES[$playmodeName] = $PlayniteApi.Database.Features.Add($playmodeName)
}
$game.FeatureIds.Add($FEATURES[$playmodeName].Id)
}
# ----------------------------------------------------------------------
# Developer / Publisher
# ----------------------------------------------------------------------
$developerName = $gameXml.Developer
if (-not [string]::IsNullOrEmpty($developerName)) {
if ($COMPANIES[$developerName] -eq $null) {
Write-Warning "Creating developer: $developerName"
$COMPANIES[$developerName] = $PlayniteApi.Database.Companies.Add($developerName)
}
$game.DeveloperIds = $COMPANIES[$developerName].Id
}
$publisherName = $gameXml.Publisher
if (-not [string]::IsNullOrEmpty($publisherName)) {
if ($COMPANIES[$publisherName] -eq $null) {
Write-Warning "Creating publisher: $publisherName"
$COMPANIES[$publisherName] = $PlayniteApi.Database.Companies.Add($publisherName)
}
$game.PublisherIds = $COMPANIES[$publisherName].Id
}
# ----------------------------------------------------------------------
# Region
# ----------------------------------------------------------------------
$game.RegionIds = New-Object System.Collections.Generic.List[System.Guid]
$gameXml.Region -Split ", " | ForEach-Object {
$regionName = $_
if ($regionName -eq "") {
return
}
if ($REGIONS[$regionName] -eq $null) {
Write-Warning "Creating region: $regionName"
$REGIONS[$regionName] = $PlayniteApi.Database.Regions.Add($regionName)
}
$game.RegionIds.Add($REGIONS[$regionName].Id)
}
# ----------------------------------------------------------------------
# Age Rating
# ----------------------------------------------------------------------
$ageRatingName = $gameXml.Rating
if (-not [string]::IsNullOrEmpty($ageRatingName)) {
if ($AGE_RATINGS[$ageRatingName] -eq $null) {
Write-Warning "Creating age rating: $ageRatingName"
$AGE_RATINGS[$ageRatingName] = $PlayniteApi.Database.AgeRatings.Add($ageRatingName)
}
$game.AgeRatingIds = $AGE_RATINGS[$ageRatingName].Id
}
# ----------------------------------------------------------------------
# Series
# ----------------------------------------------------------------------
$seriesName = $gameXml.Series
if (-not [string]::IsNullOrEmpty($seriesName)) {
if ($SERIES[$seriesName] -eq $null) {
Write-Warning "Creating series: $seriesName"
$SERIES[$seriesName] = $PlayniteApi.Database.Series.Add($seriesName)
}
$game.SeriesIds = $SERIES[$seriesName].Id
}
# ----------------------------------------------------------------------
# Actions
# ----------------------------------------------------------------------
$game.GameActions = New-Object System.Collections.Generic.List[Playnite.SDK.Models.GameAction]
$action = New-Object Playnite.SDK.Models.GameAction
$action.Name = "Play"
$action.IsPlayAction = $true
$action.Type = "Emulator"
$game.GameActions = $action
# ----------------------------------------------------------------------
# Basic Info
# ----------------------------------------------------------------------
$game.Name = $gameXml.Title
$game.Description = $gameXml.Notes
$game.IsInstalled = $platformName -ne "Windows"
$game.InstallDirectory = [System.IO.Path]::GetDirectoryName($gamePath)
$game.InstallSize = $(Get-ChildItem $gamePath).Length
$game.CommunityScore = 10 * [double]::Parse($gameXml.CommunityStarRating, [System.Globalization.CultureInfo]::InvariantCulture)
# ----------------------------------------------------------------------
# Save
# ----------------------------------------------------------------------
if ($new) {
$PlayniteApi.Database.Games.Add($game)
}
else {
$PlayniteApi.Database.Games.Update($game)
}
$GAMES[$game.GameId] = $PlayniteApi.Database.Games.Get($game.GameID)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment