refactor: make linter happy

also add a few unused coprocessor instructions

Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
2023-09-14 01:07:41 +05:30
parent 387f3c8f07
commit 3cf5cbd024
19 changed files with 394 additions and 240 deletions

8
.clang-tidy Normal file
View File

@@ -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
'

28
.github/workflows/main.yml vendored Normal file
View File

@@ -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

View File

@@ -8,10 +8,12 @@
#include <memory>
#include <vector>
// NOLINTBEGIN
int
main(int argc, const char* argv[]) {
std::vector<uint8_t> rom;
std::array<uint8_t, Memory::BIOS_SIZE> bios;
std::array<uint8_t, Memory::BIOS_SIZE> bios = { 0 };
auto usage = [argv]() {
std::cerr << "Usage: " << argv[0] << " <file> [-b <bios>]" << std::endl;
@@ -85,3 +87,5 @@ main(int argc, const char* argv[]) {
}
return 0;
}
// NOLINTEND

View File

@@ -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;

View File

@@ -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<Condition> : 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<Condition> : ostream_formatter {};
struct fmt::formatter<ShiftType> : ostream_formatter {};

View File

@@ -7,10 +7,10 @@
using namespace logger;
Cpu::Cpu(Bus& bus)
: gpr(0)
: bus(std::make_shared<Bus>(bus))
, gpr({ 0 })
, cpsr(0)
, spsr(0)
, bus(std::make_shared<Bus>(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;
}
}

View File

@@ -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> bus;
std::array<uint32_t, GPR_COUNT> 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<uint32_t, GPR_COUNT - GPR_FIQ_FIRST - 1> fiq;
std::array<uint32_t, GPR_COUNT - GPR_SVC_FIRST - 1> svc;
std::array<uint32_t, GPR_COUNT - GPR_ABT_FIRST - 1> abt;
std::array<uint32_t, GPR_COUNT - GPR_IRQ_FIRST - 1> irq;
std::array<uint32_t, GPR_COUNT - GPR_UND_FIRST - 1> und;
// visible registers before the mode switch
uint32_t old[GPR_SYS_USR_BANKED_COUNT];
std::array<uint32_t, GPR_COUNT - GPR_SYS_USR_FIRST> 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);
};

View File

@@ -5,25 +5,27 @@
#include <cstdint>
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<Condition>(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<stringv, 2> 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<array<stringv, 2>, 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<uint64_t>(gpr[rm]) *
int64_t eval = static_cast<int64_t>(gpr[rm]) *
static_cast<int64_t>(gpr[rs]) +
(a ? static_cast<int64_t>(gpr[rdhi]) << 32 |
static_cast<int64_t>(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<stringv, 2> 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<stringv, 2> 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<stringv, 2> 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;

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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<Condition> : 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<Condition> : ostream_formatter {};
struct fmt::formatter<ShiftType> : ostream_formatter {};

View File

@@ -1,6 +1,7 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
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;

View File

@@ -10,14 +10,14 @@ using namespace logger;
Memory::Memory(std::array<uint8_t, BIOS_SIZE>&& bios,
std::vector<uint8_t>&& 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':

View File

@@ -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<uint8_t, name##_END - name##_START + 1> ident;
MEMORY_REGION(BIOS, 0x00000000, 0x00003FFF)
std::array<uint8_t, BIOS_SIZE> bios;

View File

@@ -3,7 +3,6 @@ lib_sources = files(
'bus.cc'
)
subdir('util')
subdir('cpu')
fmt = dependency('fmt', version : '>=10.1.0')

View File

@@ -3,54 +3,55 @@
#include <fmt/ostream.h>
#include <iostream>
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<typename... Args>
inline void
log_raw(const fmt::format_string<Args...>& fmt, Args&&... args) {
fmt::println(stream, fmt, std::forward<Args>(args)...);
fmt::println(clog, fmt, std::forward<Args>(args)...);
}
template<typename... Args>
inline void
log_debug(const fmt::format_string<Args...>& fmt, Args&&... args) {
fmt::print(stream, "{}{}[DEBUG] ", ansi::MAGENTA, ansi::BOLD);
print(clog, "{}{}[DEBUG] ", ansi::MAGENTA, ansi::BOLD);
log_raw(fmt, std::forward<Args>(args)...);
fmt::print(stream, ansi::RESET);
print(clog, ansi::RESET);
}
template<typename... Args>
inline void
log_info(const fmt::format_string<Args...>& fmt, Args&&... args) {
fmt::print(stream, "{}[INFO] ", ansi::WHITE);
print(clog, "{}[INFO] ", ansi::WHITE);
log_raw(fmt, std::forward<Args>(args)...);
fmt::print(stream, ansi::RESET);
print(clog, ansi::RESET);
}
template<typename... Args>
inline void
log_warn(const fmt::format_string<Args...>& fmt, Args&&... args) {
fmt::print(stream, "{}[WARN] ", ansi::YELLOW);
print(clog, "{}[WARN] ", ansi::YELLOW);
log_raw(fmt, std::forward<Args>(args)...);
fmt::print(stream, ansi::RESET);
print(clog, ansi::RESET);
}
template<typename... Args>
inline void
log_error(const fmt::format_string<Args...>& fmt, Args&&... args) {
fmt::print(stream, "{}{}[ERROR] ", ansi::RED, ansi::BOLD);
print(clog, "{}{}[ERROR] ", ansi::RED, ansi::BOLD);
log_raw(fmt, std::forward<Args>(args)...);
fmt::print(stream, ansi::RESET);
print(clog, ansi::RESET);
}
}

View File

@@ -1,3 +0,0 @@
lib_sources += files(
'utils.cc'
)

View File

@@ -1,113 +0,0 @@
#include "utils.hh"
#include <bit>
#include <iomanip>
#include <sstream>
#include <vector>
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();
}
}

View File

@@ -1,10 +1,121 @@
#pragma once
#include <array>
#include <bit>
#include <fmt/core.h>
#include <iomanip>
#include <sstream>
#include <string>
// Why I wrote this myself? I do not know
// I will off myself 😹😹😹😹
namespace crypto {
using std::rotr;
template<typename std::size_t N>
std::string
sha256(const uint8_t* data, const size_t size);
sha256(std::array<uint8_t, N>& 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<uint32_t, 64> 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<uint32_t, 8> 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<uint32_t, 8> h0 = { 0 };
std::array<uint32_t, 64> 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<uint32_t, 64> 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;
}
}