Overview
What started as a simple PowerShell script to clean up RetroPie ROMs has grown into a full suite of tools for managing retro gaming distributions. The suite now supports multiple distros including Batocera, Retrobat, Recalbox, Lakka, and RetroPie, and covers everything from cleaning and organizing ROM sets to scraping validation, orphaned file cleanup, and full backup and restore of your distro.
The original goal remains the same — the No-Intro 2018 ROM set is massive. The NES alone has about 716 officially licensed games but the No-Intro set contains around 2,748. These scripts reduce that number closer to the officially licensed count by keeping only the games you want, in the language you want, without duplicates or revisions — saving space and making your library easier to browse.
DOWNLOAD THE LATEST VERSION HERE AS OF 5/29/2026!!!
Older archived versions are available below, but upgrading to v6.7 is strongly recommended as it includes significant improvements across all scripts.
What’s Included
The suite consists of seven scripts, each serving a specific purpose in the workflow:
- 1_Clean-NoIntroRoms.ps1 — Cleans No-Intro and Custom ROM sets using per-system filters, keeping only your preferred version of each game. Supports uploading cleaned ROMs directly to your distro over SMB.
- 2_CompareFolderResults.ps1 — Compares two ROM directories to show differences, useful when tweaking filters and comparing results between runs.
- 3_CheckXML.ps1 — Validates scraped metadata in gamelist.xml for EmulationStation-based distros, identifying missing scrape data, duplicate ROMs, duplicate game names, non-games, orphaned ROMs, and orphaned media files.
- 4_UpdateVersion.ps1 — Developer utility that programmatically updates version numbers across all scripts and filters, and appends a changelog entry to readme.txt.
- 5_ConfirmFiltersExist.ps1 — Audits filter files to confirm every game system has a filter before running Script 1.
- 6_RemoveOrphanedFiles.ps1 — Deletes orphaned ROM and media files from your distro that are not referenced in gamelist.xml, complementing the detection in Script 3.
- 7_Backup-RestoreDistros.ps1 — Backs up or restores BIOS files, game library files, media, ROMs, and save states between your distro and a local backup directory. Supports dry run, purge before copy, and per-section enable/disable flags.
Supported Distros
All scripts support one or more of the following retro gaming distributions:
- Batocera
- Retrobat
- Recalbox
- Lakka
- RetroPie
Supported Game Systems (No-Intro 2018)
The suite includes pre-built filters for the No-Intro 2018 ROM set covering the game systems listed below. In addition, a separate Custom ROM set is supported for systems outside the No-Intro set — such as Amstrad CPC, Apple II, Atari 800, ZX Spectrum, MAME, and others — and the filter system is fully open-ended, meaning you can add support for any ROM set you want by creating a filter file for it. If it has ROMs, you can clean it.
No-Intro 2018:
- Atari: 2600, 5200, 7800, Jaguar, Lynx, ST
- Bandai: WonderSwan, WonderSwan Color
- Coleco: ColecoVision
- GCE: Vectrex
- Microsoft: MSX1, MSX2
- NEC: PC Engine / TurboGrafx-16, SuperGrafx
- Nintendo: Family Computer Disk System, Game Boy, Game Boy Advance, Game Boy Color, Nintendo 64, Nintendo 64 DD, NES, SNES, Virtual Boy, Satellaview, Sufami Turbo
- SNK: Neo Geo Pocket, Neo Geo Pocket Color
- Sega: 32X, Game Gear, Master System, Mega Drive / Genesis, SG-1000
- Various: Arcadia 2001, Channelf, ColecoVision, CRVision, Game Master, GP32, Odyssey2, PC Engine, Pico, Pokemon Mini, PV1000, SCV, Supervision, Supra Can, Videopac+, and more
Custom ROM Sets (included by default):
- Amstrad CPC
- Apple II
- Atari 800
- CoCo
- Intellivision
- MAME (mame2003)
- Neo Geo
- ZX Spectrum
- And more — add any system by dropping in a filter file
How ROM Cleaning Works
No-Intro ROMs follow a standardized naming scheme where the game name is followed by descriptors in parentheses:
Battletoads (Europe).zipBattletoads (Japan).zipBattletoads (USA).zipCaptain Skyhawk (USA) (Rev A).zipCaptain Skyhawk (USA).zip
The script identifies unique game base names by splitting on the first parenthesis, then applies per-system filters to select the preferred version. Default filters prefer the USA release and earliest revision. Using the examples above the script keeps Battletoads (USA).zip and Captain Skyhawk (USA).zip. Every aspect of this behavior is customizable via the filter files included for each game system.
Downloads
- Latest v6.7
- Versions 6.1 to 6.7 were iterative development releases from 6.0 to 6.7, they are functional but not production ready, and it’s strongly recommended to use v6.7 instead
- Archived v6.0
- Archived v6.0b
- Archived v5.6
- Archived v5.5
- Archived v5.4
- Archived v5.3
- Archived v5.2
- Archived v5.1
- Archived v5.0
- Archived v4.0
14 comments
4 pings
Skip to comment form
Thank you, you beautiful human!
This worked perfectly and I just had to add a few more systems like Atari Jaguar, ST, etc.
The only small problem is it doesn’t pick duplicates when the US and Europe versions differ slightly with the naming scheme, though the only game I noticed this was for Lilo & Stitch 2 where the US version adds a subtitle. But that’s a small thing.
Author
Good catch! I just checked my Gameboy Advance romset, which has the following ROMs for Lilo & Stitch 2:
Lilo & Stitch 2 – Haemsterviel Havoc (USA).zip
Lilo & Stitch 2 (Europe) (En,Fr,De,Es).zip
The script compares everything to the left of the first left parenthesis. Since the USA title has a subtitle, it’s detecting them as separate titles. In this case, I would add the European title to the exceptions to remove it. I have updated the scripts to included this exception.
Author
Just did a complete rewrite on v5.0 to make the code modular and have customized the filter files for each system to address such issues.
Just a small fix – you use the alias “Sort” in some of the scripts. It’d be better to switch this to the non-alias Sort-Object, since the aliases are removed on the linux implementation of powershell. Took me a minute to find that one, but once fixed, I’m running the first script with no issue. There might be others as well to tweak.
Author
Just did a complete rewrite on v5.0 to make the code modular and replaced “Sort” with “Sort-Object” among the changes
I’m currently combing through the results of the script. I’m compiling the Parent/Clone games that were missed. If submitted, will you update your script with my findings? I should be done in less than a week.
Author
Please feel free to share your results! I will definitely add any improvements/mistakes you find.
#Excellent!! I’ve already completed…Atari – 2600, Atari 5200 (No change), Atari 7800, Atari – Jaguar, Atari – Lynx, Atari – ST, Bandai – WonderSwan, & Bandai – WonderSwan Color!
##The lists are organized into 3 categories. Parent/Clone List, Add Roms, & Remove Roms.
###Parent/Clone List – Indicates which parent rom to keep [+] and which corresponding clones to remove [-] (The Parent/Clone Lists are only applicable to roms that actually need added or removed after running the script.
###Add Roms – Indicates which roms to keep that are not currently kept after running the script.
###Remove Roms – Indicates which roms to remove that are not currently removed after running the script.
?????How would you like me to submit the lists? Currently they are separate .txt files per system.
Author
You can email me your suggestions at sigkill [at] sigkillit.com
Here’s Atari – 7800 as an example (Since it merely had one entry per category)
Programs, Applications, Prototypes, Demos fall into “remove” criteria. That is uniform with your algorithm, correct?
PARENT/CLONE LIST
+ Pete Rose Baseball (USA)
– Baseball (Europe)
ADD ROMS
+ 32 in 1 (Australia)
REMOVE ROMS
– 7800 Monitor Cart (USA) (Program) (Unl)
Author
Generally, yes it does follow that rule to remove ROMs with the default settings. However, you can manually edit the atari7800.ps1 filter if you want to customize it. I do agree that “Baseball (Europe)” is a clone of “Pete Rose Baseball (USA)” and will update that on my filters on the next update. Basically, in atari7800.ps1 in the $romsExceptions array I’ll add:
,”Baseball (Europe).zip” #Alternate Name of ‘Pete Rose Baseball (USA).zip’
On your “ADD ROMS” note for “32 in 1 (Australia)” I do not have that ROM in my original list of ROMs, which is the No-Intro 2018 list. If that ROM is being removed from your ROMs and you want to keep it, on the atari7800.ps1 filter in the $romsDoNotDelete array add that exact ROM name.
On your “REMOVE ROMS” note for “7800 Monitor Cart (USA) (Program) (Unl)” I do not have that ROM in my original list of ROMs, which is the No-Intro 2018 list. If you have that ROM in your original ROMs, you can remove it by modifying the atari7800.ps1 filter and modifying the $romsExceptions array. You can either add the exact ROM name or a portion of the name. For example, you probably would want to add one of the below where the first is an exact match and the later is a more general match:
,”7800 Monitor Cart (USA) (Program) (Unl).zip”
OR
,”(Program)”
I must say, you did a great deal of work for which I say Thank You very Much. I am curious how exactly you removed the Japan games without deleting 1 by 1 or doing a ctrl and select? Please enlighten me as to your method because I would like the knowledge for the future. Thanks so much for all of your hard work, Great Job
Thank you for this, Excellent Work!
By chance do you have any other romsets available? Specifically, I am looking for the following additional romsets:
Neo-Geo
CPS 1, 2, 3
MS-DOS
Scummvm (I think these are the same as ms-dos?)
If you have other romsets, could you post a the link?
Regards,
Brian
Author
No, this was based on the No-Intro set. However, if you have additional ROM sets, you could add them to the scripts as long as the ROMs follow a naming scheme. In this case:
1_Clean-NoIntroRoms.ps1: Add your ROM set to the $global:romNoIntroHashTable & your source ROM files should be in the No-IntroDirName
Next, create a filter file that matches the directory name on Retropie.
If we use “NeoGeo” as an example, add it to the $global:romNoIntroHashTable variable like:
“neogeo” = “NeoGeo”
Then in the filters folder, create a file named “neogeo.ps1”. You would then need to customize that file and you can use one of the other existing filter files as an example.
[…] ← Previous […]
[…] https://sigkillit.com/2019/06/19/clean-no-intro-2018-rom-set/ […]
[…] is intended to be used as the supplement script 2_CompareFolderResults.ps1 to the 1_Clean-NoIntroRoms.ps1 script. This script allows you to compare the files/roms in 2 directories to show the differences […]
[…] intended to be used as the supplemental script (3_CheckXML.ps1) to be used in conjunction with the 1_Clean-NoIntroRoms.ps1 and 2_CompareFolderResults.ps1 scripts. This script allows you check missing scraped data in […]