Completed Modified Navigation Subaction Events

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
355
#1
This code allows [1C] “Subroutine” and [14] “Goto” subaction events to be written freely within any Player, Item, or Color subaction that is contained within a DAT file.

Normally, using Crazy Hand to insert these navigation events into a moveset subaction would require modifying the file’s relocation table. With this code installed however, file data offsets used by Subroutines and Gotos that are not already in the relocation table will become relocated on their first use.

This means that moveset strings can now reach any part of the file without even touching the relocation table.


Get the code here:
Code:
-==-

Modified Navigation Subaction Events
- [00] XXXXXX = Subroutine at file data offset X
- [01] XXXXXX = Goto file data offset X
Offset X is a literal file data offset.

No file reloaction entries are required.
File relocation entries for [14] and [1C] become optional.
[Punkline]
1.02 ----- 0x803b9840 --- 80005940 -> 804DC748
1.02 ----- 0x80276BE4 --- C842CD68 -> C84280A0
1.02 ----- 0x80276AE0 --- C842CD68 -> C84280A0
1.02 ----- 0x802769D4 --- C862CD68 -> C86280A0
1.02 ----- 0x8027686C --- C842CD68 -> C84280A0
1.02 ----- 0x80276764 --- C842CD68 -> C84280A0
1.02 ----- 0x80276654 --- C862CD68 -> C86280A0
1.02 ----- 0x80276590 --- C842CD68 -> C84280A0
1.02 ----- 0x804DC748 --- 43300000 -> Branch
81630008 800B0000 2C000000 41A20008
b <SAE_navigation_syntax>
b 0x80005940
60000000
<SAE_navigation_syntax> 1.02
7C0802A6 90010004 9421FFE0 BFA10010 7FE00026 7C7D1B78 809D0008 8004FFFC 3CA01C00 7C002800 3CA01400 7C802800 80A40000 54A6C39E 54BE023E 7CC10120 4DA23382 418D0034 40AF0020 811D000C 38080001 901D000C 39240004 5500103A 7D1D0214 91280010 88040000 60080002 99040000 41AE003C 7C832378
bl <datIdentifyEx>
2C060000 41A00010 38000000 90030000
b 0x80005940
7CBE3A14 418D0020 7CBE3214 54BEF23E 80A30000 53C5023E 90A30000 57C0103A 64058000 90BD0008 7FEFF120 BBA10010 38210020 80010004 7C0803A6 4E800020
<datIdentifyEx> All
7C0802A6 90010004 9421FFE0 BFC10010 4FFFF982 7C7E1B79 40800094 3FE08043 63FF2124 38000050 7C0903A6 A87F0008 2C03270F 40A2005C A87F0006 2C03FFFF 40810050 809F0014 2C040000 41820044 80840004 80640040 2C030000 41820034 7C1E1800 41A0002C 80A40000 7C651A14 7C1E1800 41A1001C 7FE5FB78 80C40040 7D06F050 80E40020 7D27F050 48000038 3BFF001C 401FFF98 419F0014 4FFFF842 8002CDB8 7C040379 4180FFAC 38800000 38A00000 38C00000 38E00000 39000000 39200000 7FC3F378 BBC10010 38210020 80010004 7C0803A6 4E800020
1.02 ----- 80005af8 --- 90030008 -> Branch
b <SAE_navigation_handle_vanilla_ops>
60000000 00000000
1.02 ----- 80005abc --- 90030008 -> Branch
b <SAE_navigation_handle_vanilla_ops>
60000000 00000000
<SAE_navigation_handle_vanilla_ops> All
2C000000 41A00008
b <SAE_navigation_syntax>
90030008 4E800020
<EOS_hooks> All
4E800021

b <EOS_PlCo_pointer>
# this hook is responsible for clearing the PlCo header object pointer on scene changes

# <-- additional hooks may be placed here

