diff --git a/external/lekkit/sha256.cc b/external/lekkit/sha256.c similarity index 100% rename from external/lekkit/sha256.cc rename to external/lekkit/sha256.c diff --git a/linux/makefile b/linux/makefile index 0510386..f6550f9 100644 --- a/linux/makefile +++ b/linux/makefile @@ -1,11 +1,12 @@ APP_NAME = Kiwi8 -# Use VERSION if set, otherwise fall back to GITHUB_REF_NAME, then default to unknown +# Use VERSION if set, otherwise fall back to GITHUB_REF_NAME, then default to develop VERSION ?= $(GITHUB_REF_NAME) ifeq ($(VERSION),) VERSION = develop endif +# Use SUB_VERSION if set, otherwise fall back to GITHUB_SHA, then default to unknown SUB_VERSION ?= $(GITHUB_SHA) ifeq ($(SUB_VERSION),) SUB_VERSION = unknown @@ -13,9 +14,30 @@ endif APP_EXE = $(APP_NAME) -CC = g++ -CFLAGS = -std=c++11 -Wall -MMD -MP -DAPP_NAME='"$(APP_NAME)"' -DVERSION='"$(VERSION)"' -DSUB_VERSION='"$(SUB_VERSION)"' -LFLAGS = -Wl,-rpath,'$$ORIGIN' +CC = gcc +CXX = g++ +CFLAGS = -std=gnu11 +CPPFLAGS = -Wall \ + -MMD \ + -MP \ + -DAPP_NAME='"$(APP_NAME)"' \ + -DVERSION='"$(VERSION)"' \ + -DSUB_VERSION='"$(SUB_VERSION)"' + +CXXFLAGS = -std=gnu++11 + +INCLUDE_DIRS = -I../external/sdl/build/include/ \ + -I../external/imgui/ \ + -I../external/stb/ \ + -I../external/lekkit/ + +LDFLAGS = -L../external/sdl/build/lib \ + -lSDL2-2.0 \ + -lGL \ + -lm \ + -ldl \ + -lpthread \ + -Wl,-rpath,'$$ORIGIN' # Use pkg-config to get GTK3 and audio backend flags GTK3_CFLAGS = $(shell pkg-config --cflags gtk+-3.0) @@ -31,12 +53,9 @@ PIPEWIRE_LIBS = $(shell pkg-config --libs libpipewire-0.3) JACK_CFLAGS = $(shell pkg-config --cflags jack) JACK_LIBS = $(shell pkg-config --libs jack) -CFLAGS += $(GTK3_CFLAGS) $(ALSA_CFLAGS) $(PULSE_CFLAGS) $(PIPEWIRE_CFLAGS) $(JACK_CFLAGS) +CPPFLAGS += $(GTK3_CFLAGS) $(ALSA_CFLAGS) $(PULSE_CFLAGS) $(PIPEWIRE_CFLAGS) $(JACK_CFLAGS) +LDFLAGS += $(GTK3_LIBS) $(ALSA_LIBS) $(PULSE_LIBS) $(PIPEWIRE_LIBS) $(JACK_LIBS) -INCS = -I../external/sdl/build/include/ -I../external/imgui/ -I../external/stb/ -I../external/lekkit/ -LIBS = -L../external/sdl/build/lib -lSDL2-2.0 -lGL $(GTK3_LIBS) $(ALSA_LIBS) $(PULSE_LIBS) $(PIPEWIRE_LIBS) $(JACK_LIBS) $(ESD_LIBS) $(SNDIO_LIBS) -lm -ldl -lpthread - -# SDL dependency files SDL_LIB = ../external/sdl/build/lib/libSDL2-2.0.so.0 # Generated headers @@ -44,19 +63,21 @@ LICENSE_HEADER = ../shared/license.h BOOTROM_HEADER = ../shared/bootrom.h BOOTROM_SOURCE = ../roms/Kiwi8_logo_2.ch8 -# Source files -CORE_SRCS = ../shared/audio.cc ../shared/chip8.cc ../shared/display.cc ../shared/gui.cc \ - ../shared/input.cc ../shared/main.cc \ - ../shared/toast.cc ../shared/open_file_dialog.cc ../shared/profiles.cc -IMGUI_SRCS = ../external/imgui/imgui.cpp ../external/imgui/imgui_draw.cpp ../external/imgui/imgui_impl_sdl.cpp -LINUX_SRCS = src/file_dialog.cc -SHA256_SRC = ../external/lekkit/sha256.cc - -# Object files (convert source paths to .o in current directory) -OBJS = $(notdir $(CORE_SRCS:.cc=.o)) \ - $(notdir $(IMGUI_SRCS:.cpp=.o)) \ - $(notdir $(LINUX_SRCS:.cc=.o)) \ - $(notdir $(SHA256_SRC:.cc=.o)) +OBJS = audio.o \ + chip8.o \ + display.o \ + gui.o \ + input.o \ + main.o \ + toast.o \ + open_file_dialog.o \ + profiles.o \ + imgui.o \ + imgui_draw.o \ + imgui_impl_sdl.o \ + sha256.o \ + file_dialog.o + DEPS = $(OBJS:.o=.d) PROFILES_INI = ../shared/profiles.ini @@ -66,7 +87,7 @@ PROFILES_INI = ../shared/profiles.ini .DEFAULT_GOAL := all -all: debug/profiles.ini debug/$(APP_EXE) release/profiles. release/$(APP_EXE) +all: debug/profiles.ini debug/$(APP_EXE) release/profiles.ini release/$(APP_EXE) # Build SDL (force rebuild with: make sdl) sdl: @@ -86,16 +107,19 @@ $(BOOTROM_HEADER): $(BOOTROM_SOURCE) # Pattern rules for incremental compilation %.o: src/%.cc - $(CC) $(CFLAGS) $(INCS) -c $< -o $@ + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ %.o: ../external/imgui/%.cpp - $(CC) $(CFLAGS) $(INCS) -c $< -o $@ + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ + +%.o: ../external/lekkit/%.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ -%.o: ../external/lekkit/%.cc - $(CC) $(CFLAGS) $(INCS) -c $< -o $@ +%.o: ../shared/%.c $(LICENSE_HEADER) $(BOOTROM_HEADER) + $(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ %.o: ../shared/%.cc $(LICENSE_HEADER) $(BOOTROM_HEADER) - $(CC) $(CFLAGS) $(INCS) -c $< -o $@ + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ debug/profiles.ini: $(PROFILES_INI) mkdir -p debug @@ -109,13 +133,13 @@ release/profiles.ini: $(PROFILES_INI) debug/$(APP_EXE): $(SDL_LIB) $(OBJS) mkdir -p debug cp $(SDL_LIB) debug/libSDL2-2.0.so.0 - $(CC) $(CFLAGS) -g $(INCS) $(LIBDIRS) $(OBJS) -o $@ $(LIBS) $(LFLAGS) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -g $(INCLUDE_DIRS) $(OBJS) -o $@ $(LDFLAGS) # release executable release/$(APP_EXE): $(SDL_LIB) $(OBJS) mkdir -p release cp $(SDL_LIB) release/libSDL2-2.0.so.0 - $(CC) $(CFLAGS) $(INCS) $(LIBDIRS) $(OBJS) -o $@ $(LIBS) $(LFLAGS) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) $(OBJS) -o $@ $(LDFLAGS) run-debug: debug/$(APP_EXE) ./debug/$(APP_EXE) diff --git a/macos/makefile b/macos/makefile index ecc2745..d3bb845 100644 --- a/macos/makefile +++ b/macos/makefile @@ -1,11 +1,12 @@ APP_NAME = Kiwi8 -# Use VERSION if set, otherwise fall back to GITHUB_REF_NAME, then default to unknown +# Use VERSION if set, otherwise fall back to GITHUB_REF_NAME, then default to develop VERSION ?= $(GITHUB_REF_NAME) ifeq ($(VERSION),) VERSION = develop endif +# Use SUB_VERSION if set, otherwise fall back to GITHUB_SHA, then default to unknown SUB_VERSION ?= $(GITHUB_SHA) ifeq ($(SUB_VERSION),) SUB_VERSION = unknown @@ -15,13 +16,27 @@ APP_MANIFEST = src/Info.plist APP_BUNDLE = $(APP_NAME).app APP_EXE = $(APP_NAME) -CC = clang++ -CFLAGS = -std=c++11 -Wall -mmacosx-version-min=11.0 -MMD -MP -DAPP_NAME='"$(APP_NAME)"' -DVERSION='"$(VERSION)"' -DSUB_VERSION='"$(SUB_VERSION)"' -LFLAGS = -mmacosx-version-min=11.0 -INCS = -I../external/sdl/build/include/ -I../external/imgui/ -I../external/stb/ -I../external/lekkit/ -LIBS = -L../external/sdl/build/lib/ -lSDL2-2.0.0 -framework Cocoa -framework OpenGL +CC = clang +CXX = clang++ +CFLAGS = -std=c11 +CPPFLAGS = -Wall \ + -mmacosx-version-min=11.0 \ + -MMD -MP -DAPP_NAME='"$(APP_NAME)"' \ + -DVERSION='"$(VERSION)"' \ + -DSUB_VERSION='"$(SUB_VERSION)"' + +CXXFLAGS = -std=c++11 +INCLUDE_DIRS = -I../external/sdl/build/include/ \ + -I../external/imgui/ \ + -I../external/stb/ \ + -I../external/lekkit/ + +LDFLAGS = -mmacosx-version-min=11.0 \ + -L../external/sdl/build/lib/ \ + -lSDL2-2.0.0 \ + -framework Cocoa \ + -framework OpenGL -# SDL dependency files SDL_LIB = ../external/sdl/build/lib/libSDL2-2.0.0.dylib # Generated headers @@ -29,19 +44,21 @@ LICENSE_HEADER = ../shared/license.h BOOTROM_HEADER = ../shared/bootrom.h BOOTROM_SOURCE = ../roms/Kiwi8_logo_2.ch8 -# Source files -CORE_SRCS = ../shared/audio.cc ../shared/chip8.cc ../shared/display.cc ../shared/gui.cc \ - ../shared/input.cc ../shared/main.cc \ - ../shared/toast.cc ../shared/open_file_dialog.cc ../shared/profiles.cc -IMGUI_SRCS = ../external/imgui/imgui.cpp ../external/imgui/imgui_draw.cpp ../external/imgui/imgui_impl_sdl.cpp -SHA256_SRC = ../external/lekkit/sha256.cc -MACOS_SRCS = src/file_dialog.mm - -# Object files (convert source paths to .o in current directory) -OBJS = $(notdir $(CORE_SRCS:.cc=.o)) \ - $(notdir $(IMGUI_SRCS:.cpp=.o)) \ - $(notdir $(MACOS_SRCS:.mm=.o)) \ - $(notdir $(SHA256_SRC:.cc=.o)) +OBJS = audio.o \ + chip8.o \ + display.o \ + gui.o \ + input.o \ + main.o \ + toast.o \ + open_file_dialog.o \ + profiles.o \ + imgui.o \ + imgui_draw.o \ + imgui_impl_sdl.o \ + sha256.o \ + file_dialog.o + DEPS = $(OBJS:.o=.d) PROFILES_INI = ../shared/profiles.ini @@ -75,16 +92,19 @@ $(APP_MANIFEST): $(APP_MANIFEST).in # Pattern rules for incremental compilation %.o: src/%.mm - $(CC) $(CFLAGS) $(INCS) -c $< -o $@ + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ %.o: ../external/imgui/%.cpp - $(CC) $(CFLAGS) $(INCS) -c $< -o $@ + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ + +%.o: ../external/lekkit/%.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ -%.o: ../external/lekkit/%.cc - $(CC) $(CFLAGS) $(INCS) -c $< -o $@ +%.o: ../shared/%.c $(LICENSE_HEADER) $(BOOTROM_HEADER) + $(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ %.o: ../shared/%.cc $(LICENSE_HEADER) $(BOOTROM_HEADER) - $(CC) $(CFLAGS) $(INCS) -c $< -o $@ + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) -c $< -o $@ debug/profiles.ini: $(PROFILES_INI) mkdir -p debug @@ -98,7 +118,7 @@ release/$(APP_BUNDLE)/Contents/Resources/profiles.ini: $(PROFILES_INI) debug/$(APP_EXE): $(SDL_LIB) $(OBJS) mkdir -p debug cp $(SDL_LIB) debug/libSDL2-2.0.0.dylib - $(CC) $(CFLAGS) -g $(LIBS) $(INCS) $(OBJS) -o $@ $(LFLAGS) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -g $(INCLUDE_DIRS) $(OBJS) -o $@ $(LDFLAGS) # Set the dylib's install name to be relative to the bundle install_name_tool -id @executable_path/libSDL2-2.0.0.dylib debug/libSDL2-2.0.0.dylib @@ -109,7 +129,7 @@ debug/$(APP_EXE): $(SDL_LIB) $(OBJS) # release executable (inside .app bundle) release/$(APP_BUNDLE)/Contents/MacOS/$(APP_EXE): $(SDL_LIB) $(OBJS) mkdir -p release/$(APP_BUNDLE)/Contents/MacOS - $(CC) $(CFLAGS) $(LIBS) $(INCS) $(OBJS) -o $@ $(LFLAGS) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) $(OBJS) -o $@ $(LDFLAGS) # Fix executable's reference to SDL (from @rpath to bundle-relative path) install_name_tool -change @rpath/libSDL2-2.0.0.dylib @executable_path/../Frameworks/libSDL2-2.0.0.dylib release/$(APP_BUNDLE)/Contents/MacOS/$(APP_EXE) diff --git a/shared/audio.cc b/shared/audio.c similarity index 100% rename from shared/audio.cc rename to shared/audio.c diff --git a/shared/audio.h b/shared/audio.h index 78088a0..00a7166 100644 --- a/shared/audio.h +++ b/shared/audio.h @@ -1,9 +1,17 @@ #ifndef AUDIO_H #define AUDIO_H +#ifdef __cplusplus +extern "C" { +#endif + #include #include +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + #define TAU (2.0 * M_PI) #define AMPLITUDE 28000 // Max amplitude for signed 16-bit #define SAMPLE_RATE 48000 @@ -25,4 +33,8 @@ extern struct audio audio; void audio_destroy(void); int audio_init(void); +#ifdef __cplusplus +} +#endif + #endif // AUDIO_H diff --git a/shared/chip8.cc b/shared/chip8.c similarity index 99% rename from shared/chip8.cc rename to shared/chip8.c index 98a1bb5..76af933 100644 --- a/shared/chip8.cc +++ b/shared/chip8.c @@ -92,7 +92,7 @@ int chip8_init( /* load fontset */ for(int i = 0; i < FONTS_SIZE; ++i) { - chip8.memory[i] = chip8.chip8_fontset[i]; + chip8.memory[i] = chip8_fontset[i]; } /* Initialize ROM profile database */ @@ -222,7 +222,7 @@ void chip8_soft_reset() { /* load fontset */ for(int i = 0; i < FONTS_SIZE; ++i) { - chip8.memory[i] = chip8.chip8_fontset[i]; + chip8.memory[i] = chip8_fontset[i]; } /* copy the entire rom to memory starting from 0x200 */ diff --git a/shared/chip8.h b/shared/chip8.h index b1414e3..d6e438d 100644 --- a/shared/chip8.h +++ b/shared/chip8.h @@ -1,9 +1,14 @@ #ifndef CHIP8_H #define CHIP8_H +#ifdef __cplusplus +extern "C" { +#endif + #include "bootrom.h" // Generated at build time from roms/Kiwi8_logo_2.ch8 #include "quirks.h" #include +#include #define MEM_SIZE 4096 #define NUM_REGISTERS 16 @@ -15,6 +20,24 @@ #define MAX_CYCLES_PER_STEP 50 #define TICKS 60 /* hz - Timer count down rate */ +static const unsigned char chip8_fontset[FONTS_SIZE] = { + 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 + 0x20, 0x60, 0x20, 0x20, 0x70, // 1 + 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 + 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3 + 0x90, 0x90, 0xF0, 0x10, 0x10, // 4 + 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5 + 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6 + 0xF0, 0x10, 0x20, 0x40, 0x40, // 7 + 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8 + 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9 + 0xF0, 0x90, 0xF0, 0x90, 0x90, // A + 0x20, 0x60, 0x20, 0x20, 0x70, // B + 0xF0, 0x80, 0xF0, 0x80, 0xF0, // C + 0xF0, 0x80, 0xF0, 0x80, 0x80, // D + 0xF0, 0x90, 0x90, 0xF0, 0x90 // F + }; + struct chip8 { /* number of cycles per step */ int cycles; @@ -63,23 +86,7 @@ struct chip8 { /* 1-bit encoded screen pixels (64x32) */ unsigned char **vram; - const unsigned char chip8_fontset[FONTS_SIZE] = { - 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 - 0x20, 0x60, 0x20, 0x20, 0x70, // 1 - 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 - 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3 - 0x90, 0x90, 0xF0, 0x10, 0x10, // 4 - 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5 - 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6 - 0xF0, 0x10, 0x20, 0x40, 0x40, // 7 - 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8 - 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9 - 0xF0, 0x90, 0xF0, 0x90, 0x90, // A - 0x20, 0x60, 0x20, 0x20, 0x70, // B - 0xF0, 0x80, 0xF0, 0x80, 0xF0, // C - 0xF0, 0x80, 0xF0, 0x80, 0x80, // D - 0xF0, 0x90, 0x90, 0xF0, 0x90 // F - }; + }; /* Global chip8 instance */ @@ -138,4 +145,8 @@ void execFX55(void); void execFX65(void); void execUnknown(void); +#ifdef __cplusplus +} #endif + +#endif // CHIP8_H diff --git a/shared/display.cc b/shared/display.c similarity index 100% rename from shared/display.cc rename to shared/display.c diff --git a/shared/display.h b/shared/display.h index 3f0e04c..e57e8d8 100644 --- a/shared/display.h +++ b/shared/display.h @@ -1,8 +1,13 @@ #ifndef DISPLAY_H #define DISPLAY_H +#ifdef __cplusplus +extern "C" { +#endif + #include #include +#include #define WIDTH 64 #define HEIGHT 32 @@ -51,4 +56,8 @@ void display_toggle_vsync(void); void display_raise_window(void); void display_render_frame(unsigned char **frame); +#ifdef __cplusplus +} +#endif + #endif diff --git a/shared/gui.cc b/shared/gui.cc index 098b6df..635e322 100644 --- a/shared/gui.cc +++ b/shared/gui.cc @@ -1,5 +1,4 @@ #include "gui.h" -#include "chip8.h" #include "display.h" #include "imgui.h" #include "imgui_impl_sdl.h" diff --git a/shared/gui.h b/shared/gui.h index 15c8cc1..b3619c7 100644 --- a/shared/gui.h +++ b/shared/gui.h @@ -1,7 +1,13 @@ #ifndef GUI_H #define GUI_H +#ifdef __cplusplus +extern "C" { +#endif + #include +#include +#include "chip8.h" #define MENU_HEIGHT 38 @@ -34,4 +40,8 @@ void gui_process_events(SDL_Event *event); void gui_new_frame(void); void gui_render(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/shared/input.cc b/shared/input.c similarity index 95% rename from shared/input.cc rename to shared/input.c index 7951ea4..9684c06 100644 --- a/shared/input.cc +++ b/shared/input.c @@ -60,8 +60,8 @@ static int input_process_events(void) { if (input.state[SDL_SCANCODE_RALT]) gui.show_fps_flag = !gui.show_fps_flag; /* slow/raise emulation speed */ - if (input.state[SDL_SCANCODE_PAGEDOWN]) (chip8.cycles -1 < MIN_CYCLES_PER_STEP ) ? chip8.cycles = MIN_CYCLES_PER_STEP : chip8.cycles -= 1; - if (input.state[SDL_SCANCODE_PAGEUP]) (chip8.cycles +1 > MAX_CYCLES_PER_STEP ) ? chip8.cycles = MAX_CYCLES_PER_STEP : chip8.cycles += 1; + if (input.state[SDL_SCANCODE_PAGEDOWN]) (chip8.cycles -1 < MIN_CYCLES_PER_STEP ) ? (chip8.cycles = MIN_CYCLES_PER_STEP) : (chip8.cycles -= 1); + if (input.state[SDL_SCANCODE_PAGEUP]) (chip8.cycles +1 > MAX_CYCLES_PER_STEP ) ? (chip8.cycles = MAX_CYCLES_PER_STEP) : (chip8.cycles += 1); } /* window events */ diff --git a/shared/input.h b/shared/input.h index 9aeb87b..f635f96 100644 --- a/shared/input.h +++ b/shared/input.h @@ -1,6 +1,11 @@ #ifndef INPUT_H #define INPUT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include #include #define NUM_KEYS 16 @@ -32,4 +37,8 @@ extern struct input input; void input_reset(void); int input_poll(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/shared/main.cc b/shared/main.cc index ae89475..0ecbad5 100644 --- a/shared/main.cc +++ b/shared/main.cc @@ -2,6 +2,7 @@ #include "usage.h" #include #include +#include int main(int argc, char **argv){ diff --git a/shared/opcodes.h b/shared/opcodes.h index 7cb1318..e10c1d7 100644 --- a/shared/opcodes.h +++ b/shared/opcodes.h @@ -2,6 +2,10 @@ #ifndef OPCODES_H #define OPCODES_H +#ifdef __cplusplus +extern "C" { +#endif + #include "chip8.h" #include "display.h" /* for WIDTH and HEIGHT */ #include "input.h" @@ -103,7 +107,7 @@ inline void exec8XY4() { carry, and to 0 when there isn't */ unsigned short sum; sum = chip8.V[OP_Y] + chip8.V[OP_X]; - (sum > 0xFF) ? chip8.V[0xF] = 1 : chip8.V[0xF] = 0; + (sum > 0xFF) ? (chip8.V[0xF] = 1) : (chip8.V[0xF] = 0); /* only the lowest 8 bits are kept */ chip8.V[OP_X] = (unsigned char) sum; @@ -112,7 +116,7 @@ inline void exec8XY4() { inline void exec8XY5() { /* 0x8XY5: VY is subtracted from VX. VF is set to 0 when there's a borrow, and 1 when there isn't */ - (chip8.V[OP_Y] > chip8.V[OP_X]) ? chip8.V[0xF] = 0 : chip8.V[0xF] = 1; + (chip8.V[OP_Y] > chip8.V[OP_X]) ? (chip8.V[0xF] = 0) : (chip8.V[0xF] = 1); chip8.V[OP_X] -= chip8.V[OP_Y]; } @@ -120,19 +124,19 @@ inline void exec8XY6() { /* 0x8XY6: shifts VX right by one. VF is set to the value of the least significant bit of VX before the shift. */ chip8.V[0xF] = chip8.V[OP_X] & 0x01; - chip8.quirks.shift_quirk ? chip8.V[OP_X] >>= 1 : chip8.V[OP_X] = chip8.V[OP_Y] >> 1; + chip8.quirks.shift_quirk ? (chip8.V[OP_X] >>= 1) : (chip8.V[OP_X] = chip8.V[OP_Y] >> 1); } inline void exec8XY7() { /* 0x8XY7: sets VX to VY minus VX. VF is set to 0 when there's a borrow, and 1 when there isn't. */ - (chip8.V[OP_X] > chip8.V[OP_Y]) ? chip8.V[0xF] = 0 : chip8.V[0xF] = 1; + (chip8.V[OP_X] > chip8.V[OP_Y]) ? (chip8.V[0xF] = 0) : (chip8.V[0xF] = 1); chip8.V[OP_X] = chip8.V[OP_Y] - chip8.V[OP_X]; } inline void exec8XYE() { /* 0x8XYE: shifts VX left by one. VF is set to the value of the most significant bit of VX before the shift. */ chip8.V[0xF] = (chip8.V[OP_X] & 0x80) >> 7; - chip8.quirks.shift_quirk ? chip8.V[OP_X] <<= 1 : chip8.V[OP_X] = chip8.V[OP_Y] << 1; + chip8.quirks.shift_quirk ? (chip8.V[OP_X] <<= 1) : (chip8.V[OP_X] = chip8.V[OP_Y] << 1); } inline void exec9XY0() { @@ -273,4 +277,8 @@ inline void execUnknown() { fprintf (stderr, "Unknown opcode: 0x%X\n", chip8.opcode); } +#ifdef __cplusplus +} +#endif + #endif // OPCODES_H diff --git a/shared/open_file_dialog.h b/shared/open_file_dialog.h index 042c722..a0837b3 100644 --- a/shared/open_file_dialog.h +++ b/shared/open_file_dialog.h @@ -1,6 +1,10 @@ #ifndef OPEN_FILE_DIALOG_H #define OPEN_FILE_DIALOG_H +#ifdef __cplusplus +extern "C" { +#endif + #ifdef __APPLE__ #include /* PATH_MAX */ #endif @@ -16,4 +20,8 @@ int open_file_dialog(char *rom_name); +#ifdef __cplusplus +} +#endif + #endif diff --git a/shared/profiles.cc b/shared/profiles.c similarity index 100% rename from shared/profiles.cc rename to shared/profiles.c diff --git a/shared/profiles.h b/shared/profiles.h index c621baa..59d6602 100644 --- a/shared/profiles.h +++ b/shared/profiles.h @@ -1,6 +1,10 @@ #ifndef PROFILES_H #define PROFILES_H +#ifdef __cplusplus +extern "C" { +#endif + #include #include "quirks.h" #include "sha256.h" @@ -25,4 +29,8 @@ const struct profile* profile_lookup(const sha256_hash_t *sha256); * Also adds profile to runtime hashmap immediately */ void profiles_save_current(void); +#ifdef __cplusplus +} +#endif + #endif /* PROFILES_H */ diff --git a/shared/quirks.h b/shared/quirks.h index eb8501d..bd620db 100644 --- a/shared/quirks.h +++ b/shared/quirks.h @@ -1,6 +1,12 @@ #ifndef QUIRKS_H #define QUIRKS_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + /* * X-macro list of all quirk fields. * Format: X(field_name, default_value) @@ -33,4 +39,8 @@ static inline struct quirks quirks_get_defaults(void) { return defaults; } +#ifdef __cplusplus +} +#endif + #endif // QUIRKS_H diff --git a/shared/toast.cc b/shared/toast.c similarity index 100% rename from shared/toast.cc rename to shared/toast.c diff --git a/shared/toast.h b/shared/toast.h index 87241e6..9816700 100644 --- a/shared/toast.h +++ b/shared/toast.h @@ -1,6 +1,10 @@ #ifndef TOAST_H #define TOAST_H +#ifdef __cplusplus +extern "C" { +#endif + /* Toast struct definition */ struct toast { char message[256]; @@ -31,4 +35,8 @@ const struct toast* toast_get_toasts(int *count); int toast_is_active(const struct toast *t); void toast_get_info(const struct toast *t, const char **message, int *type, double *time); +#ifdef __cplusplus +} #endif + +#endif // TOAST_H diff --git a/tools/generate_bootrom_header.py b/tools/generate_bootrom_header.py index 3d717fa..bfa742c 100644 --- a/tools/generate_bootrom_header.py +++ b/tools/generate_bootrom_header.py @@ -9,28 +9,28 @@ def generate_header(rom_file, output_file): """Generate C++ header with ROM data as byte array.""" - + if not os.path.exists(rom_file): print(f"Error: ROM file '{rom_file}' not found", file=sys.stderr) sys.exit(1) - + # Read binary data with open(rom_file, 'rb') as f: rom_data = f.read() - + rom_size = len(rom_data) rom_name = os.path.splitext(os.path.basename(rom_file))[0] - + # Format bytes as hex, 8 per line hex_lines = [] for i in range(0, rom_size, 8): chunk = rom_data[i:i+8] hex_bytes = ', '.join(f'0x{b:02x}' for b in chunk) hex_lines.append(f' {hex_bytes}') - + # Join with commas and newlines formatted_data = ',\n'.join(hex_lines) - + # Generate header content header_content = f"""// Auto-generated file - DO NOT EDIT // Generated from {os.path.basename(rom_file)} @@ -38,27 +38,35 @@ def generate_header(rom_file, output_file): #ifndef BOOTROM_H #define BOOTROM_H +#ifdef __cplusplus +extern "C" {{ +#endif + #define BOOTROM_SIZE {rom_size} /* {os.path.basename(rom_file)} */ -const unsigned char bootrom[BOOTROM_SIZE] = {{ +static const unsigned char bootrom[BOOTROM_SIZE] = {{ {formatted_data} }}; +#ifdef __cplusplus +}} +#endif + #endif // BOOTROM_H """ - + # Write header file with open(output_file, 'w', encoding='utf-8') as f: f.write(header_content) - + print(f"Generated {output_file} from {rom_file} ({rom_size} bytes)") if __name__ == '__main__': if len(sys.argv) != 3: print("Usage: python3 generate_bootrom_header.py ") sys.exit(1) - + rom_file = sys.argv[1] output_file = sys.argv[2] generate_header(rom_file, output_file) diff --git a/tools/generate_license_header.py b/tools/generate_license_header.py index e9ec1ff..d44d7b2 100644 --- a/tools/generate_license_header.py +++ b/tools/generate_license_header.py @@ -59,9 +59,17 @@ def generate_header(license_file, output_file): #ifndef LICENSE_H #define LICENSE_H -const char* LICENSE_TEXT = +#ifdef __cplusplus +extern "C" {{ +#endif + +static const char* LICENSE_TEXT = {chr(10).join(cpp_lines)}; +#ifdef __cplusplus +}} +#endif + #endif // LICENSE_H """ diff --git a/windows/makefile b/windows/makefile index 343d4b2..c262232 100644 --- a/windows/makefile +++ b/windows/makefile @@ -1,6 +1,6 @@ APP_NAME = Kiwi8 -# Use VERSION if set, otherwise fall back to GITHUB_REF_NAME, then default to unknown +# Use VERSION if set, otherwise fall back to GITHUB_REF_NAME, then default to develop !IFNDEF VERSION !IFDEF GITHUB_REF_NAME VERSION = $(GITHUB_REF_NAME) @@ -9,6 +9,7 @@ VERSION = develop !ENDIF !ENDIF +# Use SUB_VERSION if set, otherwise fall back to GITHUB_SHA, then default to unknown !IFNDEF SUB_VERSION !IFDEF GITHUB_SHA SUB_VERSION = $(GITHUB_SHA) @@ -17,66 +18,76 @@ SUB_VERSION = unknown !ENDIF !ENDIF +# Detect architecture from environment (set by MSVC vcvarsall.bat) +# VSCMD_ARG_TGT_ARCH is set to x64, x86, arm64, or arm +!IFNDEF SDL_ARCH +!IFDEF VSCMD_ARG_TGT_ARCH +SDL_ARCH = $(VSCMD_ARG_TGT_ARCH) +!ELSE +SDL_ARCH = x64 +!ENDIF +!ENDIF + APP_EXE = $(APP_NAME).exe APP_PDB = $(APP_NAME).pdb APP_RES = $(APP_NAME).res CC = CL -CFLAGS = /std:c++11 /W4 /MD /nologo /w44996 "/DAPP_NAME=\"$(APP_NAME)\"" "/DVERSION=\"$(VERSION)\"" "/DSUB_VERSION=\"$(SUB_VERSION)\"" - -LFLAGS = /link \ - /LIBPATH:..\external\sdl\build\lib \ - /ENTRY:mainCRTStartup - -INCS = /I..\.shared \ +CXX = CL +CFLAGS = /std:c11 +CPPFLAGS = /W4 \ + /MD \ + /nologo \ + /w44996 \ + "/DAPP_NAME=\"$(APP_NAME)\"" \ + "/DVERSION=\"$(VERSION)\"" \ + "/DSUB_VERSION=\"$(SUB_VERSION)\"" + +CXXFLAGS = /std:c++11 +INCLUDE_DIRS = /I..\shared \ /I..\external\sdl\build\include \ /I..\external\imgui \ /I..\external\stb \ /I..\external\lekkit -LIBS = user32.lib \ +LDFLAGS = /link \ + /LIBPATH:..\external\sdl\build\lib \ + /ENTRY:mainCRTStartup \ + user32.lib \ SDL2.lib \ SDL2main.lib \ opengl32.lib \ Comdlg32.lib \ Shell32.lib -# SDL dependency files +# SDL2.dll is built in the same step as the static libs SDL_LIB = ..\external\sdl\build\lib\SDL2.lib -SDL_DLL = ..\external\sdl\build\bin\SDL2.dll # Generated headers LICENSE_HEADER = ..\shared\license.h BOOTROM_HEADER = ..\shared\bootrom.h BOOTROM_SOURCE = ..\roms\Kiwi8_logo_2.ch8 -# Source files -CORE_SRCS = ..\shared\audio.cc ..\shared\chip8.cc ..\shared\display.cc ..\shared\gui.cc \ - ..\shared\input.cc ..\shared\main.cc \ - ..\shared\toast.cc ..\shared\open_file_dialog.cc ..\shared\profiles.cc -IMGUI_SRCS = ..\external\imgui\imgui.cpp ..\external\imgui\imgui_draw.cpp ..\external\imgui\imgui_impl_sdl.cpp -WINDOWS_SRCS = src\file_dialog.cc -SHA256_SRC = ..\external\lekkit\sha256.cc - -# Object files (all built in current directory) -OBJS = audio.obj chip8.obj display.obj gui.obj imgui_impl_sdl.obj input.obj \ - main.obj toast.obj profiles.obj open_file_dialog.obj imgui.obj imgui_draw.obj \ - file_dialog.obj sha256.obj +OBJS = audio.obj \ + chip8.obj \ + display.obj \ + gui.obj \ + imgui_impl_sdl.obj \ + input.obj \ + main.obj \ + toast.obj \ + profiles.obj \ + open_file_dialog.obj \ + imgui.obj \ + imgui_draw.obj \ + file_dialog.obj \ + sha256.obj PROFILES_INI = ..\shared\profiles.ini # Default target all: debug\profiles.ini debug\$(APP_EXE) release\profiles.ini release\$(APP_EXE) -# Detect architecture from environment (set by MSVC vcvarsall.bat) -# VSCMD_ARG_TGT_ARCH is set to x64, x86, arm64, or arm -!IFNDEF SDL_ARCH -!IFDEF VSCMD_ARG_TGT_ARCH -SDL_ARCH = $(VSCMD_ARG_TGT_ARCH) -!ELSE -SDL_ARCH = x64 -!ENDIF -!ENDIF # Build SDL (force rebuild with: nmake sdl) sdl: @@ -86,9 +97,6 @@ sdl: $(SDL_LIB): powershell -ExecutionPolicy Bypass -File build_sdl.ps1 -ARCH $(SDL_ARCH) -$(SDL_DLL): $(SDL_LIB) - @REM DLL is created by same script that creates LIB - # Generate license header from LICENSE file $(LICENSE_HEADER): ..\LICENSE python3 ..\tools\generate_license_header.py ..\LICENSE $(LICENSE_HEADER) @@ -98,24 +106,27 @@ $(BOOTROM_HEADER): $(BOOTROM_SOURCE) python3 ..\tools\generate_bootrom_header.py $(BOOTROM_SOURCE) $(BOOTROM_HEADER) # Inference rules for incremental compilation -{..\shared}.cc{}.obj: - $(CC) $(CFLAGS) /c $(INCS) $< - {src}.cc{}.obj: - $(CC) $(CFLAGS) /c $(INCS) $< + $(CXX) $(CXXFLAGS) $(CPPFLAGS) /c $(INCLUDE_DIRS) $< {..\external\imgui}.cpp{}.obj: - $(CC) $(CFLAGS) /c $(INCS) $< + $(CXX) $(CXXFLAGS) $(CPPFLAGS) /c $(INCLUDE_DIRS) $< -{..\external\lekkit}.cc{}.obj: - $(CC) $(CFLAGS) /c $(INCS) $< +{..\external\lekkit}.c{}.obj: + $(CC) $(CFLAGS) $(CPPFLAGS) /c $(INCLUDE_DIRS) $< + +{..\shared}.c{}.obj: + $(CC) $(CFLAGS) $(CPPFLAGS) /c $(INCLUDE_DIRS) $< + +{..\shared}.cc{}.obj: + $(CXX) $(CXXFLAGS) $(CPPFLAGS) /c $(INCLUDE_DIRS) $< # Explicit rules for files depending on generated headers gui.obj: ..\shared\gui.cc $(LICENSE_HEADER) - $(CC) $(CFLAGS) /c $(INCS) ..\shared\gui.cc + $(CC) $(CFLAGS) $(CPPFLAGS) /c $(INCLUDE_DIRS) ..\shared\gui.cc -chip8.obj: ..\shared\chip8.cc $(BOOTROM_HEADER) - $(CC) $(CFLAGS) /c $(INCS) ..\shared\chip8.cc +chip8.obj: ..\shared\chip8.c $(BOOTROM_HEADER) + $(CC) $(CFLAGS) $(CPPFLAGS) /c $(INCLUDE_DIRS) ..\shared\chip8.c $(APP_RES): src\Kiwi8.rc resources\Kiwi8.ico RC src\Kiwi8.rc @@ -129,16 +140,16 @@ release\profiles.ini: $(PROFILES_INI) IF NOT EXIST release MKDIR release COPY $(PROFILES_INI) release\profiles.ini -debug\$(APP_EXE): $(SDL_LIB) $(SDL_DLL) $(OBJS) $(APP_RES) - $(CC) $(CFLAGS) /Zi /Fe$(APP_NAME) $(INCS) $(OBJS) $(APP_RES) $(LIBS) $(LFLAGS) /SUBSYSTEM:CONSOLE +debug\$(APP_EXE): $(SDL_LIB) $(OBJS) $(APP_RES) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) /Zi /Fe$(APP_NAME) $(INCLUDE_DIRS) $(OBJS) $(APP_RES) $(LDFLAGS) /SUBSYSTEM:CONSOLE IF NOT EXIST debug MKDIR debug - COPY $(SDL_DLL) debug\SDL2.dll + COPY ..\external\sdl\build\bin\SDL2.dll debug\SDL2.dll MOVE $(APP_EXE) $@ -release\$(APP_EXE): $(SDL_LIB) $(SDL_DLL) $(OBJS) $(APP_RES) - $(CC) $(CFLAGS) /Fe$(APP_NAME) $(INCS) $(OBJS) $(APP_RES) $(LIBS) $(LFLAGS) /SUBSYSTEM:WINDOWS +release\$(APP_EXE): $(SDL_LIB) $(OBJS) $(APP_RES) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) /Fe$(APP_NAME) $(INCLUDE_DIRS) $(OBJS) $(APP_RES) $(LDFLAGS) /SUBSYSTEM:WINDOWS IF NOT EXIST release MKDIR release - COPY $(SDL_DLL) release\SDL2.dll + COPY ..\external\sdl\build\bin\SDL2.dll release\SDL2.dll MOVE $(APP_EXE) $@ run-debug: