Repository navigation
v1.2.1
Maintenance and hardening release on top of 1.2.0. No new features; all changes are bug fixes, internal refactors that reduce drift, and test coverage for areas that previously had none.
Correctness / hardening
- Fixed
XBEcertificate parsing reading 4 bytes pastdwVersion— the version field landed in the LAN-key region, so every Original Xbox executable routed throughTitleInfo::from_xbewas returning a wrong version. Seek width corrected from 164 to 160 bytes. - Fixed
ConHeaderBuilder::with_game_titlepanicking on titles ≥ 64 UTF-16 code units; the UTF-16 writer now caps at the field length (0x80 bytes / 64 units, null included) for both title slots in the CON header. - Fixed
looks_like_gamertagrejecting all non-Latin gamertags — Cyrillic, CJK, Greek, etc. now resolve correctly. ASCII-only checks replaced withis_alphabetic/is_alphanumeric. - Fixed
pick_profile_namecaching STFS system-package titles ("Xbox 360 Dashboard") as if they were gamertags; candidates now run throughlooks_like_gamertagbefore being accepted. - Fixed
seek(SeekFrom::End(0))silently returning 0 on macOS raw block devices:partition::detect_xbox_partitions,partition::scan_for_fatx, andFatxVolume::opennow error explicitly when given a zerodevice_size.scan_for_fatxalso gained an explicitdevice_size: u64parameter, with the CLI deep-scan caller updated accordingly. - Fixed FAT16/FAT32 selection drifting from the FATX-specific 65520 (0xFFF0) threshold.
volume.rsandmkimage.rsnow use theFAT16_CLUSTER_THRESHOLDconstant fromfatxlib::types. Volumes with 65520–65524 clusters were previously mislabeled as FAT16. - Fixed
FatxVolume::write_file_in_placenot flushing the FAT cache between chain extension (Phase 1) and payload writes (Phase 2); a mid-operation failure could previously leave the directory entry advertising clusters the on-disk FAT had not yet linked. - Fixed
validate_filenamemeasuring byte length instead of character count when comparing against the 42-char FATX cap. - Fixed
FatxVolume::statspanicking in debug builds (or wrapping in release) when corrupt cached counts producedfree + bad > total; counts are nowsaturating_sub'd. - Fixed host-to-FATX directory copies reading entire files into memory; large host-FS uploads now stream cluster-by-cluster through
create_file_from_reader. - Fixed the guided picker's stale
sudo fatxhint — nowsudo xtafkit. - Tightened
build.rscatalog floor checks (xbox360 > 4000,xbox_og > 800) so a truncated source no longer ships an empty or partial title map. The literal-pairing loop inwrite_mergedwas simplified to a single pass over the merged map, eliminating a parallelvalues()/iter()zip that was correct only by coincidence ofBTreeMapiteration order. - Centralized FATX cluster allocation behind two private helpers (
reserve_free_clusters,link_allocated_clusters); previously three near-identical bitmap-walk + chain-linking copies inallocate_chain,write_file_in_place, andplan_write_in_place_for_entrycould drift on independent fixes.
TUI / quality of life
- Installed a panic hook and
Drop-based terminal guard so a crash inside Ratatui or the background IO worker no longer leaves the shell in raw mode with the alternate screen stuck. - The UI now detects
TryRecvError::Disconnectedon the IO response channel: if the worker thread dies unexpectedly the UI surfaces the failure and quits cleanly instead of freezing onis_busywith no way out. - Flush errors after destructive operations are no longer silently swallowed. A shared
flush_or_errorhelper is wired intoWriteFile,CopyDir,ExtractXiso,ConvertXisoToGod,Mkdir,Delete,Rename,Cleanup, andFlush— a failed FAT commit can no longer be reported as "uploaded successfully." - Single-delete confirmation captures the selection at prompt time via a new
pending_deletefield rather than re-reading the current selection at Enter — closes a race where a backgroundListDirrefresh could re-sort entries mid-confirmation and re-target the delete. - Replaced prompt-string
starts_withdispatch inhandle_input_keywith an exhaustivematchonInputMode, so every input mode has a single, type-checked completion handler.
Testing / maintenance
- Pinned
HashListsemantics with direct fixed-byte tests:readpreserves offsets and zero gaps,writeemits exactly 4 KiB, andHashList::new().digest()matchessha1(b"\0" * 4096)byte-for-byte. - Rewrote the GoD MHT back-chain test to seed via
HashList::read(notadd_hash) and assert against literal SHA-1 byte arrays for a three-part conversion, so byte-order or padding regressions indigest()and propagation bugs in the back-chain surface immediately. - Added a
write_file_in_placeFAT-flush regression test that injects post-flush write failures through a new file-backedFailingWriteFilewrapper, reopens the image, and asserts the chain extension survived the failure. - Added FAT16/FAT32 boundary tests at exactly
FAT16_CLUSTER_THRESHOLDandTHRESHOLD - 1—fat_type_for_cluster_estimateextracted to a private module function so the predicate is unit-testable in isolation. - Added direct
partitiontests covering both the zero-size error path and a planted-magic happy path ondetect_xbox_partitionsandscan_for_fatx. - Added an XBE certificate regression test that builds a synthetic header and verifies
title_idandversionare read from the correct offsets. - Added a CON header truncation test for
with_game_titleat oversized inputs. - Added a Cyrillic gamertag case ("Игрок 7") to the
looks_like_gamertagrules and apick_profile_nametest that rejects the overlong "Xbox 360 Dashboard" candidate. - Moved the volume stats saturation test inline into
volume.rsso theforce_stats_counts_for_testpublic helper could be deleted;fatxlib/tests/stats.rsremoved. - Removed redundant scaffolding tests:
fatxlib/tests/fixture_test.rs(three "didopen()succeed" checks already covered by every other integration test) and fiveoptimization.rstests that either re-tested already-covered invariants (test_bitmap_consistent_after_allocations,test_bitmap_consistent_after_free_chain,test_flush_after_no_changes_is_noop) or labeled themselves alignment tests while only exercising file-backed (non-aligned) I/O (test_default_alignment_works,test_read_write_at_various_offsets). tests/cli_integration::test_scan_imagenow asserts the command actually succeeded instead of discarding the exit code.
What's Changed
Full Changelog: v1.2.0...v1.2.1