00000000
1.02 ----- 801a4268 --- bb21001c -> Branch
7C791B78
bl <EOS_event>
7F23CB78 BB21001C 00000000
<EOS_event> All
7C0802A6 90010004 9421EF00 BE011000 7C000026 90011080 48000019 7C0802A6 900110F0
bl <EOS_hooks>
7FE802A6 48000010 4E800021 83E110EC 3BFF0004 801F0000 2C000000 41820010 93E110EC 7FE903A6 4E800420 80011080 7C0FF120 BA011000 38211100 80010004 7C0803A6 4E800020
<EOS_continue> All
800110F0 7C0903A6 4E800420
1.02 ----- 8038033c --- 8001002c -> Branch
93C2CDBC 8001002C 00000000
1.02 ----- 80067ae8 --- 80610008 -> Branch
8062CDBC 9062CDB8 80610008 00000000
1.02 ----- 80279608 --- C822CDB8 -> C8228000
1.02 ----- 80279574 --- C842CDB8 -> C8428000
1.02 ----- 8027920C --- C822CDB8 -> C8228000
1.02 ----- 802791B4 --- C842CDB8 -> C8428000
1.02 ----- 80278F5C --- C822CDB8 -> C8228000
1.02 ----- 804DC798 --- 4330000000000000 -> 0000000000000000
<EOS_PlCo_pointer> All
38000000 9002CDB8
b <EOS_continue>
#
Code:
-==-
!
ASM - Modified Navigation Subaction Events
- [00] XXXXXX = Subroutine at file data offset X
- [01] XXXXXX = Goto file data offset X
Offset X is a literal file data offset.

No file reloaction entries are required.
File relocation entries for [14] and [1C] become optional.
[Punkline]
1.02 ----- 0x803b9840 --- 80005940 -> 804DC748
# change target callback of [00] control event pointer

1.02 ----- 0x80276BE4 --- C842CD68 -> C84280A0
1.02 ----- 0x80276AE0 --- C842CD68 -> C84280A0
1.02 ----- 0x802769D4 --- C862CD68 -> C86280A0
1.02 ----- 0x8027686C --- C842CD68 -> C84280A0
1.02 ----- 0x80276764 --- C842CD68 -> C84280A0
1.02 ----- 0x80276654 --- C862CD68 -> C86280A0
1.02 ----- 0x80276590 --- C842CD68 -> C84280A0
1.02 ----- 0x804DC748 --- 43300000 -> Branch
# mytoc 266: -0x3298(rtoc) = 804DC748
# pointer for control event [00] targets this static address

# r3 = event controller
lwz r11, 0x8(r3)
lwz r0, 0(r11)
cmpwi r0, 0
beq+ _default
# check to see if word is null

  b <SAE_navigation_syntax>
  # if word isn't null, then opcode + input qualifies for shorthand goto/subroutine syntax

_default:
b 0x80005940
# else default to vanilla termination event
nop



<SAE_navigation_syntax> 1.02
# r3 = event controller:
# handles [00] [01] [02] [03] [14] and [1C] events
# [1C] and [14] are only handled if their file offsets have not been relocated
# [00] and [01] are converted into [02] and [03] events
# [02] and [03] unpack a RAM address and then act like [1C] and [14]

# bools:
.set bVanillaSyntax, 13 # cr3
.set bRelocated,     14
.set bSetReturn,     15

mflr r0
stw  r0, 0x4(sp)
stwu sp, -0x20(sp)
stmw r29, 0x10(sp)
mfcr r31
mr r29, r3
# backup CR so that we can use saved bools
# r29 = this event controller

lwz r4, 0x8(r29)
lwz r0, -0x4(r4)
lis r5, 0x1C00
cmpw cr0, r0, r5
lis r5, 0x1400
cmpw cr1, r0, r5
# check for vanilla syntax with cr0, cr1 comparisons

lwz r5, 0x0(r4)
rlwinm r6, r5, 24, 0x30000
# align bRelocated and bSetReturn to cr3

rlwinm r30, r5, 0, 0xFFFFFF
# extract file or RAM pointer as masked input

mtcrf 0b00010000, r6
cror bVanillaSyntax, eq, eq+4
# bools have been set
# r5 = input, unmasked
# r30 = input, masked

bt- bVanillaSyntax, _relocate_file_pointer

_check_input:
bf+ bSetReturn, _update_relocation_bit

  _set_return:
  lwz r8, 0xC(r29)
  addi r0, r8, 1
  stw r0, 0xC(r29)
  # update controller stack word pointer

  addi r9, r4, 4
  slwi r0, r8, 2
  add  r8, r29, r0
  stw  r9, 0x10(r8)
  # store return pointer in controller stack

_update_relocation_bit:
# format the pointer so that it can fit into the 24-bit input

lbz r0, 0x0(r4)
ori r8, r0, 0x2
stb r8, 0x0(r4)
# bit is written to file data in RAM.
# this causes relocation behavior to only trigger once

