Skip to content

chore: release v0.1.2 - #9

Merged
tkgstrator merged 1 commit into
developfrom
chore/release-0.1.2
Jun 19, 2026
Merged

chore: release v0.1.2#9
tkgstrator merged 1 commit into
developfrom
chore/release-0.1.2

Conversation

@tkgstrator

Copy link
Copy Markdown
Contributor

v0.1.2

bump control version to 0.1.2.

Added

  • In-process settings panel.
  • %%TIME CSA extension command with millisecond-precision remaining time response.

Fixed

  • Remaining time reporting for CPU/no-limit sides in Game_Summary and %%TIME responses.
  • CSA resign now calls MatchController.SurrenderAsync.

🤖 Generated with Claude Code

bump control version to 0.1.2.

v0.1.2 adds the in-process settings panel, %%TIME CSA extension,
and remaining time reporting fixes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 19, 2026 06:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Release housekeeping change to bump the package metadata version to v0.1.2 for KiouEngineBridge’s iOS tweak distribution.

Changes:

  • Update Debian control metadata Version from 0.1.1 to 0.1.2.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread control
@tkgstrator
tkgstrator merged commit e248c7c into develop Jun 19, 2026
5 checks passed
@tkgstrator
tkgstrator deleted the chore/release-0.1.2 branch June 19, 2026 07:10
tkgstrator added a commit that referenced this pull request Jun 22, 2026
- recipes/kiouenginebridge.py: the GetValidMatchFoundStatus row's
  comment said the hook returns NULL to reject the match, but the
  actual entry hook forwards orig's MatchFoundStatus unchanged and
  delivers the reject signal by firing ConnectionFailed at the stream.
  Rewrite the comment to match.
- docs/research/cave_kinds.md / Hook_MatchingFilterObserve.m: tighten
  the AAPCS64 wording. W9 is not "arg #9" (the integer arg sequence
  ends at x7; x8 is the indirect-result register). It IS call-clobbered
  scratch (x9–x15), which is exactly why touching it from the entry
  cave is safe — but say so in the language the ABI actually uses.
- docs/research/cave_kinds.md: drop BR / BLR from the "PC-relative,
  can't relocate" list. They're register-indirect, so the branch
  instruction itself IS PC-independent; what makes them unsafe to lift
  is the ADRP/MOVZ chain that loaded the target register a few insns
  earlier. Spell that out so the next contributor doesn't get the same
  wrong impression.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tkgstrator added a commit that referenced this pull request Jun 22, 2026
- recipes/kiouenginebridge.py: the GetValidMatchFoundStatus row's
  comment said the hook returns NULL to reject the match, but the
  actual entry hook forwards orig's MatchFoundStatus unchanged and
  delivers the reject signal by firing ConnectionFailed at the stream.
  Rewrite the comment to match.
- docs/research/cave_kinds.md / Hook_MatchingFilterObserve.m: tighten
  the AAPCS64 wording. W9 is not "arg #9" (the integer arg sequence
  ends at x7; x8 is the indirect-result register). It IS call-clobbered
  scratch (x9–x15), which is exactly why touching it from the entry
  cave is safe — but say so in the language the ABI actually uses.
- docs/research/cave_kinds.md: drop BR / BLR from the "PC-relative,
  can't relocate" list. They're register-indirect, so the branch
  instruction itself IS PC-independent; what makes them unsafe to lift
  is the ADRP/MOVZ chain that loaded the target register a few insns
  earlier. Spell that out so the next contributor doesn't get the same
  wrong impression.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tkgstrator added a commit that referenced this pull request Jun 22, 2026
… document cave kinds

* feat(chinlan): port LoginArgs / RegisterUserArgs argument swap to entry caves

So Account Switch and the Reset → Register distinctId pinning now work on
chinlan instead of being JB-only:

- recipes/kiouenginebridge.py: add LoginArgs.Create (RVA 0x5B9899C) and
  RegisterUserArgs.Create (RVA 0x5B98A2C) as CAVE_ENTRY rows so the cave
  hands the hook pristine x0..x7. CAVE_OBSERVER cannot do this because it
  restores x0..x7 from the saved frame before B orig+4, undoing any swap.
  ENTRY_SLOT_COUNT bumps from 1 to 3.
