update some command notes

This commit is contained in:
Martin Michelsen
2025-09-13 10:43:14 -07:00
parent 24cf8e73c6
commit dea0ac99c3
9 changed files with 145 additions and 116 deletions
@@ -0,0 +1,473 @@
.meta hide_from_patches_menu
.meta name="DMC"
.meta description="Mitigates effects\nof enemy health\ndesync"
.meta client_flag="0x2000000000000000"
.versions 3OJ2 3OJ3 3OJ4 3OJ5 3OE0 3OE1 3OE2 3OP0
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksGC
.label TObjectV8047c128_add_hp, <VERS 0x8001143C 0x8001145C 0x800116EC 0x8001140C 0x80011454 0x80011454 0x8001140C 0x80011484>
.label TObjectV8047c128_subtract_hp, <VERS 0x8001147C 0x8001149C 0x8001172C 0x8001144C 0x80011494 0x80011494 0x8001144C 0x800114C4>
.label get_enemy_entity, <VERS 0x800F6608 0x800F690C 0x800F6C00 0x800F6A34 0x800F68AC 0x800F68AC 0x800F6A44 0x800F6A0C>
.label send_60, <VERS 0x801DBBA8 0x801DC0D4 0x801DD314 0x801DC0D0 0x801DBFE0 0x801DBFE0 0x801DC134 0x801DC6C0>
.label send_and_handle_60, <VERS 0x801E404C 0x801E45D0 0x801E47A4 0x801E451C 0x801E44B0 0x801E44B0 0x801E4570 0x801E4BAC>
.data <VERS 0x801E40C4 0x801E4648 0x801E481C 0x801E4594 0x801E4528 0x801E4528 0x801E45E8 0x801E4C24>
.data 8
cmpwi r0, 0
beq +0x0C
# Don't allow 6x0A to set total_damage; we'll do it with 6xE4 instead
.data <VERS 0x800F6064 0x800F6368 0x800F6594 0x800F6490 0x800F6308 0x800F6308 0x800F64A0 0x800F6468>
.data 4
.address <VERS 0x800F6064 0x800F6368 0x800F6594 0x800F6490 0x800F6308 0x800F6308 0x800F64A0 0x800F6468>
bl set_enemy_total_damage_hook
# Enemy state setup debug hook
.data <VERS 0x800F60BC 0x800F63C0 0x800F65EC 0x800F64E8 0x800F6360 0x800F6360 0x800F64F8 0x800F64C0>
.data 4
.address <VERS 0x800F60BC 0x800F63C0 0x800F65EC 0x800F64E8 0x800F6360 0x800F6360 0x800F64F8 0x800F64C0>
bl debug_hook1
# Replace 6x09 with 6xE4 in subcommand handler table
.data <VERS 0x804C00C4 0x804C37FC 0x804C5C9C 0x804C5A3C 0x804C0894 0x804C0D74 0x804C5314 0x804C57B4>
.data 8
.data 0x00E40006 # subcommand=0xE4, flags=6
.data 0x800041C0 # handle_6xE4
# add_hp callsite in TObjectV8047c128_v17_accept_hit
.data <VERS 0x80013A78 0x80013AA8 0x80013E18 0x80013A58 0x80013A90 0x80013A90 0x80013A58 0x80013AD0>
.data 4
.address <VERS 0x80013A78 0x80013AA8 0x80013E18 0x80013A58 0x80013A90 0x80013A90 0x80013A58 0x80013AD0>
bl on_TObjectV8047c128_add_hp_with_sync
# subtract_hp callsites in TObjectV8047c128_subtract_hp_if_not_in_state_2
.data <VERS 0x800114F0 0x80011510 0x800117A0 0x800114C0 0x80011508 0x80011508 0x800114C0 0x80011538>
.data 4
.address <VERS 0x800114F0 0x80011510 0x800117A0 0x800114C0 0x80011508 0x80011508 0x800114C0 0x80011538>
bl on_TObjectV8047c128_subtract_hp_with_sync
# subtract_hp callsites in TObjectV8047c128_v18_handle_hit_special_effects
.data <VERS 0x80011C50 0x80011C80 0x80011F48 0x80011C30 0x80011C68 0x80011C68 0x80011C30 0x80011CA8>
.data 4
.address <VERS 0x80011C50 0x80011C80 0x80011F48 0x80011C30 0x80011C68 0x80011C68 0x80011C30 0x80011CA8>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80011CA0 0x80011CD0 0x80011F98 0x80011C80 0x80011CB8 0x80011CB8 0x80011C80 0x80011CF8>
.data 4
.address <VERS 0x80011CA0 0x80011CD0 0x80011F98 0x80011C80 0x80011CB8 0x80011CB8 0x80011C80 0x80011CF8>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80011D1C 0x80011D4C 0x80012014 0x80011CFC 0x80011D34 0x80011D34 0x80011CFC 0x80011D74>
.data 4
.address <VERS 0x80011D1C 0x80011D4C 0x80012014 0x80011CFC 0x80011D34 0x80011D34 0x80011CFC 0x80011D74>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80011D6C 0x80011D9C 0x80012064 0x80011D4C 0x80011D84 0x80011D84 0x80011D4C 0x80011DC4>
.data 4
.address <VERS 0x80011D6C 0x80011D9C 0x80012064 0x80011D4C 0x80011D84 0x80011D84 0x80011D4C 0x80011DC4>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80012774 0x800127A4 0x80012A6C 0x80012754 0x8001278C 0x8001278C 0x80012754 0x800127CC>
.data 4
.address <VERS 0x80012774 0x800127A4 0x80012A6C 0x80012754 0x8001278C 0x8001278C 0x80012754 0x800127CC>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80012AE8 0x80012B18 0x80012DE0 0x80012AC8 0x80012B00 0x80012B00 0x80012AC8 0x80012B40>
.data 4
.address <VERS 0x80012AE8 0x80012B18 0x80012DE0 0x80012AC8 0x80012B00 0x80012B00 0x80012AC8 0x80012B40>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80012C58 0x80012C88 0x80012F50 0x80012C38 0x80012C70 0x80012C70 0x80012C38 0x80012CB0>
.data 4
.address <VERS 0x80012C58 0x80012C88 0x80012F50 0x80012C38 0x80012C70 0x80012C70 0x80012C38 0x80012CB0>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80012FE0 0x80013010 0x800132D8 0x80012FC0 0x80012FF8 0x80012FF8 0x80012FC0 0x80013038>
.data 8
fmuls f3, f0, f2
fmuls f31, f30, f3
.data <VERS 0x80012FFC 0x8001302C 0x800132F4 0x80012FDC 0x80013014 0x80013014 0x80012FDC 0x80013054>
.data 4
fctiwz f3, f31
.data <VERS 0x80013004 0x80013034 0x800132FC 0x80012FE4 0x8001301C 0x8001301C 0x80012FE4 0x8001305C>
.data 4
stfd [r1 + 0x40], f3
.data <VERS 0x8001300C 0x8001303C 0x80013304 0x80012FEC 0x80013024 0x80013024 0x80012FEC 0x80013064>
.data 4
.address <VERS 0x8001300C 0x8001303C 0x80013304 0x80012FEC 0x80013024 0x80013024 0x80012FEC 0x80013064>
bl on_TObjectV8047c128_subtract_hp_with_sync_demons_devils
# subtract_hp callsites in TObjectV8047c128_v17_accept_hit
.data <VERS 0x80013454 0x80013484 0x800137F4 0x80013434 0x8001346C 0x8001346C 0x80013434 0x800134AC>
.data 4
.address <VERS 0x80013454 0x80013484 0x800137F4 0x80013434 0x8001346C 0x8001346C 0x80013434 0x800134AC>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x8001354C 0x8001357C 0x800138EC 0x8001352C 0x80013564 0x80013564 0x8001352C 0x800135A4>
.data 4
.address <VERS 0x8001354C 0x8001357C 0x800138EC 0x8001352C 0x80013564 0x80013564 0x8001352C 0x800135A4>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80013644 0x80013674 0x800139E4 0x80013624 0x8001365C 0x8001365C 0x80013624 0x8001369C>
.data 4
.address <VERS 0x80013644 0x80013674 0x800139E4 0x80013624 0x8001365C 0x8001365C 0x80013624 0x8001369C>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x800137AC 0x800137DC 0x80013B4C 0x8001378C 0x800137C4 0x800137C4 0x8001378C 0x80013804>
.data 4
.address <VERS 0x800137AC 0x800137DC 0x80013B4C 0x8001378C 0x800137C4 0x800137C4 0x8001378C 0x80013804>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x800138EC 0x8001391C 0x80013C8C 0x800138CC 0x80013904 0x80013904 0x800138CC 0x80013944>
.data 4
.address <VERS 0x800138EC 0x8001391C 0x80013C8C 0x800138CC 0x80013904 0x80013904 0x800138CC 0x80013944>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80013E00 0x80013E30 0x800141A0 0x80013DE0 0x80013E18 0x80013E18 0x80013DE0 0x80013E58>
.data 4
.address <VERS 0x80013E00 0x80013E30 0x800141A0 0x80013DE0 0x80013E18 0x80013E18 0x80013DE0 0x80013E58>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80013F04 0x80013F34 0x800142A4 0x80013EE4 0x80013F1C 0x80013F1C 0x80013EE4 0x80013F5C>
.data 4
.address <VERS 0x80013F04 0x80013F34 0x800142A4 0x80013EE4 0x80013F1C 0x80013F1C 0x80013EE4 0x80013F5C>
bl on_TObjectV8047c128_subtract_hp_with_sync
# subtract_hp callsites in TObjectV8047c128_v16
.data <VERS 0x80014770 0x800147A0 0x80014B38 0x80014750 0x80014788 0x80014788 0x80014750 0x800147C8>
.data 4
.address <VERS 0x80014770 0x800147A0 0x80014B38 0x80014750 0x80014788 0x80014788 0x80014750 0x800147C8>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data 0x800041C0
.deltaof code_start, code_end
.address 0x800041C0
code_start:
handle_6xE4: # [std] (G_IncrementEnemyDamage_Extension_6xE4* cmd @ r3) -> void
lwz r12, [r13 - <VERS 0x50A0 0x5098 0x5078 0x5078 0x5088 0x5088 0x5068 0x5028>]
andi. r12, r12, 0x0080
beqlr
mflr r0
stw [r1 + 4], r0
stwu [r1 - 0x20], r1
stw [r1 + 0x08], r31
stw [r1 + 0x0C], r30
mr r31, r3
li r3, 2
lhbrx r3, [r31 + r3]
cmplwi r3, 0x1000
blt handle_6xE4_return
cmplwi r3, 0x1B50
bge handle_6xE4_return
bl get_enemy_entity
stw [r1 + 0x18], r3 # TObjEnemy* ene @ var18 = get_enemy_entity(cmd->header.entity_id);
li r3, 2
lhbrx r3, [r31 + r3]
bl state_for_enemy # EnemyState* st = state_for_enemy(cmd->header.entity_id);
li r4, 0x0C
lwbrx r5, [r31 + r4] # cmd->factor
andis. r0, r5, 0x8000
bne handle_6xE4_not_proportional
stwx [r31 + r4], r5
li r8, 0x0A
lhbrx r8, [r31 + r8]
lhz r4, [r3 + 6]
sub r8, r8, r4 # current_hp = cmd->max_hp - st->total_damage
cmpwi r8, 0
blt handle_6xE4_not_proportional
lis r4, 0x4B00
or r5, r4, r8
stw [r1 - 4], r5
lfs f1, [r1 - 4]
stw [r1 - 4], r4
lfs f2, [r1 - 4]
fsubs f1, f1, f2 # f1 = static_cast<float>(current_hp)
lfs f2, [r31 + 0x0C]
fmuls f1, f1, f2
fctiwz f1, f1
stfd [r1 - 8], f1
lwz r8, [r1 - 4]
li r4, 1
cmp r8, r4
bge handle_6xE4_proportional_positive
mr r8, r4
handle_6xE4_proportional_positive:
li r5, 0x04
sthbrx [r31 + r5], r8
handle_6xE4_not_proportional:
# r3 still has the return value of state_for_enemy
lhz r4, [r3 + 6] # st->total_damage
li r5, 0x04
lhbrx r5, [r31 + r5] # cmd->hit_amount
add r4, r4, r5 # st->total_damage + cmd->hit_amount
li r5, 0x0A
lhbrx r5, [r31 + r5] # cmd->max_hp
cmp r4, r5
blt handle_6xE4_damage_less_than_max_hp
sth [r3 + 6], r5 # st->total_damage = cmd->max_hp;
li r4, 0x0C
bl send_debug_info # TODO: Remove this when no longer necessary
lwz r4, [r3]
andi. r0, r4, 0x800
bne handle_6xE4_return
ori r4, r4, 0x800
stw [r3], r4 # st->game_flags |= 0x800;
# Send 6x0A with dead flag, but only if the entity is constructed
lwz r6, [r1 + 0x18]
cmplwi r6, 0
beq handle_6xE4_return
stw [r1 + 0x14], r4
li r6, 0x12
sthbrx [r1 + r6], r5
lhz r6, [r31 + 2]
oris r6, r6, 0x0A03
stw [r1 + 0x0C], r6
andi. r6, r6, 0xFF0F
sth [r1 + 0x10], r6
addi r3, r1, 0x0C
bl send_and_handle_60
b handle_6xE4_return
handle_6xE4_damage_less_than_max_hp:
cmpwi r4, 0
bge handle_6xE4_damage_nonnegative
li r4, 0
handle_6xE4_damage_nonnegative:
sth [r3 + 6], r4 # st->total_damage = std::max<int16_t>(st->total_damage + cmd->hit_amount, 0);
li r4, 0x0C
mr r30, r3
bl send_debug_info
lwz r3, [r1 + 0x18] # if (ene) ene->v50_on_state_updated(&st);
cmplwi r3, 0
beq handle_6xE4_return
mr r4, r30
lwz r12, [r3 + 0x18]
lwz r12, [r12 + 0x140]
mtctr r12
bctrl
handle_6xE4_return:
lwz r30, [r1 + 0x0C]
lwz r31, [r1 + 0x08]
addi r1, r1, 0x20
lwz r0, [r1 + 4]
mtlr r0
blr
state_for_enemy: # [/r4] (uint16_t entity_id @ r3) -> EnemyState* @ r3
# return &enemy_states[entity_id & 0x0FFF];
lwz r4, [r13 - <VERS 0x44F4 0x44EC 0x44CC 0x44CC 0x44DC 0x44DC 0x44BC 0x447C>]
andi. r3, r3, 0x0FFF
mulli r3, r3, 0x0C
add r3, r3, r4
blr
# AdjustmentType:
# 0 = SUBTRACT
# 1 = SUBTRACT_PROPORTION
# 2 = ADD
on_TObjectV8047c128_subtract_hp_with_sync_demons_devils:
li r5, 1
b on_add_or_subtract_hp
on_TObjectV8047c128_add_hp_with_sync: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4) -> void
li r5, 2
b on_add_or_subtract_hp
on_TObjectV8047c128_subtract_hp_with_sync: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4) -> void
li r5, 0
on_add_or_subtract_hp: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4, AdjustmentType type @ r5) -> void
lwz r12, [r13 - <VERS 0x50A0 0x5098 0x5078 0x5078 0x5088 0x5088 0x5068 0x5028>]
andi. r12, r12, 0x0080
beq on_add_or_subtract_hp_skip_send
lhz r0, [r3 + 0x1C]
cmplwi r0, 0x1000
blt on_add_or_subtract_hp_skip_send
cmplwi r0, 0x1B50
bge on_add_or_subtract_hp_skip_send
lwz r11, [r13 - <VERS 0x50B8 0x50B0 0x5090 0x5090 0x50A0 0x50A0 0x5080 0x5040>]
cmplwi r11, 0
beq on_add_or_subtract_hp_skip_send
mflr r0
stw [r1 + 4], r0
stwu [r1 - 0x40], r1
stw [r1 + 0x34], r29
stw [r1 + 0x38], r30
stw [r1 + 0x3C], r31
mr r29, r3
mr r30, r4
mr r31, r5
lhz r3, [r29 + 0x1C]
bl state_for_enemy # EnemyState* st = state_for_enemy(ene->entity_id);
mr r5, r30
cmplwi r31, 2
bne on_add_or_subtract_hp_skip_negate_amount
neg r5, r5
on_add_or_subtract_hp_skip_negate_amount:
li r4, 0x1C
lhbrx r4, [r29 + r4]
oris r4, r4, 0xE404
stw [r1 + 0x08], r4
li r4, 0x0C
sthbrx [r1 + r4], r5
li r4, 6
lhbrx r4, [r3 + r4]
sth [r1 + 0x0E], r4
li r4, 0x32C
lhbrx r4, [r29 + r4]
sth [r1 + 0x10], r4
li r4, 0x2B8
lhbrx r4, [r29 + r4]
sth [r1 + 0x12], r4
li r5, 0x14
cmplwi r31, 1
bne on_add_or_subtract_hp_not_proportional
fmuls f0, f30, f0
stfsx [r1 + r5], f0 # current_hp_factor (== (1.0 - special_amount * 0.01)) * weapon_reduction_factor
lwzx r4, [r1 + r5]
b on_add_or_subtract_hp_proportional_check_end
on_add_or_subtract_hp_not_proportional:
lis r4, 0xBF80
on_add_or_subtract_hp_proportional_check_end:
stwbrx [r1 + r5], r4
mr r3, r11
addi r4, r1, 0x08
li r5, 0x10
bl send_60
mr r3, r29
mr r4, r30
mr r5, r31
lwz r31, [r1 + 0x3C]
lwz r30, [r1 + 0x38]
lwz r29, [r1 + 0x34]
addi r1, r1, 0x40
lwz r0, [r1 + 4]
mtlr r0
on_add_or_subtract_hp_skip_send:
cmplwi r5, 2
bne on_add_or_subtract_hp_tail_call_subtract_hp
b TObjectV8047c128_add_hp
on_add_or_subtract_hp_tail_call_subtract_hp:
b TObjectV8047c128_subtract_hp
set_enemy_total_damage_hook:
lwz r12, [r13 - <VERS 0x50A0 0x5098 0x5078 0x5078 0x5088 0x5088 0x5068 0x5028>]
andi. r12, r12, 0x0080
bnelr
sth [r1 + 0x0E], r3
blr
# TODO: Remove this when no longer necessary
debug_hook1:
mflr r0
stw [r1 + 4], r0
stwu [r1 - 0x20], r1
mr r6, r3
mr r7, r4
mr r3, r4
li r4, 0x0C
li r5, -1
bl send_debug_info
mr r3, r6
mr r4, r7
addi r1, r1, 0x20
lwz r0, [r1 + 4]
mtlr r0
mtctr r12
bctr
send_debug_info: # (void* data @ r3, uint32_t size @ r4, uint16_t what @ r5) -> void
mflr r0
stw [r1 + 0x04], r0
stw [r1 - 0x04], r3
stw [r1 - 0x08], r4
stw [r1 - 0x0C], r5
stw [r1 - 0x10], r6
stw [r1 - 0x14], r7
stw [r1 - 0x18], r8
stw [r1 - 0x1C], r9
stw [r1 - 0x20], r10
stw [r1 - 0x24], r11
stw [r1 - 0x28], r12
subi r6, r1, 0x40
sub r6, r6, r4
stw [r6], r1
mr r1, r6
rlwinm r6, r4, 14, 8, 15
addis r6, r6, 1
oris r6, r6, 0xFF00
rlwinm r5, r5, 0, 16, 31
or r5, r5, r6
stw [r1 + 0x08], r5
li r6, 0
subi r3, r3, 4
addi r7, r1, 0x08
rlwinm r0, r4, 30, 24, 31
mtctr r0
copy_again:
lwzu r0, [r3 + 4]
stwu [r7 + 4], r0
bdnz copy_again
addi r3, r1, 0x08
bl send_and_handle_60
lwz r1, [r1]
lwz r3, [r1 - 0x04]
lwz r4, [r1 - 0x08]
lwz r5, [r1 - 0x0C]
lwz r6, [r1 - 0x10]
lwz r7, [r1 - 0x14]
lwz r8, [r1 - 0x18]
lwz r9, [r1 - 0x1C]
lwz r10, [r1 - 0x20]
lwz r11, [r1 - 0x24]
lwz r12, [r1 - 0x28]
lwz r0, [r1 + 0x04]
mtlr r0
blr
code_end:
.data 0x00000000
.data 0x00000000
@@ -0,0 +1,340 @@
.meta hide_from_patches_menu
.meta name="DMC"
.meta description="Mitigates effects\nof enemy health\ndesync"
.meta client_flag="0x2000000000000000"
.versions 4OJB 4OJD 4OJU 4OED 4OEU 4OPD 4OPU
entry_ptr:
reloc0:
.offsetof start
write_call_to_code_multi:
.include WriteCallToCodeMultiXB
start:
call write_static_patches
call write_incr_hp_with_sync
call write_6x0A_patch
ret
write_6x0A_patch:
push 5
push <VERS 0x002B3B55 0x002B4625 0x002B5BB5 0x002B56C5 0x002B58A5 0x002B56E5 0x002B59B5>
push 1
call +4
.deltaof on_6x0A_patch_start, on_6x0A_patch_end
pop eax
push dword [eax]
call on_6x0A_patch_end
on_6x0A_patch_start: # (TObjectV004434c8* this @ eax, int16_t amount @ cx) -> bool @ eax
test byte [0x006354B8], 0x80
jnz on_6x0A_patch_skip_write
mov [esp + 0x16], ax
on_6x0A_patch_skip_write:
ret
on_6x0A_patch_end:
call write_call_to_code_multi
ret
# Write TObjectV004434c8::incr_hp_with_sync
write_incr_hp_with_sync:
push 5
push <VERS 0x002A60CF 0x002A6BAF 0x002A807F 0x002A7B0F 0x002A7CEF 0x002A7B2F 0x002A7DAF> # v17 inlined callsite + 5
push 5
push <VERS 0x002A808D 0x002A8B6D 0x002AA03D 0x002A9ACD 0x002A9CAD 0x002A9AED 0x002A9D6D> # TObjectV004434c8::subtract_hp_if_not_in_state_2 + D
push 5
push <VERS 0x002A68FB 0x002A73DB 0x002A88AB 0x002A833B 0x002A851B 0x002A835B 0x002A85DB> # TObjectV004434c8::v18_accept_hit (presumably Resta) - this is add_hp, not subtract_hp!
push 5
push <VERS 0x002A650D 0x002A6FED 0x002A84BD 0x002A7F4D 0x002A812D 0x002A7F6D 0x002A81ED> # TObjectV004434c8::v18_accept_hit cases 0 and 4
push 5
push <VERS 0x002A65BA 0x002A709A 0x002A856A 0x002A7FFA 0x002A81DA 0x002A801A 0x002A829A> # TObjectV004434c8::v18_accept_hit case 1
push 5
push <VERS 0x002A6670 0x002A7150 0x002A8620 0x002A80B0 0x002A8290 0x002A80D0 0x002A8350> # TObjectV004434c8::v18_accept_hit case 2
push 5
push <VERS 0x002A6769 0x002A7249 0x002A8719 0x002A81A9 0x002A8389 0x002A81C9 0x002A8449> # TObjectV004434c8::v18_accept_hit case 3
push 5
push <VERS 0x002A6C19 0x002A76F9 0x002A8BC9 0x002A8659 0x002A8839 0x002A8679 0x002A88F9> # TObjectV004434c8::v18_accept_hit case 0x13
push 5
push <VERS 0x002A6CAC 0x002A778C 0x002A8C5C 0x002A86EC 0x002A88CC 0x002A870C 0x002A898C> # TObjectV004434c8::v18_accept_hit case 0x15
push 5
push <VERS 0x002A70AE 0x002A7B92 0x002A9062 0x002A8AF2 0x002A8CD2 0x002A8B12 0x002A8D92> # TObjectV004434c8::v19_handle_hit_special_effects case 1
push 5
push <VERS 0x002A7A53 0x002A7BD3 0x002A90A3 0x002A8B33 0x002A8D13 0x002A8B53 0x002A8DD3> # TObjectV004434c8::v19_handle_hit_special_effects case 1
push 5
push <VERS 0x002A76C4 0x002A81A8 0x002A9678 0x002A9108 0x002A92E8 0x002A9128 0x002A93A8> # TObjectV004434c8::v19_handle_hit_special_effects case 6
push 5
push <VERS 0x002A7953 0x002A8437 0x002A9907 0x002A9397 0x002A9577 0x002A93B7 0x002A9637> # TObjectV004434c8::v19_handle_hit_special_effects case 9
push 5
push <VERS 0x0024A140 0x002A8530 0x002A9A00 0x002A9490 0x002A9670 0x002A94B0 0x002A9730> # TObjectV004434c8::v19_handle_hit_special_effects case 0x0A
push 5
push <VERS 0x002A7CDB 0x002A87BF 0x002A9C8F 0x002A971F 0x002A98FF 0x002A973F 0x002A99BF> # TObjectV004434c8::v19_handle_hit_special_effects case 0x0D
push 15
call +4
.deltaof on_add_or_subtract_hp_start, on_add_or_subtract_hp_end
pop eax
push dword [eax]
call on_add_or_subtract_hp_end
on_add_or_subtract_hp_start: # (TObjectV004434c8* this @ eax, int16_t amount @ cx) -> bool @ eax
# Check if callsite is subtract_hp_if_not_in_state_2
push eax
push ecx
push ebx
test byte [0x006354B8], 0x80
jz on_add_or_subtract_hp_skip_send
movzx edx, word [eax + 0x1C] # ene->entity_id
cmp edx, 0x1000
jl on_add_or_subtract_hp_skip_send
cmp edx, 0x1B50
jge on_add_or_subtract_hp_skip_send
and edx, 0x0FFF
imul edx, edx, 0x0C
add edx, [<VERS 0x00633068 0x006336C8 0x0063B210 0x006386F8 0x00637F90 0x006386F8 0x00638A90>] # eax = state_for_enemy(cmd->header.entity_id)
sub esp, 0x10
mov word [esp], 0x04E4
mov bx, [eax + 0x1C]
mov [esp + 0x02], bx # cmd.entity_id
cmp dword [esp + 0x1C], <VERS 0x002A6900 0x002A73E0 0x002A88B0 0x002A8340 0x002A8520 0x002A8360 0x002A85E0> # Check if callsite is add_hp
jne on_add_or_subtract_hp_skip_negate_amount
neg cx
on_add_or_subtract_hp_skip_negate_amount:
mov [esp + 0x04], cx # cmd.hit_amount
mov bx, [edx + 6]
mov [esp + 0x06], bx # cmd.total_damage_before_hit
mov bx, [eax + 0x0330]
mov [esp + 0x08], bx # cmd.current_hp
mov bx, [eax + 0x02BC]
mov [esp + 0x0A], bx # cmd.max_hp
mov dword [esp + 0x0C], 0xBF800000 # cmd.factor
cmp dword [esp + 0x1C], <VERS 0x002A7CE0 0x002A87C4 0x002A9C94 0x002A9724 0x002A9904 0x002A9744 0x002A99C4> # Check if callsite is Devil's/Demon's
jne on_add_or_subtract_hp_not_proportional
# esp is 0x20 down from where it is in caller's context
mov cx, 100
sub cx, [esp + 0x34] # cx = (100 - special_amount)
movsx ecx, cx
mov [esp - 4], ecx
fild st0, dword [esp - 4] # current_hp_factor = static_cast<float>(100 - special_amount)
fmul st0, dword [esp + 0x38] # *= weapon_reduction_factor
mov dword [esp - 4], 0x42C80000 # 100.0f
fdiv st0, dword [esp - 4]
fstp dword [esp + 0x0C], st0 # cmd.factor = ((100 - special_amount) * weapon_reduction_factor) / 100
on_add_or_subtract_hp_not_proportional:
mov ecx, esp
mov ebx, [<VERS 0x0071EEFC 0x0071F55C 0x007270A0 0x0072459C 0x00723E20 0x0072459C 0x00724920>] # root_protocol
test ebx, ebx
jz on_add_or_subtract_hp_skip_send
mov eax, 0x10
# Can't just `call <addr>` here because this code is relocated at apply time
mov edx, <VERS 0x002DA120 0x002DACF0 0x002DC5B0 0x002DC080 0x002DC580 0x002DC0B0 0x002DC600>
call edx # send_60(root_protocol, &out_cmd, sizeof(out_cmd))
add esp, 0x10
on_add_or_subtract_hp_skip_send:
mov edx, <VERS 0x002A80C0 0x002A8BA0 0x002AA070 0x002A9B00 0x002A9CE0 0x002A9B20 0x002A9DA0> # subtract_hp
mov eax, <VERS 0x002A80F0 0x002A8BD0 0x002AA0A0 0x002A9B30 0x002A9D10 0x002A9B50 0x002A9DD0> # add_hp
cmp dword [esp + 0x0C], <VERS 0x002A6900 0x002A73E0 0x002A88B0 0x002A8340 0x002A8520 0x002A8360 0x002A85E0> # Check if callsite is add_hp
cmove edx, eax
pop ebx
pop ecx
pop eax
jmp edx
on_add_or_subtract_hp_end:
call write_call_to_code_multi
ret
write_static_patches:
.include WriteCodeBlocksXB
.data <VERS 0x002DB7A0 0x002DC370 0x002DDC30 0x002DD700 0x002DDC00 0x002DD730 0x002DDC80>
.data 9
flag_check_start:
cmp dword [0x006354B8], 0
je +0x38
flag_check_end:
.data <VERS 0x00537180 0x00537800 0x0053EB20 0x0053BFA0 0x0053B840 0x0053BFA0 0x0053C340>
.data 8
.data 0x000600E4 # subcommand=0xE4, flags=6
.addrof handle_6xE4
.data <VERS 0x002DA510 0x002DB0E0 0x002DC9A0 0x002DC470 0x002DC970 0x002DC4A0 0x002DC9F0>
.deltaof handle_91_replacement, handle_6xE4_end
.address <VERS 0x002DA510 0x002DB0E0 0x002DC9A0 0x002DC470 0x002DC970 0x002DC4A0 0x002DC9F0>
handle_91_replacement: # [std] (S_91* cmd @ [esp + 4]) -> void
ret 4
handle_6xE4: # [std] (G_6xE4* cmd @ [esp + 4]) -> void
push ebx
push esi
push edi
test byte [0x006354B8], 0x80
jz handle_6xE4_return
mov ebx, [esp + 0x10] # cmd
movzx eax, word [ebx + 2]
cmp eax, 0x1000
jl handle_6xE4_return
cmp eax, 0x1B50
jge handle_6xE4_return
mov edi, eax
call <VERS 0x002B36B0 0x002B4180 0x002B5710 0x002B5220 0x002B5400 0x002B5240 0x002B5510> # TObjEnemy* ene = get_enemy_entity(cmd->header.entity_id);
push eax
movzx eax, word [ebx + 2]
and eax, 0x0FFF
imul eax, eax, 0x0C
add eax, [<VERS 0x00633068 0x006336C8 0x0063B210 0x006386F8 0x00637F90 0x006386F8 0x00638A90>] # eax = state_for_enemy(cmd->header.entity_id)
cmp dword [ebx + 0x0C], 0
jl handle_6xE4_not_proportional
mov cx, [ebx + 0x0A] # cmd->max_hp
sub cx, [eax + 0x06] # st.total_damage
movzx ecx, cx
xor edx, edx
cmp ecx, edx
cmovl ecx, edx
mov [esp - 4], ecx
fild st0, dword [esp - 4] # current_hp = static_cast<float>(max<int32_t>(cmd->max_hp - st.total_damage, 0))
fld st0, dword [ebx + 0x0C]
fmulp st1, st0
fistp dword [esp - 4], st0
mov ecx, dword [esp - 4] # adjusted_hit_amount = static_cast<int16_t>(current_hp * cmd->factor)
xor edx, edx
inc edx
cmp ecx, edx
cmovl ecx, edx
mov [ebx + 0x04], cx # cmd->hit_amount = min<int32_t>(1, adjusted_hit_amount)
handle_6xE4_not_proportional:
movzx edx, word [eax + 0x06] # st.total_damage
movsx esi, word [ebx + 0x04] # cmd->hit_amount
movzx edi, word [ebx + 0x0A] # cmd->max_hp
add edx, esi # st.total_damage + cmd->hit_amount
cmp edx, edi
jl handle_6xE4_damage_less_than_max_hp
mov [eax + 0x06], di # st.total_damage = cmd->max_hp;
mov edx, [eax]
test edx, 0x800
jnz handle_6xE4_return_pop_ene
or edx, 0x800
mov [eax], edx
cmp dword [esp], 0
je handle_6xE4_return_pop_ene
push edx # out_cmd.flags
sub esp, 8
mov word [esp], 0x030A # out_cmd.header.{subcommand,size}
mov si, [ebx + 2]
mov [esp + 2], si # out_cmd.header.entity_id
and si, 0x0FFF
mov [esp + 4], si # out_cmd.entity_index
mov [esp + 6], di # out_cmd.total_damage
mov ecx, esp
push ecx # For handle_60 later
mov ebx, [<VERS 0x0071EEFC 0x0071F55C 0x007270A0 0x0072459C 0x00723E20 0x0072459C 0x00724920>] # root_protocol
test ebx, ebx
jz handle_6xE4_root_protocol_missing
mov eax, 0x0C
call <VERS 0x002DA120 0x002DACF0 0x002DC5B0 0x002DC080 0x002DC580 0x002DC0B0 0x002DC600> # send_60(root_protocol, &out_cmd, sizeof(out_cmd))
handle_6xE4_root_protocol_missing:
mov dword [<VERS 0x0071E8C8 0x0071EF28 0x00726A68 0x00723F68 0x007237E8 0x00723F68 0x007242E8>], 1
call <VERS 0x002DBC30 0x002DC7B0 0x002DE070 0x002DDB90 0x002DE090 0x002DDBC0 0x002DE0C0> # handle_60(&out_cmd)
mov dword [<VERS 0x0071E8C8 0x0071EF28 0x00726A68 0x00723F68 0x007237E8 0x00723F68 0x007242E8>], 0
add esp, 0x14
jmp handle_6xE4_return
handle_6xE4_damage_less_than_max_hp:
xor edi, edi
cmp edx, edx
cmovl edx, edi
mov [eax + 0x06], dx # st.total_damage = std::max<int16_t>(st.total_damage + cmd->hit_amount, 0);
mov esi, eax # esi = ene_st
mov eax, [esp] # eax = ene
test eax, eax
jz handle_6xE4_return_pop_ene
mov ecx, eax
push esi
mov edx, [ecx]
call [edx + 0x138] # ene->vtable[0x4E](ene, &st);
handle_6xE4_return_pop_ene:
add esp, 4
handle_6xE4_return:
pop edi
pop esi
pop ebx
ret
handle_6xE4_end:
# Rewrite TObjectV004434c8::subtract_hp_if_not_in_state_2
.data <VERS 0x002A8080 0x002A8B60 0x002AA030 0x002A9AC0 0x002A9CA0 0x002A9AE0 0x002A9D60>
.deltaof on_subtract_hp_if_not_in_state_2_start, on_subtract_hp_if_not_in_state_2_end
.address <VERS 0x002A8080 0x002A8B60 0x002AA030 0x002A9AC0 0x002A9CA0 0x002A9AE0 0x002A9D60>
on_subtract_hp_if_not_in_state_2_start: # (TObjectV004434c8* this @ eax, int16_t amount @ cx) -> bool @ eax
cmp word [eax + 0x328], 2
jne on_subtract_hp_if_not_in_state_2_do_subtract
xor eax, eax
ret
on_subtract_hp_if_not_in_state_2_do_subtract:
call -1 # Overwritten by write_call_to_code_multi later
ret
on_subtract_hp_if_not_in_state_2_end:
# Inlined callsite of subtract_hp in TObjectV004434c8::v17
.data <VERS 0x002A60CA 0x002A6BAA 0x002A807A 0x002A7B0A 0x002A7CEA 0x002A7B2A 0x002A7DAA>
.deltaof v17_subtract_hp_inlined_callsite_start, v17_subtract_hp_inlined_callsite_end
.address <VERS 0x002A60CA 0x002A6BAA 0x002A807A 0x002A7B0A 0x002A7CEA 0x002A7B2A 0x002A7DAA>
v17_subtract_hp_inlined_callsite_start:
# This must assemble to exactly 0x1A bytes. There is a vfn call shortly after
# this, and fortunately it appears eax, ecx, and edx are not used before
# then, so we don't have to save any registers here; we just have to move the
# args into the right places.
mov cx, ax
mov eax, edi
call -1 # Overwritten by write_call_to_code_multi later
jmp v17_subtract_hp_inlined_callsite_end
int 3
int 3
int 3
int 3
int 3
int 3
int 3
int 3
int 3
int 3
int 3
int 3
int 3
int 3
v17_subtract_hp_inlined_callsite_end:
.data 0x00000000
.data 0x00000000
@@ -0,0 +1,257 @@
.meta hide_from_patches_menu
.meta name="DMC"
.meta description="Mitigates effects\nof enemy health\ndesync"
.meta client_flag="0x2000000000000000"
entry_ptr:
reloc0:
.offsetof start
write_call_to_code_multi:
.include WriteCallToCodeMulti-59NL
write_address_of_code:
.include WriteAddressOfCode-59NL
start:
# Replace 6x09 with 6xE4 in subcommand handler table
mov dword [0x00A0FC30], 0x000600E4 # subcommand=0xE4, flags=6
push 0x00A0FC34
call +4
.deltaof handle_6xE4_start, handle_6xE4_end
pop eax
push dword [eax]
call handle_6xE4_end
handle_6xE4_start: # (G_6xE4* cmd @ [esp + 4]) -> void
push ebx
push esi
push edi
test byte [0x00AAB27C], 0x80
jz handle_6xE4_return
mov ebx, [esp + 0x10] # cmd
movzx eax, word [ebx + 2]
cmp eax, 0x1000
jl handle_6xE4_return
cmp eax, 0x1B50
jge handle_6xE4_return
movzx eax, word [ebx + 2]
.include GetEnemyEntity-59NL # auto* ene = get_enemy_entity(cmd->header.entity_id);
push eax
movzx eax, word [ebx + 2]
and eax, 0x0FFF
imul eax, eax, 0x0C
add eax, [0x00AB02B8] # eax = state_for_enemy(cmd->header.entity_id)
cmp dword [ebx + 0x0C], 0
jl handle_6xE4_not_proportional
mov cx, [ebx + 0x0A] # cmd->max_hp
sub cx, [eax + 0x06] # st.total_damage
movzx ecx, cx
xor edx, edx
cmp ecx, edx
cmovl ecx, edx
mov [esp - 4], ecx
fild st0, dword [esp - 4] # current_hp = static_cast<float>(max<int32_t>(cmd->max_hp - st.total_damage, 0))
fld st0, dword [ebx + 0x0C]
fmulp st1, st0
fistp dword [esp - 4], st0
mov ecx, dword [esp - 4] # adjusted_hit_amount = static_cast<int16_t>(current_hp * cmd->factor)
xor edx, edx
inc edx
cmp ecx, edx
cmovl ecx, edx
mov [ebx + 0x04], cx # cmd->hit_amount = min<int32_t>(1, adjusted_hit_amount)
handle_6xE4_not_proportional:
movzx edx, word [eax + 0x06] # st.total_damage
movsx esi, word [ebx + 0x04] # cmd->hit_amount
movzx edi, word [ebx + 0x0A] # cmd->max_hp
add edx, esi # st.total_damage + cmd->hit_amount
cmp edx, edi
jl handle_6xE4_damage_less_than_max_hp
mov [eax + 0x06], di # st.total_damage = cmd->max_hp;
mov edx, [eax]
test edx, 0x800
jnz handle_6xE4_return_pop_ene
or edx, 0x800
mov [eax], edx
cmp dword [esp], 0
je handle_6xE4_return_pop_ene
push edx # out_cmd.flags
sub esp, 8
mov word [esp], 0x030A # out_cmd.header.{subcommand,size}
mov si, [ebx + 2]
mov [esp + 2], si # out_cmd.header.entity_id
and si, 0x0FFF
mov [esp + 4], si # out_cmd.entity_index
mov [esp + 6], di # out_cmd.total_damage
mov ecx, esp
mov edx, 0x008003E0
call edx # send_and_handle_60(&out_cmd);
add esp, 0x10
jmp handle_6xE4_return
handle_6xE4_damage_less_than_max_hp:
xor edi, edi
cmp edx, edx
cmovl edx, edi
mov [eax + 0x06], dx # st.total_damage = std::max<int16_t>(st.total_damage + cmd->hit_amount, 0);
mov edx, eax # edx = ene_st
mov eax, [esp] # eax = ene
test eax, eax
jz handle_6xE4_return_pop_ene
mov ecx, eax
push edx
mov edx, [ecx]
call [edx + 0x148] # ene->vtable[0x52](ene, &st);
handle_6xE4_return_pop_ene:
add esp, 4
handle_6xE4_return:
pop edi
pop esi
pop ebx
ret
handle_6xE4_end:
call write_address_of_code
# Write TObjectV00b441c0::incr_hp_with_sync
push 5
push 0x00774448 # TObjectV00b441c0::v18_accept_hit (presumably Resta) - this is add_hp, not subtract_hp!
push 5
push 0x00777287 # TObjectV00b441c0::subtract_hp_if_not_in_state_2
push 5
push 0x00776CD6 # TObjectV00b441c0::v19_handle_hit_special_effects
push 5
push 0x00776D4F # TObjectV00b441c0::v19_handle_hit_special_effects
push 5
push 0x00776E20 # TObjectV00b441c0::v19_handle_hit_special_effects
push 5
push 0x00776E99 # TObjectV00b441c0::v19_handle_hit_special_effects
push 5
push 0x00775F51 # TObjectV00b441c0::v19_handle_hit_special_effects
push 5
push 0x00775BE6 # TObjectV00b441c0::v19_handle_hit_special_effects
push 5
push 0x00775A60 # TObjectV00b441c0::v19_handle_hit_special_effects
push 5
push 0x00775726 # TObjectV00b441c0::v19_handle_hit_special_effects (Devil's/Demon's)
push 5
push 0x00774D7B # TObjectV00b441c0::v18_accept_hit
push 5
push 0x00774C47 # TObjectV00b441c0::v18_accept_hit
push 5
push 0x00774A14 # TObjectV00b441c0::v18_accept_hit
push 5
push 0x0077482A # TObjectV00b441c0::v18_accept_hit
push 5
push 0x007746E0 # TObjectV00b441c0::v18_accept_hit
push 5
push 0x00774061 # TObjectV00b441c0::v18_accept_hit
push 5
push 0x00773EFA # TObjectV00b441c0::v18_accept_hit
push 5
push 0x00773937 # TObjectV00b441c0::v17
push 18
call +4
.deltaof on_add_or_subtract_hp_start, on_add_or_subtract_hp_end
pop eax
push dword [eax]
call on_add_or_subtract_hp_end
on_add_or_subtract_hp_start: # (TObjectV00b441c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax
test byte [0x00AAB27C], 0x80
jz on_add_or_subtract_hp_skip_send
movzx eax, word [ecx + 0x1C] # ene->entity_id
cmp eax, 0x1000
jl on_add_or_subtract_hp_skip_send
cmp eax, 0x1B50
jge on_add_or_subtract_hp_skip_send
and eax, 0x0FFF
imul eax, eax, 0x0C
add eax, [0x00AB02B8] # eax = state_for_enemy(cmd->header.entity_id)
sub esp, 0x10
mov word [esp], 0x04E4
mov dx, [ecx + 0x1C]
mov [esp + 0x02], dx # cmd.entity_id
mov dx, [esp + 0x14]
cmp dword [esp + 0x10], 0x0077444D # Check if callsite is add_hp
jne on_add_or_subtract_hp_skip_negate_amount
neg dx
on_add_or_subtract_hp_skip_negate_amount:
mov [esp + 0x04], dx # cmd.hit_amount
mov dx, [eax + 6]
mov [esp + 0x06], dx # cmd.total_damage_before_hit
mov dx, [ecx + 0x0334]
mov [esp + 0x08], dx # cmd.current_hp
mov dx, [ecx + 0x02BC]
mov [esp + 0x0A], dx # cmd.max_hp
mov dword [esp + 0x0C], 0xBF800000 # cmd.factor
cmp dword [esp + 0x10], 0x0077572B # Check if callsite is Devil's/Demon's
jne on_add_or_subtract_hp_not_proportional
# esp is 0x18 down from where it is in caller's context
mov edx, 100
sub edx, [esp + 0x24] # edx = (100 - special_amount)
mov [esp - 4], edx
fild st0, dword [esp - 4] # current_hp_factor = static_cast<float>(100 - special_amount)
fmul st0, dword [esp + 0x50] # *= weapon_reduction_factor
mov dword [esp - 4], 0x42C80000 # 100.0f
fdiv st0, dword [esp - 4]
fstp dword [esp + 0x0C], st0 # cmd.factor = ((100 - special_amount) * weapon_reduction_factor) / 100
on_add_or_subtract_hp_not_proportional:
mov edx, esp
push ecx
push 0x10
push edx
mov ecx, [0x00AAB284]
mov edx, 0x007D3F38
call edx # send_60(root_protocol, &cmd, sizeof(cmd));
pop ecx
add esp, 0x10
on_add_or_subtract_hp_skip_send:
mov eax, 0x00777414 # subtract_hp
mov edx, 0x007773D4 # add_hp
cmp dword [esp], 0x0077444D # Check if callsite is add_hp
cmove eax, edx
jmp eax
on_add_or_subtract_hp_end:
call write_call_to_code_multi
push 5
push 0x0078781F
push 1
call +4
.deltaof on_6x0A_patch_start, on_6x0A_patch_end
pop eax
push dword [eax]
call on_6x0A_patch_end
on_6x0A_patch_start: # (TObjectV00b441c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax
test byte [0x00AAB27C], 0x80
jz on_6x0A_patch_skip_write
mov [esp + 0x0A], cx
on_6x0A_patch_skip_write:
ret
on_6x0A_patch_end:
call write_call_to_code_multi
ret