bt+ bRelocated, _unpack_RAM_pointer
# if this input has already been relocated, we unpack the relocation address
# else, this is the first time reading this event, so we relocate the file data offset

  _relocate_file_pointer:
  mr r3, r4
  # r3 = address of this event data word

  bl <datIdentifyEx>
  # r3 = address of this event data word
  # r4 = file header object
  # r5 = alloc index element
  # r6 = file base address
  # r7 = relocation base address
  # r8 = file offset
  # r9 = relocation offset
  cmpwi r6, 0
  blt+ _commit_to_relocation
  # if given address does not belong to a recognizable file

    _bad_address:
    li r0, 0
    stw r0, 0x0(r3)
    b 0x80005940
    # then nullify word, and branch to default termination event

  _commit_to_relocation:
  add r5, r30, r7
  bt- bVanillaSyntax, _update_event_pointer
  # if this is a vanilla syntax, then we don't need to compress the pointer

  _pack_navigation_shorthand:
  add r5, r30, r6
  rlwinm r30, r5, 30, 0xFFFFFF
  lwz r5, 0x0(r3)
  rlwimi r5, r30, 0, 0xFFFFFF
  stw r5, 0x0(r3)
  # else, pack compressed RAM pointer into navigation syntax

_unpack_RAM_pointer:
slwi r0, r30, 2
oris  r5, r0, 0x8000
# <<2, and insert 0x80000000 bit

_update_event_pointer:
stw r5, 0x8(r29)
# update event pointer

_return:
mtcr r31
lmw  r29, 0x10(sp)
addi sp, sp, 0x20
lwz  r0, 0x4(sp)
mtlr r0
blr



<datIdentifyEx> All
# r3 = any address
# checks if input address is in range of any active dat file allocations
# - this variation of datIdentify checks for a PlCo exception if no match is found

# returns:
# r3 = unchanged
# r4 = file header object
# r5 = alloc index element
# r6 = file base address
# r7 = relocation base address
# r8 = file offset
# r9 = relocation offset
# addresses:
.set allocIndexAddr, 0x80432124

# dat allocation object offsets:
.set xEntrynum, 6
.set xStatus, 8
.set xHeaderObjectLink, 0x14

# header object link offsets:
.set xHeaderObject, 4

# header object offsets:
.set xFileSize, 0
.set xRelocBase, 0x20
.set xFileStart, 0x40

# mytoc offsets:
.set xPlCo, -0x3248

# bools:
.set bCheckedPlCo, 31

_code_start:
mflr r0
stw  r0, 0x4(sp)
stwu sp, -0x20(sp)
stmw r30, 0x10(sp)
crclr bCheckedPlCo
# bit 31 in cr7 holds status of exception check
# function is a leaf, so volatile cr will still be useful

mr. r30, r3                   # r30 = input query
bge- _return_null
# if given query is not an address, then return null

lis r31, allocIndexAddr @h
ori r31, r31, allocIndexAddr @l  # r31 = loop index address
li r0, 80      # for each of 80 allocation slots...
mtctr r0
# else, setup CTR loop for parsing dat allocation index for header objects

_loop:
  lha r3, xStatus(r31)
  cmpwi r3, 9999
  bne+ _iter_loop
  # if alloc status == 9999

    lha r3, xEntrynum(r31)
    cmpwi r3, -1
    ble- _iter_loop
    # and entrynum is valid

    _get_header_object:
    lwz r4, xHeaderObjectLink(r31)
    cmpwi r4, 0
    beq- _iter_loop

    lwz r4, xHeaderObject(r4)
    # r4 = header object

    _header_object_in_r4:
    lwz r3, xFileStart(r4)
    cmpwi r3, 0
    beq- _iter_loop
    # and header object isn't null

    cmpw r30, r3
    blt+ _iter_loop
    # and query > low limit

      lwz r5, xFileSize(r4)
      add r3, r5, r3
      cmpw r30, r3
      bgt+ _iter_loop
      # and query < high limit:
      # then we have a matching header object.

        _match:
        mr  r5, r31
        lwz r6, xFileStart(r4)
        sub r8, r30, r6
        lwz r7, xRelocBase(r4)
        sub r9, r30, r7
        b _return
        # r4 = file header object
        # r5 = alloc index element
        # r6 = file base address
        # r7 = relocation base address
        # r8 = file offset
        # r9 = relocation offset

      _iter_loop:
      addi r31, r31, 0x1C
      bdnzf+ bCheckedPlCo, _loop
      # else if decremented CTR > 0 AND bCheckedPlCo is false, then iterate loop
      # else no match was found in allocation index.

