Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FF8: Better support for texture animation in WM #628

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
- Graphics: Fix texture glitches using external texture replacement ( https://github.com/julianxhokaxhiu/FFNx/pull/591 )
- Graphics: Fix external texture blending ( https://github.com/julianxhokaxhiu/FFNx/pull/598 https://github.com/julianxhokaxhiu/FFNx/pull/601 )
- Graphics: Add chara.one worldmap texture replacement ( https://github.com/julianxhokaxhiu/FFNx/pull/615 )
- Graphics: Add support for external texture animation ( https://github.com/julianxhokaxhiu/FFNx/pull/616 )
- Graphics: Add support for multiple palettes in external texture ( https://github.com/julianxhokaxhiu/FFNx/pull/617 )
- Graphics: Minimize texture uploads when the palette is not set yet ( https://github.com/julianxhokaxhiu/FFNx/pull/617 )
- Graphics: Add support for external texture animation ( https://github.com/julianxhokaxhiu/FFNx/pull/616 https://github.com/julianxhokaxhiu/FFNx/pull/628 )
- Graphics: Add support for multiple palettes in external texture ( https://github.com/julianxhokaxhiu/FFNx/pull/617 https://github.com/julianxhokaxhiu/FFNx/pull/628 )
- Graphics: Minimize texture uploads when the palette is not set yet ( https://github.com/julianxhokaxhiu/FFNx/pull/617 https://github.com/julianxhokaxhiu/FFNx/pull/628 )
- Graphics: Increase max texture size to 16384 for external textures ( https://github.com/julianxhokaxhiu/FFNx/pull/601 )
- Music: Add `ff8_external_music_force_original_filenames` option to use original music names (eg 018s-julia.ogg) instead of just the main identifier in external music ( https://github.com/julianxhokaxhiu/FFNx/pull/594 )
- Voice: Enable battle dialogs voice acting
Expand Down
105 changes: 105 additions & 0 deletions docs/ff8/mods/external_textures.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Texture names pattern in FF8 mostly follows the paths used in FS/FL/FI archives in the original game.

It is recommended to use uncompressed DDS for improved loading times.

Except for the Menu module, you can add the language at the beginning of the path for localization:
`{mod_path}\fre\cardgame\cards_00.dds`

Expand Down Expand Up @@ -31,10 +33,113 @@ Path: `{mod_path}\world`

Path: `{mod_path}\world\dat\wmset\section{section number}\texture{texture number}_00`

#### Section 17

Worldmap texture animations, replace `section38/texture21` and `section38/texture22`.

#### Section 38

| Section | Description | Animated | Multi palettes |
| -------------------------- | ---------------------------- | -------------- | -------------- |
| texture0_00 -> texture7_00 | Main textures | No | No |
| texture7_00 | Water texture (maybe unused) | No | Not sure |
| texture9_00 | Moon | No | No |
| texture10_00 | Sky | No | No |
| texture11_00 | Map | No | Yes (2) |
| texture12_00 | Circle Shadow | No | No |
| texture13_00 | Square Shadow | No | No |
| texture14_00 | Effect | No | Not sure |
| texture15_00 | Forest particles effect | No | Yes (6) |
| texture16_00 | Sea | Yes | Yes (6) |
| texture17_00 | Shallow water | Yes | Yes (6) |
| texture18_00 | Sea | Yes | Yes (6) |
| texture19_00 | River | Yes | Yes (6) |
| texture20_00 texture23_00 | Sea | No | No |
| texture21_00 texture22_00 | Beaches | See section 17 | No |
| texture24_00 | Map field of view | No | No |
| texture25_00 | Map character orientation | No | No |
| texture26_00 | Effect | No | No |
| texture27_00 | Effect | No | No |
| texture28_00 | Effect | No | No |
| texture29_00 | Effect | No | No |
| texture30_00 | Effect | No | No |
| texture31_00 | Effect | No | No |
| texture32_00 | Effect | No | No |
| texture33_00 | Effect | No | No |
| texture34_00 | Effect | No | No |
| texture35_00 | City barrier disk 4 | No | No |

#### Section 39

Rails and roads.

#### Section 40

| File name | Description | Animated | Multi palettes |
| ----------- | --------------------- | -------- | -------------- |
| texture0_00 | Esthar extra texture | No | No |

#### Section 42

Some mobile models.

| File name | Description |
| ------------ | ----------------------- |
| texture0_00 | BGU |
| texture1_00 | BGU (copy) |
| texture2_00 | Luxury blue locomotive |
| texture3_00 | Luxury blue wagon |
| texture4_00 | Luxury green locomotive |
| texture5_00 | Luxury green wagon |
| texture6_00 | Old locomotive |
| texture7_00 | Old wagon |
| texture8_00 | Grey Freight Wagon |
| texture9_00 | Yellow car |
| texture10_00 | Galbadia military car |
| texture11_00 | Galbadia military car |
| texture12_00 | Unknown |
| texture13_00 | Unknown |
| texture14_00 | Unknown |
| texture15_00 | Unknown |
| texture16_00 | Unknown |
| texture17_00 | Green car |
| texture18_00 | Brown car |
| texture19_00 | Blue car |
| texture20_00 | Mint car |
| texture21_00 | Pink car |
| texture22_00 | Yellow Esthar car |
| texture23_00 | Blue Esthar car |
| texture24_00 | Unknown |
| texture25_00 | Lunatic Pandora |
| texture26_00 | Lunatic Pandora |
| texture27_00 | Lunatic Pandora |
| texture28_00 | Disk 4 doors |
| texture29_00 | City barrier disk 4 |
| texture30_00 | Jumbo Cactuar |
| texture31_00 | Rocks |
| texture32_00 | City barrier disk 4 |

### texl.obj

Path: `{mod_path}\world\dat\texl\texture{texture number}_00`

High res version of `wmset\section38\texture{0,7}_00`. Will be loaded by the game as you travel the worldmap.
Ideally, for a smooth experience, keep `wmset\section38\texture{0,7}_00` texture resolution
low (and uncompressed DDS) and increase the resolution in the texl directory.

### chara.one

Path: `{mod_path}\world\esk\chara_one\model{model number}-{texture number}_00`

| File name | Description |
| -------------------------- | ---------------- |
| model0-0_00 -> model0-1_00 | Squall |
| model1-0_00 -> model1-3_00 | Ragnarok |
| model2-0_00 -> model3-1_00 | Chocobos |
| model4-0_00 -> model4-1_00 | Squall (Student) |
| model5-0_00 -> model5-1_00 | Zell |
| model6-0_00 -> model6-1_00 | Selphie (unused) |

## Menu

Path: `{mod_path}\data\{lang}\menu`
Expand Down
4 changes: 3 additions & 1 deletion src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,6 @@ uint32_t load_external_texture(void* image_data, uint32_t dataSize, struct textu
}
else if (textureType == TexturePacker::RemoveTexture)
{
ffnx_trace("Remove texture\n");
return true;
}
else
Expand Down Expand Up @@ -1718,8 +1717,11 @@ struct texture_set *common_load_texture(struct texture_set *_texture_set, struct
{
// optimization to not upload textures with undefined VRAM palette
TexturePacker::TiledTex tiledTex = texturePacker.getTiledTex(VREF(tex_header, image_data));

if (tiledTex.isValid() && !tiledTex.isPaletteValid(VREF(tex_header, palette_index) / 2))
{
if(trace_all || trace_vram) ffnx_trace("dll_gfx: load_texture ignored pointer=0x%X pos=(%d, %d) bpp=%d\n", VREF(tex_header, image_data), tiledTex.x(), tiledTex.y(), tiledTex.bpp());

return _texture_set;
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/ff8.h
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,9 @@ struct ff8_externals
uint32_t cdcheck_main_loop;
uint32_t cdcheck_sub_52F9E0;
uint32_t main_entry;
uint8_t *config_worldmap_fog_disabled;
uint8_t *config_worldmap_color_anim_disabled;
uint8_t *config_worldmap_textured_anim_disabled;
uint32_t init_config;
uint32_t (*reg_get_data_drive)(char*, DWORD);
void (*set_game_paths)(int, char *, const char *);
Expand Down Expand Up @@ -1066,14 +1069,19 @@ struct ff8_externals
uint32_t worldmap_main_loop;
uint32_t worldmap_enter_main;
uint32_t worldmap_sub_53F310;
uint32_t worldmap_sub_53F310_call_24D;
uint32_t worldmap_sub_53F310_call_2A9;
uint32_t worldmap_sub_53F310_call_30D;
uint32_t worldmap_sub_53F310_call_330;
uint32_t worldmap_sub_53F310_call_366;
uint32_t worldmap_sub_53F310_call_3B5;
uint32_t worldmap_sub_53F310_loc_53F7EE;
uint32_t worldmap_wmset_set_pointers_sub_542DA0;
uint32_t worldmap_sub_541970_upload_tim;
uint32_t worldmap_sub_548020;
uint32_t worldmap_sub_5531F0;
uint32_t worldmap_sub_554AA0;
uint32_t worldmap_sub_554AA0_call_C2;
uint32_t worldmap_alter_uv_sub_553B40;
uint32_t worldmap_sub_545E20;
uint32_t worldmap_chara_one;
Expand All @@ -1082,9 +1090,12 @@ struct ff8_externals
uint32_t open_file_world_sub_52D670_texl_call2;
uint32_t upload_psxvram_texl_pal_call1;
uint32_t upload_psxvram_texl_pal_call2;
uint32_t **worldmap_section17_position;
uint32_t **worldmap_section18_position;
uint32_t **worldmap_section38_position;
uint32_t **worldmap_section39_position;
uint32_t **worldmap_section40_position;
uint32_t **worldmap_section41_position;
uint32_t **worldmap_section42_position;
uint32_t (*worldmap_prepare_tim_for_upload)(uint8_t *, ff8_tim *);
uint32_t engine_eval_process_input;
Expand Down Expand Up @@ -1139,6 +1150,11 @@ struct ff8_externals
uint32_t sub_54E9B0;
uint32_t sub_550070;
int (*sub_541C80)(int);
uint32_t sub_559240;
uint32_t sub_554940;
uint32_t sub_554940_call_130;
uint32_t sub_541AE0;
uint32_t sub_554BC0;
uint32_t sub_54B460;
uint32_t sub_558D70;
uint32_t sub_545EA0;
Expand Down
11 changes: 11 additions & 0 deletions src/ff8/field/background.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ std::vector<Tile> ff8_background_parse_tiles(const uint8_t *map_data)
return tiles;
}

void ff8_background_tiles_to_map(const std::vector<Tile> &tiles, uint8_t *map_data)
{
for (const Tile &tile: tiles) {
memcpy(map_data, (const void *)&tile, sizeof(Tile));

map_data += sizeof(Tile);
}

*(uint16_t *)map_data = 0x7fff;
}

void ff8_background_draw_tile(const Tile &tile, uint32_t *target, const uint16_t target_width, const uint8_t* const textures_data, const uint16_t* const palettes_data)
{
Tim::Bpp bpp = Tim::Bpp((tile.texID >> 7) & 3);
Expand Down
1 change: 1 addition & 0 deletions src/ff8/field/background.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ struct Tile {
bool ff8_background_tiles_looks_alike(const Tile &tile, const Tile &other);

std::vector<Tile> ff8_background_parse_tiles(const uint8_t *map_data);
void ff8_background_tiles_to_map(const std::vector<Tile> &tiles, uint8_t *map_data);
bool ff8_background_save_textures(const std::vector<Tile> &tiles, const uint8_t *mim_data, const char *filename);
bool ff8_background_save_textures_legacy(const std::vector<Tile> &tiles, const uint8_t *mim_data, const char *filename);
21 changes: 17 additions & 4 deletions src/ff8/mod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ bool ModdedTexture::findExternalTexture(const char *name, char *filename, uint8_
{
char langPath[16] = "/";

if(trace_all || trace_loaders) ffnx_trace("texture file name (VRAM): %s\n", name);
if(trace_all || trace_loaders) ffnx_trace("texture file name (VRAM): %s palette_index=%d hasPal=%d\n", name, palette_index, hasPal);

if(save_textures) return false;

Expand Down Expand Up @@ -282,11 +282,12 @@ TextureModStandard::~TextureModStandard()
}
}

bool TextureModStandard::createImages(int internalLodScale)
bool TextureModStandard::createImages(int paletteCount, int internalLodScale)
{
if (trace_all || trace_vram) ffnx_trace("TextureModStandard::%s: internalLodScale=%d\n", __func__, internalLodScale);
paletteCount = paletteCount >= 0 ? paletteCount : originalTexture().palette().h(); // Works most of the time

if (trace_all || trace_vram) ffnx_trace("TextureModStandard::%s: paletteCount=%d internalLodScale=%d\n", __func__, paletteCount, internalLodScale);

int paletteCount = originalTexture().palette().h(); // Works most of the time
int modCount = std::max(paletteCount, 1);
char filename[MAX_PATH] = {}, *extension = nullptr, found_extension[16] = {};

Expand All @@ -313,6 +314,11 @@ bool TextureModStandard::createImages(int internalLodScale)

uint8_t TextureModStandard::computePaletteId(int vramPalXBpp2, int vramPalY) const
{
if (_currentPalette >= 0)
{
return uint8_t(_currentPalette);
}

if (vramPalXBpp2 == originalTexture().palette().x()
&& vramPalY >= originalTexture().palette().y() && vramPalY < originalTexture().palette().y() + originalTexture().palette().h())
{
Expand Down Expand Up @@ -433,6 +439,13 @@ void TextureModStandard::copyRect(
}
}

void TextureModStandard::forceCurrentPalette(int8_t currentPalette)
{
if (_textures.contains(currentPalette)) {
_currentPalette = currentPalette;
}
}

TextureBackground::TextureBackground(
const TexturePacker::IdentifiedTexture &originalTexture,
const std::vector<Tile> &mapTiles,
Expand Down
10 changes: 6 additions & 4 deletions src/ff8/mod.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ class ModdedTexture {

class TextureModStandard : public ModdedTexture {
public:
TextureModStandard(const TexturePacker::IdentifiedTexture &originalTexture) : ModdedTexture(originalTexture), _lastDrawnPalette(0) {}
TextureModStandard(const TexturePacker::IdentifiedTexture &originalTexture) : ModdedTexture(originalTexture), _currentPalette(-1) {}
TextureModStandard(const TextureModStandard &other) = delete;
~TextureModStandard();
inline bool canCopyRect() const override {
return true;
}
bool createImages(int internalLodScale = 1);
bool createImages(int paletteCount, int internalLodScale = 1);
uint8_t scale(int vramPalXBpp2, int vramPalY) const override;
TexturePacker::TextureTypes drawToImage(
int offsetX, int offsetY,
Expand All @@ -120,12 +120,14 @@ class TextureModStandard : public ModdedTexture {
void copyRect(int sourceXBpp2, int sourceY, int sourceWBpp2, int sourceH, int targetXBpp2, int targetY);
// Copy rect to another textures
void copyRect(int sourceXBpp2, int sourceY, int sourceWBpp2, int sourceH, int targetXBpp2, int targetY, const TextureModStandard &targetTexture);
// Set to -1 to unforce
void forceCurrentPalette(int8_t currentPalette);
private:
bool createImage(const char *name, int paletteId = -1, const char *extension = nullptr, char *foundExtension = nullptr);
uint8_t computePaletteId(int vramPalXBpp2, int vramPalY) const;
const TextureImage &textureImage(uint8_t paletteId) const;
std::map<uint8_t, TextureImage> _textures; // Index: paletteId
uint8_t _lastDrawnPalette;
std::map<uint8_t, TextureImage> _textures; // Index: paletteId or current texture
int8_t _currentPalette;
};

class TextureBackground : public ModdedTexture {
Expand Down
Loading