Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .zed/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@
"label": "GameDaddy: Debug (pokemon-red)",
"command": "./scripts/debug.sh",
},
{
"label": "GameDaddy: Test",
"command": "./scripts/test.sh",
},
]
110 changes: 67 additions & 43 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,81 @@ project(gamedaddy)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Optional quality-of-life
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# ---------------------------
# GoogleTest
# ---------------------------
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip
)
FetchContent_MakeAvailable(googletest)

# ---------------------------
# Core Emulator Library (public since we testing this)
# - CPU
# - Memory
# - Cartridge
# - MBC
# - PPU
# - Sound
# - Interrupts
# ---------------------------
file(GLOB_RECURSE CORE_SRC
src/gameboy/**/*.cpp
src/cartridge/**/*.cpp
)

add_library(gamedaddy_core ${CORE_SRC})

target_include_directories(gamedaddy_core PUBLIC
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/src
)

target_compile_features(gamedaddy_core PUBLIC cxx_std_20)

# ---------------------------
# Main Executable (private)
# - main.cpp
# - platform.cpp
# - sdl_gui.cpp
# - links SDL
# ---------------------------
file(GLOB_RECURSE PLATFORM_SRC
src/_platform/*.cpp
)

add_executable(gamedaddy
main.cpp
platform-layer/platform.cpp
platform-layer/platform.h
platform-layer/display/impl/cli.cpp
platform-layer/display/impl/cli.h
platform-layer/display/impl/sdl_gui.cpp
platform-layer/display/impl/sdl_gui.h
platform-layer/display/display_interface.h

gameboy-hardware/cpu/cpu.cpp
gameboy-hardware/cpu/cpu.h
gameboy-hardware/io/sound/sound.cpp
gameboy-hardware/io/sound/sound.h
gameboy-hardware/io/ppu/ppu.cpp
gameboy-hardware/io/ppu/ppu.h
gameboy-hardware/io/joypad/joypad.cpp
gameboy-hardware/io/joypad/joypad.h
gameboy-hardware/io/instructions/instructions.cpp
gameboy-hardware/io/instructions/instructions.h
gameboy-hardware/interrupts/interrupts.cpp
gameboy-hardware/interrupts/interrupts.h
gameboy-hardware/memory/memory.cpp
gameboy-hardware/memory/memory.h
gameboy-hardware/rom/rom-validation.cpp
gameboy-hardware/rom/rom-validation.h
include/units.h

# If these are unit tests with their own main(), DO NOT list them here.
# test/cpu_test.cpp
# test/ppu_test.cpp
# test/instructions_test.cpp
# test/interrupts_test.cpp
# test/sound_test.cpp
# test/cli_test.cpp
# test/mbc_test.cpp
src/main.cpp
${PLATFORM_SRC}
)

# SDL via imported targets from Homebrew packages
# SDL only belongs to executable, NOT tests
find_package(SDL2 CONFIG REQUIRED)
find_package(SDL2_image CONFIG REQUIRED)
# find_package(SDL2_mixer CONFIG REQUIRED) for audio

target_link_libraries(gamedaddy PRIVATE
SDL2::SDL2
SDL2_image::SDL2_image
#SDL2_mixer::SDL2_mixer
gamedaddy_core
SDL2::SDL2
SDL2_image::SDL2_image
)

# ---------------------------
# Tests (private with gtest)
# ---------------------------
enable_testing()

file(GLOB TEST_SOURCES test/*.cpp)

add_executable(tests ${TEST_SOURCES})

target_link_libraries(tests PRIVATE
gamedaddy_core
gtest_main
)

target_compile_features(gamedaddy PRIVATE cxx_std_20)
include(GoogleTest)
gtest_discover_tests(tests)
3 changes: 0 additions & 3 deletions gameboy-hardware/mbc/mbc.cpp

This file was deleted.

8 changes: 0 additions & 8 deletions gameboy-hardware/mbc/mbc.h

This file was deleted.

34 changes: 34 additions & 0 deletions include/helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include <sstream>

namespace Gameboy {
/*
* Message helper for formatting one arugment.
*
* Examples:
* msg("PC = ", pc);
*/
template <typename T>
static std::string msg(const char* prefix, T value) {
std::ostringstream oss;
oss << prefix << value;
return oss.str();
}

/*
* Message helper that formats one argue in the middle as well as the end.
*
* Examples:
* msg("I am ", 21, " years and ", 3.0/4.0);
* msg("Bank ", bank, " selected: ", romBank);
*/
template <typename A, typename B>
static std::string msg(const char* prefix, A a,
const char* mid, B b) {
std::ostringstream oss;
oss << prefix << a << mid << b;
return oss.str();
}

}
6 changes: 2 additions & 4 deletions include/units.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
// Created by William Kiem Lafond on 2025-09-18.
//

#ifndef UNITS_H
#define UNITS_H
#pragma once

#include <cstddef>

