diff --git a/asm/macros/event.inc b/asm/macros/event.inc index eb8bc7e8a4..3495598548 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -2694,6 +2694,11 @@ .byte \selectionType .endm + .macro mappreview duration:req + callnative MapPreviewScript + .2byte \duration + .endm + @ Follower NPCs @ Sets an existing NPC up to follow the player. diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 833429d262..06f4b8e5c0 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -47,6 +47,7 @@ - [Struct Pokemon Generation](tutorials/mon_generation.md) - [How to use FRLG](tutorials/how_to_frlg.md) - [How to delete vanilla maps](tutorials/how_to_delete_vanilla_maps.md) + - [How to use Map Previews](tutorials/how_to_map_preview_screen.md) - [Changelog](./CHANGELOG.md) - [1.15.x]() - [Version 1.15.0](changelogs/1.15.x/1.15.0.md) diff --git a/docs/tutorials/how_to_map_preview_screen.md b/docs/tutorials/how_to_map_preview_screen.md new file mode 100644 index 0000000000..85ea00e0b1 --- /dev/null +++ b/docs/tutorials/how_to_map_preview_screen.md @@ -0,0 +1,420 @@ +# Map Preview Screen: How To + +*written by Bivurnum* + +![map_preview_example](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/map_preview_example.gif) + +### [Click Here for a Guide to Creating a New Map Preview](#creating-a-new-map-preview-image) + +## Using the Map Previews +I'll be using an example of adding a map preview to Petalburg Woods for this section. + +You will need to define a new map preview screen in ***include/map_preview_screen.h***. Just add your new entry in the list in `MapPreviewScreenId`, leaving `MPS_COUNT` at the very end. Like so: + +```diff +enum MapPreviewScreenId +{ + MPS_VIRIDIAN_FOREST = 0u, + MPS_MT_MOON, + MPS_DIGLETTS_CAVE, + MPS_ROCK_TUNNEL, + MPS_POKEMON_TOWER, + MPS_SAFARI_ZONE, + MPS_SEAFOAM_ISLANDS, + MPS_POKEMON_MANSION, + MPS_ROCKET_HIDEOUT, + MPS_SILPH_CO, + MPS_VICTORY_ROAD, + MPS_CERULEAN_CAVE, + MPS_POWER_PLANT, + MPS_MT_EMBER, + MPS_ROCKET_WAREHOUSE, + MPS_MONEAN_CHAMBER, + MPS_DOTTED_HOLE, + MPS_BERRY_FOREST, + MPS_ICEFALL_CAVE, + MPS_LOST_CAVE, + MPS_ALTERING_CAVE, + MPS_PATTERN_BUSH, + MPS_LIPTOO_CHAMBER, + MPS_WEEPTH_CHAMBER, + MPS_TDILFORD_CHAMBER, + MPS_SCUFIB_CHAMBER, + MPS_RIXY_CHAMBER, + MPS_VIAPOIS_CHAMBER, ++ MPS_PETALBURG_WOODS, + MPS_COUNT +}; +``` + +Then, you will go to ***src/map_preview_screen.c*** and add a new section in the `sMapPreviewScreenData` list for the map preview you just defined. + +```diff +static const struct MapPreviewScreen sMapPreviewScreenData[MPS_COUNT] = { + [MPS_VIRIDIAN_FOREST] = { + .mapsec = MAPSEC_VIRIDIAN_FOREST, + .type = MPS_TYPE_FADE_IN, + .flagId = FLAG_WORLD_MAP_VIRIDIAN_FOREST, + .tilesptr = sViridianForestMapPreviewTiles, + .tilemapptr = sViridianForestMapPreviewTilemap, + .palptr = sViridianForestMapPreviewPalette + }, ++ [MPS_PETALBURG_WOODS] = { ++ .mapsec = MAPSEC_PETALBURG_WOODS, ++ .type = MPS_TYPE_FADE_IN, ++ .flagId = FLAG_VISITED_PETALBURG_WOODS, ++ .tilesptr = sViridianForestMapPreviewTiles, ++ .tilemapptr = sViridianForestMapPreviewTilemap, ++ .palptr = sViridianForestMapPreviewPalette ++ }, + [MPS_MT_MOON] = { + .mapsec = MAPSEC_MT_MOON, +... +``` + +* `mapsec` is just the name of the map section your map is in. This map preview will apply to all maps within this map section (but not when traveling between maps within the same map section, similarly to the map name popups). If it doesn't have one already, the mapsec will need an entry in ***src/data/region_map/region_map_sections.json*** for the map name to show up in the map preview. + +* `type` will be either `MPS_TYPE_BASIC`, `MPS_TYPE_FADE_IN` or `MPS_TYPE_CAVE`. + * `MPS_TYPE_BASIC` will show the map preview, then fade to black before loading into the new map. + * `MPS_TYPE_FADE_IN` will fade the map preview into the new map (see the [gif at the top of this page](#mps-fade-in-gif) for example). + * `MPS_TYPE_CAVE` will perform the warp animation for entering a cave at the end of the map preview, before the map is loaded in. +
+ MPS_TYPE_BASIC example + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/ruins_of_alph_basic.gif) +
+
+ MPS_TYPE_FADE_IN example + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/ruins_of_alph_fade.gif) +
+
+ MPS_TYPE_CAVE example + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/ruins_of_alph_cave.gif) +
+ +* `flagId` is just the name of the flag you want to set when visiting this map for the first time. The flag state determines how long the map preview will last on screen; it gets a shorter duration if the player has been to that map before. A lot of Emerald maps already have associated flags, but Petalburg Woods does not have one by default, so I repurposed one of the unused flags for use in this example. If you don't want to use a flag, you can enter `MPS_FLAG_NULL` here and the duration will have its own custom value (this can be adjusted in the configs in ***include/map_preview_screen.h***). +* `tilesptr`, `tilemapptr`, and `palptr` are the image, tiles, and palette that you want to use for this preview. I'm just using the existing image from Viridian Forest here. +* If the image will load more than 3 16-color palettes, you should add `.usesAllPalettes = TRUE` to the entry. Otherwise the palettes won't be loaded properly. (None of the vanilla FRLG images need this.) + +That's all there is to it! + +### Scripting +* `mappreview` fades the screen to black, runs a map preview for the current map for the specified number of frames, then fades back from black before continuing the script. This uses the behavior of `MPS_TYPE_BASIC`, regardless of the designated type of the map. + +### Configs +In the ***include/config/map_preview_screen.h*** file, there are a few configs you can customize for the map previews. +* `MPS_ENABLE_MAP_PREVIEWS` enables map previews for FRLG by default. To enable them for Emerald, change this value to `TRUE`. To disable map previews entirely, change this value to `FALSE`. +* `MPS_DURATION_LONG` determines how many frames the map preview lasts on screen the first time the player enters that map. +* `MPS_DURATION_SHORT` determines how many frames the map preview lasts on screen after the map's flag has been set. +* `MPS_DURATION_NO_FLAG` determines how many frames the map preview lasts if the flag has been set to `MPS_FLAG_NULL`. +* `MPS_BASIC_FADE_SPEED` determines how quickly the fade to black animation plays at the end of `MPS_TYPE_BASIC`. A larger value makes it fade out slower. A smaller value (even a negative number) makes it fade out faster. + +### Notes +* If `FLAG_HIDE_MAP_NAME_POPUP` is set, it will prevent map previews from showing. +* Due to it needing the only blend register, `MPS_TYPE_FADE_IN` causes NPC shadows (`OW_OBJECT_VANILLA_SHADOWS == FALSE`) to lose their transparency while the map preview is running. +* `MPS_TYPE_FADE_IN` does not work properly if the map has any of the following weather types. (You can use `MPS_TYPE_BASIC` for the map preview instead.) + * `WEATHER_SUNNY_CLOUDS` + * `WEATHER_FOG_HORIZONTAL` + * `WEATHER_FOG_DIAGONAL` + * `WEATHER_UNDERWATER` + * `WEATHER_UNDERWATER_BUBBLES` + +# Creating a New Map Preview Image + This guide will show you how to take a custom image and turn it into a map preview image. I'll be as comprehensive as I can with the relevant mechanics. I also provide example images from both Aseprite and Graphics Gale for the convenience of more users. + +## Contents +* [The Image](#the-image) +* [The Tilemap](#the-tilemap) +* [The Palettes](#the-palettes) + * [Two Palette Image](#two-palette-image) + * [Fifteen Palette Image](#fifteen-palette-image) +* [Map Name Text](#map-name-text) +* [The Code](#the-code) + +# The Image +I'm not much of an artist myself, so I will leave the design of the image to you. For this demonstration, I have picked out a lovely [preview image](https://bulbapedia.bulbagarden.net/wiki/Location_preview#/media/File:HGSS_Ruins_of_Alph-Day.png) from the HGSS games: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/HGSS_Ruins_of_Alph-Day.png) + +The GBA display is exactly 240x160 pixels, so if your base image is larger than that you will have to crop it to fit. My image is a little too wide, so I'll have to trim it down. I also want to incorporate the cinematic black bars, like they used in the FRLG games, so I'll have to trim quite a bit off of the top and bottom as well. + +I have created a template image that is an exact copy of the FRLG map preview, including the black bars and text box. You can find the image in the ***docs/tutorials/img/map_preview_screen/templates*** folder. Feel free to use it for your own previews: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/templates/map_preview_template.png) + +Now I have my map preview exactly how I want it to look in game: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/alph_map_preview_image.png) + +You're probably wondering why there is a big yellow bar along the right side of the image. Those extra tiles are needed because the game will load some tiles off screen. Without the yellow bar taking up that space, some of our map preview tiles would load there instead, screwing up the image. So while the GBA display is only 240x160, all map preview images must be 256x160 pixels in size. Don't worry. Those extra tiles won't show up in the game. (So you can make them whatever color you want. They don't have to be yellow.) + +Finally, you need to make sure that the image is properly indexed. +
+ How to index an image in Aseprite: + +> You just need to click `Sprite`, then `Color Mode`, then make sure the `Indexed` option is checked. +> +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/aseprite_index_example.png) +> +> Make sure to save the image when you are done. +
+
+ How to index an image in Graphics Gale: + +> You need to click `All Frames`, then `Color Depth...`. +> +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/gale_color_depth.png) +> +> Because map preview images use more than one 16-color palette, you should select the `8bpp` option. Then click `OK`. +> +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/gale_8bpp.png) +> +> Make sure to save the image when you are done. +
+ +# The Tilemap +Now that we have our image, we need to covert it into a tile sheet and generate a tilemap using [Tilemap Studio](https://github.com/Rangi42/tilemap-studio/blob/master/README.md). + +In Tilemap Studio, we want to use the Image to Tiles feature. +Click on `Tools`, then `Image to Tiles...`. Alternatively, you could also click on the little orange portrait icon on the far right, shown in the image below. + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/TS_image_to_tiles.png) + +This window will pop up: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/image_to_tiles_window.png) + +For the `Input` and `Output` options, click where it says `No file selected` and select the proper files. +* The `Input` should be the png image you just created. +* The `Output` should be the location you want the tile sheet and tilemap files to be generated. I recommend making a new folder for your map inside of the ***graphics/map_preview*** folder and setting the `Output` there. The name of the new files can be whatever you want, but if you want to match what is used for the vanilla map previews, I recommend setting the name to "tiles". + +If you want, you can check the box that says `Avoid extra blank tiles at the end`. That will make the tile sheet only contain tiles that are used in the image, saving a tiny bit of space. However, it is not strictly necessary and I will not be using it in this example. Just keep in mind that it might alter the dimensions of the tiles image to be different than my example, but it will still work properly. Leaving it unchecked might just include a handful of blank tiles at the bottom of the image. No big deal. + +The Tilemap `Format` should be set to `GBA tiles + 4bpp palettes`. + +Check the box for `Blank tiles use ID` and set its value to `000`. + +The Palette `Format` should be set to `Indexed in tileset image`. + +Check the box for `Color 0` and choose what color you want to use for transparency in all of the palettes. The transparent color won't be used in the visible part of the image, so it doesn't really matter. I like to use the color of the tiles that will be off screen in order to minimize the number of unique colors required in the palettes. (The yellow color is `FFFF00`) + +My Image to Tiles window looks like this now: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/image_to_tiles_window_filled.png) + +Now click `OK`. You should get a little alert telling you it was a success. If you get an error about too many palettes, you may have to edit your initial image to remove some unique colors or redraw parts of the image so the multiple palettes have to share less colors between them in order to transition smoothly from one palette to another. + +Now it will display your new tile sheet and tilemap: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/TS_tiles.png) + +# The Palettes +You may have noticed that the colors of some of the tiles are not correct. This is FINE. The current version of Tilemap Studio (4.0.1) sets all of the pixels in the tiles.png file to use the first palette for whatever reason. However, as long as you retain the order of the colors in each palette in the png, the game will assign them the correct palette and the map preview will show up with the proper colors in-game. + +If you use `MPS_TYPE_FADE_IN` as the map preview behavior, only three palettes can be loaded into the game for the tiles.png image to utilize. Otherwise, the map preview can take advantage of all 16 palette slots. + +This is where the instructions diverge based on how many palettes your new tiles image has. +* If your map preview has 2 or fewer palettes, follow the instructions in the [Two Palette Image](#two-palette-image) section. +* If your map preview has more than 2 palettes, skip to the [Fifteen Palette Image](#fifteen-palette-image) section and follow the instructions there instead. + +## Two Palette Image +This is the only method that supports `MPS_TYPE_FADE_IN`. If you have more than 2 palettes, you may need to reduce the number of colors used in your initial image and try the whole process again. + +The map preview palettes will be loaded into palette slots that don't interfere with the overworld palettes. Specifically, they will be loaded into slots `D`, `E`, and `F`. So, we need to change the palettes in the tilemap to match. If you open the new tiles.png file in your image editor, you can see how many palettes the map preview ended up with: + +
+ Aseprite: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/aseprite_2_palettes.png) +
+
+ Graphics Gale: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/gale_2_palettes.png) +
+ +My image ended up with exactly two palettes, which is an ideal situation. I'm going to move the palettes around so none of them get loaded into palette slot `E`. Palette slot `E` is reserved specifically for the colors used for the text that displays the map name. +For now, we just want to leave the second palette empty, like so: + +
+ Aseprite: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/aseprite_3_palettes.png) +
+
+ Graphics Gale: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/gale_3_palettes.png) +
+ +Remember that you can move whole 16-color palettes to different positions in the png, but you should not rearrange the order of the colors within any individual 16-color palette. The Image to Tiles function sets the colors to very specific positions and you don't want to mess around with that unless you really know what you are doing. +As long as you follow what I do in my screenshots, you should be fine. + +~ ~ ~ + +Now go back to Tilemap Studio and click on the `Palettes` tab. +Here you can see what tiles will use which palettes: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/TS_palettes_initial.png) + +We need to change the palette numbers in the tilemap to match the palette slots they will be loaded into. The tiles marked `0` should be changed to `D`. The ones marked `1` should be changed to `F`. Shift clicking acts as a fill tool. +Here is what my tilemap looks like after the change: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/TS_palettes_fade_in.png) + +If your tiles.png file only has one palette, just change the whole tilemap to the `D` palette. + +If your tiles.png file ended up with more than two palettes, you may have to edit your initial image to remove some unique colors or redraw parts of the image so that multiple palettes have to share fewer colors between them in order to transition smoothly from one palette to another. If you are skilled enough (or masochistic enough) you can try to rearrange some colors so they can be included in the `E` palette. I'll go over the `E` palette in more detail in the [Map Name Text](#map-name-text) section later. + +If your tiles.png file ended up with A LOT more than two palettes, you should use the instructions [here](#no-fade) to go to the [Fifteen Palette Image](#fifteen-palette-image) section instead. + +Make sure to save your changes. + +The following Fifteen Palette Image section should be skipped if your map preview uses two or less palettes. **[CLICK HERE](#map-name-text) to go to the next relevant section.** + +## Fifteen Palette Image +If you open the new tiles.png file in your image editor, you can see how many palettes the map preview ended up with: + +
+ Aseprite: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/aseprite_2_palettes.png) +
+
+ Graphics Gale: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/gale_2_palettes.png) +
+ +If your image has 14 palettes or less, you can [CLICK HERE](#map-name-text) to move to the next section. My image ended up with two palettes, which is a small enough number that I wouldn't have to do anything else in this section. + +If your image has 15 or 16 palettes, continue with this section. + +~ ~ ~ + +I'm going to show you a different example that ended up with 15 palettes: + +
+ Aseprite: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/aseprite_15_palettes.png) +
+
+ Graphics Gale: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/gale_15_palettes.png) +
+ +I'm going to move the palettes around so none of them get loaded into palette slot `E`. Palette slot `E` is reserved specifically for the colors used for the text that displays the map name. For now, we just want to leave the 15th palette empty, like so: + +
+ Aseprite: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/aseprite_16_palettes.png) +
+
+ Graphics Gale: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/gale_16_palettes.png) +
+ +Remember that you can move whole 16-color palettes to different positions in the png, but you should not rearrange the order of the colors within any individual 16-color palette. The Image to Tiles function sets the colors to very specific positions and you don't want to mess around with that unless you really know what you are doing. It's a pain in the butt! +As long as you follow what I do in my screenshots, you should be fine. + +If your tiles.png file ended up with 16 palettes, you may have to edit your initial image to remove some unique colors or redraw parts of the image so that multiple palettes have to share fewer colors between them in order to transition smoothly from one palette to another. If you are skilled enough (or masochistic enough) you can try to rearrange some colors so they can be included in the `E` palette. I'll go over the `E` palette in more detail in the [Map Name Text](#map-name-text) section next. + +Make sure to save your changes. + +~ ~ ~ + +Now go back to Tilemap Studio and click on the `Palettes` tab. Here you can see what tiles will use which palettes: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/TS_palettes_15.png) + +We need to change the palette numbers in the tilemap to match where we moved them to in the png. Since we moved a palette from the 15th position to the 16th position, the tiles marked `E` should be changed to `F`. Shift clicking acts as a fill tool. CTRL clicking a tile will replace every tile of that palette with the selected palette. +Here is what my tilemap looks like after the change: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/TS_palettes_16.png) + +Make sure to save your changes. + +# Map Name Text +The current map's name will be printed in a text box in the upper left corner of the screen. The FRLG template I used earlier shows the exact area of the image that the text box will take up (104x24 pixels, directly in the corner). + +If the map's name is longer than the standard text box size, the text box's width will automatically be extended by an extra 72 pixels. I have another FRLG template image that conforms to this larger size. You can find it in the ***docs/tutorials/img/map_preview_screen/templates*** folder. + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/templates/map_preview_template_long.png) + +The map name being loaded in separately from the image allows you to use the same map preview image for multiple different maps. + +~ ~ ~ + +Palette `E`, the one that is loaded into the second to last palette slot, is the one that the game uses for text and text boxes (not to be confused with the borders around the text boxes). While the palette is comprised of 16 colors, we are only concerned with 3 of them: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/numbered_palette.png) + +* Color `1` (Red): Used for the text box itself. This is what the text gets printed on top of. +* Color `3` (Green): Used for the shadow of the characters of text. +* Color `4` (Blue): Used for the text itself. + +The positions of these colors in the palette are specific to these functions and cannot be changed. + +To demonstrate this in action, here is what the map name text looks like with the colors used in FRLG. The yellow colors in the palettes are filler: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/map_name_frlg_pal.png) + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/map_name_frlg.png) + +And here is the same map name text, but with the colors drastically changed: + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/map_name_vivid_pal.png) + +![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/map_name_vivid.png) + +The rest of the colors in this palette can be used like normal (other than the transparent color `0`). This means you can utilize the unused portion as a sort of partial 16th palette for your map preview image. This takes further skill and knowledge than I will be covering in this guide, but if you can get the colors to line up with the pixels properly, you'll have that much more versatility with the image. + +Keep in mind that this palette needs to be in the 15th slot of tiles.png, unless your image has 2 palettes or less. In that case, you should put it in the second slot instead. + +Here is what the final palettes will look like in my Ruins of Alph tiles.png image (2 palettes): + +
+ Aseprite: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/aseprite_complete_pal_fade.png) +
+
+ Graphics Gale: + +> ![](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/tutorials/img/map_preview_screen/gale_complete_pal_fade.png) +
+ +Once again, make sure to save your changes. + +# The Code +Now that we have our files all sorted, it is time to incorporate our new map preview into the code. + +First, if you want to adhere to the naming conventions of the other map previews, you can rename the tiles.bin file to tilemap.bin. This isn't strictly necessary, but I find it convenient to keep all of the file names consistent. + +Go to ***src/map_preview_screen.c*** and add filepaths to your new files. You'll need to add three new lines. One for the palette, one for the tiles image, and one for the tilemap. The palette file does not exist yet, but this line of code will tell the compiler to generate a gbapal file from the tiles image. You'll also need to add .4bpp.smol and .bin.smolTM suffixes to the tiles and tilemap filepaths respectively. That tells the compiler to generate compressed versions of those files that the GBA can read. +Here's how I did mine: + +```diff +static const u8 sIcefallCaveMapPreviewPalette[] = INCBIN_U8("graphics/map_preview/icefall_cave/tiles.gbapal"); +static const u8 sIcefallCaveMapPreviewTiles[] = INCBIN_U8("graphics/map_preview/icefall_cave/tiles.4bpp.smol"); +static const u8 sIcefallCaveMapPreviewTilemap[] = INCBIN_U8("graphics/map_preview/icefall_cave/tilemap.bin.smolTM"); +static const u8 sAlteringCaveMapPreviewPalette[] = INCBIN_U8("graphics/map_preview/altering_cave/tiles.gbapal"); +static const u8 sAlteringCaveMapPreviewTiles[] = INCBIN_U8("graphics/map_preview/altering_cave/tiles.4bpp.smol"); +static const u8 sAlteringCaveMapPreviewTilemap[] = INCBIN_U8("graphics/map_preview/altering_cave/tilemap.bin.smolTM"); ++static const u8 sRuinsOfAlphMapPreviewPalette[] = INCBIN_U8("graphics/map_preview/ruins_of_alph/tiles.gbapal"); ++static const u8 sRuinsOfAlphMapPreviewTiles[] = INCBIN_U8("graphics/map_preview/ruins_of_alph/tiles.4bpp.smol"); ++static const u8 sRuinsOfAlphMapPreviewTilemap[] = INCBIN_U8("graphics/map_preview/ruins_of_alph/tilemap.bin.smolTM"); +``` + +Again, the names of things can be whatever you want, but keeping with the existing name convention can help you stay organized and informed. For example, I could replace `sRuinsOfAlphMapPreviewTilemap` with `SmittyWerbenJaegerManJensen` and it would still work just fine. But `sRuinsOfAlphMapPreviewTilemap` is so much more descriptive, I never run the risk of forgetting what its intended use is. Do what feels right to you. + +That's it! Now your new map preview has been added to the game! + +Follow the instructions [HERE](#using-the-map-previews) to link the map preview to a map. + diff --git a/docs/tutorials/img/map_preview_screen/HGSS_Ruins_of_Alph-Day.png b/docs/tutorials/img/map_preview_screen/HGSS_Ruins_of_Alph-Day.png new file mode 100644 index 0000000000..41c43eaf0f Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/HGSS_Ruins_of_Alph-Day.png differ diff --git a/docs/tutorials/img/map_preview_screen/TS_image_to_tiles.png b/docs/tutorials/img/map_preview_screen/TS_image_to_tiles.png new file mode 100644 index 0000000000..54fbfc8156 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/TS_image_to_tiles.png differ diff --git a/docs/tutorials/img/map_preview_screen/TS_palettes_15.png b/docs/tutorials/img/map_preview_screen/TS_palettes_15.png new file mode 100644 index 0000000000..dd6a08137e Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/TS_palettes_15.png differ diff --git a/docs/tutorials/img/map_preview_screen/TS_palettes_16.png b/docs/tutorials/img/map_preview_screen/TS_palettes_16.png new file mode 100644 index 0000000000..3443093f81 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/TS_palettes_16.png differ diff --git a/docs/tutorials/img/map_preview_screen/TS_palettes_fade_in.png b/docs/tutorials/img/map_preview_screen/TS_palettes_fade_in.png new file mode 100644 index 0000000000..df7a550128 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/TS_palettes_fade_in.png differ diff --git a/docs/tutorials/img/map_preview_screen/TS_palettes_initial.png b/docs/tutorials/img/map_preview_screen/TS_palettes_initial.png new file mode 100644 index 0000000000..80630a0ec5 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/TS_palettes_initial.png differ diff --git a/docs/tutorials/img/map_preview_screen/TS_tiles.png b/docs/tutorials/img/map_preview_screen/TS_tiles.png new file mode 100644 index 0000000000..51030e7cf7 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/TS_tiles.png differ diff --git a/docs/tutorials/img/map_preview_screen/alph_map_preview_image.png b/docs/tutorials/img/map_preview_screen/alph_map_preview_image.png new file mode 100644 index 0000000000..766818b60c Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/alph_map_preview_image.png differ diff --git a/docs/tutorials/img/map_preview_screen/aseprite_15_palettes.png b/docs/tutorials/img/map_preview_screen/aseprite_15_palettes.png new file mode 100644 index 0000000000..50e36c1d98 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/aseprite_15_palettes.png differ diff --git a/docs/tutorials/img/map_preview_screen/aseprite_16_palettes.png b/docs/tutorials/img/map_preview_screen/aseprite_16_palettes.png new file mode 100644 index 0000000000..1b94f4b4c2 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/aseprite_16_palettes.png differ diff --git a/docs/tutorials/img/map_preview_screen/aseprite_2_palettes.png b/docs/tutorials/img/map_preview_screen/aseprite_2_palettes.png new file mode 100644 index 0000000000..d07d0a462f Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/aseprite_2_palettes.png differ diff --git a/docs/tutorials/img/map_preview_screen/aseprite_3_palettes.png b/docs/tutorials/img/map_preview_screen/aseprite_3_palettes.png new file mode 100644 index 0000000000..1f7b895b15 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/aseprite_3_palettes.png differ diff --git a/docs/tutorials/img/map_preview_screen/aseprite_complete_pal_fade.png b/docs/tutorials/img/map_preview_screen/aseprite_complete_pal_fade.png new file mode 100644 index 0000000000..de667635a9 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/aseprite_complete_pal_fade.png differ diff --git a/docs/tutorials/img/map_preview_screen/aseprite_index_example.png b/docs/tutorials/img/map_preview_screen/aseprite_index_example.png new file mode 100644 index 0000000000..392f078e7c Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/aseprite_index_example.png differ diff --git a/docs/tutorials/img/map_preview_screen/gale_15_palettes.png b/docs/tutorials/img/map_preview_screen/gale_15_palettes.png new file mode 100644 index 0000000000..08f8deba0b Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/gale_15_palettes.png differ diff --git a/docs/tutorials/img/map_preview_screen/gale_16_palettes.png b/docs/tutorials/img/map_preview_screen/gale_16_palettes.png new file mode 100644 index 0000000000..ae643e94e8 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/gale_16_palettes.png differ diff --git a/docs/tutorials/img/map_preview_screen/gale_2_palettes.png b/docs/tutorials/img/map_preview_screen/gale_2_palettes.png new file mode 100644 index 0000000000..c1d4a2ac77 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/gale_2_palettes.png differ diff --git a/docs/tutorials/img/map_preview_screen/gale_3_palettes.png b/docs/tutorials/img/map_preview_screen/gale_3_palettes.png new file mode 100644 index 0000000000..4194eaffdb Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/gale_3_palettes.png differ diff --git a/docs/tutorials/img/map_preview_screen/gale_8bpp.png b/docs/tutorials/img/map_preview_screen/gale_8bpp.png new file mode 100644 index 0000000000..1f71a75cd6 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/gale_8bpp.png differ diff --git a/docs/tutorials/img/map_preview_screen/gale_color_depth.png b/docs/tutorials/img/map_preview_screen/gale_color_depth.png new file mode 100644 index 0000000000..c482b19bec Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/gale_color_depth.png differ diff --git a/docs/tutorials/img/map_preview_screen/gale_complete_pal_fade.png b/docs/tutorials/img/map_preview_screen/gale_complete_pal_fade.png new file mode 100644 index 0000000000..fd4e4643b2 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/gale_complete_pal_fade.png differ diff --git a/docs/tutorials/img/map_preview_screen/image_to_tiles_window.png b/docs/tutorials/img/map_preview_screen/image_to_tiles_window.png new file mode 100644 index 0000000000..30c85155a9 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/image_to_tiles_window.png differ diff --git a/docs/tutorials/img/map_preview_screen/image_to_tiles_window_filled.png b/docs/tutorials/img/map_preview_screen/image_to_tiles_window_filled.png new file mode 100644 index 0000000000..ac9a1f66a8 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/image_to_tiles_window_filled.png differ diff --git a/docs/tutorials/img/map_preview_screen/map_name_frlg.png b/docs/tutorials/img/map_preview_screen/map_name_frlg.png new file mode 100644 index 0000000000..31b13571d9 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/map_name_frlg.png differ diff --git a/docs/tutorials/img/map_preview_screen/map_name_frlg_pal.png b/docs/tutorials/img/map_preview_screen/map_name_frlg_pal.png new file mode 100644 index 0000000000..86e6a70962 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/map_name_frlg_pal.png differ diff --git a/docs/tutorials/img/map_preview_screen/map_name_vivid.png b/docs/tutorials/img/map_preview_screen/map_name_vivid.png new file mode 100644 index 0000000000..e105b5460e Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/map_name_vivid.png differ diff --git a/docs/tutorials/img/map_preview_screen/map_name_vivid_pal.png b/docs/tutorials/img/map_preview_screen/map_name_vivid_pal.png new file mode 100644 index 0000000000..11cff90eda Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/map_name_vivid_pal.png differ diff --git a/docs/tutorials/img/map_preview_screen/map_preview_example.gif b/docs/tutorials/img/map_preview_screen/map_preview_example.gif new file mode 100644 index 0000000000..88507f56b6 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/map_preview_example.gif differ diff --git a/docs/tutorials/img/map_preview_screen/numbered_palette.png b/docs/tutorials/img/map_preview_screen/numbered_palette.png new file mode 100644 index 0000000000..d4c9d508cb Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/numbered_palette.png differ diff --git a/docs/tutorials/img/map_preview_screen/ruins_of_alph_basic.gif b/docs/tutorials/img/map_preview_screen/ruins_of_alph_basic.gif new file mode 100644 index 0000000000..fab14b14b8 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/ruins_of_alph_basic.gif differ diff --git a/docs/tutorials/img/map_preview_screen/ruins_of_alph_cave.gif b/docs/tutorials/img/map_preview_screen/ruins_of_alph_cave.gif new file mode 100644 index 0000000000..3ac6ab7e0d Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/ruins_of_alph_cave.gif differ diff --git a/docs/tutorials/img/map_preview_screen/ruins_of_alph_fade.gif b/docs/tutorials/img/map_preview_screen/ruins_of_alph_fade.gif new file mode 100644 index 0000000000..1c02e1bace Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/ruins_of_alph_fade.gif differ diff --git a/docs/tutorials/img/map_preview_screen/templates/map_preview_template.png b/docs/tutorials/img/map_preview_screen/templates/map_preview_template.png new file mode 100644 index 0000000000..dd57cf0636 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/templates/map_preview_template.png differ diff --git a/docs/tutorials/img/map_preview_screen/templates/map_preview_template_long.png b/docs/tutorials/img/map_preview_screen/templates/map_preview_template_long.png new file mode 100644 index 0000000000..ccabc0f6a1 Binary files /dev/null and b/docs/tutorials/img/map_preview_screen/templates/map_preview_template_long.png differ diff --git a/include/config/map_preview_screen.h b/include/config/map_preview_screen.h new file mode 100644 index 0000000000..61272578c9 --- /dev/null +++ b/include/config/map_preview_screen.h @@ -0,0 +1,13 @@ +#ifndef GUARD_CONFIG_MAP_PREVIEW_H +#define GUARD_CONFIG_MAP_PREVIEW_H + +#define MPS_ENABLE_MAP_PREVIEWS IS_FRLG // Enables map previews. + +#define MPS_DURATION_LONG 120 // This is the number of frames the map preview will last when the player enters the map for the first time. +#define MPS_DURATION_SHORT 40 // This is the number of frames the map preview will last if the player has visited the map before. +#define MPS_DURATION_NO_FLAG 40 // This is the number of frames the map preview will last if the map's flagId is MPS_FLAG_NULL. +#define MPS_BASIC_FADE_SPEED 1 // This sets the speed that the map preview fades to black when MPS_TYPE_BASIC is used. + // Numbers less than 1 will have a shorter fade time (negative numbers can be used). + // Numbers greater than 1 will have a longer fade time. + +#endif // GUARD_CONFIG_MAP_PREVIEW_H diff --git a/include/constants/global.h b/include/constants/global.h index e7df979ede..21bfb129d1 100644 --- a/include/constants/global.h +++ b/include/constants/global.h @@ -25,6 +25,7 @@ #include "config/follower_npc.h" #include "config/general.h" #include "config/item.h" +#include "config/map_preview_screen.h" #include "config/overworld.h" #include "config/pokemon.h" #include "config/summary_screen.h" diff --git a/include/fldeff.h b/include/fldeff.h index d1b9e279c3..ab7fcec3f7 100644 --- a/include/fldeff.h +++ b/include/fldeff.h @@ -55,4 +55,6 @@ bool8 FldEff_UseRockSmash(void); bool32 SetUpFieldMove_Defog(void); bool8 FldEff_Defog(void); +void Task_EnterCaveTransition2(u8 taskId); + #endif // GUARD_FLDEFF_H diff --git a/include/map_preview_screen.h b/include/map_preview_screen.h index c548f7c2f2..10fc09ab3f 100644 --- a/include/map_preview_screen.h +++ b/include/map_preview_screen.h @@ -34,31 +34,36 @@ enum MapPreviewScreenId MPS_COUNT }; -#define MPS_TYPE_CAVE 0 -#define MPS_TYPE_FOREST 1 -#define MPS_TYPE_ANY 2 +#define MPS_TYPE_CAVE 0 +#define MPS_TYPE_FADE_IN 1 +#define MPS_TYPE_BASIC 2 +#define MPS_TYPE_ANY 3 + +#define MPS_FLAG_NULL 0 struct MapPreviewScreen { mapsec_u8_t mapsec; u8 type; + u8 usesAllPalettes; u16 flagId; const void *tilesptr; const void *tilemapptr; const void *palptr; }; +bool32 ShouldRunMapPreview(void); u16 MapPreview_CreateMapNameWindow(u8 id); -void MapPreview_SetFlag(u16 a0); u16 MapPreview_GetDuration(u8 id); -bool8 MapHasPreviewScreen(mapsec_u8_t mapsec, u8 type); -bool32 ForestMapPreviewScreenIsRunning(void); -const struct MapPreviewScreen * GetDungeonMapPreviewScreenInfo(mapsec_u8_t mapsec); -bool32 MapHasPreviewScreen_HandleQLState2(mapsec_u8_t mapsec, u8 type); +bool32 CurrentMapHasPreviewScreen(u8 type); +bool32 FadeInMapPreviewScreenIsRunning(void); void MapPreview_InitBgs(void); void MapPreview_LoadGfx(mapsec_u8_t mapsec); bool32 MapPreview_IsGfxLoadFinished(void); void MapPreview_Unload(s32 windowId); -void MapPreview_StartForestTransition(mapsec_u8_t mapsec); +void RunMapPreviewScreenNonFade(u8 mapSecId); +void RunMapPreviewScreenFadeIn(mapsec_u8_t mapsec); +void Task_MapPreviewScreen_NonFade(u8 taskId); +void MapPreview_SetFlag(u16 flagId); #endif //GUARD_MAP_PREVIEW_SCREEN_H diff --git a/include/overworld.h b/include/overworld.h index b3aed23ae3..70e4c81a59 100644 --- a/include/overworld.h +++ b/include/overworld.h @@ -147,6 +147,7 @@ enum MapType GetMapTypeByGroupAndId(s8 mapGroup, s8 mapNum); enum MapType GetMapTypeByWarpData(struct WarpData *warp); enum MapType GetCurrentMapType(void); enum MapType GetLastUsedWarpMapType(void); +mapsec_u8_t GetLastUsedWarpMapSectionId(void); bool8 IsMapTypeOutdoors(enum MapType mapType); bool8 Overworld_MapTypeAllowsTeleportAndFly(enum MapType mapType); bool8 IsMapTypeIndoors(enum MapType mapType); diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index 792df979a0..10d21cc2b5 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -20,6 +20,7 @@ #include "link_rfu.h" #include "load_save.h" #include "main.h" +#include "map_preview_screen.h" #include "menu.h" #include "mirage_tower.h" #include "metatile_behavior.h" @@ -384,7 +385,10 @@ static void Task_ExitDoor(u8 taskId) } break; case 4: - UnlockPlayerFieldControls(); + // Don't unlock controls until the map preview has finished. + if (!FadeInMapPreviewScreenIsRunning()) + UnlockPlayerFieldControls(); + DestroyTask(taskId); break; } @@ -431,7 +435,10 @@ static void Task_ExitNonAnimDoor(u8 taskId) } break; case 3: - UnlockPlayerFieldControls(); + // Don't unlock controls until the map preview has finished. + if (!FadeInMapPreviewScreenIsRunning()) + UnlockPlayerFieldControls(); + DestroyTask(taskId); break; } @@ -450,7 +457,10 @@ static void Task_ExitNonDoor(u8 taskId) if (WaitForWeatherFadeIn()) { UnfreezeObjectEvents(); - UnlockPlayerFieldControls(); + // Don't unlock controls until the map preview has finished. + if (!FadeInMapPreviewScreenIsRunning()) + UnlockPlayerFieldControls(); + DestroyTask(taskId); } break; diff --git a/src/field_weather.c b/src/field_weather.c index 2b2c172047..0149b6891e 100644 --- a/src/field_weather.c +++ b/src/field_weather.c @@ -169,7 +169,7 @@ static const u8 ALIGNED(2) sBasePaletteColorMapTypes[32] = COLOR_MAP_DARK_CONTRAST, COLOR_MAP_DARK_CONTRAST, COLOR_MAP_DARK_CONTRAST, - COLOR_MAP_DARK_CONTRAST, + COLOR_MAP_NONE, COLOR_MAP_NONE, COLOR_MAP_NONE, // sprite palettes diff --git a/src/fldeff_flash.c b/src/fldeff_flash.c index 2ae6b256e1..cbf753cd63 100644 --- a/src/fldeff_flash.c +++ b/src/fldeff_flash.c @@ -7,6 +7,7 @@ #include "fldeff.h" #include "gpu_regs.h" #include "main.h" +#include "map_preview_screen.h" #include "overworld.h" #include "palette.h" #include "party_menu.h" @@ -36,7 +37,6 @@ static void Task_ExitCaveTransition4(u8 taskId); static void Task_ExitCaveTransition5(u8 taskId); static void DoEnterCaveTransition(void); static void Task_EnterCaveTransition1(u8 taskId); -static void Task_EnterCaveTransition2(u8 taskId); static void Task_EnterCaveTransition3(u8 taskId); static void Task_EnterCaveTransition4(u8 taskId); @@ -157,6 +157,12 @@ static bool8 TryDoMapTransition(void) enum MapType fromType = GetLastUsedWarpMapType(); enum MapType toType = GetCurrentMapType(); + if (ShouldRunMapPreview() && (CurrentMapHasPreviewScreen(MPS_TYPE_CAVE) == TRUE || CurrentMapHasPreviewScreen(MPS_TYPE_BASIC) == TRUE)) + { + RunMapPreviewScreenNonFade(gMapHeader.regionMapSectionId); + return TRUE; + } + for (i = 0; sTransitionTypes[i].fromType; i++) { if (sTransitionTypes[i].fromType == fromType && sTransitionTypes[i].toType == toType) @@ -298,7 +304,7 @@ static void Task_EnterCaveTransition1(u8 taskId) gTasks[taskId].func = Task_EnterCaveTransition2; } -static void Task_EnterCaveTransition2(u8 taskId) +void Task_EnterCaveTransition2(u8 taskId) { SetGpuReg(REG_OFFSET_DISPCNT, 0); DecompressDataWithHeaderVram(sCaveTransitionTiles, (void *)(VRAM + 0xC000)); diff --git a/src/map_preview_screen.c b/src/map_preview_screen.c index 0844b0c3de..61e5850ea5 100644 --- a/src/map_preview_screen.c +++ b/src/map_preview_screen.c @@ -2,7 +2,10 @@ #include "event_data.h" #include "field_screen_effect.h" #include "field_weather.h" +#include "fldeff.h" #include "gpu_regs.h" +#include "io_reg.h" +#include "main.h" #include "malloc.h" #include "map_preview_screen.h" #include "menu.h" @@ -12,14 +15,12 @@ #include "script.h" #include "string_util.h" #include "constants/region_map_sections.h" +#include "constants/rgb.h" static EWRAM_DATA bool8 sHasVisitedMapBefore = FALSE; - -#if IS_FRLG - static EWRAM_DATA bool8 sAllocedBg0TilemapBuffer = FALSE; -static void Task_RunMapPreviewScreenForest(u8 taskId); +static void Task_MapPreviewScreen_FadeIn(u8 taskId); static const u8 sViridianForestMapPreviewPalette[] = INCBIN_U8("graphics/map_preview/viridian_forest/tiles.gbapal"); static const u8 sViridianForestMapPreviewTiles[] = INCBIN_U8("graphics/map_preview/viridian_forest/tiles.4bpp.smol"); @@ -88,7 +89,7 @@ static const u8 sAlteringCaveMapPreviewTilemap[] = INCBIN_U8("graphics/map_previ static const struct MapPreviewScreen sMapPreviewScreenData[MPS_COUNT] = { [MPS_VIRIDIAN_FOREST] = { .mapsec = MAPSEC_VIRIDIAN_FOREST, - .type = MPS_TYPE_FOREST, + .type = MPS_TYPE_FADE_IN, .flagId = FLAG_WORLD_MAP_VIRIDIAN_FOREST, .tilesptr = sViridianForestMapPreviewTiles, .tilemapptr = sViridianForestMapPreviewTilemap, @@ -128,7 +129,7 @@ static const struct MapPreviewScreen sMapPreviewScreenData[MPS_COUNT] = { }, [MPS_SAFARI_ZONE] = { .mapsec = MAPSEC_KANTO_SAFARI_ZONE, - .type = MPS_TYPE_FOREST, + .type = MPS_TYPE_FADE_IN, .flagId = FLAG_WORLD_MAP_SAFARI_ZONE_CENTER, .tilesptr = sSafariZoneMapPreviewTiles, .tilemapptr = sSafariZoneMapPreviewTilemap, @@ -144,7 +145,7 @@ static const struct MapPreviewScreen sMapPreviewScreenData[MPS_COUNT] = { }, [MPS_POKEMON_MANSION] = { .mapsec = MAPSEC_POKEMON_MANSION, - .type = MPS_TYPE_FOREST, + .type = MPS_TYPE_FADE_IN, .flagId = FLAG_WORLD_MAP_POKEMON_MANSION_1F, .tilesptr = sPokemonMansionMapPreviewTiles, .tilemapptr = sPokemonMansionMapPreviewTilemap, @@ -152,7 +153,7 @@ static const struct MapPreviewScreen sMapPreviewScreenData[MPS_COUNT] = { }, [MPS_ROCKET_HIDEOUT] = { .mapsec = MAPSEC_ROCKET_HIDEOUT, - .type = MPS_TYPE_FOREST, + .type = MPS_TYPE_FADE_IN, .flagId = FLAG_WORLD_MAP_ROCKET_HIDEOUT_B1F, .tilesptr = sRocketHideoutMapPreviewTiles, .tilemapptr = sRocketHideoutMapPreviewTilemap, @@ -184,7 +185,7 @@ static const struct MapPreviewScreen sMapPreviewScreenData[MPS_COUNT] = { }, [MPS_POWER_PLANT] = { .mapsec = MAPSEC_POWER_PLANT, - .type = MPS_TYPE_FOREST, + .type = MPS_TYPE_FADE_IN, .flagId = FLAG_WORLD_MAP_POWER_PLANT, .tilesptr = sPowerPlantMapPreviewTiles, .tilemapptr = sPowerPlantMapPreviewTilemap, @@ -200,7 +201,7 @@ static const struct MapPreviewScreen sMapPreviewScreenData[MPS_COUNT] = { }, [MPS_ROCKET_WAREHOUSE] = { .mapsec = MAPSEC_ROCKET_WAREHOUSE, - .type = MPS_TYPE_FOREST, + .type = MPS_TYPE_FADE_IN, .flagId = FLAG_WORLD_MAP_THREE_ISLAND_BERRY_FOREST, .tilesptr = sRocketWarehouseMapPreviewTiles, .tilemapptr = sRocketWarehouseMapPreviewTilemap, @@ -224,7 +225,7 @@ static const struct MapPreviewScreen sMapPreviewScreenData[MPS_COUNT] = { }, [MPS_BERRY_FOREST] = { .mapsec = MAPSEC_BERRY_FOREST, - .type = MPS_TYPE_FOREST, + .type = MPS_TYPE_FADE_IN, .flagId = FLAG_WORLD_MAP_THREE_ISLAND_BERRY_FOREST, .tilesptr = sBerryForestMapPreviewTiles, .tilemapptr = sBerryForestMapPreviewTilemap, @@ -256,7 +257,7 @@ static const struct MapPreviewScreen sMapPreviewScreenData[MPS_COUNT] = { }, [MPS_PATTERN_BUSH] = { .mapsec = MAPSEC_PATTERN_BUSH, - .type = MPS_TYPE_FOREST, + .type = MPS_TYPE_FADE_IN, .flagId = FLAG_WORLD_MAP_SIX_ISLAND_PATTERN_BUSH, .tilesptr = sViridianForestMapPreviewTiles, .tilemapptr = sViridianForestMapPreviewTilemap, @@ -322,12 +323,30 @@ static const struct WindowTemplate sMapNameWindow = { .baseBlock = 0x1C2 }; +static const struct WindowTemplate sMapNameWindowLarge = { + .bg = 0, + .tilemapLeft = 0, + .tilemapTop = 0, + .width = 22, + .height = 2, + .paletteNum = 14, + .baseBlock = 0x259 +}; + static const struct BgTemplate sMapPreviewBgTemplate[1] = { { .mapBaseIndex = 31 } }; +bool32 ShouldRunMapPreview(void) +{ + if (MPS_ENABLE_MAP_PREVIEWS && FlagGet(FLAG_HIDE_MAP_NAME_POPUP) != TRUE && GetLastUsedWarpMapSectionId() != gMapHeader.regionMapSectionId) + return TRUE; + + return FALSE; +} + static u8 GetMapPreviewScreenIdx(mapsec_u8_t mapsec) { s32 i; @@ -342,21 +361,17 @@ static u8 GetMapPreviewScreenIdx(mapsec_u8_t mapsec) return MPS_COUNT; } -bool8 MapHasPreviewScreen(mapsec_u8_t mapsec, u8 type) +bool32 CurrentMapHasPreviewScreen(u8 type) { u8 idx; - idx = GetMapPreviewScreenIdx(mapsec); + idx = GetMapPreviewScreenIdx(gMapHeader.regionMapSectionId); if (idx != MPS_COUNT) { if (type == MPS_TYPE_ANY) - { return TRUE; - } else - { return sMapPreviewScreenData[idx].type == type ? TRUE : FALSE; - } } else { @@ -364,11 +379,6 @@ bool8 MapHasPreviewScreen(mapsec_u8_t mapsec, u8 type) } } -bool32 MapHasPreviewScreen_HandleQLState2(mapsec_u8_t mapsec, u8 type) -{ - return MapHasPreviewScreen(mapsec, type); -} - void MapPreview_InitBgs(void) { InitBgsFromTemplates(0, sMapPreviewBgTemplate, NELEMS(sMapPreviewBgTemplate)); @@ -382,20 +392,24 @@ void MapPreview_LoadGfx(mapsec_u8_t mapsec) idx = GetMapPreviewScreenIdx(mapsec); if (idx != MPS_COUNT) { - ResetTempTileDataBuffers(); - LoadPalette(sMapPreviewScreenData[idx].palptr, BG_PLTT_ID(13), 3 * PLTT_SIZE_4BPP); - DecompressAndCopyTileDataToVram(0, sMapPreviewScreenData[idx].tilesptr, 0, 0, 0); - if (GetBgTilemapBuffer(0) == NULL) - { - SetBgTilemapBuffer(0, Alloc(BG_SCREEN_SIZE)); - sAllocedBg0TilemapBuffer = TRUE; - } - else - { - sAllocedBg0TilemapBuffer = FALSE; - } - CopyToBgTilemapBuffer(0, sMapPreviewScreenData[idx].tilemapptr, 0, 0x000); - CopyBgTilemapBufferToVram(0); + ResetTempTileDataBuffers(); + if (sMapPreviewScreenData[idx].usesAllPalettes) + LoadPalette(sMapPreviewScreenData[idx].palptr, BG_PLTT_ID(0), 16 * PLTT_SIZE_4BPP); + else + LoadPalette(sMapPreviewScreenData[idx].palptr, BG_PLTT_ID(13), 3 * PLTT_SIZE_4BPP); + + DecompressAndCopyTileDataToVram(0, sMapPreviewScreenData[idx].tilesptr, 0, 0, 0); + if (GetBgTilemapBuffer(0) == NULL) + { + SetBgTilemapBuffer(0, Alloc(BG_SCREEN_SIZE)); + sAllocedBg0TilemapBuffer = TRUE; + } + else + { + sAllocedBg0TilemapBuffer = FALSE; + } + CopyToBgTilemapBuffer(0, sMapPreviewScreenData[idx].tilemapptr, 0, 0x000); + CopyBgTilemapBufferToVram(0); } } @@ -413,33 +427,12 @@ bool32 MapPreview_IsGfxLoadFinished(void) return FreeTempTileDataBuffersIfPossible(); } -void MapPreview_StartForestTransition(mapsec_u8_t mapsec) -{ - u8 taskId; - - taskId = CreateTask(Task_RunMapPreviewScreenForest, 0); - gTasks[taskId].data[2] = GetBgAttribute(0, BG_ATTR_PRIORITY); - gTasks[taskId].data[4] = GetGpuReg(REG_OFFSET_BLDCNT); - gTasks[taskId].data[5] = GetGpuReg(REG_OFFSET_BLDALPHA); - gTasks[taskId].data[3] = GetGpuReg(REG_OFFSET_DISPCNT); - gTasks[taskId].data[6] = GetGpuReg(REG_OFFSET_WININ); - gTasks[taskId].data[7] = GetGpuReg(REG_OFFSET_WINOUT); - gTasks[taskId].data[10] = MapPreview_GetDuration(mapsec); - gTasks[taskId].data[8] = 16; - gTasks[taskId].data[9] = 0; - SetBgAttribute(0, BG_ATTR_PRIORITY, 0); - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ | BLDCNT_TGT2_BD); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); - SetGpuRegBits(REG_OFFSET_WININ, WININ_WIN0_CLR | WININ_WIN1_CLR); - SetGpuRegBits(REG_OFFSET_WINOUT, WINOUT_WIN01_CLR); - gTasks[taskId].data[11] = MapPreview_CreateMapNameWindow(mapsec); - LockPlayerFieldControls(); -} - u16 MapPreview_CreateMapNameWindow(mapsec_u8_t mapsec) { u16 windowId; u32 xctr; + s32 stringWidth; + u32 fontId; #ifdef BUGFIX // Fixes access violations indicated below. u8 color[3]; @@ -447,123 +440,243 @@ u16 MapPreview_CreateMapNameWindow(mapsec_u8_t mapsec) u8 color[0]; #endif - windowId = AddWindow(&sMapNameWindow); + GetMapName(gStringVar4, mapsec, 0); + // Use a longer window size if the map name is too long to fit. + fontId = GetFontIdToFit(gStringVar4, FONT_NORMAL, 0, 104); + stringWidth = GetStringWidth(fontId, gStringVar4, 0); + if (stringWidth > 104) + { + windowId = AddWindow(&sMapNameWindowLarge); + xctr = 177 - stringWidth; + } + else + { + xctr = 104 - stringWidth; + windowId = AddWindow(&sMapNameWindow); + } FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); PutWindowTilemap(windowId); color[0] = TEXT_COLOR_WHITE; // Access violation color[1] = TEXT_COLOR_RED; // Access violation color[2] = TEXT_COLOR_LIGHT_GRAY; // Access violation - GetMapName(gStringVar4, mapsec, 0); - xctr = 104 - GetStringWidth(FONT_NORMAL, gStringVar4, 0); - AddTextPrinterParameterized4(windowId, FONT_NORMAL, xctr / 2, 2, 0, 0, color/* Access violation */, -1, gStringVar4); + AddTextPrinterParameterized4(windowId, fontId, xctr / 2, 2, 0, 0, color/* Access violation */, -1, gStringVar4); return windowId; } -bool32 ForestMapPreviewScreenIsRunning(void) +#define tState data[0] +#define tCounter data[1] +#define tDuration data[2] +#define tMapSecId data[3] +#define tWindowId data[4] + +void RunMapPreviewScreenNonFade(u8 mapSecId) { - if (FuncIsActiveTask(Task_RunMapPreviewScreenForest) == TRUE) + u8 taskId = CreateTask(Task_MapPreviewScreen_NonFade, 0); + gTasks[taskId].tMapSecId = mapSecId; +} + +void Task_MapPreviewScreen_NonFade(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + switch (tState) { - return FALSE; - } - else - { - return TRUE; + case 0: + SetWordTaskArg(taskId, 5, (uintptr_t)gMain.vblankCallback); + SetVBlankCallback(NULL); + MapPreview_InitBgs(); + MapPreview_LoadGfx(tMapSecId); + BlendPalettes(PALETTES_ALL, 0x10, RGB_WHITE); + tState++; + break; + case 1: + if (!MapPreview_IsGfxLoadFinished()) + { + tWindowId = MapPreview_CreateMapNameWindow(tMapSecId); + CopyWindowToVram(tWindowId, COPYWIN_FULL); + tState++; + } + break; + case 2: + if (!IsDma3ManagerBusyWithBgCopy()) + { + if (CurrentMapHasPreviewScreen(MPS_TYPE_CAVE)) + BeginNormalPaletteFade(PALETTES_ALL, -1, 16, 0, RGB_WHITE); + else + BeginNormalPaletteFade(PALETTES_ALL, -1, 16, 0, RGB_BLACK); + + SetVBlankCallback((IntrCallback)GetWordTaskArg(taskId, 5)); + tState++; + } + break; + case 3: + if (!UpdatePaletteFade()) + { + tDuration = MapPreview_GetDuration(tMapSecId); + tState++; + } + break; + case 4: + tCounter++; + if (tCounter > tDuration || JOY_NEW(B_BUTTON)) + { + if (CurrentMapHasPreviewScreen(MPS_TYPE_CAVE)) + BeginNormalPaletteFade(PALETTES_ALL, -2, 0, 16, RGB_WHITE); + else + BeginNormalPaletteFade(PALETTES_ALL, MPS_BASIC_FADE_SPEED, 0, 16, RGB_BLACK); + tState++; + } + break; + case 5: + if (!UpdatePaletteFade()) + { + int i; + for (i = 0; i < 16; i++) + { + data[i] = 0; + } + MapPreview_Unload(tWindowId); + if (CurrentMapHasPreviewScreen(MPS_TYPE_CAVE)) + gTasks[taskId].func = Task_EnterCaveTransition2; + else + SetMainCallback2(gMain.savedCallback); + } + break; } } -static void Task_RunMapPreviewScreenForest(u8 taskId) +#undef tDuration +#undef tMapSecId +#undef tWindowId + +#define tBGPriority data[2] +#define tDISPCNT data[3] +#define tBLDCNT data[4] +#define tBLDALPHA data[5] +#define tWININ data[6] +#define tWINOUT data[7] +#define tBlendTgt1 data[8] +#define tBlendTgt2 data[9] +#define tDuration data[10] +#define tWindowId data[11] + +void RunMapPreviewScreenFadeIn(mapsec_u8_t mapsec) +{ + u8 taskId; + + taskId = CreateTask(Task_MapPreviewScreen_FadeIn, 0); + gTasks[taskId].tBGPriority = GetBgAttribute(0, BG_ATTR_PRIORITY); + gTasks[taskId].tBLDCNT = GetGpuReg(REG_OFFSET_BLDCNT); + gTasks[taskId].tBLDALPHA = GetGpuReg(REG_OFFSET_BLDALPHA); + gTasks[taskId].tDISPCNT = GetGpuReg(REG_OFFSET_DISPCNT); + gTasks[taskId].tWININ = GetGpuReg(REG_OFFSET_WININ); + gTasks[taskId].tWINOUT = GetGpuReg(REG_OFFSET_WINOUT); + gTasks[taskId].tDuration = MapPreview_GetDuration(mapsec); + gTasks[taskId].tBlendTgt1 = 16; + gTasks[taskId].tBlendTgt2 = 0; + SetBgAttribute(0, BG_ATTR_PRIORITY, 0); + SetGpuRegBits(REG_OFFSET_WININ, WININ_WIN0_CLR | WININ_WIN1_CLR); + SetGpuRegBits(REG_OFFSET_WINOUT, WINOUT_WIN01_CLR); + gTasks[taskId].tWindowId = MapPreview_CreateMapNameWindow(mapsec); + LockPlayerFieldControls(); +} + +bool32 FadeInMapPreviewScreenIsRunning(void) +{ + return FuncIsActiveTask(Task_MapPreviewScreen_FadeIn); +} + +static void Task_MapPreviewScreen_FadeIn(u8 taskId) { s16 * data; data = gTasks[taskId].data; - switch (data[0]) + switch (tState) { case 0: if (!MapPreview_IsGfxLoadFinished() && !IsDma3ManagerBusyWithBgCopy()) { - CopyWindowToVram(data[11], COPYWIN_FULL); - data[0]++; + CopyWindowToVram(tWindowId, COPYWIN_FULL); + tState++; } break; case 1: if (!IsDma3ManagerBusyWithBgCopy()) { FadeInFromBlack(); - data[0]++; + tState++; } break; case 2: if (IsWeatherNotFadingIn()) { Overworld_PlaySpecialMapMusic(); - data[0]++; + tState++; } break; case 3: - data[1]++; - if (data[1] > data[10]) + tCounter++; + if (tCounter > tDuration || JOY_NEW(B_BUTTON)) { - data[1] = 0; - data[0]++; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ | BLDCNT_TGT2_BD); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + tCounter = 0; + tState++; } break; case 4: - switch (data[1]) + switch (tCounter) { case 0: - data[9]++; - if (data[9] > 16) + tBlendTgt2++; + if (tBlendTgt2 > 16) { - data[9] = 16; + tBlendTgt2 = 16; } break; case 1: - data[8]--; - if (data[8] < 0) + tBlendTgt1--; + if (tBlendTgt1 < 0) { - data[8] = 0; + tBlendTgt1 = 0; } break; } - data[1] = (data[1] + 1) % 3; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(data[8], data[9])); - if (data[8] == 0 && data[9] == 16) + tCounter = (tCounter + 1) % 3; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(tBlendTgt1, tBlendTgt2)); + if (tBlendTgt1 == 0 && tBlendTgt2 == 16) { FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 32, 32); CopyBgTilemapBufferToVram(0); - data[0]++; + tState++; } break; case 5: if (!IsDma3ManagerBusyWithBgCopy()) { - MapPreview_Unload(data[11]); - SetBgAttribute(0, BG_ATTR_PRIORITY, data[2]); - SetGpuReg(REG_OFFSET_DISPCNT, data[3]); - SetGpuReg(REG_OFFSET_BLDCNT, data[4]); - SetGpuReg(REG_OFFSET_BLDALPHA, data[5]); - SetGpuReg(REG_OFFSET_WININ, data[6]); - SetGpuReg(REG_OFFSET_WINOUT, data[7]); + MapPreview_Unload(tWindowId); + SetBgAttribute(0, BG_ATTR_PRIORITY, tBGPriority); + SetGpuReg(REG_OFFSET_DISPCNT, tDISPCNT); + SetGpuReg(REG_OFFSET_BLDCNT, tBLDCNT); + SetGpuReg(REG_OFFSET_BLDALPHA, tBLDALPHA); + SetGpuReg(REG_OFFSET_WININ, tWININ); + SetGpuReg(REG_OFFSET_WINOUT, tWINOUT); + UnlockPlayerFieldControls(); DestroyTask(taskId); } break; } } -const struct MapPreviewScreen * GetDungeonMapPreviewScreenInfo(mapsec_u8_t mapsec) -{ - u8 idx; - - idx = GetMapPreviewScreenIdx(mapsec); - if (idx == MPS_COUNT) - { - return NULL; - } - else - { - return &sMapPreviewScreenData[idx]; - } -} +#undef tBGPriority +#undef tDISPCNT +#undef tBLDCNT +#undef tBLDALPHA +#undef tWININ +#undef tWINOUT +#undef tBlendTgt1 +#undef tBlendTgt2 +#undef tDuration +#undef tWindowId u16 MapPreview_GetDuration(mapsec_u8_t mapsec) { @@ -571,36 +684,30 @@ u16 MapPreview_GetDuration(mapsec_u8_t mapsec) u16 flagId; idx = GetMapPreviewScreenIdx(mapsec); + if (idx == MPS_COUNT) - { return 0; - } + flagId = sMapPreviewScreenData[idx].flagId; - if (sMapPreviewScreenData[idx].type == MPS_TYPE_CAVE) + + if (flagId == MPS_FLAG_NULL) + { + return MPS_DURATION_NO_FLAG; + } + else { if (!FlagGet(flagId)) { - return 120; + FlagSet(flagId); + return MPS_DURATION_LONG; } else { - return 40; - } - } - else { - if (sHasVisitedMapBefore) - { - return 120; - } - else - { - return 40; + return MPS_DURATION_SHORT; } } } -#endif // IS_FRLG - void MapPreview_SetFlag(u16 flagId) { if (!FlagGet(flagId)) @@ -613,3 +720,88 @@ void MapPreview_SetFlag(u16 flagId) } FlagSet(flagId); } + +static void VblankCB_MapPreviewScript(void) +{ + TransferPlttBuffer(); +} + +static void CB2_MapPreviewScript(void) +{ + RunTasks(); + DoScheduledBgTilemapCopiesToVram(); + UpdatePaletteFade(); +} + +#define tTaskStep data[0] +#define tFrameCounter data[1] +#define tWindowId data[2] +#define tDuration data[3] + +static void Task_MapPreviewScreen_Script(u8 taskId) +{ + s16 *data; + + data = gTasks[taskId].data; + switch (tTaskStep) + { + case 0: + if (!UpdatePaletteFade()) + { + SetVBlankCallback(NULL); + MapPreview_LoadGfx(gMapHeader.regionMapSectionId); + BlendPalettes(PALETTES_ALL, 16, RGB_BLACK); + gMain.savedCallback = CB2_ReturnToFieldContinueScript; + SetMainCallback2(CB2_MapPreviewScript); + tTaskStep++; + } + break; + case 1: + if (!MapPreview_IsGfxLoadFinished() && !IsDma3ManagerBusyWithBgCopy()) + { + tWindowId = MapPreview_CreateMapNameWindow(gMapHeader.regionMapSectionId); + CopyWindowToVram(tWindowId, COPYWIN_FULL); + tTaskStep++; + } + break; + case 2: + if (!IsDma3ManagerBusyWithBgCopy()) + { + SetVBlankCallback(VblankCB_MapPreviewScript); + FadeInFromBlack(); + tTaskStep++; + } + break; + case 3: + tFrameCounter++; + if (tFrameCounter > tDuration || JOY_NEW(B_BUTTON)) + { + BeginNormalPaletteFade(PALETTES_ALL, MPS_BASIC_FADE_SPEED, 0, 16, RGB_BLACK); + tFrameCounter = 0; + tTaskStep++; + } + break; + case 4: + if (!UpdatePaletteFade()) + { + MapPreview_Unload(tWindowId); + DestroyTask(taskId); + SetMainCallback2(gMain.savedCallback); + } + break; + } +} + +void MapPreviewScript(struct ScriptContext *ctx) +{ + u32 duration = ScriptReadHalfword(ctx); + u32 taskId; + + if (!CurrentMapHasPreviewScreen(MPS_TYPE_ANY)) + return; + + ScriptContext_Stop(); + FadeScreen(FADE_TO_BLACK, 0); + taskId = CreateTask(Task_MapPreviewScreen_Script, 0); + gTasks[taskId].tDuration = duration; +} diff --git a/src/overworld.c b/src/overworld.c index 1d8a3fd4b7..2c1f3555f3 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -39,6 +39,7 @@ #include "malloc.h" #include "m4a.h" #include "map_name_popup.h" +#include "map_preview_screen.h" #include "match_call.h" #include "menu.h" #include "metatile_behavior.h" @@ -1510,6 +1511,11 @@ enum MapType GetLastUsedWarpMapType(void) return GetMapTypeByWarpData(&gLastUsedWarp); } +mapsec_u8_t GetLastUsedWarpMapSectionId(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gLastUsedWarp.mapGroup, gLastUsedWarp.mapNum)->regionMapSectionId; +} + bool8 IsMapTypeOutdoors(enum MapType mapType) { if (mapType == MAP_TYPE_ROUTE @@ -2302,7 +2308,12 @@ static bool32 LoadMapInStepsLocal(u8 *state, bool32 a2) (*state)++; break; case 11: - if (gMapHeader.showMapName == TRUE && SecretBaseMapPopupEnabled() == TRUE) + if (ShouldRunMapPreview() && CurrentMapHasPreviewScreen(MPS_TYPE_FADE_IN) == TRUE) + { + MapPreview_LoadGfx(gMapHeader.regionMapSectionId); + RunMapPreviewScreenFadeIn(gMapHeader.regionMapSectionId); + } + else if (gMapHeader.showMapName == TRUE && SecretBaseMapPopupEnabled() == TRUE) ShowMapNamePopup(); (*state)++; break;