Mike Tyson's Punch-Out Disassembly

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Mon Aug 10, 2020 3:54 pm

Before I get into the disassembly techniques for the audio engine, I wanted to make a quick post on how to interface with it. The audio engine is controlled by 4 memory addresses: $F0, $F1, $F2, $F3. Details below:

$F0 - SQ1 SFX start/stop.
The valid values for this register: $01 - $18.
Writing a valid value to this register will play a sound effect that uses the SQ1 audio channel (and possibly other channels).

$F1 - SQ2 SFX start/stop.
The valid values for this register: $01 - $15.
Writing a valid value to this register will play a sound effect that uses the SQ2 audio channel (and possibly other channels).

$F2 - music start/stop.
The valid values for this register: $01 - $1F.
Writing a valid value to this register will play various musics from the game. Not all the values will play music. Writing a value of $0B, $0F, $16, $17, $18, $19, $1B or $1C will not play music and silence any currently playing music.

$F3 - DMC SFX start/stop.
The valid values for this register: $01 - $07.
Writing a valid value to this register will play a sound effect that uses the DMC audio channel.

NOTE: the various SFX/music can be stopped at any time by writing a value to the corresponding register where the MSB is set ($80, for example).

The way I listen to the various music/SFX is to open the game in FCEUX, get to a pre-fight screen (where little Mac and his trainer are on the left and the opponent is on the right) and open the hex editor from the debug menu. Simply write various values to these 4 registers to hear the different SFX/music.

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Mon Aug 10, 2020 5:01 pm

This is the 4th NES audio engine I have reversed engineered (Metroid, Dragon Warrior and SMB being the other 3, also Star Wars arcade). They all have similarities. The audio engine, in my opinion, is a good place to start when reverse engineering a game because the code is self contained. The variables used in the audio engine to not get used anywhere else in the code (except the interface registers). Once the audio engine is complete, parts of the code that start the various musics and SFX will be very obvious. This can then be used to determine what chunks of code control what game functions. For example, if a PlayerHitSFX is started somewhere in the code, it is probably safe to assume that portion of code calculates player damage values and hit detection.

One thing that has been constant in all NES and arcade audio engines I have reverse engineered is that there is a notes table. Somewhere there has to be a list of data values (usually byte pairs) that represent the different musical notes. In NES games, the tables all have identical values or values that maybe 1 bit off. The formats of these tables in NES games have all been big endian byte pairs. In Mike Tyson's Punchout I labeled the table NotesTbl. Finding this table is the first step I use in reverse engineering the audio engines.

I also make a list of all variables I see used in the audio engine. I know that those variables will only be used in the audio engine. Often times I will pick one of these variables and try to isolate its functionality by searching for all instances of that variable and observing how it interacts with the audio hardware registers. If I can't figure out its specific functionality right away, I can at least tell its used to control SQ1, SQ2 or something like that.

There are certain functionalities that must exist in the audio engine. Making a checklist of this functionality give a frame of reference of what to look for:
1)There must be some kind of pointer or index to the musical data. There must be a pointer/index for each channel used.
2)SFX have priority over music so there must be some kind of flag for each channel indicating that channel is being used by an SFX.
3)Often times there will be a restart flag that is set so a music channel can restart mid note after an SFX completes.
4)There must be a time counter for each musical channel that causes a new note to be loaded when the counter expires.
5)There is most likely a flag that initializes music/SFX and a separate flag that continues the music/SFX.

I'm sure there are more rules that could be stated about audio engines but these seem to be fundamental across the various games I've seen.

In most games I've seen (except Dragon Warrior) there are separate areas of code that handle SFX and music. And in the music player code, the different music channels have their own separate areas of code.

An important concept to realize is that even if a music channel is not playing because an SFX is playing, the counters must still run and the indexes to the musical data must still update. This is required to keep the musical data for that channel synchronized with the other channels. This can make the music player have a whole lot of branches and very confusing. I basically focus on one variable at a time and figure out what it does. I don't typically look at all the detail around it until most of the variables are understood. It gets too overwhelming trying to go through complex sections of code line by line with tons of branches and unknown variables.

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Sat Aug 15, 2020 8:51 pm

Just checking in. I have been jumping around in the disassembly deciding what to focus on next. I have the audio engine all figured out but not fully commented. I'll return to do that later. Time to look at more interesting stuff and uncover some undiscovered secrets! I took a quick look at the password system. I'll probably go deep into it soon and make some documentation on the algorithm used to encode/decode passwords. I found 6 hard coded passwords. All of them are known. Three passwords that generate a busy signal, one password that starts you at Mike Tyson, one that shows the end credits and one that starts another world circuit. Alas, there does not appear to be a NARPASSWORD waiting to be discovered :(

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Sat Aug 15, 2020 8:56 pm

An interesting note: The second controller is polled during, and only during, the boxing sequences of the game. There is actual code that is checking the values and doing something with the values. I set up breakpoints to that whole region of code and couldn't get it to trip. Whatever it is, its not being checked in the earlier fights. Also, the routines are not being directly called. If the routines are being used at all, they are happening in later fights and are being called indirectly. An interesting thing to put on the list for later...

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Sat Aug 15, 2020 9:19 pm

I've decided to focus on the data tables that control the opponents look and behavior. The data is completely encapsulated and is easy to follow. This part of the reverse engineering will not be as elegant as some of the other stuff as I plan on using brute force to figure out how the data tables work. Change and observe. That's the motto for this phase of the disassembly!

Here is what I already know:

The data for the opponents is located in the following PRG banks:
PRG bank 0: Glass Joe, Don Flemenco 1 and Don Flemenco 2.
PRG bank 1: King Hippo.
PRG bank 3: Mr. Sandman, Bald Bull 1, Bald Bull 2 and a partially functional Bald Bull 3. Playing Bald Bull 3 causes an automatic loss when the timer reaches a certain value. Leftover code fragments from another version?
PRG bank 4: Soda Popinski and Super Macho Man.
PRG bank 5: Piston Honda 1, Piston Honda 2 and Mike Tyson.
PRG bank 9: It has the patterns of opponent data but is not playable. A mystery...

The entry points into the opponent data is the rows of 8 data words at the tops of the PRG banks. This makes it very easy to swap data around and change the order of opponents. For example, The top 3 rows of PRG bank 0 look like this:

L8000: .word $8030, $8AEF, $8B23, $92B6, $0000, $0000, $0000, $9316
L8010: .word $8036, $8B27, $8B5B, $92D6, $0000, $0000, $0000, $94C3
L8020: .word $8036, $8B27, $8B5B, $92F6, $0000, $0000, $0000, $9523

The first row is the entry point into Glass Joe's data. The second row is Don Flamenco 1 and the third row is Don Flamenco 2. If the first and second row were swapped as follows:

L8000: .word $8036, $8B27, $8B5B, $92D6, $0000, $0000, $0000, $94C3
L8010: .word $8030, $8AEF, $8B23, $92B6, $0000, $0000, $0000, $9316
L8020: .word $8036, $8B27, $8B5B, $92F6, $0000, $0000, $0000, $9523

Don Flamenco 1 would now be the first fight of the game. Everything swaps properly with it. The palettes, pre-fight and inter-fight graphics and one liner comments and opponent sprites and behaviors. It's nice dealing with code so cleanly organized and encapsulated!

Also, the contents of a data containing PRG banks can be entirely swapped to change opponent order. For example, PRG bank 0 can be replaced with PRG bank 1 and King Hippo will be the first opponent. This will work until it is time to fight Don Flamenco and then the game will crash as his data has been overwritten. This will be a good reverse engineering tool.

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Sun Aug 16, 2020 2:10 pm

I mentioned above about a partially functional Bald Bull data set. I haven't confirmed it yet but I'm pretty sure this is the demo that runs during the intro.

FrankWDoom
Posts: 240
Joined: Mon Jan 23, 2012 11:27 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by FrankWDoom » Sun Aug 16, 2020 4:00 pm

Are you working on the -0 or -1 rom? Curious if you could determine what was changed. There's also the gold famicom punchout, wonder if there were any changes from that.

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Tue Aug 18, 2020 6:28 am

FrankWDoom,
I'm not sure which ROM I'm working with. How do you tell? Its not the gold one. That one was a Japanese release, right?

User avatar
dougeff
Posts: 2735
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Mike Tyson's Punch-Out Disassembly

Post by dougeff » Tue Aug 18, 2020 7:06 am

The original Japanese version didn't have Mike Tyson. Super Macho Man was the last fighter.

https://tcrf.net/Mike_Tyson%27s_Punch-Out!!
nesdoug.com -- blog/tutorial on programming for the NES

User avatar
Bregalad
Posts: 7951
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Re: Mike Tyson's Punch-Out Disassembly

Post by Bregalad » Tue Aug 18, 2020 7:43 am

dougeff wrote:
Tue Aug 18, 2020 7:06 am
The original Japanese version didn't have Mike Tyson. Super Macho Man was the last fighter.

https://tcrf.net/Mike_Tyson%27s_Punch-Out!!
Are you sure it's the original, and not a hacked version of the US game ; like for Contra ?
Because most games are 1st developed and released in Japan doesn't mean all are.
Useless, lumbering half-wits don't scare us.

FrankWDoom
Posts: 240
Joined: Mon Jan 23, 2012 11:27 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by FrankWDoom » Tue Aug 18, 2020 8:05 am

DirtyMcDingus wrote:
Tue Aug 18, 2020 6:28 am
FrankWDoom,
I'm not sure which ROM I'm working with. How do you tell? Its not the gold one. That one was a Japanese release, right?
yes, gold was japan only and did not have tyson

here's what i have for roms

Code: Select all

Mike Tyson's Punch-Out!! (JU) (PRG0) [!].nes
CRC32 
      prg: 8DB6D11F
      chr: 570B48EA
     data: 92A2185C
     file: 83DB7938

Mike Tyson's Punch-Out!! (U) (PRG1) [!].nes
CRC32 
      prg: F1D861EF
      chr: 570B48EA
     data: 2C818014
     file: 3DF8E170

nispio
Posts: 13
Joined: Thu Aug 20, 2020 11:19 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by nispio » Thu Aug 20, 2020 11:37 pm

I am really excited that you are doing this disassembly! I have been planning on doing it myself, but it would be my first reverse engineering project for NES, so I was just getting started on learning the basics of the 6502, PPU, etc., when I stumbled on this post!

I have been asking around the community, and it seems like there is very little publicly-available information about the disassembly for this game. There are some TASers who seem to know quite a bit, but they haven't published their notes for others to use. So I am happy to see you documenting things so thoroughly.

I look forward to reading your continued updates.

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Fri Aug 21, 2020 3:41 pm

nispio,
Thanks! I'll hopefully have enough new content to do a couple of posts on Sunday. I'm working on the data tables that control the opponent states. It's pretty interesting. I just need to figure out a way to present the information in an understandable way.

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Sun Aug 23, 2020 3:51 pm

I've been plugging away at the opponent state data tables. The tables are too complex to randomly change data and figure out what it does. What I'm doing is setting breakpoints at desired state data and seeing what code segments access the data. I then have to go in and read through the code.

The opponent state machine is quite elaborate. Every single state task is handled through an indirectly called subroutine. Even if its something as simple as writing a byte to a memory address. There is a subroutine that starts at address $C550 on PRG_BankDEF that is the entry point for all opponent state updates. A byte is passed in through the accumulator and the upper nibble is used as an index into a table of subroutine pointers. The lower nibble may be used as a second pointer in a second table, if necessary.

This method seems to burn a lot of clock cycles to do simple things like read and write memory addresses but it encapsulates the different states quite nicely. Now that I know the basic flow of the opponent states, I should be able to reverse engineer it pretty easily. Most of the time will be spent figuring out what the different memory addresses do.

DirtyMcDingus
Posts: 38
Joined: Sat Jul 25, 2020 5:31 pm

Re: Mike Tyson's Punch-Out Disassembly

Post by DirtyMcDingus » Sun Aug 23, 2020 3:59 pm

A few things of note:

As of yet, I have not found the RNG for the game. It's not as obvious as it is on some other games.

Also, I find it interesting that the opponent has 4 defense values(Addresses $B6-$B9). They correspond to the opponent's defense against right face punch, left face punch, right stomach punch and left stomach punch, respectively. The higher the value, the better the defense. These values potentially change every animation segment. This means there are probably many frame perfect, or near frame perfect opportunities to hit the opponent in specific ways for tons of damage. I'll keep my eyes open for anything like that.

Another thing I noticed is that Little Mac has 2 defense stats($76 and $77). The values always seem to be updated at the same time so there is effectively only 1 defense stat. Maybe at one time they were planning to have a left and right defense?

Post Reply