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