Skip to content
This repository was archived by the owner on May 31, 2026. It is now read-only.

Commit e2bffc4

Browse files
Paradoxdovclaude
andcommitted
v0.4.19: human-readable verdict text — no more "?" / "□" hieroglyphs
Field feedback (Habr): users were asking the developer what "?", "(chip ?)" and "□" mean on the verdict screen. The verdict is supposed to be for a shop technician / customer, not a developer who reads the source. If a text needs explanation, it's bad text. Three fixes: 1. Bullet character "•" (U+2022) was missing from our bundled bitmap font and rendered as a "missing glyph" box "□" before every list item. Replaced with "●" (U+25CF) which IS in the font. 2. "(chip ?)" appeared when SPD didn't expose chip width (typical on DDR4 x4 modules). Replaced with explicit prose: "Стуковый бит D[53] на планке (24 ошибок). SPD не сообщил ширину чипа — точный U-номер чипа не определить." Same in English. The verdict now branches: if SPD width known, show exact chip designator (U1..U16); if not, say so plainly instead of leaving a dangling "?". 3. "?" in the "Затронуто: A2 (8), B2 (11), ? (5)" line meant "errors at addresses not in any SMBIOS Type 20 region" — but nobody knew that. Now displayed as "вне SMBIOS-карты" / "unmapped region". Section header changed from "Затронуто:" to "Ошибки по планкам:" so the intent is obvious without context. Also fixed: when DIMM is identifiable but chip is not, the technical detail line now shows DIMM info ("DIMM2 (точный чип не определён по SPD)") instead of dropping to a generic "stuck bit + XOR mask" line that hid the DIMM number. No behavior changes; this is purely UI text + font glyph fix. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent f72743d commit e2bffc4

3 files changed

Lines changed: 77 additions & 52 deletions

File tree

MemForge2.src.c

