Releases: Lorsieab2/Virtual-Families-2-Restoration-Addition-Patcher
Release list
VF2 Patcher B171
B171
Adoption Services is base-game again. Otherwise identical to B170.
The crash
Purchasing Adoption Services crashed:
Exception code: 0xC0000005 (access violation)
Faulting module name: unknown
Fault offset: 0x000001d7
"Unknown" module at 0x1D7 means execution left every loaded module and
jumped to a near-null address — a corrupted return address or function
pointer, not a bad data read.
Cause
patch_vf3_style_child_adoption_chooser replaced the stock spawn route at
CScrollingStoreScene::HandleUpgrade+0x57A with a helper that put up a
"baby or older child" message box and spawned the adoptee itself. Two
things in it were wrong against the native code, and either could produce
this crash:
- It did not reproduce the stock call. Native is
SpawnSpecificPeep(age=1, gender=-1, body=0x3C); the helper passed
body=-1with an explicit gender. - It constructed a
theMessageBoxDlgin a0x300-byte stack buffer,
standing in for a class whose real size is not pinned anywhere. If the
real object is larger, its constructor writes past that buffer and
corrupts the return address — exactly an "unknown module" jump to a tiny
address.
Fix
Rather than guess which was fatal and ship another maybe-fix, the whole
route is reverted. HandleUpgrade is byte-identical to the stock object,
verified by diffing the patched object against work/desktop_obj_files:
HandleUpgrade changed bytes: NONE - byte-identical to stock
+0x57A: 6a 3c 6a ff 6a stock: 6a 3c 6a ff 6a
Adoption Services behaves exactly as the base game does. No baby/older-child
prompt exists in any B171 executable.
Nothing else is disabled — one hook removed, every other patch intact.
Also carried forward
Everything from B170, including the Family Tree fix (Bathroom 1's curtain id
no longer points at familytree_bg.jpg) and the bundle fixes that make the
installed game complete.
VF2 Patcher B170
B170
Fixes the Family Tree screen. Otherwise identical to B169.
The bug
Bathroom 1's closed-curtain image id was set to 615, taken from a live
read of the running game's image table. The read was accurate but the id
was not transferable: the running game is the patched build, whose table
is shifted by the ~800 images the patcher appends, so runtime ids do not
correspond to the stock ids the patcher indexes.
Against the stock table, 615 is familytree_bg.jpg. Bathroom 1's
curtain colour was therefore applied to the Family Tree background, which
then failed to draw — and with nothing repainting that region, every sprite
on the screen smeared across an uncleared frame.
The fix
Ids restored to the values data/vf2/image-descriptors.json gives:
539 = curtain_closed_southb.png -> Bathroom 1 (south, workshop-side)
538 = curtain_closed.png -> Bathroom 2 (north)
The room mix-up that prompted the original change was never about these
ids. It was fixed by routing each bathroom to its own decal slot in
RefreshProps (+0x53A and +0x570), which is untouched, so both curtains
keep working independently.
Guards added
A wrong image id is invisible by nature: it patches something real, just
not the intended thing.
validate_stock_image_ids()runs before every build and checks all three
hard-coded stock ids against the descriptor table. Given 615 it fails
withimage id 615 is 'familytree_bg.jpg' ... expected 'curtain_closed_southb.png'.work/audit_image_table.pyreads the descriptor table out of every built
variant and verifies no stock slot is repointed and no added image reuses
a stock id. B170: 19 variants, stock 0–636 intact, 751–814 added each,
zero collisions.
Bundle
The B169 packaging fixes are included: additive export now carries every
addition (7526 asset patches, was 1263), base-game classification uses a
recorded clean install rather than the working payload, and the release
gate simulates the install — 8193 of 8193 files reproduced byte-for-byte.
Verified by installing onto a clean base game with every patch enabled:
7305 images, 888 assets, matching a known-good install exactly.
VF2 Patcher B169
B169
Seventeen pull requests since B168: #15–#30 and #33.
B168 already contains #12 (toggle persistence), #13 (villager-details
Married status) and #14 — its release config was added by #14 — so none of
those are upgrade changes for an existing B168 user.
Same-sex marriage
Marrying already worked in B168; the finalization hook predates it. What
was broken was everything the game asks after the wedding.
- Spouses are now spouses everywhere.
GetMatriarchandGetPatriarch
back-fill a couple's missing half regardless of gender, which covers all
66 native call sites in one change rather than hooking nineteen functions
individually (#22). - Unrelated adults are no longer treated as a couple.
VF2MarriagePair
used to pair up any two qualifying resident adults, which also blocked
Force Marriage Email for a player with no spouse at all (#16). - Private adult romantic time. A same-sex couple, or an opposite-sex
couple already at six children, takes the ordinary baby-making path and
is simply labelled differently. Pregnancy is suppressed for both, and it
holds even against the Force Successful Pregnancy upgrade (#33). - Same-sex partners split the sequence. Behaviour 358 chooses which half
a villager performs from the gender field alone, so a same-sex pair
performed the identical half twice. The halves are now handed out by
partner slot, so one spins and one produces the roses (#33).
An earlier form of the romantic drop (#28, #29) swapped behaviour 358 for
the native 357/356 pair and skipped refusals. That approach was reverted in
#33 and rebuilt as a label variation on 358, so what ships here is #33's
design, not #28/#29's.
Toggles
- Marriage Candidate Reroll works. It used to reroll the candidate and
then immediately close the proposal it had just rerolled (#23).
Bathrooms
- Each bathroom's curtain goes to its own decal slot. A Bathroom 1
renovation used to change Bathroom 2's curtain, and one slot turned out
to be the kitchen's garbage sprite (#19, #21). - Bathroom 2 fixtures work with a remodel active. The remodel rows were
written into the native owned-items array, which native code reads to
decide the room's state; they now have their own storage, with migration
so existing saves self-heal (#27). - The native Bathroom 2 renovation survives and gates the remodel rows, so
the remodels cannot be bought without it (#24). - The five Bathroom 1 rows are renamed "Bathroom 1 Remodel in colour"
(#20).
Correctness
- Arbitrary memory corruption fixed. A 5-byte hook over a 2-byte branch
inHandleDropOnVillagerclobbered the following two pushes, and the
fall-through then executed its own jump displacement as code before
writing through a garbage address. Reachable by dropping any two
different-gender adults who were not the couple while the house was full,
so it affected opposite-sex households on a stock Behavior Patches build
(#25).
Build system
- The VF3 TVs are built from checked-in sources. They had survived only
inside each release: the matrix seeds every build from the previous one,
and the generator keeps a target it finds already present when the source
is gone. Every retained manifest from B164 through B168 records exactly
that, so the real sources had been missing for weeks without anything
noticing, and an unseeded build could not produce the TVs at all. The
sprites are now checked in, stock donor fmaps resolve from the vanilla
payload, and a test asserts every VF3 TV has a checked-in source (#30). - A missing Bathroom 1 renovation asset hard-fails the build instead of
silently shipping (#17). work\build_playtest.ps1produces a single playtest build in one command,
and dead legacy same-sex marriage code is gone (#18).- Stale manifest-shape assertions in the release parity test fixed (#15).
- Root causes for the Bathroom 2 fixture and same-sex private-time bugs
documented (#26).
Notes
CVillager::StartEmbracechanges by exactly five bytes and
theMainScene::HandleDropOnVillagerby five. Every refusal in
StartEmbrace— illness, hunger, age, pregnancy state, both random rolls
— is base-game, as are its entry animation and its sound call.- Known base-game behaviour, not introduced here: the kiss animation is
played atStartEmbrace+0x3A, before any check runs, so it can be audible
on a refusal. Where that sound is emitted was never established; every
attempt to suppress it downstream failed, and one crashed the game with a
1124-frame stack overflow, because the pending animation is what stops the
refusal tail's behaviour-137 handoff from re-enteringStartEmbrace.
VF2 Patcher B168
VF2 Patcher B168
Release built from main at 0929109 (PR #15, merged right after packaging,
is a test-only fix and doesn't affect any of the binaries in this release).
Covers PR #11 (same-sex marriage finalization on Accept), PR #12 (persist
Same-Sex Marriage / Marriage Candidate Reroll toggles across a relaunch),
PR #13 (same-sex "Married" status on the villager details screen), and
PR #14 (exporter fix needed to package this release at all) -- none of
which were in a published release before this one (B164 predates all four).
What's new since B164
- Same-sex marriage now actually finalizes. Pressing Marry on a
same-sex couple now runs the real native finalization: money,
achievements, the family tree record, and the "Announcing the marriage
of X and Y" life-event announcement -- previously silently skipped
because the native code that grants those only fires when it can find
one female adult and one male adult, which a same-sex couple can never
provide. - Same-sex "Married" status on the details screen. The villager
details screen ran the identical hard gender-filtered check as the
finalization gate above, independently, to decide which status string to
show -- so even a correctly-recorded same-sex marriage never displayed
"Married". Fixed the same way: a scoped fallback for the specific
villager being viewed. - Same-Sex Marriage and Marriage Candidate Reroll now persist correctly.
Both toggles used to live in a free-standing custom PE section that the
game's native save system never reads or writes, so buying either one
only "stuck" for the rest of that play session -- a fresh launch or a
reloaded save silently reset it to off, even though the store still
showed it as purchased. This is what made Marriage Candidate Reroll look
completely non-functional. Both toggles now live at the same
proven, actually-persisted location already used by the Bathroom 1/2
curtain colors and other renovations (insideCInventoryManager, part
of the real save payload). - All 19 feature-toggle executable variants rebuilt from current
main
and verified byte-distinct.
What's inside
Apply_B168_Patcher.bat/Launch_GUI.bat-- run either to patch your own
Virtual Families 2.exe.offline_vf2_patcher.py/offline_vf2_patcher_gui.py-- the patcher.payload/-- all 19 modded EXE variants (one per feature-toggle
combination) and their supporting assets/images.manifest.json,Transparency Log.txt,How to Use.txt.
Validation performed
- Diagnosed the Marriage Candidate Reroll bug down to the exact root cause
via a linker.mapfile and raw disassembly of the linked exe -- not
just source review -- before writing the fix. - Full
work/test suite: 471 passed, 238 subtests passed; the small
number of remaining failures are all pre-existing, environment-only gaps
(missing local icon source assets, an old release zip, IDA analysis
output, and mobile.oggassets) unrelated to anything in this release. - All 19 executable variants compiled and linked cleanly; confirmed
byte-distinct (SHA-256). - Post-link raw exe disassembly confirmed both new marriage-related hooks
(finalization guard and details-screen married-status guard) resolve to
the exact addresses the generator intended. work/package_patcher_zip.py'svalidate_executable_inventory()ran
automatically during packaging and passed.
Known limitation
- The persisted-byte storage change for Same-Sex Marriage means this
release's external offline-patcher tool can no longer flip that one
setting without an in-game purchase (it previously could, via a direct
byte patch to a now-removed custom PE section). The in-game purchase
toggle is unaffected and, unlike before, now actually persists.
Not yet fully validated
- Divorce Spouse for an existing same-sex couple married before this
build's finalization fix may still not work -- that couple's family tree
record was never populated in the first place, and this release can't
retroactively repair already-saved data. A same-sex marriage formed
under this build should not have that problem.
Package
VF2-B168-Release.zip- SHA-256:
C3022AE1E81D541BE4F9B46E7A990DA888EC23FF5B60A09411C877C733FAB7F0 - Size: 93,671,474 bytes (~89.3 MB)
A passion project by Lorsieab2 in collaboration with Codex AI/Claude. No
copyright infringement intended -- please support the original game
creators!
Safe Base VF2 Patcher with all Patches ACTUALLY Enabled
Safe Base VF2 Patcher with all Patches ACTUALLY Enabled
A clean base build of the offline Virtual Families 2 Restoration/Addition Patcher (B159) that ships with every patch actually enabled — no toggles left off by mistake.
What's inside
Apply_B159_Patcher.bat— drag/drop or enter your originalVirtual Families 2.exeto patchLaunch_GUI.bat— GUI front-end (Enable/Disable Patches,Dry Run / Validate Only)offline_vf2_patcher.py+offline_vf2_patcher_gui.py— the patcherpayload/— modded EXE variants and all supporting assets/imagesmanifest.json, transparency log, and usage docs
How to use
- Run
Apply_B159_Patcher.batand point it at your officialVirtual Families 2.exe, or runLaunch_GUI.batfor the GUI. - The patcher validates the install is genuine, backs up under
.vf2_patch_backups, and writes a clearly labeled modded folder next to the vanilla one. - Vanilla VF2 saves are compatible with the modded version.
Local machine paths (patcher_local_settings.json) and Python caches are intentionally excluded from the download.
A passion project by Lorsieab2 in collaboration with Codex AI. No copyright infringement intended — please support the original game creators!
Redesigned
Purpose
Same test pre-release as Last Matrix Build -- built from the same main commit (109b4e3), same 19 feature-toggle variants, same seed directories -- but produced through a new, data-driven build engine (work/build_matrix.ps1) instead of the old pattern of hand-copying a whole build_bNNN_matrix.ps1 script per release. Published side-by-side with Last Matrix Build so the two can be compared directly.
What's different about how this one was built
- One reusable engine script plus two small JSON files (the stable 19-variant toggle matrix, and this release's exe name/output prefix/seed paths) replace what used to be a ~124-line script copied and hand-edited per release.
- The engine cross-checks each variant's generator manifest against whether a seed was actually configured for it, and fails closed if the two disagree -- catching exactly the kind of silent seed-state drift that has caused packaging surprises in past releases.
- Spot-validated before the full run: the engine's
corevariant output was byte-diffed against the legacy script'scoreoutput. Every code/data byte was identical; the only differences were the linker'sTimeDateStampfield and its mirrored debug-directory copy (ordinary non-determinism from re-linking at a different moment, not a functional difference). Seework/build_matrix_engine_validation.mdin the repo.
Validation performed
- All 19 executable variants built successfully; each passed its generator's manifest gate checks before linking.
- All 19 executables are byte-distinct (SHA-256), same as Last Matrix Build.
work/package_patcher_zip.py'svalidate_executable_inventory()ran automatically during packaging and passed cleanly (exactly one manifest record per executable, correctly gated, no path collisions, no missing payloads).- Same payload file count (6,842) as Last Matrix Build.
Not yet validated
- No live/in-game playtesting. Same outstanding QA as every other pre-release.
Package
Redesigned.zip- SHA-256:
7BCFA52A23CC39C77903D22CE2EEFEB5C3FB14DBE73880CCA79896FC13CE9DB3 - Size: 119,690,905 bytes (~114 MB)
A passion project by Lorsieab2 in collaboration with Codex AI/Claude. No copyright infringement intended -- please support the original game creators!
Last Matrix Build
Purpose
Test pre-release built directly from main (commit 109b4e3) using the existing per-release matrix build script pattern (same approach as B162/B162.1). Not yet playtested -- this is for QA/testing purposes, not a certified stable release.
What changed since the last numbered release (B162)
src/offline_vf2_patcher.pyandsrc/offline_vf2_patcher_gui.pysynced fromwork/'s copies and substantially expanded;src/export_offline_patch_bundle.py(a stale, untested fork) removed.work/patch_mobile_furniture_pack.pygenerator logic updated (+233/-63 lines).How to Use.txtcontent restored (had been lost onmain).- No native/compiled-code inputs changed beyond the generator script above -- confirmed by diffing every file touched since B162's tag.
What's inside
Apply_B163_Patcher.bat/Launch_GUI.bat-- drag/drop or enter your originalVirtual Families 2.exeto patch, or run the GUI.offline_vf2_patcher.py+offline_vf2_patcher_gui.py-- the patcher.payload/-- all 19 executable-toggle-combination overlays and supporting assets/images.manifest.json, transparency log, and usage docs.
Validation performed
- All 19 executable variants (core, cheat upgrades, mobile renovations, island events, holiday ornaments, behavior patches, and their combinations) built successfully; each variant's generated manifest passed its own gate checks (correct feature flags, correct row/asset counts) before linking.
- All 19 executables are byte-distinct -- confirmed via SHA-256, ruling out the duplicate-executable defect class that affected a prior B162 release.
work/package_patcher_zip.py'svalidate_executable_inventory()check (the same check that would have caught that prior defect: "Payload executable must have exactly one manifest asset record") ran automatically during packaging and passed cleanly.- Full Python unit test suite (142 tests) passes.
Not yet validated
- No live/in-game playtesting has been performed on this build. Purchase, save/reload, curtain, behavior, and native feature verification are still outstanding, same as every other pre-release pending manual QA.
Package
Last-Matrix-Build.zip- SHA-256:
54DF77DDEC51BBFDE9CF750215C6A720206E68415D93EDC94775ADF18C3CC6A6 - Size: 119,786,684 bytes (~114 MB)
A passion project by Lorsieab2 in collaboration with Codex AI/Claude. No copyright infringement intended -- please support the original game creators!
VF2 Patcher B164
VF2 Patcher B164
Release built from main at 3536b8a, covering PR #9 (Bathroom 1/2 curtain
hook verification and comment fix, plus a new Bathroom 2 native-renovation
purchase gate) and PR #10 (recreated the build_matrix.ps1 release engine,
fixed a real compile-ordering bug found while standing up this build, and
a P1 seed-identity verification fix).
What's new since the last published release
- Bathroom 1 & 2 curtain colors: verified the live curtain-color hooks
for both bathrooms against the real game disassembly (not just source
review) -- both ECX-preservation fixes check out correctly. - Bathroom 2 purchase gate (new): the five Bathroom 2 curtain-color rows
are no longer purchasable until the native second-bathroom renovation is
actually owned. Attempting to buy one now refunds the price in full
(including under an active Cheat Upgrades price multiplier) and shows
"Bathroom 2 must be renovated first before this can be bought." - All 19 feature-toggle executable variants rebuilt from current
mainand
verified byte-distinct.
What's inside
Apply_B164_Patcher.bat/Launch_GUI.bat-- run either to patch your own
Virtual Families 2.exe.offline_vf2_patcher.py/offline_vf2_patcher_gui.py-- the patcher.payload/-- all 19 modded EXE variants (one per feature-toggle
combination) and their supporting assets/images.manifest.json,Transparency Log.txt,How to Use.txt.
Validation performed
- Full
work/test suite: 266 passed; 2 pre-existing failures confirmed
present on unmodifiedmaintoo (missing local.objartifact for an
unrelated, untouched island-events feature -- not a regression). - All 19 executable variants compiled and linked cleanly; confirmed
byte-distinct (SHA-256). work/package_patcher_zip.py'svalidate_executable_inventory()ran
automatically during packaging and passed (one manifest record per
executable, correctly gated, no path collisions, no missing payloads).- Retroactively verified every one of the 19 variants was built from
exactly its intended seed, no cross-variant asset contamination. - Full build-environment and validation write-up in
docs/B164-release-notes.md.
Not yet validated
- No live/in-game playtesting. Same outstanding QA as every prior release:
purchase/remove each Bathroom 1/2 curtain color, the new Bathroom 2
blocked-purchase message, save/reload, and the rest of this build's
carried-forward feature set.
Package
VF2-B164-Release.zip- SHA-256:
1A443C3DF4EA0D9CB91DA898CEC70F46E132C5075833C07C28392AA85AB694D4 - Size: 93,668,875 bytes (~89.3 MB)
A passion project by Lorsieab2 in collaboration with Codex AI/Claude. No
copyright infringement intended -- please support the original game
creators!
VF2 Patcher B162 - Renovation and Special Upgrade Repair
B162 restores the native VF2 Home Renovation rows alongside the mobile renovation catalog.
Changes:
- Preserves native Home Renovation rows 0xE1-0xEA and appends the mobile renovation rows.
- Removes live Bathroom 1/Bathroom 2 curtain refresh calls from store clicks. Curtain colors are applied on normal game load/restart, and the Bathroom 2 click-crash route is removed.
- Keeps six stock Special Upgrades, adds four mobile Special Upgrade rows, and adds 36 Cheat Upgrade rows when Cheat Upgrades is enabled. The final all-enabled overlay has 46 Special Upgrade rows.
- Keeps Anti-Spam Software and Rockhound Certificate independently repurchaseable.
Verification:
- 19 generated overlay combinations; 19 unique executable SHA-256 hashes.
- Focused source regression tests: 5 passed.
- Repository tests: 35 passed.
- Special-upgrade/package tests: 22 passed.
- Exporter overlay tests: 5 passed.
- Bundle payload audit: 6,829 referenced payload paths, 0 missing.
Runtime/player launch, purchase, restart, save/reload, and Bathroom 2 crash-reproduction verification remains required.
ZIP SHA-256: 59FEB04EC375761E9973AFAE7522EEE1C8428DAF2CCD0670125C3C5D4BF2006E
B161 - Anti-Spam and Rockhound Repurchaseable
B161 makes Anti-Spam Software (0x33) and Rockhound Certificate (0x10A) independently repurchaseable in every patched executable, including saves where the persisted effect flag has already been cleared. Active rows use the zero-price removal route; inactive rows use the native purchase price/effect path.\n\nStatic/source/package validation passed. Live purchase, effect, save/reload, and player QA remain required.