diff --git a/tools/Makefile b/tools/Makefile index 3bc54e2e..f5871c09 100755 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,10 +1,9 @@ CC := gcc CXX := g++ CFLAGS := -I . -Wall -Wextra -Wno-unused-parameter -pedantic -std=c99 -O2 -s -CXXFLAGS := --std=c++17 -lstdc++fs -lcrypto -lssl -lpthread +CXXFLAGS := --std=c++17 LDFLAGS := -lm -PROGRAMS := n64crc -CXX_PROGRAMS := dkr_assets_tool +PROGRAMS := n64crc dkr_assets_tool BUILD_DIR := dkr_assets_tool_classes/_build @@ -17,10 +16,10 @@ default: all n64crc_SOURCES := n64crc.c -all: $(PROGRAMS) $(CXX_PROGRAMS) +all: $(PROGRAMS) clean: - rm -Rf $(PROGRAMS) $(CXX_PROGRAMS) $(BUILD_DIR) + rm -Rf $(PROGRAMS) $(BUILD_DIR) distclean: clean @@ -31,16 +30,16 @@ dkr_assets_tool_CPP_FILES := dkr_assets_tool.cpp \ $(call rwildcard,dkr_assets_tool_classes,*.cpp) dkr_assets_tool_C_FILES := $(call rwildcard,dkr_assets_tool_classes,*.c) - + dkr_assets_tool_OBJ_FILES := $(foreach file,$(dkr_assets_tool_C_FILES),$(BUILD_DIR)/$(file:.c=.o)) \ $(foreach file,$(dkr_assets_tool_CPP_FILES),$(BUILD_DIR)/$(file:.cpp=.o)) DUMMY != mkdir -p $(sort $(dir $(dkr_assets_tool_OBJ_FILES))) $(BUILD_DIR)/%.o: %.c - $(CXX) -c $^ -o $@ $(CXXFLAGS) $(LDFLAGS) + $(CC) -c $^ -o $@ $(CFLAGS) $(BUILD_DIR)/%.o: %.cpp - $(CXX) -c $< -o $@ $(CXXFLAGS) $(LDFLAGS) + $(CXX) -c $< -o $@ $(CXXFLAGS) dkr_assets_tool: $(dkr_assets_tool_OBJ_FILES) $(CXX) $^ -o $@ $(CXXFLAGS) $(LDFLAGS) diff --git a/tools/dkr_assets_tool_classes/common/util/fileHelper.cpp b/tools/dkr_assets_tool_classes/common/util/fileHelper.cpp index 15369f46..dce18bde 100644 --- a/tools/dkr_assets_tool_classes/common/util/fileHelper.cpp +++ b/tools/dkr_assets_tool_classes/common/util/fileHelper.cpp @@ -1,4 +1,5 @@ #include "fileHelper.h" +#include "md5.h" std::string assetsFolderPath = ""; std::string version = ""; @@ -216,25 +217,12 @@ void make_uppercase(std::string& input) { } std::string calculate_md5(std::vector &bytes) { - uint8_t buffer[0x4000]; - uint8_t digest[MD5_DIGEST_LENGTH]; - + md5::Digest digest = md5::compute(bytes); std::stringstream ss; - MD5_CTX md5Context; - - MD5_Init(&md5Context); - MD5_Update(&md5Context, &bytes[0], bytes.size()); - int res = MD5_Final(digest, &md5Context); - - if(res == 0) { - return ""; - } - // set up stringstream format ss << std::hex << std::setfill('0'); - for(uint8_t uc: digest) { ss << std::setw(2) << (int)uc; } diff --git a/tools/dkr_assets_tool_classes/common/util/fileHelper.h b/tools/dkr_assets_tool_classes/common/util/fileHelper.h index 4cde0f43..fd69d741 100644 --- a/tools/dkr_assets_tool_classes/common/util/fileHelper.h +++ b/tools/dkr_assets_tool_classes/common/util/fileHelper.h @@ -8,10 +8,9 @@ #include #include #include -#include // C++17 -#include +#include namespace fs = std::filesystem; #include "errorHelper.h" diff --git a/tools/dkr_assets_tool_classes/common/util/md5.h b/tools/dkr_assets_tool_classes/common/util/md5.h new file mode 100644 index 00000000..58962849 --- /dev/null +++ b/tools/dkr_assets_tool_classes/common/util/md5.h @@ -0,0 +1,206 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef CONSTEXPR_MD5_H_ +#define CONSTEXPR_MD5_H_ + +#include +#include +#include + +namespace md5 { + using Digest = std::array; + + namespace details { + constexpr uint32_t CBLOCK = 64; + constexpr uint32_t LBLOCK = CBLOCK / 4; + + constexpr Digest make_digest(const std::array& input) noexcept { + Digest digest{}; + for (size_t i = 0; i < input.size(); ++i) { + digest[i * 4] = static_cast((input[i]) & 0xff); + digest[i * 4 + 1] = static_cast((input[i] >> 8) & 0xff); + digest[i * 4 + 2] = static_cast((input[i] >> 16) & 0xff); + digest[i * 4 + 3] = static_cast((input[i] >> 24) & 0xff); + } + return digest; + } + + using Fn = uint32_t(*)(uint32_t, uint32_t, uint32_t); + constexpr uint32_t f(uint32_t b, uint32_t c, uint32_t d) noexcept { + return (b & c) | (~b & d); + } + + constexpr uint32_t g(uint32_t b, uint32_t c, uint32_t d) noexcept { + return (b & d) | (c & ~d); + } + + constexpr uint32_t h(uint32_t b, uint32_t c, uint32_t d) noexcept { + return b ^ c ^ d; + } + + constexpr uint32_t i(uint32_t b, uint32_t c, uint32_t d) noexcept { + return c ^ (b | ~d); + } + + constexpr Fn F[4] = { f, g, h, i }; + + constexpr uint32_t G[CBLOCK] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 + }; + + constexpr uint32_t K[CBLOCK] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + + constexpr uint32_t S[LBLOCK] = { + 7, 12, 17, 22, + 5, 9, 14, 20, + 4, 11, 16, 23, + 6, 10, 15, 21 + }; + + constexpr uint8_t PADDING[CBLOCK] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + constexpr uint32_t rotate(uint32_t x, uint32_t n) noexcept { + return (x << n) | (x >> (32 - n)); + } + + constexpr uint32_t t(Fn f, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) noexcept { + return b + rotate(a + f(b, c, d) + x + ac, s); + } + + constexpr uint32_t to_uint32(const unsigned char* data) noexcept { + return + (static_cast(data[3]) << 24) | + (static_cast(data[2]) << 16) | + (static_cast(data[1]) << 8) | + (static_cast(data[0])); + } + + struct Context { + std::array buffer; + std::array state; + uint32_t nl, nh; + + constexpr Context() noexcept + : buffer() + , state{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 } + , nl(0) + , nh(0) + {} + + constexpr void append(const uint8_t* data, size_t len) noexcept { + std::array input{}; + auto k = (nl >> 3) & 0x3f; + auto length = static_cast(len); + nl += length << 3; + if (nl < length << 3) { + nh += 1; + } + nh += length >> 29; + for (auto ptr = data; ptr != data + len; ++ptr) { + buffer[k++] = static_cast(static_cast(*ptr) + UCHAR_MAX + 1); + if (k == 0x40) { + auto j = 0; + for (auto i = 0; i < LBLOCK; ++i) { + input[i] = to_uint32(&buffer[j]); + j += 4; + } + transform(input); + k = 0; + } + } + } + + constexpr void transform(const std::array& input) noexcept { + auto a = state[0], b = state[1], c = state[2], d = state[3]; + for (uint32_t r = 0; r < 4; ++r) { + const auto g = G + r * LBLOCK; + const auto s = S + r * 4; + const auto k = K + r * LBLOCK; + + for (auto i = 0; i < input.size(); ++i) { + const auto new_b = t(F[r], a, b, c, d, input[g[i]], s[i % 4], k[i]); + a = d; + d = c; + c = b; + b = new_b; + } + } + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + } + + constexpr Digest final() noexcept { + + std::array input{}; + const auto k = ((nl >> 3) & 0x3f); + input[14] = nl; + input[15] = nh; + + append(PADDING, k < 56 ? 56 - k : 120 - k); + + auto j = 0; + for (auto i = 0; i < 14; ++i) { + input[i] = to_uint32(&buffer[j]); + j += 4; + } + transform(input); + + return make_digest(state); + } + }; + } + + static Digest compute(std::vector &bytes) { + details::Context c; + c.append(&bytes[0], bytes.size()); + return c.final(); + } +} + +#endif diff --git a/tools/dkr_assets_tool_classes/libs/n64graphics.h b/tools/dkr_assets_tool_classes/libs/n64graphics.h index 9ced50e7..6f73156d 100644 --- a/tools/dkr_assets_tool_classes/libs/n64graphics.h +++ b/tools/dkr_assets_tool_classes/libs/n64graphics.h @@ -1,6 +1,10 @@ #ifndef N64GRAPHICS_H_ #define N64GRAPHICS_H_ +#ifdef __cplusplus +extern "C" { +#endif + #include // intermediate formats @@ -97,4 +101,8 @@ const char *n64graphics_get_read_version(void); // get version of underlying graphics writing library const char *n64graphics_get_write_version(void); +#ifdef __cplusplus +} // extern "C" +#endif + #endif // N64GRAPHICS_H_