diff --git a/game/reconstructed/btl4galm.cpp b/game/reconstructed/btl4galm.cpp index 501dedb..43861f3 100644 --- a/game/reconstructed/btl4galm.cpp +++ b/game/reconstructed/btl4galm.cpp @@ -163,8 +163,13 @@ static const int kBTQuadModeMask[12] = { 0x1,0x1,0x1,0x1, 0x20,0x20,0x20,0x20, 0 static const int kBTEngModeMask[12] = { 0x2,0x4,0x8,0x10, 0x40,0x80,0x100,0x200, 0x800,0x1000,0x2000,0x4000 }; static const int kBTQuadLamp[12] = { 0xF,0xD,0xB,0x9, 0x27,0x25,0x23,0x21, 0x7,0x5,0x3,0x1 }; static const int kBTEngBankTop[12] = { 0xF,0xF,0xF,0xF, 0x27,0x27,0x27,0x27, 0x7,0x7,0x7,0x7 }; -// (the per-condenser lamp table that used to live here is retired: condenser N -// resolves through BTFixedLampOf(N-1), the same six cooling-loop lamps. #98) +// @0051d058 per-condenser lamps, BYTE-VERIFIED from the image (int32 each): +// 07 2F 2E 2D 2B 2A 29 ... indexed 1-BASED by condenserNumber (+0x1D4), +// so slot 0 is unused and condensers 1..6 -> 2F 2E 2D 2B 2A 29. +// Deliberately NOT the coolingLoop set of FUN_004cc148 (which has 0x2C and +// no 0x29) -- overlapping but distinct lamps. Slot 6 (0x29) is also +// DAT_0051d070[0], the first per-placement lamp: the two tables abut. +static const int kBTCondenserLamp[7] = { 0x7, 0x2F,0x2E,0x2D,0x2B,0x2A, 0x29 }; static const int kBTPlacementLamp[5] = { 0x29, 0x1A,0x1B,0x1C,0x1D }; // [auxScreenPlacement] // @@ -292,21 +297,30 @@ void // #98 -- "I'm getting leaks but no indicators" / "the display // buttons aren't ALWAYS flashing on leaking components". // - // condenserNumber is 1-BASED (verified live: 'Condenser6' reports 6), - // which the old table's own comment said -- but the guard was - // `n >= 0 && n < 6`, a 0-based bound. Condenser 6 was therefore - // REJECTED outright and could never annunciate, and the table it - // indexed was missing 0x2C, so condensers 4 and 5 flashed the NEXT - // loop's button instead of their own. Three of six correct, one - // silent, two lying -- exactly the "sometimes" players reported. + // FUN_004cc264 is literally: + // return *(int *)(&DAT_0051d058 + sub[0x1d4] * 4); + // -- indexed by condenserNumber with NO bounds check. The table + // bytes at 0051d058 are, verified from the image: + // 07 2F 2E 2D 2B 2A 29 ... (int32 each) + // and condenserNumber is 1-BASED (live: 'Condenser6' reports 6), so + // slot 0 (0x7) is unused and condensers 1..6 map to + // 0x2F 0x2E 0x2D 0x2B 0x2A 0x29. + // NOTE these are NOT the coolingLoop1..6 lamps of FUN_004cc148 + // (0x2F 0x2E 0x2D 0x2C 0x2B 0x2A) -- the condenser set skips 0x2C + // and ends on 0x29. They overlap but are different lamps; do not + // "correct" one into the other (I did, and it mis-mapped 4, 5 and 6). // - // Condenser N drives cooling-loop N, whose six lamps are the same - // ones the coolingLoop1..6 codes resolve to, so use that verified - // map rather than a second, partly-wrong copy of it. + // THE PORT BUG was only the bounds check: `n >= 0 && n < 6` is a + // 0-based bound on a 1-based index, so condenser 6 was rejected and + // annunciated NOTHING, while the binary resolves it to 0x29. Six + // condensers, one permanently silent -- which is what players read as + // "sometimes". The guard now admits 1..6 (kept, unlike the binary's + // unchecked read, so a stray authored number cannot walk off the + // table into the adjacent per-placement one). // int n = BTCondenserNumber(the_subsystem); if (n >= 1 && n <= 6) - lamp_id = BTFixedLampOf(n - 1); // loop N -> its own button + lamp_id = kBTCondenserLamp[n]; } } else if (BTSubsystemIsGenerator(the_subsystem))