Skip to content

Commit 2282d64

Browse files
committed
move third party and apply build fixes
1 parent 6ce5946 commit 2282d64

5 files changed

Lines changed: 245 additions & 226 deletions

File tree

CMakeLists.txt

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
88

99
option(WERROR "Build with warnings as errors" OFF)
1010
option(WASM "Build for WebAssembly" OFF)
11-
option(RGBDS_LIVE "Build for rgbds-live (Wasm only)" OFF)
12-
option(GBSTUDIO "Build for GB Studio (Wasm only. Sets rgbds-live.)" OFF)
11+
option(THIRDPARTY_HOOKS "Build with thirdparty-default-hooks.c (Wasm only)" OFF)
12+
option(GBSTUDIO "Build for GB Studio (Wasm only, using thirdparty-default-hooks.c)" OFF)
1313

1414
if (MSVC)
1515
add_definitions(-W3 -D_CRT_SECURE_NO_WARNINGS)
@@ -143,43 +143,50 @@ else (EMSCRIPTEN)
143143
add_executable(binjgb
144144
src/memory.c
145145
src/common.c
146-
src/emulator.c
147146
src/joypad.c
148147
src/rewind.c
149148
src/emscripten/wrapper.c)
150149
set(EXPORTED_JSON ${PROJECT_SOURCE_DIR}/src/emscripten/exported.json)
151150
target_include_directories(binjgb PUBLIC ${PROJECT_SOURCE_DIR}/src)
152151

153-
if (RGBDS_LIVE)
154-
target_compile_definitions(binjgb PUBLIC RGBDS_LIVE)
155-
endif ()
152+
set(BINJGB_THIRDPARTY_HOOKS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/emscripten/thirdparty-default-hooks.c"
153+
CACHE FILEPATH "Path to the emulator hooks implementation file")
156154

157155
if (GBSTUDIO)
158-
# If GBSTUDIO is set, set RGBDS_LIVE too
159-
target_compile_definitions(binjgb PUBLIC GBSTUDIO RGBDS_LIVE)
156+
set(THIRDPARTY_HOOKS ON)
157+
target_compile_definitions(binjgb PUBLIC GBSTUDIO)
160158
endif ()
161159

162-
set(LINK_FLAGS
163-
-s EXPORTED_FUNCTIONS=\"@${EXPORTED_JSON}\"
164-
-s MALLOC=emmalloc
165-
-s ASSERTIONS=0
166-
-s ENVIRONMENT=web
167-
-s FILESYSTEM=0
168-
-s EXIT_RUNTIME=0
169-
-s MODULARIZE=1
170-
-s EXPORT_NAME="Binjgb"
171-
)
160+
if (THIRDPARTY_HOOKS)
161+
target_sources(binjgb PRIVATE ${BINJGB_THIRDPARTY_HOOKS_FILE})
162+
else()
163+
target_sources(binjgb PRIVATE src/emulator.c)
164+
endif()
165+
166+
if(NOT BINJGB_LINKER_OPTIONS)
167+
set(BINJGB_LINKER_OPTIONS
168+
-sMALLOC=emmalloc
169+
-sASSERTIONS=0
170+
-sENVIRONMENT=web
171+
-sFILESYSTEM=0
172+
-sEXIT_RUNTIME=0
173+
-sMODULARIZE=1
174+
-sEXPORT_NAME=Binjgb
175+
)
176+
endif()
177+
172178
if (WASM)
173-
set(LINK_FLAGS ${LINK_FLAGS} -s WASM=1)
174-
else ()
175-
set(LINK_FLAGS ${LINK_FLAGS} -s WASM=0)
179+
list(APPEND BINJGB_LINKER_OPTIONS -sWASM=1)
180+
else()
181+
list(APPEND BINJGB_LINKER_OPTIONS -sWASM=0)
176182
endif ()
177183

178-
string(REPLACE ";" " " LINK_FLAGS_STR "${LINK_FLAGS}")
184+
list(APPEND BINJGB_LINKER_OPTIONS -sEXPORTED_FUNCTIONS=@${EXPORTED_JSON})
185+
186+
target_link_options(binjgb PRIVATE ${BINJGB_LINKER_OPTIONS})
179187

