Skip to content

Latest commit

 

History

158 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

neoconv

neoconv

A preservation-focused CLI and GUI tool to convert between TerraOnion .neo containers and MAME / Darksoft Neo Geo ROM sets, and to edit .neo header metadata (name, manufacturer, year, genre, NGH, screenshot index) without repacking ROM data.

Use neoconv on the command line or via neoconv-gui (same core engine). It packs MAME ZIPs or ROM folders into .neo, extracts .neo back to individual ROM files, and rewrites headers when only metadata needs to change. It handles C-ROM byte-interleaving, P-ROM half-swap (default: auto-detect from the M68000 vector table, with yes / no overrides), V-ROM chunking, and TerraOnion header fields — for commercial dumps, hacks, CD conversions, and homebrew.

Getting started

Goal Command / tab
MAME ZIP or ROM folder → .neo neoconv pack … or GUI Pack
.neo → MAME / Darksoft ROM files neoconv extract … or GUI Extract
Fix title, genre, NGH, … without repacking neoconv edit … or GUI Edit
Inspect metadata, sizes, and MD5 hashes neoconv info … or GUI Info

Why neoconv?

Most Neo Geo tools only handle one direction or break on non-standard sets. neoconv focuses on correct conversion and transparent metadata edits for .neo files.

Property Description
Reliable Deterministic conversions with automated tests for core roundtrip behaviour
Universal Handles commercial sets, hacks, CD conversions, and homebrew
Transparent C interleaving, P-ROM swap (auto or manual), and V chunking are explicit and documented
Configurable On extract: --c-chip-size and --v-bank-size in bytes. neoconv falls back to 2 MB (2097152) when unset; the correct value per game comes from the MAME ROM set (e.g. 4 MB / 4194304 C chips for Neo Turf Masters), not from the .neo header alone
Dual interface Same pack / extract / edit / info workflows in CLI and GUI

Feature parity: CLI and GUI

Both interfaces support the same core workflows:

Workflow CLI GUI
Extract .neo to MAME / Darksoft files ✅ ✅
Pack MAME ZIP or directory to .neo ✅ ✅
Edit .neo header metadata (no repack) ✅ ✅
View .neo metadata, region sizes, and per-region MD5 ✅ ✅
P-ROM bank swap (auto-detect + manual override) ✅ ✅
Standalone detect-swap (inspect P-ROM without packing) ✅ — (Pack with Auto-detect logs the same check in the GUI)
Diagnostic mode for unrecognized files ✅ ✅

Requirements

  • Python 3.9+
  • GUI only: Tk (tkinter) — usually bundled with Python; on Linux install python3-tk via your package manager
  • GUI drag & drop: tkinterdnd2 (optional, see GUI usage)

CLI-only use remains pure Python stdlib (plus optional pytest for development tests).


OS-specific environment setup

Ubuntu / Debian

sudo apt-get update
sudo apt-get install -y python3 python3-pip python3-venv python3-tk

Fedora

sudo dnf install -y python3 python3-pip python3-tkinter

Arch Linux

sudo pacman -S --needed python python-pip tk

macOS

  • Install Python 3.9+ (python.org installer or Homebrew).
  • If tkinter is missing with Homebrew Python, install Tk:
brew install python tcl-tk

Windows

  • Install Python 3.9+ from python.org.
  • Keep the default Tcl/Tk component enabled in the installer.

Installation

Prebuilt GUI binaries (Windows, macOS, Linux)

Download the latest binary from the Releases page — no Python installation required. Prebuilt assets are GUI only; install from source (below) for the neoconv CLI.

Platform File
Windows neoconv-gui-x.y.z-windows.exe — run directly
macOS neoconv-gui-x.y.z-macos.zip — unzip, then double-click neoconv-gui.app (first launch: right-click → Open to bypass Gatekeeper)
Linux neoconv-gui-x.y.z-linux — chmod +x, then run

Installation (project)

git clone https://github.com/d4NY0H/neoconv
cd neoconv
python3 -m pip install .

For development (editable install + test runner):

python3 -m pip install -e ".[dev]"
python3 -m pytest tests/ -v

Quick verification (environment health check)

python3 -m neoconv --version
python3 -m neoconv --help
python3 -c "import tkinter as tk; print('tkinter', tk.TkVersion)"
python3 -c "import tkinterdnd2; print('tkinterdnd2 OK')"
  • If the tkinter check fails, the CLI still works, but the GUI needs a Python build with Tk.
  • If the tkinterdnd2 check fails, the GUI works normally — only drag & drop onto file path fields is disabled.

