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: Add support for palette changes in external textures + optimizations #617

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
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,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
Loading