_no_match:
bt- bCheckedPlCo, _return_null
# if PlCo exception has not been checked:

  _PlCo_exception:
  crnot bCheckedPlCo, bCheckedPlCo
  # invert bit, so check is only made once
  # this also disables the CTR iteration in loop

  lwz r0, xPlCo(rtoc)
  mr. r4, r0
  blt+ _header_object_in_r4
  # if PlCo header object pointer exists, use it for final check before giving up on query

_return_null:
li r4,0
li r5,0
li r6,0
li r7,0
li r8,0
li r9,0
# any returned value aside from r3 can be checked for null

_return:
mr r3, r30              # r3 = (unchanged query)
lmw  r30, 0x10(sp)
addi sp, sp, 0x20
lwz r0, 0x4(sp)
mtlr r0
blr



1.02 ----- 80005af8 --- 90030008 -> Branch
b <SAE_navigation_handle_vanilla_ops>
nop
.long 0  # 1C injection

1.02 ----- 80005abc --- 90030008 -> Branch
b <SAE_navigation_handle_vanilla_ops>
nop
.long 0  # 14 injection


<SAE_navigation_handle_vanilla_ops> All
cmpwi r0, 0
blt+ _default
# if file data offset has already been relocated,
# then use default behavior.

  b <SAE_navigation_syntax>
  # else, we are going to branch to navigation syntax
  # -- this is a hard branch, so function blr returns from default, which is a leaf

_default:
stw    r0, 0x0008 (r3)
blr



<EOS_hooks> All
4E800021

b <EOS_PlCo_pointer>
# this hook is responsible for clearing the PlCo header object pointer on scene changes

# <-- additional hooks may be placed here

00000000
1.02 ----- 801a4268 --- bb21001c -> Branch
7C791B78
bl <EOS_event>
7F23CB78 BB21001C 00000000
<EOS_event> All
7C0802A6 90010004 9421EF00 BE011000 7C000026 90011080 48000019 7C0802A6 900110F0
bl <EOS_hooks>
7FE802A6 48000010 4E800021 83E110EC 3BFF0004 801F0000 2C000000 41820010 93E110EC 7FE903A6 4E800420 80011080 7C0FF120 BA011000 38211100 80010004 7C0803A6 4E800020
<EOS_continue> All
800110F0 7C0903A6 4E800420
1.02 ----- 8038033c --- 8001002c -> Branch
93C2CDBC 8001002C 00000000
1.02 ----- 80067ae8 --- 80610008 -> Branch
8062CDBC 9062CDB8 80610008 00000000
1.02 ----- 80279608 --- C822CDB8 -> C8228000
1.02 ----- 80279574 --- C842CDB8 -> C8428000
1.02 ----- 8027920C --- C822CDB8 -> C8228000
1.02 ----- 802791B4 --- C842CDB8 -> C8428000
1.02 ----- 80278F5C --- C822CDB8 -> C8228000
1.02 ----- 804DC798 --- 4330000000000000 -> 0000000000000000
<EOS_PlCo_pointer> All
38000000 9002CDB8
b <EOS_continue>
#




To give yourself more room for writing new subaction events, open a character file in a hex editor, and add bytes to the end of it. When you have all the bytes you need, write the number of bytes of the new file size into the first 32 bits of the file header:



Then, the bytes you’ve added may be accessed using any of the following opcodes in Crazy Hand:

[1C] = “Subroutine” goes to a new file data offset.
[14] = “GoTo” goes to a new file data offset, and memorizes where it came from.
- only 5 return addresses may be memorized without overflowing the memory stack.

Note that the vanilla syntax uses a file data offset -0x20 for its input:



Also included is a new shorthand navigation syntax that can be used to interpret literal file data offsets as though they were opcodes:

[00] = Subroutine shorthand (not relocated)
[01] = GoTo shorthand (not relocated)



On first use, [00] and [01] events relocate their given file data offset and record the resulting RAM address as one of the following:

[02] = Subroutine shorthand (absolute RAM address)
[03] = Goto shorthand (absolute RAM address)



Though they are intended to be written at run-time; these [02] and [03] events may still be written out in Crazy Hand as a way of reaching static RAM addresses, if desired.

Addresses are packed into 23-bits by shifting right by >>2 and ANDing by 0x007FFFFF.
The opcode may then be ORed onto the shifted address.

The example address used in the above screenshot points to mytoc slot 1, which might be useful for the sake of creating programmable destinations.

---

Edit: because of the fact that these new shorthand syntaxes are only 4 bytes in length, they can also be used to override vanilla navigation events without requiring any modifications to the original relocation offset.

I’ll be including this code in a much broader patch for the subaction event system sometime soon. Let me know if anyone finds any bugs, has any questions, or any suggestions.

The Cape The Cape Itaru Itaru UnclePunch UnclePunch DRGN DRGN Yakult Yakult TDRR TDRR
 
Last edited:

TDRR

Smash Journeyman
Joined
Sep 18, 2017
Messages
237
Location
Venezuela
#2
Amazing work, Punkline! So this is basically the giant subactions in the DOL thing, but we can keep everything in the .DAT file this time around, right?

Assuming i understood everything correctly, i just need to write a subaction as i would normally do, put it at the end of the .DAT file and use opcode 1C to go there, and to get the correct offset i need to substract 20 from the starting offset from that subaction, am i correct?
 

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
355
#3
Amazing work, Punkline! So this is basically the giant subactions in the DOL thing, but we can keep everything in the .DAT file this time around, right?

Assuming i understood everything correctly, i just need to write a subaction as i would normally do, put it at the end of the .DAT file and use opcode 1C to go there, and to get the correct offset i need to substract 20 from the starting offset from that subaction, am i correct?
That's right! Just be sure to remember that the new file size must be also be written to the file header.

There's also a 4-byte shorthand syntax included with the code that can be used to reference file offsets directly (without subtracting 0x20). To get the same effect as a 1C event, you can use a "00" event to type in the literal file offset as a single line.

This works because all events are strictly 32-bit; so a null terminator written in all moveset data always has 32 null bits. This code makes it so that if a "00" opcode is detected but the whole word isn't null, then it becomes a shortened 1C syntax. "01" can also be used for a shortened 14 syntax.
 
Last edited:

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
355
#5
I forgot to include an important note in the op about how the shorthand syntax can be used to override existing 1C and 14 events.

Normally, if a 1C or 14 event already exists in a subaction, changing the input would require you to fiddle with the relocation table again. Because of the fact that these events are 8 bytes long however, only the second half of the syntax is relocated. So, the first half can be overwritten with the shorter 00 and 01 syntaxes that are included with the code.

This makes it possible to navigate around problematic relocation offsets that already exist in a subaction, like DK’s appeal:

 

***Justice***

Smash Journeyman
Joined
Dec 10, 2014
Messages
442
Location
Middle of Nowhere
#6
would i be able to get your assistance? im a massive noob but want to do a friend a favour and have Ganondorf SideB and air side b put him in the catch state when he hits an enemy instead of normally attacking. its kinda like a busted wizard choke for melee LOOL
 

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
355
#7
***Justice*** ***Justice*** - Here’s a code that you can install to make ganondorf’s side-b hitboxes catch like a grab. While it’s possible to trigger the catch effect from grab hitboxes by using Achilles’ character data modification code; it’s not possible to control the timing, so a custom callback code is required for practical implementation.

This code creates an event string that can be used to plug the callbacks necessary to handle grab hitboxes into any character from Crazy Hand like a recallable macro. It can be reached universally using the [03] op included with the custom navigation subaction event code.

It requires the latest version of MCM, which is 4.1 as of 12/12/2018. It also requires that you have the navigation and character data modification events installed, as prerequisites.


Catch Subaction Event Macro
Code:
    -==-


Catch Subaction Event Macro
Input 03136992 in crazyhand following a grab hitbox.
- requires navigation and character data modification events.
[Punkline]
Revision ---- DOL Offset ---- Hex to Replace ---------- ASM Code -
NTSC 1.02 --- 0x8018A320 ---- C842AC68 -> C8428000
------------- 0x8018A2D0 ---- C842AC68 -> C8428000
------------- 0x8018A1E4 ---- C842AC68 -> C8428000
------------- 0x8018A194 ---- C842AC68 -> C8428000
# rtoc - 0x5398 == 804DA648 = mytoc 167: 8 free bytes



------------- 0x804DA648 ---- 43300000 -> 1C000000
------------- 0x804DA64C ---- 00000000 -> .long <<catch_playerSAE_data>>
# 804DA6A8 = "catch" subroutine, for subaction event pointer


<catch_playerSAE_data> NTSC 1.02
.long 0x88000000, 0x00000000, 0x00000000

.long 0xF8FF002C
# start of character data modification string:

.long 0x0202221C, 0x00000200 # flag for catching state
.long 0x01001A68, 0x00000001 # hword indicates catching state

.long 0x02002190
.long <<catch_playerSAE_callback>> # point to custom grabber callback

.long 0x02002194, 0x800D8BFC # point to custom grabbee callback
.long 0x02002198, 0x800DAADC # point to unknown grab callback
# character data modifications allow for grab hitboxes to trigger

.long 0x18000000
# return to caller
<catch_playerSAE_callback> NTSC 1.02
7C0802A6 9421FFF0 90010014 9061000C
bl 0x800d9ce8
8061000C 8083002C 88A42210 60A00010 98042210 80010014 38210010 7C0803A6 4E800020
#
Code:
    -==-


ASM - Catch Subaction Event Macro
Input 03136992 in crazyhand following a grab hitbox.
- requires navigation and character data modification events.
[Punkline]
Revision ---- DOL Offset ---- Hex to Replace ---------- ASM Code -
NTSC 1.02 --- 0x8018A320 ---- C842AC68 -> C8428000
------------- 0x8018A2D0 ---- C842AC68 -> C8428000
------------- 0x8018A1E4 ---- C842AC68 -> C8428000
------------- 0x8018A194 ---- C842AC68 -> C8428000
# rtoc - 0x5398 == 804DA648 = mytoc 167: 8 free bytes



------------- 0x804DA648 ---- 43300000 -> 1C000000
------------- 0x804DA64C ---- 00000000 -> .long <<catch_playerSAE_data>>
# 804DA6A8 = "catch" subroutine, for subaction event pointer


<catch_playerSAE_data> NTSC 1.02
.long 0x88000000, 0x00000000, 0x00000000

.long 0xF8FF002C
# start of character data modification string:

.long 0x0202221C, 0x00000200 # flag for catching state
.long 0x01001A68, 0x00000001 # hword indicates catching state

.long 0x02002190
.long <<catch_playerSAE_callback>> # point to custom grabber callback

.long 0x02002194, 0x800D8BFC # point to custom grabbee callback
.long 0x02002198, 0x800DAADC # point to unknown grab callback
# character data modifications allow for grab hitboxes to trigger

.long 0x18000000
# return to caller


<catch_playerSAE_callback> NTSC 1.02
mflr r0
stwu sp, -0x10(sp)
stw  r0, 0x14(sp)
stw  r3, 0xC(sp)

bl 0x800d9ce8
# normal grabber callback

lwz r3, 0xC(sp)
lwz r4, 0x2C(r3)
lbz r5, 0x2210(r4)
ori r0, r5, 0x10
stb r0, 0x2210(r4)
# update flag for catching instantly

lwz  r0, 0x14(sp)
addi sp, sp, 0x10
mtlr r0
blr

Note, you may have to hit the install button twice when installing this code.

Once installed it should work for all characters. To apply it, use Crazy Hand to change a hitbox into a grab hitbox, and then write the line “03136992” at any point before the hitboxes have been initialized.

You can apply this to Ganondorf like so:

 
Last edited:

Dodoshian

Smash Rookie
Joined
Jul 7, 2016
Messages
20
Location
Mobile, Alabama
#8
This is really cool! How do I put it into my iso with MCM? Why is the DOL mod so strange looking? It is formatted different than any of the other DOL mods I've seen. What is that about? It looks like assembler code. Can Melee Code Manager read assembler code?
 
Last edited:

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
355
#9
This is really cool! How do I put it into my iso with MCM? Why is the DOL mod so strange looking? It is formatted different than any of the other DOL mods I've seen. What is that about? It looks like assembler code. Can Melee Code Manager read assembler code?
You can install this like any other MCM code by pasting it into a text file inside of your mods library folder. It will show up in the codes list after launching the program, or by rescanning the mods library. It can then be installed to an ISO or DOL at your discretion by selecting it and saving your selections.


MCM can actually read both machine code in hex form (see the “DOL Mod”) and raw assembly form (see the “ASM”). ASM used to be slower to parse, but has been made much faster in recent versions of MCM; so they are both viable for installation purposes. The ASM format is particularly useful for developing/modifying the code, while the DOL Mod is usually more convenient for distributing it. In some cases, the ASM format can also make it easier to define data through named symbols, with support for strings and floating point data formats.


As to why this DOL Mod looks different: when represented in hex form, whitespace can be omitted so that it all appears on 1 line for easy copying and pasting. MCM also supports a series of special syntaxes that allow developers to define and reference their own named functions in a way that is reusable; recycling code. It allows developers to create abstract systems that can dramatically lower the amount of space required, and makes it easy for other codes (or multiple parts of one big code) to have access to a designed function interface.

