more memory work

This commit is contained in:
CocoSimone
2022-05-16 09:29:55 +02:00
parent 072f5bb847
commit bc3a0ff63a
13 changed files with 242 additions and 9 deletions

View File

@@ -2,6 +2,7 @@
#include <cstdint>
#include <bitset>
#include <emmintrin.h>
#include <fmt/format.h>
using u8 = uint8_t;
using u16 = uint16_t;
@@ -19,4 +20,6 @@ using m128 = __m128i;
#define UINT128_MIN 0
#define INT128_MAX ((u128)0x7FFF'FFFF'FFFF'FFFF << 64) | 0xFFFF'FFFF'FFFF'FFFF
#define INT128_MIN (-INT128_MAX - 1LL)
#define KiB * 1024
#define MiB (KiB * 1024)
#define GiB (MiB * 1024)

View File

@@ -3,5 +3,9 @@ project(gb CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_library(gb Core.hpp Core.cpp Cpu.hpp Cpu.cpp Ppu.hpp Ppu.cpp)
target_include_directories(gb PUBLIC .)
find_package(mio REQUIRED)
find_package(fmt REQUIRED)
add_library(gb Core.hpp Core.cpp Cpu.hpp Cpu.cpp Ppu.hpp Ppu.cpp Mem.cpp Mem.hpp mbc.cpp mbc.hpp memory_regions.hpp)
target_include_directories(gb PUBLIC . ..)
target_link_libraries(gb PUBLIC mio::mio fmt::fmt)

View File

@@ -2,4 +2,10 @@
namespace natsukashii::core {
Core::Core() {}
}
void Core::Run() {
while(true) {
cpu.Step(mem);
}
}
}

View File

@@ -1,12 +1,14 @@
#pragma once
#include "Cpu.hpp"
#include "Ppu.hpp"
#include "Mem.hpp"
namespace natsukashii::core {
struct Core {
Core();
void Run();
private:
Mem mem;
Cpu cpu;
// Ppu ppu;
};

View File

@@ -1,6 +1,18 @@
#include <Cpu.hpp>
#include <util.hpp>
namespace natsukashii::core {
Cpu::Cpu() {
}
}
void Cpu::Step(Mem& mem) {
u8 opcode = mem.Consume<u8>(pc);
DecodeAndExecute(opcode);
}
void Cpu::DecodeAndExecute(u8 opcode) {
switch(opcode) {
default: util::panic("Unimplemented opcode %02X", opcode);
}
}
}

View File

@@ -1,11 +1,13 @@
#pragma once
#include "../common.hpp"
#include "Mem.hpp"
namespace natsukashii::core {
#define af regs.AF
#define bc regs.BC
#define de regs.DE
#define hl regs.HL
#define pc regs.PC
#define sp regs.SP
#define a af.A
#define f af.F
@@ -76,11 +78,14 @@ struct Registers {
REGIMPL(u8, B, u8, C);
REGIMPL(u8, C, u8, E);
REGIMPL(u8, D, u8, L);
u16 PC = 0, SP = 0;
};
struct Cpu {
Cpu();
void Step(Mem&);
private:
void DecodeAndExecute(u8);
Registers regs;
};
}

81
src/core/gb/Mem.cpp Normal file
View File

@@ -0,0 +1,81 @@
#include <Mem.hpp>
#include <util.hpp>
#include <memory_regions.hpp>
#include <fstream>
namespace natsukashii::core {
template <class T>
T ReadCart(const std::unique_ptr<Cartridge>& cart, u16 addr) {
if constexpr(sizeof(T) == 1) return cart->Read8(addr);
else if constexpr(sizeof(T) == 2) return cart->Read16(addr);
else if constexpr(sizeof(T) == 4) return cart->Read32(addr);
}
template <class T>
void WriteCart(const std::unique_ptr<Cartridge>& cart, u16 addr, T val) {
if constexpr(sizeof(T) == 1) cart->Write8(addr, val);
else if constexpr(sizeof(T) == 2) cart->Write16(addr, val);
else if constexpr(sizeof(T) == 4) cart->Write32(addr, val);
}
void Mem::LoadROM(const std::string& filename) {
std::ifstream file(filename, std::ios::binary);
file.unsetf(std::ios::skipws);
if(!file.is_open()) {
util::panic("Unable to open {}!", filename);
}
file.seekg(std::ios::end);
auto size = file.tellg();
file.seekg(std::ios::beg);
std::vector<u8> rom;
rom.reserve(size);
rom.insert(rom.begin(),
std::istream_iterator<u8>(file),
std::istream_iterator<u8>());
file.close();
cart = std::make_unique<NoMBC>(rom);
}
template <typename T>
T Mem::Read(u16 addr) {
switch(addr) {
case ROM_RNG00: return io.BootROMMapped() ? bootrom[addr] : ReadCart<T>(cart, addr);
case ROM_RNGNN: return ReadCart<T>(cart, addr);
default: util::panic("[READ] Unimplemented addr: {:04X}", addr);
}
return 0;
}
template u8 Mem::Read<u8>(u16);
template u16 Mem::Read<u16>(u16);
template u32 Mem::Read<u32>(u16);
template <typename T>
void Mem::Write(u16 addr, T val) {
switch(addr) {
case ROM_RNG00: case ROM_RNGNN: WriteCart<T>(cart, addr, val);
default: util::panic("[WRITE] Unimplemented addr: {:04X}", addr);
}
}
template void Mem::Write<u8>(u16, u8);
template void Mem::Write<u16>(u16, u16);
template void Mem::Write<u32>(u16, u32);
template <typename T>
T Mem::Consume(u16& pc) {
T result = Read<T>(pc);
pc += sizeof(T);
return result;
}
template u8 Mem::Consume<u8>(u16&);
template u16 Mem::Consume<u16>(u16&);
template u32 Mem::Consume<u32>(u16&);
}

