summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Home.md3
-rw-r--r--Triple-layer-blocks.md99
2 files changed, 101 insertions, 1 deletions
diff --git a/Home.md b/Home.md
index c946c1d..d2b7523 100644
--- a/Home.md
+++ b/Home.md
@@ -9,4 +9,5 @@ Welcome to the pokeemerald wiki!
- **[Dynamic overworld palette system](Dynamic-overworld-palette-system)**
- **[How to add a new Pokémon species](How-to-add-a-new-Pokémon-species)**
- **[Reduce Noise and Improve Sound Quality (Implementing a New Mixer)](Reduce-Noise-and-Improve-Sound-Quality-(Implementing-a-New-Mixer))**
-- **[Change initial PC items](Change-initial-PC-items)** \ No newline at end of file
+- **[Change initial PC items](Change-initial-PC-items)**
+- **[Triple-layer blocks](Triple-layer-blocks)
diff --git a/Triple-layer-blocks.md b/Triple-layer-blocks.md
new file mode 100644
index 0000000..eae1f2d
--- /dev/null
+++ b/Triple-layer-blocks.md
@@ -0,0 +1,99 @@
+Overworld maps are built out of blocks of tiles. Those blocks get placed in three overlapping layers, but only two layers can be used at a time. [A popular binary hack](https://www.pokecommunity.com/showthread.php?t=352725) allows triple-layer blocks, using all three layers at once by combining two blocks: one for the bottom and middle layers, and a subsequent "burner" block for the top layer.
+
+To allow this in pokeemerald, just edit [src/field_camera.c](../blob/src/field_camera.c):
+
+```diff
+ static void DrawMetatile(s32 metatileLayerType, u16 *metatiles, u16 offset)
+ {
+ switch (metatileLayerType)
+ {
++ case 3: // LAYER_TYPE_TRIPLE
++ // Draw metatile's bottom layer to the bottom background layer.
++ gBGTilemapBuffers3[offset] = metatiles[0];
++ gBGTilemapBuffers3[offset + 1] = metatiles[1];
++ gBGTilemapBuffers3[offset + 0x20] = metatiles[2];
++ gBGTilemapBuffers3[offset + 0x21] = metatiles[3];
++
++ // Draw metatile's top layer to the middle background layer.
++ gBGTilemapBuffers1[offset] = metatiles[4];
++ gBGTilemapBuffers1[offset + 1] = metatiles[5];
++ gBGTilemapBuffers1[offset + 0x20] = metatiles[6];
++ gBGTilemapBuffers1[offset + 0x21] = metatiles[7];
++
++ // Draw next metatile's top layer to the top background layer
++ gBGTilemapBuffers2[offset] = metatiles[12];
++ gBGTilemapBuffers2[offset + 1] = metatiles[13];
++ gBGTilemapBuffers2[offset + 0x20] = metatiles[14];
++ gBGTilemapBuffers2[offset + 0x21] = metatiles[15];
++ break;
+ case 2: // LAYER_TYPE_
+ // Draw metatile's bottom layer to the bottom background layer.
+ gBGTilemapBuffers3[offset] = metatiles[0];
+ gBGTilemapBuffers3[offset + 1] = metatiles[1];
+ gBGTilemapBuffers3[offset + 0x20] = metatiles[2];
+ gBGTilemapBuffers3[offset + 0x21] = metatiles[3];
+
+ // Draw transparent tiles to the middle background layer.
+ gBGTilemapBuffers1[offset] = 0;
+ gBGTilemapBuffers1[offset + 1] = 0;
+ gBGTilemapBuffers1[offset + 0x20] = 0;
+ gBGTilemapBuffers1[offset + 0x21] = 0;
+
+ // Draw metatile's top layer to the top background layer.
+ gBGTilemapBuffers2[offset] = metatiles[4];
+ gBGTilemapBuffers2[offset + 1] = metatiles[5];
+ gBGTilemapBuffers2[offset + 0x20] = metatiles[6];
+ gBGTilemapBuffers2[offset + 0x21] = metatiles[7];
+ break;
+ case 1: // LAYER_TYPE_COVERED_BY_OBJECTS
+ // Draw metatile's bottom layer to the bottom background layer.
+ gBGTilemapBuffers3[offset] = metatiles[0];
+ gBGTilemapBuffers3[offset + 1] = metatiles[1];
+ gBGTilemapBuffers3[offset + 0x20] = metatiles[2];
+ gBGTilemapBuffers3[offset + 0x21] = metatiles[3];
+
+ // Draw metatile's top layer to the middle background layer.
+ gBGTilemapBuffers1[offset] = metatiles[4];
+ gBGTilemapBuffers1[offset + 1] = metatiles[5];
+ gBGTilemapBuffers1[offset + 0x20] = metatiles[6];
+ gBGTilemapBuffers1[offset + 0x21] = metatiles[7];
+
+ // Draw transparent tiles to the top background layer.
+ gBGTilemapBuffers2[offset] = 0;
+ gBGTilemapBuffers2[offset + 1] = 0;
+ gBGTilemapBuffers2[offset + 0x20] = 0;
+ gBGTilemapBuffers2[offset + 0x21] = 0;
+ break;
+ case 0: // LAYER_TYPE_NORMAL
+ // Draw garbage to the bottom background layer.
+ gBGTilemapBuffers3[offset] = 0x3014;
+ gBGTilemapBuffers3[offset + 1] = 0x3014;
+ gBGTilemapBuffers3[offset + 0x20] = 0x3014;
+ gBGTilemapBuffers3[offset + 0x21] = 0x3014;
+
+ // Draw metatile's bottom layer to the middle background layer.
+ gBGTilemapBuffers1[offset] = metatiles[0];
+ gBGTilemapBuffers1[offset + 1] = metatiles[1];
+ gBGTilemapBuffers1[offset + 0x20] = metatiles[2];
+ gBGTilemapBuffers1[offset + 0x21] = metatiles[3];
+
+ // Draw metatile's top layer to the top background layer, which covers event object sprites.
+ gBGTilemapBuffers2[offset] = metatiles[4];
+ gBGTilemapBuffers2[offset + 1] = metatiles[5];
+ gBGTilemapBuffers2[offset + 0x20] = metatiles[6];
+ gBGTilemapBuffers2[offset + 0x21] = metatiles[7];
+ break;
+ }
+ schedule_bg_copy_tilemap_to_vram(1);
+ schedule_bg_copy_tilemap_to_vram(2);
+ schedule_bg_copy_tilemap_to_vram(3);
+ }
+```
+
+This is slightly different from the binary technique. The topmost third layer comes from the "burner" block's *top* layer, not its *bottom* layer. That means the burner block's bottom layer can still be used. So it's not really "wasted" because it can still be useful on its own. For example, if the first block has a bottom layer of water and a top layer of shoreline, and the burner block has a bottom layer of grass and a top layer of tree, then the first block will show the tree above the water and shoreline, while the burner block will show the tree above the grass.
+
+The problem is, [porymap](https://github.com/huderlem/porymap/) doesn't support any layer types besides the default ones: "Normal - Middle/Top", "Covered - Bottom/Middle", and "Split - Bottom/Top". (Their correspondence to the cases in the `DrawMetatile` code should be apparent.) Possible workarounds:
+
+- Keep an eye on [this issue](https://github.com/huderlem/porymap/issues/147) to see if porymap adds support for custom layer types.
+- [Build your own](https://github.com/huderlem/porymap/blob/master/INSTALL.md) copy of porymap, but edit [src/ui/tileseteditor.cpp](https://github.com/huderlem/porymap/blob/master/src/ui/tileseteditor.cpp) to support triple-layer blocks. After the line `this->ui->comboBox_layerType->addItem("Split - Bottom/Top", 2);`, just add another line `this->ui->comboBox_layerType->addItem("Triple - Bottom/Top/Top2", 4);`.
+- Hex-edit the metatile_attributes.bin files to use layer type 3. This is cumbersome compared to using porymap, but it's not a complex format. Every two bytes correspond to a block: the first byte is its behavior value, the second byte is its layer type but shifted to the first nybble. So Normal is $00, Covered is $10, and Split is $20. Just find the pair of bytes for your triple-layer block (the first one, not the burner one) and change its layer type byte to $30.