Update documentation:

- Apply more edits from #595
- Move music ID behavior from the wiki to docs
- Move assembly programming links from docs to the wiki
- Describe why the TM item gaps exist
This commit is contained in:
Rangi 2019-02-17 13:18:38 -05:00
parent 1e5c95d8d4
commit a999787cb8
9 changed files with 181 additions and 46 deletions

3
FAQ.md
View File

@ -71,7 +71,7 @@ It really depends on what image you're trying to change the colors of, where the
## How do I write new features?
There are a number of special-purpose scripting languages, as described in [docs](docs/). For more general features, you'll need to code directly in assembly language. See [docs/assembly_programming.md](docs/assembly_programming.md). Some of the [tutorials][tutorials] may also be helpful.
There are a number of special-purpose scripting languages, as described in [docs](docs/). For more general features, you'll need to code directly in [assembly language][asm]. Some of the [tutorials][tutorials] for specific features may also be helpful.
## I need more help!
@ -83,3 +83,4 @@ Try asking on IRC or Discord (see [README.md](README.md)).
[polished-map]: https://github.com/Rangi42/polished-map
[crowdmap]: https://github.com/yenatch/crowdmap/
[tutorials]: https://github.com/pret/pokecrystal/wiki/Tutorials
[asm]: https://github.com/pret/pokecrystal/wiki/Assembly-programming

View File

@ -1,25 +0,0 @@
# Assembly Programming
- [**RGBDS documentation**][rgbds-doc]: Includes information on the RGBDS tools and the assembly language syntax.
- [**GBZ80 instructions**][gbz80-instructions]: List of CPU instructions and their effects.
- [**RGBASM features**][rgbasm-features]: How to use the assembler features: constants, labels, sections, macros, etc.
- [**RGBLINK features**][rgblink-features]: How to use the linker, including the [pokecrystal.link](/pokecrystal.link) linkerscript.
- [**ASMSchool**][asmschool]: A gameboy assembly tutorial.
- [**GB ASM Tutorial**][gb-asm-tutorial]: A newer but still in-progress asm tutorial.
- [**Pan Docs**][pan-docs]: Everything You Always Wanted To Know About GAMEBOY (but were afraid to ask).
- [**GameBoy Programming Manual**][gb-manual]: The official GameBoy programming and hardware manual by Nintendo.
- [**GameBoy Opcode Summary**][gb-opcodes]: Describes the opcodes of GameBoy assembly language.
- [**GameBoy Memory Map**][gb-memory-map]: Describes the GameBoy Color address space.
- [**awesome-gbdev**][awesome-gbdev]: A curated list of Game Boy development resources such as tools, docs, emulators, related projects and open-source ROMs.
[rgbds-doc]: https://rednex.github.io/rgbds/
[rgbasm-features]: https://rednex.github.io/rgbds/rgbasm.5.html
[rgblink-features]: https://rednex.github.io/rgbds/rgblink.5.html
[gbz80-instructions]: https://rednex.github.io/rgbds/gbz80.7.html
[asmschool]: http://gameboy.mongenel.com/asmschool.html
[gb-asm-tutorial]: https://eldred.fr/gb-asm-tutorial/
[pan-docs]: http://bgb.bircd.org/pandocs.htm
[gb-manual]: https://ia801906.us.archive.org/19/items/GameBoyProgManVer1.1/GameBoyProgManVer1.1.pdf
[gb-opcodes]: http://www.devrs.com/gb/files/opcodes.html
[gb-memory-map]: http://gameboy.mongenel.com/dmg/asmmemmap.html
[awesome-gbdev]: https://github.com/avivace/awesome-gbdev

View File

@ -10,6 +10,8 @@ Fixes are written in the `diff` format. If you've used Git before, this should l
+add green + lines
```
Some fixes are mentioned as breaking compatibility with link battles. This can be avoided by writing more complicated fixes that only apply if the value at `[wLinkMode]` is not `LINK_COLOSSEUM`. That's how Crystal itself fixed two bugs in Gold and Silver regarding the moves [Reflect and Light Screen](#reflect-and-light-screen-can-make-special-defense-wrap-around-above-1024) and [Present](#present-damage-is-incorrect-in-link-battles).
## Contents
@ -898,23 +900,25 @@ CopyPokemonName_Buffer1_Buffer3:
call Random
cp 5 percent
jr c, .CheckMagikarpArea
; Try again if length >= 1616 mm (i.e. if LOW(length) >= 3 inches)
; Try again if length >= 1616 mm (i.e. if LOW(length) >= 4 inches)
ld a, [wMagikarpLength + 1]
- cp LOW(1616) ; should be "cp 3", since 1616 mm = 5'3", but LOW(1616) = 80
+ cp 3
- cp LOW(1616) ; should be "cp 4", since 1616 mm = 5'4", but LOW(1616) = 80
+ cp 4
jr nc, .GenerateDVs
; 20% chance of skipping this check
call Random
cp 20 percent - 1
jr c, .CheckMagikarpArea
; Try again if length >= 1600 mm (i.e. if LOW(length) >= 2 inches)
; Try again if length >= 1600 mm (i.e. if LOW(length) >= 3 inches)
ld a, [wMagikarpLength + 1]
- cp LOW(1600) ; should be "cp 2", since 1600 mm = 5'2", but LOW(1600) = 64
+ cp 2
- cp LOW(1600) ; should be "cp 3", since 1600 mm = 5'3", but LOW(1600) = 64
+ cp 3
jr nc, .GenerateDVs
```
**Better fix:** Rewrite the whole system to use millimeters instead of feet and inches, since they have better precision (1 in = 25.4 mm); and only convert from metric to imperial units for display purposes (or don't, of course).
## Magikarp lengths can be miscalculated
@ -1205,22 +1209,22 @@ The exact cause of this bug is unknown.
This is a mistake with the “`…`” tile in [gfx/battle/hp_exp_bar_border.png](/gfx/battle/hp_exp_bar_border.png):
![image](/docs/images/hp_exp_bar_border.png)
![image](/gfx/battle/hp_exp_bar_border.png)
**Fix:** Lower the ellipsis by two pixels:
![image](/docs/images/hp_exp_bar_border_fix.png)
![image](/docs/images/hp_exp_bar_border.png)
## Two tiles in the `port` tileset are drawn incorrectly
This is a mistake with the left-hand warp carpet corner tiles in [gfx/tilesets/port.png](/gfx/tilesets/port.png):
![image](/docs/images/port.png)
![image](/gfx/tilesets/port.png)
**Fix:** Adjust them to match the right-hand corner tiles:
![image](/docs/images/port_fix.png)
![image](/docs/images/port.png)
## `LoadMetatiles` wraps around past 128 blocks

View File

@ -8,6 +8,7 @@ These are parts of the code that do not work *incorrectly*, like [bugs and glitc
- [Pic banks are offset by `PICS_FIX`](#pic-banks-are-offset-by-pics_fix)
- [`PokemonPicPointers` and `UnownPicPointers` are assumed to start at the same address](#pokemonpicpointers-and-unownpicpointers-are-assumed-to-start-at-the-same-address)
- [Footprints are split into top and bottom halves](#footprints-are-split-into-top-and-bottom-halves)
- [Music IDs $64 and $80 or above have special behavior](#music-ids-64-and-80-or-above-have-special-behavior)
- [`ITEM_C3` and `ITEM_DC` break up the continuous sequence of TM items](#item_c3-and-item_dc-break-up-the-continuous-sequence-of-tm-items)
- [Pokédex entry banks are derived from their species IDs](#pokédex-entry-banks-are-derived-from-their-species-ids)
- [Identical sine wave code and data is repeated five times](#identical-sine-wave-code-and-data-is-repeated-five-times)
@ -73,7 +74,7 @@ GLOBAL PICS_FIX
db BANK("Pics 24") ; BANK("Pics 1") + 23
```
**Fix:** Use `dba` instead of `dba_pic`, delete `FixPicBank`, and remove all four calls to `FixPicBank`.
**Fix:** Delete `FixPicBank` and remove all four calls to `FixPicBank` in [engine/gfx/load_pics.asm](/engine/gfx/load_pics.asm). Then use `dba` instead of `dba_pic` everywhere.
## `PokemonPicPointers` and `UnownPicPointers` are assumed to start at the same address
@ -148,9 +149,9 @@ And `GetMonBackpic`:
**Fix:**
Don't enforce `org $4000` in pokecrystal.link.
Don't enforce `org $4000` in [pokecrystal.link](/pokecrystal.link).
Modify `GetFrontpicPointer`:
Edit `GetFrontpicPointer`:
```diff
ld a, [wCurPartySpecies]
@ -269,7 +270,7 @@ INCBIN "gfx/footprints/wartortle.1bpp"
...
```
Modify `Pokedex_LoadAnyFootprint`:
Edit `Pokedex_LoadAnyFootprint`:
```diff
- push hl
@ -294,6 +295,132 @@ Modify `Pokedex_LoadAnyFootprint`:
```
## Music IDs $64 and $80 or above have special behavior
If a map's music ID in [data/maps/maps.asm](/master/data/maps/maps.asm) is $64 (the value of `MUSIC_MAHOGANY_MART` or `MUSIC_SUICUNE_BATTLE`) it will play either `MUSIC_ROCKET_HIDEOUT` or `MUSIC_CHERRYGROVE_CITY`. Moreover, if a map's music ID is $80 or above (the value of `RADIO_TOWER_MUSIC`) it might play `MUSIC_ROCKET_OVERTURE` or something else.
This is caused by `GetMapMusic` in [home/map.asm](/master/home/map.asm):
```asm
GetMapMusic::
push hl
push bc
ld de, MAP_MUSIC
call GetMapField
ld a, c
cp MUSIC_MAHOGANY_MART
jr z, .mahoganymart
bit RADIO_TOWER_MUSIC_F, c
jr nz, .radiotower
farcall Function8b342
ld e, c
ld d, 0
.done
pop bc
pop hl
ret
.radiotower
ld a, [wStatusFlags2]
bit STATUSFLAGS2_ROCKETS_IN_RADIO_TOWER_F, a
jr z, .clearedradiotower
ld de, MUSIC_ROCKET_OVERTURE
jr .done
.clearedradiotower
; the rest of the byte
ld a, c
and RADIO_TOWER_MUSIC - 1
ld e, a
ld d, 0
jr .done
.mahoganymart
ld a, [wStatusFlags2]
bit STATUSFLAGS2_ROCKETS_IN_MAHOGANY_F, a
jr z, .clearedmahogany
ld de, MUSIC_ROCKET_HIDEOUT
jr .done
.clearedmahogany
ld de, MUSIC_CHERRYGROVE_CITY
jr .done
```
**Fix:**
Replace `RADIO_TOWER_MUSIC | MUSIC_GOLDENROD_CITY` with `MUSIC_RADIO_TOWER` in [data/maps/maps.asm](/master/data/maps/maps.asm).
Redefine the special music constants in [constants/music_constants.asm](/master/constants/music_constants.asm):
```diff
-; GetMapMusic picks music for this value (see home/map.asm)
-MUSIC_MAHOGANY_MART EQU $64
+; GetMapMusic picks music for these values (see home/map.asm)
+MUSIC_MAHOGANY_MART EQU $fc
+MUSIC_RADIO_TOWER EQU $fd
; ExitPokegearRadio_HandleMusic uses these values
RESTART_MAP_MUSIC EQU $fe
ENTER_MAP_MUSIC EQU $ff
-
-; GetMapMusic picks music for this bit flag
-RADIO_TOWER_MUSIC_F EQU 7
-RADIO_TOWER_MUSIC EQU 1 << RADIO_TOWER_MUSIC_F
```
And then edit `GetMapMusic`:
```diff
GetMapMusic::
push hl
push bc
ld de, MAP_MUSIC
call GetMapField
ld a, c
cp MUSIC_MAHOGANY_MART
jr z, .mahoganymart
- bit RADIO_TOWER_MUSIC_F, c
- jr nz, .radiotower
+ cp MUSIC_RADIO_TOWER
+ jr z, .radiotower
farcall Function8b342
ld e, c
ld d, 0
.done
pop bc
pop hl
ret
.radiotower
ld a, [wStatusFlags2]
bit STATUSFLAGS2_ROCKETS_IN_RADIO_TOWER_F, a
jr z, .clearedradiotower
ld de, MUSIC_ROCKET_OVERTURE
jr .done
.clearedradiotower
- ; the rest of the byte
- ld a, c
- and RADIO_TOWER_MUSIC - 1
- ld e, a
- ld d, 0
+ ld de, MUSIC_GOLDENROD_CITY
jr .done
.mahoganymart
ld a, [wStatusFlags2]
bit STATUSFLAGS2_ROCKETS_IN_MAHOGANY_F, a
jr z, .clearedmahogany
ld de, MUSIC_ROCKET_HIDEOUT
jr .done
.clearedmahogany
ld de, MUSIC_CHERRYGROVE_CITY
jr .done
```
## `ITEM_C3` and `ITEM_DC` break up the continuous sequence of TM items
[constants/item_constants.asm](/constants/item_constants.asm) defined the 50 TMs in order with `add_tm`, but `ITEM_C3` and `ITEM_DC` break up that sequence.
@ -352,11 +479,39 @@ GetNumberedTMHM:
ret
```
> There was originally a good reason for these two gaps!
>
> Pokémon traded from RBY to GSC have their catch rate interpreted as their new held item. This was planned early on in development, so some items were given indexes corresponding to appropriate Gen 1 catch rates:
>
> - $03 = 3: `BRIGHTPOWDER` is for Articuno, Zapdos, Moltres, and Mewtwo
> - $1E = 30: `LUCKY_PUNCH` is for Chansey
> - $23 = 35: `METAL_POWDER` is for Ditto
> - $3C = 60: `SILVER_LEAF` is for 10 Pokémon
> - $4B = 75: `GOLD_LEAF` is for 13 Pokémon
> - $96 = 150: `MYSTERYBERRY` is for Clefairy
> - $AA = 170: `POLKADOT_BOW` is for Jigglypuff
> - $B4 = 180: `BRICK_PIECE` is for Machop
>
> Yellow was also being developed then, and it did the reverse, altering some catch rates to correspond to appropriate Gen 2 items:
>
> - Starter Pikachu's catch rate became 163 = $A3 for `LIGHT_BALL`
> - Wild Kadabra's catch rate became 96 = $60 for `TWISTEDSPOON`
> - Wild Dragonair's catch rate became 27 = $1B for `PROTEIN`
> - Wild Dragonite's catch rate became 9 = $09 for `ANTIDOTE`
>
> Most catch rates were left as gaps in the item list, and transformed into held items via the `TimeCapsule_CatchRateItems` table in [data/items/catch_rate_items.asm](/data/items/catch_rate_items.asm). For example, the 52 Pokémon with catch rate 45 would hold the gap `ITEM_2D`, except that gets transformed into Bitter Berry.
>
> But a few Pokémon end up with weird items. Abra has a catch rate of 200, or $C8; and Krabby, Horsea, Goldeen, and Staryu have a catch rate of 225, or $E1. Those indexes correspond to the items TM09 Psych Up and TM33 Ice Punch, which seem like random choices—because they are.
>
> The TMs and HMs span from indexes $BF to $F9. However, as we can see in [pokegold-spaceworld](https://github.com/pret/pokegold-spaceworld/blob/master/constants/item_constants.asm), they *originally* spanned $C4 to $FF. For some reason they were shifted down by 5 during development.
>
> Before the index shift, the gap `ITEM_C3` would have been at index $C8, and `ITEM_DC` at $E1. In other words, they would have neatly corresponded to the catch rates for Abra, Krabby, Horsea, Goldeen, and Staryu! Then those Pokémon would have held Berries instead of random TMs.
**Fix:**
Move `ITEM_C3` and `ITEM_DC` above all the TMs in every table of item data.
Modify engine/items/items.asm:
Edit [engine/items/items.asm](/engine/items/items.asm):
```diff
GetTMHMNumber::
@ -489,7 +644,7 @@ PokedexShow_GetDexEntryBank:
db BANK("Pokedex Entries 193-251")
```
**Fix:** Use `dba` instead of `dw` in `PokedexDataPointerTable`, and modify the code that accesses it to match.
**Fix:** Use `dba` instead of `dw` in `PokedexDataPointerTable`. Then edit [home.asm](/home.asm) to contain a single copy of the `PokedexDataPointerTable` lookup code, updated to work with 3-byte `dba` entries and get the bank from the first entry byte. Delete the three separate lookup routines and use the new one (placed in [home.asm](/home.asm) so it can be called from any bank.)
## Identical sine wave code and data is repeated five times

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 B

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -6164,18 +6164,18 @@ LoadEnemyMon:
call Random
cp 5 percent
jr c, .CheckMagikarpArea
; Try again if length >= 1616 mm (i.e. if LOW(length) >= 3 inches)
; Try again if length >= 1616 mm (i.e. if LOW(length) >= 4 inches)
ld a, [wMagikarpLength + 1]
cp LOW(1616) ; should be "cp 3", since 1616 mm = 5'3", but LOW(1616) = 80
cp LOW(1616) ; should be "cp 4", since 1616 mm = 5'4", but LOW(1616) = 80
jr nc, .GenerateDVs
; 20% chance of skipping this check
call Random
cp 20 percent - 1
jr c, .CheckMagikarpArea
; Try again if length >= 1600 mm (i.e. if LOW(length) >= 2 inches)
; Try again if length >= 1600 mm (i.e. if LOW(length) >= 3 inches)
ld a, [wMagikarpLength + 1]
cp LOW(1600) ; should be "cp 2", since 1600 mm = 5'2", but LOW(1600) = 64
cp LOW(1600) ; should be "cp 3", since 1600 mm = 5'3", but LOW(1600) = 64
jr nc, .GenerateDVs
.CheckMagikarpArea: