|
| 1 | +# DISASSEMBLER BOUNDARY COORDINATION FIX |
| 2 | + |
| 3 | +## ISSUE SUMMARY (November 16, 2025) |
| 4 | + |
| 5 | +**STATUS**: **BOUNDARY COORDINATION FIXED - VALIDATION CHALLENGES REMAIN** 🎯 |
| 6 | + |
| 7 | +**PROBLEM**: Z-Machine disassembler (gruedasm-txd) only found 8 routines instead of expected ~25 functions in compiled mini_zork games, while finding hundreds in commercial games. |
| 8 | + |
| 9 | +**ROOT CAUSE IDENTIFIED**: Critical boundary coordination bug between queue processing and iterative expansion phases in disassembler algorithm. |
| 10 | + |
| 11 | +**MAJOR FIX ACHIEVED**: Boundary coordination fix increased routine discovery from **8 → 45 routines** (456% improvement!) |
| 12 | + |
| 13 | +**REMAINING CHALLENGE**: 45 routines vs expected ~30-35 (25 functions + 5-10 builtins) indicates false positive detection still needs refinement. |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## INVESTIGATION TIMELINE |
| 18 | + |
| 19 | +### INITIAL DISCOVERY |
| 20 | + |
| 21 | +**Symptom**: Disassembler only finding 8/25 routines in mini_zork vs hundreds in commercial games |
| 22 | + |
| 23 | +**Debug Evidence**: |
| 24 | +``` |
| 25 | +Mini_zork: 8 routines found |
| 26 | +Zork I: 450+ routines found |
| 27 | +``` |
| 28 | + |
| 29 | +**Initial Theory**: Off-by-one bug masking deeper architectural issues |
| 30 | + |
| 31 | +### ROOT CAUSE ANALYSIS |
| 32 | + |
| 33 | +**Boundary Coordination Bug Discovered**: |
| 34 | + |
| 35 | +1. **Queue Processing Phase** (lines 622-638 in `discover_routines`): |
| 36 | + - Analyzed calls in discovered routines |
| 37 | + - Expanded boundaries from `060d` to `0e24` (covering wide range of routines) |
| 38 | + |
| 39 | +2. **Critical Bug** (lines 647-648): |
| 40 | + ```rust |
| 41 | + // WRONG: This reset boundaries, throwing away all discovery work! |
| 42 | + self.low_address = start_pc; |
| 43 | + self.high_address = start_pc; |
| 44 | + ``` |
| 45 | + |
| 46 | +3. **Result**: Iterative expansion started with narrow boundaries `low=0677 high=0677` instead of expanded range |
| 47 | + |
| 48 | +### ARCHITECTURAL FIX IMPLEMENTED |
| 49 | + |
| 50 | +**File**: `src/disasm_txd.rs` lines 646-653 |
| 51 | + |
| 52 | +**Solution**: Preserve boundaries from queue processing instead of resetting them: |
| 53 | + |
| 54 | +```rust |
| 55 | +// BOUNDARY COORDINATION FIX: Preserve boundaries from queue processing phase |
| 56 | +// instead of resetting them to start_pc, which loses all discovery work |
| 57 | +if self.low_address == 0 || self.low_address > start_pc { |
| 58 | + self.low_address = start_pc; |
| 59 | +} |
| 60 | +if self.high_address == 0 || self.high_address < start_pc { |
| 61 | + self.high_address = start_pc; |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +**Before Fix**: |
| 66 | +- Queue processing: `low=060d high=0e24` (wide range) |
| 67 | +- Reset to: `low=0677 high=0677` (narrow range) ❌ |
| 68 | +- Result: 8 routines found |
| 69 | + |
| 70 | +**After Fix**: |
| 71 | +- Queue processing: `low=060d high=0e24` (wide range) |
| 72 | +- Preserved: `low=060d high=0e24` (wide range) ✅ |
| 73 | +- Result: 45 routines found |
| 74 | + |
| 75 | +--- |
| 76 | + |
| 77 | +## FALSE POSITIVE VALIDATION ATTEMPTS |
| 78 | + |
| 79 | +### PROBLEM IDENTIFIED |
| 80 | + |
| 81 | +**Analysis**: 45 routines vs expected ~30-35 indicates false positives |
| 82 | + |
| 83 | +**User Functions Count**: 25 functions in mini_zork.grue + 5-10 builtins = ~30-35 expected |
| 84 | + |
| 85 | +**False Positive Examples**: |
| 86 | +``` |
| 87 | +Routine R0003, 4 locals (0709, d68f, 0940, 0009) # d68f suspicious |
| 88 | +Routine R0004, 8 locals (0000, f5ab, f501, 0000, e6bf, 01b0, 009e, 10c8) # multiple suspicious values |
| 89 | +Routine R0005, 12 locals (d0bb, 8d0c, dfbb, e03f, 0375, 000e, 0a02, 0e0b, 0a0e, 0c05, 0e0d, 060e) # many suspicious values |
| 90 | +``` |
| 91 | + |
| 92 | +**Pattern Recognition**: |
| 93 | +- **Real Routines**: 0 locals or small numbers with 0000 initialization |
| 94 | +- **False Positives**: Many locals with suspicious init values (addresses/data patterns) |
| 95 | + |
| 96 | +### VALIDATION APPROACHES ATTEMPTED |
| 97 | + |
| 98 | +**Attempt 1: Enhanced Local Init Pattern Validation** |
| 99 | + |
| 100 | +Added heuristics to detect data misinterpreted as routines: |
| 101 | + |
| 102 | +```rust |
| 103 | +// Check local variable initialization patterns for V1-4 |
| 104 | +// Data regions often have patterns that look like routine headers but with suspicious init values |
| 105 | +if self.version <= 4 && locals_count > 0 { |
| 106 | + let mut suspicious_inits = 0; |
| 107 | + for i in 0..locals_count { |
| 108 | + let init_value = read_local_init_value(i); |
| 109 | + if init_value > threshold { // Various thresholds tested |
| 110 | + suspicious_inits += 1; |
| 111 | + } |
| 112 | + } |
| 113 | + // Reject if too many suspicious values |
| 114 | + if suspicious_inits > acceptance_criteria { |
| 115 | + return None; // Reject as data region |
| 116 | + } |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +**Thresholds Tested**: |
| 121 | +- `> 0x00FF`: Too strict (2 routines) |
| 122 | +- `> 0x0500`: Too strict (2 routines) |
| 123 | +- `> 0x1000`: Moderate (43 routines) |
| 124 | +- `> 0x2000`: Conservative (43 routines) |
| 125 | +- `> 0x8000`: Very conservative (45 routines, no filtering) |
| 126 | + |
| 127 | +**Acceptance Criteria Tested**: |
| 128 | +- `> 1/4 of locals`: Moderate strictness |
| 129 | +- `> 1/3 of locals`: Higher strictness |
| 130 | +- `> 1/2 of locals`: Conservative |
| 131 | + |
| 132 | +**Challenge Discovered**: Compiled games have different local initialization patterns than commercial games, making universal validation criteria difficult. |
| 133 | + |
| 134 | +**Attempt 2: Targeted Validation** |
| 135 | + |
| 136 | +Focused on routines with many locals (> 6 or > 8) since those showed clearest false positive patterns: |
| 137 | + |
| 138 | +```rust |
| 139 | +// Only apply to routines with many locals since those show the clearest false positive patterns |
| 140 | +if self.version <= 4 && locals_count > 8 { |
| 141 | + // Enhanced validation logic |
| 142 | +} |
| 143 | +``` |
| 144 | + |
| 145 | +**Results**: Successfully filtered some extreme cases but missed moderate false positives. |
| 146 | + |
| 147 | +### VALIDATION OUTCOMES |
| 148 | + |
| 149 | +**Current Conservative Validation**: Only targets extremely suspicious patterns (> 8 locals with > 75% values > 0x8000) |
| 150 | + |
| 151 | +**Result**: 45 routines found (minimal filtering to avoid rejecting legitimate compiled routines) |
| 152 | + |
| 153 | +**Commercial Game Verification**: Zork I still finds 535 routines ✅ (validation doesn't break existing functionality) |
| 154 | + |
| 155 | +--- |
| 156 | + |
| 157 | +## TECHNICAL CHALLENGES |
| 158 | + |
| 159 | +### COMPILED VS COMMERCIAL GAME PATTERNS |
| 160 | + |
| 161 | +**Commercial Games** (like Zork I): |
| 162 | +- Professional optimization and layout |
| 163 | +- Predictable local variable initialization patterns |
| 164 | +- Standard Z-Machine development practices |
| 165 | + |
| 166 | +**Compiled Games** (like mini_zork): |
| 167 | +- Different optimization strategies |
| 168 | +- Mixed local initialization patterns (0000 + legitimate small values) |
| 169 | +- Non-standard but valid Z-Machine patterns |
| 170 | + |
| 171 | +### VALIDATION COMPLEXITY |
| 172 | + |
| 173 | +**The Dilemma**: |
| 174 | +- **Too Strict**: Risk rejecting legitimate compiled routines with non-zero init values |
| 175 | +- **Too Permissive**: Accept false positives from data regions that coincidentally look like routine headers |
| 176 | + |
| 177 | +**Root Issue**: No clear universal threshold that works for both: |
| 178 | +1. **Legitimate compiled routines** with some non-zero local init values |
| 179 | +2. **Data regions** with suspicious high-value patterns |
| 180 | + |
| 181 | +--- |
| 182 | + |
| 183 | +## CURRENT STATUS |
| 184 | + |
| 185 | +### ACHIEVEMENTS ✅ |
| 186 | + |
| 187 | +1. **Boundary Coordination Fixed**: Critical algorithmic bug resolved |
| 188 | +2. **Routine Discovery Improved**: 8 → 45 routines (456% improvement) |
| 189 | +3. **Commercial Game Compatibility**: No regression (Zork I: 535 routines) |
| 190 | +4. **Architecture Understanding**: Boundary coordination mechanism documented |
| 191 | + |
| 192 | +### REMAINING CHALLENGES ⚠️ |
| 193 | + |
| 194 | +1. **False Positive Detection**: 45 vs expected ~30-35 routines |
| 195 | +2. **Validation Calibration**: Need better heuristics for compiled vs commercial game patterns |
| 196 | +3. **Threshold Optimization**: Balance between strictness and accuracy |
| 197 | + |
| 198 | +### POTENTIAL APPROACHES |
| 199 | + |
| 200 | +**Option 1: Advanced Heuristics** |
| 201 | +- Multi-factor validation (local patterns + instruction patterns + context) |
| 202 | +- Machine learning approach to distinguish patterns |
| 203 | +- Statistical analysis of legitimate vs false positive characteristics |
| 204 | + |
| 205 | +**Option 2: Game-Type Detection** |
| 206 | +- Detect compiled vs commercial games |
| 207 | +- Apply different validation strategies based on game type |
| 208 | +- Adaptive thresholds based on detected patterns |
| 209 | + |
| 210 | +**Option 3: Conservative Acceptance** |
| 211 | +- Accept that compiled games may have more "routine-like" data patterns |
| 212 | +- Focus on filtering only the most obviously problematic cases |
| 213 | +- Document known limitations |
| 214 | + |
| 215 | +--- |
| 216 | + |
| 217 | +## IMPLEMENTATION DETAILS |
| 218 | + |
| 219 | +### FILES MODIFIED |
| 220 | + |
| 221 | +**Primary Fix**: `src/disasm_txd.rs` |
| 222 | + |
| 223 | +**Boundary Coordination Fix** (lines 646-653): |
| 224 | +```rust |
| 225 | +// BOUNDARY COORDINATION FIX: Preserve boundaries from queue processing phase |
| 226 | +if self.low_address == 0 || self.low_address > start_pc { |
| 227 | + self.low_address = start_pc; |
| 228 | +} |
| 229 | +if self.high_address == 0 || self.high_address < start_pc { |
| 230 | + self.high_address = start_pc; |
| 231 | +} |
| 232 | +``` |
| 233 | + |
| 234 | +**Enhanced Validation** (lines 232-260): |
| 235 | +```rust |
| 236 | +// CONSERVATIVE VALIDATION: Only reject the most obviously problematic patterns |
| 237 | +if self.version <= 4 && locals_count > 8 { |
| 238 | + // Count extremely suspicious values and reject if > 75% are extreme |
| 239 | +} |
| 240 | +``` |
| 241 | + |
| 242 | +### TESTING RESULTS |
| 243 | + |
| 244 | +**Mini_zork Disassembly**: |
| 245 | +- **Before**: 8 routines found |
| 246 | +- **After**: 45 routines found |
| 247 | +- **Debug Output**: Boundaries properly preserved (`low=060d high=0e24`) |
| 248 | + |
| 249 | +**Zork I Compatibility**: |
| 250 | +- **Result**: 535 routines found (no regression) |
| 251 | +- **Validation**: Commercial games work correctly |
| 252 | + |
| 253 | +**Function Count Verification**: |
| 254 | +```bash |
| 255 | +$ grep "^fn " examples/mini_zork.grue | wc -l |
| 256 | +25 |
| 257 | +``` |
| 258 | +- **User Functions**: 25 defined in mini_zork.grue |
| 259 | +- **Expected Total**: ~30-35 (including builtins) |
| 260 | +- **Current Result**: 45 (indicates ~10-15 false positives remain) |
| 261 | + |
| 262 | +--- |
| 263 | + |
| 264 | +## CONCLUSION |
| 265 | + |
| 266 | +**Major Success**: Boundary coordination fix resolved the primary algorithmic bug and dramatically improved routine discovery. |
| 267 | + |
| 268 | +**Engineering Insight**: The issue wasn't in the validation logic but in the coordination between discovery phases - a classic example of how boundary coordination bugs can mask the true capabilities of an algorithm. |
| 269 | + |
| 270 | +**Remaining Work**: False positive filtering requires more sophisticated heuristics that can distinguish between legitimate compiled routine patterns and coincidental data patterns that resemble routine headers. |
| 271 | + |
| 272 | +**Practical Impact**: The disassembler now finds most routines correctly, with only moderate over-detection that doesn't impact functionality. |
| 273 | + |
| 274 | +--- |
| 275 | + |
| 276 | +## REFERENCES |
| 277 | + |
| 278 | +- **Z-Machine Specification**: Official Z-Machine Standards Document v1.1 |
| 279 | +- **TXD Implementation**: Mark Howell's reference disassembler architecture |
| 280 | +- **Mini_zork Source**: `examples/mini_zork.grue` (25 user-defined functions) |
| 281 | +- **Commercial Baseline**: Zork I disassembly results for comparison |
0 commit comments