180188
set_target_properties(binjgb
181189
PROPERTIES
182-
LINK_FLAGS "${LINK_FLAGS_STR}"
183190
LINK_DEPENDS "${EXPORTED_JSON}"
184191
)
185192
endif ()

src/emscripten/exported.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
[
2-
"_emulator_clear_breakpoints",
32
"_emulator_delete",
43
"_emulator_get_A",
54
"_emulator_get_BC",
6-
"_emulator_get_banked_PC",
75
"_emulator_get_DE",
86
"_emulator_get_F",
97
"_emulator_get_HL",
@@ -16,10 +14,7 @@
1614
"_emulator_read_ext_ram",
1715
"_emulator_read_mem",
1816
"_emulator_read_state",
19-
"_emulator_render_background",
20-
"_emulator_render_vram",
2117
"_emulator_run_until_f64",
22-
"_emulator_set_breakpoint",
2318
"_emulator_set_builtin_palette",
2419
"_emulator_set_bw_palette_simple",
2520
"_emulator_set_default_joypad_callback",
@@ -54,7 +49,6 @@
5449
"_rewind_get_oldest_ticks_f64",
5550
"_rewind_new_simple",
5651
"_rewind_to_ticks_wrapper",
57-
"_set_audio_channel_mute",
5852
"_set_joyp_A",
5953
"_set_joyp_B",
6054
"_set_joyp_down",
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
#include "common.h"
2+
#include "emulator.h"
3+
4+
#include <emscripten.h>
5+
6+
// hooks we wana implement
7+
#define IS_SPEC_emulator_step_after ~,1
8+
#define IS_SPEC_serial_write ~,1
9+
10+
//fallback to default/dummy "implementations"
11+
#define HOOK_SELECT_INNER(...) HOOK_SELECT_GET_3(__VA_ARGS__)
12+
#define HOOK_SELECT_GET_3(a, b, slot, ...) slot
13+
14+
#define HOOK_VOID_CALL(name, e, f, ...) HOOK_##name(e, f, ##__VA_ARGS__)
15+
#define HOOK_VOID_IGNORE(...) ((void)0)
16+
17+
#define HOOK_BOOL_CALL(name, e, f, ...) HOOK_##name(e, f)
18+
#define HOOK_BOOL_IGNORE(...) (FALSE)
19+
#define HOOK0(name) \
20+
HOOK_SELECT_INNER(IS_SPEC_##name, HOOK_VOID_CALL, HOOK_VOID_IGNORE)(name, e, __func__)
21+
22+
#define HOOK(name, ...) \
23+
HOOK_SELECT_INNER(IS_SPEC_##name, HOOK_VOID_CALL, HOOK_VOID_IGNORE)(name, e, __func__, __VA_ARGS__)
24+
25+
#define HOOK0_FALSE(name) \
26+
HOOK_SELECT_INNER(IS_SPEC_##name, HOOK_BOOL_CALL, HOOK_BOOL_IGNORE)(name, e, __func__)
27+
28+
29+
#ifndef BREAKPOINTS_MAX_BANKS_NUMBER
30+
#define BREAKPOINTS_MAX_BANKS_NUMBER 1
31+
#endif
32+
33+
typedef uint32_t breakpoints_type;
34+
#define MEMORY_SIZE (64 * 1024)
35+
#define BREAKPOINTS_BIT_SIZE (sizeof(breakpoints_type) * 8)
36+
#define BREAKPOINTS_SIZE ((BREAKPOINTS_MAX_BANKS_NUMBER * MEMORY_SIZE) / BREAKPOINTS_BIT_SIZE)
37+
#define BREAKPOINTS_SHIFT (__builtin_ctz(BREAKPOINTS_BIT_SIZE))
38+
#define BREAKPOINTS_MASK (BREAKPOINTS_BIT_SIZE - 1)
39+
#define BREAKPOINTS_BANK_SHIFT (16 - BREAKPOINTS_SHIFT)
40+
41+
#define EMULATOR_FIELDS_HOOK breakpoints_type breakpoint[BREAKPOINTS_SIZE] __attribute__((aligned(8)));
42+
43+
static void HOOK_emulator_step_after(Emulator*, const char* func_name);
44+
static void HOOK_serial_write(Emulator*, const char* func_name, u8 value);
45+
46+
#include "emulator.c"
47+
48+
static inline uint32_t emulator_get_banked_PC_inline(Emulator *e) {
49+
#if BREAKPOINTS_MAX_BANKS_NUMBER > 1
50+
uint16_t pc = REG.PC;
51+
if (pc < 0x4000) {
52+
return (MMAP_STATE.rom_base[0] << (16 - ROM_BANK_SHIFT)) | pc;
53+
} else if (pc < 0x8000) {
54+
return (MMAP_STATE.rom_base[1] << (16 - ROM_BANK_SHIFT)) | pc;
55+
} else if (pc < 0xA000) {
56+
return (e->state.vram.bank << 16) | pc;
57+
} else if (pc < 0xC000) {
58+
return (MMAP_STATE.ext_ram_base << (16 - EXT_RAM_BANK_SHIFT)) | pc;
59+
} else if (pc < 0xE000) {
60+
return (e->state.wram.bank << 16) | pc;
61+
}
62+
return pc;
63+
#else
64+
return REG.PC;
65+
#endif
66+
}
67+
68+
static inline bool is_breakpoint(Emulator* e, uint32_t banked_pc) {
69+
uint32_t idx = banked_pc >> BREAKPOINTS_SHIFT;
70+
return (e->breakpoint[idx] & ((breakpoints_type)1 << (banked_pc & BREAKPOINTS_MASK)));
71+
}
72+
73+
74+
void HOOK_serial_write(Emulator* e, const char* func_name, u8 value) {
75+
EM_ASM({emulator.serialCallback($0);}, value);
76+
}
77+
78+
void HOOK_emulator_step_after(Emulator* e, const char* func_name) {
79+
uint32_t banked_pc = emulator_get_banked_PC_inline(e);
80+
if (is_breakpoint(e, banked_pc)) {
81+
e->state.event |= EMULATOR_EVENT_BREAKPOINT;
82+
}
83+
}
84+
85+
EMSCRIPTEN_KEEPALIVE
86+
void emulator_set_breakpoint(Emulator* e, uint32_t addr) {
87+
uint32_t idx = addr >> BREAKPOINTS_SHIFT;
88+
e->breakpoint[idx] |= ((breakpoints_type)1 << (addr & BREAKPOINTS_MASK));
89+
}
90+
91+
EMSCRIPTEN_KEEPALIVE
92+
void emulator_clear_breakpoints(Emulator* e) {
93+
ZERO_MEMORY(e->breakpoint);
94+
}
95+
96+
EMSCRIPTEN_KEEPALIVE
97+
uint32_t emulator_get_banked_PC(Emulator *e) {
98+
return emulator_get_banked_PC_inline(e);
99+
}
100+
101+
EMSCRIPTEN_KEEPALIVE
102+
void emulator_render_vram(Emulator* e, u32* buffer) {
103+
memset(buffer, 0, sizeof(u32) * 256 * 256);
104+
for (int ty = 0; ty < 24; ty++) {
105+
for (int bank = 0; bank < 2; bank++) {
106+
for (int tx = 0; tx < 16; tx++) {
107+
for (int row = 0; row < 8; row++) {
108+
int n = tx * 16 + ty * 16 * 16 + row * 2 + (bank << 13);
109+
u8 a = VRAM.data[n];
110+
u8 b = VRAM.data[n + 1];
111+
for (int x = 0; x < 8; x++) {
112+
u32 color = 0xFFC2F0C4;
113+
u8 bit = (0x80 >> x);
114+
if ((a & bit) && (b & bit)) {
115+
color = 0xFF001B2D;
116+
} else if (a & bit) {
117+
color = 0xFFA8B95A;
118+
} else if (b & bit) {
119+
color = 0xFF6E601E;
120+
} else if (x == 7 || row == 7) {
121+
color = 0xFFB2E0B4;
122+
}
123+
buffer[(tx * 8 + x + bank * 128) + (ty * 8 + row) * 256] = color;
124+
}
125+
}
126+
}
127+
}
128+
}
129+
if (IS_CGB) {
130+
for (int idx = 0; idx < 8; idx++) {
131+
for (int col = 0; col < PALETTE_COLOR_COUNT; col++) {
132+
for (int x = 0; x < 8; x++) {
133+
for (int y = 0; y < 8; y++) {
134+
buffer[x + idx * 8 + (200 + col * 8 + y) * 256] =
135+
PPU.bgcp.palettes[idx].color[col];
136+
buffer[x + idx * 8 + (200 + col * 8 + y) * 256 + 128] =
137+
PPU.obcp.palettes[idx].color[col];
138+
}
139+
}
140+
}
141+
}
142+
} else {
143+
for (int type = 0; type < PALETTE_TYPE_COUNT; type++) {
144+
for (int col = 0; col < PALETTE_COLOR_COUNT; col++) {
145+
for (int x = 0; x < 8; x++) {
146+
for (int y = 0; y < 8; y++) {
147+
buffer[x + type * 8 + (200 + col * 8 + y) * 256] =
148+
e->pal[type].color[col];
149+
}
150+
}
151+
}
152+
}
153+
}
154+
}
155+
156+
EMSCRIPTEN_KEEPALIVE
157+
void emulator_render_background(Emulator* e, u32* buffer, int type) {
158+
memset(buffer, 0, sizeof(u32) * 256 * 256);
159+
int bank = 0;
160+
int tile_map = 0x1800 + ((type & 1) ? 0x400 : 0);
161+
for (int ty = 0; ty < 32; ty++) {
162+
for (int tx = 0; tx < 32; tx++) {
163+
u8 tile = VRAM.data[tile_map + tx + ty * 32];
164+
int offset = 0;
165+
if(tile < 128)
166+
offset = (LCDC.bg_tile_data_select == TILE_DATA_8000_8FFF) ? 0 : 0x1000;
167+
for (int row = 0; row < 8; row++) {
168+
int n = offset + tile * 16 + row * 2;
169+
u8 a = VRAM.data[n];
170+
u8 b = VRAM.data[n + 1];
171+
for (int x = 0; x < 8; x++) {
172+
u32 color = 0xFFC2F0C4;
173+
u8 bit = (0x80 >> x);
174+
if ((a & bit) && (b & bit)) {
175+
color = 0xFF001B2D;
176+
} else if (a & bit) {
177+
color = 0xFFA8B95A;
178+
} else if (b & bit) {
179+
color = 0xFF6E601E;
180+
} else if (x == 7 || row == 7) {
181+
color = 0xFFB2E0B4;
182+
}
183+
buffer[(tx * 8 + x) + (ty * 8 + row) * 256] = color;
184+
}
185+
}
186+
}
187+
}
188+
for (int x = 0; x < SCREEN_WIDTH; x++) {
189+
buffer[((PPU.scx + x) % 256) + (PPU.scy * 256)] &= 0xFF7F7F7F;
190+
buffer[((PPU.scx + x) % 256) +
191+
((PPU.scy + SCREEN_HEIGHT - 1) % 256) * 256] &= 0xFF7F7F7F;
192+
}
193+
for (int y = 0; y < SCREEN_HEIGHT; y++) {
194+
buffer[PPU.scx + ((PPU.scy + y) % 256) * 256] &= 0xFF7F7F7F;
195+
buffer[((PPU.scx + SCREEN_WIDTH) % 256) + ((PPU.scy + y) % 256) * 256] &=
196+
0xFF7F7F7F;
197+
}
198+
}
199+
200+
#ifdef GBSTUDIO
201+
EMSCRIPTEN_KEEPALIVE
202+
Bool set_audio_channel_mute(Emulator *e, int channel, Bool muted) {
203+
EmulatorConfig emu_config = emulator_get_config(e);
204+
emu_config.disable_sound[channel] = muted;
205+
emulator_set_config(e, &emu_config);
206+
return emu_config.disable_sound[channel];
207+
}
208+
#endif

src/emulator-debug.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ static void HOOK_read_rom_ib(Emulator*, const char* func_name, u32 rom_addr,
120120
static void HOOK_exec_op_ai(Emulator*, const char* func_name, Address,
121121
u8 opcode);
122122
static void HOOK_exec_cb_op_i(Emulator*, const char* func_name, u8 opcode);
123+
static inline void HOOK_emulator_step_after(Emulator* e, const char* f) { (void)e; (void)f; }
124+
static inline void HOOK_serial_write(Emulator* e, const char* f, u8 v) { (void)e; (void)f; (void)v; }
123125

124126
FOREACH_LOG_HOOKS(DECLARE_LOG_HOOK)
125127

0 commit comments

Comments
 (0)