Skeetendo

’Cause all games were better on the GBC

You are not logged in.

  • Index
  • → Help/Question
  • → Pokemon RBY Swapping/Editing Pokemon battle/pokedex sprites

#26 2019-09-14 17:23:43

Danny-E 33
Administrator
Registered: 2012-06-09
Post 1,148/1,149

Re: Pokemon RBY Swapping/Editing Pokemon battle/pokedex sprites

Here is a quick crash course on some of the assembly instructions used in that routine.

Starting with:

ld a, [wcf91]

"ld" is the "load" instruction. It takes two operands. The first operand (register "a" in this case) is the destination. The second operand ("[wcf91]" in this case) is the source. "ld" moves a value from the source to the destination.
The square brackets "[]" specify a certain kind of addressing mode. "wcf91" refers to a memory address. "[wcf91]" means the byte at that memory address.
So this instruction takes the value at memory address $cf91 and copies it into register "a".

This value happens to be the index number of the Pokemon that is being loaded. These values match the index numbers in constants/pokemon_constants.asm.

The next instruction ("ld b, a") similarly copies the value in register "a" into register "b".
In the context of this routine, this is to make a backup of the Pokemon's index number - so that if the index number in register "a" gets overwritten, the index number can be restored in register "a" by copying from register "b", as opposed to loading from memory address $cf91 again.
(This is because loading from memory addresses is slower than loading from registers, and because "ld a, [wcf91]" is a 3 byte instruction compared to "ld b, a" which is only 1 byte. However, this optimization is not really relevant to our discussion at the moment.)

The next instruction is:

cp MEW

"cp" is the "compare" instruction. Before I talk about how it behaves, I will mention the flag register.

We've already seen register "a" and register "b". There are others too, like "c", "d", and "e". These are all general-purpose registers. This means they do not have a predefined purpose that they must be used for. Instead, they can be used for any purpose the programmer needs at any given moment, to store any arbitrary data.

There is also the "f" register, which is not general-purpose. It is a special "flag" register. As a result, there are no instructions to directly read and write to the "f" register. ("ld a, f" and "ld f, a" are not legal instructions.)
Instead, this register is made up of flags (single bits) that are either set (1) or reset (0), and these flags are controlled by the CPU based on the instructions that are executed (and the results of those instructions).

One of these flags in the "f" register is the "z" flag (zero flag).
The "z" flag is set if the previous arithmetic instruction resulted in 0.
The "z" flag is reset if the previous arithmetic instruction resulted in anything other than 0.
(There are other ways the "z" flag can be set or reset, but this is good enough for this conversation.)

Another flag in the "f" register is the "c" flag (carry flag).
The "c" flag is set if the previous arithmetic instruction was a subtraction where the subtrahend was larger than the minuend. (In other words, in the calculation "x - y" the carry flag will be set if "y" is larger than "x".)
The "c" flag is reset if the previous arithmetic instruction was a subtraction where the subtrahend was not larger than the minuend.

Now back to the "cp" instruction.
The "cp" instruction performs a subtraction just for the sake of appropriately setting the "z" flag and the "c" flag. The actual result of the subtraction is not stored anywhere - the registers (other than register "f" of course) are not modified.
Usually, an instruction like this takes two operands, but here we see just one operand ("MEW"). This always means that the first operand is implied to be register "a", and "MEW" is actually the second operand.
So this instruction will calculate "a - MEW" in order to set the "z" flag and "c" flag but will not store the result of the subtraction and will not modify register "a".

Now lets think about what this means in the context of this routine.
Register "a" holds the index number of the Pokemon being loaded. So "a - Mew" will set the "z" flag if register "a" equals "MEW". ("a - MEW" will equal 0.)
"a - MEW" will set the "c" flag if register "a" is smaller than "MEW".

The next instruction is:

ld a, BANK(MewPicFront)

This overwrites the index number that is currently stored in register "a" with the bank number where MewPicFront in located.

Next is:

jr z, .GotBank

"jr" is a kind of jump instruction. Jump instructions change the current point of code execution by "jumping" to a new location in code to begin executing instead. (".GotBank" in this case, close to the end of the routine.)
The "z" that is part of this instruction turns this into a conditional jump. The condition is that the jump will only be performed if the "z" flag is set.
If the "z" flag is reset, the jump instruction will be ignored and execution will continue down as normal.

What does this mean in the context of this routine?
We know the "z" flag will be set if the index number of the Pokemon being loaded is equal to "MEW".
So the jump will be performed if the Pokemon being loaded is Mew (while the bank number for Mew's front pic is in register "a").

Lets pretend we are not loading Mew, so the jump is not taken. And lets look at a few instructions at a time. The next few instructions to be executed are:

ld a, b
cp FOSSIL_KABUTOPS
ld a, BANK(FossilKabutopsPic)
jr z, .GotBank

First, this restores the index number into register "a" like I hinted at.
Second, just like with the first "cp" command, this will set the "z" flag if register "a" is equal to "FOSSIL_KABUTOPS" and it will set the "c" flag if register "a" is less than "FOSSIL_KABUTOPS".
Third, this overwrites register "a" with the bank number of "FossilKabutopsPic".
And fourth, this jumps to the end of the routine if the index of the Pokemon being loaded is equal to "FOSSIL_KABUTOPS".

This is very similar to the "MEW" case and should be self-explanatory.

Things are changed up in the next case:

ld a, b
cp TANGELA + 1
ld a, BANK(TangelaPicFront)
jr c, .GotBank

This time, register "a" is compared to "TANGELA + 1" which is not a real Pokemon. (Refer to constants/pokemon_constants.asm.) This means the "z" flag will never be set.
But the "c" flag will be set if the index of the Pokemon being loaded is less than "TANGELA + 1".
And this time, we see "jr c" instead of "jr z", so the jump will only be taken if the "c" flag is set.
This means the front and back pics for all Pokemon with an index number less than "TANGELA + 1" (except for MEW and FOSSIL_KABUTOPS) must be stored in the same bank as each other.

This exact same logic is repeated a few more times for every other "group" of Pokemon pics.

If you fully understand the UncompressMonSprite routine and you understand the basics of writing assembly, then you can modify this routine to use specific bank numbers for specific Pokemon.

Offline

#27 2019-09-17 01:50:29

Anonymous
Member
From: Canada
Registered: 2019-02-23
Post 30/31

Re: Pokemon RBY Swapping/Editing Pokemon battle/pokedex sprites

Danny-E 33 wrote:

If you are using the disassembly then you do not need to worry about manually re-pointing.

I would guess that you still need to update UncompressMonSprite: in home.asm.
This routine hard-codes the bank number that it uses for each mon pic, including FossilKabutopsPic, FossilAerodactylPic, and GhostPic.

If you want to move any mon pics to custom banks, you need to update UncompressMonSprite.

The method you used to help me with locating pics to another offset did not work.

Just today I asked the great ROM hacker Crystal_ for a bit of help on how to move pokemon sprites to another ROM bank and he told me that I have to modify the main.asm file and told me the specific instructions which was way easier said than done.

All I had to do was this

SECTION  "Pics 6", ROMX

MewPicFront::          INCBIN "pic/bmon/mew.pic"
MewPicBack::           INCBIN "pic/monback/mewb.pic"
ArticunoPicFront::     INCBIN "pic/bmon/articuno.pic"
ArticunoPicBack::      INCBIN "pic/monback/articunob.pic"
VictreebelPicFront::   INCBIN "pic/bmon/victreebel.pic"
VictreebelPicBack::    INCBIN "pic/monback/victreebelb.pic"
RapidashPicFront::     INCBIN "pic/bmon/rapidash.pic"
RapidashPicBack::      INCBIN "pic/monback/rapidashb.pic"
PidgeotPicFront::      INCBIN "pic/bmon/pidgeot.pic"
PidgeotPicBack::       INCBIN "pic/monback/pidgeotb.pic"
MoltresPicFront::      INCBIN "pic/bmon/moltres.pic"
MoltresPicBack::       INCBIN "pic/monback/moltresb.pic"

I checked the pokered.sym file after running the make command and this is what I got

06:6718 MewPicFront
06:680B MewPicBack
06:6861 ArticunoPicFront
06:6A99 ArticunoPicBack
06:6AFE VictreebelPicFront
06:6CC6 VictreebelPicBack
06:6D58 RapidashPicFront
06:6F7A RapidashPicBack
06:702A PidgeotPicFront
06:71E1 PidgeotPicBack
06:7284 MoltresPicFront
06:74DA MoltresPicBack

Crystal_ told me that you don't need to specify it's location in the pokered.link file, the compiler will place it wherever there is space.

Offline

#28 2019-09-19 03:25:47

Danny-E 33
Administrator
Registered: 2012-06-09
Post 1,149/1,149

Re: Pokemon RBY Swapping/Editing Pokemon battle/pokedex sprites

Anonymous wrote:

The method you used to help me with locating pics to another offset did not work.

I saw your earlier reply before you deleted it, but I didn't have the time to respond yet.
The reason it did not work for you is because you did not make the correct edits to the routine.

Anonymous wrote:

Just today I asked the great ROM hacker Crystal_ for a bit of help on how to move pokemon sprites to another ROM bank and he told me that I have to modify the main.asm file and told me the specific instructions which was way easier said than done.

All I had to do was this

SECTION  "Pics 6", ROMX

MewPicFront::          INCBIN "pic/bmon/mew.pic"
MewPicBack::           INCBIN "pic/monback/mewb.pic"
ArticunoPicFront::     INCBIN "pic/bmon/articuno.pic"
ArticunoPicBack::      INCBIN "pic/monback/articunob.pic"
VictreebelPicFront::   INCBIN "pic/bmon/victreebel.pic"
VictreebelPicBack::    INCBIN "pic/monback/victreebelb.pic"
RapidashPicFront::     INCBIN "pic/bmon/rapidash.pic"
RapidashPicBack::      INCBIN "pic/monback/rapidashb.pic"
PidgeotPicFront::      INCBIN "pic/bmon/pidgeot.pic"
PidgeotPicBack::       INCBIN "pic/monback/pidgeotb.pic"
MoltresPicFront::      INCBIN "pic/bmon/moltres.pic"
MoltresPicBack::       INCBIN "pic/monback/moltresb.pic"

I checked the pokered.sym file after running the make command and this is what I got

06:6718 MewPicFront
06:680B MewPicBack
06:6861 ArticunoPicFront
06:6A99 ArticunoPicBack
06:6AFE VictreebelPicFront
06:6CC6 VictreebelPicBack
06:6D58 RapidashPicFront
06:6F7A RapidashPicBack
06:702A PidgeotPicFront
06:71E1 PidgeotPicBack
06:7284 MoltresPicFront
06:74DA MoltresPicBack

Crystal_ told me that you don't need to specify it's location in the pokered.link file, the compiler will place it wherever there is space.

Crystal_ is definitely brilliant. But I think I see part of your misunderstanding now.

There are two parts to solving this problem.

1. The easy part is literally moving the "INCBIN" statements for a Pokemon pic from one bank to another.

2. The hard part is fixing UncompressMonSprite: to more intelligently determine the bank to use to load each Pokemon pic.

So far you have only done step 1. I suspect if you tried loading each Pokemon pic (check the Pokedex, encounter them in battle) that you will see some pics load correctly and others do not.
Read my previous comment to get an understanding of how UncompressMonSprite: works to see why not all Pokemon pics load correctly.

Offline

#29 2019-09-19 19:42:01

Anonymous
Member
From: Canada
Registered: 2019-02-23
Post 31/31

Re: Pokemon RBY Swapping/Editing Pokemon battle/pokedex sprites

I already got it figured out and Crystal_ gave me more hints on how I can modify the UncompressedMonSprite section depending on the last Pokemon in the Bank.

I ran the make command and all the sprites turned out fine and there were no issues or bugs with the pokeblue and pokered.gbc files.

Anyways I would like to thank you for also giving me hints with the home.asm file.

One more thing to mention because I want to know if it will cause any glitches or not.

Remember how you helped me with adding new moves without replacing any existing moves.

I want to know what would happen if the new moves that I added into pokered were mirror moved.

I'm worried that it may cause the game to freeze or crash.

Did you ever try mirror moving the new moves you have added into your rom hacks of Pokemon Red

Last edited by Anonymous (2019-09-19 21:12:24)

Offline

  • Index
  • → Help/Question
  • → Pokemon RBY Swapping/Editing Pokemon battle/pokedex sprites

Board footer

Powered by FluxBB