These special syntaxes usually require a new line to be parsed properly, so the result is usually strings of hex sprinkled with placeholders on new lines. When installed, MCM eats all the placeholder lines and fills in the blanks with hex using information available only at the time that the codes are being assigned to available regions within the DOL. It's all very handy.
 

Dodoshian

Smash Rookie
Joined
Jul 7, 2016
Messages
20
Location
Mobile, Alabama
#10
You can install this like any other MCM code by pasting it into a text file inside of your mods library folder. It will show up in the codes list after launching the program, or by rescanning the mods library. It can then be installed to an ISO or DOL at your discretion by selecting it and saving your selections.


MCM can actually read both machine code in hex form (see the “DOL Mod”) and raw assembly form (see the “ASM”). ASM used to be slower to parse, but has been made much faster in recent versions of MCM; so they are both viable for installation purposes. The ASM format is particularly useful for developing/modifying the code, while the DOL Mod is usually more convenient for distributing it. In some cases, the ASM format can also make it easier to define data through named symbols, with support for strings and floating point data formats.


As to why this DOL Mod looks different: when represented in hex form, whitespace can be omitted so that it all appears on 1 line for easy copying and pasting. MCM also supports a series of special syntaxes that allow developers to define and reference their own named functions in a way that is reusable; recycling code. It allows developers to create abstract systems that can dramatically lower the amount of space required, and makes it easy for other codes (or multiple parts of one big code) to have access to a designed function interface.

These special syntaxes usually require a new line to be parsed properly, so the result is usually strings of hex sprinkled with placeholders on new lines. When installed, MCM eats all the placeholder lines and fills in the blanks with hex using information available only at the time that the codes are being assigned to available regions within the DOL. It's all very handy.
Okay, that is very informative. Thank you. As a side note, do you know how I would go about using your code to give attacks to characters that do not have them. Like the angled ftilts of link or Ganon's second jab? And some characters have unused mid-high and mid-low angled ftilt data as well. What about giving characters rapid jabs? Would this be possible with your code if I just make more space in their character files?
 
Last edited:

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
355
#11
Okay, that is very informative. Thank you. As a side note, do you know how I would go about using your code to give attacks to characters that do not have them. Like the angled ftilts of link or Ganon's second jab? And some characters have unused mid-high and mid-low angled ftilt data as well. What about giving characters rapid jabs? Would this be possible with your code if I just make more space in their character files?
I don’t think so, since this syntax works relative to an action that’s already been initiated.

I did find something in Marth’s file data though while looking for a way around this. The forward-up-tilt subaction is number 0x35 in the full subaction list in Crazy Hand, and is missing for Marth. By looking at the file data offset of the end of subaction 0x34, we can find the place where his subaction 0x35 string WOULD be at offset 0x4C7C.

The relocation offsets use file data offsets -0x20, so by searching the file for the hex “0x4C5C” we can find where that region is defined as a file data pointer:



A 24-byte element in an array that seems to map subaction event strings with (something else) keeps a blank record of Marth’s unused forward-up-tilt. I don’t have any idea how to make this work properly, but you could probably change the file data pointer “0x00004C5C” to a section at the end of the file to give it a region of space that can read custom subaction events.

Getting it to trigger correctly might require you to figure out how to map whatever it is that’s missing in that blank element, though. That might also require modifying the relocation table, if those other values are file data offsets (which they seem to be).
 

***Justice***

Smash Journeyman
Joined
Dec 10, 2014
Messages
442
Location
Middle of Nowhere
#12
***Justice*** ***Justice*** - Here’s a code that you can install to make ganondorf’s side-b hitboxes catch like a grab. While it’s possible to trigger the catch effect from grab hitboxes by using Achilles’ character data modification code; it’s not possible to control the timing, so a custom callback code is required for practical implementation.

This code creates an event string that can be used to plug the callbacks necessary to handle grab hitboxes into any character from Crazy Hand like a recallable macro. It can be reached universally using the [03] op included with the custom navigation subaction event code.

It requires the latest version of MCM, which is 4.1 as of 12/12/2018. It also requires that you have the navigation and character data modification events installed, as prerequisites.


Catch Subaction Event Macro
Code:
    -==-


Catch Subaction Event Macro
Input 03136992 in crazyhand following a grab hitbox.
- requires navigation and character data modification events.
[Punkline]
Revision ---- DOL Offset ---- Hex to Replace ---------- ASM Code -
NTSC 1.02 --- 0x8018A320 ---- C842AC68 -> C8428000
------------- 0x8018A2D0 ---- C842AC68 -> C8428000
------------- 0x8018A1E4 ---- C842AC68 -> C8428000
------------- 0x8018A194 ---- C842AC68 -> C8428000
# rtoc - 0x5398 == 804DA648 = mytoc 167: 8 free bytes



