11 March 2016 - Forum Rules

Main Menu

Kung Fu 50x: Fight Sylvia!

Started by Ben Boldt, April 01, 2018, 09:49:06 PM

Previous topic - Next topic

Ben Boldt

Legend has is that you get to fight Sylvia when you beat the game 50 times.  Not true, until now!

Basically, the game is completely normal for the first 49 plays.  The 50th play (when counter reads '49') is different, it is based on "Sylvia Saves Thomas" hack by Megafield64.  I made some slight alterations to indicate some marital problems, and an improved hairstyle for our protagonist. ;)

Then the 51st play (when counter reads '50'), you are Thomas again.  The plan is to graphics-hack swapping Mr.X with Sylvia (I would love some help with that), and you save Mr. X from Sylvia, revealing Mr.X was his true love all along, etc.  It is completely functional now, and just needs graphics for fighting Sylvia instead of Mr.X, and saving Mr. X instead of Sylvia.  This is maybe somewhat comical in a way, but it is not meant to be homophobic.  Not sure how this board is what that; let's treat it as light-hearted please.

Here is how I did the hack:

I took the original Kung Fu (Mapper 0) and made it into Mapper 66 like Super Mario Bros./Duck Hunt.  This allowed me to quadruple the PRG and CHR space.  I placed copies of Kung Fu PRG into slots 0, 1, and 2, and copies of CHR into slots 0, 1, and 2.  Since Kung Fu is absolutely packed full, I moved some initialization code to PRG page 3 to free up some space in each of the other slots.  Then in that free space in each game, I detect the number of plays and do PRG/CHR swap based on <49, =49, and >49.  After switching, it just carries right along at the same spot in the new page.  It is functioning like a multicart in a way.  Also, I paid special attention to the unknown initial state of the 74_161 if this is to be put onto a real cartridge.  The reset vector should function properly on each page and ultimately get redirected to page 0.

Because of this shotgun approach (having 3 whole copies of the game), each version can be hacked freely, independently.  So I am able to edit directly for separate graphics and messages in each one for example.

Here is the ROM file layout:

$00000:0000F iNES header

$00010:0800F PRG 0 - Vanilla Kung Fu
$08010:1000F PRG 1 - Marital Problems (based on Megafield64)
$10010:1800F PRG 2 - Fight Sylvia, save Mr.X
$18010:2000F PRG 3 - Offload some initialization code

$20010:2200F CHR 0 - Vanilla Kung Fu
$22010:2400F CHR 1 - Marital Problems (based on Megafield64)
$24010:2600F CHR 2 - Fight Sylvia (needs more work)
$26010:2800F CHR 3 - Not used.

Please try it and let me know if you find any issues.

Player 1 & 2 defeat counters are located at $56 & $57, which get loaded into $5E for whoever is playing at the time.  Setting to $31(49) causes the game to go into marital problems mode, $32(50) or higher is fight Sylvia mode.  This is checked at the beginning of each level.  I imagine beating the game 256 times likely rolls back to 0.  ::)

If anyone would like to lend a hand with graphics, especially Megafield64 if you're out there, that would be greatly appreciated.  Also, upgrading the beat game counter to 2-digit decade would be amazing if anyone is up for a challenge.  I looked into this but am not very familiar with the PPU, so I was not able to make any progress on it yet.  There are still 80 bytes free PRG space available in each game at ROM file address $2DB:2DA (+ $8000 * x), which can be expanded more as needed.

BPS file:

Play 49:

Play 50 (Sylvia and Mr.X graphics still not changed):


50 is way too long. I'd put it at... 10, tops, more like 5 or even right after the main game as 'game+' because i'm flighty about games.

50 is probably because it was a 'legend' ie: bull and the storyteller didn't want to be disproved. I'm surprised it isn't 100. Not even Akane from Ranma was kidnapped 5 times.

So yeah, if you complete this, i'll ask for a version that works as game++ and just shows the hack content right after one run, ie: normal game, Sylvia getting swole, Sylvia end boss game.

Ben Boldt

Thanks for the feedback.  Yes, I agree that 50 times is quite extreme, and I am sure the storyteller didn't want to be disproved. But I held true to it nonetheless.  You can have it kick in at game 2 and 3 with this Game Genie code:


Or you can use the RAM locations I mentioned earlier so you can set it to whatever version you want right from square 1.

Also, you can use these codes to make the game faster/easier as well:

XTVGGGGE   Invincible unless time runs out

EYNKIAEI   Knife throwers throw the wrong way

VVVEGSSE   Enemy starts with minimum health

VXKKZYSZ   Player has auto-recovering health instead of enemy

I think I got Mr.X figured out for the ending:

The goal would be to look like this:

This is with Thomas untouched.  Thomas is standing a bit awkwardly and I am not sure what his arm is doing anymore... But it seems reasonable.  Mr.X has to stand straight up in this situation; neither of them are, in any way, a girl.  From our experience with Mr.X over the years, I think we can say that he appreciates a level of control. It wouldn't make sense for him to bend around like Sylvia was.

I will have to learn about the PPU and how to change color tables, or if it is even possible in this case to set the colors of this image, but I will try.  The top 8x8 would need a different color table than the other ones.  Also, Mr.X needs to move 3 pixels left versus where Sylvia was standing.  Not sure how the game is positioning them now, but they are not currently on the same 8-pixel boundary, so it seems like there should reasonably be a way to bump one of them in 1-pixel increments.

Also, another issue: The exclamation point is strange; it is not part of the text string, so I do not know how to remove it.  I may be able to write a blue tile on top of it; I have not tried that yet.


I feel like this hack would be better served if it just added the secret battle. Everything else you're adding to this hack is just... well, it feels like a bad fan fiction, to put it honestly. It's not part of the legend and it serves no purpose except pandering to a very unlikely ship.

Ben Boldt

Well, you have to be creative with the ending if you fight Sylvia.  You can't defeat her and then fall in love again, that doesn't make sense.

I think this is unique, something that has not been done before.  I am definitely not the only one who is a little tired of every game being about saving the girl.  This time the girl is strong and fights back.  And you can even defeat her and go a whole different direction.

Guy saving girl isn't for everyone, guy saving guy isn't for everyone.  Think about it from a different perspective.  It might not be meant for you, but I think there is a place for it, and it can still be enjoyable.


I figured out how to edit palettes!

Thomas is a background image and Mr.X is a sprite-based image.  I think it may be possible to turn his head into a different sprite and use a different palette so I can make his hair and eye the right colors.



Luckily, Mr.X's head is comprised separate sprites in all cases, so it is already quite possible to change the palette selection of only the head, to accomplish the hair and eye colors.

I have been able to do the following things to the ending scene:

  • Put Mr.X's standing up CHR data into the game
  • Moved Mr.X 3 pixels to the left (resolved to a 1-byte change)
  • Changed the pink Sylvia palette to the body color of Thomas
  • Changed the palette selection of only Mr.X's head to sprite palette 0.
  • Changed the colors of sprite palette 0
  • Changed text to read "Thank you Thomas!", "I love you..."  Simpler is better.
  • Done.

I detect when to change the palette selection and to overwrite palette 0 colors by looking at the OAM/sprite DMA RAM area starting at CPU RAM location $200.  If the sprite tile index at location $219 == #$CC or $229 == #$CC, the game is displaying Mr.X's head in the bound-to-chair image, either in the cutscene and at the very beginning of the ending sequence.  If I do not see this tile selected, I don't touch any palette stuff.  The palette changes remain for the rest of the ending sequence after this happens.

The game has a nice existing function for writing to PPU memory that occurs at the beginning of each V-blank interrupt.  I found that it accepts a value via RAM location $52, which is in index into a lookup table that stores 16-bit addresses, which point to data packets stored in ROM.  The data packet works like this:

byte 0 = PPU write address, MSB
byte 1 = PPU write address, LSB
byte 2 = # of bytes to be written
byte n = the bytes to be written.

So I stored in ROM this data:
3f 01 03 27 30 18

What this does is writes the 3 colors of Mr.X's head to sprite palette 0 at PPU RAM location $3F01.  I inserted code after the $52 business that checks:

  • Is $52 non-zero?  if so, bail, the game is using it.
  • Otherwise, does $219 or $229 contain #$CC?  If so, run the function, pointing to Mr.X's head palette data packet

And that all worked.  Definitely in all cases, palette 0 is correct, and I consider that part finished.  The entire ending sequence is completely done, it looks identical to the picture I photoshopped now, with different text.

However, I still have a glitch with palette selection for Mr.X's 2 head sprites during the cutscenes when he is bound to a chair.  My method is to let the game write the palette it wants in the DMA RAM, then I overwrite it immediately afterwards with my palette selection.  Well, the game must be updating the palette a lot because it flashes back and forth between palette 0 (me) and palette 3 (original to the game)...  I have a bit of work to do to figure out how to prevent the wrong palette index being momentarily written.

Also, I have not yet begun to look at turning the last boss into Sylvia.  It does appear that it shares a lot of tiles with Thomas, so it may be more of a palette and hairstyle change.


I was able to fix the palette selection flashing thing when Mr.X is bound in a chair.  Mr.X has correct graphics and colors everywhere now.  All that is left is to edit the palettes of last-boss-Sylvia, change her head sprite, and anything else I can do to make her look tough and girly.

I have learned a lot from this hack!  I have never before done anything with the PPU before this, and now I have a mild understanding of how it works.  I may reattempt a 2-digit decade onscreen beat-game counter.


I got the decade beaten game counter working tonight!  It is left-aligned, so games 0-9 look the same as normal, then 10 starts using the next tile to the right.


I updated to 3-digit decade counters for lives and defeat count today.  This calculation shares common code in PRG page 03.  The new function takes in X as the number to display, Y as the offset into the RAM data packet to be fed to the PPU.  Basically, where it was doing a STA $xxxx,Y, I changed this to JSR #xxxx, and wherever it loaded A, I loaded X instead.  This allowed me to leave the code relatively untouched and using the same exact number of executable bytes.

I used the indexed INC instruction for my decade/BCD calculation.  Since indexed INC only works with X and not Y, I had to swap X and Y at the beginning and end of this function.  I pushed and pulled from the stack to do these swaps.

The extra digits for defeat count were okay, but for lives, it had the incorrect palette selected.  The extra digits came out light green.  So I changed it in the PPU attribute table.  That was a new one for me.

For game 49, I have made the walking and "smack" sound effects higher pitch and changed the pitch of the laughing in the cutscenes.  Also, Thomas still had the original Sylvia palette when he was bound to a chair in the ending, I fixed this.

This hack is pretty close to finished now.  I have saved the Sylvia battle for last.

Ben Boldt

I think it is done now!  Please try it and let me know any bugs or recommendations.

Remember, Game Genie code PAVELZPL if you do not want to play 50 times.


Updated the colors of the sprite when you defeat Sylvia (as boss) when she falls off the screen.  Updated file at same download link.