GUI usage

Start GUI:

neoconv-gui
# or
python3 -m neoconv.gui

The window uses the bundled app icon where the platform/Tk allow it.

Each file path row supports drag & drop onto its text entry field (next to "Browse…"): drop a .neo, a MAME ZIP, or a folder where the UI expects a directory. Drag & drop requires tkinterdnd2 — install it once if needed:

pip install tkinterdnd2>=0.4.0

Without it the GUI works normally; only drag & drop is disabled.

Tabs:

Tab Description
Pack Build .neo from ZIP/folder with metadata; P-ROM swap via radio (auto / yes / no). Status line checks mandatory P/S/M roles and warns on V/C filename gaps before pack
Extract Convert .neo to MAME or Darksoft ZIP/directory; P / C / V size dropdowns plus optional comma-separated size lists for mixed/multi-chip sets (same grammar as CLI). P default keeps one p1
Edit Load header fields from a .neo, adjust metadata (name/manufacturer truncated to header limits), write back (optional separate output path)
Info Inspect metadata, ROM region sizes, and MD5 per region (P, S, M, V, C)

CLI usage

neoconv <command> [options]
# or
python3 -m neoconv <command> [options]

Commands: extract, pack, edit, detect-swap, info.

On failure, the CLI prints Error: … to stderr and exits with code 1 (missing ROMs, invalid options, bad .neo, and similar cases) instead of a Python traceback.


extract — .neo → ROM files

# MAME ZIP
neoconv extract input.neo --prefix game --format mame --out game_mame.zip

# Darksoft ZIP
neoconv extract input.neo --prefix game --format darksoft --out game_darksoft.zip

# Output directory
neoconv extract input.neo --prefix game --format mame --out-dir ./roms/

# Explicit C chip size (example: 4 MB chips)
neoconv extract input.neo --prefix game --c-chip-size 4194304 --out game_customc.zip

# Explicit V bank size (example: 4 MB v1/v2 chunks)
neoconv extract input.neo --prefix game --v-bank-size 4194304 --out game_v4m.zip

# Mixed C / V / P sizes (e.g. Thrash Rally / trally) — same lists in GUI Extract
neoconv extract trally.neo --prefix 038 \
  --p-chip-sizes 524288,524288 \
  --c-chip-sizes 1048576,1048576,524288,524288 \
  --v-bank-sizes 1048576,524288 \
  --out-dir ./trally_out/
Option Default Description
--prefix, -p (input stem) Filename prefix for output files
--format, -f mame Output format: mame (.bin) or darksoft (.rom)
--out, -o (auto) Output ZIP path (ignored if --out-dir is set)
--out-dir, -d — Extract to directory instead of ZIP; wins over --out when both are given
--p-chip-size 0 (= entire as p1) Uniform size of each P chip in bytes. 0 keeps one p1. GUI: P Chip Size dropdown
--p-chip-sizes — Comma-separated per-file P sizes (p1,p2,…). Sum must equal the P region. Cannot combine with --p-chip-size. GUI: optional free-text under the P dropdown
--c-chip-size 0 (= 2097152) Uniform size of each C chip in bytes. 0 = 2 MB. GUI presets match common sizes. See C-ROM interleaving
--c-chip-sizes — Comma-separated per-chip sizes (c1,c2,c3,c4,…) for mixed C pairs. Cannot combine with --c-chip-size. GUI: optional free-text under the C dropdown
--v-bank-size 0 (= 2097152) Uniform size of each V file (v1, v2, …) in bytes. 0 = 2 MB. See V-ROM chunking
--v-bank-sizes — Comma-separated per-file V sizes (v1,v2,…) for mixed V ROMs. Cannot combine with --v-bank-size. GUI: optional free-text under the V dropdown

Overwrite behaviour: Existing output files are replaced without prompting. A warning is printed (CLI: stderr; GUI: log) for each path that already exists. Directory extract updates files in place; ZIP output is replaced atomically (see Atomic file writes).


pack — ROM files → .neo

# From MAME ZIP
neoconv pack input.zip \
  --name "Example Game" \
  --manufacturer "Example Studio" \
  --year 1995 \
  --genre Sports \
  --ngh 100 \
  --out output.neo

