• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites

  • 200
    Posts
    10
    Years
    • He or They
    • Seen Jun 19, 2022
    Yellow Hacking Tutorial (Evolve/Replace Pikachu and more)
    ========================================================

    Yellow is very similar to RGB, so you'll definitely want to review other guides. This will mooooostly focus on Yellow-specific things - evolving Pikachu,Making All Pokemon Follow or replacing with a different pokemon, but there will also be other things like biking, shinies and an uber uber basic item system.

    First off - you will want to grab Yellow Disassembly and a program like Cygwin to make it compile.
    You'll want Dannye-33's Gen 2 Sprites Base, because it's got more features than vanilla yellow, better graphics, and makes it a breeze to add in extra new gen pokemon. If you are nostalgic for any of the old yellow sprites, it's very easy to just copypaste from a vanilla yellow disassembly into the appropriate folder: I did that for Pikachu myself (revamping the image while I was at it) and left the others alone.

    Altering Our Starter
    ===========================


    Evolve Pikachu into Raichu
    ---

    Alright! The bulk of this tutorial is devoted to Pikachu (specifically, replacing it). As appropriate of a Yellow tutorial. Even if you aren't interested in Raichu specifically and just came here to turn Pikachu into Meowth or something, you'll still learn a lot here that will enable us to do things like that, or evolve said Meowth, so let's start:


    The method I prefer is 'evolve by happiness'. This ensures that you get to have Raichu emotion sprites at the appropriate times without too much fuss, although there will still probably be times when the player gets the wrong emotion sprite, the vast majority of the time they will get the right one.

    Figure out what happiness level you want Pikachu to evolve at, and alter all the images of that happiness up accordingly in gfx/pikachu. For your convenience I have included a folder where this has already been done for you!

    Next: Go to Pikachu's evo_moves.asm data, and change her evolution method to 'Level Up'. You probably want to choose a nice minimum level like 16 to discourage potion or turbo-run hax for early game Raichu. If you really want, though, you can set it to 1.

    Then, go into the engine/evos_moves.asm and alter the level up function to check if the pokemon is pikachu, and for that happiness, and if so to skip straight to evolving.

    code example: (search for .checkLevel and .doEvolution, and fix to look like this)

    Code:
    .checkLevel
      ld [hl], c
      ld a, [wEvoOldSpecies]
    	cp PIKACHU
      jr nz, .CheckL
      ;160 is happiness level you have when you get to arms raised pikachu. I think?
      ld a, [wPikachuHappiness]
      cp 160
      jp c, .nextEvoEntry2
      jp c, .doEvolution
    .CheckL
    	ld a, [hli] ; level requirement
    	ld b, a
    	ld a, [wLoadedMonLevel]
    	cp b ; is the mon's level less than the evolution requirement?
    	jp c, .nextEvoEntry2 ; if so, go the next evolution entry
    .doEvolution

    Making Raichu Follow
    ---
    This is the most interesting and painstaking part. You will need to go to each place that loads pikachu's sprite - there's one buffer that is used to reload the sprite after emotions, and two loading functions depending on if you are indoors or outdoors. Add a check if Raichu or Pikachu is in the party, then load the correct sprite depending.

    go to engine/overworld/map_sprites.asm

    First, InitOutsideMapSprites:

    change .loadSpriteSet to something like this:
    Spoiler:


    Then, in the same file, find
    LoadSpriteSetFromMapHeader:
    ;and alter the first bit of code there
    Spoiler:


    in engine/pikachu_movement, need to alter LoadPikachuSpriteIntoVRAM to something like this:

    Spoiler:


    Second, you will need to go in for any place that checks for Pikachu in your party, and add a second check for Raichu, so that Raichu's happiness can grow, you can have appropriate Raichu emotion sprites, and you can get Bulbasaur if you have a Raichu.

    engine/pikachu_status is the place to alter here (this is a bit long, and there may be a more efficient way of coding this, buuut I'm still a novice so it's what you get):

    Spoiler:


    And, less important but still good to do, is altering in the same file IsThisPartymonStarterPikachu_Party, and the IsThisSurfpikachu check , where it CPs for Pikachu, do something like this:

    Code:
    cp RAICHU
    	jr nz, .isPika
    	jr .yes
    .isPika
    	cp PIKACHU
    	jr nz, .notPlayerPikachu
    .yes

    edit: I forgot in pikachu_emotions there is a check for sleeping, too.

    If the original does cp +1, +1 as well.
    Now your Raichu can let you play the surfing minigame! Nice, huh? It'll still have a Pikachu sprite, but you could always replace that with a Raichu if you want.

    You also need to create a sprite for Raichu if you haven't yet.
    data/sprite_sets.asm, and in engine/bank3f just duplicate the PikachuSprite(s) there and include your image! This is quite important, as obviously you won't get a following Raichu otherwise!


    Altering Pikachu's Voice / Changing voice on evolve
    ---

    It is very simple, it involves replacing pikachu voice .wav files with other .wav files, or finding where they are called and choosing to play a different cry.

    If some voices are only played at a certain happiness level, then one can just replace those with Raichu/evolved form without having to do any extra special checks.
    You will also want to go to engine/battle/core.asm and to status_screen.asm to go put in a quick check for Raichu/Pikachu and load the right cry.
    Like so:
    Code:
    .playPikachuSoundClip
      callab IsStarterRaichuInOurParty ;really should make one to check box too...
      jr nc, .Pikachu
      ld e,4 ;load voice '5', which I changed to Raichu. Note e starts on 0 to load PikachuCry1.
      jr .cry
    .Pikachu
    	ld e, 16 ;pikachu's original cry for this one.
    .cry
    	callab PlayPikachuSoundClip
    	jr .continue

    For your convenience I have included several Raichu voices that I went to the trouble of cropping from the anime and putting into wav format.

    Different Starter (Replace Pikachu and Raichu)
    ----
    Having just Pikachu as your only option is boring, right? Let's change that up.

    First, start with the 'Evolve Pikachu' and 'Make Raichu Follow' code above so your new starter can evolve and still follow you around. (skip if you don't want any evolutions) Hypothetically you can do this with multiple evolutions, not just two, just choose another happiness level to evolve at for that 3rd evolution to make your final starter follower and duplicate Raichu check codes again.

    There are two different routes you can take: you can replace Pikachu and Raichu with fakemon, or you can simply leave Pikachu and Raichu in the game and switch all the places that check for Pikachu (same ones as in the Raichu code above!) with a different pokemon, so:

    cp PIKACHU

    becomes

    cp MEOWTH

    or something like that.
    It's not strictly necessary to rename PikachuSprite - no one in game will see the code, so it's just sufficient to change the image to your new pokemon. Duplicate for Raichu with any evolutions.

    If you are replacing your entire Pokedex with Fakemon (or next gen pokemon), chances are you will still have to do the above, since I imagine you'll be wanting to rename your constants.

    Here's a quick list of places you need to alter (or add stuff on to) for new pokemon:

    /pics folder, both the backsprites (/monback) and frontsprites (/ymon)
    main.asm (need to include said pics so the game knows where to find them)
    pokemon and pokedex constants
    everywhere in /data that talks about pokemunz, such as evos_moves and base_stats.
    /data/wildPokemon the wild pokemon,
    /data/baseStats individual pokemon.asms such as pikachu.asm. (Update base_stats to include any new asm.)
    data/ cries, mon_party_sprites, mon_palettes
    alter monster names and pokedex entries in /text

    You might want to consider altering pikachu's voice too. (Edit: On analysis I found you can just easily edit out calls to pikachu's voice in pikachu_emotions)

    Of course, last part needed for a new following starter is to, once again, change the pikachu emotion sprites! If you enjoy image crafting, this is the most fun and easy part, just open up in an image editor (edit: that accepts indexing) and save!
    If you hate image drawing, on the other hand, perhaps consider some generic emotion sprites instead, like a ! mark. Your image should only use 4 colors - the image itself can be black, gray and white, since the game will load colors based on palette.



    All Pokemon Follow (Now a simple version is complete!)
    -----

    The coding has been done for making any pokemon follow. It basically replaces the CheckForRaichu and makes a new happiness checker for any pokemon that isn't Pikachu. I split the old CheckforRaichu into two different functions; one to dynamically load the right sprite, and one to check if you have a pokemun in your party's first row.

    You may want to replace the pikachu happiness images with generic emotion symbols / smiley faces like SoulSilver and HeartGold does and create some other method for dealing with happiness or allow pokemon happynuzz to all be tied together.
    However, I present an alternative system of keeping Pikachu happiness as-is and having other pokemon have happiness based on HP stat exp. You can just comment out the pikachu picture anims and use the game's exclamation, hate and heart symbols.




    Check Any Pokemon
    Code:
    IsaPokemonInOurParty::
    	ld hl, wPartySpecies
    	push hl
    .loop
    	pop hl
    	ld a, [hli]
    	push hl
    	inc a
    	jr z, .noPlayerPoke
    ;	cp WHATEVERPOKE + 1, if want all, just leave like this~
    ;	jr nz, .curMonNotPlayerPikachu
      call FirstPartymonHP
    	cp 0
    	jr z, .noPlayerPoke
    	pop hl
    	scf
    	ret
    .noPlayerPoke
    	pop hl
    	and a
    	ret

    First partymonHP (needed for fainting in the above function)
    Code:
    FirstPartymonHP::
      ld hl, wPartyMon1
      ld bc,(wPartyMon1HP + 1) - wPartyMon1 ;check hp
    	add hl,bc
    	ld a,[hl]
    	ret


    I put both of these code in pikachu_status, and called them from the map sprite loader functions I talked about earlier. In this code, I chose to check against either species or type, and basically went with what I had sprites for. If your sprite doesn't have full walk animations, it WILL glitch and look terrible, so make sure it matches pikachu's sprite image set size.
    Note that unlike the original full code that checks for OT id and such, this one doesn't care if the pokemon is traded.
    If you want to use Pikachu's happiness/status function, you still have to modify IsPikachuParty, instead of IsPikachuInOurParty, to accept all mons, as that's the function that checks status I think. Without it, only Pikachu/Raichu will get happiness updates when you do things with them. Personally I prefer the idea of developing a separate happiness function for the rest of them (see further below).

    note: By default, the bird sprite, surf/seel sprite, and the slowbro sprite should have full walking sprites.

    Here's the Loading Sprites function, you'll want to modify it to match your own game; for instance, mine has an eevee sprite so I added code for eevee. It got bloated pretty quickly :P.
    Just like we did in the Raichu tutorial above, you'll want to put calls to this in engine/overworld/map_sprites.asm so both of the map sprite loading functions there will know what sprite to use.
    Code:
    LoadPokeFollowSprite::
      ld hl, wPartySpecies
    	push hl
    	pop hl
    	ld a, [hli]
    	push hl
    	inc a
    	jp z, .noPlayerPoke
    	CP PIKACHU +1
    	jr nz, .curMonNotThis0
    	ld a, SPRITE_PIKACHU
    .end
      pop hl
    	scf
    	ld [wSpriteSet], a
    	ret
    .noPlayerPoke
    	pop hl
    	and a
    	ret	
    .curMonNotThis0
    	CP RAICHU +1
    	jr nz, .curMonNotThis1
    	ld a, SPRITE_RAICHU
    	jr .end
    .curMonNotThis1
    	cp PERSIAN + 1
    	jr nz, .curMonNotThis2
    	ld a, SPRITE_PERSIAN
    	jr .end
    .curMonNotThis2
    	cp BULBASAUR + 1
    	jr nz, .curMonNotThis3b
    	ld a, SPRITE_BULBASAUR
    	jr .end
    .curMonNotThis3b
    	cp IVYSAUR + 1
    	jr nz, .curMonNotThis3c
    	ld a, SPRITE_BULBASAUR
    	jr .end
    .curMonNotThis3c
    	cp VENUSAUR + 1
    	jr nz, .curMonNotThis3
    	ld a, SPRITE_BULBASAUR
    	jr .end
    .curMonNotThis3
    	cp EEVEE + 1
    	jr nz, .curMonNotThis4a
    	ld a, SPRITE_EEVEE
    	jr .end
    .curMonNotThis4a
      cp SYLVEON + 1
    	jr nz, .curMonNotThis4b
    	ld a, SPRITE_EEVEE
    	jr .end
    .curMonNotThis4b
    	cp UMBREON + 1
    	jr nz, .curMonNotThis4c
    	ld a, SPRITE_EEVEE
    	jr .end
    .curMonNotThis4c
    	cp ESPEON + 1
    	jr nz, .curMonNotThis4d
    	ld a, SPRITE_EEVEE
    	jr .end
    .curMonNotThis4d
    	cp FLAREON + 1
    	jr nz, .curMonNotThis4e
    	ld a, SPRITE_EEVEE
    	jr .end
    .curMonNotThis4e
    	cp GLACEON + 1
    	jr nz, .curMonNotThis4f
    	ld a, SPRITE_EEVEE
    	jr .end
    .curMonNotThis4f
    	cp JOLTEON + 1
    	jr nz, .curMonNotThis4g
    	ld a, SPRITE_EEVEE
    	jr .end
    .curMonNotThis4g
    	cp VAPOREON + 1
    	jr nz, .curMonNotThisEon
    	ld a, SPRITE_EEVEE
    	jr .end
    .curMonNotThisEon
    	cp LEAFEON + 1
    	jr nz, .curMonNotThis4
    	ld a, SPRITE_EEVEE
    	jr .end
    .curMonNotThis4
    	cp DITTO + 1
    	jr nz, .curMonNotThisDitto
    	ld a, SPRITE_DITTO
    	jr .end2
    .curMonNotThisDitto
    	cp SQUIRTLE + 1
    	jr nz, .curMonNotThis5a
    	ld a, SPRITE_SQUIRTLE
    	jr .end2
    .curMonNotThis5a
    	cp WARTORTLE + 1
    	jr nz, .curMonNotThis5b
    	ld a, SPRITE_SQUIRTLE
    	jr .end2 
    .curMonNotThis5b
    	cp LAPRAS + 1
    	jr nz, .curMonNotThisM
    	ld a, SPRITE_LAPRAS
    	jr .end2
    .curMonNotThisM
    	cp GYARADOS + 1
    	jr nz, .curMonNotThisFish
    	ld a, SPRITE_GYARADOS
    	jr .end2 
    .curMonNotThisFish
    	cp SEEL + 1
    	jr nz, .curMonNotThisFishy
    	ld a, SPRITE_SEEL
    	jr .end2 
    .curMonNotThisFishy
    	cp DEWGONG + 1
    	jr nz, .curMonNotThisFishfood
    	ld a, SPRITE_SEEL
    	jr .end2 
    .curMonNotThisFishfood
    	cp SANDSHREW + 1
    	jr nz, .curMonNotThisShrew
    	ld a, SPRITE_SANDSHREW
    	jr .end2;relative value must be 8 bit
    .curMonNotThisShrew
    	cp SANDSLASH + 1
    	jr nz, .curMonNotThisS
    	ld a, SPRITE_SANDSHREW
    .end2;so, we have multiple different endings here
      pop hl
    	scf
    	ld [wSpriteSet], a
    	ret
    .curMonNotThisS
    	cp BLASTOISE + 1
    	jr nz, .curMonNotThis5
    	ld a, SPRITE_SQUIRTLE
    	jr .end2
    .curMonNotThis5
    	cp CHARIZARD + 1
    	jr nz, .curMonNotThis6a
    	ld a, SPRITE_DRAGON
    	jr .end2
    .curMonNotThis6a
    	cp CHARMELEON + 1
    	jr nz, .curMonNotThis6b
    	ld a, SPRITE_CHARMANDER
    	jr .end2
    .curMonNotThis6b
    	cp CHARMANDER + 1
    	jr nz, .curMonNotThisStarter
    	ld a, SPRITE_CHARMANDER
    	jr .end2
    .curMonNotThisStarter
    	cp DRAGONITE + 1
    	jr nz, .curMonNotThisG
    	ld a, SPRITE_DRAGON
    	jr .end2
    .curMonNotThisG
    	cp ONIX + 1
    	jr nz, .curMonNotThisMon
    	ld a, SPRITE_SNAKE2
    	jr .end2
    .curMonNotThisMon
    	cp EKANS + 1
    	jr nz, .curMonNotThisMon2
    	ld a, SPRITE_SNAKE2
    	jr .end2
    .curMonNotThisMon2
    	cp ARBOK + 1
    	jr nz, .curMonNotThisMon3
    	ld a, SPRITE_SNAKE2
    	jr .end2
    .curMonNotThisMon3
    	cp VOLTORB + 1
    	jr nz, .curMonNotThisMon4
    	ld a, SPRITE_BALL
    	jr .end2
    .curMonNotThisMon4
    	cp ELECTRODE + 1
    	jr nz, .curMonNotThisMon5
    	ld a, SPRITE_BALL
    	jr .end2
    .curMonNotThisMon5
    	cp MAGNEMITE + 1
    	jr nz, .curMonNotThisMon6
    	ld a, SPRITE_BALL
    	jr .end2
    .curMonNotThisMon6
    	cp MAGNETON + 1
    	jr nz, .curMonNotThisMon7
    	ld a, SPRITE_BALL
    	jr .resume
    .curMonNotThisMon7
    	cp MAGNEZONE + 1
    	jr nz, .curMonNotThisMon8
    	ld a, SPRITE_BALL
    	jr .resume
    .curMonNotThisMon8
    	cp GLIGAR + 1
    	jr nz, .curMonNotThisMon9
    	ld a, SPRITE_ZUBAT
    	jr .resume
    .curMonNotThisMon9
    	cp GLISCOR + 1
    	jr nz, .curMonNotThisMon10
    	ld a, SPRITE_ZUBAT
    	jr .resume
    .curMonNotThisMon10
    	ld a,[wPartyMon1Type1]
     ; callab GetPartyMonSpriteID I didn't have much luck with this, also don't have enough sprites for all of them; they have to have full walksprites.
      ;cp SPRITE_MON              ; $0
    	;cp SPRITE_BALL_M           ; $1
    	;cp SPRITE_HELIX            ; $2
    	cp FAIRY            
    	jr nz, .curMonNotThisFairy
    	ld a, SPRITE_CLEFAIRY
    	jr .resume
    .curMonNotThisFairy
    	cp WATER           
    	jr nz, .curMonNotThisWater
    	ld a, SPRITE_FISH
    	jr .resume
    .curMonNotThisWater
      cp FIRE
    	jr nz, .curMonNotThis6
    	ld a, SPRITE_DOG
    	jr .resume
    .curMonNotThis6
    	cp BUG              
    	jr nz, .curMonNotThisBug
    	ld a, SPRITE_BUTTERFREE
    	jr .resume
    .curMonNotThisBug
    	cp GRASS       
    	jr nz, .curMonNotThisGrass
    	ld a, SPRITE_ODDISH
    	jr .resume
    .curMonNotThisGrass
      cp DRAGON       
    	jr nz, .curMonNotThisDragony
    	ld a, SPRITE_SNAKE2
    	jr .resume
    .curMonNotThisDragony
      cp ROCK        
    	jr nz, .curMonNotThis
    	ld a, SPRITE_GEODUDE
    	jr .resume
    .curMonNotThis
      cp GHOST       
    	jr nz, .curMonNotThisGhost
    	ld a, SPRITE_GHOST
    	jr .resume
    .curMonNotThisGhost
      cp POISON       
    	jr nz, .curMonNotThisPoison
    	ld a, SPRITE_ZUBAT
    	jr .resume
    .curMonNotThisPoison
      ld a,[wPartyMon1Type2]
    	cp FLYING
    	jr nz, .curMonNotThisBird
    	ld a, SPRITE_BIRD
    	jr .resume
    .curMonNotThisBird
    	cp DARK        
    	jr nz, .curMonNotThisredux
    	ld a, SPRITE_MEOWTH
    	jr .resume
    .curMonNotThisredux
      ld a, SPRITE_SLOWBRO
      jr .resume
    .resume
    	ld [wSpriteSet], a
      pop hl
    	scf
    	ret
    so, using above, modify the various add/call sprite codes.

    VRAM:
    Code:
    LoadPikachuSpriteIntoVRAM:
      call IsPikachuFirst
      cp 25 ;rather arbitrary value I asked pikachufirst to load...
      ld a,0
      jr nz, .load2
      call IsStarterPikachuInOurParty2
      jr nc, .Raichu
      ld de, PikachuSprite
    	;lb bc, BANK(PikachuSprite), (SandshrewSprite - PikachuSprite) / 32
    	jr .go
    .Raichu
    	ld de, RaichuSprite
    .go
      lb bc, BANK(PikachuSprite), (SandshrewSprite - PikachuSprite) / 32
    	ld hl, vNPCSprites + $c * $10
    	push bc
    	call CopyVideoDataAlternate
    	call IsStarterRaichuInOurParty
    	jr nc, .Pikachu2
    	ld de, RaichuSprite + $c * $10
      jr .goo
    .Pikachu2
    	ld de, PikachuSprite + $c * $10
    .goo
    	ld hl, vNPCSprites2 + $c * $10
    	ld a, [h_0xFFFC]
    	and a
    	jr z, .load
    	callab IsStarterRaichuInOurParty
    	jr nc, .Pikachu3
    	ld de, RaichuSprite + $c * $10
      jr .goo2
    .Pikachu3
    	ld de, PikachuSprite + $c * $10
    .goo2
    	ld hl, vNPCSprites2 + $4c * $10
    .load
    	pop bc
    	call CopyVideoDataAlternate
    .load2
    	call LoadPikachuShadowIntoVRAM
    	call LoadPikachuBallIconIntoVRAM
    	ret


    Here's a quick example of modifying what emotion sprites come up for non-pikachu mons:
    in pikachu_emotions, you'll find .check_pikachu_status, alter the start of it:
    Code:
    .check_pikachu_status
      call IsPikachuFirst
      cp 25
      jr z, .Pika
      ldpikaemotion a, PikachuEmotion24;PikachuEmotion5 unhappy,28 status,29 heart 8 happy, 1 content, 32 confused, 27 shocked, 26 zz wakeup, 25 used attack, 24 exclaim.
    	jr c, .play_emotion
    .Pika

    I went in and disabled all the animation except the ! point for anim 24; it's for pikachu refusing to evolve and I don't really need it much. You can find PikachuEmotion24 in the other pikachu_emotions file, if you comment out:
    ;pikaemotion_pikapic PikaPicAnimScript24
    then that'll do it. Only the exclamation point will play, and you won't get Pikachu sprites for the other pokemon anymore.
    You could also try making your own emotion scripts. I'll show that shortly.

    Remember to put in some function for just pikachu/raichu detection, if you want to treat them specially:
    Code:
    IsPikachuFirst::
    	ld hl, wPartySpecies
    	push hl
    .loop
    	pop hl
    	ld a, [hli]
    	push hl
    	inc a
    	jr z, .noPlayerPoke	
    	cp PIKACHU + 1
    	jr z, .curMonPlayerPikachu
    	cp RAICHU + 1
    	jr nz, .noPlayerPoke
    .curMonPlayerPikachu
      ld a,25 ;completely arbitrary value to check for, as long as it ain't zero. >_>
      pop hl
      ret
    .noPlayerPoke
      ld a,0
    	pop hl
    	ret

    You can alter sprite_sets and sprite_constants to add on new sprites like I did, or you can just replace old ones.

    Here's a function for alternative happiness:

    Code:
    FirstPartymonHappy::
    	ld hl, wPartyMon1
    	ld bc,wPartyMon1HPExp - wPartyMon1 ;decided to base it off HP exp
    	add hl,bc
    	ld a,[hl]
    	ret

    it loads the "happiness" (really hp exp) into a.

    Then do a more elaborate modification of happiness in pikachu_emotions:

    Code:
    .check_pikachu_status
      call IsPikachuFirst
      cp 25
      jr z, .Pika
      call FirstPartymonHappy
      cp 1
      jr nc, .content ;bigger than
      ldpikaemotion a, PikachuEmotionSkull
      jr .play_emotion
    .content
      cp 10
      jr nc, .happy
      ldpikaemotion a, PikachuEmotion24;PikachuEmotion5 unhappy,28 status,29 exuberant heart 8 happy, 1 content, 32 confused, 27 shocked, 26 zz wakeup, 25 used attack, 24 exclaim.
      jr .justlilhappy
    .happy
      cp 30
      jr nc, .happy2
      ldpikaemotion a, PikachuEmotionSmile;PikachuEmotion5 unhappy,28 status,29 exuberant heart 8 happy, 1 content, 32 confused, 27 shocked, 26 zz wakeup, 25 used attack, 24 exclaim.
      jr .justlilhappy
    .happy2
      ldpikaemotion a, PikachuEmotionHeart
    .justlilhappy
    	jr .play_emotion
    .Pika
    small edit: prev happiness standards were way too high. :P

    Here's some generic replacement emotions you might like, remember to modify both pikachu_emotions (data and engine), one to add these and another has a little table listing all the emotes:

    Code:
    PikachuEmotionSmile:
    	pikaemotion_dummy2
    	pikaemotion_emotebubble SMILE_BUBBLE
    	db $ff
    	
    PikachuEmotionHeart:
    	pikaemotion_dummy2
    	pikaemotion_emotebubble HEART_BUBBLE
    	db $ff
    	
    PikachuEmotionSkull:
    	pikaemotion_dummy2
    	pikaemotion_emotebubble SKULL_BUBBLE
    	db $ff

    Running in Yellow
    ===
    Running can be done the exact same way as in Red, but it will cause Pikachu to lag behind. Provided you don't mind this, it works just fine. Pikachu will eventually catch up. Credit goes to Red++ Matteo.

    Code:
    ld a, [hJoyHeld] ; Check what buttons are being pressed for Shoes
    	and B_BUTTON ; Are you holding B?
    	jr z, .notRunning ; If you aren't holding B, skip ahead to step normally.
    	jp .goFaster ; Needs to link or call to your method of going faster. Make you go faster if you were holding B
    .notRunning ; Normal code resumes here


    I just stuck this in overworld.asm in dobikespeedup, and it worked fine. You'll want to speed up the normal bike, which brings me to....

    Altered Biking in Yellow
    ===
    This can be a pain if you are adding a girl or extra selectable character (there's a tutorial floating around somewhere on it - it just requires going in to all the places that call a boy image and adding a girl flag check, plus option to choose gender in the intro -), because you'll likely immediately run into BANK0 TOO FULL error when you try to add the extra bike image checks.

    As such, I opted for Pokemon Riding instead, since it just requires changing the bike image to a pokemon. (I also sped up my bike - now a pokemon - with an extra call AdvancePlayerSprite in the BikeSpeedUp function in overworld.asm)
    You don't have to do the same, but it may be less hassle for you.

    New, Multiple SHINIES
    ===
    (This is just a quick tut on how to do multiple shinies, not shinies in general; the full code there is in Red++)

    I altered status_screen, super_palettes (just to add one more palette is all, add as many shiny palettes as you want)
    engine/palettes.asm:

    Code:
    	ld hl, MonsterPalettes
    	;shiny
    	ld e, a
    	ld d, $00
    	add hl, de
    	ld a, [hl]
    	push bc
    	ld d, a
    	ld a, e
    	and a
    	ld a, d
    	jr z, .done
    	ld b, a
    	ld a, [wShinyMonFlag]
    	bit 0, a ; is mon supposed to be shiny?
    	ld a, b
    	jr z, .done
    	ld b, a
    	ld a,[wTemp]
    ;Shinybit 1	
    	cp 1
    	jr nz, .nextcolor
    	;ld a,b
    	;add (3) ;
    	ld a, PAL_MEWTWO ;the best pokemon? >_>
    	jr .done
    .nextcolor
    	ld a,[wTemp]
    	cp 2
    	jr nz, .nextcolor2
    	ld a,PAL_BLUEMON ; or maybe do PAL_NIDORINA 
    	;add (3)
    	jr .done
    .nextcolor2
    	ld a,[wTemp]
    	cp 3
    	jr nz, .nextcolor3
    	ld a,PAL_YELLOWMON
    	;add (4)
    	jr .done
    .nextcolor3
    	cp 5
    	jr nz, .nextcolor4
    	ld a,PAL_GREENMON ;
    	jr .done
    .nextcolor4
    	cp 6
    	jr nz, .nextcolor5
    	ld a,PAL_SHINY ;blackmon
    	jr .done
    .nextcolor5
    	ld a,[wTemp]
    	cp 4
    	jr nz, .nope
    	ld a,PAL_PINKMON
    	;ld a,b
    	;add (5) ;older version just shifted palettes forward.
    	jr .done
    .nope
     ld a,b
    .done
    	pop bc
    	ret

    and in main.asm, set the varieties/check for different shines!

    Code:
    IsMonShiny:
    ; Input: de = address in RAM for DVs
    ; Reset zero flag if mon is shiny
    ; Mon is shiny if Defense/Speed/Special are 10, and Attack is 2, 3, 6, 7, 10, 11, 14, or 15
    	ld h, d
    	ld l, e
    	;Attack must be even2,odd1 (1, 3, 5, 7, 9, 11, 13, or 15) (1 in 2)
    	ld a, [hl]
    	and 2 << 4
    	jr z, .NotShiny
    	ld a,0
    	ld [wTemp], a
    	ld a, [hli]
    	and $f
    	cp 9
    	jr z, .MaybeShiny1
    	cp 8
    	jr z, .MaybeShiny2
    	cp 7
    	jr z, .MaybeShiny3
    	cp 2
    	jr z, .MaybeShiny4
    	cp 11
    	jr nz, .NotShiny
    .MaybeShiny1 ;color1
    	ld a, 1
    	ld [wTemp], a
    	ld a, [hl]
    	jr .Shiny
    .MaybeShiny2;color2
    	ld a, 2
    	ld [wTemp], a
    	ld a, [hl]
    	jr .Shiny
    .MaybeShiny4;color2
    	ld a, 4
    	ld [wTemp], a
    	ld a, [hl]
    	jr .Shiny
    .MaybeShiny3;color3
    	ld a, 3
    	ld [wTemp], a
    	ld a, [hl]
    		;ol' speed check if we want to reduce values even more, would have to alter the maybe shinies above to go here instead of shiny. could also introduce even moar varieties of pokemonz.
    ;.shinyspeedcheck
    	;and $f << 4
    	;cp 5 << 4
    	;jr z, .Shiny
    	;cp 13 << 4
    	;jr nz, .NotShiny
    .Shiny
    	; set zero flag
    	and a ; a cannot be 0, so zero flag is set with thing command
    	ret
    .NotShiny
    	; reset zero flag
    	xor a
    	ret

    You also of course have to do the calling for the shiny check in battle.
    Code:
    		; is mon shiny?
    	ld b, Bank(IsMonShiny)
    	ld hl, IsMonShiny
    	ld de, wEnemyMonDVs
    	call Bankswitch
    	ld hl, wShinyMonFlag
    	jr nz, .shiny
    	res 0, [hl]
    	jr .setPAL
    .shiny
    	set 0, [hl]
    .setPAL
    	ld b, SET_PAL_BATTLE
    	call RunPaletteCommand 
    	call HideSprites
    	jpab PrintBeginningBattleText;search for this line
    This is just my example of modifying the shiny code, the original version you can check out in Red++; the only thing you have to worry about when porting it over to yellow is some variable names change slightly.

    NEW, ADDING HOLD ITEMS!
    ==============================

    Edit Note: There's a part of it that is bizarrely finicky. One version of my game only accepts value 20 (or super potion) another, more recent one wanted value 21 set to the item id var on party screen load and map screen load. So be careful with this or it will crash your game, and double check it on any changes you make to the game that it's still working. I suspect this is an indicator I'm doing something wrong.


    Alter items.asm, start_sub_menus, battle/core.asm, engine/menu/status_screen.asm and text_ids2. ^_^ I also altered all of the pokemon's catch rates so they would either be above my item range or valid items within that range. If you want you can personally over-ride so all caught pokemon will have catch rate of the same item, in Yellow just search for where it alters Kadabra's catch rate.

    This is a _very_ basic item system, I encourage you to develop it further than this.


    first ,items.asm:
    Code:
    	GivePokeHoldItem:
    	ld a, 1
    	ld [wActionResultOrTookBattleTurn], a ; initialise to success value
    	ld a,[wWhichPokemon]
    	ld [wTempLevel],a ; remember which item slot was used
    	
    	ld a, [wcf91]	;contains item_ID?
    	ld [wTemp],a
    	cp 20
    	jr z, .works
    	ld a, 20
    	ld [wcf91],a
    	;party menu isn't working right for anything EXCEPT super potion, equal to 20, bizarrely? probably because trying to load some value in same spot it originally saves item. so let's save the nonsuperpotion and then over-write... >_> meh.
    .works
    	ld a, [wPartyCount]
    	and a
    	jp z, .canceledItemUse
    	ld a, [wWhichPokemon]
    	push af
    	ld a, [wcf91]
    	push af
    	ld a, USE_ITEM_PARTY_MENU
    	ld [wPartyMenuTypeOrMessageID], a
    	ld a, $ff
    	ld [wUpdateSpritesEnabled], a
    	call DisplayPartyMenu
    	
    .getPartyMonDataAddress
    	jp c, .canceledItemUse
    	ld hl, wPartyMons
    	ld bc, wPartyMon2 - wPartyMon1
    	ld a, [wWhichPokemon]
    	call AddNTimes
    	ld a, [wWhichPokemon]
    	ld [wUsedItemOnWhichPokemon], a
    	ld d, a
    	
    	ld [wd0b5], a
    	call GetMonHeader
    	ld bc,wPartyMon1CatchRate - wPartyMon1
    	add hl,bc ; hl now points to catch, now item
    	ld a, [hl] ;Let's do a check for what the item is
    	cp 70 ; you need to put your max valid item count here
    	jr c, .cnt ;less than than...
    	ld a, 20
    	 ;overwrite with potion if the catch rate of Mon is nonexistent item.
    	;ld [hl],a ;not necessary to actually do it yet since we overwrite shortly anyway
    .cnt 
      ld [wTempCoins1], a ;hold bag id for laters
      ;Now give pokemon the new hold item.
    	;xor a ;remove catch, unnecessary but useful if we want no items by default.
    	ld a, [wTemp];item
    	ld [hl], a ;ld into CatchRate,a
    	ld [wd11e],a ; store item ID for GetItemName
    	call GetItemName
    	call CopyStringToCF4B ; copy name to wcf4b
    	ld hl, HoldItemText
    	Call PrintText
    	
    	;take away the old item held and give it to bag
    	ld a, [wTempCoins1]
      ld [wcf91],a ;item id
      ld [wd11e],a ;fo item name
      ld hl, wNumBagItems ;put the address of bag in hl
      ld a,1
      ld [wItemQuantity],a ;how many to add
      call AddItemToInventory
      call GetItemName
    	call CopyStringToCF4B ; copy name to wcf4b
    	ld hl, TookItemText
    	Call PrintText
    	
      ld a, 20
    	ld [wcf91],a ;overwrite fix fo map again...
    	
    .nope
      ld a,[wTempLevel]
      ld [wWhichPokemon],a
      ld a, 1
      ld [wItemQuantity],a
      ld hl, wNumBagItems
      call RemoveItemFromInventory ;needs wWhichPokemon to have itemslot in it.
    .canceledItemUse
    	call GBPalWhiteOut
    	call z, RunDefaultPaletteCommand
    	ld a, [wIsInBattle]
    	and a
    	ret nz
    	jp ReloadMapData
    
    HoldItemText::
     text "Gave the item"
     line "@"
     TX_RAM wcf4b ;some variable goes here
     text "."
     prompt
    TookItemText::
     text "Took away the item"
     line "@"
     TX_RAM wcf4b ;some variable goes here
     text "."
     prompt


    text_ids2.asm:
    alter this:
    Code:
    UseTossText:
    	db   "USE"
    	next "GIVE"
    	next "TOSS@"

    and in start_sub_menus:

    Code:
    .notBicycle2
    	ld a,[wCurrentMenuItem]
    	;and a
    	cp a, 2
    	jr z, .tossItem
    	cp a, 1
    	jr z, .giveItem1
    ; use item
      jr .useitem
    .giveItem1
      ld b,a
      ld a,8
      ld [wTemp],a
      ld a,b
    .useitem
    	ld [wPseudoItemID],a ; a must be 0 due to above conditional jump
    	ld a,[wcf91]
    	cp a,HM_01
    	jr nc,.useItem_partyMenu
    	ld hl,UsableItems_CloseMenu
    	ld de,1
    	call IsInArray
    	jr c,.useItem_closeMenu
    	ld a,[wcf91]
    	ld hl,UsableItems_PartyMenu
    	ld de,1
    	call IsInArray
    	jr c,.useItem_partyMenu
    	call UseItem
    	jp ItemMenuLoop
    .useItem_closeMenu
      ;ld a,[wTemp]
    	;cp a, 8
    	;jr z, .giveItem
    	;don't want this one
    	xor a
    	ld [wPseudoItemID],a
    	call UseItem
    	ld a,[wActionResultOrTookBattleTurn]
    	and a
    	jp z,ItemMenuLoop
    	jp CloseStartMenu
    .useItem_partyMenu
      ld a,[wTemp]
    	cp a, 8
    	jr z, .giveItem
    	;hopefully works
    	ld a,[wUpdateSpritesEnabled]
    	push af
    	call UseItem
    	ld a,[wActionResultOrTookBattleTurn]
    	cp a,$02
    	jp z,.partyMenuNotDisplayed
    	call GBPalWhiteOutWithDelay3
    	call RestoreScreenTilesAndReloadTilePatterns
    	pop af
    	ld [wUpdateSpritesEnabled],a
    	jp StartMenu_Item
    .partyMenuNotDisplayed
    	pop af
    	ld [wUpdateSpritesEnabled],a
    	jp ItemMenuLoop
    .tossItem
    	call IsKeyItem
    	ld a,[wIsKeyItem]
    	and a
    	jr nz,.skipAskingQuantity
    	ld a,[wcf91]
    	call IsItemHM
    	jr c,.skipAskingQuantity
    	call DisplayChooseQuantityMenu
    	inc a
    	jr z,.tossZeroItems
    .skipAskingQuantity
    	ld hl,wNumBagItems
    	call TossItem
    .tossZeroItems
    	jp ItemMenuLoop
    .giveItem
      ld a,[wUpdateSpritesEnabled]
    	push af
    	callab GivePokeHoldItem
    	ld a,[wActionResultOrTookBattleTurn]
    	cp a,$02
    	jp z,.partyMenuNotDisplayed
    	call GBPalWhiteOutWithDelay3
    	call RestoreScreenTilesAndReloadTilePatterns
    	pop af
    	ld [wUpdateSpritesEnabled],a
    	jp StartMenu_Item

    status_screen.asm:
    [/code]
    .StatusWritten
    coord hl, 9, 6
    ;ld de, StatusText;old status text, which just says 'status'
    ;call PlaceString ; "STATUS/"
    ld a, [wLoadedMonCatchRate]
    cp 100
    jr c, .cnt ;replace 100 above with whatever your max item is, a guard against invalid values
    ld a, 20
    ld [wLoadedMonCatchRate],a
    .cnt
    ld [wd11e],a ; store item ID for GetItemName
    call GetItemName
    ld de,wcd6d;PokeHoldItemText;
    call PlaceString
    [/code]

    In core.asm, to have it actually happen in battle, also alter
    Code:
    	ApplyAttackToEnemyPokemonDone:
    	;######HOLD ITEM SCRIPT! @@@####;
      ld a, [wBattleMonCatchRate]
      cp FULL_HEAL ;is it potionz?
      jr c, .IsItOther
      ld a,0
      ld [wBattleMonStatus],a
      jr .NoUseBerry
    .IsItOther
      cp POTION ;is it potionz
      jr c, .IsItOther2
      ld b,10 
      jr .UseHealBerry
    .IsItOther2
      cp SUPER_POTION ;is it potionz?
      jr c, .NoUseBerry
      ld b,20
    .UseHealBerry
      ld a, [wBattleMonHP + 1]
    	cp 15;less than 15 health, use a held item.
      jr nc, .NoUseBerry ;if bigger than above, don't use
      ld a,[wBattleMonHP + 1]
      ;ld b, 10
      add b
      ld b,a 
      ld a,[wBattleMonMaxHP +1]
      cp b
      jr nc, .ContUseItem ;if maxhp bigger than b, continue
    	ld a,[wBattleMonMaxHP +1] ; full restore
    	ld b,a
    .ContUseItem
      ld a, b
    	ld [wBattleMonHP + 1],a
    	ld [wHPBarNewHP],a
      ld a,FULL_RESTORE
      ld [wBattleMonCatchRate], a ;replace with diff item after use...doesn't seem to work permanently
    	callab PrintHoldItemText
    .NoUseBerry 
    	jp DrawHUDsAndHPBars
    Do same thing to Apply Damage to Player Done for items, but with different vars.
    I commented out a lot of mine because right now I just want enemies to heal up, my bank was running out of space, and didn't feel like moving around stuff just yet to free up space.
    The biggest problem with this code is making an enemy pokemon potentially easier to catch when you alter their item, since catchrate is same as item. Also, items are infinitely reusable after the battle ends, since there is no code for 'no item held' yet nor any permanent replacement mechanism here. However, if you're developing perma-held items like Mega Evolution Stones, that works great.
    Code:
    	ApplyAttackToPlayerPokemonDone:
    ;######HOLD ITEM SCRIPT! @@@####;
      ld a, [wEnemyMonCatchRate]
      cp 99 ;Enemies with catch rate lower than that should use items.
      jr nc, .NoUseBerry
     
      ld a, [wEnemyMonHP + 1]
    	cp 10;less than 10 health, use a held item.
      jr nc, .NoUseBerry ;if bigger than, don't use
      ;ld b,10 ;better heal. you can uncomment this stuff if you want
      ;ld a,[wEnemyMonHP + 1]
      ;add b
      ;ld b,a 
      ;ld a,[wEnemyMonMaxHP +1]
      ;cp b
      ;jr nc, .ContUseItem ;if maxhp bigger than b, continue
    	;ld a,[wEnemyMonMaxHP +1] ; full restore instead of letting HP overflow
    	;ld b,a
    ;.ContUseItem
      ld a, 15 ;originally load b, to be more dynamic, but no point to that here. not enough bank space atm, would have to move stuff around
    	ld [wEnemyMonHP + 1],a
      ld a,100
      ld [wEnemyMonCatchRate], a ;replace with diff item after use...doesn't seem to work permanently. anyway, may make a poke easier to catch. >_>
    	callab PrintHoldItemText
    .NoUseBerry
    	jp DrawHUDsAndHPBars
    Put this wherever you want, if in same bank then just use call instead of callab:
    Code:
    UseHoldItemText::
     text "The PKMN ate a little!"
     ;line "@"
     ;TX_RAM wcf4b ;some variable goes here if we want, could put in the item name.
     ;text "."
     prompt
    
    PrintHoldItemText:
     ld hl,UseHoldItemText
     Call PrintText
     ret


    -----

    Common Bugs -

    BANK TOO FULL.

    Yellow has less room in a lot of its banks, so you'll run into this very quickly. Some stuff can be shifted to a different bank with no problem, some code is superfluous and can be edited out (For instance, functions with a comment next to them saying 'Unused'.) but sometimes you have to be more careful. Things in banks often call in other things in that bank - I've switched from call to callab with no problems in these instances in the case of functions.
    You also need to be careful with images; if something calls a set of images from one bank, and you moved one of those, you'll need to update that code to tell it the new bank to use. In the case of adding new pokemon, I highly recommend Dannye-33's Yellow Gen 2 Sprites Base instead of vanilla pokemon yellow disassembly. All you have to do there for new pokemon images having different banks is to go into their main datafile (such as pikachu.asm) and add the bank on the end! Viola! No more bank troubles.

    My Added New Species Turned Into a Trainer!

    If you add over 201 species, those over that number will turn into trainers in the wild. Annoying, I know. I believe there is a 'expand past 255 pokemon' project that fixes this and does all the hard work of adding pokemon for ya -wink-, it's for pokered but Yellow is similar so a lot of code, maybe even all, should be portable over. I haven't done this myself though.

    My new pokemon turned into an ugly blob! / My pikachu emotion sprite is messed up!

    You need to be careful that your image isn't too big or contains too many colors. I recommend a program like gale that can reduce colors to a small palette and then draw with them. What I like to do is duplicate an existing game-friendly image and then just blank it out and draw over that.

    -------------

    If you want to see some results of this code in action, check out my Yellow hack's screenshots in my hack's thread. Or play the game yourself - it's the first and currently the only hack with an evolving following pokemon, but hopefully with this tutorial that won't stay true for long!


    UPDATE:
    I've added some extra walking sprites that you can replace pikachu and raichu with. If you are lazy, you can just rename the sprite in question 'pikachu' and put it in the proper folder and it'll work like a charm. Partial credit goes to Dannye-33 for the Persian, Meowth, Eevee, Butterfree, Ghost, Ditto, Zubat, Dratini, Geodude, Fish.
    Gyarados's partial credit goes to emimonserrate, who made the sprite I based the walkset on.

    There is now a Github that contains the changes I speak of if you want to see it.
     

    Attachments

    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      raichu.png
      640 bytes · Views: 541
    • pikachu.zip
      91 KB · Views: 39
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      cycling.png
      533 bytes · Views: 484
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      persian.png
      605 bytes · Views: 481
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      squirtle.png
      540 bytes · Views: 465
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      ballpoke.png
      346 bytes · Views: 463
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      bulbasaur.png
      569 bytes · Views: 461
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      charmander.png
      608 bytes · Views: 460
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      bug.png
      570 bytes · Views: 461
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      geodude.png
      389 bytes · Views: 453
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      gyarados.png
      529 bytes · Views: 454
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      ghost.png
      529 bytes · Views: 457
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      fish.png
      638 bytes · Views: 460
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      meowth.png
      612 bytes · Views: 458
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      eevee.png
      517 bytes · Views: 462
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      ditto.png
      406 bytes · Views: 453
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      sandshrew.png
      432 bytes · Views: 455
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      zubat.png
      464 bytes · Views: 454
    • [PokeCommunity.com] Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
      snake.png
      609 bytes · Views: 452
    • raichu_cry_1.wav
      78.3 KB
    • raichu_cry_2.wav
      79.6 KB
    • raichu_cry_3.wav
      54.5 KB
    • Raichu_unhappy.wav
      98.2 KB
    Last edited:
    Back
    Top