You are not logged in.
WARNING: This is a really long tutorial, and while it may not be as complicated for you as it was for me to make it up, it is still a lot more complicated than, say, editing the text or which item is in the PC at the start of the game or any of that jazz. But if you follow the tutorial properly (and assuming I haven't accidentally skipped something, since there was a lot to explain) you should be able to get this working in your game.
To see the finished results of this tutorial, you can check out this youtube video:
http://www.youtube.com/watch?v=9CPbmE9FQC8
Step 1: Get the graphics for the girl player.
For the girl player, you will need the following graphics:
-Front sprite
-Back sprite
-Walking sprite
-Cycling sprite
-Fishing tiles
To get the right dimensions for these, you can just copy+paste the ones for Red and edit them. Please note that in my example, I have Danny-E33's larger backsprite routine installed. You can do this without that routine of course, but your backsprite will have to be the normal Red Version size instead of the larger Gold Version size I am using.
Once you have your graphics drawn/found etc. make sure that they use ONLY the colours that other graphics in the project folder use (otherwise they won't convert properly) and save them as .png files with names you can remember. In my example, I kept the same naming scheme as the original files, but I substituted the word "Leaf" everywhere the original file name said "Red" and placed them in the same subfolders as the originals. This was just to make it easier for me to remember the file names later, and to make sure they are converted properly at compile.
So I ended up with files named:
/pic/trainer/leaf.png
/pic/trainer/leafb.png
/gfx/sprites/leaf.png
/gfx/sprites/leafcycling.png
/gfx/leaf_fishing_tile_back.png
/gfx/leaf_fishing_tile_front.png
/gfx/leaf_fishing_tile_side.png
Step 2: Inserting the sprites.
Now that you have the new .png files in the proper subfolders, we have to actually reference them somewhere to get them included. So we will open main.asm in notepad++ and find the references to the player's sprites. Doing a search for RedPicFront will eventually get you to this:
RedPicFront:: INCBIN "pic/trainer/red.pic"
ShrinkPic1:: INCBIN "pic/trainer/shrink1.pic"
ShrinkPic2:: INCBIN "pic/trainer/shrink2.pic"
Well, let's just add a new line really quick to include our new front sprite for the girl, so we can reference it later. You should have something that looks like this:
RedPicFront:: INCBIN "pic/trainer/red.pic"
LeafPicFront:: INCBIN "pic/trainer/leaf.pic"
ShrinkPic1:: INCBIN "pic/trainer/shrink1.pic"
ShrinkPic2:: INCBIN "pic/trainer/shrink2.pic"
Now if you scroll down a little from that, you should see the lines that include the overworld sprites. So we will just go to the line that says:
RedCyclingSprite: INCBIN "gfx/sprites/cycling.2bpp"
RedSprite: INCBIN "gfx/sprites/red.2bpp"
and add a couple of lines under it, so it looks like this:
RedCyclingSprite: INCBIN "gfx/sprites/cycling.2bpp"
RedSprite: INCBIN "gfx/sprites/red.2bpp"
LeafSprite: INCBIN "gfx/sprites/leaf.2bpp"
LeafCyclingSprite: INCBIN "gfx/sprites/leafcycling.2bpp"
Now, at least in my case, adding thew overworlds to this bank caused errors at compile, because we were trying to add too many sprites in this bank. To make life simpler later, we can just take 2 unrelated sprites and move them to another bank. I decided to cut and paste the lines that said:
GiovanniSprite: INCBIN "gfx/sprites/giovanni.2bpp"
RocketSprite: INCBIN "gfx/sprites/rocket.2bpp"
to the top of the other bank of overworld sprites. You can find that other bank by searching "SECTION "NPC Sprites 1"" or by scrolling up a bit from the banks we were just editing.
Now, the next thing we should come to is the fishing tiles. We won't have room to include these in the same bank as Red's fishing tiles, so we will have to find another bank to include them in. Which bank they are in is not important, since the routine that calls them can find them in any bank. So I added them in the same bank as the player backsprites.
So to finish inserting the graphics, do a search in main.asm for RedPicBack. You will eventually find something that looks like this:
RedPicBack:: INCBIN "pic/trainer/redb.pic"
OldManPic:: INCBIN "pic/trainer/oldman.pic"
So I just went ahead and added some lines to make it look like this:
RedPicBack:: INCBIN "pic/trainer/redb.pic"
LeafPicBack:: INCBIN "pic/trainer/leafb.pic"
OldManPic:: INCBIN "pic/trainer/oldman.pic"
LeafFishingTilesFront: INCBIN "gfx/leaf_fishing_tile_front.2bpp"
LeafFishingTilesBack: INCBIN "gfx/leaf_fishing_tile_back.2bpp"
LeafFishingTilesSide: INCBIN "gfx/leaf_fishing_tile_side.2bpp"
Now that we have all of the entries for the graphics added, now is a good time to save main.asm and attempt to compile the rom. If all goes well, the rom will compile normally with these extra graphics included (but nothing will call them yet). If you get errors saying that a bank is full, you will have to move something around to make it compile properly. If this happens, the cygwin terminal will tell you which line in main.asm it had a problem with, so you can go right to it and know which bank you need to make room in.
Step 3: Setting up the into.
Ok, so you got everything sorted properly so your rom will compile with the new graphics? Ok, let's start making it so we can use them!
The first thing you will want to do is add the menu that asks if you are a boy or a girl. The way I did this is by making a copy of the YesNoChoice routine, and having it reference the unused "North/West" menu string.
So, let's open up engine/menu/text_box.asm and find the menu strings. So go ahead and search for TwoOptionMenuStrings and eventually you will come to:
TwoOptionMenuStrings:
db 4,3,0
dw .YesNoMenu
db 6,3,0
dw .NorthWestMenu
db 6,3,0
dw .SouthEastMenu
db 6,3,0
dw .YesNoMenu
db 6,3,0
dw .NorthEastMenu
db 7,3,0
dw .TradeCancelMenu
db 7,4,1
dw .HealCancelMenu
db 4,3,0
dw .NoYesMenu
.NoYesMenu
db "NO"
next "YES@"
.YesNoMenu
db "YES"
next "NO@"
.NorthWestMenu
db "NORTH"
next "WEST@"
.SouthEastMenu
db "SOUTH"
next "EAST@"
.NorthEastMenu
db "NORTH"
next "EAST@"
.TradeCancelMenu
db "TRADE"
next "CANCEL@"
.HealCancelMenu
db "HEAL"
next "CANCEL@"
The only entries we are interested in right now are the ones with NorthWest. So we'll just edit these really quick so we come up with this:
TwoOptionMenuStrings:
db 4,3,0
dw .YesNoMenu
db 5,3,0
dw .BoyGirlMenu
db 6,3,0
dw .SouthEastMenu
db 6,3,0
dw .YesNoMenu
db 6,3,0
dw .NorthEastMenu
db 7,3,0
dw .TradeCancelMenu
db 7,4,1
dw .HealCancelMenu
db 4,3,0
dw .NoYesMenu
.NoYesMenu
db "NO"
next "YES@"
.YesNoMenu
db "YES"
next "NO@"
.BoyGirlMenu
db "BOY"
next "GIRL@"
.SouthEastMenu
db "SOUTH"
next "EAST@"
.NorthEastMenu
db "NORTH"
next "EAST@"
.TradeCancelMenu
db "TRADE"
next "CANCEL@"
.HealCancelMenu
db "HEAL"
next "CANCEL@"
Notice that I changed not only the text and label names, but I changed the numbers above the NorthWest choice. Those determine how large the box around the words will be, and by changing that value from 6 to 5, we make it so there isn't exta space after the Boy/Girl options.
Next, we'll need to declare a place to store the player's gender. That way when we add the code to call that menu choice, we have somewhere to save the result. So let's open up wram.asm and declare a new address!
If you search for wGameProgressFlagsEnd you'll find this:
wGameProgressFlagsEnd::
ds 56
These bytes that come after those flags are unused, but are still within the block of WRAM that gets stored in the .sav file when you save the game. So here is a good place to declare the new address we'll be making use of in the rest of this tutorial. So, just change the code above to look like this:
wGameProgressFlagsEnd::
wPlayerGender::
; $00 = male
; $01 = female
ds 1
; unused
ds 55
Now that we have these edited, you can save that file and move on to the actual intro. If you look in /engine/oak_speech.asm you will see that this is the main code for the intro. Scroll down to the bottom, and paste this:
; displays boy/girl choice
BoyGirlChoice::
call SaveScreenTilesToBuffer1
call InitBoyGirlTextBoxParameters
jr DisplayBoyGirlChoice
InitBoyGirlTextBoxParameters::
ld a, $1 ; loads the value for the unused North/West choice, that was changed to say Boy/Girl
ld [wTwoOptionMenuID], a
coord hl, 13, 7
ld bc, $80e
ret
DisplayBoyGirlChoice::
ld a, $14
ld [wTextBoxID], a
call DisplayTextBoxID
jp LoadScreenTilesFromBuffer1
This is a copy of the YesNoChoice routine, but modified to call our new Boy/Girl option instead.
Now that we have this subroutine added, we can scroll back up and write some new code to call it.
Near the top, you'll see a label called OakSpeech, and a few lines down, you'll see some code that looks like this:
xor a
ld [hTilesetType],a
ld a,[wd732]
bit 1,a ; possibly a debug mode bit
jp nz,.skipChoosingNames
Immediately under that, we'll add our new code for the gender selection. So immediately after the line about skipping the intro, we'll add this:
ld hl,BoyGirlText ; added to the same file as the other oak text
call PrintText ; show this text
call BoyGirlChoice ; added routine at the end of this file
ld a, [wCurrentMenuItem]
ld [wPlayerGender], a ; store player's gender. 00 for boy, 01 for girl
call ClearScreen ; clear the screen before resuming normal intro
Now if you scroll down a bit you will find something that looks like this:
ld hl,OakSpeechText2
call PrintText
call GBFadeOutToWhite
call ClearScreen
ld de,RedPicFront
ld bc,(Bank(RedPicFront) << 8) | $00
call IntroDisplayPicCenteredOrUpperRight
So we'll need to change this up a bit, so it can show the other pic if you are a girl. Make it look like this:
ld hl,OakSpeechText2
call PrintText
call GBFadeOutToWhite
call ClearScreen
ld de,RedPicFront
lb bc, Bank(RedPicFront), $00
ld a, [wPlayerGender] ; check gender
and a ; check gender
jr z, .NotLeaf1
ld de,LeafPicFront
lb bc, Bank(LeafPicFront), $00
.NotLeaf1:
call IntroDisplayPicCenteredOrUpperRight
Next, we can scroll down a bit more until we see:
.skipChoosingNames
call GBFadeOutToWhite
call ClearScreen
ld de,RedPicFront
lb bc, Bank(RedPicFront), $00
call IntroDisplayPicCenteredOrUpperRight
So we'll just change it to say:
.skipChoosingNames
call GBFadeOutToWhite
call ClearScreen
ld de,RedPicFront
lb bc, Bank(RedPicFront), $00
ld a, [wPlayerGender] ; check gender
and a ; check gender
jr z, .NotLeaf2
ld de,LeafPicFront
lb bc, Bank(LeafPicFront), $00
.NotLeaf2:
call IntroDisplayPicCenteredOrUpperRight
You can see where this is going, really. A lot of checking the gender and just making it load the girl's stuff instead, otherwise keep loading the boy's stuff. We're still not done with this file yet though. So scroll down a bit more until you see:
call DelayFrames
ld de,RedSprite
ld bc,(BANK(RedSprite) << 8) | $0C
ld hl,vSprites
call CopyVideoData
ld de,ShrinkPic1
ld bc,(BANK(ShrinkPic1) << 8) | $00
call IntroDisplayPicCenteredOrUpperRight
and make it look like this:
call DelayFrames
ld de,RedSprite
lb bc, BANK(RedSprite), $0C
ld a, [wPlayerGender] ; check gender
and a ; check gender
jr z, .NotLeaf3
ld de,LeafSprite
lb bc, BANK(LeafSprite), $0C
.NotLeaf3:
ld hl,vSprites
call CopyVideoData
ld de,ShrinkPic1
lb bc, BANK(ShrinkPic1), $00
call IntroDisplayPicCenteredOrUpperRight
Now, we'll scroll down a bit more until we see:
OakSpeechText3:
TX_FAR _OakSpeechText3
db "@"
Since we added a text string earlier when asking your gender, we'll need to set this up here so the script can find it. So we'll add:
BoyGirlText: ; This is new so we had to add a reference to get it to compile
TX_FAR _BoyGirlText
db "@"
under the OakSpeechText3 part. That's all we have to do in this file, but we're not quite done with the intro. (The intro is probably the most complicated part in all honesty).
Now we'll go ahead and save that file, and open /engine/oak_speech2.asm to keep working. At the top you will see:
ChoosePlayerName:
call OakSpeechSlidePicRight
ld de, DefaultNamesPlayer
call DisplayIntroNameTextBox
ld a, [wCurrentMenuItem]
and a
jr z, .customName
ld hl, DefaultNamesPlayerList
call GetDefaultName
ld de, wPlayerName
call OakSpeechSlidePicLeft
jr .done
and change that to this:
ChoosePlayerName:
call OakSpeechSlidePicRight
ld a, [wPlayerGender] ; Added gender check
and a
jr nz, .AreGirl ; Skip to girl names if you are a girl instead
ld de, DefaultNamesPlayer
call DisplayIntroNameTextBox
ld a, [wCurrentMenuItem]
and a
jr z, .customName
ld hl, DefaultNamesPlayerList
call GetDefaultName
ld de, wPlayerName
call OakSpeechSlidePicLeft
jr .done
.AreGirl ; Copy of the boy naming routine, just with girl's names
ld de, DefaultNamesGirl
call DisplayIntroNameTextBox
ld a, [wCurrentMenuItem]
and a
jr z, .customName
ld hl, DefaultNamesGirlList
call GetDefaultName
ld de, wPlayerName
call OakSpeechSlidePicLeft
jr .done ; End of new Girl Names routine
This adds a copy of the name routine that will instead call the girl's default names, which we will add in a minute. But first, we still have a little more to do.
If you will look at where it says:
.customName
ld hl, wPlayerName
xor a ; NAME_PLAYER_SCREEN
ld [wNamingScreenType], a
call DisplayNamingScreen
ld a, [wcf4b]
cp "@"
jr z, .customName
call ClearScreen
call Delay3
ld de, RedPicFront
ld b, BANK(RedPicFront)
call IntroDisplayPicCenteredOrUpperRight
.done
ld hl, YourNameIsText
jp PrintText
we'll need to change this, so that entering a custom name won't make you look like the boy when you get back to the intro. So we'll make the code look like this:
.customName
ld hl, wPlayerName
xor a ; NAME_PLAYER_SCREEN
ld [wNamingScreenType], a
call DisplayNamingScreen
ld a, [wcf4b]
cp "@"
jr z, .customName
call ClearScreen
call Delay3
ld de, RedPicFront
ld b, BANK(RedPicFront)
ld a, [wPlayerGender] ; Added gender check
and a ; Added gender check
jr z, .AreBoy3
ld de, LeafPicFront
ld b, BANK(LeafPicFront)
.AreBoy3
call IntroDisplayPicCenteredOrUpperRight
.done
ld hl, YourNameIsText
jp PrintText
Now then, we can get around to adding the name list for the girl player. So scroll down until you see:
IF _RED
DefaultNamesPlayer:
db "NEW NAME"
next "RED"
next "ASH"
next "JACK"
db "@"
DefaultNamesRival:
db "NEW NAME"
next "BLUE"
next "GARY"
next "JOHN"
db "@"
ENDC
and add a new entry for your girl names. It will look something like this:
IF _RED
DefaultNamesPlayer:
db "NEW NAME"
next "RED"
next "ASH"
next "JACK"
db "@"
DefaultNamesGirl:
db "NEW NAME"
next "SCARLET"
next "LEAF"
next "NICOLE"
db "@"
DefaultNamesRival:
db "NEW NAME"
next "BLUE"
next "GARY"
next "JOHN"
db "@"
ENDC
Obviously, you don't have to use the same names I came up with. Just make sure they aren't too long for a player name and you are fine.
So that sounds like we are done with the intro, right? Not quite. We only added the entries for the name menu. We still need to enter the actual list it will reference, because Red Version was weird. So we'll scroll down a little more until we find:
IF DEF(_RED)
DefaultNamesPlayerList:
db "NEW NAME@"
db "RED@"
db "ASH@"
db "JACK@"
DefaultNamesRivalList:
db "NEW NAME@"
db "BLUE@"
db "GARY@"
db "JOHN@"
ENDC
and add the girl list in there. It should look like this:
IF DEF(_RED)
DefaultNamesPlayerList:
db "NEW NAME@"
db "RED@"
db "ASH@"
db "JACK@"
DefaultNamesGirlList:
db "NEW NAME@"
db "SCARLET@"
db "LEAF@"
db "NICOLE@"
DefaultNamesRivalList:
db "NEW NAME@"
db "BLUE@"
db "GARY@"
db "JOHN@"
ENDC
You also need to add those entries for the girl's name lists to the IF_BLUE lists as well, if you plan on compiling as a version other than Red. That is it for the actual ASM on the intro, but we still need to open another file to finish the intro up. Remember that text string we made up to reference earlier in the gender select menu? Yeah, we have to actually put that string into the game.
So let's save that file and open up /text/oakspeech.asm and scroll down to the bottom of the file. There we can add an entry that looks like this:
_BoyGirlText::
text "Play as a boy, or"
line "as a girl?"
done
Then just save it and you're done with the intro. At this point, I would recommend compiling it again and testing the intro, just to make sure everything worked the way you wanted it to..
Step 4: Setting up the player's overworld sprites.
Ok, so you got the intro working nicely? Great! Time to move on to getting the game to show the proper sprites when you are fishing as the girl.
So let's go ahead and open up /engine/overworld/player_animations.asm and have a look. You'll want to search for FishingAnim: to find what you are looking for. It will look like this:
FishingAnim:
ld c, 10
call DelayFrames
ld hl, wd736
set 6, [hl] ; reserve the last 4 OAM entries
ld de, RedSprite
ld hl, vNPCSprites
lb bc, BANK(RedSprite), $c
call CopyVideoData
ld a, $4
ld hl, RedFishingTiles
call LoadAnimSpriteGfx
You'll want to replace that with this:
FishingAnim:
ld c, 10
call DelayFrames
ld hl, wd736
set 6, [hl] ; reserve the last 4 OAM entries
ld a, [wPlayerGender] ; added gender check
and a ; added gender check
jr z, .BoySpriteLoad
ld de, LeafSprite
ld hl, vNPCSprites
ld bc, (BANK(LeafSprite) << 8) + $0c
jr .KeepLoadingSpriteStuff
.BoySpriteLoad
ld de, RedSprite
ld hl, vNPCSprites
lb bc, BANK(RedSprite), $c
.KeepLoadingSpriteStuff
call CopyVideoData
ld a, [wPlayerGender] ; added gender check
and a ; added gender check
jr z, .BoyTiles ; skip loading Leaf's stuff if you're Red
ld a, $4
ld hl, LeafFishingTiles
jr .ContinueRoutine ; go back to main routine after loading Leaf's stuff
.BoyTiles ; alternately, load Red's stuff
ld a, $4
ld hl, RedFishingTiles
.ContinueRoutine
call LoadAnimSpriteGfx
Now I know, I know. That looks like a mess. But it's really just more of the same stuff we did in the intro. All we've done is copy part of it to make an alternate version it can load to get the girl's sprite and fishing tiles. Speaking of those fishing tiles, we'll need to add that little table it is referencing.
So let's scroll down a bit until we see:
RedFishingTiles:
dw RedFishingTilesFront
db 2, BANK(RedFishingTilesFront)
dw vNPCSprites + $20
dw RedFishingTilesBack
db 2, BANK(RedFishingTilesBack)
dw vNPCSprites + $60
dw RedFishingTilesSide
db 2, BANK(RedFishingTilesSide)
dw vNPCSprites + $a0
dw RedFishingRodTiles
db 3, BANK(RedFishingRodTiles)
dw vNPCSprites2 + $7d0
We'll want to add a new table under it, so that it will look like this:
RedFishingTiles:
dw RedFishingTilesFront
db 2, BANK(RedFishingTilesFront)
dw vNPCSprites + $20
dw RedFishingTilesBack
db 2, BANK(RedFishingTilesBack)
dw vNPCSprites + $60
dw RedFishingTilesSide
db 2, BANK(RedFishingTilesSide)
dw vNPCSprites + $a0
dw RedFishingRodTiles
db 3, BANK(RedFishingRodTiles)
dw vNPCSprites2 + $7d0
LeafFishingTiles: ; newly added table of Leaf's sprites
dw LeafFishingTilesFront
db 2, BANK(LeafFishingTilesFront)
dw vNPCSprites + $20
dw LeafFishingTilesBack
db 2, BANK(LeafFishingTilesBack)
dw vNPCSprites + $60
dw LeafFishingTilesSide
db 2, BANK(LeafFishingTilesSide)
dw vNPCSprites + $a0
dw RedFishingRodTiles
db 3, BANK(RedFishingRodTiles)
dw vNPCSprites2 + $7d0
You'll notice that leaf's table still calls one of the original graphics that Red used. I don't see a point in making an identical copy of the actual fishing pole tiles, only the part that is the actual player, so her table calls the same fishing rod sprite the boy did.
Now to move on to your walking and cycling sprites. You'll open /home/overworld.asm and take a look at it for this part. You'll want to find the routine called LoadWalkingPlayerSpriteGraphics for this part. You'll eventually find a routine that looks like this:
LoadWalkingPlayerSpriteGraphics::
ld de,RedSprite
ld hl,vNPCSprites
jr LoadPlayerSpriteGraphicsCommon
LoadSurfingPlayerSpriteGraphics::
ld de,SeelSprite
ld hl,vNPCSprites
jr LoadPlayerSpriteGraphicsCommon
LoadBikePlayerSpriteGraphics::
ld de,RedCyclingSprite
ld hl,vNPCSprites
And we'll just change this up a little to look like this:
LoadWalkingPlayerSpriteGraphics::
ld de,RedSprite
ld a, [wPlayerGender]
and a
jr z, .AreGuy1
ld de,LeafSprite
.AreGuy1
ld hl,vNPCSprites
jr LoadPlayerSpriteGraphicsCommon
LoadSurfingPlayerSpriteGraphics::
ld de,SurfingLapras
ld hl,vNPCSprites
jr LoadPlayerSpriteGraphicsCommon
LoadBikePlayerSpriteGraphics::
ld de,RedCyclingSprite
ld a, [wPlayerGender]
and a
jr z, .AreGuy2
ld de,LeafCyclingSprite
.AreGuy2
ld hl,vNPCSprites
Now you can save this file, because that is all we had to do in here. If you were to scroll down a little more, you would see that we didn't mess with the part of the code that loaded which bank these sprites were in. That is why we kept Red and Leaf in the same bank when we inserted their sprites. It just seemed simpler to do it that way to me. As with all of the other sections, you'll probably want to stop and compile the rom again to make sure everything went ok before moving on.
Step 5: Adding The Girl's Backsprite.
This section will be relatively short compared to the others, because there isn't much to do here. We'll open up engine/battle/core.asm for this part.
Search until you find LoadPlayerBackPic: and see that it looks like this:
LoadPlayerBackPic:
ld a, [wBattleType]
dec a ; is it the old man tutorial?
ld de, RedPicBack
jr nz, .next
ld de, OldManPic
.next
You'll just want to change this to be:
LoadPlayerBackPic:
ld a, [wBattleType]
dec a
ld de, OldManPic
jr z, .next
ld a, [wPlayerGender]
and a
jr z, .RedBack
ld de, LeafPicBack
jr .next
.RedBack
ld de, RedPicBack
.next
This just reorganises that a bit and adds in the check for the girl's backsprite. This also assumes that all 3 backpics are stored in the same bank, so make sure you did that unless you want to mess with the routine more on your own to allow them to be in different banks.
As always, you'll probably want to save and compile to test this before going on.
Step 6: Adding The Girl To The Hall Of Fame.
For this step, you'll want to open /engine/hall_of_fame.asm and search for HoFLoadPlayerPics: to get to the function we need. It should look something like this:
HoFLoadPlayerPics:
ld de, RedPicFront
ld a, BANK(RedPicFront)
call UncompressSpriteFromDE
ld hl, sSpriteBuffer1
ld de, sSpriteBuffer0
ld bc, $310
call CopyData
ld de, vFrontPic
call InterlaceMergeSpriteBuffers
ld de, RedPicBack
ld a, BANK(RedPicBack)
call UncompressSpriteFromDE
We'll want to edit that so it looks like this:
HoFLoadPlayerPics:
ld a, [wPlayerGender] ; New gender check
and a ; New gender check
jr nz, .GirlStuff1
ld de, RedPicFront
ld a, BANK(RedPicFront)
jr .Routine ; skip the girl stuff and go to main routine
.GirlStuff1
ld de, LeafPicFront
ld a, BANK(LeafPicFront)
.Routine ; resume original routine
call UncompressSpriteFromDE
ld hl, sSpriteBuffer1
ld de, sSpriteBuffer0
ld bc, $310
call CopyData
ld de, vFrontPic
call InterlaceMergeSpriteBuffers
ld a, [wPlayerGender] ; new gender check
and a ; new gender check
jr nz, .GirlStuff2
ld de, RedPicBack
ld a, BANK(RedPicBack)
jr .routine2 ; skip the girl stuff and continue original routine if guy
.GirlStuff2
ld de, LeafPicBack
ld a, BANK(LeafPicBack)
.routine2 ; original routine
call UncompressSpriteFromDE
This will change it so it shows the girl's front and back sprites when your team is entered in the hall of fame. Save it and you are done with this step.
Step 7: Adding The Girl To The Trainer Card
This is the final step in the tutorial. You'll want to open up /engine/menu/start_sub_menus.asm for this part. Search for the function DrawTrainerInfo: and you should see something like this:
DrawTrainerInfo:
ld de,RedPicFront
lb bc, BANK(RedPicFront), $01
predef DisplayPicCenteredOrUpperRight
So we'll just change that to:
DrawTrainerInfo:
ld de,RedPicFront
lb bc, BANK(RedPicFront), $01
ld a, [wPlayerGender]
and a
jr z, .AreBoy
ld de, LeafPicFront
lb bc, BANK(LeafPicFront), $01
.AreBoy
predef DisplayPicCenteredOrUpperRight
And you should be all set! Save it, compile it, and give it a test. If everything went as planned (and assuming I didn't accidentally leave anything out when writing this) you should now have a fully functioning gender selection system in place in Pokemon Red. Let me know if you have any problems and I will try my best to help you figure them out.
Credits:
IIMarckus, Kanzure, comet, Danny-E33, Sanky, and everyone else who contributed to the Pokered disassembly project.
Danny-E33 - Getting me interested in Pokered, and for the Gen II backsprite routine I used in that video
Pia Carrot - Talking about Pokered a lot at PHO and originally asking me to write this tutorial.
ないすべての情報が必要です。- Asking about this on Discord until I updated it.
Last edited by Luna (2017-08-03 03:07:09)
I am not very active on this forum. I only pop in from time to time.
Offline
Wow, this is pretty awesome. Very thorough tutorial. I wonder why the North/West menu ever existed in the first place.
Offline
My best guess is that the unused directional menus would somehow have been used in the Safari Zone, but as to how, I have no idea.
I am not very active on this forum. I only pop in from time to time.
Offline
Perhaps a random NPC wondering which way you took to get to Fuchsia City?
My hacks: Pokémon Maize, Pokémon Red: Battle Factory
Offline
wow
My Web:
http://www.facebook.com/ttar1romhacker
My Hacks:
Pokemon Plasma(Hack of gold currently in progress)
Do not underestimate the power of a beginner hacker.
Offline
Very nice.
Any idea how far off this throws some of the other established data?
Pokemon: Project Neo A Pokemon hack 15 years in the making...
Offline
Probably a lot. But it is irrelevant.
Offline
I've got a lot of tools, somewhat old but useful, that I'm comfortable with hacking the rom. Getting more comfortable with the ASM directly but, old dogs and new tricks as it were.
Pokemon: Project Neo A Pokemon hack 15 years in the making...
Offline
By the way, I've updated this slightly to hopefully make it compatible with current versions of Pokered. I changed the Boy/Girl Menu routine to use "wTextBoxID" instead of "wd125" like the current versions do.
I am not very active on this forum. I only pop in from time to time.
Offline
That's all well and good, but...
xor a
ld [$FFD7],a
ld a,[wd732]
bit 1,a ; XXX when is bit 1 set?
jp nz,Func_61bc ; easter egg: skip the intro
Wordpad, which I am largely using to edit the ASM code (I've succeeded thus far in using Wordpad to anti-censor that scene early on in Viridian City with the old man who teaches you how to catch Pokémon–originally, he was drunk instead of not having had his coffee), searched the entirety of /engine/oak_speech.asm and couldn't find it. That is where I'm lost. Heck, I even checked the original file on Github and couldn't find it. (And yes, I'm positive I'm following your instructions.)
Offline
Sorry for the double post, but whenever I try to compile the ROM after having done everything up to Step 3, I get the following error:
"Unknown symbol 'PlayMusic'"
Am I doing something wrong?
Offline
ld hl, wd798 ; load ram address of Gender
This seems to be the only thing not working for me so far. wd798 does not exist in my version. Any ideas what the alternative would be?
EDIT: Worked it out. Just had to change it to $14.
Last edited by megamctaco (2015-10-25 10:22:06)
Offline
If you mean that you changed it to ld hl, $14, then that is just so wrong. Replace it with ld hl, $d798 if anything.
Offline
If you mean that you changed it to ld hl, $14, then that is just so wrong. Replace it with ld hl, $d798 if anything.
All that got me was a bunch of "Expression must be 8-bit" errors.
As it stands, I can compile Red but not Blue, as "GetDefaultName" is having trouble with Blue version only for some reason. EDIT: Female sprite loads when either boy or girl are selected.
I should mention, I am up to step 4 but can't seem to compile after changing player_animations.asm and overworld.asm. Either a ROMX error or ROM0 too large error.
Last edited by megamctaco (2015-10-25 11:22:14)
Offline
The romx error means you are trying to put more in a bank than you have room for.
The issue with the name not being found is the problem with me writing this tutorial on an older version of pokered, and label/variable/etc names getting changed over time. I'll look up the proper name and update this after I have my coffee.
EDIT: Ok, I see what is causing so much trouble here. Apparently some time in the past, they stopped declaring event bytes manually, and made up a macro thing for it and just labeled the start of that block of data with an actual label, not each byte. In the original tutorial, we were just using one of the unused bits in the byte that kept up with trainers in one level of Cinnabar Mansion. It isn't the best way to do it, but it was convenient at the time since it was unused and would be saved properly. Now that the save routines have been vastly improved, it would be simpler to just add a new entry in wram.asm for wPlayerGender and reference that. At some point I'll get around to properly updating this tutorial to use the current label names, and to use a custom ram address instead of trying into that trainer byte (because what if you wanted to add more trainers to that map?)
Also, I noticed that for some reason I was still using the hard coded address $cc26 instead of wCurrentMenuItem like I should be when checking what your answer was in the intro. That's probably why it was always setting you as the girl when you tried it. If you shifted data around in ram it's probably you moved stuff so labels worked fine but the hardcoded address was probably pointing to the wrong thing or something.
As a quick fix version of how to fix some of this:
In engine/oak_speech.asm the block of code you are looking for now looks like:
xor a
ld [hTilesetType],a
ld a,[wd732]
bit 1,a ; possibly a debug mode bit
jp nz,.skipChoosingNames
so you would put the code for choosing the gender between that and the part about loading oak's pic.
And where you see:
ld a, [$cc26]
you would change it to:
ld a, [wCurrentMenuItem]
Then you would replace any instance of:
wd798
with:
wPlayerGender
and then you would need to go into wram.asm, and somewhere between "wMainDataStart::" and "wMainDataEnd::" you would need to add
wPlayerGender::
ds 1
And that aught to take care of that. As for issues with running out of space in rom banks, does it give you any information about which bank is full? You shouldn't have issues with any of the code, so it's probably an issue with graphics somewhere, but hard to say without knowing what all is going on.
Last edited by Luna (2015-10-25 15:17:46)
I am not very active on this forum. I only pop in from time to time.
Offline
OK, I'm doing this step by step, and when I added Leaf's overworld walking and cycling sprites, I expected errors and got "Unable to load fixed ROMX section into bank $05". When I then moved two sets of overworld sprites into a different bank to compensate, I got–guess what–"Unknown symbol 'PlayMusic'". Any idea what's causing this?
Offline
If you are following the tutorial correctly, I can think of absolutely no reason why it would claim to be unable to find "PlayMusic" because that doesn't even begin to make sense in this situation o.O Are you sure all you did was move the INCLUDE lines for a couple of overworld sprites to cause that to happen?
I am not very active on this forum. I only pop in from time to time.
Offline
No, I'm pretty sure all I did was cut and paste the lines for the Giovanni and Rocket sprites to NPC Sprites 1, following the example in the tutorial, and suddenly Cygwin's all "Unknown symbol 'PlayMusic'" for reasons I can't explain either.
Offline
Moving those sprites should have absolutely zero impact on the PlayMusic routine, so something has to be up. Does it give any clue as to which file is throwing that error? PlayMusic is called all over the place. I'm guessing that maybe you accientally added a linebreak somewhere so it has a line starting with PlayMusic instead of "call PlayMusic" so it is saying "whoa, PlayMusic isn't a command or a macro, idk what to do with this". I could be wrong, but that's the only thing coming to my mind as making sense at the moment.
EDIT: Also, which text editor are you using to edit the .asm files? I ask because regular notepad tends to have difficulty behaving properly when working with these .asm files, and notepad++ is greatly preferred since it doesn't do weird things like try to change linebreaks and stuff the way normal Notepad does.
Last edited by Luna (2015-10-26 02:40:44)
I am not very active on this forum. I only pop in from time to time.
Offline
When I enter:
cd pokered
make
I get this:
rgblink -n pokered.sym -o pokered.gbc red/audio.o red/main.o red/text.o red/wram.o
C:\cygwin64\usr\local]bin\rgblink.exe: Unknown symbol 'PlayMusic'
Makefile:79: recipe for target 'pokered.gbc' failed
make: *** [pokered.gbc] Error 1
There's the problem: it didn't give me any obvious clues, and I couldn't find PlayMusic anywhere in the main.asm file.
Can you replicate this error with the current version of Pokered by following each step of your own tutorial, right up to and including the point where the Giovanni and Rocket sprites are moved to NPC Sprites 1? For all I know, I might very well be the first to encounter this error while trying to insert the female player character.
Last edited by Fotomac (2015-10-26 02:47:59)
Offline
I'm not really in a place where I can just do that right now. But yeah, that error message is precisely as unhelpful as I was afraid it would be :/
Again, what text editor are you using to edit the .asm files? Because I do remember another user having similarly baffling and unrelated errors when using Notepad instead of Notepad++ because Notepad was screwing up the file's formatting and causing it to feed a bunch of jibberish to the compiler.
I am not very active on this forum. I only pop in from time to time.
Offline
I didn't use WordPad this time; I was forced to use Notepad on account of WordPad feeding me the following bull:
You are about to save the document in a Text-Only format, which
will remove all formatting. Are you sure you want to do this?To save in other format, click No.
After which, should I click No, I get directed to the Save As window, which gives me the option to save this in any of six types of documents none of which are ASM.
Offline
I highly recommend you download and use Notepad++. It is free, easy to setup, has syntax highlighting built in so the code is more readable, and it doesn't screw up formatting.
I am not very active on this forum. I only pop in from time to time.
Offline
Made those changes you suggested and now I'm getting a "Value must be 8-bit" when I changed wd798 to wPlayerGender.
I tried changing that to [wPlayerGender] and got a syntax error.
Offline
Problem appears to be solved; it would appear the Notepad save changed the font to MS Mincho (which I am guessing Cygwin or rgblink or whatever stumbled across the error didn't recognize), so I changed it back to Courier New and saved; the "Unknown symbol 'PlayMusic'" error didn't appear after that, so it would appear Notepad was the responsible party.
Offline