Skip to content

Commit

Permalink
Integrate clang-format into CMake
Browse files Browse the repository at this point in the history
This creates one target to reformat code automatically and one target to
check the codes formatting.
Adapted from:
https://github.com/ttroy50/cmake-examples/tree/master/04-static-analysis/clang-format
  • Loading branch information
dariusarnold committed Nov 27, 2022
1 parent 1069c44 commit 3141fdb
Show file tree
Hide file tree
Showing 24 changed files with 794 additions and 712 deletions.
3 changes: 2 additions & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ IndentWidth: '4'
Language: Cpp
MaxEmptyLinesToKeep: '2'
NamespaceIndentation: None
PointerAlignment: Left
PointerAlignment: Left
SortIncludes: false
9 changes: 8 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ set(CMAKE_CXX_STANDARD 20)
include(${CMAKE_BINARY_DIR}/conan_paths.cmake OPTIONAL RESULT_VARIABLE CONAN_PATHS_FOUND)
if (${CONAN_PATHS_FOUND} STREQUAL "NOTFOUND")
message(STATUS "File conan_paths.cmake not found. Maybe conan install was not executed?")
endif()
endif ()
find_package(fmt REQUIRED)
find_package(Catch2 REQUIRED)
find_package(SDL2 REQUIRED)
find_package(imgui REQUIRED)
find_package(OpenGL REQUIRED)
find_package(magic_enum REQUIRED)

# Enable clang-format integration by creating clang-format CMake targets
# Add a custom CMake Modules directory
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules
${CMAKE_MODULE_PATH})
set(CLANG_FORMAT_EXCLUDE_PATTERNS "src/bindings" ${CMAKE_BINARY_DIR})
find_package(ClangFormat)

add_subdirectory(src)
add_subdirectory(tests)
42 changes: 42 additions & 0 deletions cmake/modules/FindClangFormat.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Find Clang format
# The module defines the following variables
#
# ``ClangFormat_FOUND`` True if clang-format executable was found.
# ``ClangFormat_EXECUTABLE`` Path to clang-format executable.
#
# The behaviour of this module is influenced by the following variables
#
# ``CLANG_FORMAT_EXE_NAME`` Name of executable to find (default clang-format).
# ``CLANG_FORMAT_ROOT_DIR`` Path to search for executable name in.
#
if (NOT CLANG_FORMAT_EXE_NAME)
set(CLANG_FORMAT_EXE_NAME clang-format)
endif ()

# if custom path check there first
if (CLANG_FORMAT_ROOT_DIR)
find_program(ClangFormat_EXECUTABLE
NAMES
${CLANG_FORMAT_EXE_NAME}
PATHS
"${CLANG_FORMAT_ROOT_DIR}"
NO_DEFAULT_PATH)
else ()
find_program(ClangFormat_EXECUTABLE NAMES ${CLANG_FORMAT_EXE_NAME})
endif ()

# Print an error message when the executable was not found
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
ClangFormat
DEFAULT_MSG
ClangFormat_EXECUTABLE)

mark_as_advanced(ClangFormat_EXECUTABLE)

if (ClangFormat_FOUND)
# A CMake script to find all source files and setup clang-format targets for them
include(clang-format)
else ()
message(STATUS "clang-format not found. Not setting up format targets")
endif ()
48 changes: 48 additions & 0 deletions cmake/modules/clang-format.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# A CMake script to find all source files and setup clang-format targets for them

# Find all source files
set(CLANG_FORMAT_CXX_FILE_EXTENSIONS ${CLANG_FORMAT_CXX_FILE_EXTENSIONS} *.cpp *.h *.cxx *.hxx *.hpp *.cc *.ipp)
file(GLOB_RECURSE ALL_SOURCE_FILES ${CLANG_FORMAT_CXX_FILE_EXTENSIONS})

# Don't include some common build folders
set(CLANG_FORMAT_EXCLUDE_PATTERNS ${CLANG_FORMAT_EXCLUDE_PATTERNS} "/CMakeFiles/" "cmake")

# get all project files file
foreach (SOURCE_FILE ${ALL_SOURCE_FILES})
foreach (EXCLUDE_PATTERN ${CLANG_FORMAT_EXCLUDE_PATTERNS})
string(FIND ${SOURCE_FILE} ${EXCLUDE_PATTERN} EXCLUDE_FOUND)
if (NOT ${EXCLUDE_FOUND} EQUAL -1)
list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE})
endif ()
endforeach ()
endforeach ()

add_custom_target(clang-format
COMMENT "Running clang-format to change files"
COMMAND ${ClangFormat_EXECUTABLE}
--style=file
-i
${ALL_SOURCE_FILES}
)

add_custom_target(clang-format-check
COMMENT "Checking clang-format changes"
COMMAND ${ClangFormat_EXECUTABLE}
--style=file
--dry-run
--Werror
${ALL_SOURCE_FILES}
)

# Get the path to this file
get_filename_component(_clangcheckpath clang-format.cmake PATH)
# have at least one here by default
set(CHANGED_FILE_EXTENSIONS ".cpp")
foreach (EXTENSION ${CLANG_FORMAT_CXX_FILE_EXTENSIONS})
set(CHANGED_FILE_EXTENSIONS "${CHANGED_FILE_EXTENSIONS},${EXTENSION}")
endforeach ()

set(EXCLUDE_PATTERN_ARGS)
foreach (EXCLUDE_PATTERN ${CLANG_FORMAT_EXCLUDE_PATTERNS})
list(APPEND EXCLUDE_PATTERN_ARGS "--exclude=${EXCLUDE_PATTERN}")
endforeach ()
5 changes: 3 additions & 2 deletions src/game-boy-emulator/addressbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ uint8_t AddressBus::read_byte(uint16_t address) const {
}

void AddressBus::write_byte(uint16_t address, uint8_t value) {
if (memmap::is_in(address, memmap::InternalRamBank0) || memmap::is_in(address, memmap::HighRam)) {
if (memmap::is_in(address, memmap::InternalRamBank0)
|| memmap::is_in(address, memmap::HighRam)) {
m_emulator->get_ram()->write_byte(address, value);
} else if (memmap::is_in(address, memmap::VRam)) {
m_emulator->get_gpu()->write_byte(address, value);
} else if(memmap::is_in(address, memmap::IORegisters)) {
} else if (memmap::is_in(address, memmap::IORegisters)) {
if (m_emulator->is_booting()) {
if (address == 0xFF50) {
m_emulator->signal_boot_ended();
Expand Down
1 change: 1 addition & 0 deletions src/game-boy-emulator/addressbus.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class Emulator;
*/
class AddressBus {
Emulator* m_emulator;

public:
AddressBus(Emulator* emulator);

Expand Down
84 changes: 42 additions & 42 deletions src/game-boy-emulator/bitmanipulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,46 @@

namespace bitmanip {

// TODO This overload is not clearly distinguished by name from set
// TODO position as enum
void set(uint8_t& input, uint8_t position) {
set(input, position, BitValues::Active);
}

void unset(uint8_t& input, uint8_t position) {
set(input, position, BitValues::Inactive);
}

void set(uint8_t& input, uint8_t position, BitValues value) {
input ^= (-as_integral(value) ^ input) & (1U << position);
}
uint8_t get_high_byte(uint16_t x) {
return (x >> constants::BYTE_SIZE) & 0XFF;
}
uint8_t get_low_byte(uint16_t x) {
return x & 0xFF;
}

uint8_t get_low_nibble(uint8_t x) {
return x & 0x0F;
}
uint8_t get_high_nibble(uint8_t x) {
return (x & 0xF0) >> (constants::BYTE_SIZE / 2);
}

uint8_t rotate_left(uint8_t x) {
return (x << 1);
}

uint8_t rotate_left_carry(uint8_t x, bool& carry_flag) {
bool prev_carry_flag = carry_flag;
carry_flag = is_bit_set(x, 7);
x = x << 1;
set(x, 0, prev_carry_flag ? BitValues::Active : BitValues::Inactive);
return x;
}

uint16_t word_from_bytes(uint8_t high_byte, uint8_t low_byte) {
return (high_byte << constants::BYTE_SIZE) + low_byte;
}
// TODO This overload is not clearly distinguished by name from set
// TODO position as enum
void set(uint8_t& input, uint8_t position) {
set(input, position, BitValues::Active);
}

void unset(uint8_t& input, uint8_t position) {
set(input, position, BitValues::Inactive);
}

void set(uint8_t& input, uint8_t position, BitValues value) {
input ^= (-as_integral(value) ^ input) & (1U << position);
}
uint8_t get_high_byte(uint16_t x) {
return (x >> constants::BYTE_SIZE) & 0XFF;
}
uint8_t get_low_byte(uint16_t x) {
return x & 0xFF;
}

uint8_t get_low_nibble(uint8_t x) {
return x & 0x0F;
}
uint8_t get_high_nibble(uint8_t x) {
return (x & 0xF0) >> (constants::BYTE_SIZE / 2);
}

uint8_t rotate_left(uint8_t x) {
return (x << 1);
}

uint8_t rotate_left_carry(uint8_t x, bool& carry_flag) {
bool prev_carry_flag = carry_flag;
carry_flag = is_bit_set(x, 7);
x = x << 1;
set(x, 0, prev_carry_flag ? BitValues::Active : BitValues::Inactive);
return x;
}

uint16_t word_from_bytes(uint8_t high_byte, uint8_t low_byte) {
return (high_byte << constants::BYTE_SIZE) + low_byte;
}
} // namespace bitmanip
82 changes: 41 additions & 41 deletions src/game-boy-emulator/bitmanipulation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,44 @@
#include "fmt/format.h"

namespace bitmanip {
/**
* Set bit at position to value
* @param input Byte to modify
* @param position 0..7 where 0 is the least significant bit
* @param value 0..1
*/
void set(uint8_t& input, uint8_t position, BitValues value);
// Set bit in input at position to 1
void set(uint8_t& input, uint8_t position);
// Set bit in input at position to 0
void unset(uint8_t& input, uint8_t position);

template <typename T>
bool is_bit_set(T input, int position) {
static_assert(std::is_integral_v<T>);
return (input & (1 << position)) > 0;
}

template <typename T>
uint8_t bit_value(T input, int position) {
static_assert(std::is_integral_v<T>);
return (input >> position) & 1;
}

// Get most significant byte
uint8_t get_high_byte(uint16_t x);
// Get least significant byte
uint8_t get_low_byte(uint16_t x);

// Example 0x34 -> 0x04
uint8_t get_low_nibble(uint8_t);
// Exampple 0x34 -> 0x03
uint8_t get_high_nibble(uint8_t);

uint8_t rotate_left(uint8_t x);

uint8_t rotate_left_carry(uint8_t x, bool& carry_flag);

uint16_t word_from_bytes(uint8_t high_byte, uint8_t low_byte);

} // namespace bitmanip
/**
* Set bit at position to value
* @param input Byte to modify
* @param position 0..7 where 0 is the least significant bit
* @param value 0..1
*/
void set(uint8_t& input, uint8_t position, BitValues value);
// Set bit in input at position to 1
void set(uint8_t& input, uint8_t position);
// Set bit in input at position to 0
void unset(uint8_t& input, uint8_t position);

template <typename T>
bool is_bit_set(T input, int position) {
static_assert(std::is_integral_v<T>);
return (input & (1 << position)) > 0;
}

template <typename T>
uint8_t bit_value(T input, int position) {
static_assert(std::is_integral_v<T>);
return (input >> position) & 1;
}

// Get most significant byte
uint8_t get_high_byte(uint16_t x);
// Get least significant byte
uint8_t get_low_byte(uint16_t x);

// Example 0x34 -> 0x04
uint8_t get_low_nibble(uint8_t);
// Exampple 0x34 -> 0x03
uint8_t get_high_nibble(uint8_t);

uint8_t rotate_left(uint8_t x);

uint8_t rotate_left_carry(uint8_t x, bool& carry_flag);

uint16_t word_from_bytes(uint8_t high_byte, uint8_t low_byte);

} // namespace bitmanip
2 changes: 1 addition & 1 deletion src/game-boy-emulator/bootrom.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ class Emulator;
class BootRom {
Emulator* m_emulator;
std::array<uint8_t, 256> m_rom;

public:
BootRom(Emulator* emulator, std::array<uint8_t, 256> rom);

[[nodiscard]] uint8_t read_byte(uint16_t address) const;

};
10 changes: 5 additions & 5 deletions src/game-boy-emulator/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@

namespace constants {

constexpr size_t BOOT_ROM_SIZE = 256;
constexpr size_t BOOT_ROM_SIZE = 256;

constexpr size_t RAM_SIZE = 65536;
constexpr size_t RAM_SIZE = 65536;

// Exemptions from above comment: size in bits
constexpr int NIBBLE_SIZE = 4;
constexpr int BYTE_SIZE = 8;
// Exemptions from above comment: size in bits
constexpr int NIBBLE_SIZE = 4;
constexpr int BYTE_SIZE = 8;

} // namespace constants

Expand Down
12 changes: 8 additions & 4 deletions src/game-boy-emulator/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void Cpu::run() {
}
}

Cpu::Cpu(Emulator* emulator): Cpu(emulator,Verbosity::LEVEL_INFO){}
Cpu::Cpu(Emulator* emulator) : Cpu(emulator, Verbosity::LEVEL_INFO) {}

Cpu::Cpu(Emulator* emulator, Verbosity verbosity_) : m_emulator(emulator), verbosity(verbosity_) {}

Expand Down Expand Up @@ -541,7 +541,9 @@ void Cpu::instructionINCDEC(opcodes::Instruction instruction) {
uint16_t value_original;
// INC and DEC only differ by the operation (+/-). The timings and flags behaviour is the same.
// We can implement both using the same function.
auto operation = instruction.instruction_type == opcodes::InstructionType::INC ? [](int a, int b) {return a + b;} :[](int a, int b) {return a - b;};
auto operation = instruction.instruction_type == opcodes::InstructionType::INC
? [](int a, int b) { return a + b; }
: [](int a, int b) { return a - b; };
if (instruction.interaction_type == opcodes::InteractionType::AddressRegister) {
// Indirect access
auto address = get_register_value(instruction.register_type_destination);
Expand All @@ -564,7 +566,9 @@ void Cpu::instructionINCDEC(opcodes::Instruction instruction) {
auto was_hc = internal::was_half_carry(value_original, 1, operation);
set_half_carry_flag(was_hc);
set_zero_flag(operation(value_original, 1) == 0);
set_subtract_flag(instruction.instruction_type == opcodes::InstructionType::INC ? BitValues::Inactive : BitValues::Active);
set_subtract_flag(instruction.instruction_type == opcodes::InstructionType::INC
? BitValues::Inactive
: BitValues::Active);
}
}

Expand Down Expand Up @@ -608,7 +612,7 @@ void Cpu::instructionPUSH(opcodes::Instruction instruction) {
void Cpu::instructionRL(opcodes::Instruction instruction) {
if (instruction.instruction_type == opcodes::InstructionType::RL) {
bool cf = is_flag_set(flags::carry);
registers.a = bitmanip::rotate_left_carry(registers.a, cf);
registers.a = bitmanip::rotate_left_carry(registers.a, cf);
set_carry_flag(cf);
set_zero_flag(BitValues::Inactive);
set_subtract_flag(BitValues::Inactive);
Expand Down
Loading

0 comments on commit 3141fdb

Please sign in to comment.