Expand the Town Map tileset - pret/pokecrystal GitHub Wiki

Note: You should not follow this tutorial and the alternate one! Pick one.

This tutorial describes how to edit the Town Map with Tilemap Studio. However, you're limited to using 48 different tiles, which is not enough for more detailed maps. Here we'll see how to use at least 33 more tiles for designing Town Maps.

This alternate tutorial shows another way to do the same thing. It's more involved, but allows the Town Map tiles to be consecutive before the Pokégear tiles.

Contents

  1. Combine the Town Map and Pokégear graphics
  2. Move the "extra" font graphics and use their space

1. Combine the Town Map and Pokégear graphics

The Pokégear graphics are right after the Town Map graphics in VRAM, and they have a couple of unused tiles. Plus gfx/pokegear/town_map_palette_map.asm already assigns palettes to them both. It's fairly simple to combine them into a single tileset.

First, edit gfx/pokegear/town_map.png, appending the gfx/pokegear/pokegear.png tiles to it:

gfx/pokegear/town_map.png

You can then delete gfx/pokegear/pokegear.png.

Then edit gfx/misc.asm:

SECTION "Unown Font", ROMX

UnownFont::
INCBIN "gfx/font/unown_font.2bpp"


-SECTION "Pokégear GFX", ROMX
-
-PokegearGFX::
-INCBIN "gfx/pokegear/pokegear.2bpp.lz"

Edit layout.link:

ROMX $77
	"Unown Font"
	"Print Party"
	"Tileset Data 7"
	"bank77"
-	"Pokégear GFX"
	"European Mail"

Edit the Makefile:

-gfx/pokegear/pokegear.2bpp: rgbgfx += -x2

Edit gfx/pokegear/town_map_palette_map.asm:

-; gfx/pokegear/pokegear.png

(Removing the Makefile rule and the comment won't really do anything, but it avoids confusion from mentioning a file that we just deleted.)

And edit engine/pokegear/pokegear.asm:

 Pokegear_LoadGFX:
 	call ClearVBank1
 	ld hl, TownMapGFX
 	ld de, vTiles2
 	ld a, BANK(TownMapGFX)
 	call FarDecompress
-	ld hl, PokegearGFX
-	ld de, vTiles2 tile $30
-	ld a, BANK(PokegearGFX)
-	call FarDecompress
 	ld hl, PokegearSpritesGFX
 	ld de, vTiles0
 	ld a, BANK(PokegearSpritesGFX)
 	call Decompress
 	...
 LoadTownMapGFX:
 	ld hl, TownMapGFX
 	ld de, vTiles2
-	lb bc, BANK(TownMapGFX), 48
+	lb bc, BANK(TownMapGFX), 96
 	call DecompressRequest2bpp
 	ret

Now the whole set of 96 tiles gets loaded at once, but there's one flaw. The Pokédex area map only ever loaded the Town Map graphics; it skipped the Pokégear graphics because it used that space for the Pokédex's own graphics. Now that we're treating the Pokégear tiles as just extra Town Map tiles, we need to reload the Pokédex tiles when we close the Area map.

Edit engine/pokedex/pokedex.asm:

 DexEntryScreen_MenuActionJumptable:
 	dw Pokedex_Page
 	dw .Area
 	dw .Cry
 	dw .Print

 .Area:
 	...
 	ld a, [wDexCurLocation]
 	ld e, a
 	predef Pokedex_GetArea
 	call Pokedex_BlackOutBG
+	call Pokedex_LoadGFX
+	call Pokedex_LoadAnyFootprint
 	call DelayFrame
 	...

Now we can use tile IDs $30–$5F for the Town Map, not just $00–$2F. Most of them are needed for the Pokégear, but the last two bottom-right blank tiles, $5E and $5F, are unused. Tile $5D is also blank, but it's used once in the Radio Card, so if you overwrite it with graphics for the Town Map, you'll have to replace the byte 5D with 7F in gfx/pokegear/radio.tilemap.rle. (You can open *.tilemap.rle files in Tilemap Studio with the "Pokégear card" format, or use a hex editor.)

Two or three extra tiles isn't much of an advantage; we'd have to simplify the Pokégear graphics to make room for Town Map ones. That is possible: some tiles could be eliminated (like the embossed border tiles used only by the Radio Card), and any tile that's just black and white can be moved into gfx/font/font.png and gfx/font/font_inversed.png. However, we'd then have to thoroughly update the gfx/pokegear/*.tilemap.rle files, and track down all the places in the source code that refer to changed tile IDs, which can be tedious. Luckily there's a more efficient solution.

2. Move the "extra" font graphics and use their space

Tiles $00–$2F are the original Town Map graphics, $30–5F are the Pokégear graphics, $60–7E are some "extra" font graphics, $7F is the space character, and $80–$FF are the standard font graphics. We can see how they're laid out in BGB's VRAM viewer:

Screenshot

Those extra font graphics also take up space that could be used for overworld map tilesets. This tutorial explains how to expand map tilesets from 192 to 255 tiles, and part of that involves moving the extra font graphics from tiles $60–7E to within the standard font tile space, $80–FF. (Tile $7F stays as the space character.)

If you haven't followed the 192-to-255-tile tutorial yet, you don't actually have to do the whole thing. Steps 1–5 and 9–10 explain how to move the extra font tiles out of the $60–$7E space, and steps 6–8 explain how to repurpose that space for map tilesets. So if all you care about is the Town Map, you can skip steps 6–8. However, I recommend following the whole tutorial anyway, because if you care about graphics enough to be redesigning the Town Map, you'll probably end up pushing the limits of what 192 map tiles can do.

Anyway, after we combine the Town Map and Pokégear graphics, and move the extra font tiles by following this tutorial, then the VRAM looks like this:

Screenshot

Let's enable those 31 tiles for use in the Town Map.

First, edit gfx/pokegear/town_map.png, adding another two rows of empty tiles:

gfx/pokegear/town_map.png

Note that the bottom-right tile $7F is the space character, so it should stay blank.

Then edit gfx/pokegear/town_map_palette_map.asm:

 ; gfx/pokegear/town_map.png
 	townmappals EARTH,    EARTH,    EARTH,    MOUNTAIN, MOUNTAIN, MOUNTAIN, BORDER,   BORDER
 	townmappals EARTH,    EARTH,    CITY,     EARTH,    POI,      POI_MTN,  POI,      POI_MTN
 	townmappals EARTH,    EARTH,    EARTH,    MOUNTAIN, MOUNTAIN, MOUNTAIN, BORDER,   BORDER
 	townmappals EARTH,    EARTH,    BORDER,   EARTH,    EARTH,    BORDER,   BORDER,   BORDER
 	townmappals EARTH,    EARTH,    EARTH,    MOUNTAIN, MOUNTAIN, MOUNTAIN, BORDER,   BORDER
 	townmappals BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER
-; gfx/pokegear/pokegear.png
 	townmappals BORDER,   BORDER,   BORDER,   BORDER,   POI,      POI,      POI,      BORDER
 	townmappals BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER
 	townmappals CITY,     CITY,     CITY,     CITY,     CITY,     CITY,     CITY,     CITY
 	townmappals CITY,     CITY,     CITY,     CITY,     CITY,     CITY,     CITY,     BORDER
 	townmappals CITY,     CITY,     CITY,     CITY,     CITY,     CITY,     CITY,     CITY
 	townmappals BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER
+	townmappals BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER
+	townmappals BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER
+	townmappals BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER
+	townmappals BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER,   BORDER

And edit engine/pokegear/pokegear.asm:

 TownMapPals:
 ; Assign palettes based on tile ids
 	hlcoord 0, 0
 	decoord 0, 0, wAttrmap
 	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
 .loop
 ; Current tile
 	ld a, [hli]
 	push hl
-; The palette map covers tiles $00 to $5f; $60 and above use palette 0
-	cp $60
+; The palette map covers tiles $00 to $7e; $7f and above use palette 0
+	cp $7f
 	jr nc, .pal0
 	...
 LoadTownMapGFX:
 	ld hl, TownMapGFX
 	ld de, vTiles2
-	lb bc, BANK(TownMapGFX), 96
+	lb bc, BANK(TownMapGFX), 50
 	call DecompressRequest2bpp
 	ret

+ LoadTownMapGFX2:
+ 	ld hl, TownMapGFX
+ 	ld de, vTiles2
+	lb bc, BANK(TownMapGFX), 96
+ 	call DecompressRequest2bpp
+ 	ret
_FlyMap:
	call ClearBGPalettes
	call ClearTilemap
	call ClearSprites
	ld hl, hInMenu
	ld a, [hl]
	push af
	ld [hl], $1
	xor a
	ldh [hBGMapMode], a
	farcall ClearSpriteAnims
-	call LoadTownMapGFX
+	call LoadTownMapGFX2
	ld de, FlyMapLabelBorderGFX
	ld hl, vTiles2 tile $30
	lb bc, BANK(FlyMapLabelBorderGFX), 6
	call Request1bpp
Pokedex_GetArea:
; e: Current landmark
	ld a, [wTownMapPlayerIconLandmark]
	push af
	ld a, [wTownMapCursorLandmark]
	push af
	ld a, e
	ld [wTownMapPlayerIconLandmark], a
	call ClearSprites
	xor a
	ldh [hBGMapMode], a
	ld a, $1
	ldh [hInMenu], a
	ld de, PokedexNestIconGFX
	ld hl, vTiles0 tile $7f
	lb bc, BANK(PokedexNestIconGFX), 1
	call Request2bpp
	call .GetPlayerOrFastShipIcon
	ld hl, vTiles0 tile $78
	ld c, 4
	call Request2bpp
-	call LoadTownMapGFX
+	call LoadTownMapGFX2
	call FillKantoMap
	call .PlaceString_MonsNest

Now we're done! With extra tiles and custom colors, your project can have a really unique Town Map:

Screenshot

(Example Town Maps: FRLG-style Kanto by Rangi, HGSS-style Johto from Polished Crystal, RSE-style Hoenn by SaveState, DPPt-style Sinnoh by SaveState, Unova by JaceDeane, and Invar by Wasabi_Raptor for Brass.)