Jump to content
NHL'94 Forums

Recommended Posts

Posted

FYI to anyone reading this. This weekend I went over all the notes above, and made numerous tweaks and fixes. The notes should now be complete, and completely accurate, to the best of my abilities. I will put this out in an easier to use format soon.

  • Like 1
Posted

OK, after more testing, I updated the notes above again. Attached is the first public beta of a wide display mode patch for the Original, unmodified '94 ROM. If anyone has the time or interest in testing it, I would appreciate it. Please do report any issues.

NHL 94 (UE) [!] [h] - Wide Display Mode - v2b1.bps

Posted

I tried it out. Worked seamlessly for me.

Only issues were that I needed to download a different patching program after realizing that it was in .bps as opposed to .ips format, and that I don't like to read apparently since I initially got an error that reminded me that you specifically pointed out that this was a patch for the Original game, so obviously it won't translate to the expanded 32-Team version you dumbass.

Posted

Thanks chief. I'm getting reports of some crashes with my 32-team ROM, but I've yet to be able to recreate the issue. Regardless, while looking for it I found a couple minor issues that I solve, which could, theoretically lead to a crash. In doing so, I also inadvertently discovered how to lock to camera horizontally in place. So, there's that.

 

Posted (edited)

Newly Found Issue

Players Enter the Penalty Box 32 pixels to the right of where they are supposed to enter.

Please see the images below for clarification. Does anyone have any idea of where those co-ordinates are set?

Update: So I figured out why this is off by 32 pixels. All the gamplay is shifted 32 pixels to the right to get it centred underneath the camera view. SO, an alternate solution would be to get the camera view to centre 32 pixels to the right of its default instead.
 

Proper

NHL '94 2024-12-16 22.38.20.pngNHL '94 2024-12-16 22.38.09.png
 

Wide Display Mode

NHL 94 [h] 2025 AC v2.2 - 2024 12 16 4 2024-12-16 13.06.26.pngNHL 94 [h] 2025 AC v2.2 - 2024 12 16 4 2024-12-16 13.05.47.png

Edited by AdamCatalyst
Posted (edited)

Hey @AdamCatalyst Base 94 Rom: The '94 code is slightly different than '92, but I gave it a quick test for the home team in 94' and it works.

Location 0xC918
Original 70 0B 
  • Try changing 0B to a lower number to move the home players X position to the left.
  • The code further down just takes this value from d0 and makes it negative for the away team.
  • This automatically adjust the away player by the same amount without any further changes. (Confirmed)

Let me know if it works.

image.png

@chaosThanks for the IDA comments, made it easy to map from 92' to 94':)

Edited by McMarkis
Posted (edited)

@McMarkis Thanks man! I really appreciate you taking the time. I tried it out, and it works exactly as you describe, but doesn't solve the problem. This value sets how many pixels away from the origin point that the players should enter the penalty box. The problem is that the origin point has been shifted by 32 pixels to the right, so even if I use this method to fix one team the other team will be even worse than it is now.

Rather than taking the negative value, I assume one could set an explicit value. However, I wonder if there is a much more elegant solution…

All of this happens because there is a whole stack of mods setup predicated on shifting everything 32 pixels to the right to centre it in 320 pixel display mode. However, none of those hacks (and this problem) would be necessary if we could just tell the camera to centre properly in the first place. I was looking through the source code, and found this:

updatescroll
	;using hpos and vpos set scroll cords and flags
	;also set up map transfer if new rows of characters are needed by
	;vertical scrolling
	btst	#sfhor,sflags
	bne	rtss
	moveq	#-192+128,d0
	sub	Hpos,d0
	move	Vpos,d1
	move	d0,Hscroll
	move	d1,Vscroll
	neg	Vscroll

I don't pretend to know what it means, but I would assume that that must be some logic somewhere that takes the rink width (384 pixels), cuts it in half (192 pixels), take the viewport (256 pixels), cuts it in half, then takes the difference between those two numbers, and uses that as the offset to centre the puck or other focal point. Changing that 128 value to 160, would solve this problems at the source. I was wondering is this bit of code could be doing what I imagine is happens behind the scenes.

Is this fools gold, or could I be onto something? And if so, how would I find this code?

 

Edited by AdamCatalyst
Posted

Hey @AdamCatalyst,

I did a quick search for the UpdateScroll routine in the 94' code but I haven't had much luck locating it.

However I noticed the X and Y coordinates that the player should skate to are set before calling the Skateto routine. I would assume somewhere the origin would be referenced and the X,Y offset would be added to that.

I will keep digging around, and let you know if I find anything..

image.png

  • Thanks 1
Posted
On 12/17/2024 at 9:21 PM, AdamCatalyst said:

@McMarkis Thanks man! I really appreciate you taking the time. I tried it out, and it works exactly as you describe, but doesn't solve the problem. This value sets how many pixels away from the origin point that the players should enter the penalty box. The problem is that the origin point has been shifted by 32 pixels to the right, so even if I use this method to fix one team the other team will be even worse than it is now.

Rather than taking the negative value, I assume one could set an explicit value. However, I wonder if there is a much more elegant solution…

All of this happens because there is a whole stack of mods setup predicated on shifting everything 32 pixels to the right to centre it in 320 pixel display mode. However, none of those hacks (and this problem) would be necessary if we could just tell the camera to centre properly in the first place. I was looking through the source code, and found this:

updatescroll
	;using hpos and vpos set scroll cords and flags
	;also set up map transfer if new rows of characters are needed by
	;vertical scrolling
	btst	#sfhor,sflags
	bne	rtss
	moveq	#-192+128,d0
	sub	Hpos,d0
	move	Vpos,d1
	move	d0,Hscroll
	move	d1,Vscroll
	neg	Vscroll

I don't pretend to know what it means, but I would assume that that must be some logic somewhere that takes the rink width (384 pixels), cuts it in half (192 pixels), take the viewport (256 pixels), cuts it in half, then takes the difference between those two numbers, and uses that as the offset to centre the puck or other focal point. Changing that 128 value to 160, would solve this problems at the source. I was wondering is this bit of code could be doing what I imagine is happens behind the scenes.

Is this fools gold, or could I be onto something? And if so, how would I find this code?

 

This subroutine starts at 15F34.

15F3E is the moveq -64, d0.

