【NSMBW】上投げパッチの制作後記

こんにちは。ReaZ0nです。今回は、某チームのModに送ったコードの制作後記となります。このnoteでは、例としてPOWブロックのパッチを公開します。


アドレスとyaml

北欧版のアドレスは以下の通りです。日本版ではアドレスが違った記憶があります。
x速度:0x8089287c
y速度:0x80892880
それぞれ、速度の値をストアする命令が入っているアドレスです。

yamlはこんな感じになります。blで分岐させて、もとのアドレスに返ってくるようにしています。

  # daPowBlock_c
  - name: ThrowUpPOWSpeedX
    type: branch_insn
    branch_type: bl
    src_addr_pal: 0x8089287c
    target_func: 'ThrowUpPOWSpeedX'

  - name: ThrowUpPOWSpeedY
    type: branch_insn
    branch_type: bl
    src_addr_pal: 0x80892880
    target_func: 'ThrowUpPOWSpeedY'

x速度

x速度はプレイヤーの速度をそのまま使用しています。

.global ThrowUpPOWSpeedX # 0x8089287c
ThrowUpPOWSpeedX:
    # r24: unused, r30, r28: this ptr, r29: player ptr, r23: player->input
    mflr    r24            # maybe safe register

    mr      r3, r23
    bl      getHeldUp__14dPlayerInput_c # returns 0 (not held) or 2 (held) to r3
    cmpwi   r3, 0
    beq     L_restorePOWX

    # Set this->speed.x
    lfs     f31, 0xe8(r29) # this->speed.x = player->speed.x
    #stfs    f31, 0xf4(r30) # this->speedmax.x = player->speed.x

    # Make flag for to set speed.y
    li      r3, 0x1
    stw     r3, 0x248(sp)
    b       L_returnPOWX

L_restorePOWX:
    li      r3, 0x0        # Delete flag for to set speed.y
    stw     r3, 0x248(sp)

L_returnPOWX:
    oris    r3, r3, 0x0090 # restore r3
    stfs    f31, 0xe8(r30)

    mtlr    r24
    li      r24, 0
    blr

ストア部

以下のコードで、LRレジスタの値をr24に移動しています。

    mflr    r24

入力取得部

r23にはplayerの入力情報のメモリアドレスが入っていたので、それをr3に移動して入力を取得しています。
getHeldUp__14dPlayerInput_c(0x8005E4F0)の引数は、第一引数のplayerポインターだけなので、r4以降のレジスタに値が入っていても問題はありません。
関数が実行されたときに上入力がされていた場合、戻り値として2を返します。なので、0(他の入力)と比較して0の場合にのみrestoreに分岐させています。

    mr      r3, r23
    bl      getHeldUp__14dPlayerInput_c # returns 0 (not held) or 2 (held) to r3
    cmpwi   r3, 0
    beq     L_restorePOWX

速度保存部

r29にもplayerポインターが入っていたのでそれを使っています。
スプライトのポインター+0xe8のメモリアドレスにx速度が保存されているので、この場合はプレイヤーのx速度を取得しています。

    # Set this->speed.x
    lfs     f31, 0xe8(r29) # this->speed.x = player->speed.x

フラグ立て部

y速度でまた入力を取得するのは面倒なので、スタックポインタ(sp)もといr1+0x248のメモリアドレスにフラグを立てるようにしています。
上入力があった場合は1です。

    # Make flag for to set speed.y
    li      r3, 0x1
    stw     r3, 0x248(sp)
    b       L_returnPOWX

y速度

y速度は、置換用のデータを新たにfloat型で定義し、それをもとのデータと置換しています。

.global ThrowUpPOWSpeedY # 0x80892880
ThrowUpPOWSpeedY:
    lwz     r3, 0x248(sp)  # isFlag enable
    cmpwi   r3, 0x0
    beq     L_returnPOWY
    # Set this->speed.y
    lis     r3, ThrowUpPOWSpeedYfloat@ha
    lwz     r3, ThrowUpPOWSpeedYfloat@l(r3)
    stw     r3, 0xec(r30)  # really stupid way
    lfs     f1, 0xec(r30)
L_returnPOWY:
    oris    r3, r3, 0x0090 # restore r3
    stfs    f1, 0xec(r30)
    blr

.data
.align 4
ThrowUpPOWSpeedYfloat:
    .float 7.0    

フラグ取得部

先述したフラグを取得し分岐しています。この場合、0(上未入力)の場合に分岐ですね〜。

    lwz     r3, 0x248(sp)  # isFlag enable
    cmpwi   r3, 0x0
    beq     L_returnPOWY

置換部

コードの一番下で定義しているfloatを読み込んで置換します。
r30はthisポインタ、+0xecy速度の保存場所です。

    # Set this->speed.y
    lis     r3, ThrowUpPOWSpeedYfloat@ha
    lwz     r3, ThrowUpPOWSpeedYfloat@l(r3)
    stw     r3, 0xec(r30)  # really stupid way
    lfs     f1, 0xec(r30)

定義部

float型でY速度を定義しています。これを、上記の置換部で用いています。

.data
.align 4
ThrowUpPOWSpeedYfloat:
    .float 7.0    

迫真完成部

完成したコードはこちらです。

.text
.align 4

#ifndef __MWERKS__
.set r0,0;   .set r1,1;   .set r2,2;   .set r3,3;   .set r4,4
.set r5,5;   .set r6,6;   .set r7,7;   .set r8,8;   .set r9,9
.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
.set r30,30; .set r31,31; .set f0,0;   .set f2,2;   .set f3,3
.set f1,1;   .set f8,8;   .set f9,9;   .set f10,10; .set f11,11;
.set f30,30; .set f31,31
#endif
.set sp, 1

# Made by ReaZ0n23 Inspired in NewerGEM.
################################################################################

.extern getHeldUp__14dPlayerInput_c

################################################################################

.global ThrowUpPOWSpeedX # 0x8089287c
ThrowUpPOWSpeedX:
    # r24: unused, r30, r28: this ptr, r29: player ptr, r23: player->input
    mflr    r24            # maybe safe register

    mr      r3, r23
    bl      getHeldUp__14dPlayerInput_c # returns 0 (not held) or 2 (held) to r3
    cmpwi   r3, 0
    beq     L_restorePOWX

    # Set this->speed.x
    lfs     f31, 0xe8(r29) # this->speed.x = player->speed.x

    # Make flag for to set speed.y
    li      r3, 0x1
    stw     r3, 0x248(sp)
    b       L_returnPOWX

L_restorePOWX:
    li      r3, 0x0        # Delete flag for to set speed.y
    stw     r3, 0x248(sp)

L_returnPOWX:
    oris    r3, r3, 0x0090 # restore r3
    stfs    f31, 0xe8(r30)

    mtlr    r24
    li      r24, 0
    blr

################################################################################

.global ThrowUpPOWSpeedY # 0x80892880
ThrowUpPOWSpeedY:
    lwz     r3, 0x248(sp)  # isFlag enable
    cmpwi   r3, 0x0
    beq     L_returnPOWY

    # Set this->speed.y
    lis     r3, ThrowUpPOWSpeedYfloat@ha
    lwz     r3, ThrowUpPOWSpeedYfloat@l(r3)
    stw     r3, 0xec(r30)  # really stupid way
    lfs     f1, 0xec(r30)

L_returnPOWY:
    oris    r3, r3, 0x0090 # restore r3
    stfs    f1, 0xec(r30)

    blr

################################################################################

.data
.align 4
ThrowUpPOWSpeedYfloat:
    .float 7.0    

じゃ

いいなと思ったら応援しよう!