Jun 19

Clean No-Intro 2018 ROM Set

Overview

I did not want my RetroPie to be cluttered with ROMs I did not want. I only wanted the original games, I did not want duplicates or revisions, and I only wanted games in English so I could read the on screen text. For example, the NES has about 716 officially licensed games and the No-Intro 2018 ROM set has about 2,748 games in it. I wanted to reduce that number down closer to the officially licensed games count to save space on my MicroSD card and reduce the amount of ROMs I would have to scroll through each time. I decided to create the below powershell scripts based on the No-Intro 2018 ROM set to accomplish my goal, which I’ll explain each step in detail.

Download all of the scripts below in a zip file:

http://sigkillit.com/wp-content/uploads/2019/08/Clean-NoIntro2018.zip

Phase 1: Determine What ROMs to Keep

The No-Intro 2018 ROM set includes the following game systems that are compatible with RetroPie/Emulationstation:

  • Atari: 2600
  • Atari: 5200
  • Atari: 7800
  • Atari: Lynx
  • Bandai: WonderSwan
  • Bandai: WonderSwan Color
  • Coleco: ColecoVision
  • GCE: Vectrex
  • Microsoft: MSX
  • NEC: PC Engine / TurboGrafx 16
  • Nintendo: Family Computer Disk System
  • Nintendo: Game Boy
  • Nintendo: Game Boy Advance
  • Nintendo: Game Boy Color
  • Nintendo: Nintendo 64
  • Nintendo: Nintendo Entertainment System
  • Nintendo: Super Nintendo Entertainment System
  • Nintendo: Virtual Boy
  • SNK: Neo Geo Pocket
  • SNK: Neo Geo Pocket Color
  • Sega: 32X
  • Sega: Game Gear
  • Sega: Master System / Mark III
  • Sega: Mega Drive / Genesis
  • Sega: SG-1000

The No-Intro ROMs follow a pretty standardized naming scheme such as:

  • Battletoads (Europe).zip
  • Battletoads (Japan).zip
  • Battletoads (USA).zip
  • Captain Skyhawk (Europe).zip
  • Captain Skyhawk (USA) (Rev A).zip
  • Captain Skyhawk (USA).zip

As you can see, the base name of the ROM is followed by detailed descriptions such as the region released, revision, language, etc which is contained in parentheses. The first step is to get a unique list of all of the information contained in the parentheses for each game system so we can determine what we want to keep. In the below script, modify $global:romNoIntroDirectory to point to the root directory of your No-Introl ROMs. The script will then output the unique results by game system as well as a combined list.

Get-NoIntroExceptions.ps1

#Get-NoIntroExceptions.ps1
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\"
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".log")
$global:logOverwrite = $true
$global:romNoIntroHashTable = [ordered]@{
	#RetroPieDirName = No-IntroDirName
	"atari2600" = "Atari - 2600"
	"atari5200"  = "Atari - 5200"
	"atari7800" = "Atari - 7800 [Headered]"
	"atarilynx" = "Atari - Lynx [Headered]"
	"coleco" = "Coleco - ColecoVision"
	"fds" = "Nintendo - Family Computer Disk System [headered]"
	"gamegear" = "Sega - Game Gear"
	"gb" = "Nintendo - Game Boy"
	"gba" = "Nintendo - Game Boy Advance"
	"gbc" = "Nintendo - Game Boy Color"
	"mastersystem" = "Sega - Master System - Mark III"
	"megadrive" = "Sega - Mega Drive - Genesis"
	"msx" = "Microsoft - MSX"
	"n64" = "Nintendo - Nintendo 64"
	"nes" = "Nintendo - Nintendo Entertainment System [headered]"
	"ngp" = "SNK - Neo Geo Pocket"
	"ngpc" = "SNK - Neo Geo Pocket Color"
	"pcengine" = "NEC - PC Engine - TurboGrafx 16"
	"sega32x" = "Sega - 32X"
	"sg-1000" = "Sega - SG-1000"
	"snes" = "Nintendo - Super Nintendo Entertainment System"
	"vectrex" = "GCE - Vectrex"
	"virtualboy" = "Nintendo - Virtual Boy"
	"wonderswan" = "Bandai - WonderSwan"
	"wonderswancolor" = "Bandai - WonderSwan Color"
}



Function Main()
{
	#Use No-Intro Naming Scheme to Build a List of Unique Exception Filters Used to Remove Unwanted ROMs For Each System
	#Examples: (Beta), (Proto),(Japan)
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $false
	}
	Log-Write "Green" $global:logFile ("Name                    : $global:scriptName") $false
	Log-Write "Green" $global:logFile ("No-Intro ROM Dir        : $($global:romNoIntroDirectory)") $false
	Log-Write "Green" $global:logFile ("Log File Exceptions     : $($global:logFile)") $false
	Log-Write "Green" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	Log-Write "Green" $global:logFile ("Use No-Intro Naming Scheme to Build a List of Unique Exception Filters Used to Remove Unwanted ROMs For Each System Ex: (Japan)") $false 
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Get-NoIntroRomExceptions	
}



Function Get-NoIntroRomExceptions()
{		
	#Process Each No-Intro ROM Directory
	$colUniqueRomsAll = @()
	ForEach ($key in $global:romNoIntroHashTable.keys)
	{

		#Process Current ROM Directory
		Log-Write "Green" $global:logFile ("PROCESS: $($global:romNoIntroDirectory)$($global:romNoIntroHashTable[$key])") $false
		Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false		

		#Confirm No-Intro ROM Directory Exists
		If(!(Test-Path -LiteralPath "$($global:romNoIntroDirectory)$($global:romNoIntroHashTable[$key])"))
		{
			#Directory Does Not Exist
			Log-Write "Red" $global:logFile ("ERROR: ROM Directory Does Not Exist!!!") $false
		}
		Else 
		{
			#Directory Exists
			Log-Write "DarkGreen" $global:logFile ("Directory Exists: Continue Processing") $false
			$colRoms = @()
			$colUniqueRoms = @()
			$colRoms = Get-ChildItem -LiteralPath "$($global:romNoIntroDirectory)$($global:romNoIntroHashTable[$key])"
			$colRoms | ForEach-Object `
			{
				$colUniqueRoms += '(' + $_.basename.split("(",2)[1]
			}
			$colUniqueRoms = $colUniqueRoms | Sort -Unique
			$colUniqueRomsAll += $colUniqueRoms
			Log-Write "Green" $global:logFile ("Found $($colUniqueRoms.Count) Potential Exceptions to Filter:") $false
			ForEach ($name in $colUniqueRoms)
			{
				Log-Write "DarkGreen" $global:logFile ("$($name)") $false
			}
		}
		Log-Write "White" $global:logFile ("`n") $false
	}
	Log-Write "Green" $global:logFile ("COMBINED UNIQUE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false	
	$colUniqueRomsAll = $colUniqueRomsAll | Sort -Unique
	ForEach ($name in $colUniqueRomsAll)
	{
		Log-Write "DarkGreen" $global:logFile ("$($name)") $false
	}
}



Function Log-Write
{
	<#
	.SYNOPSIS
	Writes to a log file
	 
	.DESCRIPTION
	Appends a new line to the end of the specified log file
	.PARAMETER LogPath
	Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
	.PARAMETER LineValue
	Mandatory. The string that you want to write to the log
	.INPUTS
	Parameters above
	 
	.OUTPUTS
	None
	 
	.NOTES
	Version: 1.0
	Author: Luca Sturlese
	Creation Date: 10/05/12
	Purpose/Change: Initial function development
	Version: 1.1
	Author: Luca Sturlese
	Creation Date: 19/05/12
	Purpose/Change: Added debug mode support
	 
	.EXAMPLE
	Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
	#>
	[CmdletBinding()]
	Param 
	(
		[Parameter(Mandatory=$false)]
		[string]$ConsoleColor,
		[Parameter(Mandatory=$true)]
		[string]$LogPath,
		[Parameter(Mandatory=$true)]
		[string]$LineValue,
		[Parameter()]
		[bool]$OverwriteFile = $false
	)
	Process
	{
		if(!(Test-Path -Path $LogPath))
		{
			#Create New File If Does Not Exist
			New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
		}
		else
		{
			if($OverwriteFile -eq $true)
			{
				#Overwrite Log File
				Set-Content -Path $LogPath -Value $LineValue
			}
			else
			{
				#Append Log File
				Try {
					Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
				} Catch {
					Start-Sleep -s 3
					Add-Content -Path $LogPath -Value $LineValue
				}
			}
		}
		#Write to screen for debug mode
		#Write-Debug $LineValue
		If ($ConsoleColor)
		{
			Write-Host -ForegroundColor $ConsoleColor $lineValue
		}
		Else 
		{
			Write-Host $lineValue
		}
	}
}


Main

Get-NoIntroExceptions.log

****************************************************************
Name                    : Get-NoIntroExceptions.ps1
No-Intro ROM Dir        : C:\Games\No-Intro 2018\
Log File Exceptions     : Get-NoIntroExceptions.log
Overwrite Log File      : True
Use No-Intro Naming Scheme to Build a List of Unique Exception Filters Used to Remove Unwanted ROMs For Each System Ex: (Japan)
****************************************************************
PROCESS: C:\Games\No-Intro 2018\Atari - 2600
-------------------------------------------------------
Directory Exists: Continue Processing
Found 6 Potential Exceptions to Filter:
(Europe)
(Europe) (Proto)
(USA)
(USA) (Proto)
(USA) (Rev 1)
(USA) (Unl)


PROCESS: C:\Games\No-Intro 2018\Atari - 5200
-------------------------------------------------------
Directory Exists: Continue Processing
Found 9 Potential Exceptions to Filter:
(USA)
(USA) (82-11-05) (Proto)
(USA) (83-10-31) (Proto)
(USA) (Demo)
(USA) (Proto)
(USA) (Unl)
(USA) (v1.02)
(USA) (v2.0)
(USA) (v2.3)


PROCESS: C:\Games\No-Intro 2018\Atari - 7800 [Headered]
-------------------------------------------------------
Directory Exists: Continue Processing
Found 4 Potential Exceptions to Filter:
(Europe)
(Unknown) (Proto)
(USA)
(USA) (Proto)


PROCESS: C:\Games\No-Intro 2018\Atari - Lynx [Headered]
-------------------------------------------------------
Directory Exists: Continue Processing
Found 6 Potential Exceptions to Filter:
(Europe) (Proto)
(USA) (Demo)
(USA) (Proto)
(USA) (v3.0)
(USA, Europe)
(USA, Europe) (Beta)


PROCESS: C:\Games\No-Intro 2018\Coleco - ColecoVision
-------------------------------------------------------
Directory Exists: Continue Processing
Found 13 Potential Exceptions to Filter:
(Europe)
(Europe) (Proto)
(USA)
(USA) (Alt 1)
(USA) (Demo)
(USA) (Proto)
(USA) (Proto) (Unl)
(USA) (Unl)
(USA, Europe)
(USA, Europe) (Adam)
(USA, Europe) (Alt 1)
(USA, Europe) (Beta)
(USA, Europe) (Demo)


PROCESS: C:\Games\No-Intro 2018\Nintendo - Family Computer Disk System [headered]
-------------------------------------------------------
Directory Exists: Continue Processing
Found 40 Potential Exceptions to Filter:
(Japan)
(Japan) (Alt 1) (Unl)
(Japan) (Beta)
(Japan) (Disk 1) (Unl)
(Japan) (Disk 2) (Unl)
(Japan) (Disk Writer)
(Japan) (Disk Writer) [b]
(Japan) (DV 0)
(Japan) (DV 1)
(Japan) (DV 1) [b]
(Japan) (DV 10)
(Japan) (DV 2)
(Japan) (DV 2) (Disk Writer)
(Japan) (DV 2) [b]
(Japan) (DV 4) [b]
(Japan) (DV 5)
(Japan) (DV 5) (Disk Writer)
(Japan) (DV 6) [b]
(Japan) (DV 7)
(Japan) (DV 8) (Disk Writer)
(Japan) (National Tax Agency Demo)
(Japan) (Nintendo Classic Mini Family Computer)
(Japan) (Prize Card)
(Japan) (Promotion Card)
(Japan) (Proto)
(Japan) (Proto) (Dragon Layout)
(Japan) (Proto) (Scorpion Layout)
(Japan) (Proto) [b]
(Japan) (Rev 1)
(Japan) (Rev 1) (Disk Writer)
(Japan) (Rev 1) (Disk Writer) [b]
(Japan) (Rev 1) [b]
(Japan) (Rev 2)
(Japan) (Rev 2) (Developer Card)
(Japan) (Rev 2) (Disk Writer)
(Japan) (Rev 3) [b]
(Japan) (Sample)
(Japan) (Unl)
(Japan) (Unl) [b]
(Japan) [b]


PROCESS: C:\Games\No-Intro 2018\Sega - Game Gear
-------------------------------------------------------
Directory Exists: Continue Processing
Found 45 Potential Exceptions to Filter:
(Europe)
(Europe) (Beta)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv) (Rev 1)
(Europe) (En,Fr,De,Es,Nl,Sv)
(Europe) (Proto)
(Japan)
(Japan) (Development Edition)
(Japan) (En)
(Japan) (En) (Rev 1)
(Japan) (En) (Sample)
(Japan) (En,Fr,De,Es,It,Pt,Sv,No)
(Japan) (En,Ja)
(Japan) (Rev 1)
(Japan, Europe)
(Japan, Europe) (En,Fr,De,Es,It)
(Japan, USA)
(Japan, USA) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Korea) (Unl)
(Unknown) (Proto)
(USA)
(USA) (Auto Demo)
(USA) (Beta)
(USA) (Majesco)
(USA) (Proto 1)
(USA) (Proto 2)
(USA) (Proto)
(USA) (Proto) (Unl)
(USA) (Rev 1)
(USA, Europe)
(USA, Europe) (Beta)
(USA, Europe) (En,Fr,De,Es)
(USA, Europe) (En,Fr,De,Es,It,Nl,Pt,Sv)
(USA, Europe) (En,Fr,De,Es,It,Pt,Sv,No)
(USA, Europe) (Rev 1)
(USA, Europe) (v2.0) (Beta)
(World)
(World) (Auto Demo)
(World) (Beta)
(World) (En,Ja)
(World) (Ja)
(World) (Proto)
(World) (Rev 1)


PROCESS: C:\Games\No-Intro 2018\Nintendo - Game Boy
-------------------------------------------------------
Directory Exists: Continue Processing
Found 114 Potential Exceptions to Filter:
(Australia)
(Australia) (SGB Enhanced)
(Canada)
(China) (DMG-601 CHN)
(China) (DMG-602 CHN)
(China) (DMG-603 CHN)
(China) (DMG-604 CHN)
(China) (DMG-605 CHN)
(DMG-EM) (Europe)
(DMG-EM) (Japan)
(DMG-N5) (USA)
(DMG-N5) (USA) (Rev A)
(Europe)
(Europe) (4B-001, Sachen-Commin) (Unl)
(Europe) (4B-002, Sachen) (Unl)
(Europe) (4B-004, Sachen-Commin) (Unl)
(Europe) (4B-005, Sachen-Commin) (Unl)
(Europe) (4B-006, Sachen) (Unl)
(Europe) (4B-007, Sachen) (Unl)
(Europe) (4B-008, Sachen) (Unl)
(Europe) (4B-009, Sachen) (Unl)
(Europe) (Beta)
(Europe) (Beta) (1993-05-19)
(Europe) (En,Es) (SGB Enhanced)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De) (SGB Enhanced)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es) (Beta) (SGB Enhanced)
(Europe) (En,Fr,De,Es) (SGB Enhanced)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It,Nl)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Sv)
(Europe) (En,Fr,De,It,Nl)
(Europe) (En,Fr,De,Nl)
(Europe) (En,Fr,De,Nl) (SGB Enhanced)
(Europe) (Fr,De)
(Europe) (Fr,De) (SGB Enhanced)
(Europe) (Proto) (Unl)
(Europe) (Rev A)
(Europe) (Rev A) (SGB Enhanced)
(Europe) (SGB Enhanced)
(Europe) (Unl)
(Europe) (v3.6) (GBDSO) (Unl)
(France)
(France) (En,Fr,De,Es)
(France) (GBC,SGB Enhanced)
(France) (SGB Enhanced)
(Germany)
(Germany) (En,Fr,De,Es)
(Germany) (GBC,SGB Enhanced)
(Germany) (SGB Enhanced)
(Germany) (v1.0) (GBD1) (Unl)
(Italy) (GBC,SGB Enhanced)
(Italy) (SGB Enhanced)
(Japan)
(Japan) (Activision)
(Japan) (Beta)
(Japan) (Beta) (SGB Enhanced)
(Japan) (En)
(Japan) (En) (Beta)
(Japan) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Japan) (En,Ja)
(Japan) (HAL Laboratory)
(Japan) (IE Institute)
(Japan) (Imagineer)
(Japan) (Rev 1)
(Japan) (Rev 1) (SGB Enhanced)
(Japan) (Rev 1) (SGB Enhanced) (NP)
(Japan) (Rev 2)
(Japan) (Rev 2) (SGB Enhanced)
(Japan) (Rev 3) (SGB Enhanced)
(Japan) (Rev A)
(Japan) (Rev A) (SGB Enhanced)
(Japan) (Rev AB) (SGB Enhanced)
(Japan) (Sample)
(Japan) (SGB Enhanced)
(Japan, Europe)
(Japan, USA)
(Japan, USA) (SGB Enhanced)
(Reibun de Oboeru) Chuugaku Eitango 1132 (Japan)
(Reibun de Oboeru) Kyuukyoku no Kobun Tango (Japan)
(Spain)
(Spain) (GBC,SGB Enhanced)
(Spain) (SGB Enhanced)
(Sweden)
(Taiwan) (En,Zh) (4B-003, Sachen-Commin) (Unl)
(Unknown) (Proto)
(USA)
(USA) (Beta)
(USA) (Proto)
(USA) (Rev A)
(USA) (Rev A) (SGB Enhanced)
(USA) (SGB Enhanced)
(USA) (Unl)
(USA) (v2.1) (Unl)
(USA, Europe)
(USA, Europe) (Beta)
(USA, Europe) (Beta) (SGB Enhanced)
(USA, Europe) (En,Fr,De) (Rev A) (SGB Enhanced)
(USA, Europe) (En,Fr,De,Es)
(USA, Europe) (En,Fr,De,Es) (SGB Enhanced)
(USA, Europe) (En,Fr,De,Es,It,Nl,Sv)
(USA, Europe) (En,Fr,De,It)
(USA, Europe) (GBC,SGB Enhanced)
(USA, Europe) (Rev A)
(USA, Europe) (Rev A) (SGB Enhanced)
(USA, Europe) (Rev B)
(USA, Europe) (SGB Enhanced)
(World)
(World) (Beta)
(World) (Rev 1)
(World) (Rev A)
(World) (Rev A) (SGB Enhanced)


PROCESS: C:\Games\No-Intro 2018\Nintendo - Game Boy Advance
-------------------------------------------------------
Directory Exists: Continue Processing
Found 273 Potential Exceptions to Filter:
(Australia)
(China)
(China) (Unl)
(China) (v1.3) (Unl)
(China) (v2.0) (Unl)
(Denmark)
(Europe)
(Europe) (Alt 1) (Unl)
(Europe) (Beta)
(Europe) (Beta) (2005-07-13)
(Europe) (Beta) (2005-10-14)
(Europe) (Demo)
(Europe) (Demo) (Unl)
(Europe) (En,De)
(Europe) (En,De) (Rev 1)
(Europe) (En,De,Es)
(Europe) (En,De,Es,It)
(Europe) (En,De,Es,Nl)
(Europe) (En,De,It)
(Europe) (En,Es,It)
(Europe) (En,Es,It,Sv,Da)
(Europe) (En,Es,Nl)
(Europe) (En,Fr)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De) (Beta)
(Europe) (En,Fr,De) (Virtual Console)
(Europe) (En,Fr,De,Da)
(Europe) (En,Fr,De,Da+En,De)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es) (Rev 1)
(Europe) (En,Fr,De,Es) (Virtual Console)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It) (Beta 1)
(Europe) (En,Fr,De,Es,It) (Beta 2)
(Europe) (En,Fr,De,Es,It) (Beta)
(Europe) (En,Fr,De,Es,It) (Beta) (11-09-2002)
(Europe) (En,Fr,De,Es,It) (Beta) (16-09-2002)
(Europe) (En,Fr,De,Es,It) (Destination Software)
(Europe) (En,Fr,De,Es,It) (Proto)
(Europe) (En,Fr,De,Es,It) (Rev 1)
(Europe) (En,Fr,De,Es,It) (Rev 2)
(Europe) (En,Fr,De,Es,It) (Unl)
(Europe) (En,Fr,De,Es,It) (Virtual Console)
(Europe) (En,Fr,De,Es,It) (Vivendi)
(Europe) (En,Fr,De,Es,It) (Wii U Virtual Console)
(Europe) (En,Fr,De,Es,It,Da)
(Europe) (En,Fr,De,Es,It,Fi)
(Europe) (En,Fr,De,Es,It,Nl)
(Europe) (En,Fr,De,Es,It,Nl) (Beta)
(Europe) (En,Fr,De,Es,It,Nl) (Beta) [b]
(Europe) (En,Fr,De,Es,It,Nl) (Rev 1)
(Europe) (En,Fr,De,Es,It,Nl,Da)
(Europe) (En,Fr,De,Es,It,Nl,Pt)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Da)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi,Pl)
(Europe) (En,Fr,De,Es,It,Nl,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Sv,Da)
(Europe) (En,Fr,De,Es,It,Nl,Sv,Da+En)
(Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da,Fi)
(Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da,Fi) (Beta)
(Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,It,Nl,Sv,No,Da,Fi)
(Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,Nl)
(Europe) (En,Fr,De,Es,It,Pt)
(Europe) (En,Fr,De,Es,It,Pt) (Beta)
(Europe) (En,Fr,De,Es,It,Sv)
(Europe) (En,Fr,De,Es,It,Sv,Da)
(Europe) (En,Fr,De,Es,It,Sv,No,Da,Fi)
(Europe) (En,Fr,De,Es,It,Sv,No,Da,Fi) (Rev 2)
(Europe) (En,Fr,De,Es,It,Sv+En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It+En)
(Europe) (En,Fr,De,Es,Nl)
(Europe) (En,Fr,De,Es+En,Fr,De,Es,It,Nl)
(Europe) (En,Fr,De,It)
(Europe) (En,Fr,De,It) (Alt 1) (Unl)
(Europe) (En,Fr,De,It) (Rev 1)
(Europe) (En,Fr,De,It) (Unl)
(Europe) (En,Fr,De,It) (v3.1) (Unl)
(Europe) (En,Fr,De,It) (v3.3) (Unl)
(Europe) (En,Fr,De,It,Sv,No,Da,Fi)
(Europe) (En,Fr,De,It,Sv,No,Da,Fi) (Rev 1)
(Europe) (En,Fr,De,Nl)
(Europe) (En,Fr,De+En)
(Europe) (En,Fr,De+En,Fr,De,Es)
(Europe) (En,Fr,De+En,Fr,De,Es,It)
(Europe) (En,Fr,Es)
(Europe) (En,Fr,Es,It)
(Europe) (En,Fr,Es,It) (Ubi Soft)
(Europe) (En,Fr,Es,It) (Zoo Digital)
(Europe) (En,Fr,Es,It,Nl,Pt,Da)
(Europe) (En,Fr,Es,Nl)
(Europe) (En,Fr,It)
(Europe) (En,Fr,Nl)
(Europe) (En,It)
(Europe) (En,It) (Proto)
(Europe) (En,It,Sv,No,Da)
(Europe) (En,Ja)
(Europe) (En,Ja,Fr,De)
(Europe) (En,Ja,Fr,De,Es)
(Europe) (En,Ja,Fr,De,Es,It)
(Europe) (En,Ja,Fr,De,Es,It) (Beta)
(Europe) (En,Ja,Fr,De,Es,It+En)
(Europe) (En,Ja,Fr,De,Es,It+En,Ja,Fr,De,Es)
(Europe) (En,Ja,Fr,De,Es+En,Ja,Fr,De,Es,It)
(Europe) (En,No,Da)
(Europe) (En,Sv,No,Da,Fi)
(Europe) (En+En,Es,It,Sv,Da)
(Europe) (En+En,Fr,De)
(Europe) (En+En,Fr,De,Es,It,Nl,Sv,Da)
(Europe) (En+En,Ja,Fr,De,Es)
(Europe) (En+En+En,Fr,De)
(Europe) (Es,It)
(Europe) (Es,It+En,Es,It,Sv,Da)
(Europe) (Es,Pt)
(Europe) (Fr,De)
(Europe) (Fr,De,Es)
(Europe) (Fr,De,Es,It)
(Europe) (Fr,De,Es,It,Nl,Sv,Da)
(Europe) (Fr,De,Es,It,Sv)
(Europe) (Fr,De,Es,Nl)
(Europe) (Fr,De,Nl)
(Europe) (Fr,De,Pt)
(Europe) (Fr,Es)
(Europe) (Fr,Nl)
(Europe) (Fr,Nl+Fr,De,Nl)
(Europe) (It,Nl)
(Europe) (Proto 1)
(Europe) (Proto 2)
(Europe) (Rev 1)
(Europe) (Sv,No,Da,Fi)
(Europe) (Unl)
(Europe) (Virtual Console)
(Europe) (Wii U Virtual Console)
(France)
(France) (En,Fr)
(France) (En,Fr,De+Fr)
(France) (En,Fr,It+Fr,Nl)
(France) (Fr+En,Fr,De,Es,It)
(France) (Fr+En,Fr,De,Es,It,Nl,Sv,Da)
(France) (Proto)
(France) (Rev 1)
(Germany)
(Germany) (Beta)
(Germany) (De+En,Fr,De,Es,It,Nl,Sv,Da)
(Germany) (De+Fr,De,Nl)
(Germany) (Debug Version)
(Germany) (En,De)
(Germany) (En,Fr,De+De)
(Germany) (Rev 1)
(Italy)
(Italy) (En,Fr,It+Es,It)
(Italy) (Es,It+It)
(Italy) (It+En,Fr,De,Es,It,Nl,Sv,Da)
(Italy) (Proto)
(Italy) (Rev 1)
(Japan)
(Japan) (3DS Virtual Console)
(Japan) (Beta)
(Japan) (Beta) (06-02-2003)
(Japan) (Beta) (19-02-2003)
(Japan) (Debug Version)
(Japan) (Demo) (Kiosk)
(Japan) (Demo) (Kiosk, GameCube)
(Japan) (Demo) (Promo)
(Japan) (En)
(Japan) (En) (Rev 1)
(Japan) (En) (SDK 3.0)
(Japan) (En,Ja)
(Japan) (En,Ja) (Rev 1)
(Japan) (En,Ja,Fr,De)
(Japan) (En,Ja,Fr,De,Es)
(Japan) (En,Ja,Fr,De,Es,It)
(Japan) (En,Ja,Fr,De,Es,It) (Rev 1)
(Japan) (En,Ja,Fr,De,Es+En,Ja)
(Japan) (En,Ja+En,Ja,Fr,De,Es,It)
(Japan) (Hot Mario Campaign)
(Japan) (Promo)
(Japan) (Proto)
(Japan) (Rev 1)
(Japan) (Rev 2)
(Japan) (Unl)
(Japan) (Unreleased)
(Japan) (Virtual Console)
(Japan) (Wii U Virtual Console)
(Japan, USA) (En,Ja)
(Korea)
(Netherlands)
(Netherlands) (En,Es,Nl+Fr,Nl)
(Netherlands) (En,Nl)
(Nicktoons) (USA)
(Racing) (USA) (En,Fr,De,Es,It)
(Soccer) (Europe) (En,Fr,De,Es,It)
(Spain)
(Spain) (En,Es,Nl+Es,It)
(Spain) (Es,It+Es)
(Spain) (Es+En,Fr,De,Es,It)
(Spain) (Es+En,Fr,De,Es,It,Nl,Sv,Da)
(Spain) (Promo)
(Spain) (Rev 1)
(Spain) (Unl)
(Unknown) (Beta)
(Unknown) (Demo)
(Unknown) (Promo)
(Unknown) (Proto)
(Unknown) (Proto) (2001)
(Unknown) (Proto) (2003)
(Unknown) (Sample)
(Unknown) (Unl)
(USA)
(USA) (Advance Play Edition)
(USA) (Alt 1) (Unl)
(USA) (Beta 1)
(USA) (Beta 2)
(USA) (Beta)
(USA) (Debug Version)
(USA) (Demo) (Kiosk)
(USA) (Demo) (Kiosk, GameCube)
(USA) (Destination Software)
(USA) (En,Es)
(USA) (En,Fr)
(USA) (En,Fr,De)
(USA) (En,Fr,De,Es)
(USA) (En,Fr,De,Es,It)
(USA) (En,Fr,De,Es,It) (Rev 1)
(USA) (En,Fr,De,Es,It) (Virtual Console)
(USA) (En,Fr,De,Es,It,Da)
(USA) (En,Fr,De,Es,It,Nl)
(USA) (En,Fr,De,Es,It,Nl) (Beta)
(USA) (En,Fr,De,Es,It,Nl) (Rev 1)
(USA) (En,Fr,De,Es,It,Nl,Pt,Da)
(USA) (En,Fr,De,Es,It,Nl,Sv,Da)
(USA) (En,Fr,De,Es,It,Sv,No,Da,Fi)
(USA) (En,Fr,De+En)
(USA) (En,Fr,De+En,Fr,De,Es)
(USA) (En,Fr,Es)
(USA) (En,Fr,Es,Nl)
(USA) (En,Fr,Es,Pt)
(USA) (En,Ja)
(USA) (En,Ja,Fr,De)
(USA) (En,Ja,Fr,De,Es)
(USA) (En,Ja,Fr,De,Es,It)
(USA) (En,Ja,Fr,De,Es+En,Ja,Fr,De,Es,It)
(USA) (Fire Emblem GBA - Bonus Items)
(USA) (GameCube)
(USA) (Proto)
(USA) (Rev 1)
(USA) (Rev 5)
(USA) (Rev 6)
(USA) (Sample)
(USA) (Unl)
(USA) (v0.14) (Beta)
(USA) (Virtual Console)
(USA) (Vivendi)
(USA) (Wii U Virtual Console)
(USA, Australia)
(USA, Australia) (En,Fr,De,Es,It)
(USA, Australia) (Rev 1)
(USA, Europe)
(USA, Europe) (En,Fr,De)
(USA, Europe) (En,Fr,De,Es)
(USA, Europe) (En,Fr,De,Es,It)
(USA, Europe) (En,Fr,De,Es,It,Nl)
(USA, Europe) (En,Fr,De,Es,It,Nl,Da)
(USA, Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da)
(USA, Europe) (En,Fr,De,Es,It,Nl,Sv,Da)
(USA, Europe) (En,Fr,De,It)
(USA, Europe) (Rev 1)
(USA, Europe) (Rev 2)
(USA, Europe) (Virtual Console)
(World)


PROCESS: C:\Games\No-Intro 2018\Nintendo - Game Boy Color
-------------------------------------------------------
Directory Exists: Continue Processing
Found 185 Potential Exceptions to Filter:
(Australia) (31B-001, Sachen) (Unl)
(Australia) (SGB Enhanced) (GB Compatible)
(China) (Li Cheng) (Unl)
(Europe)
(Europe) (1B-003, Sachen) (Unl)
(Europe) (Alternate) (Unl)
(Europe) (Beta)
(Europe) (En,De)
(Europe) (En,De,Es,It)
(Europe) (En,Es)
(Europe) (En,Es,It)
(Europe) (En,Es,It) (SGB Enhanced) (GB Compatible)
(Europe) (En,Es,Nl)
(Europe) (En,Fr)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De) (GB Compatible)
(Europe) (En,Fr,De) (Rev 1) (3DS Virtual Console) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es) (GB Compatible)
(Europe) (En,Fr,De,Es) (Proto)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It) (Beta)
(Europe) (En,Fr,De,Es,It) (GB Compatible)
(Europe) (En,Fr,De,Es,It) (Rumble Version) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De,Es,It) (Sample) (GB Compatible)
(Europe) (En,Fr,De,Es,It) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De,Es,It) (v0.45.3) (Beta)
(Europe) (En,Fr,De,Es,It,Nl)
(Europe) (En,Fr,De,Es,It,Nl) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl,Ca)
(Europe) (En,Fr,De,Es,It,Nl,Da)
(Europe) (En,Fr,De,Es,It,Nl,Pt)
(Europe) (En,Fr,De,Es,It,Nl,Pt) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi)
(Europe) (En,Fr,De,Es,It,Nl,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (AP9P) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (AX9P)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (Rev A)
(Europe) (En,Fr,De,Es,It,Nl,Sv,Da)
(Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da)
(Europe) (En,Fr,De,Es,It,Pt)
(Europe) (En,Fr,De,Es,It,Pt) (Beta)
(Europe) (En,Fr,De,Es,Nl)
(Europe) (En,Fr,De,Es,Nl) (GB Compatible)
(Europe) (En,Fr,De,It) (GB Compatible)
(Europe) (En,Fr,De,It) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De,It,Nl,Sv)
(Europe) (En,Fr,It)
(Europe) (En,Nl,Sv,No,Da)
(Europe) (En,Sv,No,Da,Fi)
(Europe) (Fr,De)
(Europe) (Fr,De,Es)
(Europe) (Fr,De,Nl)
(Europe) (Fr,Nl)
(Europe) (GB Compatible)
(Europe) (Proto)
(Europe) (Rev A)
(Europe) (Rumble Version)
(Europe) (Sample)
(Europe) (SGB Enhanced) (GB Compatible)
(Europe) (Unl)
(France)
(France) (En,Fr,De,Es,It,Nl,Sv) (GB Compatible)
(France) (GB Compatible)
(France) (Rev A) (SGB Enhanced) (GB Compatible)
(France) (SGB Enhanced)
(France) (SGB Enhanced) (GB Compatible)
(Germany)
(Germany) (En)
(Germany) (En,Fr,De,Es,It,Nl,Sv) (GB Compatible)
(Germany) (GB Compatible)
(Germany) (Rev A) (SGB Enhanced) (GB Compatible)
(Germany) (SGB Enhanced) (GB Compatible)
(Italy)
(Italy) (GB Compatible)
(Italy) (SGB Enhanced) (GB Compatible)
(Japan)
(Japan) (En) (3DS Virtual Console)
(Japan) (En) (GB Compatible)
(Japan) (En) (Rumble Version)
(Japan) (En) (SGB Enhanced) (GB Compatible)
(Japan) (En,Ja)
(Japan) (En,Ja) (GB Compatible)
(Japan) (GB Compatible)
(Japan) (NP)
(Japan) (NP) (GB Compatible)
(Japan) (NP, SGB Enhanced) (GB Compatible)
(Japan) (Proto)
(Japan) (Rev 1) (GB Compatible)
(Japan) (Rev A)
(Japan) (Rev A) (GB Compatible)
(Japan) (Rev A) (NP, SGB Enhanced) (GB Compatible)
(Japan) (Rev A) (SGB Enhanced) (GB Compatible)
(Japan) (Rev B) (GB Compatible)
(Japan) (Rev B) (SGB Enhanced) (GB Compatible)
(Japan) (Rumble Version)
(Japan) (Rumble Version) (SGB Enhanced) (GB Compatible)
(Japan) (Sample)
(Japan) (SGB Enhanced) (GB Compatible)
(Korea)
(Netherlands) (GB Compatible)
(Spain)
(Spain) (GB Compatible)
(Spain) (SGB Enhanced) (GB Compatible)
(Taiwan) (1B-002, 4B-003, Sachen) (Unl)
(Taiwan) (31B-001, Sachen) (Unl)
(Taiwan) (En) (1B-001, Sachen) (Unl)
(Taiwan) (En) (1B-004, EB-004, Sachen) (Unl)
(Taiwan) (En) (Sachen) (Unl)
(Taiwan) (En,Zh) (6B-001, Sachen) (Unl)
(Unknown) (Proto)
(Unknown) (Proto) (early)
(USA)
(USA) (Beta)
(USA) (En,Es) (GB Compatible)
(USA) (En,Fr,De)
(USA) (En,Fr,De) (GB Compatible)
(USA) (En,Fr,De,Es)
(USA) (En,Fr,De,Es,It)
(USA) (En,Fr,De,Es,It) (GB Compatible)
(USA) (En,Fr,De,Es,It) (Rumble Version)
(USA) (En,Fr,De,Es,It) (SGB Enhanced) (GB Compatible)
(USA) (En,Fr,De,Es,It,Nl)
(USA) (En,Fr,De,Es,It,Nl) (GB Compatible)
(USA) (En,Fr,Es)
(USA) (En,Fr,Es) (GB Compatible)
(USA) (En,Fr,Es) (SGB Enhanced) (GB Compatible)
(USA) (En,Fr,Es,Pt) (GB Compatible)
(USA) (GB Compatible)
(USA) (Promo)
(USA) (Proto)
(USA) (Proto) (2000-04-19)
(USA) (Proto) (GB Compatible)
(USA) (Proto) (SGB Enhanced) (GB Compatible)
(USA) (Rev A)
(USA) (Rev A) (GB Compatible)
(USA) (Rev A) (SGB Enhanced) (GB Compatible)
(USA) (Rev B)
(USA) (Rev B) (GB Compatible)
(USA) (Rumble Version)
(USA) (Rumble Version) (SGB Enhanced) (GB Compatible)
(USA) (Sample)
(USA) (SGB Enhanced) (GB Compatible)
(USA) (Unl)
(USA, Australia)
(USA, Europe)
(USA, Europe) (En,De)
(USA, Europe) (En,Fr,De)
(USA, Europe) (En,Fr,De) (SGB Enhanced) (GB Compatible)
(USA, Europe) (En,Fr,De,Es)
(USA, Europe) (En,Fr,De,Es) (GB Compatible)
(USA, Europe) (En,Fr,De,Es,It)
(USA, Europe) (En,Fr,De,Es,It) (Beta)
(USA, Europe) (En,Fr,De,Es,It) (GB Compatible)
(USA, Europe) (En,Fr,De,Es,It) (Rumble Version)
(USA, Europe) (En,Fr,De,Es,It) (Sample)
(USA, Europe) (En,Fr,De,Es,It,Nl)
(USA, Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,Da)
(USA, Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi)
(USA, Europe) (En,Fr,De,Es,Sv) (GB Compatible)
(USA, Europe) (En,Fr,De,Es,Sv) (Rev A) (GB Compatible)
(USA, Europe) (En,Fr,Es,It)
(USA, Europe) (En,Ja,Fr,De,Es)
(USA, Europe) (En,Ja,Fr,De,Es,Zh)
(USA, Europe) (GB Compatible)
(USA, Europe) (Rev A)
(USA, Europe) (Rev A) (GB Compatible)
(USA, Europe) (Rev A) (SGB Enhanced) (GB Compatible)
(USA, Europe) (Rev B)
(USA, Europe) (Rev B) (SGB Enhanced) (GB Compatible)
(USA, Europe) (Rumble Version)
(USA, Europe) (SGB Enhanced) (GB Compatible)
(World)
(World) (1B-002, 1B-003, Sachen) (Unl)
(World) (4B-001, 4B-009, 8B-001, Sachen) (Unl)
(World) (4B-002, 4B-004, 8B-002, Sachen) (Unl)
(World) (4B-005, 4B-006, 8B-003, Sachen) (Unl)
(World) (4B-007, 4B-008, 8B-004, Sachen) (Unl)
(World) (En,Ja)
(World) (Rev 1) (Sachen) (No Copyright) (Unl)
(World) (SGB Enhanced) (GB Compatible)


