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

Add support for decompressing Etc, Etc2, ASTC images #214

Merged
merged 12 commits into from
Nov 6, 2024
Merged
2 changes: 1 addition & 1 deletion .github/workflows/all_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ env:
# Change the README too
GODOT_MAIN_SYNC_REF: ef8d981267702de38ffc24136f9d823d31781c60
SCONSFLAGS: verbose=yes warnings=all werror=no module_text_server_fb_enabled=yes minizip=yes debug_symbols=no deprecated=yes
SCONSFLAGS_TEMPLATE: no_editor_splash=yes module_camera_enabled=no module_mobile_vr_enabled=no module_upnp_enabled=no module_noise_enabled=no module_websocket_enabled=no use_static_cpp=yes builtin_freetype=yes builtin_libpng=yes builtin_zlib=yes builtin_libwebp=yes builtin_libvorbis=yes builtin_libogg=yes module_csg_enabled=yes module_gridmap_enabled=yes disable_3d=no
SCONSFLAGS_TEMPLATE: no_editor_splash=yes module_camera_enabled=no module_mobile_vr_enabled=no module_upnp_enabled=no module_websocket_enabled=no module_csg_enabled=yes module_gridmap_enabled=yes use_static_cpp=yes builtin_freetype=yes builtin_libpng=yes builtin_zlib=yes builtin_libwebp=yes builtin_libvorbis=yes builtin_libogg=yes disable_3d=no
SCONS_CACHE_MSVC_CONFIG: true

concurrency:
Expand Down
4 changes: 4 additions & 0 deletions SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Import("env")
Import("env_modules")


etcpak_dir = "#thirdparty/etcpak/"
mmp3thirdparty_dir = "#thirdparty/minimp3/"
liboggthirdparty_dir = "#thirdparty/libogg/"
webpthirdparty_dir = "#thirdparty/libwebp/"
Expand Down Expand Up @@ -117,6 +118,7 @@ def write_version_header():
write_version_header()


env_gdsdecomp.Prepend(CPPPATH=[etcpak_dir])
if env["builtin_libogg"]:
env_gdsdecomp.Prepend(CPPPATH=[liboggthirdparty_dir])
if env["builtin_libvorbis"]:
Expand All @@ -140,3 +142,5 @@ env_gdsdecomp.add_source_files(env.modules_sources, "exporters/*.cpp")
env_gdsdecomp.add_source_files(env.modules_sources, "utility/*.cpp")

env_gdsdecomp.add_source_files(env.modules_sources, "external/tga/*.cpp")
env_gdsdecomp.add_source_files(env.modules_sources, "external/etcpak-decompress/*.cpp")
env_gdsdecomp.add_source_files(env.modules_sources, "module_etc_decompress/*.cpp")
12 changes: 6 additions & 6 deletions bytecode/bytecode_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@
/* bytecode_base.cpp */
/*************************************************************************/

#include "bytecode/bytecode_base.h"
#include "bytecode_base.h"

#include "bytecode/bytecode_versions.h"
#include "bytecode/gdscript_tokenizer_compat.h"
#include "compat/file_access_encrypted_v3.h"
#include "compat/variant_decoder_compat.h"
#include "compat/variant_writer_compat.h"
#include "utility/common.h"
#include "utility/gdre_settings.h"
#include "utility/godotver.h"

#include "core/config/engine.h"
#include "core/error/error_list.h"
#include "core/error/error_macros.h"
#include "core/io/file_access.h"
#include "core/io/file_access_encrypted.h"
#include "core/io/marshalls.h"

#include "core/object/class_db.h"
#include "modules/gdscript/gdscript_tokenizer_buffer.h"
#include "utility/common.h"
#include "utility/gdre_settings.h"
#include "utility/godotver.h"

#include <limits.h>

Expand Down
5 changes: 1 addition & 4 deletions bytecode/bytecode_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@
/*************************************************************************/
#pragma once

#include "compat/variant_decoder_compat.h"
#include "utility/godotver.h"

#include "core/object/class_db.h"
#include "core/object/object.h"
#include "core/object/ref_counted.h"
#include "core/templates/rb_map.h"
#include "core/templates/vmap.h"
#include "utility/godotver.h"

class GDScriptDecomp : public RefCounted {
GDCLASS(GDScriptDecomp, RefCounted);
Expand Down
1 change: 0 additions & 1 deletion bytecode/bytecode_versions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// clang-format off

#include "bytecode/bytecode_versions.h"
#include "utility/godotver.h"

void register_decomp_versions() {
ClassDB::register_class<GDScriptDecomp_77af6ca>();
Expand Down
3 changes: 0 additions & 3 deletions bytecode/gdscript_tokenizer_compat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@
#include "gdscript_tokenizer_compat.h"

#include "compat/variant_decoder_compat.h"
#include "compat/variant_writer_compat.h"
#include "core/string/print_string.h"
#include "core/templates/rb_map.h"

const char *GDScriptTokenizerTextCompat::token_names[T::G_TK_MAX] = {
"Empty",
Expand Down
1 change: 0 additions & 1 deletion bytecode/gdscript_tokenizer_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#include "core/string/ustring.h"
#include "core/templates/pair.h"
#include "core/templates/rb_set.h"
#include "core/templates/vmap.h"
#include "core/variant/variant.h"

#include "utility/godotver.h"
Expand Down
2 changes: 2 additions & 0 deletions compat/oggstr_loader_compat.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "oggstr_loader_compat.h"
#include "core/error/error_macros.h"
#include "modules/vorbis/resource_importer_ogg_vorbis.h"

Ref<Resource> OggStreamConverterCompat::convert(const Ref<MissingResource> &res, ResourceInfo::LoadType p_type, int ver_major, Error *r_error) {
Expand All @@ -7,6 +8,7 @@ Ref<Resource> OggStreamConverterCompat::convert(const Ref<MissingResource> &res,
bool loop = res->get("loop");
double loop_offset = res->get("loop_offset");
Ref<AudioStreamOggVorbis> sample = ResourceImporterOggVorbis::load_from_buffer(data);
ERR_FAIL_COND_V_MSG(sample.is_null(), res, "Failed to load Ogg Vorbis stream from buffer.");
if (!name.is_empty()) {
sample->set_name(name);
}
Expand Down
10 changes: 3 additions & 7 deletions compat/resource_compat_text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ Error ResourceLoaderCompatText::load() {
MissingResource *missing_resource = nullptr;
Ref<ResourceCompatConverter> converter;

if (!is_real_load()) {
if (load_type == ResourceInfo::FAKE_LOAD) {
missing_resource = CompatFormatLoader::create_missing_internal_resource(path, type, id);
res = Ref<Resource>(missing_resource);
} else if (res.is_null()) {
Expand Down Expand Up @@ -790,10 +790,10 @@ Error ResourceLoaderCompatText::load() {
}
}
// clang-format on
if (!is_real_load()) {
if (load_type == ResourceInfo::FAKE_LOAD) {
missing_resource = CompatFormatLoader::create_missing_main_resource(local_path, res_type, res_uid);
resource = Ref<Resource>(missing_resource);
} else {
} else if (resource.is_null()) {
converter = ResourceCompatLoader::get_converter_for_type(res_type, ver_major);
if (converter.is_valid()) {
missing_resource = CompatFormatLoader::create_missing_main_resource(local_path, res_type, res_uid);
Expand All @@ -802,9 +802,6 @@ Error ResourceLoaderCompatText::load() {
}

if (!resource.is_valid()) {
if (!is_real_load()) {
WARN_PRINT("WE SHOULD NEVER GET HERE!!!!!!!!!!");
}
Object *obj = ClassDB::instantiate(res_type);
if (!obj) {
if (ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) {
Expand Down Expand Up @@ -2990,7 +2987,6 @@ ResourceInfo ResourceFormatLoaderCompatText::get_resource_info(const String &p_p
loader.progress = nullptr;
loader.res_path = loader.local_path;
loader.open(f);
err = loader.load();
_SET_R_ERR(err, r_error);
ERR_FAIL_COND_V_MSG(err, ResourceInfo(), "Cannot load file '" + p_path + "'.");
return loader.get_resource_info();
Expand Down
6 changes: 6 additions & 0 deletions compat/resource_loader_compat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,12 @@ String ResourceCompatConverter::get_resource_name(const Ref<Resource> &res, int
if (n.get_type() == Variant::STRING) {
name = n;
}
if (ver_major == 0) {
n = res->get("resource_name");
if (n.get_type() == Variant::STRING) {
name = n;
}
}
if (name.is_empty()) {
name = res->get_name();
}
Expand Down
147 changes: 75 additions & 72 deletions compat/texture_loader_compat.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
#include "texture_loader_compat.h"
#include "compat/texture_loader_compat.h"
#include "compat/image_enum_compat.h"
#include "compat/resource_compat_binary.h"
#include "compat/resource_loader_compat.h"
#include "compat/webp_compat.h"
#include "core/io/resource_loader.h"
#include "utility/resource_info.h"

#include "core/error/error_list.h"
#include "core/error/error_macros.h"
#include "core/io/file_access.h"
#include "core/io/missing_resource.h"
#include "core/variant/dictionary.h"
#include "image_enum_compat.h"
#include "scene/resources/compressed_texture.h"
#include "scene/resources/texture.h"
#include "utility/resource_info.h"
#include "webp_compat.h"

#include "utility/gdre_settings.h"

#include "core/io/file_access.h"

enum FormatBits {
FORMAT_MASK_IMAGE_FORMAT = (1 << 20) - 1,
Expand Down Expand Up @@ -707,63 +706,27 @@ Vector<Ref<Image>> TextureLoaderCompat::load_images_from_layered_tex(const Strin
}

bool ResourceConverterTexture2D::handles_type(const String &p_type, int ver_major) const {
return (p_type == "Texture" && ver_major == 2) || (p_type == "Texture2D") || (p_type == "ImageTexture") || (p_type == "StreamTexture") || (p_type == "CompressedTexture2D");
return (p_type == "Texture" && ver_major <= 3) || (p_type == "Texture2D") || (p_type == "StreamTexture") || (p_type == "CompressedTexture2D");
}

Ref<Resource> ResourceConverterTexture2D::convert(const Ref<MissingResource> &res, ResourceInfo::LoadType p_type, int ver_major, Error *r_error) {
String name;
Vector2 size;
int tw = 0;
int th = 0;
int tw_custom = 0;
int th_custom = 0;
int flags = 0;
Ref<Image> image;
Ref<Resource> image_res;
Ref<Resource> texture;

if (p_type == ResourceInfo::LoadType::NON_GLOBAL_LOAD) {
return res;
}
Dictionary compat_dict = (res->get_meta("compat", Dictionary()));
String type = res->get_original_class();

auto convert_image = [&](const Ref<Resource> &image_res) -> Ref<Image> {
Ref<Image> image = image_res;
if (image.is_null() && image_res->get_class() == "MissingResource") {
ImageConverterCompat ic;
if (ic.handles_type("Image", ver_major)) {
image = ic.convert(image_res, p_type, ver_major, r_error);
}
}
return image;
};
if ((type == "Texture" && ver_major == 2) || type == "ImageTexture") {
name = get_resource_name(res, ver_major);
image = convert_image(res->get("image"));
ERR_FAIL_COND_V_MSG(image.is_null(), res, "Cannot load resource '" + name + "'.");

size = res->get("size");
flags = res->get("flags");
bool mipmaps = flags & 1 || image->has_mipmaps();

image->set_name(name);
tw = image->get_width();
th = image->get_height();
if (size.width && tw != size.width) {
tw_custom = size.width;
}
if (size.height && th != size.height) {
th_custom = size.height;
}
texture = TextureLoaderCompat::create_image_texture(res->get_path(), p_type, tw, th, tw_custom, th_custom, mipmaps, image);
} else if (ver_major >= 3) {
if (p_type == ResourceInfo::LoadType::NON_GLOBAL_LOAD) {
return res;
}
flags = res->get("flags");
String load_path = res->get("load_path");
ResourceFormatLoaderCompatTexture2D tlc;
texture = tlc.custom_load(load_path, p_type, r_error);
} else {
ERR_FAIL_V_MSG(res, "Unsupported type: " + type);
int flags = res->get("flags");
String load_path = res->get("load_path");
if (p_type == ResourceInfo::GLTF_LOAD) {
texture = ResourceCompatLoader::gltf_load(load_path, type, r_error);
} else if (p_type == ResourceInfo::REAL_LOAD) {
texture = ResourceCompatLoader::real_load(load_path, type, ResourceFormatLoader::CACHE_MODE_IGNORE, r_error);
}
ERR_FAIL_COND_V_MSG(texture.is_null(), res, "Failed to load texture " + load_path);
if (compat_dict.size() > 0) {
texture->set_meta("compat", compat_dict);
}
Expand All @@ -774,12 +737,11 @@ Ref<Resource> ResourceConverterTexture2D::convert(const Ref<MissingResource> &re
void ResourceFormatLoaderCompatTexture2D::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("stex");
p_extensions->push_back("ctex");
p_extensions->push_back("tex");
}

// handles type
bool ResourceFormatLoaderCompatTexture2D::handles_type(const String &p_type) const {
return p_type == "CompressedTexture2D" || (p_type == "Texture2D") || p_type == "ImageTexture" || p_type == "StreamTexture" || p_type == "Texture";
return p_type == "CompressedTexture2D" || p_type == "StreamTexture";
}

// get resource type
Expand Down Expand Up @@ -836,7 +798,6 @@ ResourceInfo TextureLoaderCompat::get_resource_info(const String &p_path, Error
}
return ResourceInfo();
}
int ver_major = TextureLoaderCompat::get_ver_major_from_textype(t);
if (TextureLoaderCompat::is_binary_resource(t)) {
ResourceFormatLoaderCompatBinary rlcb;
return rlcb.get_resource_info(p_path, r_error);
Expand All @@ -859,13 +820,9 @@ Ref<Resource> ResourceFormatLoaderCompatTexture2D::custom_load(const String &p_p
return Ref<Resource>();
}
int lw, lh, lwc, lhc, lflags;
int ver_major = TextureLoaderCompat::get_ver_major_from_textype(t);
Ref<Resource> texture;
Ref<Image> image;
bool convert = false;
if (TextureLoaderCompat::is_binary_resource(t)) {
convert = true;
} else if (t == TextureLoaderCompat::FORMAT_V3_STREAM_TEXTURE2D) {
if (t == TextureLoaderCompat::FORMAT_V3_STREAM_TEXTURE2D) {
err = TextureLoaderCompat::_load_data_stex2d_v3(p_path, lw, lh, lwc, lhc, lflags, image);
} else if (t == TextureLoaderCompat::FORMAT_V4_COMPRESSED_TEXTURE2D) {
err = TextureLoaderCompat::_load_data_ctex2d_v4(p_path, lw, lh, lwc, lhc, image);
Expand All @@ -876,14 +833,7 @@ Ref<Resource> ResourceFormatLoaderCompatTexture2D::custom_load(const String &p_p
*r_error = err;
}
ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Failed to load texture " + p_path);
if (!convert) {
texture = _set_tex(p_path, p_type, lw, lh, lwc, lhc, lflags, image);
} else {
ResourceFormatLoaderCompatBinary rlcb;
Ref<Resource> res = rlcb.custom_load(p_path, ResourceInfo::LoadType::FAKE_LOAD, &err);
ResourceConverterTexture2D rc;
texture = rc.convert(res, p_type, ver_major, &err);
}
texture = _set_tex(p_path, p_type, lw, lh, lwc, lhc, lflags, image);
// TODO: Take care of the cache mode
set_res_path(texture, p_path, p_type);
auto info = TextureLoaderCompat::_get_resource_info(t);
Expand Down Expand Up @@ -1063,6 +1013,59 @@ Ref<Resource> ResourceFormatLoaderCompatTextureLayered::custom_load(const String
return texture;
}

bool ImageTextureConverterCompat::handles_type(const String &p_type, int ver_major) const {
return p_type == "ImageTexture";
}

Ref<Resource> ImageTextureConverterCompat::convert(const Ref<MissingResource> &res, ResourceInfo::LoadType p_type, int ver_major, Error *r_error) {
String name;
Vector2 size;
int tw = 0;
int th = 0;
int tw_custom = 0;
int th_custom = 0;
int flags = 0;
Ref<Image> image;
Ref<Resource> image_res;
Ref<Resource> texture;
Dictionary compat_dict = (res->get_meta("compat", Dictionary()));
String type = res->get_original_class();

auto convert_image = [&](const Ref<Resource> &image_res) -> Ref<Image> {
Ref<Image> image = image_res;
if (image.is_null() && image_res->get_class() == "MissingResource") {
ImageConverterCompat ic;
if (ic.handles_type("Image", ver_major)) {
image = ic.convert(image_res, p_type, ver_major, r_error);
}
}
return image;
};
ERR_FAIL_COND_V_MSG(type != "ImageTexture", res, "Unsupported type: " + type);
name = get_resource_name(res, ver_major);
image = convert_image(res->get("image"));
ERR_FAIL_COND_V_MSG(image.is_null(), res, "Cannot load image from ImageTexture resource '" + name + "'.");

size = res->get("size");
flags = res->get("flags");
bool mipmaps = flags & 1 || image->has_mipmaps();

image->set_name(name);
tw = image->get_width();
th = image->get_height();
if (size.width && tw != size.width) {
tw_custom = size.width;
}
if (size.height && th != size.height) {
th_custom = size.height;
}
texture = TextureLoaderCompat::create_image_texture(res->get_path(), p_type, tw, th, tw_custom, th_custom, mipmaps, image);
if (compat_dict.size() > 0) {
texture->set_meta("compat", compat_dict);
}
return texture;
}

bool ImageConverterCompat::handles_type(const String &p_type, int ver_major) const {
return (p_type == "Image") && ver_major == 3;
}
Expand Down
Loading
Loading