Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ $(TWEAK_NAME)_FILES += vendor/KIOU-Hook/KIOUHook.m
$(TWEAK_NAME)_FILES += vendor/KIOU-Hook/Account/Persistence.m
$(TWEAK_NAME)_FILES += vendor/KIOU-Hook/Hook/AccountObserve.m
$(TWEAK_NAME)_FILES += vendor/KIOU-Hook/Hook/GrpcLogging.m
$(TWEAK_NAME)_FILES += vendor/KIOU-Hook/Hook/AfkSuppress.m

BUILD_COMMIT ?= $(shell git rev-parse --short=7 HEAD 2>/dev/null || echo unknown)

Expand Down
13 changes: 13 additions & 0 deletions Sources/KiouForge/Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,19 @@ static const uintptr_t kKiouMatchModeAdapterOffsets[KIOU_MMODE_COUNT] = {
[KIOU_MMODE_RECORD_REPLAY] = 0x18,
};

// IMatchMode self -> _stateStore field offsets. All five IMatchMode
// implementations carry a GameStateStore reference sitting one pointer
// slot before _gameAdapter — reading it lets the kif writer pull
// player names via the same ReactiveProperty<PlayerInfo> path online
// matches use.
static const uintptr_t kKiouMatchModeStateStoreOffsets[KIOU_MMODE_COUNT] = {
[KIOU_MMODE_AI_MATCH] = 0x40,
[KIOU_MMODE_CPU_STREAM] = 0x48,
[KIOU_MMODE_LOCAL_PVP] = 0x10,
[KIOU_MMODE_ONLINE_PVP] = 0x28,
[KIOU_MMODE_RECORD_REPLAY] = 0x10,
};

static const char *const kKiouMatchModeTags[KIOU_MMODE_COUNT] = {
[KIOU_MMODE_AI_MATCH] = "AIMatchMode",
[KIOU_MMODE_CPU_STREAM] = "CPUStreamMode",
Expand Down
14 changes: 9 additions & 5 deletions Sources/KiouForge/Kif/Helpers.m
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,15 @@
// ---------------------------------------------------------------------------
// RVAs (KIOU 1.0.1 build 11). Same source of truth as KiouUsiProxy.
// ---------------------------------------------------------------------------
#define RVA_GAMECTRL_GET_USI_TEXT 0x5D44074 // string GameController.GetUSIText(this)
#define RVA_POSITION_TO_SFEN 0x5D44374 // string Position.ToSFEN(this)
#define RVA_USIPARSER_PARSE_USI 0x5D572B4 // static RecordManager USIParser.ParseUSI(string)
#define RVA_KIFWRITEOPTIONS_CTOR 0x5D53960 // void KIFWriteOptions..ctor(this)
#define RVA_KIFWRITER_WRITE 0x5D53968 // static string KIFWriter.Write(RecordManager, KIFWriteOptions)
// RVAs pinned to KIOU 1.0.2 (dump.cs verified 2026-07-02). The previous
// values were 1.0.1 leftovers pointing at unrelated methods — calling
// through them at match-end crashed with a SIGSEGV inside GetUSIText
// (LDR from a bogus X10 loaded from *(gameCtrl+0xB0)).
#define RVA_GAMECTRL_GET_USI_TEXT 0x5D49970 // string GameController.GetUSIText(this)
#define RVA_POSITION_TO_SFEN 0x5D49C70 // string Position.ToSFEN(this)
#define RVA_USIPARSER_PARSE_USI 0x5D5CBB0 // static RecordManager USIParser.ParseUSI(string)
#define RVA_KIFWRITEOPTIONS_CTOR 0x5D5925C // void KIFWriteOptions..ctor(this)
#define RVA_KIFWRITER_WRITE 0x5D59264 // static string KIFWriter.Write(RecordManager, KIFWriteOptions)

// KIFWriteOptions instance size needed for the raw-buffer trick. See the
// KIFOPTS_OFF_* constants in Internal.h for the field map. Last field
Expand Down
11 changes: 8 additions & 3 deletions Sources/KiouForge/Kif/Writer.m
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,18 @@ KIOUUniTaskRet KIOUKifuObserveMatchEnd(void *self, void *ct,
return zero;
}

// MatchConfig / GameStateStore only available on OnlinePvPMode's `self`;
// other modes' KIF gets blank player names (acceptable for offline play).
// All five IMatchMode implementations carry a GameStateStore that
// KIOUKifDescribeOpponents / KIOUKifFillWriteOptions can read player
// names from via ReactiveProperty<PlayerInfo>. Only OnlinePvPMode
// additionally exposes a MatchConfig — the other modes seed the
// PlayerInfo directly into stateStore at match start.
void *matchConfig = NULL;
void *stateStore = NULL;
if (mode_index < KIOU_MMODE_COUNT && ptrLooksValid(self)) {
stateStore = readPtr(self, kKiouMatchModeStateStoreOffsets[mode_index]);
}
if (mode_index == KIOU_MMODE_ONLINE_PVP && ptrLooksValid(self)) {
matchConfig = readPtr(self, ONLINEPVPMODE_OFF_MATCHCONFIG);
stateStore = readPtr(self, ONLINEPVPMODE_OFF_STATE_STORE);
}

IPALog([NSString stringWithFormat:
Expand Down
1 change: 1 addition & 0 deletions Sources/KiouForge/Tweak.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ static void installUnityHooks(uintptr_t unityBase, const char *unityName) {
KIOUInstallKifuObserveHook(unityBase);
KIOUInstallAccountObserveHook(unityBase);
KIOUInstallGrpcLoggingHook(unityBase);
KIOUInstallAfkSuppressHook(unityBase);

g_unityHooked = YES;
IPALog(@"=== KiouForge: all hooks installed ===");
Expand Down
2 changes: 1 addition & 1 deletion vendor/KIOU-Hook
Loading