make ep3 editors patch idempotent
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
# r3 = dest ptr
|
||||||
|
# r4 = src ptr
|
||||||
|
# r5 = size
|
||||||
|
addi r5, r5, 3
|
||||||
|
rlwinm r5, r5, 30, 2, 31 # r5 = number of words to copy
|
||||||
|
mtctr r5
|
||||||
|
subi r3, r3, 4 # r3 = r3 - 4 (so we can use stwu)
|
||||||
|
subi r4, r4, 4 # r4 = r4 - 4 (so we can use lwzu)
|
||||||
|
copy_word_again:
|
||||||
|
lwzu r0, [r4 + 4]
|
||||||
|
stwu [r3 + 4], r0
|
||||||
|
bdnz copy_word_again
|
||||||
|
|
||||||
|
rlwinm r4, r5, 2, 0, 29
|
||||||
|
addi r3, r3, 4
|
||||||
|
sub r3, r3, r4
|
||||||
|
.include FlushCachedCode
|
||||||
@@ -9,19 +9,6 @@
|
|||||||
# option is disabled, the Patches menu won't appear for the client. If this
|
# option is disabled, the Patches menu won't appear for the client. If this
|
||||||
# patch is run on a different client version, it will do nothing.
|
# patch is run on a different client version, it will do nothing.
|
||||||
|
|
||||||
# When you run this patch (via the $patch chat command, since it must be done
|
|
||||||
# when already in a lobby or game), the screen will go mostly black for a few
|
|
||||||
# seconds while the editors are constructed. It's unclear why this takes so
|
|
||||||
# long, but it doesn't seem to cause any other issues.
|
|
||||||
|
|
||||||
# This patch automatically does nothing if it has been run already in the
|
|
||||||
# current session, since some of the things it does have unclear lifecycles.
|
|
||||||
# This means it can only be used once per power-on; in the future, we could hook
|
|
||||||
# into the destroy functions of the various editors to know when it's OK to
|
|
||||||
# construct them again. (We'd also have to manage some hackish bookkeeping that
|
|
||||||
# the TEditor base class does so its list doesn't overflow, which would cause
|
|
||||||
# any new editors to be deleted immediately.)
|
|
||||||
|
|
||||||
entry_ptr:
|
entry_ptr:
|
||||||
reloc0:
|
reloc0:
|
||||||
.offsetof start
|
.offsetof start
|
||||||
@@ -48,43 +35,49 @@ start:
|
|||||||
cmp r4, r5
|
cmp r4, r5
|
||||||
bne skip_all
|
bne skip_all
|
||||||
|
|
||||||
# Running this patch multiple times will likely crash the client, so do
|
# Write a short hook that updates our editors table when TEditor_destroy() is
|
||||||
# nothing if we detect the patch has already run.
|
# called
|
||||||
|
bl get_TEditor_destroy_hook_addr
|
||||||
|
mr r4, r3
|
||||||
|
bl get_TEditor_destroy_hook_end
|
||||||
|
sub r5, r3, r4
|
||||||
|
subi r5, r5, 0x08
|
||||||
|
lis r3, 0x8000
|
||||||
|
ori r3, r3, 0xBD00
|
||||||
|
bl copy_code
|
||||||
|
|
||||||
|
# Make TEditor_destroy call our hook immediately before returning
|
||||||
|
bl get_patch_branch_opcode
|
||||||
|
mr r4, r3
|
||||||
|
lis r3, 0x8002
|
||||||
|
ori r3, r3, 0xE554
|
||||||
|
li r5, 4
|
||||||
|
bl copy_code
|
||||||
|
|
||||||
lis r29, 0x8000
|
lis r29, 0x8000
|
||||||
ori r29, r29, 0xBD44
|
ori r29, r29, 0xBD44
|
||||||
lwz r3, [r29 - 4]
|
|
||||||
mr. r0, r3
|
|
||||||
bne skip_all
|
|
||||||
li r0, -1
|
|
||||||
stw [r29 - 4], r0
|
|
||||||
|
|
||||||
setup_editors:
|
|
||||||
# This function sets up various things that the editors require. Most editors
|
|
||||||
# will crash in update() if this isn't called before construction time.
|
|
||||||
# Note: In PSO PC (the version I have, at least) this function may not exist.
|
|
||||||
# It can presumably be simulated by calling the first of each triplet of
|
|
||||||
# function pointers, which is essentially what this function does in Episode
|
|
||||||
# 3. Below, we call [r30 + 0x08], which constructs each editor; there are
|
|
||||||
# optional function pointers at [r30 + 0x00] and [r30 + 0x04] which prepare
|
|
||||||
# and clean up each editor respectively. It will probably suffice on PSOPC to
|
|
||||||
# simply call all the prepare functions that aren't null.
|
|
||||||
lis r0, 0x8002
|
|
||||||
ori r0, r0, 0x9D88
|
|
||||||
mtctr r0
|
|
||||||
bctrl
|
|
||||||
|
|
||||||
construct_editors:
|
construct_editors:
|
||||||
# Call the constructors for all the editors and save the object pointers
|
# Call the constructors for all the editors and save the object pointers. If
|
||||||
|
# an editor already exists, set its disable flags. (This behavior allows this
|
||||||
|
# patch to run again to switch to a different editor without changing rooms.)
|
||||||
# Note: In PSO PC (the version I have, at least) this table is at 00691FA8.
|
# Note: In PSO PC (the version I have, at least) this table is at 00691FA8.
|
||||||
lis r30, 0x8043
|
lis r30, 0x8043
|
||||||
ori r30, r30, 0x3760
|
ori r30, r30, 0x3760
|
||||||
addi r31, r30, 0xB4 # 15 entries * 12 bytes per entry
|
addi r31, r30, 0xB4 # 15 entries * 12 bytes per entry
|
||||||
again:
|
again:
|
||||||
|
lwz r3, [r29]
|
||||||
|
mr. r0, r3
|
||||||
|
bne editor_already_exists
|
||||||
lwz r0, [r30 + 0x08]
|
lwz r0, [r30 + 0x08]
|
||||||
mtctr r0
|
mtctr r0
|
||||||
bctrl
|
bctrl
|
||||||
addi r30, r30, 0x0C
|
|
||||||
stw [r29], r3
|
stw [r29], r3
|
||||||
|
editor_already_exists:
|
||||||
|
li r0, 0x0014 # Flags: disable update, disable render
|
||||||
|
# See comment below about the flags field on PSO PC.
|
||||||
|
sth [r3 + 0x04], r0
|
||||||
|
addi r30, r30, 0x0C
|
||||||
addi r29, r29, 4
|
addi r29, r29, 4
|
||||||
cmpl r30, r31
|
cmpl r30, r31
|
||||||
blt again
|
blt again
|
||||||
@@ -92,9 +85,9 @@ again:
|
|||||||
activate_chosen_editor:
|
activate_chosen_editor:
|
||||||
# All of the editors have flags set at construction time that effectively
|
# All of the editors have flags set at construction time that effectively
|
||||||
# disable them (by disabling both the update and render functions). At the
|
# disable them (by disabling both the update and render functions). At the
|
||||||
# time this code is executed, the flags are already set, so we can unset them
|
# time this code is executed, the flags are already set (and we set them again
|
||||||
# for whichever editor we want to run by uncommenting the appropriate lwz
|
# in the above loop anyway), so we can unset the flags for whichever editor we
|
||||||
# opcode below.
|
# want to run by uncommenting the appropriate lwz opcode below.
|
||||||
# Most of these tools expect input from the controller in port 3; the comments
|
# Most of these tools expect input from the controller in port 3; the comments
|
||||||
# below all refer to inputs from that port.
|
# below all refer to inputs from that port.
|
||||||
|
|
||||||
@@ -201,3 +194,42 @@ skip_all:
|
|||||||
addi r1, r1, 0x20
|
addi r1, r1, 0x20
|
||||||
mtlr r0
|
mtlr r0
|
||||||
blr
|
blr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
copy_code:
|
||||||
|
.include CopyCode
|
||||||
|
blr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
get_addr_ret:
|
||||||
|
mflr r3
|
||||||
|
mtlr r0
|
||||||
|
blr
|
||||||
|
|
||||||
|
get_TEditor_destroy_hook_addr:
|
||||||
|
mflr r0
|
||||||
|
bl get_addr_ret
|
||||||
|
|
||||||
|
TEditor_destroy_hook:
|
||||||
|
li r4, 0x0F
|
||||||
|
mtctr r4
|
||||||
|
lis r4, 0x8000
|
||||||
|
ori r4, r4, 0xBD40
|
||||||
|
li r0, 0
|
||||||
|
TEditor_destroy_hook_check_next:
|
||||||
|
lwzu r5, [r4 + 4]
|
||||||
|
cmp r5, r3
|
||||||
|
bne TEditor_destroy_hook_skip_clear
|
||||||
|
stw [r4], r0
|
||||||
|
TEditor_destroy_hook_skip_clear:
|
||||||
|
bdnz TEditor_destroy_hook_check_next
|
||||||
|
blr
|
||||||
|
|
||||||
|
get_TEditor_destroy_hook_end:
|
||||||
|
get_patch_branch_opcode:
|
||||||
|
mflr r0
|
||||||
|
bl get_addr_ret
|
||||||
|
|
||||||
|
.data 0x4BFDD7AC # (at 8002E554) b 8000BD00
|
||||||
|
|||||||
Reference in New Issue
Block a user