Lines changed: 75 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ static void init_splash(CHAR16 *stage) {
839839
cls();
840840
UINTN cy = g_h / 2;
841841
/* Title — large centered line. */
842-
CHAR16 *title = L"MEMFORGE v0.4.18";
842+
CHAR16 *title = L"MEMFORGE v0.4.19";
843843
UINTN tx = (g_w - StrLen(title) * g_char_w) / 2;
844844
gfx_draw_str_color(tx, cy - g_char_h * 2, title, COL_ACCENT_HI);
845845
/* Stage indicator — what we're doing right now. */
@@ -943,7 +943,7 @@ static UINTN g_card_cols = 1;
943943
compute_layout(). */
944944
static int g_show_cards = 1;
945945

946-
/* v0.4.18 — focused cards layout for small screens (g_h < 900).
946+
/* v0.4.19 — focused cards layout for small screens (g_h < 900).
947947
Instead of one full-width row per test (14 rows × ~40 px = 560 px,
948948
which on a 1024×768 screen eats 70% of vertical space and clips the
949949
core panel + footer), we draw:
@@ -1013,7 +1013,7 @@ static void compute_layout(UINTN n_tests) {
10131013
g_card_w = g_inner;
10141014
g_card_row_h = g_compact ? g_char_h : (g_char_h + 16);
10151015

1016-
/* v0.4.18 — focused layout on small screens.
1016+
/* v0.4.19 — focused layout on small screens.
10171017
On g_h<900 the per-test card list eats 60-70% of vertical space
10181018
and clips the core panel / footer (YgrecK field report on 1024×768
10191019
Radeon HD 4350). Replace with: 1-row strip of all test dots +
@@ -1227,9 +1227,9 @@ static void render_header(UINT64 elapsed_ms, UINTN done, UINTN total) {
12271227
UINTN cols = g_text_cols;
12281228
if (cols >= 110) {
12291229
SPrint(buf, sizeof(buf),
1230-
T(L" MEMFORGE v0.4.18 | %ld.%ld ГБ RAM | %s "
1230+
T(L" MEMFORGE v0.4.19 | %ld.%ld ГБ RAM | %s "
12311231
L"| %s | %02d:%02d | ост ~%02d:%02d | Тесты %d/%d",
1232-
L" MEMFORGE v0.4.18 | %ld.%ld GB RAM | %s "
1232+
L" MEMFORGE v0.4.19 | %ld.%ld GB RAM | %s "
12331233
L"| %s | %02d:%02d | ETA ~%02d:%02d | Tests %d/%d"),
12341234
ram_gb_x10 / 10, ram_gb_x10 % 10,
12351235
pass_tag,
@@ -1239,25 +1239,25 @@ static void render_header(UINT64 elapsed_ms, UINTN done, UINTN total) {
12391239
(UINT32)done, (UINT32)total);
12401240
} else if (cols >= 90) {
12411241
SPrint(buf, sizeof(buf),
1242-
T(L" MEMFORGE v0.4.18 | %ld.%ld ГБ RAM | %s | %s | %02d:%02d | ост ~%02d:%02d",
1243-
L" MEMFORGE v0.4.18 | %ld.%ld GB RAM | %s | %s | %02d:%02d | ETA ~%02d:%02d"),
1242+
T(L" MEMFORGE v0.4.19 | %ld.%ld ГБ RAM | %s | %s | %02d:%02d | ост ~%02d:%02d",
1243+
L" MEMFORGE v0.4.19 | %ld.%ld GB RAM | %s | %s | %02d:%02d | ETA ~%02d:%02d"),
12441244
ram_gb_x10 / 10, ram_gb_x10 % 10,
12451245
pass_tag,
12461246
err_tag,
12471247
secs / 60, secs % 60,
12481248
eta_secs / 60, eta_secs % 60);
12491249
} else if (cols >= 70) {
12501250
SPrint(buf, sizeof(buf),
1251-
T(L" MEMFORGE v0.4.18 | %ld.%ld ГБ RAM | %s | %s | %02d:%02d",
1252-
L" MEMFORGE v0.4.18 | %ld.%ld GB RAM | %s | %s | %02d:%02d"),
1251+
T(L" MEMFORGE v0.4.19 | %ld.%ld ГБ RAM | %s | %s | %02d:%02d",
1252+
L" MEMFORGE v0.4.19 | %ld.%ld GB RAM | %s | %s | %02d:%02d"),
12531253
ram_gb_x10 / 10, ram_gb_x10 % 10,
12541254
pass_tag,
12551255
err_tag,
12561256
secs / 60, secs % 60);
12571257
} else {
12581258
SPrint(buf, sizeof(buf),
1259-
T(L" MEMFORGE v0.4.18 | %s | %s | %02d:%02d",
1260-
L" MEMFORGE v0.4.18 | %s | %s | %02d:%02d"),
1259+
T(L" MEMFORGE v0.4.19 | %s | %s | %02d:%02d",
1260+
L" MEMFORGE v0.4.19 | %s | %s | %02d:%02d"),
12611261
pass_tag,
12621262
err_tag,
12631263
secs / 60, secs % 60);
@@ -1635,7 +1635,8 @@ static void record_error(kernel_id_t test, UINT32 core,
16351635
static int dimm_label_for_addr(UINT64 addr, CHAR16 *out, UINTN out_sz_chars) {
16361636
out[0] = 0;
16371637
if (g_dimm_map_count == 0 || g_dimm_count == 0) {
1638-
SPrint(out, out_sz_chars * sizeof(CHAR16), L"?");
1638+
SPrint(out, out_sz_chars * sizeof(CHAR16),
1639+
T(L"вне SMBIOS-карты", L"unmapped region"));
16391640
return 0;
16401641
}
16411642
/* Collect all map entries whose address range contains this byte.
@@ -1651,7 +1652,8 @@ static int dimm_label_for_addr(UINT64 addr, CHAR16 *out, UINTN out_sz_chars) {
16511652
}
16521653
}
16531654
if (n_match == 0) {
1654-
SPrint(out, out_sz_chars * sizeof(CHAR16), L"?");
1655+
SPrint(out, out_sz_chars * sizeof(CHAR16),
1656+
T(L"вне SMBIOS-карты", L"unmapped region"));
16551657
return 0;
16561658
}
16571659
/* Resolve handles to locator strings. */
@@ -1664,14 +1666,14 @@ static int dimm_label_for_addr(UINT64 addr, CHAR16 *out, UINTN out_sz_chars) {
16641666
break;
16651667
}
16661668
}
1667-
if (!loc || !loc[0]) loc = (CHAR8 *)"?";
1669+
if (!loc || !loc[0]) loc = (CHAR8 *)(g_lang ? "unknown DIMM" : "планка без имени");
16681670
pos += SPrint(out + pos, (out_sz_chars - pos) * sizeof(CHAR16),
16691671
(m == 0) ? L"%a" : L"+%a", loc);
16701672
if (pos >= out_sz_chars - 16) break;
16711673
}
16721674
if (intl_depth > 1 && n_match > 1) {
16731675
SPrint(out + pos, (out_sz_chars - pos) * sizeof(CHAR16),
1674-
L" (%d-way intl)", intl_depth);
1676+
T(L" (interleave %d×)", L" (%d-way intl)"), intl_depth);
16751677
}
16761678
return 1;
16771679
}
@@ -1735,16 +1737,20 @@ static int chip_label_for_bit(UINT32 dimm_idx_0based, int bit_pos,
17351737
dimm_info_t *d = &g_dimms[dimm_idx_0based];
17361738
UINT8 dw = d->spd_device_width;
17371739
if (dw != 4 && dw != 8 && dw != 16) {
1738-
/* SPD didn't tell us organization (most likely on HP Sure Start
1739-
or DDR5 where we couldn't read the full block). Show bit only. */
1740-
SPrint(out, out_chars * sizeof(CHAR16), L"bit %d (chip ?)", bit_pos);
1740+
/* SPD didn't expose chip organization — typically on DDR4 x4 modules
1741+
where the SPD width byte wasn't readable, or on systems where
1742+
we couldn't get the full SPD block. We can't map bit→chip.
1743+
Return empty (caller should branch and use a different sentence). */
1744+
out[0] = 0;
17411745
return 0;
17421746
}
1743-
/* Chip index 1-based: matches PCB silkscreen designation. */
1747+
/* Chip index 1-based: matches PCB silkscreen designation (U1..U8 / U1..U16). */
17441748
UINT32 chip_idx = (UINT32)bit_pos / dw + 1;
17451749
UINT32 within = (UINT32)bit_pos % dw;
17461750
SPrint(out, out_chars * sizeof(CHAR16),
1747-
L"chip U%d bit %d (x%d)", chip_idx, within, dw);
1751+
T(L"чип U%d (бит %d, ширина x%d)",
1752+
L"chip U%d (bit %d, width x%d)"),
1753+
chip_idx, within, dw);
17481754
return 1;
17491755
}
17501756

