Skip to content

Commit

Permalink
Parse binjgb.ini file
Browse files Browse the repository at this point in the history
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. :-)
  • Loading branch information
binji committed Aug 21, 2021
1 parent 3add194 commit b983f55
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 14 deletions.
58 changes: 58 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,64 @@ Keys:
| Pause | <kbd>Space</kbd> |
| Step one frame | <kbd>N</kbd> |

## INI file

Binjgb tries to read from `binjgb.ini` on startup for configuration. The
following keys are supported:

```
# Load this file automatically on startup
autoload=filename.gb
# Set the audio frequency in Hz
audio-frequency=44100
# Set the number of audio frames per buffer
# lower=better latency, more pops/clicks
# higher=worse latency, fewer pops/clicks
audio-frames=2048
# Set to the index of a builtin palette
# (valid numbers are 0..82)
builtin-palette=0
# Force the emulator to run in DMG (original gameboy) mode.
# 0=Don't force DMG
# 1=Force DMG
force-dmg=0
# The number of video frames to display before storing a full dump of
# the emulator state in the rewind buffer. Probably best to leave this
# alone
rewind-frames-per-base-state=45
# The number of megabytes to allocate to the rewind buffer.
# lower=less memory usage, less rewind time
# higher=more memory usage, more rewind time
rewind-buffer-capacity-megabytes=32
# The speed at which to rewind the game, as a scale.
# 1=rewind at 1x
# 2=rewind at 2x
# etc.
rewind-scale=1.5
# How much to scale the emulator window at startup.
render-scale=4
# What to set the random seed to when initializing memory. Using 0
# disables memory randomization.
random-seed=0
# Whether to display the SGB border or not.
# 0=Don't display SGB border
# 1=Display SGB border, even if it doesn't exist.
sgb-border=0
```

The INI file is loaded before parsing the command line flags, so you can use
the command line to override the values in the INI file.

## Running tests

Run `scripts/build_tests.py` to download and build the necessary testsuites.
Expand Down
86 changes: 72 additions & 14 deletions src/binjgb.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@
#define STATUS_TEXT_RGBA MAKE_RGBA(255, 0, 0, 255)
#define STATUS_TEXT_TIMEOUT 120 /* Frames */

// TODO: make these configurable?
#define AUDIO_FREQUENCY 44100
#define AUDIO_FRAMES 2048 /* ~46ms of latency at 44.1kHz */
#define REWIND_FRAMES_PER_BASE_STATE 45
#define REWIND_BUFFER_CAPACITY MEGABYTES(32)
#define REWIND_CYCLES_PER_FRAME (70224 * 3 / 2) /* Rewind at 1.5x */