namespace GameBoy::units {

static constexpr std::size_t KiB = 1024;
static constexpr std::size_t MiB = 1024 * KiB;
}

#endif //UNITS_H
4 changes: 4 additions & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -e

./build/debug/tests
File renamed without changes.
File renamed without changes.
9 changes: 4 additions & 5 deletions platform-layer/platform.cpp → src/_platform/platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
#include <SDL_timer.h>
#include <thread>

#include "display/impl/sdl_gui.h"
#include "../gameboy-hardware/memory/memory.h"
#include "../gameboy-hardware/rom/rom-validation.h"
#include "../gameboy/memory/memory.h"
#include "../cartridge/rom/rom-validation.h"

namespace GameBoy {
// TODO: implement the commented parts
Expand Down Expand Up @@ -89,17 +88,17 @@ void Platform::run() {
}
}

// TODO: change this into attach_cartridge_to_
void Platform::load_rom_into_memory(const std::vector<uint8_t>& rom_data) {
memory_->load_rom(rom_data);
}

bool Platform::validate_rom_bytes(const std::vector<uint8_t>& rom_data) {
auto res = GameBoy::validate_rom_file(rom_data);
auto res = Cartridge::validate_rom_file(rom_data);
// INVALID ROM
if (res.ok == false) {
for (std::string& e : res.errors) std::cerr << " - " << e << std::endl;
}
return res.ok;
}
} // namespace GameBoy

File renamed without changes.
7 changes: 7 additions & 0 deletions src/cartridge/cart.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

#include "cart.h"

namespace Cartridge {


}
58 changes: 58 additions & 0 deletions src/cartridge/cart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/// We removed the SGB functionality

#pragma once
#include "mbc/mbc.h"
#include <cstdint>
#include <vector>
#include <unordered_map>

namespace Cartridge {

inline const std::unordered_map<uint8_t, std::string> CARTRIDGE_TYPES = {
{0x00, "ROM ONLY"},
{0x01, "MBC1"},
{0x02, "MBC1+RAM"},
{0x03, "MBC1+RAM+BATTERY"},
{0x05, "MBC2"},
{0x06, "MBC2+BATTERY"},
{0x08, "ROM+RAM"},
{0x09, "ROM+RAM+BATTERY"},
{0x0B, "MMM01"},
{0x0C, "MMM01+RAM"},
{0x0D, "MMM01+RAM+BATTERY"},
{0x0F, "MBC3+TIMER+BATTERY"},
{0x10, "MBC3+TIMER+RAM+BATTERY"},
{0x11, "MBC3"},
{0x12, "MBC3+RAM"},
{0x13, "MBC3+RAM+BATTERY"},
{0x19, "MBC5"},
{0x1A, "MBC5+RAM"},
{0x1B, "MBC5+RAM+BATTERY"},
{0x1C, "MBC5+RUMBLE"},
{0x1D, "MBC5+RUMBLE+RAM"},
{0x1E, "MBC5+RUMBLE+RAM+BATTERY"},
{0x20, "MBC6"},
{0x22, "MBC7+SENSOR+RUMBLE+RAM+BATTERY"},
{0xFC, "POCKET CAMERA"},
{0xFD, "BANDAI TAMA5"},
{0xFE, "HuC3"},
{0xFF, "HuC1+RAM+BATTERY"}
};

class Cart {
private:
uint8_t cart_type_; // 0x0147
uint8_t rom_size_; // 0x0148
uint8_t ram_size_; // 0x0149

std::vector<uint8_t> rom_;
std::vector<uint8_t> ram_;
std::unique_ptr<MBC> mbc_;

public:
Cart();

uint8_t call_read(uint8_t);
uint8_t call_write(uint8_t);
};
}
53 changes: 53 additions & 0 deletions src/cartridge/mbc/mbc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Created by William Lafond on 2025-07-08.
//

#include "mbc.h"

#include <cstddef>
#include <cstdint>
#include <sys/types.h>

namespace Cartridge {

static uint32_t rom_bank_count_from_bytes(std::size_t rom_size) {
// each bank is 16KB
return static_cast<uint32_t>(rom_size / 0x4000);
}

static uint32_t ram_bank_count_bytes(std::size_t ram_size) {
// each RAM bank is 8KB. (except for MBC2, there are 2KB)
if (ram_size == 0) return 0;
if (ram_size <= 0x2000) return 1;
return static_cast<uint32_t>(ram_size / 0x2000);
}

MBC1::MBC1(const std::vector<uint8_t>& rom, std::vector<uint8_t>& ram)
: rom_(rom), ram_(ram)
{
// TODO constructor init functions

}

uint32_t MBC1::clamp_rom_bank_(uint32_t bank) const {
// TODO
return 0;
}

uint32_t MBC1::clamp_ram_bank_(uint32_t bank) const {
// TODO
return 0;
}

void MBC1::write(uint16_t addr, uint8_t value) {
// TODO
return;
}

uint8_t MBC1::read(uint16_t addr) {
// TODO
return 0;
}


}
Loading