Skip to content

Instantly share code, notes, and snippets.

@milnak
Last active November 22, 2023 18:19
Show Gist options
  • Save milnak/deb3f4e81b40c5489dda2feb88a58972 to your computer and use it in GitHub Desktop.
Save milnak/deb3f4e81b40c5489dda2feb88a58972 to your computer and use it in GitHub Desktop.
PinHP Rom Organizer #pinhp
# Place this file in root of USB, i.e. parent of the "rpi2jamma" folder.
# Prerequisite:
# category.ini and version.ini from https://www.progettosnaps.net/index.php
# Place these files into "folders" folder off USB root.
# When run, this will:
# 1. Move unsupported ROMS to "roms_unused"
# 2. Organize roms into folders under "roms_advmame"
# 3. Add a ".title" file in each rom folder, describing the content.
# 4. Ensure that all extras (button, marquee, etc.) exist for each ROM file.
# 5. Check that custom_folders=Y is set in "config.ini" file.
function Create-LegalFilename {
Param(
[Parameter(Mandatory)][string]$Filename
)
# This won't work, as characters need regex escaping.
# $group = '[{0}]' -f [System.IO.Path]::GetInvalidFileNameChars() -join ''
$group = '['
foreach ($c in [IO.Path]::GetInvalidFileNameChars()) {
$group += [regex]::escape($c)
}
$group += ']'
$Filename -replace $group, '-'
}
function Read-MameIni {
Param(
[Parameter(Mandatory)][string]$Filename,
[switch]$IsVersion = $False
)
$hash = @{}
$section = $null
Get-Content $Filename -ErrorAction Stop | ForEach-Object {
$line = $_.ToString()
# '[' indicates a section marker
if ($line.length -ge 3 -and $line.Substring(0, 1) -eq '[') {
if ($line -eq '[FOLDER_SETTINGS]') {
$section = $null
}
else {
if ($IsVersion) {
if ($line -ne '[ROOT_FOLDER]') {
# versions can include 'a', 'b', 'u', 'rc', e.g. '0.106u1' or b, e.g. '0.34b5'
$line = ($line -split 'a' -split 'b' -split 'u' -split 'r' -split ']')[0]
$section = [Version]$line.Substring(1)
}
}
else {
$section = $line.Substring(1, $line.Length - 2)
}
}
}
elseif ($section -and $line -match '^[a-z0-9]') {
# Return as a hash rather than a PSCustomObject as hash lookup is much faster.
# [PSCustomObject]@{ rom=$line; value=$section }
$hash[$line] = $section
}
}
$hash
}
function Move-UnsupportedRoms {
Param(
[Parameter(Mandatory)][string]$Folder,
[Parameter(Mandatory)][string]$BackupFolder
)
if (-not (Test-Path $BackupFolder -PathType Container)) {
New-Item -ItemType Directory -Name $BackupFolder -ErrorAction Stop | Out-Null
}
# map of romname to version where rom was introduced.
$version = Read-MameIni -Filename 'folders\version.ini' -IsVersion
# AdvanceMAME 1.4 Reference Collection (Complete MAME 0.106)
$supportedRoms = $version | Where-Object value -le '0.106'
Get-ChildItem $Folder -Recurse -Filter '*.zip' | ForEach-Object {
$romName = $_.BaseName
if (-not ($supportedRoms.ContainsKey($romName))) {
# ROM not supported in this MAME version, move to backup folder.
'Unsupported ROM: {0}' -f $romName
Move-Item -LiteralPath $_.FullName -Destination $BackupFolder -ErrorAction Stop -Force
}
}
}
function Categorize-Roms {
Param(
[Parameter(Mandatory)][string]$Folder,
[Parameter(Mandatory)][string]$BackupFolder
)
# map of romname to category description, e.g. 'Casino / Cards'
$categories = Read-MameIni -Filename 'folders\category.ini'
Get-ChildItem $Folder -Recurse -Filter '*.zip' | ForEach-Object {
$romName = $_.BaseName
$category = $categories[$romName]
if (-not $category) {
# Can't find category, move to backup folder.
'Unknown category: {0}' -f $romName
Move-Item -LiteralPath $_.FullName -Destination $BackupFolder -ErrorAction Stop -Force
}
else {
# pinHP crashes if a folder contains an '&'
$category = $category -replace '&', '-'
$split = ($category -split '/').Trim()
if ($split.Length -eq 2) {
# For some categories, use the primary.
if ($split[0] -in @('Driving', 'Fighter', 'Maze', 'Shooter', 'Sports', 'System')) {
$category = $split[0]
}
else {
$category = $split[1]
}
}
else {
$category = $split[0]
}
if ($category -eq 'System') {
# 'System' is a BIOS. Move it to the backup folder.
'System file: {0}' -f $romName
$targetFolder = $BackupFolder
}
else {
$targetFolder = Join-Path $Folder (Create-LegalFilename -Filename $category)
if (-not (Test-Path $targetFolder -PathType Container)) {
New-Item -ItemType Directory -Name $targetFolder -ErrorAction Stop | Out-Null
# Each folder needs a '.title' file containing folder description.
$category | Out-File -Encoding ascii -FilePath (Join-Path $targetFolder '.title')
}
}
Move-Item -LiteralPath $_.FullName -Destination $targetFolder -ErrorAction Stop -Force
}
}
}
function Cleanup-Folders {
Param(
[Parameter(Mandatory)][string]$Folder
)
# Find empty folders or folders with only a '.title' file in it, and remove the folder.
Get-ChildItem -LiteralPath $Folder -Directory | ForEach-Object {
$files = Get-ChildItem -LiteralPath $_.FullName
if ($files.Count -eq 0 -or ($files.Count -eq 1 -and $files[0].Name -eq '.title')) {
Remove-Item -LiteralPath $_.FullName -Recurse -Force
}
}
}
# Look for any "extras" (marquee, button, etc.) that are missing for a rom.
function Check-Extras {
Param(
[Parameter(Mandatory)][string]$Folder
)
$buttons = Get-ChildItem (Join-Path $Folder 'buttons') -Filter '*.png' | Select-Object -ExpandProperty BaseName
$logos = Get-ChildItem (Join-Path $Folder 'logos') -Filter '*.png' | Select-Object -ExpandProperty BaseName
$marquees = Get-ChildItem (Join-Path $Folder 'marquees') -Filter '*.png' | Select-Object -ExpandProperty BaseName
$snaps = Get-ChildItem (Join-Path $Folder 'snaps') -Filter '*.png' | Select-Object -ExpandProperty BaseName
$titles = Get-ChildItem (Join-Path $Folder 'titles') -Filter '*.png' | Select-Object -ExpandProperty BaseName
$videos = Get-ChildItem (Join-Path $Folder 'videos') -Filter '*.mp4' | Select-Object -ExpandProperty BaseName
Get-ChildItem (Join-Path $Folder 'roms_advmame') -Recurse -Filter '*.zip' | Select-Object BaseName | Sort-Object BaseName | ForEach-Object {
$romName = $_.BaseName
$missing = $null
if (-not ($buttons -contains $romName)) { $missing += 'button ' }
if (-not ($logos -contains $romName)) { $missing += 'logo ' }
if (-not ($marquees -contains $romName)) { $missing += 'marquee ' }
if (-not ($snaps -contains $romName)) { $missing += 'snap ' }
if (-not ($titles -contains $romName)) { $missing += 'title ' }
if (-not ($videos -contains $romName)) { $missing += 'video ' }
if ($missing) {
'{0}: {1}' -f $romName, $missing
}
}
}
# Ensure custom_folders=Y in config.ini
function Check-CustomFolders {
Param(
[Parameter(Mandatory)][string]$Folder
)
$configPath = (Join-Path $Folder 'config.ini')
$data = Get-Content $configPath `
| Select-String 'custom_folders' `
| ConvertFrom-StringData
if ($data['custom_folders'] -ne 'Y') {
Write-Warning ('Set custom_folders=Y in {0}' -f $configPath)
}
}
#
# main
#
if (-not (Test-Path './rpi2jamma' -PathType Container)) {
Write-Warning 'rpi2jamma folder not found'
Exit
}
Move-UnsupportedRoms -Folder 'rpi2jamma\roms_advmame' -BackupFolder 'rpi2jamma\roms_unused'
Categorize-Roms -Folder 'rpi2jamma\roms_advmame' -BackupFolder 'rpi2jamma\roms_unused'
Cleanup-Folders -Folder 'rpi2jamma\roms_advmame'
Check-Extras -Folder 'rpi2jamma'
Check-CustomFolders -Folder 'rpi2jamma'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment