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