@@ -1777,7 +1783,7 @@ static int dominant_dimm_idx(void) {
17771783
return best;
17781784
}
17791785

1780-
/* v0.4.18 — detect dual-channel interleave ambiguity.
1786+
/* v0.4.19 — detect dual-channel interleave ambiguity.
17811787
On consumer desktops with dual/quad-channel memory, the iMC interleaves
17821788
addresses between channels at 64-byte (cache-line) granularity. A
17831789
SINGLE bad chip on one stick produces errors that, when mapped through
@@ -1786,7 +1792,7 @@ static int dominant_dimm_idx(void) {
17861792

17871793
Field report from a Habr user (Netac DDR4 kit): same stuck bit
17881794
D[53] was reported 24 times, distributed as A2 (8) + B2 (11) + ? (5).
1789-
Pre-v0.4.18 verdict confidently said "REPLACE: DDR4-B2 (HIGH)" — but
1795+
Pre-v0.4.19 verdict confidently said "REPLACE: DDR4-B2 (HIGH)" — but
17901796
physically it's likely ONE bad chip on one of A2/B2, NOT both.
17911797

17921798
This helper returns the list of DIMM indices that each hold >=25% of
@@ -4768,15 +4774,15 @@ static void amd_thermal_probe(void) {
47684774
}
47694775

47704776
static UINT32 amd_thermal_sample(void) {
4771-
/* v0.4.18 — correct decode per Linux k10temp / FreeBSD amdtemp.c:
4777+
/* v0.4.19 — correct decode per Linux k10temp / FreeBSD amdtemp.c:
47724778
SMN 0x59800 (SMU_THM_TCON_CUR_TMP)
47734779
bits [31:21] raw temperature value (11 bits, mask 0x7FF)
47744780
bit 19 TempRangeSel — when SET, scale is -49°C..+206°C
47754781
(subtract 49°C from the raw decode); when CLEAR
47764782
scale is 0..225°C (no offset).
47774783
temp_c = (raw * 0.125) - (range_sel ? 49 : 0)
47784784

4779-
Pre-v0.4.18 code was missing both the 0x7FF mask AND the bit-19
4785+
Pre-v0.4.19 code was missing both the 0x7FF mask AND the bit-19
47804786
range adjustment, which inflated readings by ~49°C on Ryzen SKUs
47814787
that report on the -49..206 scale (most Renoir/Cezanne/Zen3+
47824788
desktop parts). Field report on Ryzen 5 4500 showed Tctl=93°C at
@@ -6528,7 +6534,7 @@ typedef struct {
65286534
} card_info_t;
65296535
static card_info_t g_cards[N_TESTS];
65306536

6531-
/* v0.4.18 — Forward decls for focused-mode helpers (defined below
6537+
/* v0.4.19 — Forward decls for focused-mode helpers (defined below
65326538
card_paint so they can share the same color-lookup logic). */
65336539
static void card_paint_full(UINTN i);
65346540
static void card_strip_paint(UINTN i);
@@ -6642,7 +6648,7 @@ static void card_paint_full(UINTN i) {
66426648
}
66436649
}
66446650