typedef enum Layer {
LAYER_BG,
LAYER_WINDOW,
Expand Down Expand Up @@ -69,6 +62,12 @@ static Bool s_force_dmg;
static Bool s_use_sgb_border;
static u32 s_render_scale = 4;

static u32 s_audio_frequency = 44100;
static u32 s_audio_frames = 2048; /* ~46ms of latency at 44.1kHz */
static u32 s_rewind_frames_per_base_state = 45;
static u32 s_rewind_buffer_capacity_megabytes = 32;
static f32 s_rewind_scale = 1.5f;

static Overlay s_overlay;
static StatusText s_status_text;

Expand Down Expand Up @@ -413,9 +412,68 @@ void parse_arguments(int argc, char** argv) {
exit(1);
}

void read_ini_file(void) {
FILE* file = fopen("binjgb.ini", "r");
if (!file) {
return;
}
while (1) {
char buffer[1024], *value, *equals, *newline;
if (!fgets(buffer, sizeof(buffer), file)) {
break;
}

if (buffer[0] == '#' || buffer[0] == '\n') {
continue;
}

equals = strchr(buffer, '=');
if (!equals) {
fprintf(stderr, "warning: bad ini line: %s\n", buffer);
continue;
}
*equals = 0;
value = equals + 1;

newline = strchr(value, '\n');
if (newline) {
*newline = 0;
}

if (strcmp(buffer, "autoload") == 0) {
s_rom_filename = xstrdup(value);
} else if (strcmp(buffer, "audio-frequency") == 0) {
s_audio_frequency = atoi(value);
} else if (strcmp(buffer, "audio-frames") == 0) {
s_audio_frames = atoi(value);
} else if (strcmp(buffer, "builtin-palette") == 0) {
s_builtin_palette = atoi(value);
} else if (strcmp(buffer, "force-dmg") == 0) {
s_force_dmg = atoi(value);
} else if (strcmp(buffer, "rewind-frames-per-base-state") == 0) {
s_rewind_frames_per_base_state = atoi(value);
} else if (strcmp(buffer, "rewind-buffer-capacity-megabytes") == 0) {
s_rewind_buffer_capacity_megabytes = atoi(value);
} else if (strcmp(buffer, "rewind-scale") == 0) {
s_rewind_scale = atof(value);
} else if (strcmp(buffer, "render-scale") == 0) {
s_render_scale = atoi(value);
} else if (strcmp(buffer, "random-seed") == 0) {
s_random_seed = atoi(value);
} else if (strcmp(buffer, "sgb-border") == 0) {
s_use_sgb_border = atoi(value);
} else {
fprintf(stderr, "warning: unknown ini key: %s\n", buffer);
}
}
fclose(file);
}

int main(int argc, char** argv) {
int result = 1;

read_ini_file();

parse_arguments(argc, argv);

FileData rom;
Expand All @@ -424,8 +482,8 @@ int main(int argc, char** argv) {
EmulatorInit emulator_init;
ZERO_MEMORY(emulator_init);
emulator_init.rom = rom;
emulator_init.audio_frequency = AUDIO_FREQUENCY;
emulator_init.audio_frames = AUDIO_FRAMES;
emulator_init.audio_frequency = s_audio_frequency;
emulator_init.audio_frames = s_audio_frames;
emulator_init.random_seed = s_random_seed;
emulator_init.builtin_palette = s_builtin_palette;
emulator_init.force_dmg = s_force_dmg;
Expand All @@ -437,11 +495,11 @@ int main(int argc, char** argv) {
host_init.hooks.key_down = key_down;
host_init.hooks.key_up = key_up;
host_init.render_scale = s_render_scale;
host_init.audio_frequency = AUDIO_FREQUENCY;
host_init.audio_frames = AUDIO_FRAMES;
host_init.audio_frequency = s_audio_frequency;
host_init.audio_frames = s_audio_frames;
host_init.audio_volume = s_audio_volume;
host_init.rewind.frames_per_base_state = REWIND_FRAMES_PER_BASE_STATE;
host_init.rewind.buffer_capacity = REWIND_BUFFER_CAPACITY;
host_init.rewind.frames_per_base_state = s_rewind_frames_per_base_state;
host_init.rewind.buffer_capacity = s_rewind_buffer_capacity_megabytes * MEGABYTES(1);
host_init.joypad_filename = s_read_joypad_filename;
host_init.use_sgb_border = s_use_sgb_border;
host = host_new(&host_init, e);
Expand All @@ -458,7 +516,7 @@ int main(int argc, char** argv) {
f64 refresh_ms = host_get_monitor_refresh_ms(host);
while (s_running && host_poll_events(host)) {
if (s_rewinding) {
rewind_by(REWIND_CYCLES_PER_FRAME);
rewind_by((Ticks)(PPU_FRAME_TICKS * s_rewind_scale));
} else if (!s_paused) {
EmulatorEvent event = host_run_ms(host, refresh_ms);
if (event & EMULATOR_EVENT_INVALID_OPCODE) {
Expand Down
6 changes: 6 additions & 0 deletions src/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ void* xcalloc_(const char* file, int line, size_t count, size_t size) {
return p;
}

char* xstrdup_(const char* file, int line, const char* s) {
char* p = strdup(s);
printf("%s:%d: %s(%p) => %p\n", file, line, __func__, s, p);
return p;
}

#endif
4 changes: 4 additions & 0 deletions src/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define BINJGB_MEMORY_H_

#include <stdlib.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
Expand All @@ -20,17 +21,20 @@ extern "C" {
#define xmalloc(size) xmalloc_(__FILE__, __LINE__, size)
#define xfree(p) xfree_(__FILE__, __LINE__, p)
#define xcalloc(count, size) xcalloc_(__FILE__, __LINE__, count, size)
#define xstrdup(s) xstrdup_(__FILE__, __LINE__, s)

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

#else

#define xmalloc malloc
#define xfree free
#define xcalloc calloc
#define xstrdup strdup

#endif

Expand Down

0 comments on commit b983f55

Please sign in to comment.