Skip to content

Commit

Permalink
Make binjnes work on Windows
Browse files Browse the repository at this point in the history
* Add new BINJNES_{CLANG,GCC,MSVC} preprocessor defines
* Remove Linux-only compile flags
* Remove Linux-only linked libraries
* Add platform-specific atomic.h (stdatomic for C is not supported in my
  version of MSVC)
* Fix some MSVC compiler warnings
* Repurpose UNREACHABLE as __builtin_unreachable/__assume(0)
* MSVC doesn't allow you to predeclare an indeterminately sized array
  :-/
* Extend vec library to support all uses needed for emulator.c (e.g.
  don't use vector extensions)
* Fix alignment bug in apu_tick. Previously this code was forcing
  unaligned accesses to make it work. This didn't seem to work on MSVC.
  Now it is always aligned and masks off parts of the calculation that
  are not used
* Remove uses of case range extension
  • Loading branch information
binji committed Aug 16, 2023
1 parent 9e698bf commit 0b95f45
Show file tree
Hide file tree
Showing 10 changed files with 815 additions and 347 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/bin/
/out/
/build/
63 changes: 43 additions & 20 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,34 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)

option(WERROR "Build with warnings as errors" OFF)

add_definitions(
-Wall -Wextra -Wpointer-arith -Wno-unused-parameter -g
-Wno-unused-function -Wno-unused-variable
-Wno-implicit-fallthrough -Wno-unknown-pragmas
)
if (WERROR)
add_definitions(-Werror)
if (UNIX AND NOT APPLE)
set(LINUX TRUE)
endif ()

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_definitions(-DBINJNES_CLANG)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
add_definitions(-DBINJNES_GCC)
endif ()
add_definitions(
-Wall -Wextra -Wpointer-arith -Wno-unused-parameter -g
-Wno-unused-function -Wno-unused-variable
-Wno-implicit-fallthrough -Wno-unknown-pragmas
)
if (WERROR)
add_definitions(-Werror)
endif ()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
add_definitions(
/DBINJNES_MSVC
/D_CRT_SECURE_NO_WARNINGS
/std:c11
/wd4146 # unary minus operator applied to unsigned type
/wd4098 # 'void' function returning a value
)
endif()

