Skip to content

Commit b983f55

Browse files
committed
Parse binjgb.ini file
Has very simple format, with following keys: ``` autoload=filename.gb audio-frequency=44100 audio-frames=2048 builtin-palette=0 force-dmg=0 rewind-frames-per-base-state=45 rewind-buffer-capacity-megabytes=32 rewind-scale=1.5 render-scale=4 random-seed=0 sgb-border=0 ``` Some of these probably should not be adjusted by users. :-)
1 parent 3add194 commit b983f55

4 files changed

Lines changed: 140 additions & 14 deletions

File tree

README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,64 @@ Keys:
168168
| Pause | <kbd>Space</kbd> |
169169
| Step one frame | <kbd>N</kbd> |
170170

171+
## INI file
172+
173+
Binjgb tries to read from `binjgb.ini` on startup for configuration. The
174+
following keys are supported:
175+
176+
```
177+
# Load this file automatically on startup
178+
autoload=filename.gb
179+
180+
# Set the audio frequency in Hz
181+
audio-frequency=44100
182+
183+
# Set the number of audio frames per buffer
184+
# lower=better latency, more pops/clicks
185+
# higher=worse latency, fewer pops/clicks
186+
audio-frames=2048
187+
188+
# Set to the index of a builtin palette
189+
# (valid numbers are 0..82)
190+
builtin-palette=0
191+
192+
# Force the emulator to run in DMG (original gameboy) mode.
193+
# 0=Don't force DMG
194+
# 1=Force DMG
195+
force-dmg=0
196+
197+
# The number of video frames to display before storing a full dump of
198+
# the emulator state in the rewind buffer. Probably best to leave this
199+
# alone
200+
rewind-frames-per-base-state=45
201+
202+
# The number of megabytes to allocate to the rewind buffer.
203+
# lower=less memory usage, less rewind time
204+
# higher=more memory usage, more rewind time
205+
rewind-buffer-capacity-megabytes=32
206+
207+
# The speed at which to rewind the game, as a scale.
208+
# 1=rewind at 1x
209+
# 2=rewind at 2x
210+
# etc.
211+
rewind-scale=1.5
212+
213+
# How much to scale the emulator window at startup.
214+
render-scale=4
215+
216+
# What to set the random seed to when initializing memory. Using 0
217+
# disables memory randomization.
218+
random-seed=0
219+
220+
# Whether to display the SGB border or not.
221+
# 0=Don't display SGB border
222+
# 1=Display SGB border, even if it doesn't exist.
223+
sgb-border=0
224+
```
225+
226+
The INI file is loaded before parsing the command line flags, so you can use
227+
the command line to override the values in the INI file.
228+
171229
## Running tests
172230

173231
Run `scripts/build_tests.py` to download and build the necessary testsuites.

src/binjgb.c

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@
2626
#define STATUS_TEXT_RGBA MAKE_RGBA(255, 0, 0, 255)
2727
#define STATUS_TEXT_TIMEOUT 120 /* Frames */
2828

29-
// TODO: make these configurable?
30-
#define AUDIO_FREQUENCY 44100
31-
#define AUDIO_FRAMES 2048 /* ~46ms of latency at 44.1kHz */
32-
#define REWIND_FRAMES_PER_BASE_STATE 45
33-
#define REWIND_BUFFER_CAPACITY MEGABYTES(32)
34-
#define REWIND_CYCLES_PER_FRAME (70224 * 3 / 2) /* Rewind at 1.5x */
35-
3629
typedef enum Layer {
3730
LAYER_BG,
3831
LAYER_WINDOW,
@@ -69,6 +62,12 @@ static Bool s_force_dmg;
6962
static Bool s_use_sgb_border;
7063
static u32 s_render_scale = 4;
7164

65+
static u32 s_audio_frequency = 44100;
66+
static u32 s_audio_frames = 2048; /* ~46ms of latency at 44.1kHz */
67+
static u32 s_rewind_frames_per_base_state = 45;
68+
static u32 s_rewind_buffer_capacity_megabytes = 32;
69+
static f32 s_rewind_scale = 1.5f;
70+
7271
static Overlay s_overlay;
7372
static StatusText s_status_text;
7473

@@ -413,9 +412,68 @@ void parse_arguments(int argc, char** argv) {
413412
exit(1);
414413
}
415414

415+
void read_ini_file(void) {
416+
FILE* file = fopen("binjgb.ini", "r");
417+
if (!file) {
418+
return;
419+
}
420+
while (1) {
421+
char buffer[1024], *value, *equals, *newline;
422+
if (!fgets(buffer, sizeof(buffer), file)) {
423+
break;
424+
}
425+
426+
if (buffer[0] == '#' || buffer[0] == '\n') {
427+
continue;
428+
}
429+
430+
equals = strchr(buffer, '=');
431+
if (!equals) {
432+
fprintf(stderr, "warning: bad ini line: %s\n", buffer);
433+
continue;
434+
}
435+
*equals = 0;
436+
value = equals + 1;
437+
438+
newline = strchr(value, '\n');
439+
if (newline) {
440+
*newline = 0;
441+
}
442+
443+
if (strcmp(buffer, "autoload") == 0) {
444+
s_rom_filename = xstrdup(value);
445+
} else if (strcmp(buffer, "audio-frequency") == 0) {
446+
s_audio_frequency = atoi(value);
447+
} else if (strcmp(buffer, "audio-frames") == 0) {
448+
s_audio_frames = atoi(value);
449+
} else if (strcmp(buffer, "builtin-palette") == 0) {
450+
s_builtin_palette = atoi(value);
451+
} else if (strcmp(buffer, "force-dmg") == 0) {
452+
s_force_dmg = atoi(value);
453+
} else if (strcmp(buffer, "rewind-frames-per-base-state") == 0) {
454+
s_rewind_frames_per_base_state = atoi(value);
455+
} else if (strcmp(buffer, "rewind-buffer-capacity-megabytes") == 0) {
456+
s_rewind_buffer_capacity_megabytes = atoi(value);
457+
} else if (strcmp(buffer, "rewind-scale") == 0) {
458+
s_rewind_scale = atof(value);
459+
} else if (strcmp(buffer, "render-scale") == 0) {
460+
s_render_scale = atoi(value);
461+
} else if (strcmp(buffer, "random-seed") == 0) {
462+
s_random_seed = atoi(value);
463+
} else if (strcmp(buffer, "sgb-border") == 0) {
464+
s_use_sgb_border = atoi(value);
465+
} else {
466+
fprintf(stderr, "warning: unknown ini key: %s\n", buffer);
467+
}
468+
}
469+
fclose(file);
470+
}
471+
416472
int main(int argc, char** argv) {
417473
int result = 1;
418474

475+
read_ini_file();
476+
419477
parse_arguments(argc, argv);
420478

421479
FileData rom;
@@ -424,8 +482,8 @@ int main(int argc, char** argv) {
424482
EmulatorInit emulator_init;
425483
ZERO_MEMORY(emulator_init);
426484
emulator_init.rom = rom;
427-
emulator_init.audio_frequency = AUDIO_FREQUENCY;
428-
emulator_init.audio_frames = AUDIO_FRAMES;
485+
emulator_init.audio_frequency = s_audio_frequency;
486+
emulator_init.audio_frames = s_audio_frames;
429487
emulator_init.random_seed = s_random_seed;
430488
emulator_init.builtin_palette = s_builtin_palette;
431489
emulator_init.force_dmg = s_force_dmg;
@@ -437,11 +495,11 @@ int main(int argc, char** argv) {
437495
host_init.hooks.key_down = key_down;
438496
host_init.hooks.key_up = key_up;
439497
host_init.render_scale = s_render_scale;
440-
host_init.audio_frequency = AUDIO_FREQUENCY;
441-
host_init.audio_frames = AUDIO_FRAMES;
498+
host_init.audio_frequency = s_audio_frequency;
499+
host_init.audio_frames = s_audio_frames;
442500
host_init.audio_volume = s_audio_volume;
443-
host_init.rewind.frames_per_base_state = REWIND_FRAMES_PER_BASE_STATE;
444-
host_init.rewind.buffer_capacity = REWIND_BUFFER_CAPACITY;
501+
host_init.rewind.frames_per_base_state = s_rewind_frames_per_base_state;
502+
host_init.rewind.buffer_capacity = s_rewind_buffer_capacity_megabytes * MEGABYTES(1);
445503
host_init.joypad_filename = s_read_joypad_filename;
446504
host_init.use_sgb_border = s_use_sgb_border;
447505
host = host_new(&host_init, e);
@@ -458,7 +516,7 @@ int main(int argc, char** argv) {
458516
f64 refresh_ms = host_get_monitor_refresh_ms(host);
459517
while (s_running && host_poll_events(host)) {
460518
if (s_rewinding) {
461-
rewind_by(REWIND_CYCLES_PER_FRAME);
519+
rewind_by((Ticks)(PPU_FRAME_TICKS * s_rewind_scale));
462520
} else if (!s_paused) {
463521
EmulatorEvent event = host_run_ms(host, refresh_ms);
464522
if (event & EMULATOR_EVENT_INVALID_OPCODE) {

src/memory.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,10 @@ void* xcalloc_(const char* file, int line, size_t count, size_t size) {
3232
return p;
3333
}
3434

35+
char* xstrdup_(const char* file, int line, const char* s) {
36+
char* p = strdup(s);
37+
printf("%s:%d: %s(%p) => %p\n", file, line, __func__, s, p);
38+
return p;
39+
}
40+
3541
#endif

src/memory.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define BINJGB_MEMORY_H_
99

1010
#include <stdlib.h>
11+
#include <string.h>
1112

1213
#ifdef __cplusplus
1314
extern "C" {
@@ -20,17 +21,20 @@ extern "C" {
2021
#define xmalloc(size) xmalloc_(__FILE__, __LINE__, size)
2122
#define xfree(p) xfree_(__FILE__, __LINE__, p)
2223
#define xcalloc(count, size) xcalloc_(__FILE__, __LINE__, count, size)
24+
#define xstrdup(s) xstrdup_(__FILE__, __LINE__, s)
2325

2426
/* Use these instead to make it easier to track memory usage. */
2527
void* xmalloc_(const char* file, int line, size_t);
2628
void xfree_(const char* file, int line, void*);
2729
void* xcalloc_(const char* file, int line, size_t, size_t);
30+
char* xstrdup_(const char* file, int line, const char*);
2831

2932
#else
3033

3134
#define xmalloc malloc
3235
#define xfree free
3336
#define xcalloc calloc
37+
#define xstrdup strdup
3438

3539
#endif
3640

0 commit comments

Comments
 (0)