diff --git a/CMakeLists.txt b/CMakeLists.txt index e68124b8..52359634 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,6 +160,17 @@ endif() option(TV_BUILD_TESTS "Build and run tests" OFF) +# Endianness detection + +include(TestBigEndian) +TEST_BIG_ENDIAN(BIGENDIAN) +if(${BIGENDIAN}) + add_definitions(-DTV_BIG_ENDIAN) + tv_message_mp(STATUS "BIG ENDIAN platform detected") +else() + tv_message_mp(STATUS "LITTLE ENDIAN platform detected") +endif(${BIGENDIAN}) + # Library add_subdirectory(source) diff --git a/include/tvision/internal/ansidisp.h b/include/tvision/internal/ansidisp.h index b39fdcc8..946768d6 100644 --- a/include/tvision/internal/ansidisp.h +++ b/include/tvision/internal/ansidisp.h @@ -30,14 +30,14 @@ struct TermColor TermColor& operator=(uint32_t val) noexcept { - memcpy(this, &val, sizeof(*this)); + tvintmemcpy(this, &val, sizeof(*this)); return *this; static_assert(sizeof(*this) == 4, ""); } operator uint32_t() const noexcept { uint32_t val; - memcpy(&val, this, sizeof(*this)); + tvintmemcpy(&val, this, sizeof(*this)); return val; } TermColor(uint8_t aIdx, TermColorTypes aType) noexcept diff --git a/include/tvision/internal/codepage.h b/include/tvision/internal/codepage.h index 6c90ab8b..a51fa5ae 100644 --- a/include/tvision/internal/codepage.h +++ b/include/tvision/internal/codepage.h @@ -23,7 +23,7 @@ class CpTranslator static uint32_t toPackedUtf8(unsigned char c) noexcept { uint32_t asInt; - memcpy(&asInt, (*currentToUtf8)[c], sizeof(asInt)); + tvintmemcpy(&asInt, (*currentToUtf8)[c], sizeof(asInt)); return asInt; } diff --git a/include/tvision/internal/strings.h b/include/tvision/internal/strings.h index 0cb8254e..ed758eae 100644 --- a/include/tvision/internal/strings.h +++ b/include/tvision/internal/strings.h @@ -13,8 +13,12 @@ inline constexpr Int string_as_int(TStringView s) noexcept { Int res = 0; for (size_t i = 0; i < min(s.size(), sizeof(res)); ++i) +#ifndef TV_BIG_ENDIAN // CAUTION: Assumes Little Endian. res |= uint64_t(uint8_t(s[i])) << 8*i; +#else + res |= uint64_t(uint8_t(s[i])) << 8*(sizeof(res)-1-i); +#endif return res; } @@ -35,6 +39,7 @@ inline char *fast_btoa(uint8_t value, char *buffer) noexcept { extern const btoa_lut_t btoa_lut; const auto &lut = (btoa_lut_elem_t (&) [256]) btoa_lut; +#ifndef TV_BIG_ENDIAN // CAUTION: Assumes Little Endian. // We can afford to write more bytes into 'buffer' than digits. uint32_t asInt; @@ -42,6 +47,11 @@ inline char *fast_btoa(uint8_t value, char *buffer) noexcept memcpy(buffer, &asInt, 4); return buffer + (asInt >> 24); static_assert(sizeof(btoa_lut_elem_t) == 4, ""); +#else + memcpy(buffer, &lut[value].chars, lut[value].digits); + buffer[lut[value].digits] = 0; // null-terminate for safety - may not be needed? + return buffer + lut[value].digits; +#endif } } // namespace tvision diff --git a/include/tvision/internal/utf8.h b/include/tvision/internal/utf8.h index df02c5a9..9e2487b6 100644 --- a/include/tvision/internal/utf8.h +++ b/include/tvision/internal/utf8.h @@ -66,7 +66,7 @@ inline size_t utf32To8(uint32_t u32, char u8[4]) noexcept (( u32 & 0b00111111) | 0b10000000) << 24; length = 4; } - memcpy(u8, &asInt, 4); + tvintmemcpy(u8, &asInt, 4); return length; } diff --git a/include/tvision/scrncell.h b/include/tvision/scrncell.h index f2f8fef3..c356fe65 100644 --- a/include/tvision/scrncell.h +++ b/include/tvision/scrncell.h @@ -83,7 +83,7 @@ inline void TCellChar::moveInt(uint32_t mbc, bool wide) { memset(this, 0, sizeof(*this)); // CAUTION: Assumes Little Endian. - memcpy(_text, &mbc, sizeof(mbc)); + tvintmemcpy(_text, &mbc, sizeof(mbc)); _flags = -int(wide) & fWide; } diff --git a/include/tvision/system.h b/include/tvision/system.h index 71a65bbe..19a96141 100644 --- a/include/tvision/system.h +++ b/include/tvision/system.h @@ -187,8 +187,14 @@ inline void TMouse::registerHandler( unsigned mask, void (_FAR *func)() ) struct CharScanType { +#ifndef TV_BIG_ENDIAN uchar charCode; uchar scanCode; +#else + // big endian version reverses the order + uchar scanCode; + uchar charCode; +#endif }; struct KeyDownEvent diff --git a/include/tvision/util.h b/include/tvision/util.h index 9b2742ae..7b70ff59 100644 --- a/include/tvision/util.h +++ b/include/tvision/util.h @@ -110,4 +110,21 @@ char *ultoa( ulong value, char *buffer, int radix ) noexcept; #endif // __BORLANDC__ +#ifdef TV_BIG_ENDIAN + inline void *be_tvintmemcpy(void *dest, const void *src, size_t n) // implementation of tvintmemcpy for Big Endian platforms, reverses bytes while copying + { + // TVision assumes Little Endian byte order for some operations where uints are assigned to stucts etc. + // This memcpy-like function reverses the order of the bytes when copying them, so can be used on big-endian + // platforms in place of a standard memcpy. + for (size_t i=0; i