diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..e380b8c --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,8 @@ +Checks: ' + , clang-analyzer-* + , cppcoreguidelines-* + , -cppcoreguidelines-avoid-magic-numbers + , -cppcoreguidelines-pro-bounds-constant-array-index + , -cppcoreguidelines-macro-usage + , -cppcoreguidelines-avoid-const-or-ref-data-members +' \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..a759924 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,28 @@ +name: matar +on: [push, pull_request, workflow_dispatch] + +env: + BUILDDIR: build + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v20 + with: + extra_nix_config: | + auto-optimise-store = true + experimental-features = nix-command flakes + + - name: meson build + run: nix develop -c meson setup $BUILDDIR + + - name: clang-format check + run: nix develop -c ninja clang-format-check -C $BUILDDIR + + - name: clang-tidy check + run: nix develop -c ninja clang-tidy -C $BUILDDIR + + - name: ninja compile + run: nix develop -c ninja -C $BUILDDIR diff --git a/apps/target/main.cc b/apps/target/main.cc index 2efe183..3a5d692 100644 --- a/apps/target/main.cc +++ b/apps/target/main.cc @@ -8,10 +8,12 @@ #include #include +// NOLINTBEGIN + int main(int argc, const char* argv[]) { std::vector rom; - std::array bios; + std::array bios = { 0 }; auto usage = [argv]() { std::cerr << "Usage: " << argv[0] << " [-b ]" << std::endl; @@ -85,3 +87,5 @@ main(int argc, const char* argv[]) { } return 0; } + +// NOLINTEND diff --git a/flake.nix b/flake.nix index 6eaa4af..fe03bc4 100644 --- a/flake.nix +++ b/flake.nix @@ -8,7 +8,7 @@ systems = [ "x86_64-linux" "aarch64-linux" - "i686-linux" + # "i686-linux" ]; eachSystem = with nixpkgs.lib; f: foldAttrs mergeAttrs { } (map (s: mapAttrs (_: v: { ${s} = v; }) (f s)) systems); @@ -53,10 +53,6 @@ packages = nativeBuildInputs ++ (with pkgs; [ # dev tools clang-tools_16 - - # other tools - valgrind - llvm.lldb ]); }; default = matar; diff --git a/include/cpu/utility.hh b/include/cpu/utility.hh index a790ebd..dcee945 100644 --- a/include/cpu/utility.hh +++ b/include/cpu/utility.hh @@ -40,6 +40,12 @@ enum class Condition { AL = 0b1110 }; +// https://fmt.dev/dev/api.html#std-ostream-support +std::ostream& +operator<<(std::ostream& os, const Condition cond); +template<> +struct fmt::formatter : ostream_formatter {}; + enum class OpCode { AND = 0b0000, EOR = 0b0001, @@ -68,6 +74,6 @@ enum class ShiftType { // https://fmt.dev/dev/api.html#std-ostream-support std::ostream& -operator<<(std::ostream& os, const Condition cond); +operator<<(std::ostream& os, const ShiftType cond); template<> -struct fmt::formatter : ostream_formatter {}; +struct fmt::formatter : ostream_formatter {}; diff --git a/src/cpu/cpu.cc b/src/cpu/cpu.cc index 9873fbc..d2097da 100644 --- a/src/cpu/cpu.cc +++ b/src/cpu/cpu.cc @@ -7,10 +7,10 @@ using namespace logger; Cpu::Cpu(Bus& bus) - : gpr(0) + : bus(std::make_shared(bus)) + , gpr({ 0 }) , cpsr(0) , spsr(0) - , bus(std::make_shared(bus)) , gpr_banked({ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }) , spsr_banked({ 0, 0, 0, 0, 0 }) { cpsr.set_mode(Mode::System); @@ -18,20 +18,25 @@ Cpu::Cpu(Bus& bus) cpsr.set_fiq_disabled(true); cpsr.set_state(State::Arm); log_info("CPU successfully initialised"); + + // PC is always two instructions ahead in the pipeline + pc += 2 * ARM_INSTRUCTION_SIZE; } /* change modes */ void -Cpu::chg_mode(Mode from, Mode to) { +Cpu::chg_mode(const Mode to) { + Mode from = cpsr.mode(); + if (from == to) return; /* TODO: replace visible registers with view once I understand how to * concatenate views */ #define STORE_BANKED(mode, MODE) \ - std::copy(gpr + GPR_##MODE##_BANKED_FIRST, \ - gpr + GPR_##MODE##_BANKED_FIRST + GPR_##MODE##_BANKED_COUNT, \ - gpr_banked.mode) + std::copy(gpr.begin() + GPR_##MODE##_FIRST, \ + gpr.begin() + GPR_COUNT - 1, \ + gpr_banked.mode.begin()) switch (from) { case Mode::Fiq: @@ -66,9 +71,9 @@ Cpu::chg_mode(Mode from, Mode to) { } #define RESTORE_BANKED(mode, MODE) \ - std::copy(gpr_banked.mode, \ - gpr_banked.mode + GPR_##MODE##_BANKED_COUNT, \ - gpr + GPR_##MODE##_BANKED_FIRST) + std::copy(gpr_banked.mode.begin(), \ + gpr_banked.mode.end(), \ + gpr.begin() + GPR_##MODE##_FIRST) switch (to) { case Mode::Fiq: @@ -109,11 +114,15 @@ Cpu::chg_mode(Mode from, Mode to) { void Cpu::step() { - uint32_t insn = 0xffffffff; + uint32_t cur_pc = pc - 2 * ARM_INSTRUCTION_SIZE; if (cpsr.state() == State::Arm) { - std::string disassembled = exec_arm(insn); - log_info("{:#010X} : {}", gpr[15], disassembled); - gpr[15] += ARM_INSTRUCTION_SIZE; + log_info("{:#034b}", bus->read_word(cur_pc)); + + std::string disassembled = exec_arm(bus->read_word(cur_pc)); + + log_info("{:#010X} : {}", cur_pc, disassembled); + + pc += ARM_INSTRUCTION_SIZE; } } diff --git a/src/cpu/cpu.hh b/src/cpu/cpu.hh index c329417..83af397 100644 --- a/src/cpu/cpu.hh +++ b/src/cpu/cpu.hh @@ -13,40 +13,32 @@ class Cpu { void step(); private: - static constexpr size_t GPR_FIQ_BANKED_FIRST = 8; - static constexpr size_t GPR_FIQ_BANKED_COUNT = 7; + static constexpr size_t GPR_COUNT = 16; - static constexpr size_t GPR_SVC_BANKED_FIRST = 13; - static constexpr size_t GPR_SVC_BANKED_COUNT = 2; + static constexpr size_t GPR_FIQ_FIRST = 8; + static constexpr size_t GPR_SVC_FIRST = 13; + static constexpr size_t GPR_ABT_FIRST = 13; + static constexpr size_t GPR_IRQ_FIRST = 13; + static constexpr size_t GPR_UND_FIRST = 13; + static constexpr size_t GPR_SYS_USR_FIRST = 8; - static constexpr size_t GPR_ABT_BANKED_FIRST = 13; - static constexpr size_t GPR_ABT_BANKED_COUNT = 2; - - static constexpr size_t GPR_IRQ_BANKED_FIRST = 13; - static constexpr size_t GPR_IRQ_BANKED_COUNT = 2; - - static constexpr size_t GPR_UND_BANKED_FIRST = 13; - static constexpr size_t GPR_UND_BANKED_COUNT = 2; - - static constexpr size_t GPR_SYS_USR_BANKED_FIRST = 8; - static constexpr size_t GPR_SYS_USR_BANKED_COUNT = 7; - - static constexpr size_t GPR_VISIBLE_COUNT = 16; - - uint32_t gpr[GPR_VISIBLE_COUNT]; // general purpose registers - Psr cpsr; // current program status register - Psr spsr; // status program status register std::shared_ptr bus; + std::array gpr; // general purpose registers + + Psr cpsr; // current program status register + Psr spsr; // status program status register + + uint32_t& pc = gpr[15]; struct { - uint32_t fiq[GPR_FIQ_BANKED_COUNT]; - uint32_t svc[GPR_SVC_BANKED_COUNT]; - uint32_t abt[GPR_ABT_BANKED_COUNT]; - uint32_t irq[GPR_IRQ_BANKED_COUNT]; - uint32_t und[GPR_UND_BANKED_COUNT]; + std::array fiq; + std::array svc; + std::array abt; + std::array irq; + std::array und; // visible registers before the mode switch - uint32_t old[GPR_SYS_USR_BANKED_COUNT]; + std::array old; } gpr_banked; // banked general purpose registers struct { @@ -57,6 +49,6 @@ class Cpu { Psr und; } spsr_banked; // banked saved program status registers - void chg_mode(Mode from, Mode to); - std::string exec_arm(uint32_t insn); + void chg_mode(const Mode to); + std::string exec_arm(const uint32_t insn); }; diff --git a/src/cpu/instruction.cc b/src/cpu/instruction.cc index 261c94b..b93d331 100644 --- a/src/cpu/instruction.cc +++ b/src/cpu/instruction.cc @@ -5,25 +5,27 @@ #include using namespace logger; +using std::array; +using stringv = std::string_view; std::string -Cpu::exec_arm(uint32_t insn) { +Cpu::exec_arm(const uint32_t insn) { Condition cond = static_cast(get_bit_range(insn, 28, 31)); std::string disassembled; - auto pc_error = [](uint8_t r, const char* syn) { + auto pc_error = [](uint8_t r, stringv syn) { if (r == 15) log_error("Using PC (R15) as operand in {}", syn); }; - auto pc_undefined = [](uint8_t r, const char* syn) { + auto pc_undefined = [](uint8_t r, stringv syn) { if (r == 15) log_warn("Using PC (R15) as operand in {}", syn); }; // Branch and exhcange if ((insn & 0x0FFFFFF0) == 0x012FFF10) { - static constexpr char syn[] = "BX"; + static constexpr stringv syn = "BX"; uint8_t rn = insn & 0b1111; @@ -38,16 +40,16 @@ Cpu::exec_arm(uint32_t insn) { cpsr.set_state(state); // copy to PC - gpr[15] = gpr[rn]; + pc = gpr[rn]; // ignore [1:0] bits for arm and 0 bit for thumb - rst_nth_bit(gpr[15], 0); + rst_nth_bit(pc, 0); if (state == State::Arm) - rst_nth_bit(gpr[15], 1); + rst_nth_bit(pc, 1); } // Branch } else if ((insn & 0x0E000000) == 0x0A000000) { - static constexpr char syn[] = "B"; + static constexpr stringv syn = "B"; bool link = get_nth_bit(insn, 24); uint32_t offset = get_bit_range(insn, 0, 23); @@ -63,14 +65,14 @@ Cpu::exec_arm(uint32_t insn) { offset |= 0xFC000000; if (link) - gpr[14] = gpr[15] - ARM_INSTRUCTION_SIZE; + gpr[14] = pc - ARM_INSTRUCTION_SIZE; - gpr[15] += offset; + pc += offset - ARM_INSTRUCTION_SIZE; } // Multiply } else if ((insn & 0x0FC000F0) == 0x00000090) { - static constexpr char syn[2][4] = { "MUL", "MLA" }; + static constexpr array syn = { "MUL", "MLA" }; uint8_t rm = get_bit_range(insn, 0, 3); uint8_t rs = get_bit_range(insn, 8, 11); @@ -117,8 +119,9 @@ Cpu::exec_arm(uint32_t insn) { } // Multiply long } else if ((insn & 0x0F8000F0) == 0x00800090) { - static constexpr char syn[2][2][6] = { { "SMULL", "SMLAL" }, - { "UMULL", "UMLAL" } }; + static constexpr array, 2> syn = { + { { "SMULL", "SMLAL" }, { "UMULL", "UMLAL" } } + }; uint8_t rm = get_bit_range(insn, 0, 3); uint8_t rs = get_bit_range(insn, 8, 11); @@ -157,7 +160,7 @@ Cpu::exec_arm(uint32_t insn) { gpr[rdhi] = get_bit_range(eval, 32, 63); } else { - int64_t eval = static_cast(gpr[rm]) * + int64_t eval = static_cast(gpr[rm]) * static_cast(gpr[rs]) + (a ? static_cast(gpr[rdhi]) << 32 | static_cast(gpr[rdlo]) @@ -178,7 +181,7 @@ Cpu::exec_arm(uint32_t insn) { // Single data swap } else if ((insn & 0x0FB00FF0) == 0x01000090) { - static constexpr char syn[] = "SWP"; + static constexpr stringv syn = "SWP"; uint8_t rm = get_bit_range(insn, 0, 3); uint8_t rd = get_bit_range(insn, 12, 15); @@ -206,32 +209,32 @@ Cpu::exec_arm(uint32_t insn) { // TODO: create abstraction to reuse for block data and single data // transfer } else if ((insn & 0x0E000090) == 0x00000090) { - static constexpr char syn[2][4] = { "STR", "LDR" }; + static constexpr array syn_ = { "STR", "LDR" }; - uint8_t rm = get_bit_range(insn, 0, 3); - uint8_t h = get_nth_bit(insn, 5); - uint8_t s = get_nth_bit(insn, 6); - uint8_t rd = get_bit_range(insn, 12, 15); - uint8_t rn = get_bit_range(insn, 16, 19); - bool l = get_nth_bit(insn, 20); - bool w = get_nth_bit(insn, 21); - bool imm = get_nth_bit(insn, 22); - bool u = get_nth_bit(insn, 23); - bool p = get_nth_bit(insn, 24); - uint32_t offset; + uint8_t rm = get_bit_range(insn, 0, 3); + uint8_t h = get_nth_bit(insn, 5); + uint8_t s = get_nth_bit(insn, 6); + uint8_t rd = get_bit_range(insn, 12, 15); + uint8_t rn = get_bit_range(insn, 16, 19); + bool l = get_nth_bit(insn, 20); + bool w = get_nth_bit(insn, 21); + bool imm = get_nth_bit(insn, 22); + bool u = get_nth_bit(insn, 23); + bool p = get_nth_bit(insn, 24); + uint32_t offset = 0; + + std::string syn = + fmt::format("{}{}{}", syn_[l], (s ? "S" : ""), (h ? 'H' : 'B')); if (!p && w) - log_error("Write-back enabled with post-indexing in {}", syn[l]); + log_error("Write-back enabled with post-indexing in {}", syn); if (s && !l) - log_error("Signed data found in {}", syn[l]); + log_error("Signed data found in {}", syn); if (w) - pc_error(rn, syn[l]); - pc_error(rm, syn[l]); - - if (rd == 15 && !l && s && h) - ; + pc_error(rn, syn); + pc_error(rm, syn); { offset = (imm ? get_bit_range(insn, 8, 11) << 4 | rm : gpr[rm]); @@ -241,8 +244,8 @@ Cpu::exec_arm(uint32_t insn) { (imm ? offset : rm)); disassembled = fmt::format( - "{}{}{}{} R{:d}{}", - syn[l], + "{}{}{}{} R{:d},{}", + syn_[l], cond, (s ? "S" : ""), (h ? 'H' : 'B'), @@ -254,7 +257,10 @@ Cpu::exec_arm(uint32_t insn) { } if (cpsr.condition(cond)) { - uint32_t address = (u ? gpr[rn] + offset : gpr[rn] - offset); + uint32_t address = gpr[rn]; + + if (p) + address += (u ? offset : -offset); // load if (l) { @@ -287,7 +293,92 @@ Cpu::exec_arm(uint32_t insn) { bus->write_halfword(address, gpr[rd]); } } + + if (!p) + address += (u ? offset : -offset); + + if (!p || w) + gpr[rn] = address; } + + // Software Interrupt + // What to do here? + } else if ((insn & 0x0F000000) == 0x0F000000) { + static constexpr stringv syn = "SWI"; + + if (cpsr.condition(cond)) { + chg_mode(Mode::Supervisor); + pc = 0x08; + spsr = cpsr; + } + + disassembled = fmt::format("{}{} 0", syn, cond); + + // Coprocessor data transfer + } else if ((insn & 0x0E000000) == 0x0C000000) { + static constexpr array syn = { "STC", "LDC" }; + + [[maybe_unused]] uint8_t offset = get_bit_range(insn, 0, 7); + uint8_t cpn = get_bit_range(insn, 8, 11); + uint8_t crd = get_bit_range(insn, 12, 15); + [[maybe_unused]] uint8_t rn = get_bit_range(insn, 16, 19); + bool l = get_nth_bit(insn, 20); + [[maybe_unused]] bool w = get_nth_bit(insn, 21); + bool n = get_nth_bit(insn, 22); + [[maybe_unused]] bool u = get_nth_bit(insn, 23); + [[maybe_unused]] bool p = get_nth_bit(insn, 24); + + disassembled = fmt::format( + "{}{}{} p{},c{},{}", syn[l], cond, (n ? "L" : ""), cpn, crd, "a."); + + log_error("Unimplemented instruction: {}", syn[l]); + + // Coprocessor data operation + } else if ((insn & 0x0F000010) == 0x0E000000) { + static constexpr stringv syn = "CDP"; + + uint8_t crm = get_bit_range(insn, 0, 4); + uint8_t cp = get_bit_range(insn, 5, 7); + uint8_t cpn = get_bit_range(insn, 8, 11); + uint8_t crd = get_bit_range(insn, 12, 15); + uint8_t crn = get_bit_range(insn, 16, 19); + uint8_t cp_opc = get_bit_range(insn, 20, 23); + + disassembled = fmt::format("{}{} p{},{},c{},c{},c{},{}", + syn, + cond, + cpn, + cp_opc, + crd, + crn, + crm, + cp); + + log_error("Unimplemented instruction: {}", syn); + + // Coprocessor register transfer + } else if ((insn & 0x0F000010) == 0x0E000010) { + static constexpr array syn = { "MCR", "MRC" }; + + uint8_t crm = get_bit_range(insn, 0, 4); + uint8_t cp = get_bit_range(insn, 5, 7); + uint8_t cpn = get_bit_range(insn, 8, 11); + uint8_t rd = get_bit_range(insn, 12, 15); + uint8_t crn = get_bit_range(insn, 16, 19); + bool l = get_nth_bit(insn, 20); + uint8_t cp_opc = get_bit_range(insn, 21, 23); + + disassembled = fmt::format("{}{} p{},{},c{},c{},c{},{}", + syn[l], + cond, + cpn, + cp_opc, + rd, + crn, + crm, + cp); + + log_error("Unimplemented instruction: {}", syn[l]); } return disassembled; diff --git a/src/cpu/psr.cc b/src/cpu/psr.cc index c34df55..5128baf 100644 --- a/src/cpu/psr.cc +++ b/src/cpu/psr.cc @@ -2,9 +2,8 @@ #include "util/bits.hh" #include "util/log.hh" -Psr::Psr(uint32_t raw) { - psr = raw & PSR_CLEAR_RESERVED; -} +Psr::Psr(uint32_t raw) + : psr(raw & PSR_CLEAR_RESERVED) {} Mode Psr::mode() const { diff --git a/src/cpu/utility.cc b/src/cpu/utility.cc index 25c9861..9c17af9 100644 --- a/src/cpu/utility.cc +++ b/src/cpu/utility.cc @@ -32,3 +32,23 @@ operator<<(std::ostream& os, const Condition cond) { return os; } + +std::ostream& +operator<<(std::ostream& os, const ShiftType shift_type) { + +#define CASE(type) \ + case ShiftType::type: \ + os << #type; \ + break; + + switch (shift_type) { + CASE(LSL) + CASE(LSR) + CASE(ASR) + CASE(ROR) + } + +#undef CASE + + return os; +} diff --git a/src/cpu/utility.hh b/src/cpu/utility.hh index a790ebd..dcee945 100644 --- a/src/cpu/utility.hh +++ b/src/cpu/utility.hh @@ -40,6 +40,12 @@ enum class Condition { AL = 0b1110 }; +// https://fmt.dev/dev/api.html#std-ostream-support +std::ostream& +operator<<(std::ostream& os, const Condition cond); +template<> +struct fmt::formatter : ostream_formatter {}; + enum class OpCode { AND = 0b0000, EOR = 0b0001, @@ -68,6 +74,6 @@ enum class ShiftType { // https://fmt.dev/dev/api.html#std-ostream-support std::ostream& -operator<<(std::ostream& os, const Condition cond); +operator<<(std::ostream& os, const ShiftType cond); template<> -struct fmt::formatter : ostream_formatter {}; +struct fmt::formatter : ostream_formatter {}; diff --git a/src/header.hh b/src/header.hh index 11aae03..4e454d3 100644 --- a/src/header.hh +++ b/src/header.hh @@ -1,6 +1,7 @@ #pragma once #include +#include #include typedef struct { @@ -33,9 +34,9 @@ typedef struct { }; uint32_t entrypoint; - char title[12]; + std::string title; + std::string title_code; UniqueCode unique_code; - char title_code[2]; I18n i18n; uint8_t version; BootMode multiboot; diff --git a/src/memory.cc b/src/memory.cc index c1edcd2..e1e8a5f 100644 --- a/src/memory.cc +++ b/src/memory.cc @@ -10,14 +10,14 @@ using namespace logger; Memory::Memory(std::array&& bios, std::vector&& rom) noexcept : bios(std::move(bios)) - , board_wram(0) - , chip_wram(0) - , palette_ram(0) - , vram(0) - , oam_obj_attr(0) + , board_wram({ 0 }) + , chip_wram({ 0 }) + , palette_ram({ 0 }) + , vram({ 0 }) + , oam_obj_attr({ 0 }) , rom(std::move(rom)) { - std::string bios_hash = crypto::sha256(bios.data(), bios.size()); - static constexpr char expected_hash[] = + std::string bios_hash = crypto::sha256(this->bios); + static constexpr std::string_view expected_hash = "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570"; if (bios_hash != expected_hash) { @@ -137,7 +137,7 @@ Memory::parse_header() { log_info("HEADER: BIOS debugger bits not set to 0"); // game info - std::copy(&rom[0xA0], &rom[0xA0 + 12], header.title); + header.title = std::string(&rom[0xA0], &rom[0xA0 + 12]); switch (rom[0xAC]) { case 'A': @@ -172,8 +172,7 @@ Memory::parse_header() { log_error("HEADER: invalid unique code: {}", rom[0xAC]); } - header.title_code[0] = rom[0xAD]; - header.title_code[1] = rom[0xAE]; + header.title_code = std::string(&rom[0xAD], &rom[0xAE]); switch (rom[0xAF]) { case 'J': diff --git a/src/memory.hh b/src/memory.hh index 98120c8..9262a68 100644 --- a/src/memory.hh +++ b/src/memory.hh @@ -29,7 +29,7 @@ class Memory { #define DECL_MEMORY(name, ident, start, end) \ MEMORY_REGION(name, start, end) \ - uint8_t ident[name##_END - name##_START + 1]; + std::array ident; MEMORY_REGION(BIOS, 0x00000000, 0x00003FFF) std::array bios; diff --git a/src/meson.build b/src/meson.build index 28c6153..7381d51 100644 --- a/src/meson.build +++ b/src/meson.build @@ -3,7 +3,6 @@ lib_sources = files( 'bus.cc' ) -subdir('util') subdir('cpu') fmt = dependency('fmt', version : '>=10.1.0') diff --git a/src/util/log.hh b/src/util/log.hh index 3e7e270..8ecd504 100644 --- a/src/util/log.hh +++ b/src/util/log.hh @@ -3,54 +3,55 @@ #include #include -namespace logger { -inline std::ostream& stream = std::clog; +using fmt::print; +using std::clog; +namespace logger { namespace ansi { -static constexpr char RED[] = "\033[31m"; -static constexpr char YELLOW[] = "\033[33m"; -static constexpr char MAGENTA[] = "\033[35m"; -static constexpr char WHITE[] = "\033[37m"; -static constexpr char BOLD[] = "\033[1m"; -static constexpr char RESET[] = "\033[0m"; +static constexpr std::string_view RED = "\033[31m"; +static constexpr std::string_view YELLOW = "\033[33m"; +static constexpr std::string_view MAGENTA = "\033[35m"; +static constexpr std::string_view WHITE = "\033[37m"; +static constexpr std::string_view BOLD = "\033[1m"; +static constexpr std::string_view RESET = "\033[0m"; } template inline void log_raw(const fmt::format_string& fmt, Args&&... args) { - fmt::println(stream, fmt, std::forward(args)...); + fmt::println(clog, fmt, std::forward(args)...); } template inline void log_debug(const fmt::format_string& fmt, Args&&... args) { - fmt::print(stream, "{}{}[DEBUG] ", ansi::MAGENTA, ansi::BOLD); + print(clog, "{}{}[DEBUG] ", ansi::MAGENTA, ansi::BOLD); log_raw(fmt, std::forward(args)...); - fmt::print(stream, ansi::RESET); + print(clog, ansi::RESET); } template inline void log_info(const fmt::format_string& fmt, Args&&... args) { - fmt::print(stream, "{}[INFO] ", ansi::WHITE); + print(clog, "{}[INFO] ", ansi::WHITE); log_raw(fmt, std::forward(args)...); - fmt::print(stream, ansi::RESET); + print(clog, ansi::RESET); } template inline void log_warn(const fmt::format_string& fmt, Args&&... args) { - fmt::print(stream, "{}[WARN] ", ansi::YELLOW); + print(clog, "{}[WARN] ", ansi::YELLOW); log_raw(fmt, std::forward(args)...); - fmt::print(stream, ansi::RESET); + print(clog, ansi::RESET); } template inline void log_error(const fmt::format_string& fmt, Args&&... args) { - fmt::print(stream, "{}{}[ERROR] ", ansi::RED, ansi::BOLD); + print(clog, "{}{}[ERROR] ", ansi::RED, ansi::BOLD); log_raw(fmt, std::forward(args)...); - fmt::print(stream, ansi::RESET); + print(clog, ansi::RESET); } } diff --git a/src/util/meson.build b/src/util/meson.build deleted file mode 100644 index 41c0f08..0000000 --- a/src/util/meson.build +++ /dev/null @@ -1,3 +0,0 @@ -lib_sources += files( - 'utils.cc' -) \ No newline at end of file diff --git a/src/util/utils.cc b/src/util/utils.cc deleted file mode 100644 index cf6731c..0000000 --- a/src/util/utils.cc +++ /dev/null @@ -1,113 +0,0 @@ -#include "utils.hh" -#include -#include -#include -#include - -namespace crypto { - -using std::rotr; - -std::string -sha256(const uint8_t* data, const size_t size) { - // Assuming 1 byte = 8 bits - std::stringstream string; - size_t k = 512 - (size * 8 + 65) % 512; - size_t L = size + (65 + k) / 8; - size_t i, j; - bool c = 0; - - static constexpr uint32_t K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, - 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, - 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, - 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, - 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, - 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - }; - - uint32_t h[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; - - for (i = 0; i < L; i += 64) { - size_t n = (size > i ? size - i : 0); - uint32_t h0[8]; - uint32_t w[64] = { 0 }; - - if (n == 64) - c = 1; - - if (n >= 64) { - for (j = 0; j < 16; j++) { - w[j] = data[i + j * 4] << 24 | data[i + j * 4 + 1] << 16 | - data[i + j * 4 + 2] << 8 | data[i + j * 4 + 3]; - } - } else { - uint8_t cur[64] = { 0 }; - - if (n) { - std::copy(data + i, data + size, cur); - cur[n] = 0x80; - } else if (c) { - cur[n] = 0x80; - } - - if (n < 54) { - for (j = 56; j < 64; j++) { - cur[j] = (size * 8 >> ((63 - j) * 8)) & 0xFF; - } - } - - for (j = 0; j < 16; j++) { - w[j] = cur[j * 4] << 24 | cur[j * 4 + 1] << 16 | - cur[j * 4 + 2] << 8 | cur[j * 4 + 3]; - } - } - - for (j = 16; j < 64; j++) { - uint32_t s0 = - rotr(w[j - 15], 7) ^ rotr(w[j - 15], 18) ^ (w[j - 15] >> 3); - uint32_t s1 = - rotr(w[j - 2], 17) ^ rotr(w[j - 2], 19) ^ (w[j - 2] >> 10); - - w[j] = w[j - 16] + w[j - 7] + s0 + s1; - } - - std::copy(h, h + 8, h0); - - for (j = 0; j < 64; j++) { - uint32_t s1 = rotr(h0[4], 6) ^ rotr(h0[4], 11) ^ rotr(h0[4], 25); - uint32_t ch = (h0[4] & h0[5]) ^ (~h0[4] & h0[6]); - uint32_t t1 = h0[7] + s1 + ch + K[j] + w[j]; - uint32_t s0 = rotr(h0[0], 2) ^ rotr(h0[0], 13) ^ rotr(h0[0], 22); - uint32_t maj = (h0[0] & h0[1]) ^ (h0[0] & h0[2]) ^ (h0[1] & h0[2]); - uint32_t t2 = s0 + maj; - - h0[7] = h0[6]; - h0[6] = h0[5]; - h0[5] = h0[4]; - h0[4] = h0[3] + t1; - h0[3] = h0[2]; - h0[2] = h0[1]; - h0[1] = h0[0]; - h0[0] = t1 + t2; - } - - for (j = 0; j < 8; j++) - h[j] += h0[j]; - } - - string << std::hex << std::setfill('0'); - - for (j = 0; j < 8; j++) - for (i = 0; i < 4; i++) - string << std::setw(2) << ((h[j] >> (24 - i * 8)) & 0xFF); - - return string.str(); -} -} diff --git a/src/util/utils.hh b/src/util/utils.hh index 4731768..60819e9 100644 --- a/src/util/utils.hh +++ b/src/util/utils.hh @@ -1,10 +1,121 @@ #pragma once +#include +#include +#include +#include +#include #include // Why I wrote this myself? I do not know // I will off myself 😹😹😹😹 namespace crypto { + +using std::rotr; + +template std::string -sha256(const uint8_t* data, const size_t size); +sha256(std::array& data) { + // Assuming 1 byte = 8 bits + std::string string; + size_t k = 512 - (N * 8 + 65) % 512; + size_t L = N + (65 + k) / 8; + size_t i = 0, j = 0; + bool c = 0; + + static constexpr std::array K = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + + std::array h = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, + 0xa54ff53a, 0x510e527f, 0x9b05688c, + 0x1f83d9ab, 0x5be0cd19 }; + + for (i = 0; i < L; i += 64) { + size_t n = (N > i ? N - i : 0); + + std::array h0 = { 0 }; + std::array w = { 0 }; + + if (n == 64) + c = 1; + + if (n >= 64) { + for (j = 0; j < 16; j++) { + w[j] = data[i + j * 4] << 24 | data[i + j * 4 + 1] << 16 | + data[i + j * 4 + 2] << 8 | data[i + j * 4 + 3]; + } + } else { + std::array cur = { 0 }; + + if (n) { + std::copy(data.begin() + i, data.begin() + N, cur.begin()); + cur[n] = 0x80; + } else if (c) { + cur[n] = 0x80; + } + + if (n < 54) { + for (j = 56; j < 64; j++) { + cur[j] = (N * 8 >> ((63 - j) * 8)) & 0xFF; + } + } + + for (j = 0; j < 16; j++) { + w[j] = cur[j * 4] << 24 | cur[j * 4 + 1] << 16 | + cur[j * 4 + 2] << 8 | cur[j * 4 + 3]; + } + } + + for (j = 16; j < 64; j++) { + uint32_t s0 = + rotr(w[j - 15], 7) ^ rotr(w[j - 15], 18) ^ (w[j - 15] >> 3); + uint32_t s1 = + rotr(w[j - 2], 17) ^ rotr(w[j - 2], 19) ^ (w[j - 2] >> 10); + + w[j] = w[j - 16] + w[j - 7] + s0 + s1; + } + + std::copy(h.begin(), h.end(), h0.begin()); + + for (j = 0; j < 64; j++) { + uint32_t s1 = rotr(h0[4], 6) ^ rotr(h0[4], 11) ^ rotr(h0[4], 25); + uint32_t ch = (h0[4] & h0[5]) ^ (~h0[4] & h0[6]); + uint32_t t1 = h0[7] + s1 + ch + K[j] + w[j]; + uint32_t s0 = rotr(h0[0], 2) ^ rotr(h0[0], 13) ^ rotr(h0[0], 22); + uint32_t maj = (h0[0] & h0[1]) ^ (h0[0] & h0[2]) ^ (h0[1] & h0[2]); + uint32_t t2 = s0 + maj; + + h0[7] = h0[6]; + h0[6] = h0[5]; + h0[5] = h0[4]; + h0[4] = h0[3] + t1; + h0[3] = h0[2]; + h0[2] = h0[1]; + h0[1] = h0[0]; + h0[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) + h[j] += h0[j]; + } + + for (j = 0; j < 8; j++) + for (i = 0; i < 4; i++) + fmt::format_to(std::back_inserter(string), + "{:02x}", + ((h[j] >> (24 - i * 8)) & 0xFF)); + + return string; +} }