PROCESS: C:\Games\No-Intro 2018\Sega - Master System - Mark III
-------------------------------------------------------
Directory Exists: Continue Processing
Found 82 Potential Exceptions to Filter:
(A) (Korea) (Unl)
(Australia) (Unl)
(B) (Korea) (Unl)
(Brazil)
(Brazil) (En,Es,Pt)
(Brazil) (En,Fr,De,Es,It,Pt,Sv,No)
(Brazil) (Sample)
(Brazil, Korea)
(C) (Korea) (Unl)
(D) (Korea) (Unl)
(E) (Korea) (Unl)
(Europe)
(Europe) (Beta)
(Europe) (En,Fr)
(Europe) (En,Fr) (Rev 1)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es) (Beta)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Europe) (En,Fr,De,Es,It,Pt,Sv,No)
(Europe) (Image Works)
(Europe) (Light Phaser)
(Europe) (Proto)
(Europe) (Rev 1)
(Europe) (Rev 2)
(Europe) (Sample)
(Europe) (v2.0)
(Europe) (Virgin)
(F) (Korea) (Unl)
(Japan)
(Japan) (Beta)
(Japan) (Proto)
(Japan) (Proto) (Ep-MyCard)
(Japan) (v2.1)
(Japan, Europe)
(Japan, Europe) (En,Ja)
(Japan, Europe) (Rev 1)
(Japan, USA)
(Korea)
(Korea) (Clover)
(Korea) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Korea) (Pirate)
(Korea) (Unl)
(Korea) (Unl) (Pirate)
(Taiwan)
(Unknown)
(Unknown) (Beta)
(Unknown) (Demo)
(Unknown) (Proto)
(Unknown) (Sample)
(USA)
(USA) (Beta 1)
(USA) (Beta 2)
(USA) (Beta)
(USA) (Ja) (Demo)
(USA) (M404) (Proto)
(USA) (Proto)
(USA) (Rev 1)
(USA) (Sample)
(USA) (Store Display Unit)
(USA) (v1.0) (Proto)
(USA) (v2.0) (Proto)
(USA, Europe)
(USA, Europe) (Beta 1)
(USA, Europe) (Beta 2)
(USA, Europe) (Beta 3)
(USA, Europe) (Beta)
(USA, Europe) (Easy Version)
(USA, Europe) (En,Fr,De,Es,It) (Proto)
(USA, Europe) (Hard Version)
(USA, Europe) (Rev 1)
(USA, Europe) (Rev 2)
(USA, Europe) (Rev 3)
(USA, Europe) (v1.3)
(USA, Europe) (v2.4)
(USA, Europe) (v3.4)
(USA, Europe) (v4.4)
(World)
(World) (Beta)
(World) (Rev 1) (Beta)
(World) (Rev 2)


PROCESS: C:\Games\No-Intro 2018\Sega - Mega Drive - Genesis
-------------------------------------------------------
Directory Exists: Continue Processing
Found 214 Potential Exceptions to Filter:
(Argentina) (Unl)
(Asia) (En)
(Asia) (Ja)
(Asia) (Ja) (v1.00S)
(Australia)
(Australia) (Beta)
(Brazil)
(Brazil) (Alt 1)
(Brazil) (Beta)
(Brazil) (Es,Pt)
(Brazil) (Program)
(Brazil) (Unl)
(Europe)
(Europe) (Alt 1) (Program) (Unl)
(Europe) (Alt)
(Europe) (Beta 1)
(Europe) (Beta 2)
(Europe) (Beta)
(Europe) (Beta) (Earlier)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es) (Beta)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It) (Alt)
(Europe) (En,Fr,De,Es,It) (Beta)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Europe) (En,Fr,De,Es,It,Pt,Sv,No)
(Europe) (En,Fr,De,Es,Nl,Sv)
(Europe) (En,Fr,De,Es,Pt)
(Europe) (En,Fr,De,It)
(Europe) (En,Fr,Es,It,Sv)
(Europe) (J-Cart)
(Europe) (Program) (Unl)
(Europe) (Proto)
(Europe) (Proto) (10.07.1994)
(Europe) (Requires MegaCD) (Program)
(Europe) (v1.00)
(Europe) (v1.1) (J-Cart)
(Europe) (v2.00)
(Europe) (v2.00W)
(Europe) (v2.21X)
(Europe) (Virtual Console)
(France)
(Germany)
(Germany) (Beta)
(Hong Kong)
(Japan)
(Japan) (1.00l)
(Japan) (1.00S)
(Japan) (Beta)
(Japan) (Beta) (1993-11-27)
(Japan) (Beta) (Earlier)
(Japan) (Beta) [b]
(Japan) (En)
(Japan) (En) (Beta) (21.08.1989) (Sega Channel)
(Japan) (En) (Beta) (XX.XX.1989) (Sega Smash Pack)
(Japan) (En) (Proto)
(Japan) (En) (Proto) (08.04.1994)
(Japan) (En) (Proto) (17.05.1994)
(Japan) (En) (Proto) [b]
(Japan) (En) (v1.00) (Sega)
(Japan) (En,Fr,De,Es,It,Pt,Sv,No)
(Japan) (En,Ja)
(Japan) (Launch Cart)
(Japan) (Program)
(Japan) (Proto)
(Japan) (Proto) [b]
(Japan) (Rev A)
(Japan) (Rev A) (Program)
(Japan) (Rev B)
(Japan) (Rev C)
(Japan) (Sample)
(Japan) (Sega Channel)
(Japan) (SegaNet)
(Japan) (Unl)
(Japan) (v1.00P)
(Japan) (v1.02)
(Japan) (v2.00)
(Japan) (v2.00C)
(Japan, Europe)
(Japan, Europe) (Alt)
(Japan, Europe) (En,Ja)
(Japan, Europe) (En,Ja) (Rev A)
(Japan, Europe) (En,Ja) (Rev B)
(Japan, Europe) (Rev A)
(Japan, Korea)
(Japan, USA)
(Japan, USA) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Japan, USA) (En,Fr,De,Es,It,Nl,Pt,Sv) (Rev A)
(Japan, USA) (En,Ja)
(Japan, USA) (Rev A)
(Japan, USA) (Rev B)
(Japan, USA) (Rev C)
(Korea)
(Korea) (En,Fr,De,Es)
(Korea) (En,Ko)
(Russia) (Unl)
(Spain)
(Sweden)
(Taiwan) (Alt 1) (Unl)
(Taiwan) (Alt) (Unl)
(Taiwan) (En)
(Taiwan) (En) (Unl)
(Taiwan) (Simple Chinese) (Unl)
(Taiwan) (Unl)
(Taiwan) (Unl) [b]
(USA)
(USA) (02.03.1992) (Sega Channel)
(USA) (03.02.1992) (Sega Channel)
(USA) (13.03.1992) (Sega Channel)
(USA) (Acclaim) (Beta)
(USA) (Acclaim) (Beta) (Earlier)
(USA) (Alpha)
(USA) (Beta 1)
(USA) (Beta 2)
(USA) (Beta)
(USA) (Beta) (13.12.1991) (Sega Channel)
(USA) (Beta) (16.01.1992) (Sega Channel)
(USA) (Beta) (1993-06-27)
(USA) (Beta) (1993-08-13)
(USA) (Beta) (1995-07-07)
(USA) (Beta) (Alt 1)
(USA) (Beta) (Earlier)
(USA) (Beta) (July 1994)
(USA) (Beta) (September 1994)
(USA) (Beta) [b]
(USA) (En,Fr,De,Es,It)
(USA) (En,Fr,De,Es,It,Pt,Sv,No)
(USA) (En,Ja)
(USA) (En,Ja) (Rev C)
(USA) (Es)
(USA) (General Instrument) (Program)
(USA) (Majesco)
(USA) (Program)
(USA) (Proto)
(USA) (Proto) (02.03.1992) (Sega Channel)
(USA) (Proto) (03.06.1994)
(USA) (Proto) (06.06.1994)
(USA) (Proto) (11.08.1994)
(USA) (Proto) (26.06.1990) (Sega Channel)
(USA) (Proto) (28.07.1994)
(USA) (Proto) (28.12.1991) (Sega Channel)
(USA) (Proto) (Earlier)
(USA) (Rev A)
(USA) (Rev A) (Beta) (25.09.1990) (Sega Channel)
(USA) (Sample)
(USA) (Sample) (NGen)
(USA) (Scientific Atlanta) (Program)
(USA) (Sega Smash Pack)
(USA) (Unl)
(USA) (v1.00)
(USA) (v1.02)
(USA) (v1.04)
(USA) (v1.10)
(USA) (v2.00)
(USA) (v2.00W)
(USA) (v2.11X)
(USA) (v2.21X)
(USA) (Virtual Console)
(USA, Asia) (Unl)
(USA, Australia)
(USA, Australia) (Rev A) (Beta)
(USA, Europe)
(USA, Europe) (1.0) (J-Cart) (MDST17FF)
(USA, Europe) (1.1) (J-Cart) (MDST6636)
(USA, Europe) (1.2) (J-Cart) (MDSTEE13)
(USA, Europe) (Acclaim)
(USA, Europe) (Alt 1)
(USA, Europe) (Alt 2)
(USA, Europe) (Alt 3)
(USA, Europe) (Alt) (Unl)
(USA, Europe) (Beta)
(USA, Europe) (En,Fr,De,Es)
(USA, Europe) (En,Fr,De,Es,It)
(USA, Europe) (En,Fr,De,Es,It,Sv)
(USA, Europe) (En,Fr,It)
(USA, Europe) (En,Ja) (Virtual Console)
(USA, Europe) (Program)
(USA, Europe) (Rev A)
(USA, Europe) (Rev A) (Beta) (18.01.1991) (Sega Channel)
(USA, Europe) (Rev A) (Beta) (22.03.1990) (Sega Channel)
(USA, Europe) (Rev A) (Beta) (29.06.1993) (Sega Channel)
(USA, Europe) (Rev A) (Program)
(USA, Europe) (Rev B)
(USA, Europe) (Rev C)
(USA, Europe) (Rev D) (Virtual Console)
(USA, Europe) (Sega Channel)
(USA, Europe) (Sega Smash Pack)
(USA, Europe) (Unl)
(USA, Korea)
(World)
(World) (Beta 1)
(World) (Beta 2)
(World) (Beta)
(World) (Beta) (Unl)
(World) (En,Es,Pt) (Reprint B) (Unl)
(World) (En,Fr,De) (Reprint A) (Unl)
(World) (En,Fr,De) (Reprint) (Unl)
(World) (En,Fr,De,Es)
(World) (En,Fr,Es) (Unl)
(World) (En,Ja)
(World) (En,Ja) (Beta) (18.08.1989) (Sega Channel)
(World) (En,Ja) (Rev A)
(World) (GameCube Edition)
(World) (Proto)
(World) (Rev A)
(World) (Rev A) (Sega Channel)
(World) (Rev B) (GameCube Edition)
(World) (Rev B) (Sega Smash Pack)
(World) (Sega Channel)
(World) (Sega Smash Pack)
(World) (Sega)
(World) (Unl)
(World) (V1.1) (Unl)


PROCESS: C:\Games\No-Intro 2018\Microsoft - MSX
-------------------------------------------------------
Directory Exists: Continue Processing
Found 40 Potential Exceptions to Filter:
(Europe)
(Europe) (Alt 1)
(Europe) (Alt 2)
(Europe) (Converted from Tape)
(Europe) (Program)
(France)
(Japan)
(Japan) (Alt 1)
(Japan) (Alt 2)
(Japan) (Alt 3)
(Japan) (Alt 4)
(Japan) (Beta)
(Japan) (Demo)
(Japan) (FS-CA1) (Program)
(Japan) (High Speed)
(Japan) (HX-MU900) (Program)
(Japan) (NGA II) (Program)
(Japan) (NGA II) (Program) (Alt 1)
(Japan) (Program)
(Japan) (Program) (Alt 1)
(Japan) (Unl)
(Japan) (v1.03)
(Japan) (v1.1) (Program)
(Japan) (v1.2) (Program)
(Japan) (v2)
(Japan) (v2) (Alt 1)
(Japan, Europe)
(Japan, Europe) (Alt 1)
(Japan, Europe) (Alt 2)
(Japan, Europe) (Alt 3)
(Japan, Europe) (Alt 4)
(Japan, Europe) (Beta)
(Korea)
(Korea) (Alt 1)
(Korea) (Alt 1) (Unl)
(Korea) (Unl)
(Netherlands)
(Netherlands) (Program)
(Spain)
(Spain) (Alt 1)


PROCESS: C:\Games\No-Intro 2018\Nintendo - Nintendo 64
-------------------------------------------------------
Directory Exists: Continue Processing
Found 98 Potential Exceptions to Filter:
(Australia)
(Australia) (En,Fr,De)
(Australia) (Proto)
(Brazil)
(Brazil) (En,Fr)
(Europe)
(Europe) (Beta)
(Europe) (Demo) (Kiosk)
(Europe) (En,De)
(Europe) (En,De,Sv,Fi)
(Europe) (En,Es,It)
(Europe) (En,Es,It) (Proto)
(Europe) (En,Fr)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De) (Rev A)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es) (Debug Version)
(Europe) (En,Fr,De,Es) (Rev A)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It) (Proto)
(Europe) (En,Fr,De,Es,It,Nl)
(Europe) (En,Fr,De,Es,It,Nl,Da)
(Europe) (En,Fr,De,Es,It,Nl,Pt)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Sv,Da)
(Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da,Fi)
(Europe) (En,Fr,Es)
(Europe) (En,Fr,Es,It)
(Europe) (En,Fr,It)
(Europe) (En,Ja,Fr,De)
(Europe) (Es,It)
(Europe) (Fr,De)
(Europe) (Fr,De,Nl)
(Europe) (Fr,It)
(Europe) (GameCube Edition)
(Europe) (Proto)
(Europe) (Rev A)
(Europe) (Rev B)
(Europe) (v1.1) (Unl)
(Europe) (v3.0) (Unl)
(Europe) (v3.3) (Unl)
(France)
(Germany)
(Germany) (Proto)
(Germany) (Rev A)
(Germany) (Rev B)
(Germany) (v1.067) (Unl)
(Italy)
(Japan)
(Japan) (Beta)
(Japan) (Demo) (Kiosk)
(Japan) (En)
(Japan) (GameCube Edition)
(Japan) (Proto)
(Japan) (Rev A)
(Japan) (Rev A) (Shindou Edition)
(Japan) (Rev B)
(Japan) (Rev B) (Shindou Edition)
(Japan) (Rev C)
(Japan, USA) (En,Ja)
(Spain)
(USA)
(USA) (Alt 1)
(USA) (Beta)
(USA) (Beta) (2000-05-31)
(USA) (Beta) (2000-07-10)
(USA) (Debug Version)
(USA) (Demo)
(USA) (Demo) (Kiosk)
(USA) (Demo) (Kiosk, ECTS 2000)
(USA) (En,Es)
(USA) (En,Fr)
(USA) (En,Fr) (Rev A)
(USA) (En,Fr,De)
(USA) (En,Fr,De) (Rev A)
(USA) (En,Fr,De,Es)
(USA) (En,Fr,De,Es,It)
(USA) (En,Fr,De,Es,It,Nl)
(USA) (En,Fr,De,Es,It,Nl,Pt,Sv)
(USA) (En,Fr,De,Es,It,Nl,Sv)
(USA) (En,Fr,De,Es,It,Nl,Sv,Da)
(USA) (En,Fr,De,Es,It,Nl,Sv,No,Da,Fi)
(USA) (En,Fr,Es)
(USA) (En,Fr,Es) (Beta)
(USA) (En,Fr,Es) (Proto)
(USA) (En,Ja)
(USA) (GameCube Edition)
(USA) (Ja) (Proto)
(USA) (Promo)
(USA) (Proto)
(USA) (Proto) (early)
(USA) (Rev A)
(USA) (Rev A) (Proto)
(USA) (Rev B)
(USA) (v1.1) (Unl)
(USA) (v2.0) (Unl)
(USA) (v3.3) (Unl)


PROCESS: C:\Games\No-Intro 2018\Nintendo - Nintendo Entertainment System [headered]
-------------------------------------------------------
Directory Exists: Continue Processing
Found 168 Potential Exceptions to Filter:
(Asia) (En) (Mega Soft) (Unl)
(Asia) (En) (Unl)
(Asia) (Ja) (Hacker) (Unl)
(Asia) (Ja) (Hwang Shinwei) (Unl)
(Asia) (Ja) (NTSC) (Unl)
(Asia) (Ja) (PAL) (Unl)
(Asia) (Ja) (RCM Group) (Unl)
(Asia) (Ja) (Sachen) (Unl)
(Asia) (Ja) (Unl)
(Asia) (Unl)
(Asia, Australia) (Unl)
(Australia)
(Australia) (Beta)
(Australia) (HES) (Unl)
(Australia) (Unl)
(Brazil) (CCE, Gluk Video) (Unl)
(Brazil) (Unl)
(Bulletproof) (Japan)
(Bulletproof) (Japan) (Rev A)
(Bulletproof) (Japan) (Rev B)
(Canada)
(China) (Unl)
(Europe)
(Europe) (Beta)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De) (Beta)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es) (Unl)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Pt,Pl) (Unl)
(Europe) (Plug-Thru Cart) (Unl)
(Europe) (Promo, Virtual Console)
(Europe) (Proto)
(Europe) (Rev A)
(Europe) (Rev B)
(Europe) (Unl)
(Europe) (v1.0) (Unl)
(Europe) (v1.2) (Cart Present) (Unl)
(Europe) (v1.2) (No Cart Present) (Unl)
(Europe) (Wii Virtual Console)
(France)
(France) (En,Fr,Nl)
(France) (Rev A)
(Germany)
(Italy)
(Italy) (Unl)
(Japan)
(Japan) (Alt)
(Japan) (ArchiMENdes Hen)
(Japan) (Beta)
(Japan) (Beta) (1986-06-30)
(Japan) (Beta) (Earlier)
(Japan) (En)
(Japan) (En) (Beta)
(Japan) (En) (Promo, Wii U Virtual Console)
(Japan) (En) (Proto)
(Japan) (En) (Proto) [b]
(Japan) (En) (Rev 1)
(Japan) (En) (Rev A)
(Japan) (En) (Rev B)
(Japan) (En) (Sample)
(Japan) (FamicomBox)
(Japan) (Genteiban!)
(Japan) (Gold Edition)
(Japan) (Hacker inc.) (Unl)
(Japan) (Namco)
(Japan) (Proto)
(Japan) (Rev 0)
(Japan) (Rev 0A)
(Japan) (Rev 0B)
(Japan) (Rev 1)
(Japan) (Rev 1.2)
(Japan) (Rev 1.4)
(Japan) (Rev 2)
(Japan) (Rev 3)
(Japan) (Rev A)
(Japan) (Rev AB)
(Japan) (Rev B)
(Japan) (Sample)
(Japan) (Sample) (Final Version)
(Japan) (Unl)
(Japan) (Unl) [b]
(Japan) (v0.0) (Beta)
(Japan) (v1.0)
(Japan) (v2.0a)
(Japan) (v2.1a)
(Japan) (v3.0)
(Japan) (Victor)
(Japan, USA)
(Japan, USA) (Rev A)
(Korea) (Unl)
(NES Test) (USA) (Rev 1)
(Russia) (Unl)
(Spain)
(Spain) (Gluk Video) (Unl)
(Spain) (Rev 1) (Gluk Video) (Unl)
(Sunsoft) (USA) (Proto)
(Sweden)
(Sweden) (Sv,Da,Fi)
(Taiwan)
(Unknown) (Beta)
(Unknown) (Proto 1)
(Unknown) (Proto 1) (Unl)
(Unknown) (Proto 2)
(Unknown) (Proto 2) (Unl)
(Unknown) (Proto)
(Unknown) (Proto) (1993-09-24) (Unl)
(Unknown) (Proto) (RAM) (Unl)
(Unknown) (Proto) (Unl)
(Unknown) (Unl)
(USA)
(USA) (Aladdin Compact Cartridge) (Unl)
(USA) (Beta 1)
(USA) (Beta 2)
(USA) (Beta)
(USA) (Beta) (1989)
(USA) (Beta) (1990-01-18)
(USA) (Beta) (1990-02-02)
(USA) (Beta) (1990-04-27)
(USA) (Beta) (Between 1990-02-02 &amp; 1990-04-27, earlier)
(USA) (Beta) (Between 1990-02-02 &amp; 1990-04-27, later)
(USA) (Beta) (Unl)
(USA) (Beta) [b]
(USA) (En,Fr,De,Es) (Unl)
(USA) (GameCube Edition)
(USA) (Namco)
(USA) (Proto 1)
(USA) (Proto 1) (Unl)
(USA) (Proto 2)
(USA) (Proto 2) (Unl)
(USA) (Proto 2) [b]
(USA) (Proto)
(USA) (Proto) (Unl)
(USA) (Proto) [b]
(USA) (Rev 0A)
(USA) (Rev 1) (Unl)
(USA) (Rev A)
(USA) (Rev A) (GameCube Edition)
(USA) (Rev A) (Unl)
(USA) (Rev B)
(USA) (Rev B) (GameCube Edition)
(USA) (Sample)
(USA) (Taito)
(USA) (Tengen)
(USA) (Tengen) (Unl)
(USA) (UBI Soft)
(USA) (Unl)
(USA) (v0.924B) (Proto)
(USA) (v1.0) (Unl)
(USA) (v1.1) (Unl)
(USA) (v1.2) (Unl)
(USA) (v1.3) (Unl)
(USA) (v1.4) (Unl)
(USA) (v3.11.088) (Unl)
(USA) (v3.12.027) (Unl)
(USA) (v4.0) (Unl)
(USA) (v5.0) (Unl)
(USA) (v5.01.033) (Unl)
(USA) (v5.1) (Unl)
(USA) (v6.0) (Unl)
(USA) (v6.02.002) (Unl)
(USA) (v6.1) (Unl)
(USA) (v9.03.128) (Unl)
(USA) (Virtual Console)
(USA, Europe)
(World)
(World) (Rev A)
(Yi) (Asia) (Ja) (Unl)