6645-
/* ---------- Focused-mode card painters (v0.4.18) ---------- */
6651+
/* ---------- Focused-mode card painters (v0.4.19) ---------- */
66466652

66476653
/* Paint the small status dot for test i in the top strip. The strip is
66486654
one row tall and shows N evenly-spaced dots, one per test. The dot
@@ -7766,11 +7772,23 @@ static int verdict_describe_what_broke(CHAR16 *line1, UINTN cap1,
77667772
int bp = single_bit_pos(stuck_x);
77677773
if (stuck_n >= 5 && bp >= 0 && dominant_dimm_0based >= 0) {
77687774
CHAR16 chip[64];
7769-
chip_label_for_bit((UINT32)dominant_dimm_0based, bp, chip, 64);
7770-
SPrint(line1, cap1,
7771-
T(L"• %s — бит %d застрял (%d ошибок этого типа)",
7772-
L"• %s — bit %d stuck (%d errors of this type)"),
7773-
chip, bp, stuck_n);
7775+
int have_chip = chip_label_for_bit((UINT32)dominant_dimm_0based, bp, chip, 64);
7776+
if (have_chip) {
7777+
/* SPD told us chip width → can name the exact chip on PCB */
7778+
SPrint(line1, cap1,
7779+
T(L"● Дохлая ячейка: %s — биту %d стуковое значение (%d ошибок этого типа)",
7780+
L"● Dead cell: %s — bit %d stuck (%d errors of this type)"),
7781+
chip, bp, stuck_n);
7782+
} else {
7783+
/* SPD didn't expose chip width (typical for DDR4 x4 / некоторые DDR5)
7784+
— we know which bit, just not which physical chip on the PCB */
7785+
SPrint(line1, cap1,
7786+
T(L"● Стуковый бит D[%d] на планке (%d ошибок). "
7787+
L"SPD не сообщил ширину чипа — точный U-номер чипа не определить.",
7788+
L"● Stuck bit D[%d] on DIMM (%d errors). "
7789+
L"SPD did not expose chip width — exact chip U-number unknown."),
7790+
bp, stuck_n);
7791+
}
77747792
n++;
77757793
}
77767794