------------- 0x804DA648 ---- 43300000 -> 1C000000
------------- 0x804DA64C ---- 00000000 -> .long <<catch_playerSAE_data>>
# 804DA6A8 = "catch" subroutine, for subaction event pointer


<catch_playerSAE_data> NTSC 1.02
.long 0x88000000, 0x00000000, 0x00000000

.long 0xF8FF002C
# start of character data modification string:

.long 0x0202221C, 0x00000200 # flag for catching state
.long 0x01001A68, 0x00000001 # hword indicates catching state

.long 0x02002190
.long <<catch_playerSAE_callback>> # point to custom grabber callback

.long 0x02002194, 0x800D8BFC # point to custom grabbee callback
.long 0x02002198, 0x800DAADC # point to unknown grab callback
# character data modifications allow for grab hitboxes to trigger

.long 0x18000000
# return to caller
<catch_playerSAE_callback> NTSC 1.02
7C0802A6 9421FFF0 90010014 9061000C
bl 0x800d9ce8
8061000C 8083002C 88A42210 60A00010 98042210 80010014 38210010 7C0803A6 4E800020
#
Code:
    -==-


ASM - Catch Subaction Event Macro
Input 03136992 in crazyhand following a grab hitbox.
- requires navigation and character data modification events.
[Punkline]
Revision ---- DOL Offset ---- Hex to Replace ---------- ASM Code -
NTSC 1.02 --- 0x8018A320 ---- C842AC68 -> C8428000
------------- 0x8018A2D0 ---- C842AC68 -> C8428000
------------- 0x8018A1E4 ---- C842AC68 -> C8428000
------------- 0x8018A194 ---- C842AC68 -> C8428000
# rtoc - 0x5398 == 804DA648 = mytoc 167: 8 free bytes



------------- 0x804DA648 ---- 43300000 -> 1C000000
------------- 0x804DA64C ---- 00000000 -> .long <<catch_playerSAE_data>>
# 804DA6A8 = "catch" subroutine, for subaction event pointer


<catch_playerSAE_data> NTSC 1.02
.long 0x88000000, 0x00000000, 0x00000000

.long 0xF8FF002C
# start of character data modification string:

.long 0x0202221C, 0x00000200 # flag for catching state
.long 0x01001A68, 0x00000001 # hword indicates catching state

.long 0x02002190
.long <<catch_playerSAE_callback>> # point to custom grabber callback

.long 0x02002194, 0x800D8BFC # point to custom grabbee callback
.long 0x02002198, 0x800DAADC # point to unknown grab callback
# character data modifications allow for grab hitboxes to trigger

.long 0x18000000
# return to caller


<catch_playerSAE_callback> NTSC 1.02
mflr r0
stwu sp, -0x10(sp)
stw  r0, 0x14(sp)
stw  r3, 0xC(sp)

bl 0x800d9ce8
# normal grabber callback

lwz r3, 0xC(sp)
lwz r4, 0x2C(r3)
lbz r5, 0x2210(r4)
ori r0, r5, 0x10
stb r0, 0x2210(r4)
# update flag for catching instantly

lwz  r0, 0x14(sp)
addi sp, sp, 0x10
mtlr r0
blr

Note, you may have to hit the install button twice when installing this code.

Once installed it should work for all characters. To apply it, use Crazy Hand to change a hitbox into a grab hitbox, and then write the line “03136992” at any point before the hitboxes have been initialized.

You can apply this to Ganondorf like so:



it took me a while, but i FINALLY did it. Thank you!
 

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
355
#14
***Justice*** ***Justice*** - In general, other codes shouldn't cause an issue unless they're directly in conflict with it. It was also designed so that if it failed for any reason (like if the code were uninstalled) then the vanilla interpretation of custom lines would end up being read like a termination line.

Also, once you change the "autocancel" line like in that screenshot and save the file, Crazy Hand won't recognize the opcode anymore -- so it will probably say unknown. It just means it's not longer an autocancel, and so long as the value you typed in is still there, it will work as intended.

If it seems like the action is being cut off at the point where you put the [03] line -- the code might just need to be re-installed, because that would indicate that the terminator failsafe is working.

---


If that's not it, then you can upload the DOL (not the ISO), tell me what other codes you're using, and I'll try to look into.
 
Top