PROCESS: C:\Games\No-Intro 2018\SNK - Neo Geo Pocket
-------------------------------------------------------
Directory Exists: Continue Processing
Found 4 Potential Exceptions to Filter:
(Japan)
(Japan) (Demo)
(Japan, Europe)
(Japan, Europe) (En,Ja)


PROCESS: C:\Games\No-Intro 2018\SNK - Neo Geo Pocket Color
-------------------------------------------------------
Directory Exists: Continue Processing
Found 30 Potential Exceptions to Filter:
(Europe)
(Japan)
(Japan) (Beta)
(Japan) (Demo)
(Japan) (En,Ja)
(Japan) (v1.02)
(Japan) (v1.04)
(Japan, Europe) (En,Ja)
(Japan, Europe) (En,Ja) (Demo)
(Japan, Europe) (v1.09)
(Japan, Europe) (v1.10)
(Ka) (Japan)
(USA)
(USA) (Beta)
(USA, Europe)
(USA, Europe) (Demo)
(USA, Europe) (Sample)
(World)
(World) (Beta)
(World) (Beta) (1999-10-22)
(World) (Demo)
(World) (En,Ja)
(World) (En,Ja) (Beta 1)
(World) (En,Ja) (Beta 2)
(World) (En,Ja) (Beta)
(World) (En,Ja) (Demo)
(World) (En,Ja) (v1.05)
(World) (En,Ja) (v1.06)
(World) (En,Ja) (v1.11)
(World) (En,Ja) (v1.13)


PROCESS: C:\Games\No-Intro 2018\NEC - PC Engine - TurboGrafx 16
-------------------------------------------------------
Directory Exists: Continue Processing
Found 18 Potential Exceptions to Filter:
(Japan)
(Japan) (All Star Version)
(Japan) (Alt 1)
(Japan) (Alt)
(Japan) (Demo)
(Japan) (En)
(Japan) (En) (Special Version)
(Japan) (En,Ja,Zh)
(Japan) (Proto)
(Japan) (Special Version)
(Japan) (v1.0)
(Japan) (v1.5)
(Japan) (v2.0)
(Japan) (v2.1)
(Japan) (v3.0)
(USA)
(USA) (v2.0)
(USA) (v3.0)


PROCESS: C:\Games\No-Intro 2018\Sega - 32X
-------------------------------------------------------
Directory Exists: Continue Processing
Found 16 Potential Exceptions to Filter:
(Europe)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es,It,Sv)
(Europe) (En,Ja)
(Japan)
(Japan, USA)
(Japan, USA) (Developer Cart)
(Japan, USA) (En,Ja)
(Japan, USA) (SDK Build)
(Japan, USA) (SDK Build) (Set 1)
(Japan, USA) (SDK Build) (Set 2)
(USA)
(USA) (Proto)
(USA) (SDK Build)
(USA, Europe)
(World)


PROCESS: C:\Games\No-Intro 2018\Sega - SG-1000
-------------------------------------------------------
Directory Exists: Continue Processing
Found 49 Potential Exceptions to Filter:
(Chuugaku 1-Nen) (Japan) (16kB) (SC-3000)
(Chuugaku 1-Nen) (Japan) (40kB) (SC-3000)
(Chuugaku 1-Nen) (Japan) (SC-3000)
(Chuugaku 2-Nen) (Japan) (16kB) (SC-3000)
(Chuugaku 2-Nen) (Japan) (40kB) (SC-3000)
(Chuugaku 2-Nen) (Japan) (SC-3000)
(Europe)
(Gensokigou Master) (Japan) (SC-3000)
(Japan)
(Japan) (16kB)
(Japan) (40kB)
(Japan) (Alt 1)
(Japan) (Beta)
(Japan) (English Title)
(Japan) (MyCard)
(Japan) (Othello Multivision)
(Japan) (Rev 1)
(Japan) (Rev 1) (40kB)
(Japan) (Rev 1) (Othello Multivision)
(Japan) (Rev 2)
(Japan) (SC-3000)
(Japan) (v1.0) (Othello Multivision)
(Japan) (v2.0) (Newer) (Othello Multivision)
(Japan) (v2.0) (Othello Multivision)
(Japan) (v2.6) (Othello Multivision)
(Japan) (v2.7) (Othello Multivision)
(Japan) (vA) (16kB) (Othello Multivision)
(Japan) (vA) (40kB) (Othello Multivision)
(Japan) (vB) (Othello Multivision)
(Japan, Europe)
(Japan, Europe) (Rev 1)
(Japan, Europe) (Rev 2)
(Korea)
(Shougaku 4-Nen Ge) (Japan) (SC-3000)
(Shougaku 4-Nen Jou) (Japan) (16kB) (SC-3000)
(Shougaku 4-Nen Jou) (Japan) (40kB) (SC-3000)
(Shougaku 5-Nen Ge) (Japan) (SC-3000)
(Shougaku 5-Nen Jou) (Japan) (SC-3000)
(Shougaku 6-Nen Ge) (Japan) (SC-3000)
(Shougaku 6-Nen Jou) (Japan) (SC-3000)
(Taiwan)
(Taiwan) (Alt 1)
(Taiwan) (Chinese Logo)
(Taiwan) (DahJee)
(Taiwan) (English Logo)
(Taiwan) (Jumbo)
(Taiwan) (MSX)
(Taiwan) (No Logo)
(Taiwan) (Othello Multivision)


PROCESS: C:\Games\No-Intro 2018\Nintendo - Super Nintendo Entertainment System
-------------------------------------------------------
Directory Exists: Continue Processing
Found 189 Potential Exceptions to Filter:
(^^; (Japan)
(Australia)
(Brazil) (En,Fr,De,Es,It,Sv)
(Brazil) (Es,Pt)
(Brazil) (Unl) (Pirate)
(Canada)
(China) (Unl)
(Europe)
(Europe) (Accolade)
(Europe) (Beta 1)
(Europe) (Beta 2)
(Europe) (Beta)
(Europe) (Beta) [b]
(Europe) (En,Es)
(Europe) (En,Fr)
(Europe) (En,Fr) (Rev 1)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De) (Beta)
(Europe) (En,Fr,De) (Rev 1)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It) (Beta)
(Europe) (En,Fr,De,Es,It) (Proto)
(Europe) (En,Fr,De,Es,It) (Proto) (1994-12-05)
(Europe) (En,Fr,De,Es,It,Nl)
(Europe) (En,Fr,De,Es,It,Nl) (Beta)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (Beta)
(Europe) (En,Fr,De,Es,It,Pt,Sv,No)
(Europe) (En,Fr,De,Es,It,Sv)
(Europe) (En,Fr,De,Es,Nl) (Proto)
(Europe) (En,Fr,De,Es,Pt)
(Europe) (En,Fr,De,It)
(Europe) (En,Fr,De,It) (Beta)
(Europe) (En,Fr,De,It) (Rev 1)
(Europe) (En,Fr,De,Nl)
(Europe) (En,Ja)
(Europe) (GamesMaster Special Edition)
(Europe) (Gremlin Graphics)
(Europe) (It,Sv) (Proto)
(Europe) (Proto)
(Europe) (Proto) (1994-04-12)
(Europe) (Proto) (No. 04)
(Europe) (Proto) (No. 14)
(Europe) (Proto) [b]
(Europe) (Putative Proto)
(Europe) (Rev 1)
(Europe) (Sample)
(Europe) (Unl)
(Europe) (Unl) [b]
(Europe) (v1.1) (Unl) [b]
(Europe) (v1.6) (Unl)
(Europe) (v1.7) (Unl)
(France)
(France) (Beta)
(France) (Beta) (1993-10-27)
(France) (En,Fr)
(France) (En,Fr,De,Es,It,Nl,Sv)
(France) (Rev 1)
(Germany)
(Germany) (En)
(Germany) (En,De)
(Germany) (En,De) (Rev 1)
(Germany) (Rev 1)
(Germany) (Sample)
(Hong Kong)
(Hong Kong) (Unl) [b]
(Italy)
(Japan)
(Japan) (Activision)
(Japan) (Alt 1) (Unl) [b]
(Japan) (Beta 1)
(Japan) (Beta 2)
(Japan) (Beta)
(Japan) (Beta) (1992-12-21)
(Japan) (Beta) (1993-03-03)
(Japan) (Bunka Housou Special Version)
(Japan) (Caravan Event Ban)
(Japan) (Caravan You Taikenban)
(Japan) (Demo)
(Japan) (En)
(Japan) (En) (Arcade) [b]
(Japan) (En) (Genteiban)
(Japan) (En) (NP)
(Japan) (En) (Proto 2)
(Japan) (En) (Proto 3)
(Japan) (En) (Proto)
(Japan) (En) (Putative Proto)
(Japan) (En) (Rev 1)
(Japan) (En) (v0.95) (Proto)
(Japan) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Japan) (En,Ja)
(Japan) (En,Ja) (NP)
(Japan) (Enhancement Chip)
(Japan) (HOT B)
(Japan) (Ja,Ko)
(Japan) (JR Nishi-Nihon Presents)
(Japan) (Keihin Ban)
(Japan) (NP)
(Japan) (Premium Box)
(Japan) (Proto 1)
(Japan) (Proto 4)
(Japan) (Proto)
(Japan) (Putative Beta)
(Japan) (Putative Sample) [b]
(Japan) (Renkaban)
(Japan) (Rev 1)
(Japan) (Rev 1) (NP)
(Japan) (Rev 2)
(Japan) (Rev 3)
(Japan) (Rev 4)
(Japan) (Rev 5)
(Japan) (Sample)
(Japan) (Shounen Jump no Shou)
(Japan) (TJAJ)
(Japan) (TJBJ)
(Japan) (TJCJ)
(Japan) (TJDJ)
(Japan) (TJEJ)
(Japan) (TOAJ)
(Japan) (TOBJ)
(Japan) (UCC Xaqua Version)
(Japan) (Unl)
(Japan) (Unl) [b]
(Japan, USA)
(Japan, USA) (Beta)
(Japan, USA) (En,Ja)
(Japan, USA) (Enhancement Chip)
(Japan, USA) (Rev 1)
(Korea)
(Mine Level) (Europe) (Proto)
(Netherlands)
(Palace Level) (Europe) (Proto)
(Spain)
(Sweden)
(USA)
(USA) (Alt 1) (Unl) [b]
(USA) (Arcade)
(USA) (Beta 1)
(USA) (Beta 1) [b]
(USA) (Beta 2)
(USA) (Beta 2) [b]
(USA) (Beta 3)
(USA) (Beta)
(USA) (Beta) (1993-07-30)
(USA) (Beta) (1994-xx-xx)
(USA) (Beta) (CES Version)
(USA) (Beta) [b]
(USA) (Demo)
(USA) (Doritos Promo)
(USA) (En,Es)
(USA) (En,Fr)
(USA) (En,Fr) (Beta)
(USA) (En,Fr) (Rev 1)
(USA) (En,Fr,De)
(USA) (En,Fr,De) (Proto) (1994-07-12)
(USA) (En,Fr,De,Es)
(USA) (En,Fr,De,Es) (Beta)
(USA) (En,Fr,De,Es,It)
(USA) (En,Fr,De,Es,It,Nl,Pt,Sv)
(USA) (En,Fr,De,Es,It,Pt,Sv,No)
(USA) (En,Fr,De,Es,It,Sv)
(USA) (En,Fr,De,Es,Pt) (Proto)
(USA) (En,Fr,De,It)
(USA) (En,Fr,De,It) (Beta)
(USA) (En,Fr,Es)
(USA) (En,Ja)
(USA) (Es)
(USA) (Proto 1)
(USA) (Proto 2)
(USA) (Proto)
(USA) (Proto) (1994-06-21 Level 11-G)
(USA) (Proto) (1994-06-21 Levels 000)
(USA) (Proto) (1994-06-22 Levels-B)
(USA) (Proto) (1995-02-16)
(USA) (Proto) [b]
(USA) (Rev 1)
(USA) (Rev 2)
(USA) (Rev D)
(USA) (Sample)
(USA) (Unl)
(USA) (Unl) [b]
(USA) (v2.0) (Unl)
(USA) [b]
(Woods Level) (Europe) (Proto)
(World) (Enhancement Chip)
(World) (Rev 2)
(World) (Unl) (Pirate)


PROCESS: C:\Games\No-Intro 2018\GCE - Vectrex
-------------------------------------------------------
Directory Exists: Continue Processing
Found 15 Potential Exceptions to Filter:
(Europe)
(USA)
(USA) (A00ED3D6)
(USA) (Beta)
(USA) (C10F37D8)
(USA) (Proto)
(USA) (Proto) (05838962)
(USA) (Proto) (DA1AC0DB)
(USA) (Rev 2)
(USA) (Rev 4) (Proto)
(USA) (Sample)
(USA, Europe)
(USA, Europe) (0F11CE0C)
(USA, Europe) (881B27C5)
(World)


PROCESS: C:\Games\No-Intro 2018\Nintendo - Virtual Boy
-------------------------------------------------------
Directory Exists: Continue Processing
Found 5 Potential Exceptions to Filter:
(Japan)
(Japan) (Proto)
(Japan, USA)
(Unknown) (Proto)
(USA)


PROCESS: C:\Games\No-Intro 2018\Bandai - WonderSwan
-------------------------------------------------------
Directory Exists: Continue Processing
Found 9 Potential Exceptions to Filter:
(Asia) (En)
(Asia) (En,Ja) (Rev 1)
(Japan)
(Japan) (En,Ja) (Rev 1)
(Japan) (Rev 1)
(Japan) (Rev 2)
(Japan) (Rev 3)
(Japan) (Rev 4)
(Japan) (Rev 5)


PROCESS: C:\Games\No-Intro 2018\Bandai - WonderSwan Color
-------------------------------------------------------
Directory Exists: Continue Processing
Found 10 Potential Exceptions to Filter:
(Asia) (En)
(Japan)
(Japan) (En,Ja)
(Japan) (Rev 1)
(Japan) (Rev 2)
(Japan) (Rev 4321)
(Japan) (Rev 5C21)
(Japan) (v1.1)
(Japan) (v1.5)
(Japan) (v1.6)


