Skip to content

Commit

Permalink
FF8: Add support for palette changes in external textures (#617)
Browse files Browse the repository at this point in the history
  • Loading branch information
myst6re committed Nov 1, 2023
1 parent d1a7099 commit 639ec28
Show file tree
Hide file tree
Showing 16 changed files with 1,694 additions and 1,128 deletions.
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
- 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: 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
13 changes: 7 additions & 6 deletions docs/ff8/mods/external_textures.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ Except for the Menu module, you can add the language at the beginning of the pat

Path: `{mod_path}\cardgame`

| File name | Description | Animated |
| --------- | ----------------------- | -------- |
| cards_00 | Cards front and back | No |
| game_00 | Game background | No |
| icons_00 | Numbers, icons and text | No |
| intro_00 | Intro/outro background | No |
| File name | Description | Animated | Multi palettes |
| --------- | ----------------------- | -------- | -------------- |
| cards_00 | Cards front and back | No | No |
| game_00 | Game background | No | No |
| icons_00 | Numbers, icons and text | No | No |
| intro_00 | Intro/outro background | No | No |
| font_00 | Font (unused) | No | Yes (2) |

## Battle

Expand Down
104 changes: 29 additions & 75 deletions src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,6 @@ GamepadAnalogueIntent gamepad_analogue_intent = INTENT_NONE;
uint32_t *image_data_cache = nullptr;
uint32_t image_data_size_cache = 0;

uint8_t *image_data_scaled_cache = nullptr;
uint32_t image_data_scaled_size_cache = 0;

uint32_t noop() { return 0; }
uint32_t noop_a1(uint32_t a1) { return 0; }
uint32_t noop_a2(uint32_t a1, uint32_t a2) { return 0; }
Expand Down Expand Up @@ -1429,40 +1426,6 @@ void blit_framebuffer_texture(struct texture_set *texture_set, struct tex_header
);
}


// Scale 32-bit BGRA image in place
void scale_up_image_data_in_place(uint8_t *sourceAndTarget, int w, int h, int scale)
{
if (scale <= 1)
{
return;
}

uint32_t *source = (uint32_t *)sourceAndTarget + w * h,
*target = (uint32_t *)sourceAndTarget + (w * scale) * (h * scale);

for (int y = 0; y < h; ++y)
{
uint32_t *source_line_start = source;

for (int i = 0; i < scale; ++i)
{
source = source_line_start;

for (int x = 0; x < w; ++x)
{
source -= 1;
target -= scale;

for (int i = 0; i < scale; ++i)
{
target[i] = *source;
}
}
}
}
}

// load modpath texture for tex file, returns true if successful
uint32_t load_external_texture(void* image_data, uint32_t dataSize, struct texture_set *texture_set, struct tex_header *tex_header, uint32_t originalWidth, uint32_t originalHeight)
{
Expand Down Expand Up @@ -1505,50 +1468,31 @@ uint32_t load_external_texture(void* image_data, uint32_t dataSize, struct textu
}
else if(ff8)
{
uint8_t scale = texturePacker.getMaxScale(VREF(tex_header, image_data));
uint8_t *image_data_scaled = (uint8_t *)image_data;

if (scale > 1)
{
uint32_t image_data_size = originalWidth * scale * originalHeight * scale * 4;
// Allocate with cache
if (image_data_scaled_size_cache == 0 || image_data_size > image_data_scaled_size_cache) {
if (image_data_scaled_cache != nullptr) {
driver_free(image_data_scaled_cache);
}
image_data_scaled_cache = (uint8_t*)driver_malloc(image_data_size);
image_data_scaled_size_cache = image_data_size;
}

image_data_scaled = image_data_scaled_cache;

// convert source data
if (image_data_scaled != nullptr)
{
memcpy(image_data_scaled, image_data, dataSize);
scale_up_image_data_in_place(image_data_scaled, originalWidth, originalHeight, scale);
}
}
uint32_t *image_data_scaled = nullptr;
uint8_t scale = 1;
TexturePacker::TextureTypes textureType = texturePacker.drawTextures(
VREF(tex_header, image_data), reinterpret_cast<uint32_t *>(image_data), dataSize, originalWidth, originalHeight,
VREF(tex_header, palette_index) / 2,
&scale, &image_data_scaled
);

TexturePacker::TextureTypes textureType = TexturePacker::NoTexture;
if (save_textures && textureType != TexturePacker::InternalTexture) return false;

if (image_data_scaled != nullptr && scale > 0)
if (textureType == TexturePacker::NoTexture)
{
textureType = texturePacker.drawTextures(VREF(tex_header, image_data), tex_format, (uint32_t *)image_data_scaled, (uint32_t *)image_data, originalWidth, originalHeight, scale, VREF(tex_header, palette_index));
if(VREF(texture_set, ogl.external)) stats.external_textures--;
VRASS(texture_set, ogl.external, false);
}

if(save_textures && textureType != TexturePacker::InternalTexture) return false;

if (textureType != TexturePacker::NoTexture)
else if (textureType == TexturePacker::RemoveTexture)
{
VREF(texture_set, ogl.width) = originalWidth * scale;
VREF(texture_set, ogl.height) = originalHeight * scale;
texture = newRenderer.createTexture(image_data_scaled, VREF(texture_set, ogl.width), VREF(texture_set, ogl.height));
ffnx_trace("Remove texture\n");
return true;
}
else
{
if(VREF(texture_set, ogl.external)) stats.external_textures--;
VRASS(texture_set, ogl.external, false);
VREF(texture_set, ogl.width) = originalWidth * scale;
VREF(texture_set, ogl.height) = originalHeight * scale;
texture = newRenderer.createTexture(reinterpret_cast<uint8_t *>(image_data_scaled), VREF(texture_set, ogl.width), VREF(texture_set, ogl.height));
}

if (textureType == TexturePacker::InternalTexture)
Expand Down Expand Up @@ -1768,8 +1712,18 @@ struct texture_set *common_load_texture(struct texture_set *_texture_set, struct
if(tex_format->palettes == 0) tex_format->palettes = VREF(tex_header, palette_entries);

// convert texture data from source format and load it
if(texture_format != 0 && VREF(tex_header, image_data) != 0 && (! ff8 || ! texturePacker.drawTexturesBackgroundIsDisabled()))
if(texture_format != 0 && VREF(tex_header, image_data) != 0)
{
if (ff8)
{
// 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))
{
return _texture_set;
}
}

// detect changes in palette data for FF8, we can't trust it to notify us
if(ff8 && VREF(tex_header, palettes) > 0 && VREF(tex_header, version) != FB_TEX_VERSION && tex_format->bytesperpixel == 1)
{
Expand Down Expand Up @@ -1904,7 +1858,7 @@ uint32_t common_write_palette(uint32_t source_offset, uint32_t size, void *sourc
VOBJ(texture_set, texture_set, texture_set);
VOBJ(tex_header, tex_header, VREF(texture_set, tex_header));

if(trace_all) ffnx_trace("dll_gfx: write_palette 0x%x, %i, %i, %i, 0x%x, 0x%x\n", texture_set, source_offset, dest_offset, size, source, palette->palette_entry);
if(trace_all) ffnx_trace("dll_gfx: write_palette 0x%x, %i, %i, %i, 0x%x, 0x%x, image_data=0x%X\n", texture_set, source_offset, dest_offset, size, source, palette->palette_entry, VREF(tex_header, image_data));

if(palette == 0) return false;

Expand Down
3 changes: 3 additions & 0 deletions src/ff8.h
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,9 @@ struct ff8_externals
uint32_t sub_462DF0;
uint32_t sub_461220;
uint32_t ssigpu_tx_select_2_sub_465CE0;
uint32_t write_palette_texture_set_sub_466190;
uint32_t read_vram_palette_sub_467370;
uint32_t write_palette_to_driver_sub_467310;
int (*sub_464F70)(struc_50 *, texture_page *, int, int, int, int, int, int, int, uint8_t *);
void(*read_vram_1)(uint8_t *, int, uint8_t *, int, signed int, int, int);
void(*read_vram_2_paletted)(uint8_t *, int, uint8_t *, int, signed int, int, int, uint16_t *);
Expand Down

0 comments on commit 639ec28

Please sign in to comment.