function (target_copy_to_bin name)
add_custom_target(${name}-copy-to-bin ALL
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/bin
Expand All @@ -39,11 +58,13 @@ if (NOT EMSCRIPTEN)


# Sokol stuff
set(OpenGL_GL_PREFERENCE GLVND)
find_package(OpenGL)
find_package(X11)
find_package(Threads)
find_package(ALSA)
if (LINUX)
set(OpenGL_GL_PREFERENCE GLVND)
find_package(OpenGL)
find_package(X11)
find_package(Threads)
find_package(ALSA)
endif()

add_executable(binjnes
src/binjnes.c
Expand All @@ -57,14 +78,16 @@ if (NOT EMSCRIPTEN)
)
target_include_directories(binjnes
PUBLIC ${PROJECT_SOURCE_DIR}/third_party)
target_link_libraries(binjnes
OpenGL::GL
${X11_X11_LIB}
${X11_Xi_LIB}
${X11_Xcursor_LIB}
ALSA::ALSA
Threads::Threads
)
if (LINUX)
target_link_libraries(binjnes
OpenGL::GL
${X11_X11_LIB}
${X11_Xi_LIB}
${X11_Xcursor_LIB}
ALSA::ALSA
Threads::Threads
)
endif ()
install(TARGETS binjnes DESTINATION bin)
target_copy_to_bin(binjnes)

Expand Down
31 changes: 31 additions & 0 deletions src/atomic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#if defined(BINJNES_GCC) || defined(BINJNES_CLANG)

#include <stdatomic.h>

typedef atomic_size_t AtomicSize;
static inline size_t atomic_load_size(AtomicSize* addr) {
return atomic_load(addr);
}

static inline void atomic_store_size(AtomicSize* addr, size_t value) {
atomic_store(addr, value);
}

#elif defined(BINJNES_MSVC)

#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#undef ERROR

typedef volatile PVOID AtomicSize;

size_t atomic_load_size(AtomicSize* addr) {
return (size_t)*addr;
}

void atomic_store_size(AtomicSize* addr, size_t value) {
_InterlockedExchangePointer(addr, (PVOID)value);
}

#endif
29 changes: 15 additions & 14 deletions src/binjnes.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#include <assert.h>
#include <stdarg.h>
#include <stdatomic.h>

#include "sokol/sokol_app.h"
#include "sokol/sokol_audio.h"
#include "sokol/sokol_gfx.h"
#include "sokol/sokol_glue.h"

#include "atomic.h"
#include "common.h"
#include "emulator.h"
#include "joypad.h"
Expand Down Expand Up @@ -70,8 +70,8 @@ static bool s_update_viewport = true;
static f32 s_viewport_x, s_viewport_y, s_viewport_w, s_viewport_h;
static f32 s_audio_volume = 0.5f;
static f32 s_audio_buffer[AUDIO_FRAMES * AUDIO_CHANNELS * 5 + 1];
static atomic_size_t s_audio_buffer_read = 0;
static atomic_size_t s_audio_buffer_write = 0;
static AtomicSize s_audio_buffer_read = 0;
static AtomicSize s_audio_buffer_write = 0;
static bool s_key_state[KEYCODE_COUNT];
static bool s_mouse_state[MOUSEBUTTON_COUNT];
static f32 s_mouse_x, s_mouse_y;
Expand Down Expand Up @@ -161,7 +161,7 @@ static void draw_str(int x, int y, RGBA color, const char* s) {

static void draw_rect_str(int x, int y, RGBA rectcolor, RGBA strcolor,
const char *s) {
size_t len = strlen(s);
int len = (int)strlen(s);
fill_rect(x - 1, y - 1, x + len * (GLYPH_WIDTH + 1) + 1, y + GLYPH_HEIGHT + 1,
rectcolor);
draw_str(x, y, strcolor, s);
Expand Down Expand Up @@ -398,8 +398,8 @@ static void init_graphics(void) {
}

static void audio_stream(float* dst_buffer, int num_frames, int num_channels) {
size_t read_head = atomic_load(&s_audio_buffer_read);
size_t write_head = atomic_load(&s_audio_buffer_write);
size_t read_head = atomic_load_size(&s_audio_buffer_read);
size_t write_head = atomic_load_size(&s_audio_buffer_write);
size_t src_avail = read_head <= write_head
? write_head - read_head
: ARRAY_SIZE(s_audio_buffer) - read_head + write_head;
Expand All @@ -421,7 +421,7 @@ static void audio_stream(float* dst_buffer, int num_frames, int num_channels) {
memcpy(dst_buffer + to_end, s_audio_buffer, to_read * sizeof(f32));
read_head = to_read;
}
atomic_store(&s_audio_buffer_read, read_head);
atomic_store_size(&s_audio_buffer_read, read_head);
}

static void init_audio(void) {
Expand Down Expand Up @@ -571,8 +571,8 @@ static void run_until_ticks(Ticks until_ticks) {
AudioBuffer *audio_buffer = emulator_get_audio_buffer(e);
size_t src_avail =
MIN(AUDIO_FRAMES, audio_buffer_get_frames(audio_buffer));
size_t read_head = atomic_load(&s_audio_buffer_read);
size_t write_head = atomic_load(&s_audio_buffer_write);
size_t read_head = atomic_load_size(&s_audio_buffer_read);
size_t write_head = atomic_load_size(&s_audio_buffer_write);
size_t dst_avail =
write_head < read_head
? read_head - write_head - 1
Expand All @@ -593,7 +593,7 @@ static void run_until_ticks(Ticks until_ticks) {
write_head = to_write - to_end;
write_audio(audio_buffer->data + to_end, 0, write_head);
}
atomic_store(&s_audio_buffer_write, write_head);
atomic_store_size(&s_audio_buffer_write, write_head);
}

if (event & EMULATOR_EVENT_RESET_CHANGE) {
Expand Down Expand Up @@ -648,7 +648,7 @@ static void rewind_by(Ticks delta) {
Ticks oldest = rewind_get_oldest_ticks(s_rewind_buffer);
Ticks total = s_rewind_start - oldest;
Ticks then_diff = then - oldest;
int num_ticks = then_diff * (GLYPHS_PER_LINE - 2) / total;
int num_ticks = (int)(then_diff * (GLYPHS_PER_LINE - 2) / total);

char buffer[GLYPHS_PER_LINE + 1];
buffer[0] = '|';
Expand Down Expand Up @@ -692,8 +692,8 @@ static void frame(void) {
rewind_by(REWIND_CYCLES_PER_FRAME);
} else if (s_paused) {
// Clear audio buffer.
size_t read_head = atomic_load(&s_audio_buffer_read);
size_t write_head = atomic_load(&s_audio_buffer_write);
size_t read_head = atomic_load_size(&s_audio_buffer_read);
size_t write_head = atomic_load_size(&s_audio_buffer_write);
if (write_head < read_head) {
memset(s_audio_buffer + write_head, 0,
(read_head - write_head - 1) * sizeof(f32));
Expand All @@ -702,7 +702,7 @@ static void frame(void) {
memset(s_audio_buffer + write_head, 0, to_end * sizeof(f32));
memset(s_audio_buffer, 0, (read_head - 1) * sizeof(f32));
}
atomic_store(&s_audio_buffer_write, read_head - 1);
atomic_store_size(&s_audio_buffer_write, read_head - 1);
} else {
f64 delta_sec = sapp_frame_duration();
Ticks delta_ticks = (Ticks)(delta_sec * PPU_TICKS_PER_SECOND);
Expand Down Expand Up @@ -837,5 +837,6 @@ sapp_desc sokol_main(int argc, char *argv[]) {
.width = SCREEN_WIDTH * s_render_scale,
.height = SCREEN_HEIGHT * s_render_scale,
.window_title = "binjnes",
.win32_console_attach = true,
};
}
2 changes: 1 addition & 1 deletion src/cartdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static u32 get_crc(u8 *buf, int len) {
const CartDbInfo* cartdb_info_from_file(const FileData* file_data) {
const size_t kHeaderSize = 16;
const size_t kCartDbLength = ARRAY_SIZE(s_cart_db);
u32 crc = get_crc(file_data->data + kHeaderSize, file_data->size - kHeaderSize);
u32 crc = get_crc(file_data->data + kHeaderSize, (int)(file_data->size - kHeaderSize));
const CartDbInfo* begin = &s_cart_db[0];
const CartDbInfo* end = &s_cart_db[kCartDbLength];
LOWER_BOUND(const CartDbInfo, found, begin, end, crc, GET_CRC, CMP_LT);
Expand Down
11 changes: 9 additions & 2 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,22 @@
extern "C" {
#endif

#if defined(__clang__) || defined(__GNUC__)
#if defined(BINJNES_CLANG) || defined(BINJNES_GCC)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#define LIKELY(x) __builtin_expect(!!(x), 1)
#else
#define UNLIKELY(x) (x)
#define LIKELY(x) (x)
#endif

#if defined(BINJNES_CLANG) || defined(BINJNES_GCC)
#define UNREACHABLE() __builtin_unreachable()
#elif defined(BINJNES_MSVC)
#define UNREACHABLE() __assume(0)
#else
#error "How to define unreachable on this compiler?"
#endif

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define ZERO_MEMORY(x) memset(&(x), 0, sizeof(x))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
Expand Down Expand Up @@ -59,7 +67,6 @@ extern "C" {
fclose(f); \
} \
return ERROR
#define UNREACHABLE(...) PRINT_ERROR(__VA_ARGS__), exit(1)

#define MAKE_RGBA(r, g, b, a) \
(((u32)(u8)(a) << 24) | ((u32)(u8)(b) << 16) | ((u32)(u8)(g) << 8) | \
Expand Down
Loading

0 comments on commit 0b95f45

Please sign in to comment.