COMBINED UNIQUE EXCEPTIONS
-------------------------------------------------------
(^^; (Japan)
(A) (Korea) (Unl)
(Argentina) (Unl)
(Asia) (En)
(Asia) (En) (Mega Soft) (Unl)
(Asia) (En) (Unl)
(Asia) (En,Ja) (Rev 1)
(Asia) (Ja)
(Asia) (Ja) (Hacker) (Unl)
(Asia) (Ja) (Hwang Shinwei) (Unl)
(Asia) (Ja) (NTSC) (Unl)
(Asia) (Ja) (PAL) (Unl)
(Asia) (Ja) (RCM Group) (Unl)
(Asia) (Ja) (Sachen) (Unl)
(Asia) (Ja) (Unl)
(Asia) (Ja) (v1.00S)
(Asia) (Unl)
(Asia, Australia) (Unl)
(Australia)
(Australia) (31B-001, Sachen) (Unl)
(Australia) (Beta)
(Australia) (En,Fr,De)
(Australia) (HES) (Unl)
(Australia) (Proto)
(Australia) (SGB Enhanced)
(Australia) (SGB Enhanced) (GB Compatible)
(Australia) (Unl)
(B) (Korea) (Unl)
(Brazil)
(Brazil) (Alt 1)
(Brazil) (Beta)
(Brazil) (CCE, Gluk Video) (Unl)
(Brazil) (En,Es,Pt)
(Brazil) (En,Fr)
(Brazil) (En,Fr,De,Es,It,Pt,Sv,No)
(Brazil) (En,Fr,De,Es,It,Sv)
(Brazil) (Es,Pt)
(Brazil) (Program)
(Brazil) (Sample)
(Brazil) (Unl)
(Brazil) (Unl) (Pirate)
(Brazil, Korea)
(Bulletproof) (Japan)
(Bulletproof) (Japan) (Rev A)
(Bulletproof) (Japan) (Rev B)
(C) (Korea) (Unl)
(Canada)
(China)
(China) (DMG-601 CHN)
(China) (DMG-602 CHN)
(China) (DMG-603 CHN)
(China) (DMG-604 CHN)
(China) (DMG-605 CHN)
(China) (Li Cheng) (Unl)
(China) (Unl)
(China) (v1.3) (Unl)
(China) (v2.0) (Unl)
(Chuugaku 1-Nen) (Japan) (16kB) (SC-3000)
(Chuugaku 1-Nen) (Japan) (40kB) (SC-3000)
(Chuugaku 1-Nen) (Japan) (SC-3000)
(Chuugaku 2-Nen) (Japan) (16kB) (SC-3000)
(Chuugaku 2-Nen) (Japan) (40kB) (SC-3000)
(Chuugaku 2-Nen) (Japan) (SC-3000)
(D) (Korea) (Unl)
(Denmark)
(DMG-EM) (Europe)
(DMG-EM) (Japan)
(DMG-N5) (USA)
(DMG-N5) (USA) (Rev A)
(E) (Korea) (Unl)
(Europe)
(Europe) (1B-003, Sachen) (Unl)
(Europe) (4B-001, Sachen-Commin) (Unl)
(Europe) (4B-002, Sachen) (Unl)
(Europe) (4B-004, Sachen-Commin) (Unl)
(Europe) (4B-005, Sachen-Commin) (Unl)
(Europe) (4B-006, Sachen) (Unl)
(Europe) (4B-007, Sachen) (Unl)
(Europe) (4B-008, Sachen) (Unl)
(Europe) (4B-009, Sachen) (Unl)
(Europe) (Accolade)
(Europe) (Alt 1)
(Europe) (Alt 1) (Program) (Unl)
(Europe) (Alt 1) (Unl)
(Europe) (Alt 2)
(Europe) (Alt)
(Europe) (Alternate) (Unl)
(Europe) (Beta 1)
(Europe) (Beta 2)
(Europe) (Beta)
(Europe) (Beta) (1993-05-19)
(Europe) (Beta) (2005-07-13)
(Europe) (Beta) (2005-10-14)
(Europe) (Beta) (Earlier)
(Europe) (Beta) [b]
(Europe) (Converted from Tape)
(Europe) (Demo)
(Europe) (Demo) (Kiosk)
(Europe) (Demo) (Unl)
(Europe) (En,De)
(Europe) (En,De) (Rev 1)
(Europe) (En,De,Es)
(Europe) (En,De,Es,It)
(Europe) (En,De,Es,Nl)
(Europe) (En,De,It)
(Europe) (En,De,Sv,Fi)
(Europe) (En,Es)
(Europe) (En,Es) (SGB Enhanced)
(Europe) (En,Es,It)
(Europe) (En,Es,It) (Proto)
(Europe) (En,Es,It) (SGB Enhanced) (GB Compatible)
(Europe) (En,Es,It,Sv,Da)
(Europe) (En,Es,Nl)
(Europe) (En,Fr)
(Europe) (En,Fr) (Rev 1)
(Europe) (En,Fr,De)
(Europe) (En,Fr,De) (Beta)
(Europe) (En,Fr,De) (GB Compatible)
(Europe) (En,Fr,De) (Rev 1)
(Europe) (En,Fr,De) (Rev 1) (3DS Virtual Console) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De) (Rev A)
(Europe) (En,Fr,De) (SGB Enhanced)
(Europe) (En,Fr,De) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De) (Virtual Console)
(Europe) (En,Fr,De,Da)
(Europe) (En,Fr,De,Da+En,De)
(Europe) (En,Fr,De,Es)
(Europe) (En,Fr,De,Es) (Beta)
(Europe) (En,Fr,De,Es) (Beta) (SGB Enhanced)
(Europe) (En,Fr,De,Es) (Debug Version)
(Europe) (En,Fr,De,Es) (GB Compatible)
(Europe) (En,Fr,De,Es) (Proto)
(Europe) (En,Fr,De,Es) (Rev 1)
(Europe) (En,Fr,De,Es) (Rev A)
(Europe) (En,Fr,De,Es) (SGB Enhanced)
(Europe) (En,Fr,De,Es) (Unl)
(Europe) (En,Fr,De,Es) (Virtual Console)
(Europe) (En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It) (Alt)
(Europe) (En,Fr,De,Es,It) (Beta 1)
(Europe) (En,Fr,De,Es,It) (Beta 2)
(Europe) (En,Fr,De,Es,It) (Beta)
(Europe) (En,Fr,De,Es,It) (Beta) (11-09-2002)
(Europe) (En,Fr,De,Es,It) (Beta) (16-09-2002)
(Europe) (En,Fr,De,Es,It) (Destination Software)
(Europe) (En,Fr,De,Es,It) (GB Compatible)
(Europe) (En,Fr,De,Es,It) (Proto)
(Europe) (En,Fr,De,Es,It) (Proto) (1994-12-05)
(Europe) (En,Fr,De,Es,It) (Rev 1)
(Europe) (En,Fr,De,Es,It) (Rev 2)
(Europe) (En,Fr,De,Es,It) (Rumble Version) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De,Es,It) (Sample) (GB Compatible)
(Europe) (En,Fr,De,Es,It) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De,Es,It) (Unl)
(Europe) (En,Fr,De,Es,It) (v0.45.3) (Beta)
(Europe) (En,Fr,De,Es,It) (Virtual Console)
(Europe) (En,Fr,De,Es,It) (Vivendi)
(Europe) (En,Fr,De,Es,It) (Wii U Virtual Console)
(Europe) (En,Fr,De,Es,It,Da)
(Europe) (En,Fr,De,Es,It,Fi)
(Europe) (En,Fr,De,Es,It,Nl)
(Europe) (En,Fr,De,Es,It,Nl) (Beta)
(Europe) (En,Fr,De,Es,It,Nl) (Beta) [b]
(Europe) (En,Fr,De,Es,It,Nl) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl) (Rev 1)
(Europe) (En,Fr,De,Es,It,Nl) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl,Ca)
(Europe) (En,Fr,De,Es,It,Nl,Da)
(Europe) (En,Fr,De,Es,It,Nl,Pt)
(Europe) (En,Fr,De,Es,It,Nl,Pt) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Da)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv) (Rev 1)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi)
(Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi,Pl)
(Europe) (En,Fr,De,Es,It,Nl,Sv)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (AP9P) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (AX9P)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (Beta)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (GB Compatible)
(Europe) (En,Fr,De,Es,It,Nl,Sv) (Rev A)
(Europe) (En,Fr,De,Es,It,Nl,Sv,Da)
(Europe) (En,Fr,De,Es,It,Nl,Sv,Da+En)
(Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da)
(Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da,Fi)
(Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da,Fi) (Beta)
(Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,It,Nl,Sv,No,Da,Fi)
(Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,Nl)
(Europe) (En,Fr,De,Es,It,Pt)
(Europe) (En,Fr,De,Es,It,Pt) (Beta)
(Europe) (En,Fr,De,Es,It,Pt,Sv,No)
(Europe) (En,Fr,De,Es,It,Sv)
(Europe) (En,Fr,De,Es,It,Sv,Da)
(Europe) (En,Fr,De,Es,It,Sv,No,Da,Fi)
(Europe) (En,Fr,De,Es,It,Sv,No,Da,Fi) (Rev 2)
(Europe) (En,Fr,De,Es,It,Sv+En,Fr,De,Es,It)
(Europe) (En,Fr,De,Es,It+En)
(Europe) (En,Fr,De,Es,Nl)
(Europe) (En,Fr,De,Es,Nl) (GB Compatible)
(Europe) (En,Fr,De,Es,Nl) (Proto)
(Europe) (En,Fr,De,Es,Nl,Sv)
(Europe) (En,Fr,De,Es,Pt)
(Europe) (En,Fr,De,Es+En,Fr,De,Es,It,Nl)
(Europe) (En,Fr,De,It)
(Europe) (En,Fr,De,It) (Alt 1) (Unl)
(Europe) (En,Fr,De,It) (Beta)
(Europe) (En,Fr,De,It) (GB Compatible)
(Europe) (En,Fr,De,It) (Rev 1)
(Europe) (En,Fr,De,It) (SGB Enhanced) (GB Compatible)
(Europe) (En,Fr,De,It) (Unl)
(Europe) (En,Fr,De,It) (v3.1) (Unl)
(Europe) (En,Fr,De,It) (v3.3) (Unl)
(Europe) (En,Fr,De,It,Nl)
(Europe) (En,Fr,De,It,Nl,Sv)
(Europe) (En,Fr,De,It,Sv,No,Da,Fi)
(Europe) (En,Fr,De,It,Sv,No,Da,Fi) (Rev 1)
(Europe) (En,Fr,De,Nl)
(Europe) (En,Fr,De,Nl) (SGB Enhanced)
(Europe) (En,Fr,De+En)
(Europe) (En,Fr,De+En,Fr,De,Es)
(Europe) (En,Fr,De+En,Fr,De,Es,It)
(Europe) (En,Fr,Es)
(Europe) (En,Fr,Es,It)
(Europe) (En,Fr,Es,It) (Ubi Soft)
(Europe) (En,Fr,Es,It) (Zoo Digital)
(Europe) (En,Fr,Es,It,Nl,Pt,Da)
(Europe) (En,Fr,Es,It,Sv)
(Europe) (En,Fr,Es,Nl)
(Europe) (En,Fr,It)
(Europe) (En,Fr,Nl)
(Europe) (En,It)
(Europe) (En,It) (Proto)
(Europe) (En,It,Sv,No,Da)
(Europe) (En,Ja)
(Europe) (En,Ja,Fr,De)
(Europe) (En,Ja,Fr,De,Es)
(Europe) (En,Ja,Fr,De,Es,It)
(Europe) (En,Ja,Fr,De,Es,It) (Beta)
(Europe) (En,Ja,Fr,De,Es,It+En)
(Europe) (En,Ja,Fr,De,Es,It+En,Ja,Fr,De,Es)
(Europe) (En,Ja,Fr,De,Es+En,Ja,Fr,De,Es,It)
(Europe) (En,Nl,Sv,No,Da)
(Europe) (En,No,Da)
(Europe) (En,Pt,Pl) (Unl)
(Europe) (En,Sv,No,Da,Fi)
(Europe) (En+En,Es,It,Sv,Da)
(Europe) (En+En,Fr,De)
(Europe) (En+En,Fr,De,Es,It,Nl,Sv,Da)
(Europe) (En+En,Ja,Fr,De,Es)
(Europe) (En+En+En,Fr,De)
(Europe) (Es,It)
(Europe) (Es,It+En,Es,It,Sv,Da)
(Europe) (Es,Pt)
(Europe) (Fr,De)
(Europe) (Fr,De) (SGB Enhanced)
(Europe) (Fr,De,Es)
(Europe) (Fr,De,Es,It)
(Europe) (Fr,De,Es,It,Nl,Sv,Da)
(Europe) (Fr,De,Es,It,Sv)
(Europe) (Fr,De,Es,Nl)
(Europe) (Fr,De,Nl)
(Europe) (Fr,De,Pt)
(Europe) (Fr,Es)
(Europe) (Fr,It)
(Europe) (Fr,Nl)
(Europe) (Fr,Nl+Fr,De,Nl)
(Europe) (GameCube Edition)
(Europe) (GamesMaster Special Edition)
(Europe) (GB Compatible)
(Europe) (Gremlin Graphics)
(Europe) (Image Works)
(Europe) (It,Nl)
(Europe) (It,Sv) (Proto)
(Europe) (J-Cart)
(Europe) (Light Phaser)
(Europe) (Plug-Thru Cart) (Unl)
(Europe) (Program)
(Europe) (Program) (Unl)
(Europe) (Promo, Virtual Console)
(Europe) (Proto 1)
(Europe) (Proto 2)
(Europe) (Proto)
(Europe) (Proto) (10.07.1994)
(Europe) (Proto) (1994-04-12)
(Europe) (Proto) (No. 04)
(Europe) (Proto) (No. 14)
(Europe) (Proto) (Unl)
(Europe) (Proto) [b]
(Europe) (Putative Proto)
(Europe) (Requires MegaCD) (Program)
(Europe) (Rev 1)
(Europe) (Rev 2)
(Europe) (Rev A)
(Europe) (Rev A) (SGB Enhanced)
(Europe) (Rev B)
(Europe) (Rumble Version)
(Europe) (Sample)
(Europe) (SGB Enhanced)
(Europe) (SGB Enhanced) (GB Compatible)
(Europe) (Sv,No,Da,Fi)
(Europe) (Unl)
(Europe) (Unl) [b]
(Europe) (v1.0) (Unl)
(Europe) (v1.00)
(Europe) (v1.1) (J-Cart)
(Europe) (v1.1) (Unl)
(Europe) (v1.1) (Unl) [b]
(Europe) (v1.2) (Cart Present) (Unl)
(Europe) (v1.2) (No Cart Present) (Unl)
(Europe) (v1.6) (Unl)
(Europe) (v1.7) (Unl)
(Europe) (v2.0)
(Europe) (v2.00)
(Europe) (v2.00W)
(Europe) (v2.21X)
(Europe) (v3.0) (Unl)
(Europe) (v3.3) (Unl)
(Europe) (v3.6) (GBDSO) (Unl)
(Europe) (Virgin)
(Europe) (Virtual Console)
(Europe) (Wii U Virtual Console)
(Europe) (Wii Virtual Console)
(F) (Korea) (Unl)
(France)
(France) (Beta)
(France) (Beta) (1993-10-27)
(France) (En,Fr)
(France) (En,Fr,De,Es)
(France) (En,Fr,De,Es,It,Nl,Sv)
(France) (En,Fr,De,Es,It,Nl,Sv) (GB Compatible)
(France) (En,Fr,De+Fr)
(France) (En,Fr,It+Fr,Nl)
(France) (En,Fr,Nl)
(France) (Fr+En,Fr,De,Es,It)
(France) (Fr+En,Fr,De,Es,It,Nl,Sv,Da)
(France) (GB Compatible)
(France) (GBC,SGB Enhanced)
(France) (Proto)
(France) (Rev 1)
(France) (Rev A)
(France) (Rev A) (SGB Enhanced) (GB Compatible)
(France) (SGB Enhanced)
(France) (SGB Enhanced) (GB Compatible)
(Gensokigou Master) (Japan) (SC-3000)
(Germany)
(Germany) (Beta)
(Germany) (De+En,Fr,De,Es,It,Nl,Sv,Da)
(Germany) (De+Fr,De,Nl)
(Germany) (Debug Version)
(Germany) (En)
(Germany) (En,De)
(Germany) (En,De) (Rev 1)
(Germany) (En,Fr,De,Es)
(Germany) (En,Fr,De,Es,It,Nl,Sv) (GB Compatible)
(Germany) (En,Fr,De+De)
(Germany) (GB Compatible)
(Germany) (GBC,SGB Enhanced)
(Germany) (Proto)
(Germany) (Rev 1)
(Germany) (Rev A)
(Germany) (Rev A) (SGB Enhanced) (GB Compatible)
(Germany) (Rev B)
(Germany) (Sample)
(Germany) (SGB Enhanced)
(Germany) (SGB Enhanced) (GB Compatible)
(Germany) (v1.0) (GBD1) (Unl)
(Germany) (v1.067) (Unl)
(Hong Kong)
(Hong Kong) (Unl) [b]
(Italy)
(Italy) (En,Fr,It+Es,It)
(Italy) (Es,It+It)
(Italy) (GB Compatible)
(Italy) (GBC,SGB Enhanced)
(Italy) (It+En,Fr,De,Es,It,Nl,Sv,Da)
(Italy) (Proto)
(Italy) (Rev 1)
(Italy) (SGB Enhanced)
(Italy) (SGB Enhanced) (GB Compatible)
(Italy) (Unl)
(Japan)
(Japan) (1.00l)
(Japan) (1.00S)
(Japan) (16kB)
(Japan) (3DS Virtual Console)
(Japan) (40kB)
(Japan) (Activision)
(Japan) (All Star Version)
(Japan) (Alt 1)
(Japan) (Alt 1) (Unl)
(Japan) (Alt 1) (Unl) [b]
(Japan) (Alt 2)
(Japan) (Alt 3)
(Japan) (Alt 4)
(Japan) (Alt)
(Japan) (ArchiMENdes Hen)
(Japan) (Beta 1)
(Japan) (Beta 2)
(Japan) (Beta)
(Japan) (Beta) (06-02-2003)
(Japan) (Beta) (19-02-2003)
(Japan) (Beta) (1986-06-30)
(Japan) (Beta) (1992-12-21)
(Japan) (Beta) (1993-03-03)
(Japan) (Beta) (1993-11-27)
(Japan) (Beta) (Earlier)
(Japan) (Beta) (SGB Enhanced)
(Japan) (Beta) [b]
(Japan) (Bunka Housou Special Version)
(Japan) (Caravan Event Ban)
(Japan) (Caravan You Taikenban)
(Japan) (Debug Version)
(Japan) (Demo)
(Japan) (Demo) (Kiosk)
(Japan) (Demo) (Kiosk, GameCube)
(Japan) (Demo) (Promo)
(Japan) (Development Edition)
(Japan) (Disk 1) (Unl)
(Japan) (Disk 2) (Unl)
(Japan) (Disk Writer)
(Japan) (Disk Writer) [b]
(Japan) (DV 0)
(Japan) (DV 1)
(Japan) (DV 1) [b]
(Japan) (DV 10)
(Japan) (DV 2)
(Japan) (DV 2) (Disk Writer)
(Japan) (DV 2) [b]
(Japan) (DV 4) [b]
(Japan) (DV 5)
(Japan) (DV 5) (Disk Writer)
(Japan) (DV 6) [b]
(Japan) (DV 7)
(Japan) (DV 8) (Disk Writer)
(Japan) (En)
(Japan) (En) (3DS Virtual Console)
(Japan) (En) (Arcade) [b]
(Japan) (En) (Beta)
(Japan) (En) (Beta) (21.08.1989) (Sega Channel)
(Japan) (En) (Beta) (XX.XX.1989) (Sega Smash Pack)
(Japan) (En) (GB Compatible)
(Japan) (En) (Genteiban)
(Japan) (En) (NP)
(Japan) (En) (Promo, Wii U Virtual Console)
(Japan) (En) (Proto 2)
(Japan) (En) (Proto 3)
(Japan) (En) (Proto)
(Japan) (En) (Proto) (08.04.1994)
(Japan) (En) (Proto) (17.05.1994)
(Japan) (En) (Proto) [b]
(Japan) (En) (Putative Proto)
(Japan) (En) (Rev 1)
(Japan) (En) (Rev A)
(Japan) (En) (Rev B)
(Japan) (En) (Rumble Version)
(Japan) (En) (Sample)
(Japan) (En) (SDK 3.0)
(Japan) (En) (SGB Enhanced) (GB Compatible)
(Japan) (En) (Special Version)
(Japan) (En) (v0.95) (Proto)
(Japan) (En) (v1.00) (Sega)
(Japan) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Japan) (En,Fr,De,Es,It,Pt,Sv,No)
(Japan) (En,Ja)
(Japan) (En,Ja) (GB Compatible)
(Japan) (En,Ja) (NP)
(Japan) (En,Ja) (Rev 1)
(Japan) (En,Ja,Fr,De)
(Japan) (En,Ja,Fr,De,Es)
(Japan) (En,Ja,Fr,De,Es,It)
(Japan) (En,Ja,Fr,De,Es,It) (Rev 1)
(Japan) (En,Ja,Fr,De,Es+En,Ja)
(Japan) (En,Ja,Zh)
(Japan) (En,Ja+En,Ja,Fr,De,Es,It)
(Japan) (English Title)
(Japan) (Enhancement Chip)
(Japan) (FamicomBox)
(Japan) (FS-CA1) (Program)
(Japan) (GameCube Edition)
(Japan) (GB Compatible)
(Japan) (Genteiban!)
(Japan) (Gold Edition)
(Japan) (Hacker inc.) (Unl)
(Japan) (HAL Laboratory)
(Japan) (High Speed)
(Japan) (HOT B)
(Japan) (Hot Mario Campaign)
(Japan) (HX-MU900) (Program)
(Japan) (IE Institute)
(Japan) (Imagineer)
(Japan) (Ja,Ko)
(Japan) (JR Nishi-Nihon Presents)
(Japan) (Keihin Ban)
(Japan) (Launch Cart)
(Japan) (MyCard)
(Japan) (Namco)
(Japan) (National Tax Agency Demo)
(Japan) (NGA II) (Program)
(Japan) (NGA II) (Program) (Alt 1)
(Japan) (Nintendo Classic Mini Family Computer)
(Japan) (NP)
(Japan) (NP) (GB Compatible)
(Japan) (NP, SGB Enhanced) (GB Compatible)
(Japan) (Othello Multivision)
(Japan) (Premium Box)
(Japan) (Prize Card)
(Japan) (Program)
(Japan) (Program) (Alt 1)
(Japan) (Promo)
(Japan) (Promotion Card)
(Japan) (Proto 1)
(Japan) (Proto 4)
(Japan) (Proto)
(Japan) (Proto) (Dragon Layout)
(Japan) (Proto) (Ep-MyCard)
(Japan) (Proto) (Scorpion Layout)
(Japan) (Proto) [b]
(Japan) (Putative Beta)
(Japan) (Putative Sample) [b]
(Japan) (Renkaban)
(Japan) (Rev 0)
(Japan) (Rev 0A)
(Japan) (Rev 0B)
(Japan) (Rev 1)
(Japan) (Rev 1) (40kB)
(Japan) (Rev 1) (Disk Writer)
(Japan) (Rev 1) (Disk Writer) [b]
(Japan) (Rev 1) (GB Compatible)
(Japan) (Rev 1) (NP)
(Japan) (Rev 1) (Othello Multivision)
(Japan) (Rev 1) (SGB Enhanced)
(Japan) (Rev 1) (SGB Enhanced) (NP)
(Japan) (Rev 1) [b]
(Japan) (Rev 1.2)
(Japan) (Rev 1.4)
(Japan) (Rev 2)
(Japan) (Rev 2) (Developer Card)
(Japan) (Rev 2) (Disk Writer)
(Japan) (Rev 2) (SGB Enhanced)
(Japan) (Rev 3)
(Japan) (Rev 3) (SGB Enhanced)
(Japan) (Rev 3) [b]
(Japan) (Rev 4)
(Japan) (Rev 4321)
(Japan) (Rev 5)
(Japan) (Rev 5C21)
(Japan) (Rev A)
(Japan) (Rev A) (GB Compatible)
(Japan) (Rev A) (NP, SGB Enhanced) (GB Compatible)
(Japan) (Rev A) (Program)
(Japan) (Rev A) (SGB Enhanced)
(Japan) (Rev A) (SGB Enhanced) (GB Compatible)
(Japan) (Rev A) (Shindou Edition)
(Japan) (Rev AB)
(Japan) (Rev AB) (SGB Enhanced)
(Japan) (Rev B)
(Japan) (Rev B) (GB Compatible)
(Japan) (Rev B) (SGB Enhanced) (GB Compatible)
(Japan) (Rev B) (Shindou Edition)
(Japan) (Rev C)
(Japan) (Rumble Version)
(Japan) (Rumble Version) (SGB Enhanced) (GB Compatible)
(Japan) (Sample)
(Japan) (Sample) (Final Version)
(Japan) (SC-3000)
(Japan) (Sega Channel)
(Japan) (SegaNet)
(Japan) (SGB Enhanced)
(Japan) (SGB Enhanced) (GB Compatible)
(Japan) (Shounen Jump no Shou)
(Japan) (Special Version)
(Japan) (TJAJ)
(Japan) (TJBJ)
(Japan) (TJCJ)
(Japan) (TJDJ)
(Japan) (TJEJ)
(Japan) (TOAJ)
(Japan) (TOBJ)
(Japan) (UCC Xaqua Version)
(Japan) (Unl)
(Japan) (Unl) [b]
(Japan) (Unreleased)
(Japan) (v0.0) (Beta)
(Japan) (v1.0)
(Japan) (v1.0) (Othello Multivision)
(Japan) (v1.00P)
(Japan) (v1.02)
(Japan) (v1.03)
(Japan) (v1.04)
(Japan) (v1.1)
(Japan) (v1.1) (Program)
(Japan) (v1.2) (Program)
(Japan) (v1.5)
(Japan) (v1.6)
(Japan) (v2)
(Japan) (v2) (Alt 1)
(Japan) (v2.0)
(Japan) (v2.0) (Newer) (Othello Multivision)
(Japan) (v2.0) (Othello Multivision)
(Japan) (v2.00)
(Japan) (v2.00C)
(Japan) (v2.0a)
(Japan) (v2.1)
(Japan) (v2.1a)
(Japan) (v2.6) (Othello Multivision)
(Japan) (v2.7) (Othello Multivision)
(Japan) (v3.0)
(Japan) (vA) (16kB) (Othello Multivision)
(Japan) (vA) (40kB) (Othello Multivision)
(Japan) (vB) (Othello Multivision)
(Japan) (Victor)
(Japan) (Virtual Console)
(Japan) (Wii U Virtual Console)
(Japan) [b]
(Japan, Europe)
(Japan, Europe) (Alt 1)
(Japan, Europe) (Alt 2)
(Japan, Europe) (Alt 3)
(Japan, Europe) (Alt 4)
(Japan, Europe) (Alt)
(Japan, Europe) (Beta)
(Japan, Europe) (En,Fr,De,Es,It)
(Japan, Europe) (En,Ja)
(Japan, Europe) (En,Ja) (Demo)
(Japan, Europe) (En,Ja) (Rev A)
(Japan, Europe) (En,Ja) (Rev B)
(Japan, Europe) (Rev 1)
(Japan, Europe) (Rev 2)
(Japan, Europe) (Rev A)
(Japan, Europe) (v1.09)
(Japan, Europe) (v1.10)
(Japan, Korea)
(Japan, USA)
(Japan, USA) (Beta)
(Japan, USA) (Developer Cart)
(Japan, USA) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Japan, USA) (En,Fr,De,Es,It,Nl,Pt,Sv) (Rev A)
(Japan, USA) (En,Ja)
(Japan, USA) (Enhancement Chip)
(Japan, USA) (Rev 1)
(Japan, USA) (Rev A)
(Japan, USA) (Rev B)
(Japan, USA) (Rev C)
(Japan, USA) (SDK Build)
(Japan, USA) (SDK Build) (Set 1)
(Japan, USA) (SDK Build) (Set 2)
(Japan, USA) (SGB Enhanced)
(Ka) (Japan)
(Korea)
(Korea) (Alt 1)
(Korea) (Alt 1) (Unl)
(Korea) (Clover)
(Korea) (En,Fr,De,Es)
(Korea) (En,Fr,De,Es,It,Nl,Pt,Sv)
(Korea) (En,Ko)
(Korea) (Pirate)
(Korea) (Unl)
(Korea) (Unl) (Pirate)
(Mine Level) (Europe) (Proto)
(NES Test) (USA) (Rev 1)
(Netherlands)
(Netherlands) (En,Es,Nl+Fr,Nl)
(Netherlands) (En,Nl)
(Netherlands) (GB Compatible)
(Netherlands) (Program)
(Nicktoons) (USA)
(Palace Level) (Europe) (Proto)
(Racing) (USA) (En,Fr,De,Es,It)
(Reibun de Oboeru) Chuugaku Eitango 1132 (Japan)
(Reibun de Oboeru) Kyuukyoku no Kobun Tango (Japan)
(Russia) (Unl)
(Shougaku 4-Nen Ge) (Japan) (SC-3000)
(Shougaku 4-Nen Jou) (Japan) (16kB) (SC-3000)
(Shougaku 4-Nen Jou) (Japan) (40kB) (SC-3000)
(Shougaku 5-Nen Ge) (Japan) (SC-3000)
(Shougaku 5-Nen Jou) (Japan) (SC-3000)
(Shougaku 6-Nen Ge) (Japan) (SC-3000)
(Shougaku 6-Nen Jou) (Japan) (SC-3000)
(Soccer) (Europe) (En,Fr,De,Es,It)
(Spain)
(Spain) (Alt 1)
(Spain) (En,Es,Nl+Es,It)
(Spain) (Es,It+Es)
(Spain) (Es+En,Fr,De,Es,It)
(Spain) (Es+En,Fr,De,Es,It,Nl,Sv,Da)
(Spain) (GB Compatible)
(Spain) (GBC,SGB Enhanced)
(Spain) (Gluk Video) (Unl)
(Spain) (Promo)
(Spain) (Rev 1)
(Spain) (Rev 1) (Gluk Video) (Unl)
(Spain) (SGB Enhanced)
(Spain) (SGB Enhanced) (GB Compatible)
(Spain) (Unl)
(Sunsoft) (USA) (Proto)
(Sweden)
(Sweden) (Sv,Da,Fi)
(Taiwan)
(Taiwan) (1B-002, 4B-003, Sachen) (Unl)
(Taiwan) (31B-001, Sachen) (Unl)
(Taiwan) (Alt 1)
(Taiwan) (Alt 1) (Unl)
(Taiwan) (Alt) (Unl)
(Taiwan) (Chinese Logo)
(Taiwan) (DahJee)
(Taiwan) (En)
(Taiwan) (En) (1B-001, Sachen) (Unl)
(Taiwan) (En) (1B-004, EB-004, Sachen) (Unl)
(Taiwan) (En) (Sachen) (Unl)
(Taiwan) (En) (Unl)
(Taiwan) (En,Zh) (4B-003, Sachen-Commin) (Unl)
(Taiwan) (En,Zh) (6B-001, Sachen) (Unl)
(Taiwan) (English Logo)
(Taiwan) (Jumbo)
(Taiwan) (MSX)
(Taiwan) (No Logo)
(Taiwan) (Othello Multivision)
(Taiwan) (Simple Chinese) (Unl)
(Taiwan) (Unl)
(Taiwan) (Unl) [b]
(Unknown)
(Unknown) (Beta)
(Unknown) (Demo)
(Unknown) (Promo)
(Unknown) (Proto 1)
(Unknown) (Proto 1) (Unl)
(Unknown) (Proto 2)
(Unknown) (Proto 2) (Unl)
(Unknown) (Proto)
(Unknown) (Proto) (1993-09-24) (Unl)
(Unknown) (Proto) (2001)
(Unknown) (Proto) (2003)
(Unknown) (Proto) (early)
(Unknown) (Proto) (RAM) (Unl)
(Unknown) (Proto) (Unl)
(Unknown) (Sample)
(Unknown) (Unl)
(USA)
(USA) (02.03.1992) (Sega Channel)
(USA) (03.02.1992) (Sega Channel)
(USA) (13.03.1992) (Sega Channel)
(USA) (82-11-05) (Proto)
(USA) (83-10-31) (Proto)
(USA) (A00ED3D6)
(USA) (Acclaim) (Beta)
(USA) (Acclaim) (Beta) (Earlier)
(USA) (Advance Play Edition)
(USA) (Aladdin Compact Cartridge) (Unl)
(USA) (Alpha)
(USA) (Alt 1)
(USA) (Alt 1) (Unl)
(USA) (Alt 1) (Unl) [b]
(USA) (Arcade)
(USA) (Auto Demo)
(USA) (Beta 1)
(USA) (Beta 1) [b]
(USA) (Beta 2)
(USA) (Beta 2) [b]
(USA) (Beta 3)
(USA) (Beta)
(USA) (Beta) (13.12.1991) (Sega Channel)
(USA) (Beta) (16.01.1992) (Sega Channel)
(USA) (Beta) (1989)
(USA) (Beta) (1990-01-18)
(USA) (Beta) (1990-02-02)
(USA) (Beta) (1990-04-27)
(USA) (Beta) (1993-06-27)
(USA) (Beta) (1993-07-30)
(USA) (Beta) (1993-08-13)
(USA) (Beta) (1994-xx-xx)
(USA) (Beta) (1995-07-07)
(USA) (Beta) (2000-05-31)
(USA) (Beta) (2000-07-10)
(USA) (Beta) (Alt 1)
(USA) (Beta) (Between 1990-02-02 &amp; 1990-04-27, earlier)
(USA) (Beta) (Between 1990-02-02 &amp; 1990-04-27, later)
(USA) (Beta) (CES Version)
(USA) (Beta) (Earlier)
(USA) (Beta) (July 1994)
(USA) (Beta) (September 1994)
(USA) (Beta) (Unl)
(USA) (Beta) [b]
(USA) (C10F37D8)
(USA) (Debug Version)
(USA) (Demo)
(USA) (Demo) (Kiosk)
(USA) (Demo) (Kiosk, ECTS 2000)
(USA) (Demo) (Kiosk, GameCube)
(USA) (Destination Software)
(USA) (Doritos Promo)
(USA) (En,Es)
(USA) (En,Es) (GB Compatible)
(USA) (En,Fr)
(USA) (En,Fr) (Beta)
(USA) (En,Fr) (Rev 1)
(USA) (En,Fr) (Rev A)
(USA) (En,Fr,De)
(USA) (En,Fr,De) (GB Compatible)
(USA) (En,Fr,De) (Proto) (1994-07-12)
(USA) (En,Fr,De) (Rev A)
(USA) (En,Fr,De,Es)
(USA) (En,Fr,De,Es) (Beta)
(USA) (En,Fr,De,Es) (Unl)
(USA) (En,Fr,De,Es,It)
(USA) (En,Fr,De,Es,It) (GB Compatible)
(USA) (En,Fr,De,Es,It) (Rev 1)
(USA) (En,Fr,De,Es,It) (Rumble Version)
(USA) (En,Fr,De,Es,It) (SGB Enhanced) (GB Compatible)
(USA) (En,Fr,De,Es,It) (Virtual Console)
(USA) (En,Fr,De,Es,It,Da)
(USA) (En,Fr,De,Es,It,Nl)
(USA) (En,Fr,De,Es,It,Nl) (Beta)
(USA) (En,Fr,De,Es,It,Nl) (GB Compatible)
(USA) (En,Fr,De,Es,It,Nl) (Rev 1)
(USA) (En,Fr,De,Es,It,Nl,Pt,Da)
(USA) (En,Fr,De,Es,It,Nl,Pt,Sv)
(USA) (En,Fr,De,Es,It,Nl,Sv)
(USA) (En,Fr,De,Es,It,Nl,Sv,Da)
(USA) (En,Fr,De,Es,It,Nl,Sv,No,Da,Fi)
(USA) (En,Fr,De,Es,It,Pt,Sv,No)
(USA) (En,Fr,De,Es,It,Sv)
(USA) (En,Fr,De,Es,It,Sv,No,Da,Fi)
(USA) (En,Fr,De,Es,Pt) (Proto)
(USA) (En,Fr,De,It)
(USA) (En,Fr,De,It) (Beta)
(USA) (En,Fr,De+En)
(USA) (En,Fr,De+En,Fr,De,Es)
(USA) (En,Fr,Es)
(USA) (En,Fr,Es) (Beta)
(USA) (En,Fr,Es) (GB Compatible)
(USA) (En,Fr,Es) (Proto)
(USA) (En,Fr,Es) (SGB Enhanced) (GB Compatible)
(USA) (En,Fr,Es,Nl)
(USA) (En,Fr,Es,Pt)
(USA) (En,Fr,Es,Pt) (GB Compatible)
(USA) (En,Ja)
(USA) (En,Ja) (Rev C)
(USA) (En,Ja,Fr,De)
(USA) (En,Ja,Fr,De,Es)
(USA) (En,Ja,Fr,De,Es,It)
(USA) (En,Ja,Fr,De,Es+En,Ja,Fr,De,Es,It)
(USA) (Es)
(USA) (Fire Emblem GBA - Bonus Items)
(USA) (GameCube Edition)
(USA) (GameCube)
(USA) (GB Compatible)
(USA) (General Instrument) (Program)
(USA) (Ja) (Demo)
(USA) (Ja) (Proto)
(USA) (M404) (Proto)
(USA) (Majesco)
(USA) (Namco)
(USA) (Program)
(USA) (Promo)
(USA) (Proto 1)
(USA) (Proto 1) (Unl)
(USA) (Proto 2)
(USA) (Proto 2) (Unl)
(USA) (Proto 2) [b]
(USA) (Proto)
(USA) (Proto) (02.03.1992) (Sega Channel)
(USA) (Proto) (03.06.1994)
(USA) (Proto) (05838962)
(USA) (Proto) (06.06.1994)
(USA) (Proto) (11.08.1994)
(USA) (Proto) (1994-06-21 Level 11-G)
(USA) (Proto) (1994-06-21 Levels 000)
(USA) (Proto) (1994-06-22 Levels-B)
(USA) (Proto) (1995-02-16)
(USA) (Proto) (2000-04-19)
(USA) (Proto) (26.06.1990) (Sega Channel)
(USA) (Proto) (28.07.1994)
(USA) (Proto) (28.12.1991) (Sega Channel)
(USA) (Proto) (DA1AC0DB)
(USA) (Proto) (Earlier)
(USA) (Proto) (early)
(USA) (Proto) (GB Compatible)
(USA) (Proto) (SGB Enhanced) (GB Compatible)
(USA) (Proto) (Unl)
(USA) (Proto) [b]
(USA) (Rev 0A)
(USA) (Rev 1)
(USA) (Rev 1) (Unl)
(USA) (Rev 2)
(USA) (Rev 4) (Proto)
(USA) (Rev 5)
(USA) (Rev 6)
(USA) (Rev A)
(USA) (Rev A) (Beta) (25.09.1990) (Sega Channel)
(USA) (Rev A) (GameCube Edition)
(USA) (Rev A) (GB Compatible)
(USA) (Rev A) (Proto)
(USA) (Rev A) (SGB Enhanced)
(USA) (Rev A) (SGB Enhanced) (GB Compatible)
(USA) (Rev A) (Unl)
(USA) (Rev B)
(USA) (Rev B) (GameCube Edition)
(USA) (Rev B) (GB Compatible)
(USA) (Rev D)
(USA) (Rumble Version)
(USA) (Rumble Version) (SGB Enhanced) (GB Compatible)
(USA) (Sample)
(USA) (Sample) (NGen)
(USA) (Scientific Atlanta) (Program)
(USA) (SDK Build)
(USA) (Sega Smash Pack)
(USA) (SGB Enhanced)
(USA) (SGB Enhanced) (GB Compatible)
(USA) (Store Display Unit)
(USA) (Taito)
(USA) (Tengen)
(USA) (Tengen) (Unl)
(USA) (UBI Soft)
(USA) (Unl)
(USA) (Unl) [b]
(USA) (v0.14) (Beta)
(USA) (v0.924B) (Proto)
(USA) (v1.0) (Proto)
(USA) (v1.0) (Unl)
(USA) (v1.00)
(USA) (v1.02)
(USA) (v1.04)
(USA) (v1.1) (Unl)
(USA) (v1.10)
(USA) (v1.2) (Unl)
(USA) (v1.3) (Unl)
(USA) (v1.4) (Unl)
(USA) (v2.0)
(USA) (v2.0) (Proto)
(USA) (v2.0) (Unl)
(USA) (v2.00)
(USA) (v2.00W)
(USA) (v2.1) (Unl)
(USA) (v2.11X)
(USA) (v2.21X)
(USA) (v2.3)
(USA) (v3.0)
(USA) (v3.11.088) (Unl)
(USA) (v3.12.027) (Unl)
(USA) (v3.3) (Unl)
(USA) (v4.0) (Unl)
(USA) (v5.0) (Unl)
(USA) (v5.01.033) (Unl)
(USA) (v5.1) (Unl)
(USA) (v6.0) (Unl)
(USA) (v6.02.002) (Unl)
(USA) (v6.1) (Unl)
(USA) (v9.03.128) (Unl)
(USA) (Virtual Console)
(USA) (Vivendi)
(USA) (Wii U Virtual Console)
(USA) [b]
(USA, Asia) (Unl)
(USA, Australia)
(USA, Australia) (En,Fr,De,Es,It)
(USA, Australia) (Rev 1)
(USA, Australia) (Rev A) (Beta)
(USA, Europe)
(USA, Europe) (0F11CE0C)
(USA, Europe) (1.0) (J-Cart) (MDST17FF)
(USA, Europe) (1.1) (J-Cart) (MDST6636)
(USA, Europe) (1.2) (J-Cart) (MDSTEE13)
(USA, Europe) (881B27C5)
(USA, Europe) (Acclaim)
(USA, Europe) (Adam)
(USA, Europe) (Alt 1)
(USA, Europe) (Alt 2)
(USA, Europe) (Alt 3)
(USA, Europe) (Alt) (Unl)
(USA, Europe) (Beta 1)
(USA, Europe) (Beta 2)
(USA, Europe) (Beta 3)
(USA, Europe) (Beta)
(USA, Europe) (Beta) (SGB Enhanced)
(USA, Europe) (Demo)
(USA, Europe) (Easy Version)
(USA, Europe) (En,De)
(USA, Europe) (En,Fr,De)
(USA, Europe) (En,Fr,De) (Rev A) (SGB Enhanced)
(USA, Europe) (En,Fr,De) (SGB Enhanced) (GB Compatible)
(USA, Europe) (En,Fr,De,Es)
(USA, Europe) (En,Fr,De,Es) (GB Compatible)
(USA, Europe) (En,Fr,De,Es) (SGB Enhanced)
(USA, Europe) (En,Fr,De,Es,It)
(USA, Europe) (En,Fr,De,Es,It) (Beta)
(USA, Europe) (En,Fr,De,Es,It) (GB Compatible)
(USA, Europe) (En,Fr,De,Es,It) (Proto)
(USA, Europe) (En,Fr,De,Es,It) (Rumble Version)
(USA, Europe) (En,Fr,De,Es,It) (Sample)
(USA, Europe) (En,Fr,De,Es,It,Nl)
(USA, Europe) (En,Fr,De,Es,It,Nl,Da)
(USA, Europe) (En,Fr,De,Es,It,Nl,Pt,Sv)
(USA, Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,Da)
(USA, Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da)
(USA, Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi)
(USA, Europe) (En,Fr,De,Es,It,Nl,Sv)
(USA, Europe) (En,Fr,De,Es,It,Nl,Sv,Da)
(USA, Europe) (En,Fr,De,Es,It,Pt,Sv,No)
(USA, Europe) (En,Fr,De,Es,It,Sv)
(USA, Europe) (En,Fr,De,Es,Sv) (GB Compatible)
(USA, Europe) (En,Fr,De,Es,Sv) (Rev A) (GB Compatible)
(USA, Europe) (En,Fr,De,It)
(USA, Europe) (En,Fr,Es,It)
(USA, Europe) (En,Fr,It)
(USA, Europe) (En,Ja) (Virtual Console)
(USA, Europe) (En,Ja,Fr,De,Es)
(USA, Europe) (En,Ja,Fr,De,Es,Zh)
(USA, Europe) (GB Compatible)
(USA, Europe) (GBC,SGB Enhanced)
(USA, Europe) (Hard Version)
(USA, Europe) (Program)
(USA, Europe) (Rev 1)
(USA, Europe) (Rev 2)
(USA, Europe) (Rev 3)
(USA, Europe) (Rev A)
(USA, Europe) (Rev A) (Beta) (18.01.1991) (Sega Channel)
(USA, Europe) (Rev A) (Beta) (22.03.1990) (Sega Channel)
(USA, Europe) (Rev A) (Beta) (29.06.1993) (Sega Channel)
(USA, Europe) (Rev A) (GB Compatible)
(USA, Europe) (Rev A) (Program)
(USA, Europe) (Rev A) (SGB Enhanced)
(USA, Europe) (Rev A) (SGB Enhanced) (GB Compatible)
(USA, Europe) (Rev B)
(USA, Europe) (Rev B) (SGB Enhanced) (GB Compatible)
(USA, Europe) (Rev C)
(USA, Europe) (Rev D) (Virtual Console)
(USA, Europe) (Rumble Version)
(USA, Europe) (Sample)
(USA, Europe) (Sega Channel)
(USA, Europe) (Sega Smash Pack)
(USA, Europe) (SGB Enhanced)
(USA, Europe) (SGB Enhanced) (GB Compatible)
(USA, Europe) (Unl)
(USA, Europe) (v1.3)
(USA, Europe) (v2.0) (Beta)
(USA, Europe) (v2.4)
(USA, Europe) (v3.4)
(USA, Europe) (v4.4)
(USA, Europe) (Virtual Console)
(USA, Korea)
(Woods Level) (Europe) (Proto)
(World)
(World) (1B-002, 1B-003, Sachen) (Unl)
(World) (4B-001, 4B-009, 8B-001, Sachen) (Unl)
(World) (4B-002, 4B-004, 8B-002, Sachen) (Unl)
(World) (4B-005, 4B-006, 8B-003, Sachen) (Unl)
(World) (4B-007, 4B-008, 8B-004, Sachen) (Unl)
(World) (Auto Demo)
(World) (Beta 1)
(World) (Beta 2)
(World) (Beta)
(World) (Beta) (1999-10-22)
(World) (Beta) (Unl)
(World) (Demo)
(World) (En,Es,Pt) (Reprint B) (Unl)
(World) (En,Fr,De) (Reprint A) (Unl)
(World) (En,Fr,De) (Reprint) (Unl)
(World) (En,Fr,De,Es)
(World) (En,Fr,Es) (Unl)
(World) (En,Ja)
(World) (En,Ja) (Beta 1)
(World) (En,Ja) (Beta 2)
(World) (En,Ja) (Beta)
(World) (En,Ja) (Beta) (18.08.1989) (Sega Channel)
(World) (En,Ja) (Demo)
(World) (En,Ja) (Rev A)
(World) (En,Ja) (v1.05)
(World) (En,Ja) (v1.06)
(World) (En,Ja) (v1.11)
(World) (En,Ja) (v1.13)
(World) (Enhancement Chip)
(World) (GameCube Edition)
(World) (Ja)
(World) (Proto)
(World) (Rev 1)
(World) (Rev 1) (Beta)
(World) (Rev 1) (Sachen) (No Copyright) (Unl)
(World) (Rev 2)
(World) (Rev A)
(World) (Rev A) (Sega Channel)
(World) (Rev A) (SGB Enhanced)
(World) (Rev B) (GameCube Edition)
(World) (Rev B) (Sega Smash Pack)
(World) (Sega Channel)
(World) (Sega Smash Pack)
(World) (Sega)
(World) (SGB Enhanced) (GB Compatible)
(World) (Unl)
(World) (Unl) (Pirate)
(World) (V1.1) (Unl)
(Yi) (Asia) (Ja) (Unl)

