This commit is contained in:
CocoSimone
2022-06-10 12:01:09 +02:00
parent e70aa0b072
commit aeded59dab
21 changed files with 252 additions and 165 deletions

61
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
name: build
on: push
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -y build-essential libsdl2-dev libfmt-dev qt5-default git
- name: Build natsukashii
run: |
cmake -B build -DCMAKE_BUILD_TYPE=Release
cd build
make -j$(nproc)
- name: Collect artifacts
run: |
mkdir upload
cp build/bin/qt/natsukashii-qt upload
cp build/bin/sdl/natsukashii-sdl upload
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: natsukashii-linux
path: upload
if-no-files-found: error
build-windows:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- uses: msys2/setup-msys2@v2
with:
install: make git mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-qt5-static mingw-w64-x86_64-fmt
- name: Build natsukashii
run: |
cmake \
-G"Unix Makefiles" \
-B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-s"
cd build
make -j$(nproc)
- name: Collect artifacts
run: |
mkdir upload
cp build/bin/qt/natsukashii-qt upload
cp build/bin/sdl/natsukashii-sdl upload
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: natsukashii-windows
path: upload
if-no-files-found: error

View File

@@ -3,8 +3,15 @@ project(natsukashii CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
add_subdirectory(src/core)
add_subdirectory(src)
add_executable(natsukashii src/main.cpp)
target_include_directories(natsukashii PUBLIC src/frontend/)
target_link_libraries(natsukashii cores frontend)
option(BUILD_SDL "Build the SDL frontend" ON)
option(BUILD_QT "Build the QT frontend" ON)
if(${BUILD_QT})
add_subdirectory(src/frontend/qt ${CMAKE_CURRENT_BINARY_DIR}/bin/qt/)
endif()
if(${BUILD_SDL})
add_subdirectory(src/frontend/sdl ${CMAKE_CURRENT_BINARY_DIR}/bin/sdl/)
endif()

View File

@@ -2,5 +2,6 @@
### _"Joyful nostalgia"_
[![CodeFactor](https://www.codefactor.io/repository/github/cocosimone/natsukashii/badge/master)](https://www.codefactor.io/repository/github/cocosimone/natsukashii/overview/master)
[![build](https://github.com/CocoSimone/natsukashii/actions/workflows/build.yml/badge.svg)](https://github.com/CocoSimone/natsukashii/actions/workflows/build.yml)
Multi-system emulator in its infancy

View File

@@ -5,6 +5,7 @@
// an example on how to get the endian conversion functions on different platforms.
#pragma once
#include <stdint.h>
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
@@ -114,64 +115,17 @@
#endif
// Adapted from Google's CityHash source code:
//
// https://github.com/google/cityhash/blob/8af9b8c2b889d80c22d6bc26ba0df1afb79a30db/src/city.cc#L50
#if defined(_MSC_VER)
#include <stdlib.h>
#define bswap_16(x) _byteswap_ushort(x)
#define bswap_32(x) _byteswap_ulong(x)
#define bswap_64(x) _byteswap_uint64(x)
#elif defined(__APPLE__)
// Mac OS X / Darwin features
#include <libkern/OSByteOrder.h>
#define bswap_16(x) OSSwapInt16(x)
#define bswap_32(x) OSSwapInt32(x)
#define bswap_64(x) OSSwapInt64(x)
#elif defined(__sun) || defined(sun)
#include <sys/byteorder.h>
#define bswap_16(x) BSWAP_16(x)
#define bswap_32(x) BSWAP_32(x)
#define bswap_64(x) BSWAP_64(x)
#elif defined(__FreeBSD__)
#include <sys/endian.h>
#define bswap_16(x) bswap16(x)
#define bswap_32(x) bswap32(x)
#define bswap_64(x) bswap64(x)
#elif defined(__OpenBSD__)
#include <sys/types.h>
#define bswap_16(x) swap16(x)
#define bswap_32(x) swap32(x)
#define bswap_64(x) swap64(x)
#elif defined(__NetBSD__)
#include <sys/types.h>
#include <machine/bswap.h>
#if defined(__BSWAP_RENAME) && !defined(__bswap_32)
#define bswap_16(x) bswap16(x)
#define bswap_32(x) bswap32(x)
#define bswap_64(x) bswap64(x)
#endif
#elif __has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)
#define bswap_16(x) __builtin_bswap16(x)
#define bswap_32(x) __builtin_bswap32(x)
#define bswap_64(x) __builtin_bswap64(x)
#else
#include <byteswap.h>
#endif
#define bswap_16(x) (((x) & 0xFF00u) >> 8) | \
(((x) & 0x00FFu) << 8)
#define bswap_32(x) (((x) & 0xFF000000u) >> 24u) | \
(((x) & 0x00FF0000u) >> 8u) | \
(((x) & 0x0000FF00u) << 8u) | \
(((x) & 0x000000FFu) << 24u)
#define bswap_64(x) (((x) & 0xFF00000000000000u) >> 56u) | \
(((x) & 0x00FF000000000000u) >> 40u) | \
(((x) & 0x0000FF0000000000u) >> 24u) | \
(((x) & 0x000000FF00000000u) >> 8u) | \
(((x) & 0x00000000FF000000u) << 8u) | \
(((x) & 0x0000000000FF0000u) << 24u) | \
(((x) & 0x000000000000FF00u) << 40u) | \
(((x) & 0x00000000000000FFu) << 56u)

View File

@@ -1,15 +0,0 @@
cmake_minimum_required(VERSION 3.20)
add_subdirectory(core)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(FRONTEND "sdl" CACHE INTERNAL "")
if(${FRONTEND} MATCHES "qt")
add_subdirectory(frontend/qt)
elseif(${FRONTEND} MATCHES "sdl")
add_subdirectory(frontend/sdl)
else()
message("Invalid frontend specified, falling back to Qt.")
add_subdirectory(frontend/qt)
endif()

5
src/core/BaseCore.cpp Normal file
View File

@@ -0,0 +1,5 @@
#include <BaseCore.hpp>
namespace natsukashii::core {
void BaseCore::Run() {}
}

View File

@@ -2,6 +2,7 @@
namespace natsukashii::core {
struct BaseCore {
virtual void Run() {}
virtual ~BaseCore() {}
virtual void Run();
};
}

View File

@@ -11,7 +11,7 @@ add_library(cores
Scheduler.cpp
Scheduler.hpp
common.hpp
BaseCore.hpp)
util.hpp)
target_include_directories(cores PRIVATE .)
target_include_directories(cores PUBLIC ../../external)
target_link_libraries(cores PUBLIC gb n64)

View File

@@ -3,10 +3,35 @@ project(gb CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(mio REQUIRED)
find_package(fmt REQUIRED)
find_package(toml11 REQUIRED)
include(FetchContent)
FetchContent_Declare(
mio
GIT_REPOSITORY https://github.com/CocoSimone/mio
GIT_TAG master
)
FetchContent_Declare(
toml11
GIT_REPOSITORY https://github.com/ToruNiina/toml11
GIT_TAG dcfe39a783a94e8d52c885e5883a6fbb21529019
)
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 PRIVATE . ..)
target_link_libraries(gb PUBLIC toml11::toml11 mio::mio fmt::fmt)
FetchContent_MakeAvailable(mio toml11)
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
../BaseCore.cpp
../BaseCore.hpp)
target_include_directories(gb PRIVATE . .. ../../../external)
target_include_directories(gb PUBLIC ${mio_SOURCE_DIR}/include ${toml11_SOURCE_DIR}/include)
target_link_libraries(gb PRIVATE toml11::toml11 mio::mio fmt::fmt)

View File

@@ -5,8 +5,10 @@
#include <BaseCore.hpp>
namespace natsukashii::gb::core {
struct Core : natsukashii::core::BaseCore {
Core(const std::string&);
using namespace natsukashii::core;
struct Core : BaseCore {
~Core() override = default;
explicit Core(const std::string&);
void Run() override;
private:
Mem mem;

View File

@@ -3,15 +3,15 @@
#include <util.hpp>
namespace natsukashii::gb::core {
#define REGIMPL(type1, reg1, type2, reg2) \
struct reg##reg1##reg2 { \
reg##reg1##reg2() {} \
union { \
type1 reg1; \
type2 reg2; \
}; \
u16 raw = 0; \
} reg1##reg2
template <class T1, class T2>
struct Reg {
Reg() : raw(0) {};
union {
T1 hi;
T2 lo;
};
u16 raw = 0;
};
struct RegF {
RegF() : raw(0) {}
@@ -71,20 +71,20 @@ private:
};
struct Registers {
REGIMPL(u8, A, RegF, F);
REGIMPL(u8, B, u8, C);
REGIMPL(u8, D, u8, E);
REGIMPL(u8, H, u8, L);
Reg<u8, RegF> AF;
Reg<u8, u8> BC;
Reg<u8, u8> DE;
Reg<u8, u8> HL;
u16 pc = 0, sp = 0;
u8& a() { return AF.A; }
RegF& f() { return AF.F; }
u8& b() { return BC.B; }
u8& c() { return BC.C; }
u8& d() { return DE.D; }
u8& e() { return DE.E; }
u8& h() { return HL.H; }
u8& l() { return HL.L; }
u8& a() { return AF.hi; }
RegF& f() { return AF.lo; }
u8& b() { return BC.hi; }
u8& c() { return BC.lo; }
u8& d() { return DE.hi; }
u8& e() { return DE.lo; }
u8& h() { return HL.hi; }
u8& l() { return HL.lo; }
u16& af() { return AF.raw; }
u16& bc() { return BC.raw; }
@@ -124,6 +124,7 @@ private:
case 3: return regs.af();
}
}
return 0;
}
template <int group>

View File

@@ -1,10 +1,10 @@
#pragma once
#include <common.hpp>
#include <memory>
#include <mio/mmap.hpp>
#include <vector>
#include "memory_regions.hpp"
#include "mbc.hpp"
#include <mio/mmap.hpp>
#include <memory_regions.hpp>
#include <mbc.hpp>
namespace natsukashii::gb::core {
struct IO {

View File

@@ -3,10 +3,31 @@ project(n64 CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#find_package(mio REQUIRED)
find_package(fmt REQUIRED)
#find_package(toml11 REQUIRED)
include(FetchContent)
FetchContent_Declare(
mio
GIT_REPOSITORY https://github.com/CocoSimone/mio
GIT_TAG master
)
FetchContent_Declare(
toml11
GIT_REPOSITORY https://github.com/ToruNiina/toml11
GIT_TAG dcfe39a783a94e8d52c885e5883a6fbb21529019
)
add_library(n64 Core.hpp Core.cpp Cpu.hpp Cpu.cpp Mem.cpp Mem.hpp memory_regions.hpp)
target_include_directories(n64 PRIVATE . ..)
target_link_libraries(n64 PUBLIC fmt::fmt)
FetchContent_MakeAvailable(mio toml11)
find_package(fmt REQUIRED)
add_library(n64
Core.hpp
Core.cpp
Cpu.hpp
Cpu.cpp
Mem.cpp
Mem.hpp
memory_regions.hpp
../BaseCore.cpp
../BaseCore.hpp)
target_include_directories(n64 PRIVATE . .. ../../../external)
target_include_directories(n64 PUBLIC ${mio_SOURCE_DIR}/include ${toml11_SOURCE_DIR}/include)
target_link_libraries(n64 PRIVATE mio::mio toml11::toml11 fmt::fmt)

View File

@@ -5,8 +5,10 @@
#include <string>
namespace natsukashii::n64::core {
struct Core : natsukashii::core::BaseCore {
Core(const std::string&);
virtual void Run() override;
using namespace natsukashii::core;
struct Core : BaseCore {
~Core() override = default;
explicit Core(const std::string&);
void Run() override;
};
}

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.20)
project(frontend)
project(natsukashii-qt)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -9,8 +9,7 @@ set(CMAKE_AUTOUIC ON)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
add_library(frontend Frontend.hpp Frontend.cpp)
add_executable(natsukashii-qt Frontend.hpp Frontend.cpp main.cpp)
target_compile_definitions(frontend PUBLIC FRONTEND_QT)
target_include_directories(frontend PUBLIC .)
target_link_libraries(frontend PUBLIC Qt5::Widgets)
target_include_directories(natsukashii-qt PRIVATE . ../../core ../../core/gb ../../core/n64 ../../../external)
target_link_libraries(natsukashii-qt PRIVATE cores Qt5::Widgets)

8
src/frontend/qt/main.cpp Normal file
View File

@@ -0,0 +1,8 @@
#include <Frontend.hpp>
#include <util.hpp>
int main(int argc, char* argv[]) {
natsukashii::frontend::App app;
app.Run();
return 0;
}

View File

@@ -1,11 +1,19 @@
cmake_minimum_required(VERSION 3.20)
project(frontend)
project(natsukashii-sdl)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(SDL2 REQUIRED)
add_library(frontend Frontend.cpp Frontend.hpp)
target_compile_definitions(frontend PUBLIC FRONTEND_SDL)
target_include_directories(frontend PUBLIC . ../../core ../../core/gb ../../core/n64)
target_link_libraries(frontend PUBLIC SDL2)
add_executable(natsukashii-sdl Frontend.cpp Frontend.hpp main.cpp)
include(FetchContent)
FetchContent_Declare(
argparse
GIT_REPOSITORY https://github.com/p-ranav/argparse
GIT_TAG 40a3888f151256bba95c45860af381b2b73752e8
)
FetchContent_MakeAvailable(argparse)
target_include_directories(natsukashii-sdl PRIVATE . ../../core ../../core/gb ../../core/n64 ../../../external)
target_link_libraries(natsukashii-sdl PRIVATE cores argparse::argparse SDL2)

View File

@@ -1,30 +1,28 @@
#include <Frontend.hpp>
#include <algorithm>
#include <cctype>
#include <gb/Core.hpp>
#include <n64/Core.hpp>
namespace natsukashii::frontend {
using namespace natsukashii;
App::~App() {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
App::App(const std::string& rom) {
App::App(const std::string& rom, const std::string& selectedCore) {
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
window = SDL_CreateWindow("natukashii", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
id = SDL_GetWindowID(window);
std::string ext{rom.begin() + rom.find_first_of('.') + 1, rom.end()};
std::transform(ext.begin(), ext.end(), ext.begin(), [](unsigned char c){
return std::tolower(c);
});
if(ext == "gb") core = std::make_unique<gb::core::Core>(rom);
else if(ext == "n64") core = std::make_unique<n64::core::Core>(rom);
else util::panic("Unimplemented core!");
if(selectedCore == "gb") {
core = std::make_unique<gb::core::Core>(rom);
} else if(selectedCore == "n64") {
core = std::make_unique<n64::core::Core>(rom);
} else {
util::panic("Unimplemented core!");
}
}
void App::Run() {

View File

@@ -1,4 +1,5 @@
#pragma once
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <BaseCore.hpp>
#include <string>
@@ -9,7 +10,7 @@ namespace natsukashii::frontend {
using namespace natsukashii::core;
struct App {
~App();
App(const std::string&);
App(const std::string&, const std::string&);
void Run();
private:
SDL_Window *window = nullptr;

28
src/frontend/sdl/main.cpp Normal file
View File

@@ -0,0 +1,28 @@
#include <Frontend.hpp>
#include <util.hpp>
#include <argparse/argparse.hpp>
int main(int argc, char* argv[]) {
argparse::ArgumentParser program("natsukashii");
program.add_argument("-c", "--core")
.required()
.help("Select the core");
program.add_argument("rom")
.required()
.help("ROM to load");
try {
program.parse_args(argc, argv);
}
catch (const std::runtime_error& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
natsukashii::frontend::App app(program.get<const std::string&>("rom"), program.get<const std::string&>("--core"));
app.Run();
return 0;
}

View File

@@ -1,20 +0,0 @@
#ifdef FRONTEND_QT
#include <qt/Frontend.hpp>
#elifdef FRONTEND_SDL
#include <sdl/Frontend.hpp>
#endif
#include <util.hpp>
int main(int argc, char* argv[]) {
#ifdef FRONTEND_SDL
if(argc < 2) {
natsukashii::util::panic("Usage: natsukashii [rom]");
}
natsukashii::frontend::App app(argv[1]);
#else
natsukashii::frontend::App app;
#endif
app.Run();
return 0;
}