30
src/core/gb/Mem.hpp Normal file
View File

@@ -0,0 +1,30 @@
#pragma once
#include <common.hpp>
#include <memory>
#include <mio/mmap.hpp>
#include <vector>
#include <memory_regions.hpp>
#include <mbc.hpp>
namespace natsukashii::core {
struct IO {
[[nodiscard]] bool BootROMMapped() const { return ff50 != 1; }
private:
u8 ff50 = 0;
};
struct Mem {
Mem() = default;
void LoadROM(const std::string& filename);
template <typename T>
T Read(u16 addr);
template <typename T>
void Write(u16 addr, T val);
template <typename T>
T Consume(u16& pc);
private:
std::unique_ptr<Cartridge> cart;
IO io{};
u8 bootrom[BOOTROM_SIZE]{};
};
}

24
src/core/gb/mbc.cpp Normal file
View File

@@ -0,0 +1,24 @@
#include <mbc.hpp>
#include <utility>
#include <util.hpp>
namespace natsukashii::core {
NoMBC::NoMBC(std::vector<u8> rom) : data(std::move(rom)) {}
u8 NoMBC::Read8(u16 addr) {
return data[addr];
}
void NoMBC::Write8(u16 addr, u8 val) {
util::panic("Writing to a NoMBC cartridge is not allowed!");
}
u16 NoMBC::Read16(u16 addr) {
return ((u16)Read8(addr) << 8) | Read8(addr + 1);
}
void NoMBC::Write16(u16 addr, u16 val) {
Write8(addr, val >> 8);
Write8(addr + 1, val & 0xff);
}
}

23
src/core/gb/mbc.hpp Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
#include <common.hpp>
#include <memory_regions.hpp>
#include <vector>
namespace natsukashii::core {
struct Cartridge {
virtual u8 Read8(u16 addr);
virtual u16 Read16(u16 addr);
virtual void Write8(u16 addr, u8 val);
virtual void Write16(u16 addr, u16 val);
};
struct NoMBC : public Cartridge {
explicit NoMBC(std::vector<u8> rom);
u8 Read8(u16 addr) override;
void Write8(u16 addr, u8 val) override;
u16 Read16(u16 addr) override;
void Write16(u16 addr, u16 val) override;
private:
std::vector<u8> data{};
};
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include <common.hpp>
#define BOOTROM_SIZE 512
#define ROM_STR00 0x0000
#define ROM_END00 ROM_STR00 + 16 KiB - 1
#define ROM_STRNN ROM_END00 + 1
#define ROM_ENDNN ROM_STRNN + 16 KiB - 1
#define ROM_RNG00 ROM_STR00 ... ROM_END00
#define ROM_RNGNN ROM_STRNN ... ROM_ENDNN
#define VRAM_START ROM_ENDNN + 1
#define VRAM_END VRAM_START + 8 KiB - 1
#define VRAM_RANGE VRAM_START ... VRAM_END
#define EXTRAM_START VRAM_END + 1
#define EXTRAM_END EXTRAM_START + 8 KiB - 1
#define EXTRAM_RANGE EXTRAM_START ... EXTRAM_END
#define WRAM_STR00 EXTRAM_END + 1
#define WRAM_END00 WRAM_STR00 + 4 KiB - 1
#define WRAM_STRNN WRAM_END00 + 1
#define WRAM_ENDNN WRAM_STRNN + 4 KiB - 1
#define WRAM_RNG00 WRAM_STR00 ... WRAM_END00
#define WRAM_RNGNN WRAM_STRNN ... WRAM_ENDNN
#define OAM_START WRAM_ENDNN + 1
#define OAM_END OAM_START + 0x9F
#define OAM_RANGE OAM_START ... OAM_END
#define UNUSABLE_START OAM_END + 1
#define UNUSABLE_END UNUSABLE_START + 0x5F
#define UNUSABLE_RANGE UNUSABLE_START ... UNUSABLE_END
#define IO_START UNUSABLE_END + 1
#define IO_END IO_START + 0x7F
#define IO_RANGE IO_START ... IO_END
#define HRAM_START IO_END + 1
#define HRAM_END HRAM_START + 0x7E
#define HRAM_RANGE HRAM_START ... HRAM_END

View File

@@ -4,6 +4,12 @@
#include <cassert>
namespace natsukashii::util {
template <typename ...Args>
constexpr void panic(const std::string& fmt, Args... args) {
fmt::print(fmt, args...);
exit(-1);
}
template <u8 start, u8 end>
using BitSliceType =
typename std::conditional<(end - start) <= 7, u8,
@@ -29,4 +35,5 @@ T BitSlice(const T& num, int start, int end) {
auto correctedEnd = end == (sizeof(T) * 8) - 1 ? end : end + 1;
return (num >> start) & ((1 << correctedEnd) - 1);
}
}

View File

@@ -16,9 +16,11 @@ App::App() {
void App::Run() {
while(!quit) {
SDL_Event e;
SDL_PollEvent(&e);
quit = e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_CLOSE && e.window.windowID == id;
gb.Run();
SDL_Event event;
SDL_PollEvent(&event);
quit = event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == id;
}
}
}