@@ -7780,8 +7798,8 @@ static int verdict_describe_what_broke(CHAR16 *line1, UINTN cap1,
77807798
CHAR16 *target = (n == 0) ? line1 : line2;
77817799
UINTN cap = (n == 0) ? cap1 : cap2;
77827800
SPrint(target, cap,
7783-
T(L" Повреждён ряд ячеек ~0x%lx (%d ошибок в одном ряду)",
7784-
L" Damaged cell row ~0x%lx (%d errors in same row)"),
7801+
T(L" Повреждён ряд ячеек ~0x%lx (%d ошибок в одном ряду)",
7802+
L" Damaged cell row ~0x%lx (%d errors in same row)"),
77857803
srow, srow_n);
77867804
n++;
77877805
if (n >= 2) return n;
@@ -7793,8 +7811,8 @@ static int verdict_describe_what_broke(CHAR16 *line1, UINTN cap1,
77937811
CHAR16 *target = (n == 0) ? line1 : line2;
77947812
UINTN cap = (n == 0) ? cap1 : cap2;
77957813
SPrint(target, cap,
7796-
T(L" Повреждена секция памяти (bank-group %d / bank %d, %d ошибок)",
7797-
L" Damaged memory bank (bank-group %d / bank %d, %d errors)"),
7814+
T(L" Повреждена секция памяти (банк-группа %d / банк %d, %d ошибок)",
7815+
L" Damaged memory bank (bank-group %d / bank %d, %d errors)"),
77987816
(sbank >> 4) & 0xF, sbank & 0xF, sbank_n);
77997817
n++;
78007818
if (n >= 2) return n;
@@ -7803,8 +7821,8 @@ static int verdict_describe_what_broke(CHAR16 *line1, UINTN cap1,
78037821
/* Fallback when no clear pattern — say total error count + dominant DIMM */
78047822
if (n == 0) {
78057823
SPrint(line1, cap1,
7806-
T(L" %ld ошибок памяти без чёткой локализации",
7807-
L" %ld memory errors without a clear pattern"),
7824+
T(L" %ld ошибок памяти без чёткой локализации",
7825+
L" %ld memory errors without a clear pattern"),
78087826
(UINT64)g_err_count);
78097827
}
78107828
return n;
@@ -7964,7 +7982,7 @@ static void render_simple_verdict(UINT64 total_ms) {
79647982
}
79657983
} else { /* VERDICT_FAIL */
79667984
int didx = dominant_dimm_idx();
7967-
/* v0.4.18 — interleave detection.
7985+
/* v0.4.19 — interleave detection.
79687986
If errors are distributed across 2+ DIMMs (typical dual-channel
79697987
interleave hiding a single bad chip behind two DIMM labels),
79707988
we MUST NOT confidently name one DIMM. Verdict instead tells
@@ -8187,8 +8205,8 @@ static void render_summary(UINT64 total_ms) {
81878205
UINTN hrow = (g_hdr_h / 2 - g_char_h / 2) / g_char_h;
81888206
CHAR16 buf[200];
81898207
SPrint(buf, sizeof(buf),
8190-
T(L" MEMFORGE v0.4.18 ИТОГИ | %d сек | Ядра %d/%d",
8191-
L" MEMFORGE v0.4.18 SUMMARY | %d sec | Cores %d/%d"),
8208+
T(L" MEMFORGE v0.4.19 ИТОГИ | %d сек | Ядра %d/%d",
8209+
L" MEMFORGE v0.4.19 SUMMARY | %d sec | Cores %d/%d"),
81928210
(UINT32)(total_ms / 1000),
81938211
(UINT32)g_n_enabled, (UINT32)g_n_cores);
81948212
say_at_rc(0, hrow, buf);
@@ -8271,15 +8289,22 @@ static void render_summary(UINT64 total_ms) {
82718289
if (didx >= 0)
82728290
chip_label_for_bit((UINT32)didx, bp, chip, 64);
82738291
if (didx >= 0 && chip[0]) {
8292+
/* Full info: DIMM + exact chip designator */
82748293
SPrint(sb, sizeof(sb),
8275-
T(L"⚠ Застрял бит D[%d] → DIMM%d %s: %d ошибок",
8276-
L"⚠ Stuck bit D[%d] → DIMM%d %s: %d errors"),
8294+
T(L"⚠ Застрял бит D[%d] → DIMM%d, %s: %d ошибок",
8295+
L"⚠ Stuck bit D[%d] → DIMM%d, %s: %d errors"),
82778296
bp, didx + 1, chip, stuck_n);
8297+
} else if (didx >= 0) {
8298+
/* DIMM known, exact chip not — say so plainly */
8299+
SPrint(sb, sizeof(sb),
8300+
T(L"⚠ Застрял бит D[%d] → DIMM%d (точный чип не определён по SPD): %d ошибок",
8301+
L"⚠ Stuck bit D[%d] → DIMM%d (exact chip unknown per SPD): %d errors"),
8302+
bp, didx + 1, stuck_n);
82788303
} else {
82798304
SPrint(sb, sizeof(sb),
8280-
T(L"⚠ Застрял бит D[%d]: %d ошибок с XOR=0x%016lx",
8281-
L"⚠ Stuck bit D[%d]: %d errors with XOR=0x%016lx"),
8282-
bp, stuck_n, stuck_x);
8305+
T(L"⚠ Застрял бит D[%d] (планку определить не удалось): %d ошибок",
8306+
L"⚠ Stuck bit D[%d] (DIMM could not be identified): %d errors"),
8307+
bp, stuck_n);
82838308
}
82848309
} else {
82858310
SPrint(sb, sizeof(sb),
@@ -8321,9 +8346,9 @@ static void render_summary(UINT64 total_ms) {
83218346
}
83228347

83238348
/* (2) Affected-DIMM list (from SMBIOS Type 20 mapping). */
8324-
CHAR16 dimm_line[220]; UINTN pos = 0;
8349+
CHAR16 dimm_line[260]; UINTN pos = 0;
83258350
pos += SPrint(dimm_line + pos, sizeof(dimm_line) - pos * sizeof(CHAR16),
8326-
T(L"Затронуто: ", L"Affected DIMMs: "));
8351+
T(L"Ошибки по планкам: ", L"Errors by DIMM: "));
83278352
/* Aggregate: tally errors per distinct DIMM-label string. */
83288353
CHAR16 labels[8][64]; UINT32 lcount[8] = {0}; UINT32 nl = 0;
83298354
UINT32 shown = g_err_count > MAX_ERR_RECORDS ? MAX_ERR_RECORDS : g_err_count;
@@ -9968,7 +9993,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
99689993
}
99699994
}
99709995