# From directory
neoconv pack ./roms/ \
  --name "My Game" \
  --manufacturer "Example Studio" \
  --year 1994 \
  --genre Fighting \
  --ngh 149 \
  --out mygame.neo

# With P-ROM bank swap auto-detect (default — recommended)
neoconv pack input.zip --name "Example Game" --ngh 100 --out output_auto.neo

# Force swap (explicit override)
neoconv pack input.zip --name "Example Game" --ngh 100 --swap-p yes --out output_swap_yes.neo

# Never swap (opt out of auto-detect)
neoconv pack input.zip --name "Example Game" --ngh 100 --swap-p no --out output_swap_no.neo

# Diagnostic output for unrecognized files
neoconv pack ./roms/ --name "Test" --diagnostic --out test.neo
Option Default Description
--name, -n Unknown Game title in the .neo header: latin-1, max 32 content bytes (33-byte field incl. NUL). The GUI truncates to this limit.
--manufacturer, -m Unknown Manufacturer string: latin-1, max 16 content bytes (17-byte field incl. NUL). The GUI truncates to this limit.
--year, -y 0 Release year: uint32.
--genre, -g Other Genre name or numeric uint32 id (see list below).
--ngh 0 NGH catalogue number: uint32 (non-negative integer).
--screenshot 0 TerraOnion screenshot index: uint32 (non-negative integer).
--out, -o (input stem + .neo) Output .neo path
--swap-p auto P-ROM half-swap mode: auto (heuristic, default), yes (always), no (never)
--diagnostic off Warn on unrecognized filenames

Genres (--genre name or numeric id):

ID Name
0 Other
1 Action
2 BeatEmUp
3 Sports
4 Driving
5 Platformer
6 Mahjong
7 Shooter
8 Quiz
9 Fighting
10 Puzzle

See also: P-ROM bank swap, ROM file naming.


edit — change .neo header metadata (no repack)

Updates TerraOnion header fields without touching P/S/M/V/C payload. At least one metadata option is required.

# Correct title in place (overwrites the input file atomically)
neoconv edit game.neo --name "Windjammers"

# Multiple fields; write a new file (input unchanged)
neoconv edit game.neo --genre Fighting --year 1994 --ngh 65 --out game_fixed.neo
Option Default Description
--out, -o (overwrite input) Output .neo path
--name, -n — Same limits as pack: latin-1, max 32 content bytes
--manufacturer, -m — Same limits as pack: latin-1, max 16 content bytes
--year, -y — uint32 year
--genre, -g — Genre name or uint32 id (same set as pack)
--ngh — uint32 NGH number
--screenshot — uint32 screenshot index

detect-swap — inspect P-ROM swap requirement

neoconv detect-swap input.zip
neoconv detect-swap input-p1.bin

Inspects the M68000 vector table in both 1 MB halves of a 2 MB P-ROM and reports whether --swap-p yes is needed. Works with raw P-ROM files or MAME ZIPs.

Example output:

Inspecting P-ROM from ZIP: input.zip  (2,097,152 bytes)
  Result  : --swap-p yes  ← required
  Reason  : Second half has valid vectors (SP=0x0010F300, Reset=0x00C00402) — swap required.

See P-ROM bank swap for --swap-p modes when packing.


info — display .neo metadata

Prints header metadata, ROM region sizes, and MD5 per region (P, S, M, V, C) when a full .neo is loaded — useful to compare two files that differ only in the header.

neoconv info input.neo

Technical details

Background on pack/extract behaviour, ROM naming, and the on-disk .neo layout.

Section Topics
Pack input MAME filenames, directory layout, synthetic S-ROM
Extract sizing Byte presets, P split, C interleaving, V chunking
P-ROM swap --swap-p / auto-detect
.neo format Header layout, V1/V2 fields
Notes CRC mismatches, out-of-scope items
Errors NeoConvError hierarchy for library callers

Errors (library API)

Expected failures from neoconv.core raise subclasses of NeoConvError (not bare ValueError):

Class Typical cause
InvalidNeoError Truncated or invalid .neo container
InvalidRomLayoutError Missing/duplicate ROM roles, ZIP/dir layout, C/V sequence gaps
InvalidConfigurationError Extract chip/bank size, P-ROM swap size rules
UserCancelledError GUI worker cancelled by the user

Each error has a stable code string and optional hint for remediation. The CLI prints hints after an em dash; the GUI logs them on the same line as the message.


Pack input: ROM file naming

The table below matches the primary rules in name_to_role: extension (e.g. .p1, .c1) or basename suffix patterns such as -p1.bin, _m1.bin, or a stem ending in -v3 / _c2.

Role Recognized patterns
P ROM .p1, .p2, -p1.bin, _p1.bin, -p2.bin
S ROM .s1, -s1.bin, _s1.bin
M ROM .m1, -m1.bin, _m1.bin
V ROMs .v1-.v8, -v1.bin--v8.bin, _v1.bin-_v8.bin
C ROMs .c1-.c16, -c1.bin--c16.bin, _c1.bin-_c16.bin, and letter-split parts -c1a.bin / -c1b.bin (C9–C16 for extended / hack sets)

Directory layout and sequence gaps

pack reads ROM files in the chosen folder and one level of subfolders (typical after unzipping).

Gaps in the V or C sequence (e.g. v1 + v3 without v2) cause pack to abort with an error instead of producing a broken .neo.

Synthetic S-ROM (no physical s1)

Some MAME parents (e.g. PVC / encrypted boards such as mslug5, samsho5, svc, kof2003) ship without a separate text-layer s1; the emulator driver uses a zero-filled "fixed" region. If P and M are present, there is no s1, but filenames look like a Neo Geo C1 sprite set, neoconv may inject a zero-filled S region and emit a UserWarning.

That fill matches MAME softlist size heuristics so pack can complete — it is not a hardware-correct .neo. On TerraOnion / MiSTer (and similar cores) the text/fix layer will be missing or corrupt. Bootlegs that do include an s1 (e.g. ms5plus) pack normally. There is currently no path to derive real s1 tiles from C-ROM data.

Pattern Synthetic S size
Basenames starting with kf10- (KOF2002 bootleg) 256 KiB
-c1r. / -c2r. sprite chip names (e.g. 269-c1r.c1) 512 KiB
Certain three-digit MAME set IDs in NNN-p1. / NNN-m1. / NNN-c1….c1 (see _SYNTH_S_MAME_512K_SET_IDS in neoconv/core/constants.py) 512 KiB
Default (e.g. mslug5 / set id 268 — do not force 512 KiB) 128 KiB

If synthetic S is injected but no C sprite data was collected, pack aborts (avoids a silent empty-C .neo).

To get a playable file for those parents today: start from a known-good .neo that already has real S data, or use a ROM set that includes a dedicated s1.

FBNeo compatibility

FBNeo Neo Geo sets use the same ROM naming conventions as MAME and are supported out of the box. BIOS-related files (000-lo.lo, sfix.sfix, sm1.sm1, sp-s2.sp1, etc.) are ignored automatically.

Sets where C-chip filenames carry a suffix in the stem but use native extensions (e.g. 263-c1d.c1, 269-c1r.c1, 268-c1c.c1) are recognised correctly — the extension .c1 / .c2 match takes priority.

Split C chips (c1a + c1b style): Hack/homebrew sets that split individual C chips across letter-suffixed .bin files are merged automatically (parts concatenated in letter order, then interleaved as usual):

Set Files
kog, kogplus 5232-c1a.bin + 5232-c1b.bin → c1, etc.
kof10th and variants kf10-c1a.bin + kf10-c1b.bin → c1, etc.

A single letter part alone (e.g. only kf10-c1a.bin / kf10-c2a.bin) is also accepted as the full chip. All official SNK titles and the vast majority of hacks work without any preparation.

Ignored files

Standard BIOS files (000-lo.lo, sfix.sfix, etc.) are ignored. Unknown files are also ignored unless --diagnostic is enabled.


Extract: P, C and V ROM sizing

Why you need to specify chip sizes at all

The .neo header stores only the total byte count for the P-, C-, and V-ROM blocks — it does not record how many chips those blocks were split across, or how large each individual chip was. That information existed in the original MAME ROM set but is lost when the files are merged into the .neo container.

When neoconv extracts, it must re-split those blocks into individual files. The split is purely mechanical — any size that divides the total evenly is accepted without error. The question is only whether the resulting files match what MAME or Darksoft expect.

For example, 8 MB of C-ROM data could legitimately be split as c1(4 MB)+c2(4 MB) or as c1(2 MB)+c2(2 MB)+c3(2 MB)+c4(2 MB). Both extractions succeed, but only one matches the MAME neogeo.xml entry for that title. Using the wrong split means MAME's ROM verification (verifyroms) will report missing or mismatched files. The ROM data itself is intact — if you correct the XML to match the actual file layout, the game will run.