As you can see from the output, there are some inconsistencies in the naming conventions such as (Rev 1) vs (Rev A) OR (Rev 1.2). However, we now have all of the necessary information to choose the ROMs we want to keep.

Phase 2: Create the No-Intro 2018 ROM Set Clean Up Scripts

The cleanup script is broken down into 4 main parts:

  1. Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set. We can use this list to determine which ROMs to keep and to keep count
  2. Remove Exceptions from the list based on the results from the Get-NoIntroExceptions.ps1 script. This will help speed up things up by reducing the # of ROMs we need to process
  3. Identify a Primary ROM to Keep and Remove Duplicates from the list based on the results from the Get-NoIntroExceptions.ps1 script
  4. Copy the No-Intro ROMs to keep from our list to a new directory

Since each game system varies on what I wanted to keep, I decided it would be best to create a separate script for each system based on the same template. This way, I could easily customize what I wanted per system. For example, Japan games on NES tend to be in Japanese but on the FDS they are in English. Below is the template used as well as an explanation on how to configure it followed by my customization for each system.

Clean-NoIntroRomsTemplate.ps1

For each system, you will want to customize the following:

  • $global:scriptDescription = What the script does
    • Ex: Cleanup Nintendo Entertainment System No-Intro 2018 ROMs
  • $global:romNoIntroDirectory = No-Intro 2018 Game System ROM Directory
    • Ex: C:\Games\No-Intro 2018\nes\
  • $global:romCleanDirectory = Directory to copy No-Intro ROMs to
    • Ex: C:\Games\RetroPie\nes\
  • $global:romsDoNotDelete = Add full name of any ROM to want to keep, even if it matches an exception or is not the primary ROM
    • Ex: Castlevania (USA) (Rev A).zip
  • $global:romsExceptions = Any ROM containing any of these will not be copied unless specified in “$global:romsDoNotDelete”
  • $global:romsSortOrder = When there is more than 1 version of a ROM, it uses this preferred matching order to determine the Primary ROM to keep. If it does not match anything, it will determine the Primary ROM as the first alphabetical result
#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = ""
$global:romNoIntroDirectory = ""
$global:romCleanDirectory = ""
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder 
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

atari2600.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Atari 2600 ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Atari - 2600"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\atari2600"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

atari5200.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Atari 5200 ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Atari - 5200"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\atari5200"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

atari7800.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Atari 7800 ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Atari - 7800 [Headered]"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\atari7800"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

atarilynx.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Atari Lynx ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Atari - Lynx [Headered]"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\atarilynx"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

coleco.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Colecovision ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Coleco - ColecoVision"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\coleco"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

fds.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Family Disk System ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Nintendo - Family Computer Disk System [headered]"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\fds"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
	"Bodycon Quest I - Abakareshi Musume Tachi (Japan) (Disk 1) (Unl).zip"
	,"Bodycon Quest I - Abakareshi Musume Tachi (Japan) (Disk 2) (Unl).zip"
	,"Kind Gal's (Japan) (Disk 1) (Unl).zip"
	,"Kind Gal's (Japan) (Disk 2) (Unl).zip"
	,"Tenshi Tachi no Houkago (Japan) (Disk 1) (Unl).zip"
	,"Tenshi Tachi no Houkago (Japan) (Disk 2) (Unl).zip"
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	#,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

gamegear.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Game Gear ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Sega - Game Gear"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\gamegear"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

gb.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Game Boy ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Nintendo - Game Boy"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\gb"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

gba.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Game Boy Advanced ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Nintendo - Game Boy Advance"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\gba"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
	"4 Games on One Game Pak (Nicktoons) (USA).zip"
	,"4 Games on One Game Pak (Racing) (USA) (En,Fr,De,Es,It).zip"
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
	,"Lilo &amp; Stitch 2 (Europe) (En,Fr,De,Es).zip"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

gbc.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Game Boy Color ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Nintendo - Game Boy Color"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\gbc"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

mastersystem.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Sega Master System ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Sega - Master System - Mark III"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\mastersystem"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

megadrive.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Sega Megadrive/Genesis ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Sega - Mega Drive - Genesis"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\megadrive"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

msx.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup MSX ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Microsoft - MSX"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\msx"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	#,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

n64.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Nintendo 64 ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Nintendo - Nintendo 64"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\n64"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

nes.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Nintendo Entertainment System ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Nintendo - Nintendo Entertainment System [headered]"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\nes"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

ngp.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Neo Geo Pocket ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\SNK - Neo Geo Pocket"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\ngp"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

ngpc.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Neo Geo Pocket Color ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\SNK - Neo Geo Pocket Color"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\ngpc"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
	"Puzzle Bobble Mini (Japan, Europe) (v1.09).zip"
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

pcengine.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup PC Engine/TurboGrafx 16 ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\NEC - PC Engine - TurboGrafx 16"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\pcengine"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	#,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

sega32x.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Sega 32X ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Sega - 32X"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\sega32x"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
"Mars Check Program Version 1.0 (Japan, USA) (SDK Build) (Set 2).zip"
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

sg-1000.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Sega SG-1000 ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Sega - SG-1000"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\sg-1000"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	#,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

snes.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Super Nintendo Entertainment System ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Nintendo - Super Nintendo Entertainment System"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\snes"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

vectrex.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Vectrex ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\GCE - Vectrex"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\vectrex"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

virtualboy.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Nintendo Virtual Boy ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Nintendo - Virtual Boy"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\virtualboy"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	#,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

wonderswan.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup WonderSwan ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Bandai - WonderSwan"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\wonderswan"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	#,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	#,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

wonderswancolor.ps1

#Global Variables
#- Modify: scriptVersion, scriptDescription, romNoIntroDirectory, romCleanDirectory
#- Add/Modify: romsDoNotDelete, romsExceptions, romSortOrder
$global:scriptVersion = "v4.0"
$global:scriptDescription = "Cleanup Wonderswan Color ROMs"
$global:romNoIntroDirectory = "C:\Games\No-Intro 2018\Bandai - WonderSwan Color"
$global:romCleanDirectory = "C:\Games\RetroPie\roms\wonderswancolor"
$global:romOverwriteFiles = $false
$global:scriptName = $MyInvocation.MyCommand.Name
$global:logFile = $MyInvocation.MyCommand.Name.Replace(".ps1",".txt")
$global:logOverwrite = $true
$global:logFullDetails = $false
$global:countTotal  = 0
$global:countUnique = 0
$global:countExceptionsDeleted = 0
$global:countDuplicatesDeleted = 0
$global:countNonDuplicatesDeleted = 0

#Any Exact ROM Name (Including Extension) In This List Will Not Be Deleted
#-ROMs listed here will NOT be deleted even if they match a value in romsExceptions
#-ROMs listed here will NOT be deleted if it's NOT the Primary ROM via romsSortOrder
#-Ex: "Castlevania (USA) (Rev A).zip"
$global:romsDoNotDelete = @(
)

#Any ROMs Containing These Strings Will Be Removed Unless the Exact ROM Name Is In romsDoNotDelete
$global:romsExceptions = @(
	"[BIOS]"
	,"[b]"
    ,"(Alpha)"
	,"(Beta)"
	,"(Beta 1)"
	,"(Beta 2)"
	,"(Beta 3)"
	,"(Proto)"
	,"(Proto 1)"
	,"(Proto 2)"
	,"(Promo)"
	,"(Sample)"
	,"(Debug Version)"
	,"(GameCube Edition)"
	,"(Promo, Virtual Console)"
	,"(Virtual Console)"
	,"(Wii Virtual Console)"
	,"(Wii U Virtual Console)"
	#,"(Asia)"
	,"(Australia)"
	,"(Brazil)"
	,"(Canada)"
	,"(China)"
	,"(France)"
	,"(Germany)"
	,"(Hong Kong)"
	,"(Italy)"
	#,"(Japan)"
	,"(Korea)"
	,"(Netherlands)"
	,"(Russia)"
	,"(Spain)"
	,"(Sweden)"
	,"(Taiwan)"
)

#Preferred Sorting Order to Pick 1 Primary ROM to Keep When Evaluating Duplicates
#-Order Selects Specific Names followed by more generalized names based around language
#-ROMs in romsExceptions will not be deleted even if it is not determined as the primary
#-Ex: "Joust (USA).zip" would be primary over "Joust (Japan).zip"
$global:romsSortOrder = @(
	#---------------------------------------
	#---USA PREFERRED ORDER---
	#---------------------------------------
	#(USA).zip
	"\(USA\)\.zip"
	#(USA) (Unl).zip
	,"\(USA\)\s*\(Unl\)\.zip"
	#(USA) (En,*).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA) (En,*) (Unl).zip
	,"\(USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Europe).zip
	,"\(USA,\s*Europe\)\.zip"
	#(USA, Europe) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(Unl\)\.zip"
	#(USA, Europe) (En,*).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Europe) (En,*) (Unl).zip
	,"\(USA,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, USA).zip
	,"\(Japan,\s*USA\)\.zip"
	#(Japan, USA) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(Unl\)\.zip"
	#(Japan, USA) (En,*).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, USA) (En,*) (Unl).zip
	,"\(Japan,\s*USA\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, USA) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*USA\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Asia).zip
	,"\(USA,\s*Asia\)\.zip"
	#(USA, Asia) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(Unl\)\.zip"
	#(USA, Asia) (En,*).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Asia) (En,*) (Unl).zip
	,"\(USA,\s*Asia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Asia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Asia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"	
	#(USA, Australia).zip
	,"\(USA,\s*Australia\)\.zip"
	#(USA, Australia) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(Unl\)\.zip"
	#(USA, Australia) (En,*).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Australia) (En,*) (Unl).zip
	,"\(USA,\s*Australia\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Australia) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Australia\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA, Korea).zip
	,"\(USA,\s*Korea\)\.zip"
	#(USA, Korea) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(Unl\)\.zip"
	#(USA, Korea) (En,*).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(USA, Korea) (En,*) (Unl).zip
	,"\(USA,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(USA, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(USA,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(USA) (Rev #)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(USA) (Rev A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(USA) (Rev #A)
	,"^(?=.*?\(USA\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(USA) (Alt) OR (Alternate)
	,"^(?=.*?\(USA\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(USA) (Alt #)
	,"^(?=.*?\(USA\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(USA)
	,"\(USA\)"
	#(USA, Europe)
	,"\(USA,\s*Europe\)"
	#(Japan, USA)
	,"\(Japan,\s*USA\)"
	#(USA, Asia)
	,"\(USA,\s*Asia\)"
	#(USA, Australia)
	,"\(USA,\s*Australia\)"
	#(USA, Korea)
	,"\(USA,\s*Korea\)"	
	#(*USA*)
	,"\((.*?)USA(.*?)\)"
	#---------------------------------------
	#---WORLD PREFERRED ORDER---
	#---------------------------------------
	#(World).zip
	"\(World\)\.zip"
	#(World) (Unl).zip
	,"\(World\)\s*\(Unl\)\.zip"
	#(World) (En,*).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(World) (En,*) (Unl).zip
	,"\(World\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(World) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(World\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(World) (Rev #)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(World) (Rev A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(World) (Rev #A)
	,"^(?=.*?\(World\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(World) (Alt) OR (Alternate)
	,"^(?=.*?\(World\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(World) (Alt #)
	,"^(?=.*?\(World\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(World)
	,"\(World\)"
	#(*World*)
	,"\((.*?)World(.*?)\)"
	#---------------------------------------
	#---EUROPE PREFERRED ORDER---
	#---------------------------------------
	#(Europe).zip
	"\(Europe\)\.zip"
	#(Europe) (Unl).zip
	,"\(Europe\)\s*\(Unl\)\.zip"
	#(Europe) (En,*).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Europe) (En,*) (Unl).zip
	,"\(Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Europe).zip
	,"\(Japan,\s*Europe\)\.zip"
	#(Japan, Europe) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(Unl\)\.zip"
	#(Japan, Europe) (En,*).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Europe) (En,*) (Unl).zip
	,"\(Japan,\s*Europe\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Europe) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Europe\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Europe) (Rev #)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Europe) (Rev A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Europe) (Rev #A)
	,"^(?=.*?\(Europe\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Europe) (Alt) OR (Alternate)
	,"^(?=.*?\(Europe\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Europe) (Alt #)
	,"^(?=.*?\(Europe\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Europe)
	,"\(Europe\)"
	#(*Europe*)
	,"\((.*?)Europe(.*?)\)"
	#---------------------------------------
	#---JAPAN PREFERRED ORDER---
	#---------------------------------------
	#(Japan).zip
	"\(Japan\)\.zip"
	#(Japan) (Unl).zip
	,"\(Japan\)\s*\(Unl\)\.zip"
	#(Japan) (En,*).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan) (En,*) (Unl).zip
	,"\(Japan\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan, Korea).zip
	,"\(Japan,\s*Korea\)\.zip"
	#(Japan, Korea) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(Unl\)\.zip"
	#(Japan, Korea) (En,*).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\.zip"
	#(Japan, Korea) (En,*) (Unl).zip
	,"\(Japan,\s*Korea\)\s*\(En(,|\+|Ca|Da|De|En|Es|Fi|Fr|It|Ja|Nl|No|Pl|Pt|Sv|Zh)*?\)\s*\(Unl\)\.zip"
	#(Japan, Korea) <Anything Except (Alt ) or (Rev ) or (Demo)>.zip
	,"^(?=.*?\(Japan,\s*Korea\))((?!\(Alt\s*[A-Z0-9]{0,2}\)|\(Rev\s*[A-Z0-9\.]{0,4}\)|\(Demo\)).)*$"
	#(Japan) (Rev #)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[0-9\.]{0,4}\)).*$"
	#(Japan) (Rev A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z]{0,4}\)).*$"
	#(Japan) (Rev #A)
	,"^(?=.*?\(Japan\))(?=.*?\(Rev\s*[A-Z0-9\.]{0,4}\)).*$"
	#(Japan) (Alt) OR (Alternate)
	,"^(?=.*?\(Japan\))(?=.*?(\(Alt\)|\(Alternate\))).*$"
	#(Japan) (Alt #)
	,"^(?=.*?\(Japan\))(?=.*?\(Alt\s*[A-Z0-9]{1,2}\)).*$"
	#(Japan)
	,"\(Japan\)"
	#(*Japan*)
	,"\((.*?)Japan(.*?)\)"
	#---------------------------------------
	#---ALL ELSE FAILED PREFERRED ORDER---
	#---------------------------------------
	#(Unknown)
	,"\(Unknown\)"
)