9971-
log_line(L"=== MemForge2 v0.4.18 init ===");
9996+
log_line(L"=== MemForge2 v0.4.19 init ===");
99729997
log_line(L"[WATCHDOG] UEFI 5-min watchdog disabled at app entry");
99739998
/* Show splash IMMEDIATELY so the user sees the program is alive while
99749999
INI parsing, SMBus probes and SMBIOS walk happen. Without this, the
@@ -10013,7 +10038,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
1001310038
if (uefi_call_wrapper(g_gop->QueryMode, 4,
1001410039
g_gop, m, &info_sz, &info) != EFI_SUCCESS)
1001510040
continue;
10016-
/* v0.4.18 — also log PixelFormat and PixelsPerScanLine
10041+
/* v0.4.19 — also log PixelFormat and PixelsPerScanLine
1001710042
so we can see if a card (e.g. old Radeon HD 4350) only
1001810043
offers BltOnly modes (PixelFormat=3) that prevent
1001910044
direct-fb rendering. */
@@ -10028,7 +10053,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
1002810053
log_line(L"[GFX] NO GOP PROTOCOL FOUND — firmware has no UEFI graphics. "
1002910054
L"Falling back to 800x600 default. UI will not render correctly.");
1003010055
}
10031-
/* v0.4.18 — MP Services Protocol diagnostic. Without this log it
10056+
/* v0.4.19 — MP Services Protocol diagnostic. Without this log it
1003210057
was impossible to tell from a field report whether multi-core
1003310058
dispatch failed (LocateProtocol error / GetNumberOfProcessors
1003410059
returned 1) or the test was simply running on a single-core

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ EnableAVX=1
191191
;MarathonHours=0 ; 0 = off, 1..24 = run for N hours
192192

193193
[Meta]
194-
Version=0.4.18
194+
Version=0.4.19
195195
Language=en ; "ru" or "en"
196196

197197
[Display]

quantai.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ EnableAVX=1
8282

8383
; Used by the UEFI binary for the menu language. Also used by the analyzer.
8484
[Meta]
85-
Version=0.4.18
85+
Version=0.4.19
8686
Debug=0
8787
Language=en
8888

0 commit comments

Comments
 (0)