The 2 MB default covers the majority of titles. Always cross-check against the MAME neogeo.xml or FBNeo ROM database for any title you are unsure about.

Common extract sizes (CLI bytes)

The CLI flags --c-chip-size and --v-bank-size take bytes (not megabytes). The GUI dropdown labels use MB/KB; values map to the same byte counts.

Label CLI value (--c-chip-size / --v-bank-size) C GUI V GUI
512 KB 524288 ✅ ✅
1 MB 1048576 ✅ ✅
2 MB (unset / 0) 2097152 ✅ ✅
4 MB 4194304 ✅ ✅
8 MB 8388608 ✅ ✅
16 MB 16777216 ✅ ✅
20 MB 20971520 ✅ (C only) —

0 for either flag is neoconv’s fallback (2097152, 2 MB), not necessarily the correct size for every game. Any other positive integer is accepted on the CLI.

C-ROM interleaving

C-ROM graphics are byte-interleaved in .neo:

  • even bytes → odd chips (c1, c3, …)
  • odd bytes → even chips (c2, c4, …)

C chips always come in pairs. Interleaved bank size is chip_size × 2.

On extract, if unset, neoconv assumes 2 MB per chip (2097152 bytes; CLI 0 / GUI “2 MB”). Larger chips (e.g. 4 MB / 4194304 for Neo Turf Masters) must match the MAME set — total C size in the .neo header does not uniquely determine per-chip size.

When unset GUI presets CLI
C chip (c1, c2, …) 2 MB (2097152) 512 KB – 20 MB --c-chip-size any positive byte value (0 = 2097152); or --c-chip-sizes for mixed pairs

Choosing the right size: For a known title, open MAME’s neogeo.xml (or the FBNeo ROM database) and check each c1, c2, … entry. The size="…" attribute is the per-chip size in bytes (e.g. size="4194304" → --c-chip-size 4194304). If extract fails with “not a multiple of chip_size×2”, try another size from that list — or use --c-chip-sizes when chip pairs have different sizes.

Mixed C pair sizes: Some parents (e.g. trally) interleave a 1 MiB pair then a 512 KiB pair (C blob 3 MiB). A single --c-chip-size 524288 divides evenly but yields wrong chip boundaries. Use the list form instead:

neoconv extract trally.neo --c-chip-sizes 1048576,1048576,524288,524288 --out-dir ./out

In the GUI Extract tab, leave the dropdowns as-is and fill C chip sizes / V bank sizes with the same comma-separated byte lists.

P-ROM splitting

Pack concatenates multi-chip program ROMs (p1 + p2 + …) into one P region. On extract the default is a single p1 for the whole region (most titles).

When unset GUI presets CLI
P chip (p1, p2, …) Entire region as p1 Entire as p1; 512 KB – 8 MB --p-chip-size positive bytes (0 = entire as p1); or --p-chip-sizes for unequal parts

Equal halves (e.g. trally): --p-chip-size 524288 (or GUI 512 KB) yields p1 + p2 of 512 KiB each.

Unequal parts: use --p-chip-sizes / GUI P chip sizes; the sum must equal len(P) or extract fails hard (no silent wrong split).

V-ROM chunking

V-ROM data is contiguous in .neo and split to v1, v2, … on extract. When unset, chunk size is 2 MB (2097152; --v-bank-size 0 or GUI V Bank Size).

When unset GUI presets CLI
V bank (v1, v2, …) 2 MB (2097152) 512 KB – 16 MB --v-bank-size any positive byte value (0 = 2097152); or --v-bank-sizes for mixed V files

Choosing the right size: In MAME neogeo.xml, check each v1, v2, … entry — the file size is the bank size for --v-bank-size (often 2 MB / 2097152; some sets use 4 MB / 4194304). Match what the MAME ZIP contains so filenames and lengths align after extract.

If total V size is not a multiple of a uniform bank size, the last file is shorter and a warning is emitted. For mixed V sizes (e.g. 1 MiB + 512 KiB), use --v-bank-sizes so the sum matches len(V) exactly (no silent wrong split).


P-ROM bank swap (--swap-p)

Some Neo Geo titles and hacks store their 2 MB P-ROM with the two 1 MB halves in reversed order relative to what TerraOnion NeoSD / MiSTer expect.