You can try changing 15F3E from 70 C0 to 70 E0 and see if that works. Or change it to 70 FE (that's 32 pixels in each direction)

 

  • Thanks 1
Posted (edited)
2 hours ago, chaos said:

This subroutine starts at 15F34.

15F3E is the moveq -64, d0.

You can try changing 15F3E from 70 C0 to 70 E0 and see if that works. Or change it to 70 FE (that's 32 pixels in each direction)

 

You da man, Looks like Adam already changed it from 70 C0 to 70 E0 in his ROM. 
Must be a different scroll happening when in Horizontal mode for the penalty box.
I'm still convinced it has something to do with the Skateto Routine.

Edited by McMarkis
  • Like 1
Posted
2 hours ago, chaos said:

This subroutine starts at 15F34.

15F3E is the moveq -64, d0.

You can try changing 15F3E from 70 C0 to 70 E0 and see if that works. Or change it to 70 FE (that's 32 pixels in each direction)

 

Thank-you for this! Turns out I am jumping at shadows. That controls the X-Position of the background, which I had already identified. I just had no way of knowing where the source code corresponded to compiled code! How would I go about trying to go from instructions in the source to compiled code in the ROM?

Posted (edited)

@McMarkis & @chaos in case this is helpful, here is are some key changes that are likely relevant. The problem is caused by changing the gameplay registration point at 0x016951, which is done to compensate for all the other changes used to get the background centred.

 

 

 21. Rink Background X-position

@ 0x015F3F

C0

v1.2

E0


22. Sideboards Crowd Animation X-position

@ 0x0161F7

C0

v1.2

E0


23. Rink Crowd Animation X-position

@ 0x016287

90

v2b1

D0


24. Rink Player Visibility Right Side

@ 0x016941

90

v1.2

B0

 

25. Rink Player Visibility Left Side

@ 0x016949

70

v1.2

50

 

26. Rink Gameplay X-position

@ 0x016951

00

v1.2

20

32-Team Recommendation
Use as-is.
NOTE - Causes Penalty Box Players entering to be off by 32 pixels.

 

27. Unknown

@ 0x01695B

90

v1.2

B0

 

28. Unknown

@ 0x016963

70

v1.2

50

 

Edited by AdamCatalyst
Posted (edited)
1 hour ago, AdamCatalyst said:

Thank-you for this! Turns out I am jumping at shadows. That controls the X-Position of the background, which I had already identified. I just had no way of knowing where the source code corresponded to compiled code! How would I go about trying to go from instructions in the source to compiled code in the ROM?

I'm not sure how @chaos does it, he may have an easier way, but here is the method I use:

  1. I compile the NHL 92' source code from the github repo using the included batch file.
  2. This produces a listing file (nhl92.lst) that contains both the source code and the compiled binary (hexadecimal) values.
  3. I search the nhl92.lst file for the routine, comment or code I’m looking for—in this example, the updatescroll routine.
  4. The left-hand side of the listing file contains the offset in the nhl92.bin file along with the generated hex values (70C0)
    1. For instance, 0000C2D2 is the ROM location of the instruction in the nhl92.bin file, and 70C0 is the binary (hex) value generated by the moveq #-192+128,d0 instruction.
  5. I then open the nhl94.bin in HxD editor and I search for the hex value 70C0.
    1. In this case, the code was found at offset 15F3E (second screenshot)

Additionally, @chaos has shared a decompiled version of NHL '94 with me, which includes many comments copied over from the NHL '92 source code. This is incredibly helpful because it makes the instructions easier to read and provides useful context with comments.
image.png


image.png

 

Edited by McMarkis
  • Thanks 1
Posted
11 hours ago, AdamCatalyst said:

@McMarkis THANKYOU FOR THIS! Going to try this out tomorrow. 

In IDA Pro I have it showing the opcodes. I can't change it in there, so I will use a hex editor, open the ROM, and change it in there (I admit I didn't test the above, I just gave you options for what you thought might help). I use an opcode cheat sheet to figure out what I need to change it to. But, I've also used Claude AI and it will give me the opcode for an instruction if I ask it.

 

M68kOpcodes-v2.3.pdfAsm_Lang_Prog_68K_Family.pdf

  • Thanks 1
Posted
47 minutes ago, chaos said:

In IDA Pro I have it showing the opcodes. I can't change it in there, so I will use a hex editor, open the ROM, and change it in there (I admit I didn't test the above, I just gave you options for what you thought might help). I use an opcode cheat sheet to figure out what I need to change it to. But, I've also used Claude AI and it will give me the opcode for an instruction if I ask it.

 

M68kOpcodes-v2.3.pdf 179.85 kB · 0 downloads Asm_Lang_Prog_68K_Family.pdf 3.94 MB · 0 downloads

 

I agree with @McMarkis here. The players are set to skate to a specific location based on how many players are in the penalty box. In this case, it's more likely to be a Y offset and not an X offset because of the horizontal nature of the screen. 

 

 

image.png

 

This is the asspenalty assignment, given to a player with a penalty. @McMarkis suggested changing the 

moveq #$b, d0

which would be the right thing. This is +11 decimal in Y. So Home box would be -11 decimal, away +11 decimal.

You would need Home to be 21 decimal ($15 hex) and Away to be 43 decimal ($2B hex).

you can set the $B to $2B

change C919 from 0B to 2B

 

then

change starting at C92A from 44 40 to 70 15

Instead of making neg d0, you will just change the value from $2B to $15 in d0.

You might have to play with this $15 value and see what works best for multiple players in the box.

The higher the number, the more left on the horizontal screen the player will travel.

  • Thanks 1
Posted

I should make a .LST file and have it on GitHub so others can see the comments in my code (its not compilable though)

  • Love 1
Posted (edited)
2 hours ago, chaos said:

This is the asspenalty assignment, given to a player with a penalty.

That sounds like a human rights violation.

FYI, tried out the changes Chaos mentioned above. At first it seems to work, but then with each subsequent penalty, Away players end up skating farther and farther away, until some don't even appear on screen. I'm assuming this is because value D1 is multiplied by D0, so by increasing the Away value, we end up with some crazy high multiples.

Regardless there is tonnes of good info for me to go on here. Looking forward to going through it al later.

EDIT: looking this over, I could just re-write it with absolute values, no multiples, where penalty box players always go to the centre of their respective boxes. That would look fine, but it would be inauthentic for purists. Going to try it, in part just as an exercise in learning assembly.

Edited by AdamCatalyst
  • Like 1
Posted (edited)

So, I was able to write a patch to fix the position of the player entering the penalty box, but I realize now that ALL players in the sideboard view are off by 32 pixels. Whenever you pause the game, etc. player appear 32 pixels to the right from where they should.

I ASSUME that it takes the players Y-position in Vertical view and converts it to their X-position for Horizontal view, and since I change the centre point from 256 pixels to 288 pixels in Vertical, that value is now 32 pixels too high in Horizontal. I somehow doubt these dimensions have a 1:1 correlation, and suspect that there is a simple that converts the value from one to the other, and back again. Of course, I could be very wrong about all of this. Regardless, that's what I am looking for right now, to try to solve this problem at the source, in all scenarios. As always, any help is greatly appreciated.

p.s. I'v been continuing to updated the posts on the original patch, as I've identified the function of significantly more code now. Hopefully this will be of use to someone someday.

Edited by AdamCatalyst
Posted (edited)

@McMarkis @chaos When you have a moment, would you look at this? Here is what I did…

1. @ 0x01694e = 0640 0100 D242. If I increase the 0100 to 0120, the vertical players are centred, but the sideboard players are shifted too far to the right by 32 pixels.

2. So instead, I remove the code, and insert this to jump to a new patch: 4EF9 001F FA4A

3. @ 0x1FFA4A I insert the patch:

0640 0120 0838 0007 C2EC 6700 0006 0640 FFDF D242 4EF9 0001 6954 

What I'm trying to do, is set the value to 288 , then  test the bit in memory that indicates if the view is Horizontal or Vertical, if it is horizontal, subtract 32, then jump back to where we left off. (edited since first posted)

This seems to work, I've not yet get it to skip a beat. Players are always in the exact right position, vertical or horizontal view, entering the box, exiting the box, etc. I am shocked.

Please let me know if this looks reasonable to you, or if there is a better way to do this kind of thing.

Edited by AdamCatalyst
updated code
Posted
34 minutes ago, AdamCatalyst said:

@McMarkis @chaos When you have a moment, would you look at this? Here is what I did…

1. @ 0x01694e = 0640 0100 D242. If I increase the 0100 to 0120, the vertical players are centred, but the sideboard players are shifted too far to the right by 32 pixels.

2. So instead, I remove the code, and insert this to jump to a new patch: 4EF9 001F FA4A

3. @ 0x1FFA4A I insert the patch:

0838 0007 C2EC 6600 0008 0640 0020 D242 0640 0100 D242 4EF9 0001 6954 4E75

What I'm trying to do, is test the bit in memory that indicates if the view is Horizontal or Vertical, if it is vertical, add 0020, then add 0100 regardless, then jump back to where we left off.

This seems to work, I've not yet get it to skip a beat. Players are always in the exact right position, vertical or horizontal view, entering the box, exiting the box, etc. I am shocked.

Please let me know if this looks reasonable to you, or if there is a better way to do this kind of thing.

 

Looks like this part of the code in 92 source in VIDEO.ASM: find3d sub routine

 

horoff	=	197
find3d	;input - d0=xfield,d1=yfield,d2=height off field
	;output - d0=xscreen,d1=yscreen

	btst	#sfhor,sflags
	beq	.nhor

	exg	d0,d1
	neg	d0
	sub	#horoff,d1
	bra	.crange

.nhor	sub	Hpos,d0
	sub	Vpos,d1
.crange	cmp	#128+16,d0
	bgt	.offscr
	cmp	#-(128+16),d0
	blt	.offscr
	add	#128+128,d0
	add	d2,d1
	asr	#1,d2
	add	d2,d1
	cmp	#112+32,d1
	bgt	.offscr
	cmp	#-(112+32),d1
	blt	.offscr
	neg	d1
	add	#112+128,d1
	rts
.offscr	move	#osflag,d1
	rts

You are changing the 

add #128+128, d0

instruction.

Maybe for horizontal, you can try changing the 

sub #horoff, d1

instruction. The value #horoff is $C5 (197 dec). you can change this value at 16931 in the 94 ROM (currently C5). It won't run this instruction if you are in vertical mode, so worth just trying to adjust that.

  • Thanks 1
Posted (edited)

Thanks so much @chaos. Merry Christmas to you and yours. 

EDIT: I tried your suggestion out. Neat! It actually changes the Vertical offset in the Sideboards view, so you can alter how far into the boards players can skate. It seems the ROM may use the nomenclature "Horizontal" when expressing what would be horizontal in Vertical view. "VerticalOffset" seems to be its counterpart, but I've not been able to locate it. Hypothetically, it would act in the same way. If I understand the code correctly, it code seems to indicate that it has a value of 0x55 set… somewhere.

 

Edited by AdamCatalyst
Posted
3 hours ago, AdamCatalyst said:

Thanks so much @chaos. Merry Christmas to you and yours. 

EDIT: I tried your suggestion out. Neat! It actually changes the Vertical offset in the Sideboards view, so you can alter how far into the boards players can skate. It seems the ROM may use the nomenclature "Horizontal" when expressing what would be horizontal in Vertical view. "VerticalOffset" seems to be its counterpart, but I've not been able to locate it. Hypothetically, it would act in the same way. If I understand the code correctly, it code seems to indicate that it has a value of 0x55 set… somewhere.

 

That's interesting, because according to the code, it should skip those instructions if in vertical mode. I wonder if you are skipping setting the horizontal flag in your modified code somewhere.

 

btst	#sfhor,sflags
	beq	.nhor

	exg	d0,d1
	neg	d0
	sub	#horoff,d1
	bra	.crange

.nhor	sub	Hpos,d0
	sub	Vpos,d1

The btst instruction is testing if the bit is set or not. It's checking the #sfhor flag, which is set when in horizontal mode (side bar). The beq instruction will branch the code to .nhor if the bit is not set (beq meaning the previous instruction set the conditional "Zero" flag, which is set when the check reads a zero or "cleared, not set"). And the label .nhor stands for "not horizontal"

 

I'll have to try this out on a regular ROM and see how it works

Posted (edited)
4 minutes ago, chaos said:

That's interesting, because according to the code, it should skip those instructions if in vertical mode. I wonder if you are skipping setting the horizontal flag in your modified code somewhere.

 

btst	#sfhor,sflags
	beq	.nhor

	exg	d0,d1
	neg	d0
	sub	#horoff,d1
	bra	.crange

.nhor	sub	Hpos,d0
	sub	Vpos,d1

The btst instruction is testing if the bit is set or not. It's checking the #sfhor flag, which is set when in horizontal mode (side bar). The beq instruction will branch the code to .nhor if the bit is not set (beq meaning the previous instruction set the conditional "Zero" flag, which is set when the check reads a zero or "cleared, not set"). And the label .nhor stands for "not horizontal"

 

I'll have to try this out on a regular ROM and see how it works

Sorry if I was unclear! To clarify, YES, it only functions in Horizontal mode, no effect in Vertical mode. However it modifies the opposite offset axis, so the y-axis in Horizontal mode.

I really appreciate all your annotations on code. I learn something new each time.

Edited by AdamCatalyst
  • Thanks 1
Posted

To anyone following this thread, I went through and updated all the notes today. You can use them as-is to update just about any '94 ROM. I will be looking to write up a how-to, and release patches soon. Known issues are listed on the first post.

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...