P0: fix build (levelpath in CMake, FLOOR_LIN, exact LUT curve formulas), robust RPP param decoder (607 rpp ok), preserve f_52b570/f529fe0 disasms

This commit is contained in:
2026-08-19 21:54:26 +03:00
parent 55623b998f
commit 58164f2952
3 changed files with 99 additions and 88 deletions
+35 -56
View File
@@ -24,7 +24,7 @@
#include <cstdint>
// Constants extracted from binary
static constexpr float SCALE = 0.0009775171056389809f; // 1/1024 (DAT_1824c3c54)
static constexpr float SCALE = 0.0009775171056389809f; // 1/1023 (DAT_1824c3c54, verified 2026-08-19)
static constexpr float ONE = 1.0f; // DAT_1824c3ea4
static constexpr float TWO = 2.0f; // DAT_1824c41e0
static constexpr float NEG1 = -1.0f; // DAT_1824c4680
@@ -33,7 +33,7 @@ static constexpr float ZERO = 0.0f; // DAT_1824c4140
static constexpr float DEPTH_SCALE = 4.0f; // DAT_1824c4334
static constexpr float DB_CONV = 8.68588924407959f; // 20/ln(10) (DAT_1824c43e0)
static constexpr float FLOOR_DB = -6.907755374908447f; // ln(0.001) (DAT_1824c4704)
static constexpr float FLOOR LIN = 0.001f; // exp(FLOOR_DB)
static constexpr float FLOOR_LIN = 0.001f; // exp(FLOOR_DB)
// PRNG state offsets from param_1
static constexpr int PRNG_STATE = 0x2404e0;
@@ -51,68 +51,47 @@ struct BandConfig {
void* callback; // +0x50: vtable callback (if non-null, use callback)
};
// LUT evaluation for a single bin
// x is in [0, 1] range
// Structural LUT curve (f_563440.dis, exact transcription 2026-08-19)
// x in [0,1], gamma == band->threshold (offset +0x0c), A=+0x00, B=+0x04
static float eval_lut_bin(float x, const BandConfig* band) {
// Path 1: callback exists → use vtable
if (band->callback != nullptr) {
// TODO: transcribe callback vtable call
return x;
}
// Path 2: power-law (flag != 0 and threshold != 1.0)
if (band->flag != 0 && band->threshold != ONE) {
float C = band->threshold;
// x = 2*x - 1 (center at zero: [-1, 1])
float centered = TWO * x - ONE;
if (C == ONE || centered == ZERO) {
// fall through to linear
} else {
// sign(x) * 10^(log10(|x|) / C)
float sign = (centered < ZERO) ? NEG1 : ONE;
// absolute value: |x|
float abs_x = fabsf(centered);
// if abs_x > 0: result = sign * exp(log(|x|) * (1/C))
if (abs_x > ZERO) {
float log_val = log10f(abs_x);
float result = powf(10.0f, log_val / C);
centered = sign * result;
}
// fall through to linear with transformed x
x = centered * HALF + HALF; // remap back to [0,1]
float gamma = band->threshold;
float result;
if (band->flag == 0) {
// Linear path (0x563595): t = x^(1/γ) if γ!=1 && x>0; val = A + (B-A)*t
float t = x;
if (gamma != ONE && x > ZERO) {
double d = static_cast<double>(fabsf(x));
d = std::log(d) / static_cast<double>(gamma);
t = static_cast<float>(std::exp(d));
}
result = band->A + (band->B - band->A) * t;
} else {
// Power-law path (0x5635cd): t = 2x-1; if γ!=1 && t!=0: t = sign(t)·|t|^(1/γ)
// val = A + (B-A)·0.5·(1+t)
float t = TWO * x - ONE;
if (gamma != ONE && t != ZERO) {
float sign = (t < ZERO) ? NEG1 : ONE;
double d = static_cast<double>(fabsf(t));
d = std::log(d) / static_cast<double>(gamma);
t = static_cast<float>(std::exp(d)) * sign;
}
result = band->A + (band->B - band->A) * HALF * (ONE + t);
}
// Path 3: linear interpolation (always applied after transform)
float slope = band->B - band->A;
return slope * x + band->A;
return result;
}
// FUN_180563440: LUT curve evaluation for 1024 bins
// r13 = context pointer (param_1)
// Reads: band config at r13+0x188 (one per band)
// Writes: output at r13+0x198 (1024 doubles, stride 8)
void lut_curve_eval(void* ctx, int bin_start, int bin_end) {
// FUN_180563440: LUT curve evaluation for 0x400 bins
// r13 = context pointer (param_1). Loop counter edi, x = i*SCALE clamp[0,1],
// band config read from r13+0x188 each iteration (rbx), output double at r13+0x198[i*8].
void lut_curve_eval(void* ctx) {
auto* base = static_cast<uint8_t*>(ctx);
int band_count = *reinterpret_cast<int*>(base + 0x540868);
if (band_count <= 0) {
// Initialize with default 0x800 bins
band_count = 0x800; // 2048? or 1024?
}
// Output pointer: r13+0x198
double* output = reinterpret_cast<double*>(base + 0x198);
// Evaluate LUT curve for each bin (0x400 = 1024 iterations)
for (int bin = 0; bin < 0x400; bin++) {
BandConfig* band = reinterpret_cast<BandConfig*>(base + 0x188);
for (int bin = 0; bin < 0x400; bin++) { // cmp $0x400 jl
float x = static_cast<float>(bin) * SCALE;
x = fminf(fmaxf(x, ZERO), ONE); // clamp to [0, 1]
BandConfig* band = reinterpret_cast<BandConfig*>(base + 0x188);
float result = eval_lut_bin(x, band);
// Store as double-precision (line 196: cvtss2sd + movsd [rsi])
output[bin] = static_cast<double>(result);
x = fminf(x, ONE);
if (x < ZERO) x = ZERO;
output[bin] = static_cast<double>(eval_lut_bin(x, band));
}
}