neoconv detects this automatically by inspecting the M68000 exception-vector table (initial Stack Pointer + Reset PC) in both halves. The half carrying valid values — SP in Work RAM (0x100000–0x10FFFF), Reset PC in ROM or BIOS (0x000100–0x1FFFFF or 0xC00000–0xC7FFFF) — determines whether a swap is applied.

Mode Behaviour
auto (default) Detect from vector table; prints a diagnostic line
yes Always swap — for titles where auto-detect is ambiguous
no Never swap — to opt out explicitly

When auto-detect is inconclusive (neither half has plausible M68k vectors), pack continues without swap but prints [WARN] and emits a warning — run neoconv detect-swap <zip> or set --swap-p yes / no explicitly.


.neo container format

V1 / V2 size fields (read vs write)

Some .neo files split the total V ROM payload across the V1 and V2 size fields at offsets 0x010 and 0x014. neoconv reads both and merges the bytes in memory. On output (pack, build_neo, replace_neo_metadata), the header is normalised: all V length is stored in V1 and V2 is set to 0 (TerraOnion-style layout). Loading or rewriting such a file may emit a UserWarning.

Header and payload layout

Offset 0x000   Magic         b'NEO\x01'  (4 bytes)
Offset 0x004   P ROM size    uint32 LE
Offset 0x008   S ROM size    uint32 LE
Offset 0x00C   M ROM size    uint32 LE
Offset 0x010   V1 ROM size   uint32 LE   (all V data merged here on write; read accepts split V1/V2)
Offset 0x014   V2 ROM size   uint32 LE   (0 when written by neoconv; non-zero allowed on read)
Offset 0x018   C ROM size    uint32 LE   (total, interleaved)
Offset 0x01C   Year          uint32 LE
Offset 0x020   Genre         uint32 LE
Offset 0x024   Screenshot    uint32 LE
Offset 0x028   NGH number    uint32 LE
Offset 0x02C   Name          33 bytes, null-terminated, latin-1
Offset 0x04D   Manufacturer  17 bytes, null-terminated, latin-1
Offset 0x200-0xFFF  (padding, header is always 4096 bytes)
Data:  P, S, M, V, C   (sequentially, sizes from header)

Atomic file writes

pack (output .neo), extract (output ZIP), and edit write via a temporary file in the same directory and os.replace, so an interrupted run is less likely to leave a truncated file. Directory extract still overwrites individual ROM files in place (with warnings).


Notes

About CRC mismatches

For hacks and CD conversions, MAME verifyroms may report CRC mismatches because data differs from known dumps. This is expected when the dump is intentionally different from MAME's reference set.

Out of scope

  • detect-swap on .neo files: not useful — the P-ROM swap is applied during pack and already encoded in the .neo payload. There is nothing left to detect.
  • verify CLI subcommand: verify_roundtrip exists in neoconv.core as a testing utility. Exposing it as a CLI command would only confirm that neoconv round-trips its own output correctly, which is covered by the test suite. It is not a user-facing feature.
  • Directory traversal deeper than one level in pack: the one-level limit (top-level files + one subdirectory) covers all known MAME unzip layouts. Recursive traversal would risk picking up unrelated files from nested archives or build artefacts.
  • FBNeo as a separate input format: FBNeo Neo Geo sets use the same naming conventions as MAME and are supported out of the box — see FBNeo compatibility.
  • Deriving real s1 / text-layer tiles from C-ROM for PVC parents (and CLI/--s1 injection from a reference .neo): not supported yet — see Synthetic S-ROM.

Legacy neoconv headers (Year/Genre as uint16)

Older neoconv builds packed Year/Genre as uint16 at 0x1C/0x1E (NGH at 0x24). Current neoconv matches TerraOnion / neosdconv (four uint32). On read, headers that still look like the old layout (non-zero packed genre beside year, NGH slot at 0x28 empty) are detected, parsed correctly, and emit a UserWarning. Rewriting with edit or pack migrates them to the modern layout. Files with genre 0 under the old layout cannot be distinguished reliably and are read as modern.


License

MIT - see LICENSE.

About

A preservation-focused CLI and GUI tool to convert between TerraOnion .neo containers and MAME / Darksoft Neo Geo ROM sets, and to edit .neo header metadata (name, manufacturer, year, genre, NGH, screenshot index) without repacking ROM data.

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages