diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d9656c4060..e0a20f9030e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1631,32 +1631,16 @@ if(FIRST_RUN) endif() endif() -# set the endian define -if(MSVC) - # For some reason this fails on MSVC. - add_definitions(-D__LITTLE_ENDIAN__) - - # OSX-Note: as we do cross-compiling with specific set architecture, - # endianness-detection and auto-setting is counterproductive - # so we just set endianness according CMAKE_OSX_ARCHITECTURES - -elseif(CMAKE_OSX_ARCHITECTURES MATCHES i386 OR - CMAKE_OSX_ARCHITECTURES MATCHES x86_64 OR - CMAKE_OSX_ARCHITECTURES MATCHES arm64) - add_definitions(-D__LITTLE_ENDIAN__) -elseif(CMAKE_OSX_ARCHITECTURES MATCHES ppc OR CMAKE_OSX_ARCHITECTURES MATCHES ppc64) - add_definitions(-D__BIG_ENDIAN__) - +# Test endianness and set the endian define. +include(TestBigEndian) +test_big_endian(_SYSTEM_BIG_ENDIAN) +if(_SYSTEM_BIG_ENDIAN) + message(FATAL_ERROR "Blender does not support building on Big Endian systems" ) else() - include(TestBigEndian) - test_big_endian(_SYSTEM_BIG_ENDIAN) - if(_SYSTEM_BIG_ENDIAN) - add_definitions(-D__BIG_ENDIAN__) - else() - add_definitions(-D__LITTLE_ENDIAN__) - endif() - unset(_SYSTEM_BIG_ENDIAN) + add_definitions(-D__LITTLE_ENDIAN__) endif() +unset(_SYSTEM_BIG_ENDIAN) + if(WITH_IMAGE_OPENJPEG) # Special handling of Windows platform where openjpeg is always static. if(WIN32) diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.cc b/intern/guardedalloc/intern/mallocn_guarded_impl.cc index 1a5fae39ae9..966be293d07 100644 --- a/intern/guardedalloc/intern/mallocn_guarded_impl.cc +++ b/intern/guardedalloc/intern/mallocn_guarded_impl.cc @@ -174,11 +174,8 @@ static const char *check_memlist(const MemHead *memh); /* locally used defines */ /* --------------------------------------------------------------------- */ -#ifdef __BIG_ENDIAN__ -# define MAKE_ID(a, b, c, d) (int(a) << 24 | int(b) << 16 | (c) << 8 | (d)) -#else -# define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a)) -#endif +/* NOTE: this is endianness-sensitive. */ +#define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a)) #define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O') #define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L') diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c index 38a082b7e54..72a15a5dda9 100644 --- a/release/datafiles/userdef/userdef_default_theme.c +++ b/release/datafiles/userdef/userdef_default_theme.c @@ -14,13 +14,9 @@ /* clang-format off */ -#ifdef __LITTLE_ENDIAN__ -# define RGBA(c) {((c) >> 24) & 0xff, ((c) >> 16) & 0xff, ((c) >> 8) & 0xff, (c) & 0xff} -# define RGB(c) {((c) >> 16) & 0xff, ((c) >> 8) & 0xff, (c) & 0xff} -#else -# define RGBA(c) {(c) & 0xff, ((c) >> 8) & 0xff, ((c) >> 16) & 0xff, ((c) >> 24) & 0xff} -# define RGB(c) {(c) & 0xff, ((c) >> 8) & 0xff, ((c) >> 16) & 0xff} -#endif +/* NOTE: this is endianness-sensitive. */ +#define RGBA(c) {((c) >> 24) & 0xff, ((c) >> 16) & 0xff, ((c) >> 8) & 0xff, (c) & 0xff} +#define RGB(c) {((c) >> 16) & 0xff, ((c) >> 8) & 0xff, (c) & 0xff} const bTheme U_theme_default = { .name = "Default", diff --git a/source/blender/blendthumb/src/blendthumb.hh b/source/blender/blendthumb/src/blendthumb.hh index 628da011958..df2d14daa09 100644 --- a/source/blender/blendthumb/src/blendthumb.hh +++ b/source/blender/blendthumb/src/blendthumb.hh @@ -45,10 +45,5 @@ std::optional> blendthumb_create_png_data_from_thumb( eThumbStatus blendthumb_create_thumb_from_file(FileReader *rawfile, Thumbnail *thumb); /* INTEGER CODES */ -#ifdef __BIG_ENDIAN__ -/* Big Endian */ -# define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d)) -#else -/* Little Endian */ -# define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a)) -#endif +/* NOTE: this is endianness-sensitive. */ +#define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a)) diff --git a/source/blender/blendthumb/src/blendthumb_extract.cc b/source/blender/blendthumb/src/blendthumb_extract.cc index 74acf23fb4a..a8711151e11 100644 --- a/source/blender/blendthumb/src/blendthumb_extract.cc +++ b/source/blender/blendthumb/src/blendthumb_extract.cc @@ -14,7 +14,6 @@ #include "BLI_alloca.h" #include "BLI_endian_defines.h" -#include "BLI_endian_switch.h" #include "BLI_fileops.h" #include "BLI_filereader.h" #include "BLI_string.h" @@ -24,6 +23,8 @@ #include "blendthumb.hh" +BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems") + static void thumb_data_vertical_flip(Thumbnail *thumb) { uint32_t *rect = (uint32_t *)thumb->data.data(); @@ -43,13 +44,12 @@ static void thumb_data_vertical_flip(Thumbnail *thumb) free(line); } -static int32_t bytes_to_native_i32(const uint8_t bytes[4], bool endian_switch) +static int32_t bytes_to_native_i32(const uint8_t bytes[4]) { int32_t data; memcpy(&data, bytes, 4); - if (endian_switch) { - BLI_endian_switch_int32(&data); - } + /* NOTE: this is endianness-sensitive. */ + /* PNG is always little-endian, and would require switching on a big-endian system. */ return data; } @@ -84,12 +84,11 @@ static eThumbStatus blendthumb_extract_from_file_impl(FileReader *file, Thumbnail *thumb, const BlenderHeader &header) { - const bool endian_switch = header.endian != ENDIAN_ORDER; + BLI_assert(header.endian == L_ENDIAN); /* Iterate over file blocks until we find the thumbnail or run out of data. */ while (true) { /* Read next BHead. */ - const std::optional bhead = BLO_readfile_read_bhead( - file, header.bhead_type(), endian_switch); + const std::optional bhead = BLO_readfile_read_bhead(file, header.bhead_type()); if (!bhead.has_value()) { /* File has ended. */ return BT_INVALID_THUMB; @@ -104,8 +103,8 @@ static eThumbStatus blendthumb_extract_from_file_impl(FileReader *file, if (!file_read(file, shape, sizeof(shape))) { return BT_INVALID_THUMB; } - thumb->width = bytes_to_native_i32(&shape[0], endian_switch); - thumb->height = bytes_to_native_i32(&shape[4], endian_switch); + thumb->width = bytes_to_native_i32(&shape[0]); + thumb->height = bytes_to_native_i32(&shape[4]); /* Verify that image dimensions and data size make sense. */ size_t data_size = bhead->len - sizeof(shape); @@ -190,6 +189,13 @@ eThumbStatus blendthumb_create_thumb_from_file(FileReader *rawfile, Thumbnail *t return BT_EARLY_VERSION; } + /* Check if the file was written from a big-endian build. */ + if (header.endian != L_ENDIAN) { + file->close(file); + return BT_INVALID_FILE; + } + BLI_assert(header.endian == ENDIAN_ORDER); + /* Read the thumbnail. */ eThumbStatus err = blendthumb_extract_from_file_impl(file, thumb, header); file->close(file); diff --git a/source/blender/blendthumb/src/blendthumb_png.cc b/source/blender/blendthumb/src/blendthumb_png.cc index 4b979fd776a..89f6e1d81c4 100644 --- a/source/blender/blendthumb/src/blendthumb_png.cc +++ b/source/blender/blendthumb/src/blendthumb_png.cc @@ -21,9 +21,9 @@ static void png_extend_native_int32(blender::Vector &output, int32_t data) { - if (ENDIAN_ORDER == L_ENDIAN) { - BLI_endian_switch_int32(&data); - } + /* NOTE: this is endianness-sensitive. */ + /* PNG is big-endian, its values need to be switched on little-endian systems. */ + BLI_endian_switch_int32(&data); output.extend_unchecked(blender::Span((uint8_t *)&data, 4)); } diff --git a/source/blender/blenkernel/intern/action.cc b/source/blender/blenkernel/intern/action.cc index 8e362743d31..44c67fc4797 100644 --- a/source/blender/blenkernel/intern/action.cc +++ b/source/blender/blenkernel/intern/action.cc @@ -24,7 +24,6 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BLI_endian_switch.h" #include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math_color.h" @@ -671,12 +670,11 @@ static void read_slots(BlendDataReader *reader, animrig::Action &action) for (int i = 0; i < action.slot_array_num; i++) { BLO_read_struct(reader, ActionSlot, &action.slot_array[i]); - /* Undo generic endian switching, as the ID type values are not numerically the same between - * little and big endian machines. Due to the way they are defined, they are always in the same - * byte order, regardless of hardware/platform endianness. */ - if (BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_int16(&action.slot_array[i]->idtype); - } + /* NOTE: this is endianness-sensitive. */ + /* In case of required endian switching, this code would have to undo the generic endian + * switching, as the ID type values are not numerically the same between little and big endian + * machines. Due to the way they are defined, they are always in the same byte order, + * regardless of hardware/platform endianness. */ action.slot_array[i]->wrap().blend_read_post(); } @@ -686,12 +684,10 @@ static void action_blend_read_data(BlendDataReader *reader, ID *id) { animrig::Action &action = reinterpret_cast(id)->wrap(); - /* Undo generic endian switching (careful, only the two least significant bytes of the int32 must - * be swapped back here, since this value is actually an int16). */ - if (BLO_read_requires_endian_switch(reader)) { - bAction *act = reinterpret_cast(id); - BLI_endian_switch_int16(reinterpret_cast(&act->idroot)); - } + /* NOTE: this is endianness-sensitive. */ + /* In case of required endianness switching, this code would need to undo the generic endian + * switching (careful, only the two least significant bytes of the int32 must be swapped back + * here, since this value is actually an int16). */ read_strip_keyframe_data_array(reader, action); read_layers(reader, action); diff --git a/source/blender/blenkernel/intern/bake_items_serialize.cc b/source/blender/blenkernel/intern/bake_items_serialize.cc index 99aa33c54fd..1150be710c0 100644 --- a/source/blender/blenkernel/intern/bake_items_serialize.cc +++ b/source/blender/blenkernel/intern/bake_items_serialize.cc @@ -15,7 +15,6 @@ #include "BKE_volume.hh" #include "BLI_endian_defines.h" -#include "BLI_endian_switch.h" #include "BLI_listbase.h" #include "BLI_math_matrix_types.hh" #include "BLI_path_utils.hh" @@ -289,11 +288,8 @@ std::optional BlobReadSharing::read_shared( static StringRefNull get_endian_io_name(const int endian) { - if (endian == L_ENDIAN) { - return "little"; - } - BLI_assert(endian == B_ENDIAN); - return "big"; + BLI_assert(endian == L_ENDIAN); + return "little"; } static StringRefNull get_domain_io_name(const AttrDomain domain) @@ -329,7 +325,7 @@ static std::optional get_data_type_from_io_name(const StringRef } /** - * Write the data and remember which endianness the data had. + * Write the data, always in little endian. */ static std::shared_ptr write_blob_raw_data_with_endian( BlobWriter &blob_writer, @@ -338,14 +334,14 @@ static std::shared_ptr write_blob_raw_data_with_endian( const int64_t size_in_bytes) { auto io_data = blob_sharing.write_deduplicated(blob_writer, data, size_in_bytes); - if (ENDIAN_ORDER == B_ENDIAN) { - io_data->append_str("endian", get_endian_io_name(ENDIAN_ORDER)); - } + BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems") return io_data; } /** - * Read data of an into an array and optionally perform an endian switch if necessary. + * Read data of an into an array. + * + * \returns True if sucessful, false if reading fails, or endian switch would be needed. */ [[nodiscard]] static bool read_blob_raw_data_with_endian(const BlobReader &blob_reader, const DictionaryValue &io_data, @@ -367,21 +363,9 @@ static std::shared_ptr write_blob_raw_data_with_endian( const StringRefNull current_endian = get_endian_io_name(ENDIAN_ORDER); const bool need_endian_switch = stored_endian != current_endian; if (need_endian_switch) { - switch (element_size) { - case 1: - break; - case 2: - BLI_endian_switch_uint16_array(static_cast(r_data), elements_num); - break; - case 4: - BLI_endian_switch_uint32_array(static_cast(r_data), elements_num); - break; - case 8: - BLI_endian_switch_uint64_array(static_cast(r_data), elements_num); - break; - default: - return false; - } + /* NOTE: this is endianness-sensitive. */ + /* Blender only builds on little endian systems, and reads little endian data here. */ + return false; } return true; } diff --git a/source/blender/blenkernel/intern/customdata_file.cc b/source/blender/blenkernel/intern/customdata_file.cc index c39f70dc08a..d2a1a3aa3ed 100644 --- a/source/blender/blenkernel/intern/customdata_file.cc +++ b/source/blender/blenkernel/intern/customdata_file.cc @@ -13,7 +13,6 @@ #include "MEM_guardedalloc.h" #include "BLI_endian_defines.h" -#include "BLI_endian_switch.h" #include "BLI_fileops.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -78,7 +77,6 @@ struct CDataFile { FILE *readf; FILE *writef; - int switchendian; size_t dataoffset; }; @@ -86,11 +84,8 @@ struct CDataFile { static int cdf_endian() { - if (ENDIAN_ORDER == L_ENDIAN) { - return CDF_ENDIAN_LITTLE; - } - - return CDF_ENDIAN_BIG; + BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems") + return CDF_ENDIAN_LITTLE; } CDataFile *cdf_create(int type) @@ -138,15 +133,14 @@ static bool cdf_read_header(CDataFile *cdf) if (header->version > CDF_VERSION) { return false; } + if (header->endian != cdf_endian()) { + return false; + } - cdf->switchendian = header->endian != cdf_endian(); header->endian = cdf_endian(); - if (cdf->switchendian) { - BLI_endian_switch_int32(&header->type); - BLI_endian_switch_int32(&header->totlayer); - BLI_endian_switch_int32(&header->structbytes); - } + /* NOTE: this is endianness-sensitive. + * Some non-char `header` data would need to be switched. */ if (!ELEM(header->type, CDF_TYPE_IMAGE, CDF_TYPE_MESH)) { return false; @@ -165,12 +159,8 @@ static bool cdf_read_header(CDataFile *cdf) return false; } - if (cdf->switchendian) { - BLI_endian_switch_int32(&image->width); - BLI_endian_switch_int32(&image->height); - BLI_endian_switch_int32(&image->tile_size); - BLI_endian_switch_int32(&image->structbytes); - } + /* NOTE: this is endianness-sensitive. + * Some non-char `image` data would need to be switched. */ offset += image->structbytes; image->structbytes = sizeof(CDataFileImageHeader); @@ -181,9 +171,8 @@ static bool cdf_read_header(CDataFile *cdf) return false; } - if (cdf->switchendian) { - BLI_endian_switch_int32(&mesh->structbytes); - } + /* NOTE: this is endianness-sensitive. + * Some non-char `mesh` data would need to be switched. */ offset += mesh->structbytes; mesh->structbytes = sizeof(CDataFileMeshHeader); @@ -207,12 +196,8 @@ static bool cdf_read_header(CDataFile *cdf) return false; } - if (cdf->switchendian) { - BLI_endian_switch_int32(&layer->type); - BLI_endian_switch_int32(&layer->datatype); - BLI_endian_switch_uint64(&layer->datasize); - BLI_endian_switch_int32(&layer->structbytes); - } + /* NOTE: this is endianness-sensitive. + * Some non-char `layer` data would need to be switched. */ if (layer->datatype != CDF_DATA_FLOAT) { return false; @@ -319,10 +304,8 @@ bool cdf_read_data(CDataFile *cdf, uint size, void *data) return false; } - /* switch endian if necessary */ - if (cdf->switchendian) { - BLI_endian_switch_float_array(static_cast(data), size / sizeof(float)); - } + /* NOTE: this is endianness-sensitive. + * `data` would need to be switched. */ return true; } diff --git a/source/blender/blenkernel/intern/idprop.cc b/source/blender/blenkernel/intern/idprop.cc index 038d5fb84db..dd3d7709bc2 100644 --- a/source/blender/blenkernel/intern/idprop.cc +++ b/source/blender/blenkernel/intern/idprop.cc @@ -15,7 +15,6 @@ #include -#include "BLI_endian_switch.h" #include "BLI_listbase.h" #include "BLI_math_base.h" #include "BLI_set.hh" @@ -1621,18 +1620,12 @@ static void IDP_DirectLinkProperty(IDProperty *prop, BlendDataReader *reader) IDP_DirectLinkIDPArray(prop, reader); break; case IDP_DOUBLE: - /* Workaround for doubles. - * They are stored in the same field as `int val, val2` in the #IDPropertyData struct, - * they have to deal with endianness specifically. + /* NOTE: this is endianness-sensitive. */ + /* Doubles are stored in the same field as `int val, val2` in the #IDPropertyData struct. * - * In theory, val and val2 would've already been swapped - * if switch_endian is true, so we have to first un-swap - * them then re-swap them as a single 64-bit entity. */ - if (BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_int32(&prop->data.val); - BLI_endian_switch_int32(&prop->data.val2); - BLI_endian_switch_int64((int64_t *)&prop->data.val); - } + * In case of endianness switching, `val` and `val2` would have already been switched by the + * generic reading code, so they would need to be first un-switched individually, and then + * re-switched as a single 64-bit entity. */ break; case IDP_INT: case IDP_FLOAT: diff --git a/source/blender/blenkernel/intern/ipo.cc b/source/blender/blenkernel/intern/ipo.cc index 1bf1f588b7a..7f19eea2c16 100644 --- a/source/blender/blenkernel/intern/ipo.cc +++ b/source/blender/blenkernel/intern/ipo.cc @@ -37,7 +37,6 @@ #include "DNA_world_types.h" #include "BLI_dynstr.h" -#include "BLI_endian_switch.h" #include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_string_utils.hh" @@ -126,38 +125,15 @@ static void ipo_blend_read_data(BlendDataReader *reader, ID *id) BLO_read_struct_list(reader, IpoCurve, &(ipo->curve)); + /* NOTE: this is endianness-sensitive. + * Not clear why, but endianness switching was undone here for some data? + * That 'undo switching' code appeared to be heavily broken in 4.x code actually, performing + * switch on `ipo` data as part of the loop on `icu`'s, among other obvious mistakes. */ + LISTBASE_FOREACH (IpoCurve *, icu, &ipo->curve) { BLO_read_struct_array(reader, BezTriple, icu->totvert, &icu->bezt); BLO_read_struct_array(reader, BPoint, icu->totvert, &icu->bp); BLO_read_struct(reader, IpoDriver, &icu->driver); - - /* Undo generic endian switching. */ - if (BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_int16(&icu->blocktype); - if (icu->driver != nullptr) { - - /* Undo generic endian switching. */ - if (BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_int16(&icu->blocktype); - if (icu->driver != nullptr) { - BLI_endian_switch_int16(&icu->driver->blocktype); - } - } - } - - /* Undo generic endian switching. */ - if (BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_int16(&ipo->blocktype); - if (icu->driver != nullptr) { - BLI_endian_switch_int16(&icu->driver->blocktype); - } - } - } - } - - /* Undo generic endian switching. */ - if (BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_int16(&ipo->blocktype); } } diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc index f8c2bba7178..36e24f486b5 100644 --- a/source/blender/blenkernel/intern/key.cc +++ b/source/blender/blenkernel/intern/key.cc @@ -14,7 +14,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_endian_switch.h" #include "BLI_listbase.h" #include "BLI_math_matrix.h" #include "BLI_math_vector.h" @@ -151,33 +150,6 @@ static void shapekey_blend_write(BlendWriter *writer, ID *id, const void *id_add #define IPO_BEZTRIPLE 100 #define IPO_BPOINT 101 -static void switch_endian_keyblock(Key *key, KeyBlock *kb) -{ - int elemsize = key->elemsize; - char *data = static_cast(kb->data); - - for (int a = 0; a < kb->totelem; a++) { - const char *cp = key->elemstr; - char *poin = data; - - while (cp[0]) { /* cp[0] == amount */ - switch (cp[1]) { /* cp[1] = type */ - case IPO_FLOAT: - case IPO_BPOINT: - case IPO_BEZTRIPLE: { - int b = cp[0]; - BLI_endian_switch_float_array((float *)poin, b); - poin += sizeof(float) * b; - break; - } - } - - cp += 2; - } - data += elemsize; - } -} - static void shapekey_blend_read_data(BlendDataReader *reader, ID *id) { Key *key = (Key *)id; @@ -188,9 +160,9 @@ static void shapekey_blend_read_data(BlendDataReader *reader, ID *id) LISTBASE_FOREACH (KeyBlock *, kb, &key->block) { BLO_read_data_address(reader, &kb->data); - if (BLO_read_requires_endian_switch(reader)) { - switch_endian_keyblock(key, kb); - } + /* NOTE: this is endianness-sensitive. */ + /* Keyblock data would need specific endian switching depending of the exact type of data it + * contain. */ } } diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 8722af14183..113305a3b18 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -21,7 +21,6 @@ #include "DNA_object_types.h" #include "BLI_bounds.hh" -#include "BLI_endian_switch.h" #include "BLI_hash.h" #include "BLI_implicit_sharing.hh" #include "BLI_index_range.hh" @@ -430,12 +429,9 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) mesh->totselect = 0; } - if (BLO_read_requires_endian_switch(reader) && mesh->tface) { - TFace *tf = mesh->tface; - for (int i = 0; i < mesh->totface_legacy; i++, tf++) { - BLI_endian_switch_uint32_array(tf->col, 4); - } - } + /* NOTE: this is endianness-sensitive. */ + /* Each legacy TFace would need to undo the automatic DNA switch of its array of four uint32_t + * RGBA colors. */ } IDTypeInfo IDType_ID_ME = { diff --git a/source/blender/blenkernel/intern/packedFile.cc b/source/blender/blenkernel/intern/packedFile.cc index 0a81572f652..beb784c60bb 100644 --- a/source/blender/blenkernel/intern/packedFile.cc +++ b/source/blender/blenkernel/intern/packedFile.cc @@ -987,6 +987,7 @@ void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p, Strin if (pf == nullptr) { return; } + /* NOTE: this is endianness-sensitive. */ /* NOTE: there is no way to handle endianness switch here. */ pf->sharing_info = BLO_read_shared(reader, &pf->data, [&]() { BLO_read_data_address(reader, &pf->data); diff --git a/source/blender/blenlib/intern/BLI_mempool.cc b/source/blender/blenlib/intern/BLI_mempool.cc index 89c3aa76064..8ef700ccc3f 100644 --- a/source/blender/blenlib/intern/BLI_mempool.cc +++ b/source/blender/blenlib/intern/BLI_mempool.cc @@ -46,19 +46,11 @@ #endif /* NOTE: copied from BLO_core_bhead.hh, don't use here because we're in BLI. */ -#ifdef __BIG_ENDIAN__ -/* Big Endian */ -# define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d)) -# define MAKE_ID_8(a, b, c, d, e, f, g, h) \ - ((int64_t)(a) << 56 | (int64_t)(b) << 48 | (int64_t)(c) << 40 | (int64_t)(d) << 32 | \ - (int64_t)(e) << 24 | (int64_t)(f) << 16 | (int64_t)(g) << 8 | (h)) -#else -/* Little Endian */ -# define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a)) -# define MAKE_ID_8(a, b, c, d, e, f, g, h) \ - (int64_t(h) << 56 | int64_t(g) << 48 | int64_t(f) << 40 | int64_t(e) << 32 | \ - int64_t(d) << 24 | int64_t(c) << 16 | int64_t(b) << 8 | (a)) -#endif +/* NOTE: this is endianness-sensitive. */ +#define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a)) +#define MAKE_ID_8(a, b, c, d, e, f, g, h) \ + (int64_t(h) << 56 | int64_t(g) << 48 | int64_t(f) << 40 | int64_t(e) << 32 | int64_t(d) << 24 | \ + int64_t(c) << 16 | int64_t(b) << 8 | (a)) /** * Important that this value is an is _not_ aligned with `sizeof(void *)`. diff --git a/source/blender/blenlib/intern/filereader_zstd.cc b/source/blender/blenlib/intern/filereader_zstd.cc index 44544fa1a9b..5f16b55d4a6 100644 --- a/source/blender/blenlib/intern/filereader_zstd.cc +++ b/source/blender/blenlib/intern/filereader_zstd.cc @@ -13,10 +13,6 @@ #include "BLI_fileops.hh" #include "BLI_filereader.h" -#ifdef __BIG_ENDIAN__ -# include "BLI_endian_switch.h" -#endif - #include "MEM_guardedalloc.h" struct ZstdReader { @@ -43,9 +39,8 @@ static bool zstd_read_u32(FileReader *base, uint32_t *val) if (base->read(base, val, sizeof(uint32_t)) != sizeof(uint32_t)) { return false; } -#ifdef __BIG_ENDIAN__ - BLI_endian_switch_uint32(val); -#endif + /* NOTE: this is endianness-sensitive. + * `val` would need to be switched on a big endian system. */ return true; } diff --git a/source/blender/blenlib/intern/hash_md5.cc b/source/blender/blenlib/intern/hash_md5.cc index 4903da67a8c..2f902662701 100644 --- a/source/blender/blenlib/intern/hash_md5.cc +++ b/source/blender/blenlib/intern/hash_md5.cc @@ -70,11 +70,8 @@ struct md5_ctx { md5_uint32 D; }; -#ifdef __BIG_ENDIAN__ -# define SWAP(n) (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) -#else -# define SWAP(n) (n) -#endif +/* NOTE: this is endianness-sensitive. */ +#define SWAP(n) (n) /* This array contains the bytes used to pad the buffer to the next 64-byte boundary. * (RFC 1321, 3.1: Step 1) */ diff --git a/source/blender/blenlib/intern/math_color.cc b/source/blender/blenlib/intern/math_color.cc index 43a69419b63..ac7a1a6b87f 100644 --- a/source/blender/blenlib/intern/math_color.cc +++ b/source/blender/blenlib/intern/math_color.cc @@ -721,11 +721,8 @@ static ushort hipart(const float f) tmp.f = f; -#ifdef __BIG_ENDIAN__ - return tmp.us[0]; -#else + /* NOTE: this is endianness-sensitive. */ return tmp.us[1]; -#endif } static float index_to_float(const ushort i) @@ -748,13 +745,9 @@ static float index_to_float(const ushort i) return -FLT_MAX; } -#ifdef __BIG_ENDIAN__ - tmp.us[0] = i; - tmp.us[1] = 0x8000; -#else + /* NOTE: this is endianness-sensitive. */ tmp.us[0] = 0x8000; tmp.us[1] = i; -#endif return tmp.f; } diff --git a/source/blender/blenlib/intern/math_color_inline.cc b/source/blender/blenlib/intern/math_color_inline.cc index 396c03f8469..f63dd9889e6 100644 --- a/source/blender/blenlib/intern/math_color_inline.cc +++ b/source/blender/blenlib/intern/math_color_inline.cc @@ -108,11 +108,8 @@ MINLINE unsigned short to_srgb_table_lookup(const float f) unsigned short us[2]; } tmp; tmp.f = f; -# ifdef __BIG_ENDIAN__ - return BLI_color_to_srgb_table[tmp.us[0]]; -# else + /* NOTE: this is endianness-sensitive. */ return BLI_color_to_srgb_table[tmp.us[1]]; -# endif } MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4]) diff --git a/source/blender/blenlib/intern/rand.cc b/source/blender/blenlib/intern/rand.cc index 65355ca091f..b5cf2b13c29 100644 --- a/source/blender/blenlib/intern/rand.cc +++ b/source/blender/blenlib/intern/rand.cc @@ -391,12 +391,9 @@ void RandomNumberGenerator::get_bytes(MutableSpan r_bytes) int64_t i = 0; while (i != trim_len) { BLI_assert(i < trim_len); -#ifdef __BIG_ENDIAN__ - for (int64_t j = (rand_stride + mask_bytes) - 1; j != mask_bytes - 1; j--) -#else - for (int64_t j = 0; j != rand_stride; j++) -#endif - { + /* NOTE: this is endianness-sensitive. + * Big Endian needs to iterate in reverse, with a `mask_bytes - 1` offset. */ + for (int64_t j = 0; j != rand_stride; j++) { r_bytes[i++] = data_src[j]; } this->step(); diff --git a/source/blender/blenlib/tests/BLI_build_config_test.cc b/source/blender/blenlib/tests/BLI_build_config_test.cc index 2594967b473..5c13ad2fdec 100644 --- a/source/blender/blenlib/tests/BLI_build_config_test.cc +++ b/source/blender/blenlib/tests/BLI_build_config_test.cc @@ -26,6 +26,8 @@ TEST(BLI_build_config, Endian) #if defined(__BIG_ENDIAN__) static_assert(ARCH_CPU_BIG_ENDIAN); static_assert(!ARCH_CPU_LITTLE_ENDIAN); + /* Blender does not build on big endian systems. */ + static_assert(0); #endif #if defined(__LITTLE_ENDIAN__) static_assert(!ARCH_CPU_BIG_ENDIAN); diff --git a/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc b/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc index 9c8364a6cc4..2623373110c 100644 --- a/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc +++ b/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc @@ -19,11 +19,9 @@ TEST(hash_mm2a, MM2ABasic) BLI_hash_mm2a_init(&mm2, 0); BLI_hash_mm2a_add(&mm2, (const uchar *)data, strlen(data)); -#ifdef __LITTLE_ENDIAN__ + /* NOTE: this is endianness-sensitive. */ + /* On BE systems, the expected value would be 959283772. */ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 1633988145); -#else - EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 959283772); -#endif } TEST(hash_mm2a, MM2AConcatenateStrings) @@ -43,11 +41,9 @@ TEST(hash_mm2a, MM2AConcatenateStrings) hash = BLI_hash_mm2a_end(&mm2); BLI_hash_mm2a_init(&mm2, 0); BLI_hash_mm2a_add(&mm2, (const uchar *)data123, strlen(data123)); -#ifdef __LITTLE_ENDIAN__ + /* NOTE: this is endianness-sensitive. */ + /* On BE systems, the expected value would be 2604964730. */ EXPECT_EQ(hash, 1545105348); -#else - EXPECT_EQ(hash, 2604964730); -#endif EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash); } @@ -66,11 +62,8 @@ TEST(hash_mm2a, MM2AIntegers) hash = BLI_hash_mm2a_end(&mm2); BLI_hash_mm2a_init(&mm2, 0); BLI_hash_mm2a_add(&mm2, (const uchar *)ints, sizeof(ints)); - /* Yes, same hash here on little and big endian. */ -#ifdef __LITTLE_ENDIAN__ + /* NOTE: this is endianness-sensitive. */ + /* Actually, same hash here on little and big endian. */ EXPECT_EQ(hash, 405493096); -#else - EXPECT_EQ(hash, 405493096); -#endif EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash); } diff --git a/source/blender/blenloader/BLO_read_write.hh b/source/blender/blenloader/BLO_read_write.hh index 2dedba211dd..db4623fadd2 100644 --- a/source/blender/blenloader/BLO_read_write.hh +++ b/source/blender/blenloader/BLO_read_write.hh @@ -369,7 +369,6 @@ const blender::ImplicitSharingInfo *BLO_read_shared( } int BLO_read_fileversion_get(BlendDataReader *reader); -bool BLO_read_requires_endian_switch(BlendDataReader *reader); bool BLO_read_data_is_undo(BlendDataReader *reader); void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr); void BLO_read_glob_list(BlendDataReader *reader, ListBase *list); diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index cd0732c120e..7b26b692ee6 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -623,12 +623,11 @@ struct BlendLibReader { static BHeadN *get_bhead(FileData *fd) { BHeadN *new_bhead = nullptr; - const bool do_endian_swap = fd->flags & FD_FLAGS_SWITCH_ENDIAN; if (fd) { if (!fd->is_eof) { - std::optional bhead_opt = BLO_readfile_read_bhead( - fd->file, fd->blender_header.bhead_type(), do_endian_swap); + std::optional bhead_opt = BLO_readfile_read_bhead(fd->file, + fd->blender_header.bhead_type()); BHead *bhead = nullptr; if (!bhead_opt.has_value()) { fd->is_eof = true; @@ -884,10 +883,9 @@ static bool read_file_dna(FileData *fd, const char **r_error_message) subversion = atoi(num); } else if (bhead->code == BLO_CODE_DNA1) { - const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0; + BLI_assert((fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0); const bool do_alias = false; /* Postpone until after #blo_do_versions_dna runs. */ - fd->filesdna = DNA_sdna_from_data( - &bhead[1], bhead->len, do_endian_swap, true, do_alias, r_error_message); + fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, true, do_alias, r_error_message); if (fd->filesdna) { blo_do_versions_dna(fd->filesdna, fd->fileversion, subversion); /* Allow aliased lookups (must be after version patching DNA). */ @@ -1200,7 +1198,18 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports) { read_blender_header(fd); - if (fd->flags & FD_FLAGS_FILE_OK) { + if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { + BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems") + BKE_reportf(reports, + RPT_ERROR, + "Blend file '%s' created by a Big Endian version of Blender, support for " + "these files has been removed in Blender 5.0, use an older version of Blender " + "to open and convert it.", + fd->relabase); + blo_filedata_free(fd); + fd = nullptr; + } + else if (fd->flags & FD_FLAGS_FILE_OK) { const char *error_message = nullptr; if (read_file_dna(fd, &error_message) == false) { BKE_reportf( @@ -1212,22 +1221,6 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports) blo_filedata_free(fd); fd = nullptr; } - else if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { - if (ENDIAN_ORDER == L_ENDIAN) { - if (!BKE_reports_print_test(reports, RPT_WARNING)) { - CLOG_WARN( - &LOG, - "Blend file '%s' created by a Big Endian version of Blender, support for these " - "files will be removed in Blender 5.0", - fd->relabase); - } - BKE_reportf(reports, - RPT_WARNING, - "Blend file '%s' created by a Big Endian version of Blender, support for " - "these files will be removed in Blender 5.0", - fd->relabase); - } - } } else if (fd->flags & FD_FLAGS_FILE_FUTURE) { BKE_reportf( @@ -1784,23 +1777,6 @@ void blo_cache_storage_end(FileData *fd) /** \name DNA Struct Loading * \{ */ -static void switch_endian_structs(const SDNA *filesdna, BHead *bhead) -{ - int blocksize, nblocks; - char *data; - - data = (char *)(bhead + 1); - - blocksize = DNA_struct_size(filesdna, bhead->SDNAnr); - - nblocks = bhead->nr; - while (nblocks--) { - DNA_struct_switch_endian(filesdna, bhead->SDNAnr, data); - - data += blocksize; - } -} - /** * Generate the final allocation string reference for read blocks of data. If \a blockname is * given, use it as 'owner block' info, otherwise use the id type index to get that info. @@ -1897,6 +1873,7 @@ static void *read_struct(FileData *fd, BHead *bh, const char *blockname, const i * * NOTE: raw data (aka #SDNA_RAW_DATA_STRUCT_INDEX #SDNAnr) is not handled here, it's up to * the calling code to manage this. */ + BLI_assert((fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0); BLI_STATIC_ASSERT(SDNA_RAW_DATA_STRUCT_INDEX == 0, "'raw data' SDNA struct index should be 0") if (bh->SDNAnr > SDNA_RAW_DATA_STRUCT_INDEX && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) { #ifdef USE_BHEAD_READ_ON_DEMAND @@ -1908,7 +1885,6 @@ static void *read_struct(FileData *fd, BHead *bh, const char *blockname, const i } } #endif - switch_endian_structs(fd->filesdna, bh); } if (fd->compflags[bh->SDNAnr] != SDNA_CMP_REMOVED) { @@ -4764,6 +4740,8 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag, ReportL /* FIXME This is extremely bad design, #library_link_end should probably _always_ free the file * data? */ if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) { + /* Big Endian blendfiles are not supported for linking. */ + BLI_assert_unreachable(); blo_filedata_free(*fd); *fd = nullptr; } @@ -5229,11 +5207,6 @@ int BLO_read_fileversion_get(BlendDataReader *reader) return reader->fd->fileversion; } -bool BLO_read_requires_endian_switch(BlendDataReader *reader) -{ - return (reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0; -} - void BLO_read_struct_list_with_size(BlendDataReader *reader, const size_t expected_elem_size, ListBase *list) @@ -5277,40 +5250,28 @@ void BLO_read_int16_array(BlendDataReader *reader, const int64_t array_size, int { *ptr_p = reinterpret_cast( BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int16_t) * array_size)); - - if (*ptr_p && BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_int16_array(*ptr_p, array_size); - } + BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0); } void BLO_read_int32_array(BlendDataReader *reader, const int64_t array_size, int32_t **ptr_p) { *ptr_p = reinterpret_cast( BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int32_t) * array_size)); - - if (*ptr_p && BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_int32_array(*ptr_p, array_size); - } + BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0); } void BLO_read_uint32_array(BlendDataReader *reader, const int64_t array_size, uint32_t **ptr_p) { *ptr_p = reinterpret_cast( BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(uint32_t) * array_size)); - - if (*ptr_p && BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_uint32_array(*ptr_p, array_size); - } + BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0); } void BLO_read_float_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p) { *ptr_p = reinterpret_cast( BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(float) * array_size)); - - if (*ptr_p && BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_float_array(*ptr_p, array_size); - } + BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0); } void BLO_read_float3_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p) @@ -5322,10 +5283,7 @@ void BLO_read_double_array(BlendDataReader *reader, const int64_t array_size, do { *ptr_p = reinterpret_cast( BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(double) * array_size)); - - if (*ptr_p && BLO_read_requires_endian_switch(reader)) { - BLI_endian_switch_double_array(*ptr_p, array_size); - } + BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0); } void BLO_read_string(BlendDataReader *reader, char **ptr_p) @@ -5362,9 +5320,9 @@ static void convert_pointer_array_64_to_32(BlendDataReader *reader, const uint64_t *src, uint32_t *dst) { - const bool use_endian_swap = BLO_read_requires_endian_switch(reader); + BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0); for (int i = 0; i < array_size; i++) { - dst[i] = uint32_from_uint64_ptr(src[i], use_endian_swap); + dst[i] = uint32_from_uint64_ptr(src[i]); } } diff --git a/source/blender/blenloader/intern/writefile.cc b/source/blender/blenloader/intern/writefile.cc index 0d45d326dcd..fc6deac2e1c 100644 --- a/source/blender/blenloader/intern/writefile.cc +++ b/source/blender/blenloader/intern/writefile.cc @@ -12,12 +12,13 @@ * * IFF-style structure (but not IFF compatible!) * - * Start file: - *
- * `BLENDER_V100`  `12` bytes  (version 1.00 is just an example).
- *                 `V` = big endian, `v` = little endian.
- *                 `_` = 4 byte pointer, `-` = 8 byte pointer.
- * 
+ * Start of the file: + * + * Historic Blendfiles (pre-Blender 5.0): + * `BLENDER_V100` : Fixed 12 bytes length. See #BLEND_FILE_FORMAT_VERSION_0 for details. + * + * Current Blendfiles (Blender 5.0 and later): + * `BLENDER17-01v0500`: Variable bytes length. See #BLEND_FILE_FORMAT_VERSION_1 for details. * * data-blocks: (also see struct #BHead). *
@@ -92,7 +93,6 @@
 #include "DNA_userdef_types.h"
 
 #include "BLI_endian_defines.h"
-#include "BLI_endian_switch.h"
 #include "BLI_fileops.hh"
 #include "BLI_implicit_sharing.hh"
 #include "BLI_math_base.h"
@@ -312,9 +312,9 @@ bool ZstdWriteWrap::open(const char *filepath)
 
 void ZstdWriteWrap::write_u32_le(uint32_t val)
 {
-  if (ENDIAN_ORDER == B_ENDIAN) {
-    BLI_endian_switch_uint32(&val);
-  }
+  /* NOTE: this is endianness-sensitive.
+   * This value must always be written as little-endian. */
+  BLI_assert(ENDIAN_ORDER == L_ENDIAN);
   base_wrap.write(&val, sizeof(uint32_t));
 }
 
@@ -1380,7 +1380,7 @@ static std::string get_blend_file_header()
   }
 
   const char pointer_size_char = sizeof(void *) == 8 ? '-' : '_';
-  const char endian_char = ENDIAN_ORDER == B_ENDIAN ? 'V' : 'v';
+  const char endian_char = 'v';
 
   /* Legacy blend file header format. */
   std::stringstream ss;
diff --git a/source/blender/blenloader_core/BLO_core_bhead.hh b/source/blender/blenloader_core/BLO_core_bhead.hh
index e58dfcd618a..d06656c7de1 100644
--- a/source/blender/blenloader_core/BLO_core_bhead.hh
+++ b/source/blender/blenloader_core/BLO_core_bhead.hh
@@ -111,9 +111,7 @@ enum {
  *
  * \return The next #BHEad or #std::nullopt if the file is exhausted.
  */
-std::optional BLO_readfile_read_bhead(FileReader *file,
-                                             BHeadType type,
-                                             bool do_endian_swap);
+std::optional BLO_readfile_read_bhead(FileReader *file, BHeadType type);
 
 /**
  * Converts a BHead.old pointer from 64 to 32 bit. This can't work in the general case, but only
@@ -121,12 +119,11 @@ std::optional BLO_readfile_read_bhead(FileReader *file,
  * pointers will map to the same, which will break things later on. There is no way to check for
  * that here unfortunately.
  */
-inline uint32_t uint32_from_uint64_ptr(uint64_t ptr, const bool use_endian_swap)
+inline uint32_t uint32_from_uint64_ptr(uint64_t ptr)
 {
-  if (use_endian_swap) {
-    /* Do endian switch so that the resulting pointer is not all 0. */
-    BLI_endian_switch_uint64(&ptr);
-  }
+  /* NOTE: this is endianness-sensitive. */
+  /* Switching endianess would be required to reduce the risk of two different 64bits pointers
+   * generating the same 32bits value. */
   /* Behavior has to match #cast_pointer_64_to_32. */
   ptr >>= 3;
   return uint32_t(ptr);
diff --git a/source/blender/blenloader_core/intern/blo_core_bhead.cc b/source/blender/blenloader_core/intern/blo_core_bhead.cc
index a380dc95f43..1e0a7af13e0 100644
--- a/source/blender/blenloader_core/intern/blo_core_bhead.cc
+++ b/source/blender/blenloader_core/intern/blo_core_bhead.cc
@@ -6,48 +6,6 @@
 
 #include "BLO_core_bhead.hh"
 
-static void switch_endian_bh4(BHead4 *bhead)
-{
-  /* the ID_.. codes */
-  if ((bhead->code & 0xFFFF) == 0) {
-    bhead->code >>= 16;
-  }
-
-  if (bhead->code != BLO_CODE_ENDB) {
-    BLI_endian_switch_int32(&bhead->len);
-    BLI_endian_switch_int32(&bhead->SDNAnr);
-    BLI_endian_switch_int32(&bhead->nr);
-  }
-}
-
-static void switch_endian_small_bh8(SmallBHead8 *bhead)
-{
-  /* The ID_* codes. */
-  if ((bhead->code & 0xFFFF) == 0) {
-    bhead->code >>= 16;
-  }
-
-  if (bhead->code != BLO_CODE_ENDB) {
-    BLI_endian_switch_int32(&bhead->len);
-    BLI_endian_switch_int32(&bhead->SDNAnr);
-    BLI_endian_switch_int32(&bhead->nr);
-  }
-}
-
-static void switch_endian_large_bh8(LargeBHead8 *bhead)
-{
-  /* The ID_* codes. */
-  if ((bhead->code & 0xFFFF) == 0) {
-    bhead->code >>= 16;
-  }
-
-  if (bhead->code != BLO_CODE_ENDB) {
-    BLI_endian_switch_int64(&bhead->len);
-    BLI_endian_switch_int32(&bhead->SDNAnr);
-    BLI_endian_switch_int64(&bhead->nr);
-  }
-}
-
 static BHead bhead_from_bhead4(const BHead4 &bhead4)
 {
   BHead bhead;
@@ -59,51 +17,49 @@ static BHead bhead_from_bhead4(const BHead4 &bhead4)
   return bhead;
 }
 
-static const void *old_ptr_from_uint64_ptr(const uint64_t ptr, const bool use_endian_swap)
+static const void *old_ptr_from_uint64_ptr(const uint64_t ptr)
 {
   if constexpr (sizeof(void *) == 8) {
     return reinterpret_cast(ptr);
   }
   else {
-    return reinterpret_cast(uintptr_t(uint32_from_uint64_ptr(ptr, use_endian_swap)));
+    return reinterpret_cast(uintptr_t(uint32_from_uint64_ptr(ptr)));
   }
 }
 
-static BHead bhead_from_small_bhead8(const SmallBHead8 &small_bhead8, const bool use_endian_swap)
+static BHead bhead_from_small_bhead8(const SmallBHead8 &small_bhead8)
 {
   BHead bhead;
   bhead.code = small_bhead8.code;
   bhead.len = small_bhead8.len;
-  bhead.old = old_ptr_from_uint64_ptr(small_bhead8.old, use_endian_swap);
+  bhead.old = old_ptr_from_uint64_ptr(small_bhead8.old);
   bhead.SDNAnr = small_bhead8.SDNAnr;
   bhead.nr = small_bhead8.nr;
   return bhead;
 }
 
-static BHead bhead_from_large_bhead8(const LargeBHead8 &large_bhead8, const bool use_endian_swap)
+static BHead bhead_from_large_bhead8(const LargeBHead8 &large_bhead8)
 {
   BHead bhead;
   bhead.code = large_bhead8.code;
   bhead.len = large_bhead8.len;
-  bhead.old = old_ptr_from_uint64_ptr(large_bhead8.old, use_endian_swap);
+  bhead.old = old_ptr_from_uint64_ptr(large_bhead8.old);
   bhead.SDNAnr = large_bhead8.SDNAnr;
   bhead.nr = large_bhead8.nr;
   return bhead;
 }
 
-std::optional BLO_readfile_read_bhead(FileReader *file,
-                                             const BHeadType type,
-                                             const bool do_endian_swap)
+std::optional BLO_readfile_read_bhead(FileReader *file, const BHeadType type)
 {
+  /* NOTE: this is endianness-sensitive. */
+  /* The various BHead data below would need to be switched if the read blend-file was saved from a
+   * system using a different endianness. */
   switch (type) {
     case BHeadType::BHead4: {
       BHead4 bhead4{};
       bhead4.code = BLO_CODE_DATA;
       const int64_t readsize = file->read(file, &bhead4, sizeof(bhead4));
       if (readsize == sizeof(bhead4) || bhead4.code == BLO_CODE_ENDB) {
-        if (do_endian_swap) {
-          switch_endian_bh4(&bhead4);
-        }
         return bhead_from_bhead4(bhead4);
       }
       break;
@@ -113,10 +69,7 @@ std::optional BLO_readfile_read_bhead(FileReader *file,
       small_bhead8.code = BLO_CODE_DATA;
       const int64_t readsize = file->read(file, &small_bhead8, sizeof(small_bhead8));
       if (readsize == sizeof(small_bhead8) || small_bhead8.code == BLO_CODE_ENDB) {
-        if (do_endian_swap) {
-          switch_endian_small_bh8(&small_bhead8);
-        }
-        return bhead_from_small_bhead8(small_bhead8, do_endian_swap);
+        return bhead_from_small_bhead8(small_bhead8);
       }
       break;
     }
@@ -125,10 +78,7 @@ std::optional BLO_readfile_read_bhead(FileReader *file,
       large_bhead8.code = BLO_CODE_DATA;
       const int64_t readsize = file->read(file, &large_bhead8, sizeof(large_bhead8));
       if (readsize == sizeof(large_bhead8) || large_bhead8.code == BLO_CODE_ENDB) {
-        if (do_endian_swap) {
-          switch_endian_large_bh8(&large_bhead8);
-        }
-        return bhead_from_large_bhead8(large_bhead8, do_endian_swap);
+        return bhead_from_large_bhead8(large_bhead8);
       }
       break;
     }
diff --git a/source/blender/draw/engines/eevee/eevee_precompute.hh b/source/blender/draw/engines/eevee/eevee_precompute.hh
index 8eb09631164..5d6e6a4a521 100644
--- a/source/blender/draw/engines/eevee/eevee_precompute.hh
+++ b/source/blender/draw/engines/eevee/eevee_precompute.hh
@@ -63,11 +63,9 @@ class Precompute {
     file.open(std::string(name) + ".pfm");
     file << "PF\n";
     file << n_x * n_z << " " << n_y * n_w << "\n";
-#ifdef __LITTLE_ENDIAN__
+    /* NOTE: this is endianness-sensitive.
+     * Big endian system would have needed `1.0` value instead. */
     file << "-1.0\n";
-#else
-    file << "1.0\n";
-#endif
     file.close();
 
     /* Write binary float content. */
diff --git a/source/blender/editors/armature/armature_select.cc b/source/blender/editors/armature/armature_select.cc
index c97f3fe17ef..6297ec6c0b0 100644
--- a/source/blender/editors/armature/armature_select.cc
+++ b/source/blender/editors/armature/armature_select.cc
@@ -740,13 +740,10 @@ cache_end:
         union {
           uint32_t as_u32;
           struct {
-#ifdef __BIG_ENDIAN__
-            uint16_t ob;
-            uint16_t bone;
-#else
+            /* NOTE: this is endianness-sensitive.
+             * In Big Endian the order of these two variable would have to be inverted. */
             uint16_t bone;
             uint16_t ob;
-#endif
           };
         } offset, test, best;
       } cycle_order;
diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc
index 1f5e344d1c4..7ed019d0bca 100644
--- a/source/blender/editors/space_view3d/view3d_select.cc
+++ b/source/blender/editors/space_view3d/view3d_select.cc
@@ -38,10 +38,6 @@
 
 #include "BLT_translation.hh"
 
-#ifdef __BIG_ENDIAN__
-#  include "BLI_endian_switch.h"
-#endif
-
 #include "BKE_action.hh"
 #include "BKE_armature.hh"
 #include "BKE_attribute.hh"
@@ -2238,14 +2234,11 @@ static int gpu_select_buffer_depth_id_cmp(const void *sel_a_p, const void *sel_b
   }
 
   /* Depths match, sort by id. */
+  /* NOTE: this is endianness-sensitive.
+   * GPUSelectResult values are always expected to be little-endian. */
   uint sel_a = a->id;
   uint sel_b = b->id;
 
-#ifdef __BIG_ENDIAN__
-  BLI_endian_switch_uint32(&sel_a);
-  BLI_endian_switch_uint32(&sel_b);
-#endif
-
   if (sel_a < sel_b) {
     return -1;
   }
@@ -4225,14 +4218,11 @@ static bool do_armature_box_select(const ViewContext *vc, const rcti *rect, cons
  */
 static int gpu_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
 {
+  /* NOTE: this is endianness-sensitive.
+   * GPUSelectResult values are always expected to be little-endian. */
   uint sel_a = ((GPUSelectResult *)sel_a_p)->id;
   uint sel_b = ((GPUSelectResult *)sel_b_p)->id;
 
-#ifdef __BIG_ENDIAN__
-  BLI_endian_switch_uint32(&sel_a);
-  BLI_endian_switch_uint32(&sel_b);
-#endif
-
   if (sel_a < sel_b) {
     return -1;
   }
diff --git a/source/blender/imbuf/intern/format_dds.cc b/source/blender/imbuf/intern/format_dds.cc
index 37e3fc0b75e..3d1a9e6241d 100644
--- a/source/blender/imbuf/intern/format_dds.cc
+++ b/source/blender/imbuf/intern/format_dds.cc
@@ -21,10 +21,6 @@
 #include "BLI_path_utils.hh"
 #include "BLI_string.h"
 
-#ifdef __BIG_ENDIAN__
-#  include "BLI_endian_switch.h"
-#endif
-
 OIIO_NAMESPACE_USING
 using namespace blender::imbuf;
 
@@ -307,13 +303,11 @@ static void LoadDXTCImage(ImBuf *ibuf, Filesystem::IOMemReader &mem_reader)
    * we've made it this far. */
   uint32_t flags = 0;
   mem_reader.pread(&flags, sizeof(uint32_t), 8);
+  /* NOTE: this is endianness-sensitive. */
+  /* `ibuf->dds_data.nummipmaps` is always expected to be little-endian. */
   mem_reader.pread(&ibuf->dds_data.nummipmaps, sizeof(uint32_t), 28);
   mem_reader.pread(&ibuf->dds_data.fourcc, sizeof(uint32_t), 84);
 
-#ifdef __BIG_ENDIAN__
-  BLI_endian_switch_uint32(&ibuf->dds_data.nummipmaps);
-#endif
-
   const uint32_t DDSD_MIPMAPCOUNT = 0x00020000U;
   if ((flags & DDSD_MIPMAPCOUNT) == 0) {
     ibuf->dds_data.nummipmaps = 1;
diff --git a/source/blender/imbuf/movie/intern/movie_proxy_indexer.cc b/source/blender/imbuf/movie/intern/movie_proxy_indexer.cc
index e456d90cd24..142abca3de4 100644
--- a/source/blender/imbuf/movie/intern/movie_proxy_indexer.cc
+++ b/source/blender/imbuf/movie/intern/movie_proxy_indexer.cc
@@ -83,7 +83,9 @@ static MovieIndexBuilder *index_builder_create(const char *filepath)
   fprintf(rv->fp,
           "%s%c%.3d",
           binary_header_str,
-          (ENDIAN_ORDER == B_ENDIAN) ? 'V' : 'v',
+          /* NOTE: this is endianness-sensitive.
+           * On Big Endian system 'V' must be used instead of 'v'. */
+          'v',
           INDEX_FILE_VERSION);
 
   return rv;
@@ -179,7 +181,10 @@ static MovieIndex *movie_index_open(const char *filepath)
     return nullptr;
   }
 
-  if ((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V')) {
+  /* NOTE: this is endianness-sensitive. */
+  BLI_assert(ELEM(header[8], 'v', 'V'));
+  const int16_t file_endianness = (header[8] == 'v') ? L_ENDIAN : B_ENDIAN;
+  if (file_endianness == B_ENDIAN) {
     for (int64_t i = 0; i < num_entries; i++) {
       BLI_endian_switch_int32(&idx->entries[i].frameno);
       BLI_endian_switch_uint64(&idx->entries[i].seek_pos_pts);
diff --git a/source/blender/imbuf/movie/intern/movie_write.cc b/source/blender/imbuf/movie/intern/movie_write.cc
index 7ff6c883bf2..309f8e4bc27 100644
--- a/source/blender/imbuf/movie/intern/movie_write.cc
+++ b/source/blender/imbuf/movie/intern/movie_write.cc
@@ -21,7 +21,6 @@
 
 #  include "MEM_guardedalloc.h"
 
-#  include "BLI_endian_defines.h"
 #  include "BLI_fileops.h"
 #  include "BLI_math_base.h"
 #  include "BLI_path_utils.hh"
@@ -254,30 +253,15 @@ static AVFrame *generate_video_frame(MovieWriter *context, const ImBuf *image)
     }
   }
   else {
-    /* Byte image: flip the image vertically, possibly with endian
-     * conversion. */
+    /* Byte image: flip the image vertically. */
     const size_t linesize_src = rgb_frame->width * 4;
     for (int y = 0; y < height; y++) {
       uint8_t *target = rgb_frame->data[0] + linesize_dst * (height - y - 1);
       const uint8_t *src = pixels + linesize_src * y;
 
-#  if ENDIAN_ORDER == L_ENDIAN
+      /* NOTE: this is endianness-sensitive. */
+      /* The target buffer is always expected to conaint little-endian RGBA values. */
       memcpy(target, src, linesize_src);
-
-#  elif ENDIAN_ORDER == B_ENDIAN
-      const uint8_t *end = src + linesize_src;
-      while (src != end) {
-        target[3] = src[0];
-        target[2] = src[1];
-        target[1] = src[2];
-        target[0] = src[3];
-
-        target += 4;
-        src += 4;
-      }
-#  else
-#    error ENDIAN_ORDER should either be L_ENDIAN or B_ENDIAN.
-#  endif
     }
   }
 
diff --git a/source/blender/makesdna/DNA_ID_enums.h b/source/blender/makesdna/DNA_ID_enums.h
index 52ccbdfe17f..e94684fee1a 100644
--- a/source/blender/makesdna/DNA_ID_enums.h
+++ b/source/blender/makesdna/DNA_ID_enums.h
@@ -97,14 +97,8 @@ typedef enum eIDPropertyFlag {
  * The tags represent types! This is a dirty way of enabling RTTI. The
  * sig_byte end endian defines aren't really used much.
  */
-
-#ifdef __BIG_ENDIAN__
-/* big endian */
-#  define MAKE_ID2(c, d) ((c) << 8 | (d))
-#else
-/* little endian */
-#  define MAKE_ID2(c, d) ((d) << 8 | (c))
-#endif
+/* NOTE: this is endianness-sensitive. */
+#define MAKE_ID2(c, d) ((d) << 8 | (c))
 
 /**
  * ID from database.
diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h
index aaee664a2ec..85da301354c 100644
--- a/source/blender/makesdna/DNA_genfile.h
+++ b/source/blender/makesdna/DNA_genfile.h
@@ -24,10 +24,11 @@ extern const int DNAlen;
 
 /**
  * Primitive (non-struct, non-pointer/function/array) types,
+ *
+ * NOTE: this is endianness-sensitive.
  * \warning Don't change these values!
- * Currently changes here will work on native endianness,
- * however #DNA_struct_switch_endian currently checks these
- * hard-coded values against those from old files.
+ * Currently changes here will work on native endianness, however before 5.0,
+ * #DNA_struct_switch_endian used to check these hard-coded values against those from old files.
  */
 typedef enum eSDNA_Type {
   SDNA_TYPE_CHAR = 0,
@@ -61,8 +62,7 @@ enum eSDNA_StructCompare {
   /* Struct has disappeared
    * (values of this struct type will not be loaded by the current Blender) */
   SDNA_CMP_REMOVED = 0,
-  /* Struct is the same
-   * (can be loaded with straight memory copy after any necessary endian conversion) */
+  /* Struct is the same (can be loaded with straight memory copy). */
   SDNA_CMP_EQUAL = 1,
   /* Struct is different in some way
    * (needs to be copied/converted field by field) */
@@ -74,12 +74,8 @@ enum eSDNA_StructCompare {
 /**
  * Constructs and returns a decoded SDNA structure from the given encoded SDNA data block.
  */
-struct SDNA *DNA_sdna_from_data(const void *data,
-                                int data_len,
-                                bool do_endian_swap,
-                                bool data_alloc,
-                                bool do_alias,
-                                const char **r_error_message);
+struct SDNA *DNA_sdna_from_data(
+    const void *data, int data_len, bool data_alloc, bool do_alias, const char **r_error_message);
 void DNA_sdna_free(struct SDNA *sdna);
 
 /* Access for current Blender versions SDNA. */
@@ -137,14 +133,6 @@ bool DNA_struct_member_exists_without_alias(const struct SDNA *sdna,
                                             const char *vartype,
                                             const char *name);
 
-/**
- * Does endian swapping on the fields of a struct value.
- *
- * \param sdna: SDNA of the struct_nr belongs to
- * \param struct_nr: Index of struct info within sdna
- * \param data: Struct data that is to be converted
- */
-void DNA_struct_switch_endian(const struct SDNA *sdna, int struct_index, char *data);
 /**
  * Constructs and returns an array of byte flags with one element for each struct in oldsdna,
  * indicating how it compares to newsdna.
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index ba77fed35ed..b086689817a 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -53,7 +53,6 @@ set(BLENLIB_SRC
   ../../blenlib/intern/BLI_linklist.cc
   ../../blenlib/intern/BLI_memarena.cc
   ../../blenlib/intern/BLI_mempool.cc
-  ../../blenlib/intern/endian_switch.cc
   ../../blenlib/intern/listbase.cc
   ../../blenlib/intern/string.cc
 
diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c
index fe72758c5d1..553f99c4bcf 100644
--- a/source/blender/makesdna/intern/dna_defaults.c
+++ b/source/blender/makesdna/intern/dna_defaults.c
@@ -69,7 +69,6 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "BLI_endian_switch.h"
 #include "BLI_math_base.h"
 #include "BLI_math_rotation.h"
 #include "BLI_utildefines.h"
diff --git a/source/blender/makesdna/intern/dna_genfile.cc b/source/blender/makesdna/intern/dna_genfile.cc
index 0bfe18e7787..d76a3c896d6 100644
--- a/source/blender/makesdna/intern/dna_genfile.cc
+++ b/source/blender/makesdna/intern/dna_genfile.cc
@@ -23,7 +23,6 @@
 
 #include "MEM_guardedalloc.h" /* for MEM_freeN MEM_mallocN MEM_callocN */
 
-#include "BLI_endian_switch.h"
 #include "BLI_ghash.h"
 #include "BLI_index_range.hh"
 #include "BLI_math_matrix_types.hh"
@@ -42,8 +41,8 @@
  * - if you want a struct not to be in DNA file: add two hash marks above it `(##)`.
  *
  * Structure DNA data is added to each blender file and to each executable, this to detect
- * in .blend files new variables in structs, changed array sizes, etc. It's also used for
- * converting endian and pointer size (32-64 bits)
+ * in .blend files new variables in structs, changed array sizes, etc. It is also used for
+ * converting pointer size (32-64 bits) (and it used to be to handle endianness).
  * As an extra, Python uses a call to detect run-time the contents of a blender struct.
  *
  * Create a structDNA: only needed when one of the input include (.h) files change.
@@ -95,7 +94,6 @@
  *  - array (`vec[3]`) to float struct (`vec3f`).
  *
  * DONE:
- *  - Endian compatibility.
  *  - Pointer conversion (32-64 bits).
  *
  * IMPORTANT:
@@ -117,13 +115,9 @@
  *    always check blender running from a console.
  */
 
-#ifdef __BIG_ENDIAN__
-/* Big Endian */
-#  define MAKE_ID(a, b, c, d) (int(a) << 24 | int(b) << 16 | (c) << 8 | (d))
-#else
+/* NOTE: this is endianness-sensitive. */
 /* Little Endian */
-#  define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a))
-#endif
+#define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a))
 
 /* ************************* DIV ********************** */
 
@@ -322,7 +316,7 @@ BLI_INLINE const char *pad_up_4(const char *ptr)
 /**
  * In sdna->data the data, now we convert that to something understandable
  */
-static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error_message)
+static bool init_structDNA(SDNA *sdna, const char **r_error_message)
 {
   int member_index_gravity_fix = -1;
 
@@ -358,10 +352,8 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
   if (*data == MAKE_ID('N', 'A', 'M', 'E')) {
     data++;
 
+    /* NOTE: this is endianness-sensitive. */
     sdna->members_num = *data;
-    if (do_endian_swap) {
-      BLI_endian_switch_int32(&sdna->members_num);
-    }
     sdna->members_num_alloc = sdna->members_num;
 
     data++;
@@ -398,10 +390,8 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
   if (*data == MAKE_ID('T', 'Y', 'P', 'E')) {
     data++;
 
+    /* NOTE: this is endianness-sensitive. */
     sdna->types_num = *data;
-    if (do_endian_swap) {
-      BLI_endian_switch_int32(&sdna->types_num);
-    }
 
     data++;
     sdna->types = MEM_calloc_arrayN(sdna->types_num, "sdnatypes");
@@ -428,13 +418,10 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
   short *sp;
   if (*data == MAKE_ID('T', 'L', 'E', 'N')) {
     data++;
+    /* NOTE: this is endianness-sensitive. */
     sp = (short *)data;
     sdna->types_size = sp;
 
-    if (do_endian_swap) {
-      BLI_endian_switch_int16_array(sp, sdna->types_num);
-    }
-
     sp += sdna->types_num;
   }
   if (!sdna->types_size) {
@@ -451,10 +438,8 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
   if (*data == MAKE_ID('S', 'T', 'R', 'C')) {
     data++;
 
+    /* NOTE: this is endianness-sensitive. */
     sdna->structs_num = *data;
-    if (do_endian_swap) {
-      BLI_endian_switch_int32(&sdna->structs_num);
-    }
 
     data++;
     sdna->structs = MEM_calloc_arrayN(sdna->structs_num, "sdnastrcs");
@@ -468,19 +453,10 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
   blender::Set struct_indices;
   sp = (short *)data;
   for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
+    /* NOTE: this is endianness-sensitive. */
     SDNA_Struct *struct_info = (SDNA_Struct *)sp;
     sdna->structs[struct_index] = struct_info;
 
-    if (do_endian_swap) {
-      BLI_endian_switch_int16(&struct_info->type_index);
-      BLI_endian_switch_int16(&struct_info->members_num);
-
-      for (short a = 0; a < struct_info->members_num; a++) {
-        SDNA_StructMember *member = &struct_info->members[a];
-        BLI_endian_switch_int16(&member->type_index);
-        BLI_endian_switch_int16(&member->member_index);
-      }
-    }
     if (!struct_indices.add(struct_info->type_index)) {
       *r_error_message = "Invalid duplicate struct type index in SDNA file";
       return false;
@@ -572,7 +548,6 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
 
 SDNA *DNA_sdna_from_data(const void *data,
                          const int data_len,
-                         bool do_endian_swap,
                          bool data_alloc,
                          const bool do_alias,
                          const char **r_error_message)
@@ -591,7 +566,7 @@ SDNA *DNA_sdna_from_data(const void *data,
   }
   sdna->data_alloc = data_alloc;
 
-  if (init_structDNA(sdna, do_endian_swap, &error_message)) {
+  if (init_structDNA(sdna, &error_message)) {
     if (do_alias) {
       DNA_sdna_alias_data_ensure_structs_map(sdna);
     }
@@ -618,7 +593,7 @@ static SDNA *g_sdna = nullptr;
 
 void DNA_sdna_current_init()
 {
-  g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, true, nullptr);
+  g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, true, nullptr);
 }
 
 const SDNA *DNA_sdna_current_get()
@@ -755,7 +730,8 @@ const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna
    *   - `struct Link` never needed DNA-versioning.
    *
    * NOTE: This may have been broken in BE/LE conversion cases, however this endianness handling
-   * code have likely been dead/never used in practice for many years now.
+   * code have likely been dead/never used in practice for many years, and has been removed in
+   * Blender 5.0.
    */
   BLI_STATIC_ASSERT(SDNA_RAW_DATA_STRUCT_INDEX == 0, "'raw data' SDNA struct index should be 0")
   compare_flags[SDNA_RAW_DATA_STRUCT_INDEX] = SDNA_CMP_EQUAL;
@@ -1115,74 +1091,6 @@ static int get_member_size_in_bytes(const SDNA *sdna, const SDNA_StructMember *m
   return type_size * array_length;
 }
 
-void DNA_struct_switch_endian(const SDNA *sdna, int struct_index, char *data)
-{
-  if (struct_index == -1) {
-    return;
-  }
-
-  const SDNA_Struct *struct_info = sdna->structs[struct_index];
-
-  int offset_in_bytes = 0;
-  for (int member_index = 0; member_index < struct_info->members_num; member_index++) {
-    const SDNA_StructMember *member = &struct_info->members[member_index];
-    const eStructMemberCategory member_category = get_struct_member_category(sdna, member);
-    char *member_data = data + offset_in_bytes;
-    const char *member_type_name = sdna->types[member->type_index];
-    const int member_array_length = sdna->members_array_num[member->member_index];
-
-    switch (member_category) {
-      case STRUCT_MEMBER_CATEGORY_STRUCT: {
-        const int substruct_size = sdna->types_size[member->type_index];
-        const int substruct_index = DNA_struct_find_index_without_alias(sdna, member_type_name);
-        BLI_assert(substruct_index != -1);
-        for (int a = 0; a < member_array_length; a++) {
-          DNA_struct_switch_endian(sdna, substruct_index, member_data + a * substruct_size);
-        }
-        break;
-      }
-      case STRUCT_MEMBER_CATEGORY_PRIMITIVE: {
-        switch (member->type_index) {
-          case SDNA_TYPE_SHORT:
-          case SDNA_TYPE_USHORT: {
-            BLI_endian_switch_int16_array((int16_t *)member_data, member_array_length);
-            break;
-          }
-          case SDNA_TYPE_INT:
-          case SDNA_TYPE_FLOAT: {
-            /* NOTE: intentionally ignore `long/ulong`, because these could be 4 or 8 bytes.
-             * Fortunately, we only use these types for runtime variables and only once for a
-             * struct type that is no longer used. */
-            BLI_endian_switch_int32_array((int32_t *)member_data, member_array_length);
-            break;
-          }
-          case SDNA_TYPE_INT64:
-          case SDNA_TYPE_UINT64:
-          case SDNA_TYPE_DOUBLE: {
-            BLI_endian_switch_int64_array((int64_t *)member_data, member_array_length);
-            break;
-          }
-          default: {
-            break;
-          }
-        }
-        break;
-      }
-      case STRUCT_MEMBER_CATEGORY_POINTER: {
-        /* See `readfile.cc` (#uint32_from_uint64_ptr swap endian argument),
-         * this is only done when reducing the size of a pointer from 4 to 8. */
-        if (sizeof(void *) < 8) {
-          if (sdna->pointer_size == 8) {
-            BLI_endian_switch_uint64_array((uint64_t *)member_data, member_array_length);
-          }
-        }
-        break;
-      }
-    }
-    offset_in_bytes += get_member_size_in_bytes(sdna, member);
-  }
-}
-
 enum eReconstructStepType {
   RECONSTRUCT_STEP_MEMCPY,
   RECONSTRUCT_STEP_CAST_PRIMITIVE,
diff --git a/source/blender/makesrna/intern/rna_define.cc b/source/blender/makesrna/intern/rna_define.cc
index 277f456b57d..6db4ac9315e 100644
--- a/source/blender/makesrna/intern/rna_define.cc
+++ b/source/blender/makesrna/intern/rna_define.cc
@@ -707,7 +707,7 @@ BlenderRNA *RNA_create()
   /* We need both alias and static (on-disk) DNA names. */
   const bool do_alias = true;
 
-  DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, do_alias, &error_message);
+  DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, do_alias, &error_message);
   if (DefRNA.sdna == nullptr) {
     CLOG_ERROR(&LOG, "Failed to decode SDNA: %s.", error_message);
     DefRNA.error = true;
diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.cc b/source/blender/modifiers/intern/MOD_meshcache_mdd.cc
index 7cc26ffc700..28070b6c956 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_mdd.cc
+++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.cc
@@ -11,11 +11,9 @@
 #include 
 #include 
 
+#include "BLI_endian_switch.h"
 #include "BLI_fileops.h"
 #include "BLI_math_base.h"
-#ifdef __LITTLE_ENDIAN__
-#  include "BLI_endian_switch.h"
-#endif
 #ifdef WIN32
 #  include "BLI_winstuff.h"
 #endif
@@ -41,9 +39,9 @@ static bool meshcache_read_mdd_head(FILE *fp,
     return false;
   }
 
-#ifdef __LITTLE_ENDIAN__
+  /* NOTE: this is endianness-sensitive. */
+  /* MDD is big-endian, its values need to be switched on little-endian systems. */
   BLI_endian_switch_int32_array((int *)mdd_head, 2);
-#endif
 
   if (mdd_head->verts_tot != verts_tot) {
     *r_err_str = RPT_("Vertex count mismatch");
@@ -104,9 +102,10 @@ static bool meshcache_read_mdd_range_from_time(FILE *fp,
   errno = 0;
   for (i = 0; i < mdd_head.frame_tot; i++) {
     frames_num_read += fread(&f_time, sizeof(float), 1, fp);
-#ifdef __LITTLE_ENDIAN__
+    /* NOTE: this is endianness-sensitive. */
+    /* MDD is big-endian, its values need to be switched on little-endian systems. */
     BLI_endian_switch_float(&f_time);
-#endif
+
     if (f_time >= time) {
       frames_num_expect = i + 1;
       break;
@@ -169,11 +168,11 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
     for (i = mdd_head.verts_tot; i != 0; i--, vco += 3) {
       verts_read_num += fread(vco, sizeof(float[3]), 1, fp);
 
-#  ifdef __LITTLE_ENDIAN__
+      /* NOTE: this is endianness-sensitive. */
+      /* MDD is big-endian, its values need to be switched on little-endian systems. */
       BLI_endian_switch_float(vco + 0);
       BLI_endian_switch_float(vco + 1);
       BLI_endian_switch_float(vco + 2);
-#  endif /* __LITTLE_ENDIAN__ */
     }
 #else
     /* no blending */
@@ -181,9 +180,9 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
       *r_err_str = errno ? strerror(errno) : RPT_("Failed to read frame");
       return false;
     }
-#  ifdef __LITTLE_ENDIAN__
+    /* NOTE: this is endianness-sensitive. */
+    /* MDD is big-endian, its values need to be switched on little-endian systems. */
     BLI_endian_switch_float_array(vertexCos[0], mdd_head.verts_tot * 3);
-#  endif
 #endif
   }
   else {
@@ -194,11 +193,11 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
       float tvec[3];
       verts_read_num += fread(tvec, sizeof(float[3]), 1, fp);
 
-#ifdef __LITTLE_ENDIAN__
+      /* NOTE: this is endianness-sensitive. */
+      /* MDD is big-endian, its values need to be switched on little-endian systems. */
       BLI_endian_switch_float(tvec + 0);
       BLI_endian_switch_float(tvec + 1);
       BLI_endian_switch_float(tvec + 2);
-#endif
 
       vco[0] = (vco[0] * ifactor) + (tvec[0] * factor);
       vco[1] = (vco[1] * ifactor) + (tvec[1] * factor);
diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.cc b/source/blender/modifiers/intern/MOD_meshcache_pc2.cc
index 292fe60e3de..5ec010c311e 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_pc2.cc
+++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.cc
@@ -14,9 +14,6 @@
 #include "BLI_utildefines.h"
 
 #include "BLI_fileops.h"
-#ifdef __BIG_ENDIAN__
-#  include "BLI_endian_switch.h"
-#endif
 
 #ifdef WIN32
 #  include "BLI_winstuff.h"
@@ -52,10 +49,9 @@ static bool meshcache_read_pc2_head(FILE *fp,
     return false;
   }
 
-#ifdef __BIG_ENDIAN__
-  BLI_endian_switch_int32_array(&pc2_head->file_version,
-                                (sizeof(*pc2_head) - sizeof(pc2_head->header)) / sizeof(int));
-#endif
+  /* NOTE: this is endianness-sensitive. */
+  /* The pc2_head->file_version and following values would need to be switched on big-endian
+   * systems. */
 
   if (pc2_head->verts_tot != verts_tot) {
     *r_err_str = RPT_("Vertex count mismatch");
@@ -150,11 +146,8 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
     for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) {
       verts_read_num += fread(vco, sizeof(float[3]), 1, fp);
 
-#ifdef __BIG_ENDIAN__
-      BLI_endian_switch_float(vco + 0);
-      BLI_endian_switch_float(vco + 1);
-      BLI_endian_switch_float(vco + 2);
-#endif /* __BIG_ENDIAN__ */
+      /* NOTE: this is endianness-sensitive. */
+      /* The `vco` values would need to be switched on big-endian systems. */
     }
   }
   else {
@@ -165,11 +158,8 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
       float tvec[3];
       verts_read_num += fread(tvec, sizeof(float[3]), 1, fp);
 
-#ifdef __BIG_ENDIAN__
-      BLI_endian_switch_float(tvec + 0);
-      BLI_endian_switch_float(tvec + 1);
-      BLI_endian_switch_float(tvec + 2);
-#endif /* __BIG_ENDIAN__ */
+      /* NOTE: this is endianness-sensitive. */
+      /* The `tvec` values would need to be switched on big-endian systems. */
 
       vco[0] = (vco[0] * ifactor) + (tvec[0] * factor);
       vco[1] = (vco[1] * ifactor) + (tvec[1] * factor);
diff --git a/source/blender/python/mathutils/mathutils_Euler.cc b/source/blender/python/mathutils/mathutils_Euler.cc
index 961681308ad..566c9ecd002 100644
--- a/source/blender/python/mathutils/mathutils_Euler.cc
+++ b/source/blender/python/mathutils/mathutils_Euler.cc
@@ -39,11 +39,8 @@ short euler_order_from_string(const char *str, const char *error_prefix)
 {
   if (str[0] && str[1] && str[2] && str[3] == '\0') {
 
-#ifdef __LITTLE_ENDIAN__
-#  define MAKE_ID3(a, b, c) ((a) | ((b) << 8) | ((c) << 16))
-#else
-#  define MAKE_ID3(a, b, c) (((a) << 24) | ((b) << 16) | ((c) << 8))
-#endif
+/* NOTE: this is endianness-sensitive. */
+#define MAKE_ID3(a, b, c) ((a) | ((b) << 8) | ((c) << 16))
 
     switch (*((const PY_INT32_T *)str)) {
       case MAKE_ID3('X', 'Y', 'Z'):
diff --git a/source/creator/creator.cc b/source/creator/creator.cc
index ec585b3e3d4..1c68b96afee 100644
--- a/source/creator/creator.cc
+++ b/source/creator/creator.cc
@@ -28,6 +28,7 @@
 
 #include "DNA_genfile.h"
 
+#include "BLI_endian_defines.h"
 #include "BLI_fftw.hh"
 #include "BLI_string.h"
 #include "BLI_system.h"
@@ -98,6 +99,8 @@
 
 #include "creator_intern.h" /* Own include. */
 
+BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems")
+
 /* -------------------------------------------------------------------- */
 /** \name Local Defines
  * \{ */
diff --git a/tests/python/bl_blendfile_versioning.py b/tests/python/bl_blendfile_versioning.py
index 26659b45114..aad022a3978 100644
--- a/tests/python/bl_blendfile_versioning.py
+++ b/tests/python/bl_blendfile_versioning.py
@@ -31,30 +31,205 @@ class TestBlendFileOpenAllTestFiles(TestHelper):
         # Each file in this list should either be the source of a bug report,
         # or removed from tests repo.
         self.excluded_paths = {
-            # tests/modifier_stack/explode_modifier.blend
+            # modifier_stack/explode_modifier.blend
             # BLI_assert failed: source/blender/blenlib/BLI_ordered_edge.hh:41, operator==(), at 'e1.v_low < e1.v_high'
             "explode_modifier.blend",
 
-            # tests/depsgraph/deg_anim_camera_dof_driving_material.blend
+            # depsgraph/deg_anim_camera_dof_driving_material.blend
             # ERROR (bke.fcurve):
             # source/blender/blenkernel/intern/fcurve_driver.cc:188 dtar_get_prop_val:
             # Driver Evaluation Error: cannot resolve target for OBCamera ->
             # data.dof_distance
             "deg_anim_camera_dof_driving_material.blend",
 
-            # tests/depsgraph/deg_driver_shapekey_same_datablock.blend
+            # depsgraph/deg_driver_shapekey_same_datablock.blend
             # Error: Not freed memory blocks: 4, total unfreed memory 0.000427 MB
             "deg_driver_shapekey_same_datablock.blend",
 
-            # tests/physics/fluidsim.blend
+            # physics/fluidsim.blend
             # Error: Not freed memory blocks: 3, total unfreed memory 0.003548 MB
             "fluidsim.blend",
 
-            # tests/opengl/ram_glsl.blend
+            # opengl/ram_glsl.blend
             # Error: Not freed memory blocks: 4, total unfreed memory 0.000427 MB
             "ram_glsl.blend",
         }
 
+        # Some files are expected to be invalid.
+        # This mapping stores filenames as keys, and expected error message as value.
+        self.invalid_paths = {
+            # animation/driver-object-eyes.blend
+            # File generated from a big endian build of Blender.
+            "driver-object-eyes.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+
+            # modeling/faceselectmode.blend
+            # File generated from a big endian build of Blender.
+            "faceselectmode.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # modeling/weight-paint_test.blend
+            # File generated from a big endian build of Blender.
+            "weight-paint_test.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+
+            # io_tests/blend_big_endian/1.62/glass.blend
+            # File generated from a big endian build of Blender.
+            "glass.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/1.62/room.blend
+            # File generated from a big endian build of Blender.
+            "room.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/1.69/s-mesh.blend
+            # File generated from a big endian build of Blender.
+            "s-mesh.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/1.70/escher.blend
+            # File generated from a big endian build of Blender.
+            "escher.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/1.98/egypt.blend
+            # File generated from a big endian build of Blender.
+            "egypt.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.25/FroggyPacked.blend
+            # File generated from a big endian build of Blender.
+            "FroggyPacked.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.30/CtrlObject.blend
+            # File generated from a big endian build of Blender.
+            "CtrlObject.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.30/demofile.blend
+            # File generated from a big endian build of Blender.
+            "demofile.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.30/dolphin.blend
+            # File generated from a big endian build of Blender.
+            "dolphin.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.30/mball.blend
+            # File generated from a big endian build of Blender.
+            "mball.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.30/motor9.blend
+            # File generated from a big endian build of Blender.
+            "motor9.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.30/relative.blend
+            # File generated from a big endian build of Blender.
+            "relative.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.31/Raptor.blend
+            # File generated from a big endian build of Blender.
+            "Raptor.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.31/allselect.blend
+            # File generated from a big endian build of Blender.
+            "allselect.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.31/arealight.blend
+            # File generated from a big endian build of Blender.
+            "arealight.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.31/hairball.blend
+            # File generated from a big endian build of Blender.
+            "hairball.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.31/luxo.blend
+            # File generated from a big endian build of Blender.
+            "luxo.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.31/monkey_cornelius.blend
+            # File generated from a big endian build of Blender.
+            "monkey_cornelius.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.31/refract_monkey.blend
+            # File generated from a big endian build of Blender.
+            "refract_monkey.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.31/robo.blend
+            # File generated from a big endian build of Blender.
+            "robo.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.34/flippedmatrixes.blend
+            # File generated from a big endian build of Blender.
+            "flippedmatrixes.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.34/lostride.blend
+            # File generated from a big endian build of Blender.
+            "lostride.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.34/tapercurve.blend
+            # File generated from a big endian build of Blender.
+            "tapercurve.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.36/pathdist.blend
+            # File generated from a big endian build of Blender.
+            "pathdist.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+            # io_tests/blend_big_endian/2.76/bird_sintel.blend
+            # File generated from a big endian build of Blender.
+            "bird_sintel.blend": (
+                (OSError, RuntimeError),
+                "created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
+            ),
+        }
+
         # Directories to exclude relative to `./tests/files/`.
         self.excluded_dirs = ()
 
@@ -102,6 +277,18 @@ class TestBlendFileOpenAllTestFiles(TestHelper):
                 return True
         return False
 
+    def invalid_path_exception_process(self, bfp, exception):
+        expected_failure = self.invalid_paths.get(os.path.basename(bfp), None)
+        if not expected_failure:
+            raise exception
+        # Check expected exception type(s).
+        if not isinstance(exception, expected_failure[0]):
+            raise exception
+        # Check expected exception (partial) message.
+        if expected_failure[1] not in str(exception):
+            raise exception
+        print(f"\tExpected failure: '{exception}'", flush=True)
+
     def test_open(self):
         for bfp in self.blendfile_paths:
             if self.skip_path_check(bfp):
@@ -109,7 +296,10 @@ class TestBlendFileOpenAllTestFiles(TestHelper):
             if not self.args.is_quiet:
                 print(f"Trying to open {bfp}", flush=True)
             bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
-            bpy.ops.wm.open_mainfile(filepath=bfp, load_ui=False)
+            try:
+                bpy.ops.wm.open_mainfile(filepath=bfp, load_ui=False)
+            except BaseException as e:
+                self.invalid_path_exception_process(bfp, e)
 
     def link_append(self, do_link):
         operation_name = "link" if do_link else "append"
@@ -117,15 +307,18 @@ class TestBlendFileOpenAllTestFiles(TestHelper):
             if self.skip_path_check(bfp):
                 continue
             bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
-            with bpy.data.libraries.load(bfp, link=do_link) as (lib_in, lib_out):
-                if len(lib_in.collections):
-                    if not self.args.is_quiet:
-                        print(f"Trying to {operation_name} {bfp}/Collection/{lib_in.collections[0]}", flush=True)
-                    lib_out.collections.append(lib_in.collections[0])
-                elif len(lib_in.objects):
-                    if not self.args.is_quiet:
-                        print(f"Trying to {operation_name} {bfp}/Object/{lib_in.objects[0]}", flush=True)
-                    lib_out.objects.append(lib_in.objects[0])
+            try:
+                with bpy.data.libraries.load(bfp, link=do_link) as (lib_in, lib_out):
+                    if len(lib_in.collections):
+                        if not self.args.is_quiet:
+                            print(f"Trying to {operation_name} {bfp}/Collection/{lib_in.collections[0]}", flush=True)
+                        lib_out.collections.append(lib_in.collections[0])
+                    elif len(lib_in.objects):
+                        if not self.args.is_quiet:
+                            print(f"Trying to {operation_name} {bfp}/Object/{lib_in.objects[0]}", flush=True)
+                        lib_out.objects.append(lib_in.objects[0])
+            except BaseException as e:
+                self.invalid_path_exception_process(bfp, e)
 
     def test_link(self):
         self.link_append(do_link=True)