Skip to content

Instantly share code, notes, and snippets.

@ner00
Last active February 22, 2024 03:24
Show Gist options
  • Save ner00/aec56bad2461938f5eae33f5ef564009 to your computer and use it in GitHub Desktop.
Save ner00/aec56bad2461938f5eae33f5ef564009 to your computer and use it in GitHub Desktop.
NES ROM UNHEADER (16 Byte Header Remover)
# NES ROM UNHEADER (16 Byte Header Remover)
# -----------------------------------------
#
# ner0
# Created: 13/04/2020
# Reviewed: 14/04/2020
#
#
#
# Usage:
# 1. Place the script '#nes_rom_unheader.ps1' inside the same folder as your NES zipped ROMs
# 2. Open the command-line and change into the ROMs folder:
# ex: cd /d "f:\my roms\nes"
# 3. Run the script:
# ex: powershell.exe -ExecutionPolicy Bypass .\#nes_rom_unheader.ps1
#
#
# What does it do?
# The script goes through all the zip files in your NES roms folder and extracts them,
# then it parses every unpacked ROM file and checks if it has the extra 16 byte header;
# if it does, it removes those extra bytes and repacks the ROM into the original zip file.
#
#
# Header to look for - script can be adapted to other simple ascii header tags like this one
$header_tag = "NES"
$header_length = 16
# Set script start time
$start_time = Get-Date
# Set counters
$total_files = (Get-ChildItem .\ -Filter *.zip | Measure-Object).Count
$cur_archive = 0
$parsed = 0
$fixed = 0
# Loop through all the zip files in the current folder
Get-ChildItem .\ -Filter *.zip | Foreach-Object {
# Unpack zip file contents
$zip = $_.FullName
$rom_folder = "$($_.DirectoryName)\$($_.BaseName)"
$global:ProgressPreference = "SilentlyContinue"
Expand-Archive -LiteralPath $zip -Force
# Show progress
$cur_archive++
$global:ProgressPreference = "Continue"
$percentage = [math]::Round($cur_archive / $total_files * 100, 2)
Write-Progress -Activity "Parsing ROM files" -Status "$percentage% Complete: $cur_archive/$total_files" -PercentComplete $percentage
# Loop through the nes files in the rom folders
Get-ChildItem -LiteralPath $rom_folder -Filter *.nes | Foreach-Object {
# Read the rom file contents
#"Parsing '$($_.Name)'..."
$rom = $_.FullName
$bytes = [System.IO.File]::ReadAllBytes($rom)
# Get the rom file header
$header = $null
for ($i=0; $i -lt $header_tag.Length; $i++) {
$header += [Convert]::ToString($bytes[$i], 16)
}
$ascii_header = -join ($header -split '(..)' | ? { $_ } | % { [char][convert]::ToUInt32($_,16) })
# Check if the header matches what is expected
if ($ascii_header -eq $header_tag) {
# Output the rom file without the header
[System.IO.File]::WriteAllBytes($rom, $bytes[$header_length..($bytes.count-1)])
# Replace square brackets in the name (workaround due to M$ stupidity)
if ($zip.Contains("[")) { $zip = $zip.replace("[", "_lsb_"); $sb_workaround = 1 }
if ($zip.Contains("]")) { $zip = $zip.replace("]", "_rsb_"); $sb_workaround = 1 }
# Repack the rom into the zip file (overwrites existing)
$global:ProgressPreference = "SilentlyContinue"
Compress-Archive -LiteralPath $rom -DestinationPath $zip -Force
# Restore square brackets to the name (rolling-back workaround)
if ($sb_workaround -eq 1) {
$nicezip = $zip
if ($zip.Contains("_lsb_")) { $zip = $zip.replace("_lsb_", "[") }
if ($zip.Contains("_rsb_")) { $zip = $zip.replace("_rsb_", "]") }
Move-Item -LiteralPath $nicezip -Destination $zip -Force
$sb_workaround = 0
}
#" * Fixed '$($_.Name)'..."
$fixed++
}
$parsed++
}
# Remove the unpacked rom
Remove-Item -LiteralPath $rom_folder -Recurse -Force -ErrorAction SilentlyContinue
}
# Output stats
"`n------------------------"
" ZIP Files: $total_files"
" Parsed ROMs: $parsed"
" Fixed ROMs: $fixed"
"------------------------"
# Get script end time
$end_time = Get-Date
# Calculate duration of execution
$diff = New-TimeSpan -Start $start_time -End $end_time
"Total duration: {0:hh\:mm\:ss}" -f ([TimeSpan] $diff)
"------------------------`n"
pause
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment