Some sounds worked, and I couldn’t tell whether combat was supposed to be this quiet. We went looking. The selected handset build could play audio, and the missing attack and impact sounds were sitting in its resources.

Already in the package

The audio investigation finds eight dormant PCM WAV entries beside the enabled clips. The selected 1.4.58 build loads only its first three sound slots and rejects requests used by ordinary attack and impact paths. A comparison with an original full-audio 1.4.46 variant gives those dormant requests somewhere specific to go.G03

We followed the native requests into the original sound controller. Pressing Attack wouldn’t simply trigger a punch noise from the bridge: the game still decided when an impact happened, which request was active and what priority got played.

The original behavior stays selectable, and the game’s own Sound setting still wins. Those choices matter here because this handset edition really did disable those effects. The recovery is an optional restoration of material the game already carries, rather than a new soundtrack laid over it.G03

A wrong label was hiding in plain sight

The earlier “GRAB/CYCLE” wording also turns out to be wrong. Original help text and handlers put grabbing, chests and levers on Down/8. Star and the left softkey handle weapon or magic cycling. Two useful actions had been muddled together by the bridge label.G04

We corrected the labels to follow the game’s current prompts and original grab conditions. Down still sent Down. Fire still sent Fire when the prompt became Finish. I shouldn’t have to memorize a misleading label to use the original action.

Then the phone disagrees

Then 0.1.2 came back from the phone with zero frames, zero audio starts and one fault. We weren’t even getting far enough to hear whether the combat sounds worked.G01

The loader calls getClassLoadingLock(String), a method the investigation identifies as absent from Android’s ClassLoader API. The earlier compile had resolved that base class through the desktop JDK. The host replay ran host classfiles and skipped the Android DEX installation path. It had passed the route it exercised; the phone had found the route it had not.G02

We had to separate that failure from the sound repair. A compatibility mistake in the loader had stopped the entire game before it rendered a frame. Passing the host replay hadn’t exercised the route the phone needed.

Make that failure useful

The 0.1.3 loader uses its own monitor for class lookup and definition. The new build gate compiles against Android’s actual boot-class API. The old loader now fails the check at the very method the phone complained about; the repaired one passes, and the signed DEX no longer references it.G02

With the loader repaired, the host could again run real first-level movement, grabbing and finishers, sound on/off, restoration on/off and lifecycle transitions. We also had a check that would reject the earlier loader mistake. The phone fault had shown us something the old test wasn’t looking for.G05

About these records

The inspected 0.1.3 handoff ends with phone startup, audible restored effects, touch, save/load and Omni acceptance still open. Framework audio uses a shadow; the rage-specific sound path and full campaign were not completed. Those are the endpoint of this window, not extra setbacks invented for the story.

The receipts

Selected report lines, investigation notes and recorded feedback behind the story. Each receipt keeps its source and context.

G01 / The phone stops before its first framePhone fault report

Source: God of War: Betrayal v0.1.2 / startup-fault report · selected lines 3–9

Device-identifying and app-installation-path lines are omitted.

Report reason: startup-fault
God of War: Betrayal Bridge v0.1.2
Original MIDlet 1.4.58 Nokia 352x416; original code with one-byte optional audio-request hook
Original SHA256: 42c829b3dbe2f5d21cd940b8ecedbca94f8a34e9054eb152a892785ebba42a29
frames=0 lastFrameAgeMs=1792971649420
active=true ended=false keys=0 pending=1
shimResourceReads=0 rmsWrites=0 faults=1 audioStarts=0
G02 / Why a desktop compile missed an Android API failureRegression investigation

Source: God of War: Betrayal v0.1.3 / VERIFICATION.txt · selected lines 4–18

The attached SM-S938U Android 17 reports show frames=0 and NoSuchMethodError:
getClassLoadingLock(String), in OriginalGameLoader.loadClass at line 41.
The Android SDK ClassLoader API omits that desktop-JDK method. javac with only
-classpath android.jar had resolved java.lang.ClassLoader from the desktop JDK.
The prior Engine framework replay uses host classfiles and skips device DEX
installation, so its passing result never verified this failing path.

The loader now synchronizes its own monitor while looking up/defining the six
original game classes. Class selection, resolution, resource delegation and
read-only content-addressed DEX cache behavior are preserved.
BUILD_LINUX.sh requires tools/check_loader_android_api.py, compiling the loader
with Android's actual boot-class API. The unchanged v0.1.2 source fails this
check at the exact reported method; the v0.1.3 source passes. The signed APK's
bridge DEX contains no getClassLoadingLock method reference.
This is compile/API evidence, not actual Android DEX execution.
G03 / The dormant sound resources and original filteringAudio investigation