Function Main()
{
	#Create Log File
	If ($global:logOverwrite -eq $true)
	{
		Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Else 
	{
			Log-Write "Green" $global:logFile ("****************************************************************") $true
	}
	Log-Write "Green" $global:logFile ("SECTION 1: STARTING SCRIPT:") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "DarkGreen" $global:logFile ("Name                    : $($global:scriptName)") $false 
	Log-Write "DarkGreen" $global:logFile ("Version                 : $($global:scriptVersion)") $false
	Log-Write "DarkGreen" $global:logFile ("Description             : $($global:scriptDescription)") $false
	$timeStart = (Get-Date)
	Log-Write "DarkGreen" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Source Dir          : $($global:romNoIntroDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("ROM Clean  Dir          : $($global:romCleanDirectory)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Existing ROMs : $($global:romOverwriteFiles)") $false
	Log-Write "DarkGreen" $global:logFile ("Log File                : $($global:logFile)") $false
	Log-Write "DarkGreen" $global:logFile ("Overwrite Log File      : $($global:logOverwrite)") $false
	If(!(Test-Path -LiteralPath $global:romNoIntroDirectory))
	{
		Log-Write "Red" $global:logFile ("ERROR: ROM Source Directory Does Not Exist - Quitting Script!") $false
		Exit
	}
	
	
	
	#Get List of ROMs and Unique ROMs in the original No-Intro 2018 ROM set
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 2: GET ALL NO-INTRO ROMs and UNIQUE ROMs TO PROCESS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	[System.Collections.ArrayList]$colRoms = @()
	(Get-ChildItem -LiteralPath $global:romNoIntroDirectory).ForEach({$obj = [PSCustomObject]@{ FullName = $_.FullName; Name = $_.Name};$colRoms.add($obj)|out-null})
	$colUniqueRoms = @()
	$colRoms | ForEach-Object `
	{
		$colUniqueRoms += $_.Name.split("(")[0]
	}
	$colUniqueRoms = $colUniqueRoms | Sort -Unique
	#Count Total Original Source ROMs and Original Source Unique ROMs
	$global:countTotal = $colRoms.count
	$global:countUnique = $colUniqueRoms.count
	Log-Write "DarkGreen" $global:logFile ("Total ROMs: $($global:countTotal)") $false
	Log-Write "DarkGreen" $global:logFile ("Total Unique ROMs: $($global:countUnique)") $false



	#Remove Exceptions - Further Speeds Things Up By Not Having to Process As Much
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 3: REMOVE EXCEPTIONS") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	For ($i=0; $i -lt $colRoms.Count; $i++)
	{
		ForEach ($romException in $global:romsExceptions) 
		{
			#Check If Current ROM Matches Exception
			If ($colRoms[$i].Name -match [regex]::escape($romException))
			{
				#Exception Found (Flag Delete)
				#Special Case Do Not Delete ROMs Check
				$romDND = $false
				If ($global:romsDoNotDelete.Count -gt 0)
				{
					ForEach ($doNotDelete in $global:romsDoNotDelete)
					{
						If ($doNotDelete -eq $_.Name)
						{
							#Found Special Case (Flag NOT Delete)
							$romDND = $true
							break
						}
					}
				}
				#Check to Delete or Not
				If ($romDND -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTON (Special Case): $($colRoms[$i].Name)") $false
				}
				Else
				{
					#Delete ROM
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colRoms[$i].Name)") $false
					$colRoms.RemoveAt($i)
					$i--
					$global:countExceptionsDeleted++
				}
				break
			}
		}
	}
	
	
	
	#Identify Primary ROM to Keep and Remove Duplicates
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 4: IDENTIFY PRIMARY ROM AND REMOVE DUPLICATES") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	ForEach ($uniqueRom in $colUniqueRoms)
	{
		#Determine Duplicates For Each Unique ROM Name
		$colDuplicateRoms = @()
		$colDuplicateRoms = $colRoms.Name -match ("^"+[regex]::escape($uniqueRom)+"\(")
		Log-Write "Green" $global:logFile ("PROCESS: '$($uniqueRom)'") $false
		If ($colDuplicateRoms.count -gt 1)
		{
			#Determine Primary ROM In Each Duplicate ROM Set By Matching Sorting Preference
			:regloop ForEach ($sortRegex in $global:romsSortOrder )
			{
				#Process ROMS That Match A Sorting Order
				$primaryRom = ""
				$colRomsToSort = @()
				[array]$colRomsToSort = $colDuplicateRoms -match $sortRegex
				$colRomsToSort = $colRomsToSort | sort
				If ($colRomsToSort.count -ge 1)
				{
					#Find Primary ROM To Keep
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("TEST REGEX ($($colRomsToSort.count) Matches): $($sortRegex)") $false
					}
					For($i = $colRomsToSort.GetLowerBound(0); $i -le $colRomsToSort.GetUpperBound(0); $i++) 
					{
						$matchRomException = $false
						If ($global:logFullDetails -eq $true)
						{
							Log-Write "DarkGreen" $global:logFile ("Primary ROM Found (Match $($i + 1) of $($colRomsToSort.GetUpperBound(0) + 1)): $($colRomsToSort[$i])") $false
						}
						#Check Primary ROM For Exceptions
						ForEach ($romException in $global:romsExceptions) 
						{
							If ($colRomsToSort[$i] -match [regex]::escape($romException))
							{
								$matchRomException = $true
								If ($global:logFullDetails -eq $true)
								{
									Log-Write "DarkGreen" $global:logFile ("Primary ROM Exception Found (Match $($i+1) of $($colRomsToSort.count): $($romException)") $false
								}
								break
							}
						}
						#Set Primary ROM 
						If ($matchRomException -eq $false)
						{
							$primaryRom = $colRomsToSort[$i]
							break regloop
						}
					}
				}
				Else 
				{
					If ($global:logFullDetails -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Matches): $($sortRegex)") $false
					}
				}
			}
			
			#Display Primary ROM Result
			If ($primaryRom -eq "")
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: No Primary Found!") $false
				}
			}
			Else
			{
				If ($global:logFullDetails -eq $true)
				{
					Log-Write "DarkGreen" $global:logFile ("Primary ROM Set: $($primaryRom)") $false
				}
			}
			
			#Remove All Duplicate ROMS Except Primary ROM
			ForEach ($duplicateRom in $colDuplicateRoms)
			{
				#Primary ROM Found
				If ($duplicateRom -eq $primaryRom)
				{
					#Keep Primary ROM
					Log-Write "DarkGreen" $global:logFile ("KEEP(Primary): $($duplicateRom)") $false
				}
				Else
				{
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $duplicateRom)
							{
								$romDND = $true
								break
							}
						}
					}
					
					If ($romDND -eq $true)
					{
						Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE (Special Case): $($duplicateRom)") $false
					}
					Else 
					{
						If ($primaryRom -eq "")
						{
							#No Primary Found Delete Duplicate
							Log-Write "DarkRed" $global:logFile ("DELETE(No Primary Found): $($duplicateRom)") $false
						}
						Else
						{
							#Not The Primary ROM Delete Duplicate Or Exception
							Log-Write "DarkRed" $global:logFile ("DELETE(Duplicate/Exception): $($duplicateRom)") $false
						}					
						#Delete ROM
						For ($i=0; $i -lt $colRoms.Count; $i++)
						{
							If ($colRoms[$i].Name -eq $duplicateRom)
							{
								$colRoms.RemoveAt($i)
								$i--
							}
						}
						$global:countDuplicatesDeleted++
					}
				}			
			}
		}
		Else 
		{
			#NOTE - $colDuplicateRoms acts as a variable (type=object) because there's a single item in the array!
			#Non-Duplicate ROM Primary By Default
			If ($global:logFullDetails -eq $true)
			{
				Log-Write "DarkGreen" $global:logFile ("SKIP REGEX (No Duplicates): ") $false
				Log-Write "DarkGreen" $global:logFile ("Primary ROM Set (Non-Duplicate): $($colDuplicateRoms)") $false
			}
			#Check Primary ROM For Exceptions
			$matchRomException = $false
			ForEach ($romException in $global:romsExceptions) 
			{
				#Check If Current ROM Matches Exception
				If ($colDuplicateRoms -match [regex]::escape($romException))
				{
					#Exception Found (Flag Delete)
					$matchRomException = $true
					#Special Case Do Not Delete ROMs Check
					$romDND = $false
					If ($global:romsDoNotDelete.Count -gt 0)
					{
						ForEach ($doNotDelete in $global:romsDoNotDelete)
						{
							If ($doNotDelete -eq $colDuplicateRoms)
							{
								#Found Special Case (Flag NOT Delete)
								$romDND = $true
								break
							}
						}
					}
					break
				}
			}
			#Check to Delete or Not 
			If ($matchRomException -eq $false)
			{
				Log-Write "DarkGreen" $global:logFile ("KEEP(Primary Non-Duplicate): $($colDuplicateRoms.Name)") $false
			}
			Else 
			{
				#Delete
				If ($romDND -eq $true)
				{
					#Special Case Keep
					Log-Write "DarkGreen" $global:logFile ("DO NOT DELETE EXCEPTION (Special Case): $($colDuplicateRoms.Name)") $false
				}
				Else 
				{
					#Delete ROM 
					Log-Write "DarkRed" $global:logFile ("DELETE EXCEPTION '$($romException)': $($colDuplicateRoms.Name)") $false
					For ($i=0; $i -lt $colRoms.Count; $i++)
					{
						If ($colRoms[$i].Name -eq $duplicateRom)
						{
							$colRoms.RemoveAt($i)
							$i--
						}
					}
				}
			}
		}
	}
	
	
	#Copy NoIntro ROMs
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 5: COPY NOINTRO ROMs") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	#Process Current ROM Directory
	Log-Write "Green" $global:logFile ("PROCESS $(Split-Path $global:romNoIntroDirectory -Leaf) ($(Split-Path $global:romCleanDirectory -Leaf))") $false
	Log-Write "Green" $global:logFile ("-------------------------------------------------------") $false
	#Confirm Source ROM Directory Exists
	If (Test-Path -LiteralPath $global:romNoIntroDirectory)
	{
		Log-Write "DarkGreen" $global:logFile ("Source Exist: '$($global:romNoIntroDirectory)'") $false
		
		#Confirm Destination Directory NOT Exists
		If (Test-Path -LiteralPath $global:romCleanDirectory)
		{
			#Destination Directory Exists - Overwrite?
			If ($global:romOverwriteFiles -eq $true)
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)*' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}				
			}
			Else 
			{
				Log-Write "Yellow" $global:logFile ("Destination EXIST (Do Not Overwrite): '$($global:romCleanDirectory)'") $false
				Log-Write "Yellow" $global:logFile ("No Files Copied!'") $false
			}
		}
		Else 
		{
			Log-Write "DarkGreen" $global:logFile ("Destination Not Exist: '$($global:romCleanDirectory)'") $false
			Log-Write "DarkGreen" $global:logFile ("Create Folder: '$($global:romCleanDirectory)'") $false
			If (New-Item -ItemType Directory -Path $global:romCleanDirectory -Force)
			{
				Log-Write "DarkGreen" $global:logFile ("Copy $($colRoms.count) ROMs from '$($global:romNoIntroDirectory)' to '$($global:romCleanDirectory)'") $false
				ForEach ($rom in $colRoms)
				{
					Copy-Item -LiteralPath $rom.FullName -Destination $global:romCleanDirectory -Recurse -Force
				}
			}
			Else 
			{
				Log-Write "Red" $global:logFile ("ERROR Creating Destination No ROMs Copied!") $false
			}
		}
	}
	Else
	{
		Log-Write "Red" $global:logFile ("Source NOT Exist: '$($global:romNoIntroDirectory)'") $false
		Log-Write "Red" $global:logFile ("ERROR CANNOT COPY!!!") $false
	}
	Log-Write "White" $global:logFile ("`n") $false



	#Finish Script
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "Green" $global:logFile ("SECTION 6: FINISH SCRIPT") $false
	Log-Write "Green" $global:logFile ("****************************************************************") $false
	Log-Write "White" $global:logFile ("ROMs TOTAL              : $($global:countTotal)") $false
	Log-Write "White" $global:logFile ("ROMs UNIQUE             : $($global:countUnique)") $false
	Log-Write "White" $global:logFile ("ROMs Exceptions Deleted : $($global:countExceptionsDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Dups Deleted       : $($global:countDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Non-Dup Deleted    : $($global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total Deleted      : $($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted)") $false
	Log-Write "White" $global:logFile ("ROMs Total After Clean  : $($global:countTotal - ($global:countExceptionsDeleted + $global:countDuplicatesDeleted + $global:countNonDuplicatesDeleted))") $false
	Log-Write "White" $global:logFile ("Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeStart)") $false
	$timeEnd = (Get-Date)
	Log-Write "White" $global:logFile ("End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $timeEnd)") $false
	Log-Write "White" $global:logFile ("Elapsed Time            : $([math]::Round(($timeEnd-$timeStart).totalseconds, 2)) seconds") $false
}





Function Log-Write
{
<#
.SYNOPSIS
Writes to a log file
 
.DESCRIPTION
Appends a new line to the end of the specified log file
.PARAMETER LogPath
Mandatory. Full path of the log file you want to write to. Example: C:\Windows\Temp\Test_Script.log
.PARAMETER LineValue
Mandatory. The string that you want to write to the log
.INPUTS
Parameters above
 
.OUTPUTS
None
 
.NOTES
Version: 1.0
Author: Luca Sturlese
Creation Date: 10/05/12
Purpose/Change: Initial function development
Version: 1.1
Author: Luca Sturlese
Creation Date: 19/05/12
Purpose/Change: Added debug mode support
 
.EXAMPLE
Log-Write -LogPath "C:\Windows\Temp\Test_Script.log" -LineValue "This is a new line which I am appending to the end of the log file."
#>
[CmdletBinding()]
Param 
(
	[Parameter(Mandatory=$false)]
	[string]$ConsoleColor,
	[Parameter(Mandatory=$true)]
	[string]$LogPath,
	[Parameter(Mandatory=$true)]
	[string]$LineValue,
	[Parameter()]
	[bool]$OverwriteFile = $false
)
Process
{
	if(!(Test-Path -Path $LogPath))
	{
		#Create New File If Does Not Exist
		New-Item -Path $LogPath -type file -force -Value $LineValue`r`n
	}
	else
	{
		if($OverwriteFile -eq $true)
		{
			#Overwrite Log File
			Set-Content -Path $LogPath -Value $LineValue
		}
		else
		{
			#Append Log File
			Try {
				Add-Content -Path $LogPath -Value $LineValue -ErrorAction Stop
			} Catch {
				Start-Sleep -s 3
				Add-Content -Path $LogPath -Value $LineValue
			}
		}
	}
	#Write to screen for debug mode
	#Write-Debug $LineValue
	If ($ConsoleColor)
	{
		Write-Host -ForegroundColor $ConsoleColor $lineValue
	}
	Else 
	{
		Write-Host $lineValue
	}
}
}



Main

Phase 3: Putting the Scripts Together

Use the below script to run all of the clean up scripts for each system. Also for convenience, you can download all of the scripts below as well.

http://sigkillit.com/wp-content/uploads/2019/06/Clean-NoIntro2018.zip

Clean-NoIntroRoms.ps1

$tStart = (Get-Date)
$global:scriptPath = $MyInvocation.MyCommand.Path.Replace($MyInvocation.MyCommand.Name,"")
$global:romCleanDirectory = "C:\Games\RetroPie\roms\"
$global:romCleanupScripts = @(
	"atari2600.ps1"
	,"atari5200.ps1"
	,"atari7800.ps1"
	,"atarilynx.ps1"
	,"coleco.ps1"
	,"fds.ps1"
	,"gamegear.ps1"
	,"gb.ps1"
	,"gba.ps1"
	,"gbc.ps1"
	,"mastersystem.ps1"
	,"megadrive.ps1"
	,"msx.ps1"
	,"n64.ps1"
	,"nes.ps1"
	,"ngp.ps1"
	,"ngpc.ps1"
	,"pcengine.ps1"
	,"sega32x.ps1"
	,"sg-1000.ps1"
	,"snes.ps1"
	,"vectrex.ps1"
	,"virtualboy.ps1"
	,"wonderswan.ps1"
	,"wonderswancolor.ps1"
)
ForEach ($cleanupScript in $global:romCleanupScripts)
{
	powershell -Command "&amp; '$($global:scriptPath)$($cleanupScript)'"
}
#Unzip N64 ROMs BC .zip Is Not Supported by Default
$colN64Roms = Get-ChildItem -Path "$($global:romCleanDirectory)n64\"
ForEach ($n64Rom in $colN64Roms)
{
	Write-Host $n64Rom.FullName
	Expand-Archive "$($n64Rom.FullName)" -DestinationPath "$($global:romCleanDirectory)n64\" -Force
}
#Delete N64 .zip ROMs
$colN64Roms = Get-ChildItem -Path "$($global:romCleanDirectory)n64\" -Filter "*.zip"
ForEach ($n64Rom in $colN64Roms)
{
	Remove-Item -LiteralPath $n64Rom.FullName -Force
}
$tEnd = (Get-Date)
Write-Host "Start Time              : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $tStart)"
Write-Host "End Time                : $("{0:MM/dd/yy} {0:HH:mm:ss}" -f $tEnd)"
Write-Host "Elapsed Time            : $([math]::Round(($tEnd-$tStart).totalseconds, 2)) seconds"

CompareFolders.ps1
Bonus Script: if you want to test modifying the exceptions or sort order, this script allows you to compare differences of files in 2 folders.

#Global Variables
$romsPath = "C:\Games\RetroPie\roms\"
$roms1Path = "C:\Games\RetroPie\roms1\"
$romsSystems = @(
	"atari2600"
	,"atari5200"
	,"atari7800"
	,"atarilynx"
	,"coleco"
	,"fds"
	,"gamegear"
	,"gb"
	,"gba"
	,"gbc"
	,"mastersystem"
	,"megadrive"
	,"msx"
	,"n64"
	,"nes"
	,"ngp"
	,"ngpc"
	,"pcengine"
	,"sega32x"
	,"sg-1000"
	,"snes"
	,"vectrex"
	,"virtualboy"
	,"wonderswan"
	,"wonderswancolor"
)
ForEach ($romSystem in $romsSystems)
{
	Write-Host -Foregroundcolor "Green" "PROCCESSING ($($romSystem)): $($romsPath | Split-Path -Leaf) :: $($roms1Path | Split-Path -Leaf)"
	Write-Host -Foregroundcolor "Green" "----------------------------------------------------------"
	$fso = Get-ChildItem -Recurse -path "$($romsPath)$($romSystem)"
	$fso1 = Get-ChildItem -Recurse -path "$($roms1Path)$($romSystem)"
	$results = Compare-Object -ReferenceObject $fso -DifferenceObject $fso1
	ForEach ($r in $results)
	{
		If ($r.SideIndicator -eq "<=")
		{
			Write-Host -Foregroundcolor "DarkGreen" $r.SideIndicator $r.InputObject
		}
		Else
		{
			Write-Host -Foregroundcolor "DarkRed" $r.SideIndicator $r.InputObject
		}
		
	}
}
Apr 28

Determine If A Date Is Between Two Dates

If you need to know if a date is between two dates, you can easily figure this out by treating the date as a number and doing comparisons.  This can be useful for instances where you need a script to do a different task on different months, days, years, etc.  Let’s start with our first example, which will demonstrate how the comparison works.

Example 1 – Time Matters

In this example, if the current date/time is 4/27/2015 12:01:00 PM then it would return False due to the time being outside of our defined end range.  If the date/time was 4/27/2015 12:00:00 PM then it would return True.  If you do not specify the time then it will automatically be defined as 12:00:00 AM in the $start and $end variables; it is important to understand this or else it will affect your date comparisons.  If you do not want time to be a factor, I’d suggest always defining your start time as 12:00:00 AM and your end time as 11:59:59 PM.

Example 2 – Year Does Not Matter

In this example, I’m replacing the year from any specified date and making it the current year.  This allows us to focus our comparison based on the month, day, and time.  For example, if the current date/time is 4/27/2015 12:00:00 PM and want to know if our script is running during April.  We can input the start date/time as 4/1/2016 12:00:00 AM our end date/time as 4/30/2016 11:59:59 PM and the script would return True despite the year not matching.

Conclusion

With a basic understanding of compairing dates in powershell, you can easily customize the above scripts to meet any custom needs.