Files
nxnative-easy/dm/host/dm_widget.h
T
seedds d1b17080ed smbw-mobile: Mac host boots Mario Wonder v0 into its frame loop
Generic host, gfx and tools taken from d2r-mobile (MIT), with the D2R
gameplay, diagnostics and Blizzard/Granny/movie layers removed.

- hle_hid.c: generic standard-controller layer (all Npad styles)
- hle_sdk16.c: newer-SDK oe/time/pl/vsync/diag hooks
- hle_offline.c: offline stubs for prepo/ldn/socket/ssl/nifm/nsd/friends/ngc/err
- hle_fs.c, hle_account.c: SDK 16 overloads
- loader.c: unreferenced forced hooks only logged (DM_FORCE_STRICT=1 aborts)
- NVN: API 55.15, 13 newer names, ~45 state-only functions, tex_t packed
  to 0x80 (Mario allocates NVNtexture as 0x80; 0x88 corrupted the heap)

Frontier: null read at main+0x64763c inside the frame loop.
2026-10-12 22:04:20 +08:00

37 lines
4.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 按偏移读写原版界面控件的「类专有字段」之前,先核它是不是预期的那个类(虚表)。
// 来由:按名字找到的控件不保证是当初量偏移时的那个类(布局改了、同名控件换了类、原版把槽位换成别的控件),按偏移写下去就是往别的对象里乱写。
// 所有控件共有的基类字段(名字 +8、可见 +0x50 / +0x51、子控件 +0x58 / +0x60、矩形 +0x70)不用核。
// 虚表值是 main 模块内偏移(3.3.94012),宿主实读:
// Before reading or writing "class-specific fields" of a native UI widget by offset, check that it is the expected class (vtable).
// Why: a widget found by name is not guaranteed to be the class the offsets were measured on (layout changed, a same-named widget changed class, the game swapped the slot for another widget), and writing by offset then scribbles into some other object.
// Base-class fields shared by all widgets (name +8, visible +0x50 / +0x51, children +0x58 / +0x60, rect +0x70) need no check.
// Vtable values are offsets within the main module (3.3.94012), read on the host:
#pragma once
#include <stdint.h>
enum {
DM_VT_TEXT = 0x20ba4c8, // 文字框:串 +0x88 / 长 +0x90,字色 +0xbc | text box: string +0x88 / length +0x90, text color +0xbc
DM_VT_INPUT = 0x20b8718, // 输入框:正式文字串 +0x558 | input box: committed text string +0x558
DM_VT_NUMINPUT = 0x20b91c0, // 数字输入框 | numeric input box
DM_VT_TOGGLE = 0x20bc110, // 勾选框 / 子页签(ToggleButtonWidget):勾上 +0xa88,四个帧号 +0x6e8.. ,此刻的帧 +0x610 | checkbox / sub-tab (ToggleButtonWidget): checked +0xa88, four frame ids at +0x6e8.., current frame +0x610
DM_VT_TABBAR = 0x20ba3a8, // 页签条(TabBarWidget) | tab bar (TabBarWidget)
DM_VT_SLOT = 0x2089fa0, // 物品格:部位号 +0x5d8、属主 +0x5c8 | item slot: body location +0x5d8, owner +0x5c8
DM_VT_SLOT_B = 0x2089ab8, // 物品格(另一种,dm_actions.c / dm_runeword.c 认的) | item slot (another kind, recognized by dm_actions.c / dm_runeword.c)
DM_VT_SLOT_C = 0x2088fc8, // 物品格(dm_cursor_item.c 认的第三种) | item slot (the third kind, recognized by dm_cursor_item.c)
DM_VT_IMAGE = 0x20b8650, // 图片控件:此刻的帧 +0x90(宿主实读:编年史页的 Img) | image widget: current frame +0x90 (read on the host: Img on the Chronicle page)
DM_VT_BUTTON = 0x20b7b00, // 按钮:四个帧号 +0x6e8..,此刻的帧 +0x610(宿主实读:秘境选层页的 TouchRF_M1) | button: four frame ids at +0x6e8.., current frame +0x610 (read on the host: TouchRF_M1 on the Greater Rift level select page)
};
static inline uint64_t dm_widget_vt(const uint8_t *base, uint64_t w) { return w && base ? *(const uint64_t *)(uintptr_t)w - (uint64_t)(uintptr_t)base : 0; }
static inline int dm_widget_is(const uint8_t *base, uint64_t w, uint64_t vt) { return w && base && dm_widget_vt(base, w) == vt; }
static inline int dm_widget_is_slot(const uint8_t *base, uint64_t w) { uint64_t v = dm_widget_vt(base, w); return v == DM_VT_SLOT || v == DM_VT_SLOT_B || v == DM_VT_SLOT_C; }
// 调用点用:是预期的类 → 1;不是 → 0,并记一次红(每个文件最多 5 次,不刷屏)。用它的文件要有 LOG(hle.h),并在文件里放一次 DM_WIDGET_RED_DEF
// For call sites: expected class → 1; otherwise → 0 and log one failure (at most 5 per file, no log flooding). A file using it needs LOG (hle.h) and one DM_WIDGET_RED_DEF in the file
#define DM_WIDGET_OK(base, w, vt, who) (dm_widget_is((base), (w), (vt)) ? 1 : dm_widget_red_((base), (w), (vt), (who)))
#define DM_WIDGET_RED_DEF \
static int dm_widget_red_(const uint8_t *base, uint64_t w, uint64_t vt, const char *who) { static int n; \
if (w && base && n++ < 5) { const char *nm = *(const char **)(uintptr_t)(w + 8); \
LOG("【红】%s:控件「%s」不是预期的类(虚表 main+%#llx,应为 %#llx),不按偏移读写", who, nm ? nm : "?", (unsigned long long)dm_widget_vt(base, w), (unsigned long long)vt); } \
return 0; }