Skip to content

Non binary gender selection

RainbowMetalPigeon edited this page Aug 7, 2023 · 2 revisions

First, I want to say that this tutorial is not originally mine. The tutorial in its original binary form was originally done by Mateo, adapted by veganlies2me, and edited by DavidWhite-Vulpin, me, and mirko93s.

Preliminary steps

I would strongly recommend to implement the picture system improvement tutorial and the tutorial on how to free some space in the Home BANK. If you end up having issues with Bank 1E being too full, you may take a look at the corresponding tutorial. I can't guarantee that doing so will make everything work smoothly, but I can almost guarantee that not doing that is very likely to give you some memory-related errors.

Actual tutorial

First thing you have to do is to add the graphics for the other genders (welp, ok, the very first thing is probably to draw said graphic, but that's beyond the scope of this tutorial): the front sprite, the back sprite, the walking sprites, the cycling sprites, and the fishing sprites. In the following we'll use "Green" for the female character and "Yellow" for the enby one. Then insert them in these folders:

/gfx/player/green.png  (front sprite)
/gfx/player/greenb.png (back sprite)
/gfx/player/yellow.png  (front sprite)
/gfx/player/yellowb.png (back sprite)

/gfx/sprites/green.png (walking sprites)
/gfx/sprites/green_bike.png (cycling sprites)
/gfx/sprites/yellow.png (walking sprites)
/gfx/sprites/yellow_bike.png (cycling sprites)

(fishing sprites)
/gfx/overworld/green_fish_back.png
/gfx/overworld/green_fish_front.png
/gfx/overworld/green_fish_side.png
/gfx/overworld/yellow_fish_back.png
/gfx/overworld/yellow_fish_front.png
/gfx/overworld/yellow_fish_side.png

Now we have to include the sprites. Open gfx/player.asm and modify the following:

RedPicFront:: INCBIN "gfx/player/red.pic"
+GreenPicFront:: INCBIN "gfx/player/green.pic"
+YellowPicFront:: INCBIN "gfx/player/yellow.pic"
ShrinkPic1::  INCBIN "gfx/player/shrink1.pic"
ShrinkPic2::  INCBIN "gfx/player/shrink2.pic"

Then open gfx/pics.asm and modify it as follows:

SECTION "Pics 7", ROMX

RedPicBack::       INCBIN "gfx/player/redb.pic"
+GreenPicBack::     INCBIN "gfx/player/greenb.pic"
+YellowPicBack::     INCBIN "gfx/player/yellowb.pic"
OldManPicBack::    INCBIN "gfx/battle/oldmanb.pic"
ProfOakPicBack::   INCBIN "gfx/battle/prof.oakb.pic"

After following the aforementioned tutorial about improving the picture system, I created this Section just for the backpics, but the system is now quite flexible and you can modify it according to your needs. Whatever you do, keep these five backsprites together in the same Section.

Then, open gfx/sprites.asm and add these lines of code:

RedBikeSprite::          INCBIN "gfx/sprites/red_bike.2bpp"
RedSprite::              INCBIN "gfx/sprites/red.2bpp"
+GreenBikeSprite::        INCBIN "gfx/sprites/green_bike.2bpp"
+GreenSprite::            INCBIN "gfx/sprites/green.2bpp"
+YellowBikeSprite::        INCBIN "gfx/sprites/yellow_bike.2bpp"
+YellowSprite::            INCBIN "gfx/sprites/yellow.2bpp"

It is important that Red's, Green's, and Yellow's sprites are in the same Section. This may give you memory issues; I solved them by moving all sprites between Lance and Seel included to a new Section:

[...]
BrunetteGirlSprite::     INCBIN "gfx/sprites/brunette_girl.2bpp"

SECTION "NPC Sprites 3", ROMX

OfficerJennySprite::     INCBIN "gfx/sprites/officer_jenny.2bpp"
[...]
JamesSprite::            INCBIN "gfx/sprites/james.2bpp"

+SECTION "NPC Sprites 4", ROMX

LanceSprite::            INCBIN "gfx/sprites/lance.2bpp"
[...]
SeelSprite::             INCBIN "gfx/sprites/seel.2bpp"

Now open gfx/fishing.asm and add:

RedFishingTilesFront: INCBIN "gfx/overworld/red_fish_front.2bpp"
RedFishingTilesBack:  INCBIN "gfx/overworld/red_fish_back.2bpp"
RedFishingTilesSide:  INCBIN "gfx/overworld/red_fish_side.2bpp"
RedFishingRodTiles:   INCBIN "gfx/overworld/fishing_rod.2bpp"
+GreenFishingTilesFront: INCBIN "gfx/overworld/green_fish_front.2bpp"
+GreenFishingTilesBack:  INCBIN "gfx/overworld/green_fish_back.2bpp"
+GreenFishingTilesSide:  INCBIN "gfx/overworld/green_fish_side.2bpp"
+YellowFishingTilesFront: INCBIN "gfx/overworld/yellow_fish_front.2bpp"
+YellowFishingTilesBack:  INCBIN "gfx/overworld/yellow_fish_back.2bpp"
+YellowFishingTilesSide:  INCBIN "gfx/overworld/yellow_fish_side.2bpp"

Alright! We included the graphics, but we need to make use of them, to add the option to not be a boy. We'll start by editing an unused text box to suit our needs. This is done in two steps (both of them are brand-new of this tutorial, so please inform me if there's any bug): first open constants/menu_constants.asm and edit the following:

	const MON_SPRITE_POPUP                  ; $11
-	const JP_AH_MENU_TEMPLATE               ; $12
+	const BOY_GIRL_NO                       ; $12 new for gender non-binary selection
	const MONEY_BOX                         ; $13

Now that we've declared the new menu template, let's give it an X/Y position, a size, a text placement, and a text content. (fwiw, to my understanding the X and Y positions are taken with respect to a reference frame that has its origin in the top-left corner of the screen, and the values are defined positive, i.e. X increases going right and Y increases going down. I think the max values for X and Y is 19 (or 20? Anyway it's not terribly important for our tutorial)) Open data/text_boxes.asm and modify it as follows:

	text_box_text MONEY_BOX_TEMPLATE,                11,  0, 19,  2, MoneyText,               13,  0
-	text_box_text JP_AH_MENU_TEMPLATE,                7,  6, 11, 10, JapaneseAhText,           8,  8
+	text_box_text BOY_GIRL_NO,                       13,  6, 19, 12, BoyGirlNoText,           15,  7
	text_box_text JP_POKEDEX_MENU_TEMPLATE,          11,  8, 19, 17, JapanesePokedexMenu,     12, 10

[...]

-JapaneseAhText:
-	db "アッ!@"
+BoyGirlNoText:
+	db   "BOY"
+	next "GIRL"
+	next "NO@"

Now we need to allocate a wram byte that will keep track of our gender (or lack-of). Open ram/wram.asm and edit:

	wGameProgressFlagsEnd::

-	ds 56
+wPlayerGender::
+	; $00 = male
+	; $01 = female
+	; $02 = enby
+	ds 1
+	
+; unused
+	ds 55

Open engine/movie/oak_speech/oak_speech.asm. Scroll to the very bottom and add these lines of code:

; displays boy/girl choice
BoyGirlChoice::
	call SaveScreenTilesToBuffer1
	jr DisplayBoyGirlNoChoice

DisplayBoyGirlNoChoice::
	ld a, BOY_GIRL_NO
	ld [wTextBoxID], a
	call DisplayTextBoxID
	ld hl, wTopMenuItemY
	ld a, 7
	ld [hli], a ; top menu item Y
	ld a, 14
	ld [hli], a ; top menu item X
	xor a
	ld [hli], a ; current menu item ID
	inc hl
	ld a, $2
	ld [hli], a ; wMaxMenuItem
	ld a, B_BUTTON | A_BUTTON
	ld [hli], a ; wMenuWatchedKeys
	xor a
	ld [hl], a ; wLastMenuItem
	call HandleMenuInput
	bit BIT_B_BUTTON, a
	jr nz, .defaultOption ; if B was pressed, assign enby
; A was pressed
	call PlaceUnfilledArrowMenuCursor
	ld a, [wCurrentMenuItem]
	jp LoadScreenTilesFromBuffer1
.defaultOption
	ld a, $02
	ld [wCurrentMenuItem], a
	jp LoadScreenTilesFromBuffer1

This will load the text box we defined earlier, where the options will appear. Scroll up to the OakSpeech: label and find these lines of code:

	xor a
	ldh [hTileAnimations], a
	ld a, [wd732]
	bit 1, a ; possibly a debug mode bit
	jp nz, .skipChoosingNames

Under those lines of code add these lines of code:

	jp nz, .skipChoosingNames
+	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, 02 for enby
+   	call ClearScreen ; clear the screen before resuming normal intro

Search these lines of code, they're a dozen lines below:

	ld hl, OakSpeechText2
	call PrintText
	call GBFadeOutToWhite
	call ClearScreen
	ld de, RedPicFront
	lb bc, BANK(RedPicFront), $00
	call IntroDisplayPicCenteredOrUpperRight

Edit them:

	ld hl, OakSpeechText2
	call PrintText
	call GBFadeOutToWhite
	call ClearScreen
	ld de, RedPicFront
	lb bc, BANK(RedPicFront), $00 ; this is sometimes done in two lines, loading in b and c separately
-	call IntroDisplayPicCenteredOrUpperRight
+	ld a, [wPlayerGender] 	; load gender
+	and a      				; check gender - and a is equivalent to `cp a, 0` (but faster)
+						; if a=0->gender=male, ergo jump to the vanilla part of the code
+	jr z, .ContinueWithOakIntro1
+	cp a, 2					; check gender: if a=2->gender=enby, jump to the yellow subroutine, otherwise continue below
+	jp z, .LoadYellowPicFront1
+	ld de, GreenPicFront
+	lb bc, BANK(GreenPicFront), $00
+	jr .ContinueWithOakIntro1
+.LoadYellowPicFront1
+	ld de, YellowPicFront
+	lb bc, BANK(YellowPicFront), $00
+.ContinueWithOakIntro1:
+	call IntroDisplayPicCenteredOrUpperRight
	call MovePicLeft

Scroll down until you see:

.skipChoosingNames
	call GBFadeOutToWhite
	call ClearScreen
	ld de, RedPicFront
	lb bc, BANK(RedPicFront), $00
	call IntroDisplayPicCenteredOrUpperRight

Edit these too:

.skipChoosingNames
	call GBFadeOutToWhite
	call ClearScreen
	ld de, RedPicFront
	lb bc, Bank(RedPicFront), $00
-	call IntroDisplayPicCenteredOrUpperRight
+	ld a, [wPlayerGender] ; check gender
+	and a      ; check gender -> if male, jump to vanilla code
+	jr z, .ContinueWithOakIntro2
+	cp a, 2
+	jp z, .LoadYellowPicFront2
+	ld de, GreenPicFront
+	lb bc, BANK(GreenPicFront), $00
+	jr .ContinueWithOakIntro2
+.LoadYellowPicFront2
+	ld de, YellowPicFront
+	lb bc, BANK(YellowPicFront), $00
+.ContinueWithOakIntro2:
+	call IntroDisplayPicCenteredOrUpperRight
	call GBFadeInFromWhite

Search now these lines of code:

	call DelayFrames
	ld de, RedSprite
	ld hl, vSprites
	lb bc, BANK(RedSprite), $0C
	call CopyVideoData
	ld de, ShrinkPic1
	lb bc, BANK(ShrinkPic1), $00
	call IntroDisplayPicCenteredOrUpperRight

And modify:

	call DelayFrames
   	ld de,RedSprite
	ld hl, vSprites
	lb bc, BANK(RedSprite), $0C
-	call CopyVideoData
-	ld de, ShrinkPic1
-	lb bc, BANK(ShrinkPic1), $00
-	call IntroDisplayPicCenteredOrUpperRight
+	ld a, [wPlayerGender] ; check gender
+	and a      ; check gender -> if male, jump to vanilla code
+	jr z, .ContinueWithOakIntro3
+	cp a, 2
+	jp z, .LoadYellowPicFront3
+	ld de, GreenSprite
+	lb bc, BANK(GreenSprite), $0C
+	jr .ContinueWithOakIntro3
+.LoadYellowPicFront3
+	ld de, YellowSprite
+	lb bc, BANK(YellowSprite), $0C
+.ContinueWithOakIntro3:
	ld hl, vSprites

What we just did is added some gender checking routines, so the game will load the sprites for the other gender if that gender is selected.

Below OakSpeechText3:, add these lines:

+BoyGirlText: ; This is new so we had to add a reference to get it to compile
+	text_far _BoyGirlText
+	text_end

We're done with the first oakspeech file! Let's move onto engine/movie/oak_speech/oakspeech2.asm. We will edit these lines of code at the top:

ChoosePlayerName:
	call OakSpeechSlidePicRight
-	ld de, DefaultNamesPlayer
-	call DisplayIntroNameTextBox
+	ld a, [wPlayerGender] ; load gender
+	cp a, $01
+	jr z, .AreGirl ; Skip to girl names if you are girl instead
+	cp a, $02
+	jr z, .AreEnby ; Skip to enby names if you are enby instead
+	ld de, DefaultNamesBoy
+	call DisplayIntroNameTextBox
	ld a, [wCurrentMenuItem]
	and a
	jr z, .customName
-	ld hl, DefaultNamesPlayerList
+	ld hl, DefaultNamesBoyList
	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
+.AreEnby ; Copy of the boy naming routine, just with enby's names
+	ld de, DefaultNamesEnby
+	call DisplayIntroNameTextBox
+	ld a, [wCurrentMenuItem]
+	and a
+	jr z, .customName
+	ld hl, DefaultNamesEnbyList
+	call GetDefaultName
+	ld de, wPlayerName
+	call OakSpeechSlidePicLeft
+	jr .done ; End of new Enby Names routine
.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
+	ld a, [wPlayerGender] ; Added gender check
+	and a      ; Added gender check
+	jr z, .ContinueWithRoutine
+	cp a, $02
+	jr z, .LoadYellowPicFront
+	ld de, GreenPicFront
+	ld b, BANK(GreenPicFront)
+.LoadYellowPicFront
+	ld de, YellowPicFront
+	ld b, BANK(YellowPicFront)
+.ContinueWithRoutine
+	call IntroDisplayPicCenteredOrUpperRight
+.done
+	ld hl, YourNameIsText
+	jp PrintText

All the above edits are to load the other default names. Now let's add some names to be loaded. Open data/player_names.asm and add (just examples):

-DefaultNamesPlayer:
+DefaultNamesBoy:
	db   "NEW NAME"
	next "RED"
	next "ASH"
	next "JACK"
	db   "@"

+DefaultNamesGirl:
+	db   "NEW NAME"
+	next "GREEN"
+	next "LEAF"
+	next "JULIET"
+	db   "@"

+DefaultNamesEnby:
+	db   "NEW NAME"
+	next "YELLOW"
+	next "AMARILLO"
+	next "ALEXYS"
+	db   "@"

DefaultNamesRival:
	db   "NEW NAME"
	next "BLUE"
	next "GARY"
	next "JOHN"
	db   "@"

We do pretty much the same thing on data/player_names_list.asm:

-DefaultNamesPlayerList:
+DefaultNamesBoyList
	db "NEW NAME@"
	db "RED@"
	db "ASH@"
	db "JACK@"

+DefaultNamesGirlList:
+	db "NEW NAME@"
+ 	db "GREEN@"
+	db "LEAF@"
+	db "JULIET@"

+DefaultNamesEnbyList:
+	db "NEW NAME@"
+	db "YELLOW@"
+	db "AMARILLO@"
+	db "ALEXYS@"

DefaultNamesRivalList:
	db "NEW NAME@"
	db "BLUE@"
	db "GARY@"
	db "JOHN@"

We go to data/text/text_2.asm and add these lines of code:

+_BoyGirlText::
+	text "Play as a boy or"
+	line "as a girl?"
+	done

Hurray! We added the option on the intro! Now let's add the girl and enby sprites in the main game. Open engine/overworld/player_animations.asm and look for FishingAnim: and edit these lines of code:

FishingAnim:
	ld c, 10
	call DelayFrames
	ld hl, wd736
	set 6, [hl] ; reserve the last 4 OAM entries
	ld hl, vNPCSprites ; ???
-	ld de, RedSprite
-	ld b, BANK(RedSprite)
-	ld c, 12
-	call CopyVideoData
-	ld a, $4
-	ld hl, RedFishingTiles
-	call LoadAnimSpriteGfx
+	ld a, [wPlayerGender]	; load gender
+	and a					; check if gender=male
+	jr z, .BoySpriteLoad
+	cp a, 2		; check if enby
+	jr z, .EnbySpriteLoad
+	ld de, GreenSprite
+	ld hl, vNPCSprites
+	ld bc, (BANK(GreenSprite) << 8) + $0c
+	jr .KeepLoadingSpriteStuff
+.EnbySpriteLoad
+	ld de, YellowSprite
+	ld hl, vNPCSprites
+	ld bc, (BANK(YellowSprite) << 8) + $0c
+	jr .KeepLoadingSpriteStuff
+.BoySpriteLoad
+	ld de, RedSprite
+	ld hl, vNPCSprites
+	lb bc, BANK(RedSprite), $c
+.KeepLoadingSpriteStuff
+	call CopyVideoData
+	ld a, [wPlayerGender]	; load gender
+	and a      				; check if gender=male
+	jr z, .BoyTiles ; skip loading Green's stuff if you're Red
+	cp a, 2
+	jr z, .EnbyTiles
+	ld a, $4
+	ld hl, GreenFishingTiles
+	jr .ContinueRoutine ; go back to main routine after loading Green's stuff
+.EnbyTiles
+	ld a, $4
+	ld hl, YellowFishingTiles
+	jr .ContinueRoutine ; go back to main routine after loading Yellow's stuff
+.BoyTiles ; alternately, load Red's stuff
+	ld a, $4
+	ld hl, RedFishingTiles
+.ContinueRoutine
+	call LoadAnimSpriteGfx
ld a, [wSpritePlayerStateData1ImageIndex]

Next, we'll look for this:

RedFishingTiles:
	fishing_gfx RedFishingTilesFront, 2, $02
	fishing_gfx RedFishingTilesBack,  2, $06
	fishing_gfx RedFishingTilesSide,  2, $0a
	fishing_gfx RedFishingRodTiles,   3, $fd

Red has his fishing tiles defined so let's give Green and Yellow some defined tiles. Add these lines after the ones above:

+GreenFishingTiles:
+	fishing_gfx GreenFishingTilesFront, 2, $02
+	fishing_gfx GreenFishingTilesBack,  2, $06
+	fishing_gfx GreenFishingTilesSide,  2, $0a
+	fishing_gfx RedFishingRodTiles,     3, $fd
+YellowFishingTiles:
+	fishing_gfx YellowFishingTilesFront, 2, $02
+	fishing_gfx YellowFishingTilesBack,  2, $06
+	fishing_gfx YellowFishingTilesSide,  2, $0a
+	fishing_gfx RedFishingRodTiles,      3, $fd

We only added fishing tiles. Let's add walking and cycling tiles too. Open home/overworld.asm and look for LoadWalkingPlayerSpriteGraphics:. Add these lines of code:

LoadWalkingPlayerSpriteGraphics::
; new sprite copy stuff
	xor a
	ld [wd473], a
	ld b, BANK(RedSprite)
	ld de, RedSprite
-	jr LoadPlayerSpriteGraphicsCommon
+	ld a, [wPlayerGender] ; from Vortiene
+	and a			; check if boy
+	jr z, .ContinueLoadSprites1
+	cp a, 2			; check if enby
+	jr z, .AreEnby1
+	ld de, GreenSprite
+	jr .ContinueLoadSprites1
+.AreEnby1
+	ld de, YellowSprite
+.ContinueLoadSprites1
+	ld hl, vNPCSprites
+	jr LoadPlayerSpriteGraphicsCommon

[...]

LoadBikePlayerSpriteGraphics::
	ld b, BANK(RedBikeSprite)
	ld de, RedBikeSprite
+	ld a, [wPlayerGender]
+	and a
+	jr z, .ContinueLoadSprites2
+	cp a, 2			; check if enby
+	jr z, .AreEnby2
+	ld de, GreenBikeSprite
+	jr .ContinueLoadSprites2
+.AreEnby2
+	ld de, YellowBikeSprite
+.ContinueLoadSprites2
+	ld hl, vNPCSprites

Now, let's add the new backsprites. Open engine/battle/core.asm and look for LoadPlayerBackPic: so we can edit it:

LoadPlayerBackPic:
	ld a, [wBattleType]
	ld de, OldManPicBack
	cp BATTLE_TYPE_OLD_MAN ; is it the old man tutorial?
	jr z, .next
	ld de, ProfOakPicBack
	cp BATTLE_TYPE_PIKACHU ; is it the pikachu battle at the beginning of the game?
	jr z, .next
-	ld de, RedPicBack
-.next
-	ld a, BANK(RedPicBack)
-	ASSERT BANK(RedPicBack) == BANK(OldManPicBack)
-	ASSERT BANK(RedPicBack) == BANK(ProfOakPicBack)
+	ld a, [wPlayerGender]
+	and a
+	jr z, .RedBack
+	cp a, 2			; check if enby
+	jr z, .YellowBack
+	ld de, GreenPicBack
+	jr .next
+.YellowBack
+	ld de, YellowPicBack
+	jr .next
+.RedBack
+	ld de, RedPicBack
+.next
+	ld a, BANK(RedPicBack)
+	ASSERT BANK(RedPicBack) == BANK(OldManPicBack)
+	ASSERT BANK(GreenPicBack) == BANK(OldManPicBack)
+	ASSERT BANK(YellowPicBack) == BANK(OldManPicBack)
+	ASSERT BANK(RedPicBack) == BANK(ProfOakPicBack)

Second-to-last, Hall of Fame! Open engine/movie/hall_of_fame.asm and go to HoFLoadPlayerPics: so we can change some stuff. Nota bene: there are three lines, the ones commented as these are needed only in Yellow, that are needed (only) in Yellow to avoid funny glitches.

HoFLoadPlayerPics:
-	ld de, RedPicFront
-	ld a, BANK(RedPicFront)
-	call UncompressSpriteFromDE
-	ld a, $0 				; not in pokered
-	call SwitchSRAMBankAndLatchClockData	; not in pokered
-	ld hl, sSpriteBuffer1
-	ld de, sSpriteBuffer0
-	ld bc, $310
-	call CopyData
-	call PrepareRTCDataAndDisableSRAM 	; not in pokered
-	ld de, vFrontPic
-	call InterlaceMergeSpriteBuffers
-	ld de, RedPicBack
-	ld a, BANK(RedPicBack)
-	call UncompressSpriteFromDE
+	ld a, [wPlayerGender] 	; load gender
+	and a      				; check if male
+	jr z, .BoyStuff1
+	cp a, 2					; check if enby
+	jr z, .EnbyStuff1
+	ld de, GreenPicFront
+	ld a, BANK(GreenPicFront)
+	jr .Routine ; skip the enby and boy stuff and go to main routine1
+.EnbyStuff1
+	ld de, YellowPicFront
+	ld a, BANK(YellowPicFront)
+	jr .Routine ; skip the boy stuff and go to main routine1
+.BoyStuff1
+	ld de, RedPicFront
+	ld a, BANK(RedPicFront)
+.Routine ; resume original routine
+	call UncompressSpriteFromDE
+	ld a, $0				; these are needed only in Yellow
+	call SwitchSRAMBankAndLatchClockData	; these are needed only in Yellow
+	ld hl, sSpriteBuffer1
+	ld de, sSpriteBuffer0
+	ld bc, $310
+	call CopyData
+	call PrepareRTCDataAndDisableSRAM	; these are needed only in Yellow
+	ld de, vFrontPic
+	call InterlaceMergeSpriteBuffers
+	ld a, [wPlayerGender]	; load gender
+	and a					; check if male
+	jr z, .BoyStuff2
+	cp a, 2					; check if enby
+	jr z, .EnbyStuff2
+	ld de, GreenPicBack
+	ld a, BANK(GreenPicBack)
+	jr .Routine2 ; skip the enby and boy stuff and go to the main routine2
+.EnbyStuff2
+	ld de, YellowPicBack
+	ld a, BANK(YellowPicBack)
+	jr .Routine2 ; skip the boy stuff and go to the main routine2
+.BoyStuff2
+	ld de, RedPicBack
+	ld a, BANK(RedPicBack)
+.Routine2 ; original routine
+	call UncompressSpriteFromDE ; end of new gender stuff
	predef ScaleSpriteByTwo

The last thing we're gonna do is make sure that the new sprite shows up on the Trainer Card. Open engine/menus/start_sub_menus.asm and go find DrawTrainerInfo: so we can finish this.

DrawTrainerInfo:
	ld de, RedPicFront
	lb bc, BANK(RedPicFront), $01
-	predef DisplayPicCenteredOrUpperRight
+	ld a, [wPlayerGender]
+	and a
+	jr z, .ContinueWithLoading
+	cp a, 2
+	jr z, .AreEnby
+	ld de, GreenPicFront
+	lb bc, BANK(GreenPicFront), $01
+	jr .ContinueWithLoading
+.AreEnby
+	ld de, YellowPicFront
+	lb bc, BANK(YellowPicFront), $01
+.ContinueWithLoading
+	predef DisplayPicCenteredOrUpperRight
	call DisableLCD

And there we have it! Non-binary gender selection in Pokémon Yellow! :D A huge thanks to everyone who contributed to this before me, and please lemme know if there's any problem, I welcome any beta tester :)