- Internal.h: enum entries + entry-slot enum entries for both sites.
- ChinlanDispatcher.m: publishes &HookLoginArgsCreateEntry and
  &HookRegisterUserArgsCreateEntry into their entry slots at boot.
- Hook_AccountObserve.m: factors the JB substitution logic into
  loginArgsSwapDeviceId() / registerUserArgsSwapDistinctId() so both the
  JB hooks and the new chinlan entry hooks reuse it. The entry hooks
  invoke orig themselves through the cave bypass entry (cave_va + 0x4C,
  published via g_inject_entry[KIOU_BR_HOOK_*_CREATE]) and forward the
  freshly built ILoginArgs* / IRegisterUserArgs*. The JB hooks are
  wrapped in #if !KIOU_CHINLAN so chinlan's varargs-dropping
  KIOU_CALL_ORIG_RET macro doesn't trip -Werror=unused-variable.

Builds: JB + chinlan both clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(matching): wire seat / rate-range filters on JB + chinlan

Two parts:

1. Tweak.m finally calls InstallMatchingFilterObserveHook from both the
   JB and chinlan branches. The Settings UI rows were already shipping;
   they just weren't connected to anything because nobody invoked the
   installer.

2. recipes/kiouenginebridge.py adds three new chinlan cave sites so
   the filter works without MSHookFunction:
   * GetValidMatchFoundStatus (0x5D04E94) — CAVE_ENTRY. The hook fires
     ConnectionFailed at the stream when the filter rejects the seat,
     then forwards orig's MatchFoundStatus*.
   * IShogiMatchStreamArgs.Create (0x5BCA664) — CAVE_ENTRY. Must be
     entry, not observer: its 7th C argument lands in W6 which
     CAVE_OBSERVER would clobber with the dispatcher hook_id. The entry
     cave only touches W9, an unused slot here.
   * MatchingHandler.ReceiveWithTimeoutAsync.MoveNext (0x5D06B10) —
     CAVE_OBSERVER. Single-arg state-machine peek; we cache the stream
     pointer and react to MatchingStatus replies for Fixed Rate Range.

   ENTRY_SLOT_COUNT bumps from 3 to 5.

3. Hook_MatchingFilterObserve.m factors the JB hook bodies into shared
   helpers (filterMatchFoundResult / cacheJoinQueueParams) so the new
   chinlan entry hooks reuse the same decision logic and only differ in
   how orig is invoked (MSHookFunction trampoline on JB; cave-bypass
   entry on chinlan). InstallMatchingFilterObserveHook on chinlan now
   points g_ArgsCreate at the cave-bypass entry so sendAction() doesn't
   re-enter the entry hook on every requeue.

Builds: JB + chinlan both clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: document chinlan cave kinds with capability matrix and walkthrough

New page covers CAVE_OBSERVER vs CAVE_ENTRY:

- At-a-glance capability matrix (override return, swap args, W6 clobber,
  shared dispatcher vs per-site slot, etc.) so contributors can pick the
  right cave kind without reading the recipe.
- Annotated 21-insn cave layouts side-by-side so the +0x4C bypass-entry
  contract that both kinds preserve is obvious.
- 8-step walkthrough for adding a new site: pick the kind, validate the
  prologue is PC-independent, edit recipe / Internal.h / hook file /
  ChinlanDispatcher / Tweak.m, and verify with make ipa + chinlan boot
  logs. Worked example targets a CAVE_ENTRY conversion since that's the
  trickier case that needed cross-file coordination.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(chinlan): bump Sources/Chinlan submodule to 94d098d

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(chinlan): move ENTRY_SLOT_BASE_RVA into __common to fix the bss overflow

Previously the entry slot table started at 0x8F90CD0 — the last 8 bytes
of __DATA,__bss — so slot[0] fit but slot[1+] silently spilled into the
40-byte padding between __bss and __common. Both regions are zero-fill
so dyld didn't catch it, but Shared/tools/patch_macho.py's
assert_slot_in_bss only validates HOOK_SLOT_RVA and never noticed.