Source: God of War: Betrayal v0.1.3 / history-v012 / AUDIO_AUDIT.txt · selected lines 3–15, 24–37

The phone recording1000103755.mp4 contains selected original WAV1062 around
2.563,5.083,12.286seconds (waveform correlation0.9963). The enabled game audio was
working; ordinary attack/impact paths were disabled inside the original build.
The phone report has nativeSound=on,0faults and enabled WAV playback completions.

RP1 has11 audio entries: eight dormant PCM WAV entries1054..1061, plus enabled
WAV1062, MIDI1063 and WAV1064. Some dormant entries are identical audio bytes.
Original1.4.58 only loads sound0=1063,1=1064,2=1062 and rejects requested IDs3/4.

Original full-audio mapping reference from the same36-variant archive:
God of War - Betrayal [1.4.46] [LockedRes] [352x416] [En,Fr,Es,De,It,Pt].jar
Its loader initializes slot i with resource1054+i for i0..10. Original y(int)
passes sound IDs to its controller without the selected edition's filtering.

[... selected excerpt ...]


The prepared e.class changes a single existing constant-pool owner byte6->2 at
2804, invoking inherited Canvas.J. The original private e.J body remains exact.
Off delegates every request to that original routine. On restores disabled3/4
using the original d controller's unused slots3..10, single-play, priority0.
Original Sound off and controller priority remain authoritative. Transient
restored effects are cleared before background and on native menus.

Current native replay records24+ backend starts with zero faults and no unmapped
requests. Native d.v forwards now include5,6,9,10 for confirmed ordinary impacts
and attack movement. Off and original mute/unmute scenarios pass via normal keys.
Rage mappings are original-source audited but unreached in first-level play.
See restoration-replay-run.log, audio-hook-audit.json, audio-source-checks.json.
Phone audible output and Android DEX boot remain pending actual-device testing.
G04 / GRAB/CYCLE was a bridge-label mistakeOriginal-control investigation

Source: God of War: Betrayal v0.1.3 / CONTROL_MAPPING_CORRECTION.txt · selected lines 1–13

Native text181 says press glyph } to grab; text114 identifies } as Down/8.
Native text219 uses the same Down glyph for opening chests/pulling levers.
Native text213 assigns * or Left Soft Key to weapons/magic. Original e.g(boolean)
handles internal10 (*) and27 (LSK) identically for weapon cycling. Internal6
(Down/8) calls e.M(), the native grab/use routine. Original a.G maps Down to -2
and numeric8 to56. The old GRAB/CYCLE wording was a bridge-label error.

Original softkey draw helper e.a(Graphics,int,int) writes kU/kV, then draws the
chosen native labels from a.m/a.n UTF8 text. Observer reads those exact fields
on the worker after paint. It does not guess a label from a screenshot/state map.
Original e.M's weak soldier conditions are observed read-only, including ground,
idle/lock gates, companion exclusion, recovery timer, health, overlap and walls.
The actual replay proves contextual GRAB -> original Down -> native pose12.
G05 / The final handoff still leaves phone acceptance openCheckpoint summary

Source: God of War: Betrayal v0.1.3 / VERIFICATION.txt · selected lines 20–38, 50–52

CURRENT VALIDATION
12 Robolectric/API34 UI tests pass: cold UI construction, native-sized viewport,
input ownership, inline control switching, softkey labels, Back/report wiring,
restoration utility and saved preference. No shared UI kit source was changed.
2 real Engine/resource framework tests pass: original rendered frames, native
shutdown, background/resume, responsive report and saved sentinel/re-entry;
parent stream delegation for Omni's imported original-root resources.
MediaPlayer uses a framework shadow. No audible output is claimed.

The real original host replay passes its first-level movement, jump, block,
Down grab and finisher, weapon and upgrades actions. It also checks optional
restoration and original Sound off/on, background/resume and original worker
shutdown/static re-entry, with zero runtime faults. It sends ordinary input
without writing health, position, progress, RNG or original timing state.

The actual Omni 0.5.7 generic Python preparer and GuestCompiler reproduce all
six prepared guest DEX files exactly. The stripped capsule leaves original and
derived bytes empty/absent and includes no original class definitions in the
bridge DEX. Production phone import/two cumulative exports remain pending.

[... selected excerpt ...]

Physical-phone v0.1.3 install/cold DEX startup, audible restored combat effects,
touch comfort/Downloads/save-load and production Omni acceptance. Full game
completion and the native rage-specific audio path have not been played.
Continue through the archiveDeadShot →