Jump to content
NHL'94 Forums

Recommended Posts

Posted (edited)

How to: Fixing the "Handedness" in the Face-Off Insets

It's always annoyed me how during a face-off, the inset displays the player on the right (bottom) with the wrong hand. The errors seem to be there from the original, up to and including '94 for SNES.

I've played with the code, and can reverse the handedness etc, but can't figure out how to affect the player on the right only. In fact, I can't see any evidence that the flag for the bottom team is even being read in the source code (below). If anyone had any suggestions as to how to handle this (other than a Psychiatrist), I would greatly appreciate it.

EDIT: Solution below.

cheers,

-Adam
 



NHL Hockey (92)

Code to Modify

Original Logic to Set Handedness for Face-Off Graphics @
0x63CC

4A2B 0074 6600 0004 5640

Revised
In this code I've specified that the patch will be at 0x0007FEDC, but you can change this to wherever you have space.

4EF9 0007 FEDC 4E71 4E71


New Code to Insert

Insert this code wherever you specified above.
0x0007FEDC

082B 0007 0062 6700 000E 4A2B 0074 6600 000E 6000 000C 4A2B 0074 6600 0004 5640 4EF9 0000 63D6

 


 

NHL 94

Code to Modify

Original Logic to Set Handedness for Face-Off Graphics @
0x63CC

4A2B 0074 6600 0004 5640

Revised
In this code I've specified that the patch will be at 0x001FFEA0, but you can change this to wherever you have space.

4EF9 001F FEA0 4E71 4E71


New Code to Insert

Insert this code wherever you specified above.
0x001FFEA0

082B 0007 0062 6700 000E 4A2B 0076 6600 000E 6000 000C 4A2B 0076 6600 0004 5640 4EF9 0000 63D6

 


 

If you want to understand how this works, check out this post.

 

Edited by AdamCatalyst
Including Solution
Posted (edited)

LOL, @AdamCatalyst, diving into source code assembly and the listing file? You're leveling up fast! I wouldn't be surprised if you're rewriting this entire game next.

Just to clarify, this is what I am seeing when I test with Montreal (Home), LA (Away) 1st period.

  • 1st image is Muller (Lefty) Home team (Bottom).
  • 2nd image is Bellows (Righty) Home team (Bottom).
  • 3rd image is Gretzky (Lefty) Away Team (Top)
  • 4th image is Carson (Righty) Away Team (Top)

Your saying the stance is wrong?

  • When your a lefty like muller in image 1, it should actually be the 2nd image? where your left hand is on the lower portion of the stick.
  • You can't find the code that controls this?


image.pngimage.pngimage.pngimage.png

Edited by McMarkis
Posted (edited)

YES. Exactly. I mean, I can find the code to swap it back and forth, or ignore handedness, etc. but I can't figure out how to *only* flip the bottom player in the face-offset. I keep thinking that I could branch out and check the bottom team flag, but that's a bit beyond me. But perhaps there is a simpler solution I am not thinking of, such as… I dunno, swapping the second bit in the array? LOL. Is that a thing? Is that just nonsense? I am clearly NOT a programmer.

Edited by AdamCatalyst
Posted

OK, this seems to work in '92. Please let me know if I'm committing any errors, omission, or sins against programming.

 

Code redirect

1. Original Logic to Set Handedness for Face-Off Graphics

0x63CC

4A2B 0074 6600 0004 5640

Revised

4EF9 0007 FEDC 4E71 4E71

 

Code

2. Test if BOTTOM

082B 0007 0062

 

3. IF BOTTOM jump ahead to #7

6700 000E

 

4. Test HAND = RIGHT

4A2B 0074

 

5. If NOT RIGHT (T), jump ahead to #9

6600 000E

 

6. ELSE go to #10

6000 000C


7. Test HAND = RIGHT

4A2B 0074


8. If LEFT (B), jump to #10

6600 0004


9. Add 3, d0

5640


10. Go Back to continue where we left off 

4EF9 0000 63D6


 

Posted (edited)

I believe @chaos dreams in m68k assembly now, so I would defer to him about assembly sins 😁. Below are a few of my thoughts.
I converted you HEX values to assembly code, and made the smallest of changes for the branching.

I personally like JSR.L so i can just do RTS commands to return back to the original code. I haven't tested this, but your pattern seems good.

  1. Hack-jack existing code
  2. Jump to new code and NOP extra instructions
  3. Perform New code and return on exit.
;Hijack Old code and call to new code
    JSR.L   $0007FEDC           ; Call new subroutine (long)
    NOP                  	; No operation
    NOP                  	; No operation
    
;Start of Your new subroutine @7FEDC    
    BTST.B  #7,$0062(A3)        ; Test bit 7 (bottom)
    BEQ.S   .bottom             ; If bottom, branch (short)
    
    TST.B   $0074(A3)           ; Test if hand = RIGHT
    BEQ.S   .exit               ; If RIGHT, exit (short)
    BRA.S   .add3               ; Not RIGHT, do add3 (short)

.bottom:
    TST.B   $0074(A3)           ; Test if hand = RIGHT
    BNE.S   .exit               ; If LEFT, exit (short)

.add3:
    ADDQ.W  #3,D0               ; Add 3 to D0

.exit:
    RTS                         ; Return from subroutine    

AI Suggestions:

My gut was telling me that you can probably simplify the multiple BTST & TST scenarios with some combo statement. So I asked Claude AI to help, and it suggested the following.

Break down the problem into a matrix like (Truth) table to help understand the possible combinations.

  • You want to add 3 when the player is Left handed and top position?
  • You want to add 3 when the player is Right handed and bottom position?
Position(bit7) Hand      EOR Result    BTST #7   Add 3?
TOP(0)         RIGHT(0)     0            0        No
TOP(0)         LEFT(1)      1            1        Yes    <-- Add 3
BOTTOM(1)      RIGHT(0)     1            1        Yes    <-- Add 3
BOTTOM(1)      LEFT(1)      0            0        No

Something like this now possibly, I haven't tested this code.

JSR.L   $0007FEDC           ; Call subroutine (long)
    NOP                         ; Padding/placeholder
    NOP                         ; Padding/placeholder

;Start of Your new subroutine @7FEDC    
    MOVE.W  D1,-(SP)            ; Save original D1 value since we are overwriting it
    MOVE.B  $0074(A3),D1        ; Get hand orientation
    EOR.B   $0062(A3),D1        ; XOR with position
    BTST    #7,D1               ; Test result
    BNE.S   .add3              ; If NOT equal, add3
    BRA.S   .exit              ; Otherwise exit

.add3:
    ADDQ.W  #3,D0               ; Add 3 to D0

.exit:
    MOVE.W  (SP)+,D1            ; Restore D1
    RTS

I know this is a bit of a brain dump—I went full over-explainer mode here. If anything’s unclear, just holler, and I’ll happily clarify. Honestly, though, I’m being a bit selfish because it’d be amazing to rope in another brave soul into the wonderful, weird world of assembly. Welcome to the dark side—we have opcodes!

Edited by McMarkis
  • Thanks 1
  • Haha 1
Posted

Oh wow, yes, will need some time to digest. And I seriously have to remember that AI exists. One side note, I originally tried a JSR command, but it caused visual flickering, for reasons that I wasn't table to discern. My brain is exhausted for the day, will definitely look this over at breakfast tomorrow!

Posted
1 hour ago, McMarkis said:

I believe @chaos dreams in m68k assembly now, so I would defer to him about assembly sins 😁. Below are a few of my thoughts.
I converted you HEX values to assembly code, and made the smallest of changes for the branching.

I personally like JSR.L so i can just do RTS commands to return back to the original code. I haven't tested this, but your pattern seems good.

  1. Hack-jack existing code
  2. Jump to new code and NOP extra instructions
  3. Perform New code and return on exit.
;Hijack Old code and call to new code
    JSR.L   $0007FEDC           ; Call new subroutine (long)
    NOP                  	; No operation
    NOP                  	; No operation
    
;Start of Your new subroutine @7FEDC    
    BTST.B  #7,$0062(A3)        ; Test bit 7 (bottom)
    BEQ.S   .bottom             ; If bottom, branch (short)
    
    TST.B   $0074(A3)           ; Test if hand = RIGHT
    BEQ.S   .exit               ; If RIGHT, exit (short)
    BRA.S   .add3               ; Not RIGHT, do add3 (short)

.bottom:
    TST.B   $0074(A3)           ; Test if hand = RIGHT
    BNE.S   .exit               ; If LEFT, exit (short)

.add3:
    ADDQ.W  #3,D0               ; Add 3 to D0

.exit:
    RTS                         ; Return from subroutine    

AI Suggestions:

My gut was telling me that you can probably simplify the multiple BTST & TST scenarios with some combo statement. So I asked Claude AI to help, and it suggested the following.

Break down the problem into a matrix like (Truth) table to help understand the possible combinations.

  • You want to add 3 when the player is Left handed and top position?
  • You want to add 3 when the player is Right handed and bottom position?
Position(bit7) Hand      EOR Result    BTST #7   Add 3?
TOP(0)         RIGHT(0)     0            0        No
TOP(0)         LEFT(1)      1            1        Yes    <-- Add 3
BOTTOM(1)      RIGHT(0)     1            1        Yes    <-- Add 3
BOTTOM(1)      LEFT(1)      0            0        No

Something like this now possibly, I haven't tested this code.

JSR.L   $0007FEDC           ; Call subroutine (long)
    NOP                         ; Padding/placeholder
    NOP                         ; Padding/placeholder

;Start of Your new subroutine @7FEDC    
    MOVE.W  D1,-(SP)            ; Save original D1 value since we are overwriting it
    MOVE.B  $0074(A3),D1        ; Get hand orientation
    EOR.B   $0062(A3),D1        ; XOR with position
    BTST    #7,D1               ; Test result
    BNE.S   .add3              ; If NOT equal, add3
    BRA.S   .exit              ; Otherwise exit

.add3:
    ADDQ.W  #3,D0               ; Add 3 to D0

.exit:
    MOVE.W  (SP)+,D1            ; Restore D1
    RTS

I know this is a bit of a brain dump—I went full over-explainer mode here. If anything’s unclear, just holler, and I’ll happily clarify. Honestly, though, I’m being a bit selfish because it’d be amazing to rope in another brave soul into the wonderful, weird world of assembly. Welcome to the dark side—we have opcodes!

The hand byte is $0076 in 94 FYI. ($74 is Fight)

Not sure if this would work. The hand orientation is just one bit, and the flag for which net they are shooting on is bit 7 of 62. So when you EOR, it would be comparing bit 0 of 62 offset, which is the deceleration bit. You would have to do an LSL.B #7, D1 before the EOR to line up the bits.

I feel like there could be an easier way to do this, but this should work, and who cares, we aren't crammed for space.

CB8C is the ROM location in 94 for the code where you want to inject (tst.b($76(a3))

  • Thanks 1
Posted

My inefficient method seems to work fine in '92 & '94 (I did note the difference in the hand byte, etc), but going to experiment with all this stuff while I watch the Leafs game tonight. Thanks guys!

Posted (edited)

@McMarkis I tried your revised code, and for some reason it didn't work. It's ENTIRELY possible that I am misunderstanding or implementing it wrong. To that end, a few questions.

Here is my current working patch in '94:

082B 0007 0062 6700 000E 4A2B 0076 6600 000E 6000 000C 4A2B 0076 6600 0004 5640 4EF9 0000 CB96

I adapted your instructions to this:

082B 0007 0062 6712 4A2B 0076 670C 6008 4A2B 0076 6604 5640 4EF9 0000 CB96

For whatever reason, whenever I change to use the JSR.L, I get flickering graphics for the left player in the face-off inset. Odd. Hence the change at the end. As for the rest, I had a few questions…

1. Why 6712 @ 0x06? Wouldn't that make the bottom face-off always use the same graphic, regardless of hand?

2. Why 670C @ 0x0C? My original logic was to use 66, but this reverses the logic of the branch, and jumps two bytes ahead?

3. Why 6604 @ 0x0E? My original logic jumped to the end, but this instead jumps to add #3 to d0 first, or am I misunderstanding something? Or lots of things…

I tried a few variants, and couldn't get the desired behaviour. Not sure what I'm missing.

As for the AI generated code, I couldn't get it to work, and it might be too far over my head to even ask questions about. I've never used Claude.AI before. I assume it is what you would recommend for this? 

In any case, my bloated code seems to work fine, but I am definitely curious to learn how to write this optimally!

 

Edited by AdamCatalyst
Posted
2 hours ago, AdamCatalyst said:

@McMarkis I tried your revised code, and for some reason it didn't work. It's ENTIRELY possible that I am misunderstanding or implementing it wrong. To that end, a few questions.

Here is my current working patch in '94:

082B 0007 0062 6700 000E 4A2B 0076 6600 000E 6000 000C 4A2B 0076 6600 0004 5640 4EF9 0000 CB96

I adapted your instructions to this:

082B 0007 0062 6712 4A2B 0076 670C 6008 4A2B 0076 6604 5640 4EF9 0000 CB96

For whatever reason, whenever I change to use the JSR.L, I get flickering graphics for the left player in the face-off inset. Odd. Hence the change at the end. As for the rest, I had a few questions…

1. Why 6712 @ 0x06? Wouldn't that make the bottom face-off always use the same graphic, regardless of hand?

2. Why 670C @ 0x0C? My original logic was to use 66, but this reverses the logic of the branch, and jumps two bytes ahead?

3. Why 6604 @ 0x0E? My original logic jumped to the end, but this instead jumps to add #3 to d0 first, or am I misunderstanding something? Or lots of things…

I tried a few variants, and couldn't get the desired behaviour. Not sure what I'm missing.

As for the AI generated code, I couldn't get it to work, and it might be too far over my head to even ask questions about. I've never used Claude.AI before. I assume it is what you would recommend for this? 

In any case, my bloated code seems to work fine, but I am definitely curious to learn how to write this optimally!

 

Keep your code if it works fine. Did you add the change I made? The code McMarkis posted won't work because it's not Exclusive ORing the right bits. Needs that LSL.B #7, D1 part

  • Thanks 1
Posted

Here is what I tried for the AI suggested code. It affects the face-off animation, but not in a desirable way. I suspect that I did this wrong.

MOVE.W  D1,-(SP)           ; 48E7 0200    ; Save D1
MOVE.B  $0076(A3),D1       ; 122B 0076    ; Load from offset 0x76
LSL.B   #7,D1              ; EF09         ; Shift left 7 bits
EOR.B   $0062(A3),D1       ; B32B 0062    ; XOR with position
BTST    #7,D1              ; 0801 0007    ; Test bit 7
BNE.S   .add3              ; 6600 0006    ; Branch if not zero
BRA.S   .exit              ; 6000 0004    ; Branch to exit
.add3:
ADDQ.W  #3,D0              ; 5240         ; Add 3 to D0
.exit:
MOVE.W  (SP)+,D1           ; 4CDF 0400    ; Restore D1
JMP     $0000CB96          ; 4EF9 0000 CB96 ; Jump to absolute address

 

 

Posted

I agree with Chaos, If your code is working keep that. The AI generated code is overkill and was just there as a reference as a possible way to reduce the number of TST instructions. But it can often be wrong and needs to be iterated through to get the correct answer.

 

 

  • Thanks 1
Posted

I just checked the AI suggested code with the LSL, it should work as intended. It's possible an opcode is messed up. Just stick with your code

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...