Relocate to 0x091E90B8 in __DATA,__common (2.4 MB section, 32-slot
reservation = 256 bytes at the section tail). Static asserts at recipe
import time now catch any future ENTRY_SLOT_CAPACITY / base bump that
would overflow the section bound captured in _COMMON_SECTION_END_RVA.

Extending the patcher's per-binary assert_slot_in_bss check to cover
every entry slot — not just HOOK_SLOT_RVA — is a separate Shared PR.

Builds: chinlan IPA repack confirmed; recipe import-time asserts hold
(reservation tail 0x091E91B8 == __common end).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(chinlan): persist LoginReply + SelfProfile on chinlan via entry caves

So accounts.json on chinlan finally carries the same accessToken-derived
userId, sessionId, deviceId, userName, and rank/rating array that the JB
build has been recording since PR #14.

- RunLoginSequenceAsync.MoveNext (RVA 0x5812534) and
  GetSelfUserProfileAsync.MoveNext (RVA 0x5BB4774) join the entry-cave
  table. The MoveNext fields they read (LoginReply pointer at
  state-machine offset 0x50, SelfUserProfileStatus rank list at 0x28)
  only land after orig advances state to -2, so the cave has to be
  CAVE_ENTRY: the hook calls the per-site bypass entry to actually run
  MoveNext, then reads the now-populated fields.

- Hook_AccountObserve.m factors the post-completion scan logic into
  observeRunLoginSeqCompletion() / observeGetSelfProfileCompletion() so
  the JB MSHook hooks and the new chinlan entry hooks reuse the same
  body. JB hooks call KIOU_CALL_ORIG_VOID first; chinlan entry hooks
  invoke orig through g_inject_entry[…] first. Either way the body sees
  a state-machine struct that's already advanced past the await.

- ENTRY_SLOT_COUNT goes 5 → 7. ChinlanDispatcher's publish log adds the
  two new pointers so a boot log makes the wiring obvious.

Builds: JB + chinlan + chinlan IPA repack all clean; all three new
patches (one observer for ReceiveTimeoutMoveNext, two entries for the
MoveNext observers) are applied to the IPA.

Untested on-device — but the read paths inside observe*() are unchanged
since PR #14 / #17, and the entry-cave dispatch shape is the same as
HookLoginArgsCreateEntry / HookAccountExistsEntry which have been
exercised in the prior chinlan boot logs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(chinlan): bump Sources/Chinlan submodule

* docs: address Copilot review nits on PR #17

- recipes/kiouenginebridge.py: the GetValidMatchFoundStatus row's
  comment said the hook returns NULL to reject the match, but the
  actual entry hook forwards orig's MatchFoundStatus unchanged and
  delivers the reject signal by firing ConnectionFailed at the stream.
  Rewrite the comment to match.
- docs/research/cave_kinds.md / Hook_MatchingFilterObserve.m: tighten
  the AAPCS64 wording. W9 is not "arg #9" (the integer arg sequence
  ends at x7; x8 is the indirect-result register). It IS call-clobbered
  scratch (x9–x15), which is exactly why touching it from the entry
  cave is safe — but say so in the language the ABI actually uses.
- docs/research/cave_kinds.md: drop BR / BLR from the "PC-relative,
  can't relocate" list. They're register-indirect, so the branch
  instruction itself IS PC-independent; what makes them unsafe to lift
  is the ADRP/MOVZ chain that loaded the target register a few insns
  earlier. Spell that out so the next contributor doesn't get the same
  wrong impression.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(cave_kinds): unify ADRP/LDR placeholder names in cave diagrams

Copilot review on the sibling Chinlan PR (and applicable here too)
noted that the ADRP/LDR pair used different placeholders for the same
address — `page(HOOK_SLOT_RVA)` + `lo12(SLOT)`, and similarly
`page(entry_slot_va)` + `lo12(slot)`. Make both sides of each ADRP/LDR
pair name the same symbol so the relocation pattern is unambiguous.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(chinlan): bump submodule to 90512ec

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
tkgstrator added a commit that referenced this pull request Jun 23, 2026
… document cave kinds

* feat(chinlan): port LoginArgs / RegisterUserArgs argument swap to entry caves

So Account Switch and the Reset → Register distinctId pinning now work on
chinlan instead of being JB-only:

- recipes/kiouenginebridge.py: add LoginArgs.Create (RVA 0x5B9899C) and
  RegisterUserArgs.Create (RVA 0x5B98A2C) as CAVE_ENTRY rows so the cave
  hands the hook pristine x0..x7. CAVE_OBSERVER cannot do this because it
  restores x0..x7 from the saved frame before B orig+4, undoing any swap.
  ENTRY_SLOT_COUNT bumps from 1 to 3.
- Internal.h: enum entries + entry-slot enum entries for both sites.
- ChinlanDispatcher.m: publishes &HookLoginArgsCreateEntry and
  &HookRegisterUserArgsCreateEntry into their entry slots at boot.
- Hook_AccountObserve.m: factors the JB substitution logic into
  loginArgsSwapDeviceId() / registerUserArgsSwapDistinctId() so both the
  JB hooks and the new chinlan entry hooks reuse it. The entry hooks
  invoke orig themselves through the cave bypass entry (cave_va + 0x4C,
  published via g_inject_entry[KIOU_BR_HOOK_*_CREATE]) and forward the
  freshly built ILoginArgs* / IRegisterUserArgs*. The JB hooks are
  wrapped in #if !KIOU_CHINLAN so chinlan's varargs-dropping
  KIOU_CALL_ORIG_RET macro doesn't trip -Werror=unused-variable.

Builds: JB + chinlan both clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(matching): wire seat / rate-range filters on JB + chinlan

Two parts:

1. Tweak.m finally calls InstallMatchingFilterObserveHook from both the
   JB and chinlan branches. The Settings UI rows were already shipping;
   they just weren't connected to anything because nobody invoked the
   installer.

2. recipes/kiouenginebridge.py adds three new chinlan cave sites so
   the filter works without MSHookFunction:
   * GetValidMatchFoundStatus (0x5D04E94) — CAVE_ENTRY. The hook fires
     ConnectionFailed at the stream when the filter rejects the seat,
     then forwards orig's MatchFoundStatus*.
   * IShogiMatchStreamArgs.Create (0x5BCA664) — CAVE_ENTRY. Must be
     entry, not observer: its 7th C argument lands in W6 which
     CAVE_OBSERVER would clobber with the dispatcher hook_id. The entry
     cave only touches W9, an unused slot here.
   * MatchingHandler.ReceiveWithTimeoutAsync.MoveNext (0x5D06B10) —
     CAVE_OBSERVER. Single-arg state-machine peek; we cache the stream
     pointer and react to MatchingStatus replies for Fixed Rate Range.

   ENTRY_SLOT_COUNT bumps from 3 to 5.

3. Hook_MatchingFilterObserve.m factors the JB hook bodies into shared
   helpers (filterMatchFoundResult / cacheJoinQueueParams) so the new
   chinlan entry hooks reuse the same decision logic and only differ in
   how orig is invoked (MSHookFunction trampoline on JB; cave-bypass
   entry on chinlan). InstallMatchingFilterObserveHook on chinlan now
   points g_ArgsCreate at the cave-bypass entry so sendAction() doesn't
   re-enter the entry hook on every requeue.

Builds: JB + chinlan both clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: document chinlan cave kinds with capability matrix and walkthrough

New page covers CAVE_OBSERVER vs CAVE_ENTRY:

- At-a-glance capability matrix (override return, swap args, W6 clobber,
  shared dispatcher vs per-site slot, etc.) so contributors can pick the
  right cave kind without reading the recipe.
- Annotated 21-insn cave layouts side-by-side so the +0x4C bypass-entry
  contract that both kinds preserve is obvious.
- 8-step walkthrough for adding a new site: pick the kind, validate the
  prologue is PC-independent, edit recipe / Internal.h / hook file /
  ChinlanDispatcher / Tweak.m, and verify with make ipa + chinlan boot
  logs. Worked example targets a CAVE_ENTRY conversion since that's the
  trickier case that needed cross-file coordination.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(chinlan): bump Sources/Chinlan submodule to 94d098d

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(chinlan): move ENTRY_SLOT_BASE_RVA into __common to fix the bss overflow

Previously the entry slot table started at 0x8F90CD0 — the last 8 bytes
of __DATA,__bss — so slot[0] fit but slot[1+] silently spilled into the
40-byte padding between __bss and __common. Both regions are zero-fill
so dyld didn't catch it, but Shared/tools/patch_macho.py's
assert_slot_in_bss only validates HOOK_SLOT_RVA and never noticed.

Relocate to 0x091E90B8 in __DATA,__common (2.4 MB section, 32-slot
reservation = 256 bytes at the section tail). Static asserts at recipe
import time now catch any future ENTRY_SLOT_CAPACITY / base bump that
would overflow the section bound captured in _COMMON_SECTION_END_RVA.

Extending the patcher's per-binary assert_slot_in_bss check to cover
every entry slot — not just HOOK_SLOT_RVA — is a separate Shared PR.

Builds: chinlan IPA repack confirmed; recipe import-time asserts hold
(reservation tail 0x091E91B8 == __common end).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(chinlan): persist LoginReply + SelfProfile on chinlan via entry caves

So accounts.json on chinlan finally carries the same accessToken-derived
userId, sessionId, deviceId, userName, and rank/rating array that the JB
build has been recording since PR #14.

- RunLoginSequenceAsync.MoveNext (RVA 0x5812534) and
  GetSelfUserProfileAsync.MoveNext (RVA 0x5BB4774) join the entry-cave
  table. The MoveNext fields they read (LoginReply pointer at
  state-machine offset 0x50, SelfUserProfileStatus rank list at 0x28)
  only land after orig advances state to -2, so the cave has to be
  CAVE_ENTRY: the hook calls the per-site bypass entry to actually run
  MoveNext, then reads the now-populated fields.

- Hook_AccountObserve.m factors the post-completion scan logic into
  observeRunLoginSeqCompletion() / observeGetSelfProfileCompletion() so
  the JB MSHook hooks and the new chinlan entry hooks reuse the same
  body. JB hooks call KIOU_CALL_ORIG_VOID first; chinlan entry hooks
  invoke orig through g_inject_entry[…] first. Either way the body sees
  a state-machine struct that's already advanced past the await.

- ENTRY_SLOT_COUNT goes 5 → 7. ChinlanDispatcher's publish log adds the
  two new pointers so a boot log makes the wiring obvious.

Builds: JB + chinlan + chinlan IPA repack all clean; all three new
patches (one observer for ReceiveTimeoutMoveNext, two entries for the
MoveNext observers) are applied to the IPA.

Untested on-device — but the read paths inside observe*() are unchanged
since PR #14 / #17, and the entry-cave dispatch shape is the same as
HookLoginArgsCreateEntry / HookAccountExistsEntry which have been
exercised in the prior chinlan boot logs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(chinlan): bump Sources/Chinlan submodule

* docs: address Copilot review nits on PR #17

- recipes/kiouenginebridge.py: the GetValidMatchFoundStatus row's
  comment said the hook returns NULL to reject the match, but the
  actual entry hook forwards orig's MatchFoundStatus unchanged and
  delivers the reject signal by firing ConnectionFailed at the stream.
  Rewrite the comment to match.
- docs/research/cave_kinds.md / Hook_MatchingFilterObserve.m: tighten
  the AAPCS64 wording. W9 is not "arg #9" (the integer arg sequence
  ends at x7; x8 is the indirect-result register). It IS call-clobbered
  scratch (x9–x15), which is exactly why touching it from the entry
  cave is safe — but say so in the language the ABI actually uses.
- docs/research/cave_kinds.md: drop BR / BLR from the "PC-relative,
  can't relocate" list. They're register-indirect, so the branch
  instruction itself IS PC-independent; what makes them unsafe to lift
  is the ADRP/MOVZ chain that loaded the target register a few insns
  earlier. Spell that out so the next contributor doesn't get the same
  wrong impression.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(cave_kinds): unify ADRP/LDR placeholder names in cave diagrams

Copilot review on the sibling Chinlan PR (and applicable here too)
noted that the ADRP/LDR pair used different placeholders for the same
address — `page(HOOK_SLOT_RVA)` + `lo12(SLOT)`, and similarly
`page(entry_slot_va)` + `lo12(slot)`. Make both sides of each ADRP/LDR
pair name the same symbol so the relocation pattern is unambiguous.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(chinlan): bump submodule to 90512ec

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants