mirror of https://github.com/inolen/redream.git
removed debug menus for options that are now accessible through the ui
added key mappings as options added return value to keydown events so they can be cancelled
This commit is contained in:
parent
8d4486b2c3
commit
0593853b2a
177
src/emulator.c
177
src/emulator.c
|
@ -40,10 +40,6 @@ enum {
|
|||
ASPECT_RATIO_4BY3,
|
||||
};
|
||||
|
||||
static const char *aspect_ratios[] = {
|
||||
"stretch", "16:9", "4:3",
|
||||
};
|
||||
|
||||
/* emulation thread state */
|
||||
enum {
|
||||
EMU_SHUTDOWN,
|
||||
|
@ -410,10 +406,9 @@ static void emu_push_audio(void *userdata, const int16_t *data, int frames) {
|
|||
*/
|
||||
static void emu_set_aspect_ratio(struct emu *emu, const char *new_ratio) {
|
||||
int i;
|
||||
int num_aspect_ratios = ARRAY_SIZE(aspect_ratios);
|
||||
|
||||
for (i = 0; i < num_aspect_ratios; i++) {
|
||||
const char *aspect_ratio = aspect_ratios[i];
|
||||
for (i = 0; i < NUM_ASPECT_RATIOS; i++) {
|
||||
const char *aspect_ratio = ASPECT_RATIOS[i];
|
||||
|
||||
if (!strcmp(aspect_ratio, new_ratio)) {
|
||||
break;
|
||||
|
@ -421,12 +416,12 @@ static void emu_set_aspect_ratio(struct emu *emu, const char *new_ratio) {
|
|||
}
|
||||
|
||||
/* force to stretch if the new ratio isn't a valid one */
|
||||
if (i == num_aspect_ratios) {
|
||||
if (i == NUM_ASPECT_RATIOS) {
|
||||
i = ASPECT_RATIO_STRETCH;
|
||||
}
|
||||
|
||||
/* update persistent option as well as this session's aspect ratio */
|
||||
strncpy(OPTION_aspect, aspect_ratios[i], sizeof(OPTION_aspect));
|
||||
strncpy(OPTION_aspect, ASPECT_RATIOS[i], sizeof(OPTION_aspect));
|
||||
emu->aspect_ratio = i;
|
||||
}
|
||||
|
||||
|
@ -437,7 +432,7 @@ static void emu_debug_menu(struct emu *emu) {
|
|||
}
|
||||
|
||||
if (igBeginMainMenuBar()) {
|
||||
if (igBeginMenu("DEBUG", 1)) {
|
||||
if (igBeginMenu("EMU", 1)) {
|
||||
if (igMenuItem("frame stats", NULL, emu->frame_stats, 1)) {
|
||||
emu->frame_stats = !emu->frame_stats;
|
||||
}
|
||||
|
@ -453,32 +448,9 @@ static void emu_debug_menu(struct emu *emu) {
|
|||
igEndMenu();
|
||||
}
|
||||
|
||||
if (igBeginMenu("VIDEO", 1)) {
|
||||
if (igBeginMenu("aspect ratio", 1)) {
|
||||
for (int i = 0; i < ARRAY_SIZE(aspect_ratios); i++) {
|
||||
const char *aspect_ratio = aspect_ratios[i];
|
||||
int selected = !strcmp(OPTION_aspect, aspect_ratio);
|
||||
|
||||
if (igMenuItem(aspect_ratio, NULL, selected, 1)) {
|
||||
emu_set_aspect_ratio(emu, aspect_ratio);
|
||||
}
|
||||
}
|
||||
|
||||
igEndMenu();
|
||||
}
|
||||
if (video_can_fullscreen(emu->host)) {
|
||||
int fullscreen = video_is_fullscreen(emu->host);
|
||||
if (igMenuItem("fullscreen", NULL, fullscreen, 1)) {
|
||||
video_set_fullscreen(emu->host, !fullscreen);
|
||||
}
|
||||
}
|
||||
igEndMenu();
|
||||
}
|
||||
|
||||
igEndMainMenuBar();
|
||||
}
|
||||
|
||||
bios_debug_menu(emu->dc->bios);
|
||||
holly_debug_menu(emu->dc->holly);
|
||||
aica_debug_menu(emu->dc->aica);
|
||||
sh4_debug_menu(emu->dc->sh4);
|
||||
|
@ -598,89 +570,88 @@ static void emu_run_frame(struct emu *emu) {
|
|||
void emu_render_frame(struct emu *emu) {
|
||||
prof_counter_add(COUNTER_frames, 1);
|
||||
|
||||
if (OPTION_aspect_dirty) {
|
||||
emu_set_aspect_ratio(emu, OPTION_aspect);
|
||||
OPTION_aspect_dirty = 0;
|
||||
}
|
||||
|
||||
r_clear(emu->r);
|
||||
|
||||
if (!dc_running(emu->dc)) {
|
||||
/* not running, just build debug menu */
|
||||
emu_debug_menu(emu);
|
||||
return;
|
||||
}
|
||||
|
||||
int width = r_width(emu->r);
|
||||
int height = r_height(emu->r);
|
||||
int frame_width;
|
||||
int frame_height;
|
||||
int frame_x;
|
||||
int frame_y;
|
||||
|
||||
r_clear(emu->r);
|
||||
if (emu->aspect_ratio == ASPECT_RATIO_STRETCH) {
|
||||
frame_height = height;
|
||||
frame_width = width;
|
||||
frame_x = 0;
|
||||
frame_y = 0;
|
||||
} else if (emu->aspect_ratio == ASPECT_RATIO_16BY9) {
|
||||
frame_width = width;
|
||||
frame_height = (int)(frame_width * (9.0f / 16.0f));
|
||||
frame_x = 0;
|
||||
frame_y = (int)((height - frame_height) / 2.0f);
|
||||
} else if (emu->aspect_ratio == ASPECT_RATIO_4BY3) {
|
||||
frame_height = height;
|
||||
frame_width = (int)(frame_height * (4.0f / 3.0f));
|
||||
frame_x = (int)((width - frame_width) / 2.0f);
|
||||
frame_y = 0;
|
||||
} else {
|
||||
LOG_FATAL("unexpected aspect ratio %d", emu->aspect_ratio);
|
||||
}
|
||||
|
||||
if (dc_running(emu->dc)) {
|
||||
/* render dreamcast video */
|
||||
int frame_height, frame_width;
|
||||
int frame_x, frame_y;
|
||||
r_viewport(emu->r, frame_x, frame_y, frame_width, frame_height);
|
||||
|
||||
if (emu->aspect_ratio == ASPECT_RATIO_STRETCH) {
|
||||
frame_height = height;
|
||||
frame_width = width;
|
||||
frame_x = 0;
|
||||
frame_y = 0;
|
||||
} else if (emu->aspect_ratio == ASPECT_RATIO_16BY9) {
|
||||
frame_width = width;
|
||||
frame_height = (int)(frame_width * (9.0f / 16.0f));
|
||||
frame_x = 0;
|
||||
frame_y = (int)((height - frame_height) / 2.0f);
|
||||
} else if (emu->aspect_ratio == ASPECT_RATIO_4BY3) {
|
||||
frame_height = height;
|
||||
frame_width = (int)(frame_height * (4.0f / 3.0f));
|
||||
frame_x = (int)((width - frame_width) / 2.0f);
|
||||
frame_y = 0;
|
||||
} else {
|
||||
LOG_FATAL("unexpected aspect ratio %d", emu->aspect_ratio);
|
||||
}
|
||||
if (emu->multi_threaded) {
|
||||
/* tell the emulation thread to run the next frame */
|
||||
{
|
||||
mutex_lock(emu->run_mutex);
|
||||
|
||||
r_viewport(emu->r, frame_x, frame_y, frame_width, frame_height);
|
||||
|
||||
if (emu->multi_threaded) {
|
||||
/* tell the emulation thread to run the next frame */
|
||||
{
|
||||
mutex_lock(emu->run_mutex);
|
||||
|
||||
/* build the debug menus before running the frame, while the two threads
|
||||
are synchronized */
|
||||
emu_debug_menu(emu);
|
||||
|
||||
emu->state = EMU_RUNFRAME;
|
||||
cond_signal(emu->run_cond);
|
||||
|
||||
mutex_unlock(emu->run_mutex);
|
||||
}
|
||||
|
||||
/* wait for the emulation thread to submit a context */
|
||||
{
|
||||
mutex_lock(emu->frame_mutex);
|
||||
|
||||
while (emu->state == EMU_RUNFRAME && !emu->pending_ctx) {
|
||||
cond_wait(emu->frame_cond, emu->frame_mutex);
|
||||
}
|
||||
|
||||
/* if a context was submitted before the vblank, convert it and upload
|
||||
its textures to the render backend */
|
||||
if (emu->pending_ctx) {
|
||||
tr_convert_context(emu->r, emu, &emu_find_texture, emu->pending_ctx,
|
||||
&emu->pending_rc);
|
||||
emu->pending_ctx = NULL;
|
||||
}
|
||||
|
||||
/* unblock the emulation thread */
|
||||
mutex_unlock(emu->frame_mutex);
|
||||
}
|
||||
|
||||
/* render the latest context. note, the emulation thread may still be
|
||||
running at this time */
|
||||
tr_render_context(emu->r, &emu->pending_rc);
|
||||
} else {
|
||||
/* build the debug menus before running the frame, while the two threads
|
||||
are synchronized */
|
||||
emu_debug_menu(emu);
|
||||
|
||||
emu_run_frame(emu);
|
||||
emu->state = EMU_RUNFRAME;
|
||||
cond_signal(emu->run_cond);
|
||||
|
||||
mutex_unlock(emu->run_mutex);
|
||||
}
|
||||
|
||||
/* wait for the emulation thread to submit a context */
|
||||
{
|
||||
mutex_lock(emu->frame_mutex);
|
||||
|
||||
while (emu->state == EMU_RUNFRAME && !emu->pending_ctx) {
|
||||
cond_wait(emu->frame_cond, emu->frame_mutex);
|
||||
}
|
||||
|
||||
/* if a context was submitted before the vblank, convert it and upload
|
||||
its textures to the render backend */
|
||||
if (emu->pending_ctx) {
|
||||
tr_convert_context(emu->r, emu, &emu_find_texture, emu->pending_ctx,
|
||||
&emu->pending_rc);
|
||||
emu->pending_ctx = NULL;
|
||||
}
|
||||
|
||||
/* unblock the emulation thread */
|
||||
mutex_unlock(emu->frame_mutex);
|
||||
}
|
||||
|
||||
/* render the latest context. note, the emulation thread may still be
|
||||
running at this time */
|
||||
tr_render_context(emu->r, &emu->pending_rc);
|
||||
} else {
|
||||
/* not running, just build debug menu */
|
||||
emu_debug_menu(emu);
|
||||
|
||||
emu_run_frame(emu);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -688,14 +659,16 @@ int emu_load(struct emu *emu, const char *path) {
|
|||
return dc_load(emu->dc, path);
|
||||
}
|
||||
|
||||
void emu_keydown(struct emu *emu, int port, int key, int16_t value) {
|
||||
if (key == K_F1 && value > 0) {
|
||||
int emu_keydown(struct emu *emu, int port, int key, int16_t value) {
|
||||
if (key == K_F1 && value) {
|
||||
OPTION_debug = !OPTION_debug;
|
||||
}
|
||||
|
||||
if (key >= K_CONT_C && key <= K_CONT_RTRIG) {
|
||||
dc_input(emu->dc, port, key - K_CONT_C, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void emu_vid_swapped(struct emu *emu) {
|
||||
|
|
|
@ -13,7 +13,7 @@ void emu_destroy(struct emu *emu);
|
|||
void emu_vid_created(struct emu *emu, struct render_backend *r);
|
||||
void emu_vid_destroyed(struct emu *emu);
|
||||
void emu_vid_swapped(struct emu *emu);
|
||||
void emu_keydown(struct emu *emu, int port, int key, int16_t value);
|
||||
int emu_keydown(struct emu *emu, int port, int key, int16_t value);
|
||||
|
||||
int emu_load(struct emu *emu, const char *path);
|
||||
void emu_render_frame(struct emu *emu);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "guest/gdrom/gdrom.h"
|
||||
#include "guest/rom/flash.h"
|
||||
#include "guest/sh4/sh4.h"
|
||||
#include "imgui.h"
|
||||
#include "options.h"
|
||||
|
||||
/* system settings */
|
||||
|
@ -319,62 +318,6 @@ static int bios_post_init(struct device *dev) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_IMGUI
|
||||
void bios_debug_menu(struct bios *bios) {
|
||||
int changed = 0;
|
||||
|
||||
if (igBeginMainMenuBar()) {
|
||||
if (igBeginMenu("BIOS", 1)) {
|
||||
if (igBeginMenu("region", 1)) {
|
||||
for (int i = 0; i < ARRAY_SIZE(regions); i++) {
|
||||
const char *region = regions[i];
|
||||
int selected = !strcmp(OPTION_region, region);
|
||||
|
||||
if (igMenuItem(region, NULL, selected, 1)) {
|
||||
changed = 1;
|
||||
strncpy(OPTION_region, region, sizeof(OPTION_region));
|
||||
}
|
||||
}
|
||||
igEndMenu();
|
||||
}
|
||||
|
||||
if (igBeginMenu("language", 1)) {
|
||||
for (int i = 0; i < ARRAY_SIZE(languages); i++) {
|
||||
const char *language = languages[i];
|
||||
int selected = !strcmp(OPTION_language, language);
|
||||
|
||||
if (igMenuItem(language, NULL, selected, 1)) {
|
||||
changed = 1;
|
||||
strncpy(OPTION_language, language, sizeof(OPTION_language));
|
||||
}
|
||||
}
|
||||
igEndMenu();
|
||||
}
|
||||
|
||||
if (igBeginMenu("broadcast", 1)) {
|
||||
for (int i = 0; i < ARRAY_SIZE(broadcasts); i++) {
|
||||
const char *broadcast = broadcasts[i];
|
||||
int selected = !strcmp(OPTION_broadcast, broadcast);
|
||||
|
||||
if (igMenuItem(broadcast, NULL, selected, 1)) {
|
||||
changed = 1;
|
||||
strncpy(OPTION_broadcast, broadcast, sizeof(OPTION_broadcast));
|
||||
}
|
||||
}
|
||||
igEndMenu();
|
||||
}
|
||||
|
||||
igEndMenu();
|
||||
}
|
||||
igEndMainMenuBar();
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
LOG_WARNING("bios settings changed, restart to apply");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int bios_invalid_instr(struct bios *bios) {
|
||||
struct dreamcast *dc = bios->dc;
|
||||
struct sh4_context *ctx = &dc->sh4->ctx;
|
||||
|
|
|
@ -19,6 +19,5 @@ struct bios *bios_create(struct dreamcast *dc);
|
|||
void bios_destroy(struct bios *bios);
|
||||
|
||||
int bios_invalid_instr(struct bios *bios);
|
||||
void bios_debug_menu(struct bios *bios);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,7 +37,7 @@ static int controller_input(struct maple_device *dev, int button,
|
|||
struct controller *ctrl = (struct controller *)dev;
|
||||
|
||||
if (button <= CONT_DPAD2_RIGHT) {
|
||||
if (value > 0) {
|
||||
if (value) {
|
||||
ctrl->cnd.buttons &= ~(1 << button);
|
||||
} else {
|
||||
ctrl->cnd.buttons |= (1 << button);
|
||||
|
|
|
@ -6,12 +6,4 @@ struct host;
|
|||
/* audio */
|
||||
void audio_push(struct host *host, const int16_t *data, int frames);
|
||||
|
||||
/* video */
|
||||
int video_can_fullscreen(struct host *host);
|
||||
int video_is_fullscreen(struct host *host);
|
||||
void video_set_fullscreen(struct host *host, int fullscreen);
|
||||
|
||||
/* input */
|
||||
int16_t input_get(struct host *host, int port, int button);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "core/filesystem.h"
|
||||
#include "emulator.h"
|
||||
#include "host/host.h"
|
||||
#include "options.h"
|
||||
#include "render/render_backend.h"
|
||||
|
||||
#define AUDIO_FREQ 44100
|
||||
|
@ -94,19 +95,6 @@ void audio_push(struct host *host, const int16_t *data, int frames) {
|
|||
audio_batch_cb(data, frames);
|
||||
}
|
||||
|
||||
/*
|
||||
* video
|
||||
*/
|
||||
void video_set_fullscreen(struct host *host, int fullscreen) {}
|
||||
|
||||
int video_is_fullscreen(struct host *host) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int video_can_fullscreen(struct host *host) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* input
|
||||
*/
|
||||
|
@ -312,7 +300,7 @@ bool retro_load_game(const struct retro_game_info *info) {
|
|||
return false;
|
||||
}
|
||||
|
||||
return emu_load_game(g_host->emu, info->path);
|
||||
return emu_load(g_host->emu, info->path);
|
||||
}
|
||||
|
||||
bool retro_load_game_special(unsigned game_type,
|
||||
|
|
|
@ -141,6 +141,49 @@ static void audio_write_cb(void *userdata, Uint8 *stream, int len) {
|
|||
host->audio.last_cb = time_nanoseconds();
|
||||
}
|
||||
|
||||
static void audio_destroy_device(struct host *host) {
|
||||
if (!host->audio.dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_CloseAudioDevice(host->audio.dev);
|
||||
host->audio.dev = 0;
|
||||
}
|
||||
|
||||
static int audio_create_device(struct host *host) {
|
||||
/* match AICA output format */
|
||||
SDL_AudioSpec want;
|
||||
SDL_zero(want);
|
||||
want.freq = AUDIO_FREQ;
|
||||
want.format = AUDIO_S16LSB;
|
||||
want.channels = 2;
|
||||
want.samples = MS_TO_AUDIO_FRAMES(OPTION_latency);
|
||||
want.userdata = host;
|
||||
want.callback = audio_write_cb;
|
||||
|
||||
host->audio.dev = SDL_OpenAudioDevice(NULL, 0, &want, &host->audio.spec, 0);
|
||||
if (!host->audio.dev) {
|
||||
LOG_WARNING("audio_create_device failed to open device: %s",
|
||||
SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_INFO("audio_create_device latency=%d ms/%d frames",
|
||||
AUDIO_FRAMES_TO_MS(host->audio.spec.samples),
|
||||
host->audio.spec.samples);
|
||||
|
||||
/* resume device */
|
||||
SDL_PauseAudioDevice(host->audio.dev, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void audio_set_latency(struct host *host, int latency) {
|
||||
audio_destroy_device(host);
|
||||
int res = audio_create_device(host);
|
||||
CHECK(res);
|
||||
}
|
||||
|
||||
void audio_push(struct host *host, const int16_t *data, int num_frames) {
|
||||
if (!host->audio.dev) {
|
||||
return;
|
||||
|
@ -164,34 +207,17 @@ static int audio_init(struct host *host) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* match AICA output format */
|
||||
SDL_AudioSpec want;
|
||||
SDL_zero(want);
|
||||
want.freq = AUDIO_FREQ;
|
||||
want.format = AUDIO_S16LSB;
|
||||
want.channels = 2;
|
||||
want.samples = MS_TO_AUDIO_FRAMES(OPTION_latency);
|
||||
want.userdata = host;
|
||||
want.callback = audio_write_cb;
|
||||
|
||||
host->audio.dev = SDL_OpenAudioDevice(NULL, 0, &want, &host->audio.spec, 0);
|
||||
if (!host->audio.dev) {
|
||||
LOG_WARNING("failed to open SDL audio device: %s", SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create ringbuffer to store data coming in from AICA. note, the buffer needs
|
||||
to be at least two video frames in size, in order to handle the coarse
|
||||
synchronization used by the main loop, where an entire guest video frame is
|
||||
ran when the buffered audio data is deemed low */
|
||||
host->audio.frames = ringbuf_create(AUDIO_FREQ * AUDIO_FRAME_SIZE);
|
||||
|
||||
/* resume device */
|
||||
SDL_PauseAudioDevice(host->audio.dev, 0);
|
||||
|
||||
LOG_INFO("audio_init latency=%d ms/%d frames",
|
||||
AUDIO_FRAMES_TO_MS(host->audio.spec.samples),
|
||||
host->audio.spec.samples);
|
||||
int success = audio_create_device(host);
|
||||
if (!success) {
|
||||
LOG_WARNING("audio_init failed to open audio device: %s", SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -237,22 +263,10 @@ static SDL_GLContext video_create_context(struct host *host) {
|
|||
return ctx;
|
||||
}
|
||||
|
||||
void video_set_fullscreen(struct host *host, int fullscreen) {
|
||||
static void video_set_fullscreen(struct host *host, int fullscreen) {
|
||||
uint32_t flags = fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0;
|
||||
int res = SDL_SetWindowFullscreen(host->win, flags);
|
||||
CHECK_EQ(res, 0);
|
||||
|
||||
/* persist the setting */
|
||||
OPTION_fullscreen = fullscreen;
|
||||
}
|
||||
|
||||
int video_is_fullscreen(struct host *host) {
|
||||
uint32_t flags = SDL_GetWindowFlags(host->win);
|
||||
return flags & SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
int video_can_fullscreen(struct host *host) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void video_shutdown(struct host *host) {
|
||||
|
@ -460,30 +474,43 @@ static int input_find_controller_port(struct host *host, int instance_id) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void input_update_keymap(struct host *host) {
|
||||
memset(host->input.keymap, 0, sizeof(host->input.keymap));
|
||||
|
||||
for (int i = 0; i < NUM_BUTTONS; i++) {
|
||||
struct button_map *btnmap = &BUTTONS[i];
|
||||
|
||||
if (btnmap->key) {
|
||||
host->input.keymap[*btnmap->key] = K_CONT_C + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void input_mousemove(struct host *host, int port, int x, int y) {
|
||||
imgui_mousemove(host->imgui, x, y);
|
||||
}
|
||||
|
||||
static void input_keydown(struct host *host, int port, int key, int16_t value) {
|
||||
int keys[2] = {key, 0};
|
||||
int num_keys = 1;
|
||||
/* send event for both the original key as well as the mapped button, if a
|
||||
mapping is available */
|
||||
int mapping = host->input.keymap[key];
|
||||
|
||||
/* send an extra event for keys that map to a controller button */
|
||||
int button = host->input.keymap[key];
|
||||
if (button) {
|
||||
keys[num_keys++] = button;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_keys; i++) {
|
||||
if (host->emu) {
|
||||
emu_keydown(host->emu, port, keys[i], value);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (key == K_UNKNOWN) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (host->tracer) {
|
||||
tracer_keydown(host->tracer, keys[i], value);
|
||||
if (host->emu && emu_keydown(host->emu, port, key, value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
imgui_keydown(host->imgui, keys[i], value);
|
||||
if (host->tracer && tracer_keydown(host->tracer, key, value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
imgui_keydown(host->imgui, key, value);
|
||||
|
||||
key = mapping;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -528,19 +555,6 @@ static void input_shutdown(struct host *host) {
|
|||
}
|
||||
|
||||
static int input_init(struct host *host) {
|
||||
/* development key map */
|
||||
host->input.keymap[K_SPACE] = K_CONT_START;
|
||||
host->input.keymap['k'] = K_CONT_A;
|
||||
host->input.keymap['l'] = K_CONT_B;
|
||||
host->input.keymap['j'] = K_CONT_X;
|
||||
host->input.keymap['i'] = K_CONT_Y;
|
||||
host->input.keymap['w'] = K_CONT_DPAD_UP;
|
||||
host->input.keymap['s'] = K_CONT_DPAD_DOWN;
|
||||
host->input.keymap['a'] = K_CONT_DPAD_LEFT;
|
||||
host->input.keymap['d'] = K_CONT_DPAD_RIGHT;
|
||||
host->input.keymap['o'] = K_CONT_LTRIG;
|
||||
host->input.keymap['p'] = K_CONT_RTRIG;
|
||||
|
||||
/* SDL won't push events for joysticks which are already connected at init */
|
||||
int num_joysticks = SDL_NumJoysticks();
|
||||
|
||||
|
@ -552,11 +566,9 @@ static int input_init(struct host *host) {
|
|||
input_controller_added(host, device_id);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
input_update_keymap(host);
|
||||
|
||||
void input_poll(struct host *host) {
|
||||
host_poll_events(host);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -718,6 +730,7 @@ static void host_poll_events(struct host *host) {
|
|||
if (ev.window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||
host->video.width = ev.window.data1;
|
||||
host->video.height = ev.window.data2;
|
||||
|
||||
int res = video_restart(host);
|
||||
CHECK(res, "video_restart failed");
|
||||
}
|
||||
|
@ -728,6 +741,37 @@ static void host_poll_events(struct host *host) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for option changes at this time as well */
|
||||
if (OPTION_latency_dirty) {
|
||||
audio_set_latency(host, OPTION_latency);
|
||||
OPTION_latency_dirty = 0;
|
||||
}
|
||||
|
||||
if (OPTION_fullscreen_dirty) {
|
||||
video_set_fullscreen(host, OPTION_fullscreen);
|
||||
OPTION_fullscreen_dirty = 0;
|
||||
}
|
||||
|
||||
/* update reverse button map when optionsc hange */
|
||||
int dirty_map = 0;
|
||||
|
||||
for (int i = 0; i < NUM_BUTTONS; i++) {
|
||||
struct button_map *btnmap = &BUTTONS[i];
|
||||
|
||||
if (!btnmap->desc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*btnmap->dirty) {
|
||||
dirty_map = 1;
|
||||
*btnmap->dirty = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty_map) {
|
||||
input_update_keymap(host);
|
||||
}
|
||||
}
|
||||
|
||||
static int host_init(struct host *host) {
|
||||
|
@ -881,6 +925,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (host->emu) {
|
||||
emu_destroy(host->emu);
|
||||
host->emu = NULL;
|
||||
}
|
||||
|
||||
if (host->tracer) {
|
||||
|
|
|
@ -125,10 +125,10 @@ void imgui_begin_frame(struct imgui *imgui) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void imgui_keydown(struct imgui *imgui, int key, int16_t value) {
|
||||
int imgui_keydown(struct imgui *imgui, int key, int16_t value) {
|
||||
#ifdef HAVE_IMGUI
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
int down = value > 0;
|
||||
int down = !!value;
|
||||
|
||||
if (key == K_MWHEELUP) {
|
||||
io.MouseWheel = 1.0f;
|
||||
|
@ -154,6 +154,7 @@ void imgui_keydown(struct imgui *imgui, int key, int16_t value) {
|
|||
io.KeysDown[key] = down;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void imgui_mousemove(struct imgui *imgui, int x, int y) {
|
||||
|
|
|
@ -19,7 +19,7 @@ void imgui_destroy(struct imgui *imgui);
|
|||
void imgui_vid_created(struct imgui *imgui, struct render_backend *r);
|
||||
void imgui_vid_destroyed(struct imgui *imgui);
|
||||
void imgui_mousemove(struct imgui *imgui, int x, int y);
|
||||
void imgui_keydown(struct imgui *imgui, int key, int16_t value);
|
||||
int imgui_keydown(struct imgui *imgui, int key, int16_t value);
|
||||
|
||||
void imgui_begin_frame(struct imgui *imgui);
|
||||
void imgui_end_frame(struct imgui *imgui);
|
||||
|
|
|
@ -1,9 +1,56 @@
|
|||
#include "options.h"
|
||||
#include "core/core.h"
|
||||
#include "host/keycode.h"
|
||||
|
||||
const int LATENCY_PRESETS[] = {50, 75, 100, 125, 150};
|
||||
const int NUM_LATENCY_PRESETS = ARRAY_SIZE(LATENCY_PRESETS);
|
||||
|
||||
const char *ASPECT_RATIOS[] = {
|
||||
"stretch", "16:9", "4:3",
|
||||
};
|
||||
const int NUM_ASPECT_RATIOS = ARRAY_SIZE(ASPECT_RATIOS);
|
||||
|
||||
struct button_map BUTTONS[] = {
|
||||
{NULL, NULL, NULL}, /* K_CONT_C */
|
||||
{"B button", &OPTION_key_b, &OPTION_key_b_dirty},
|
||||
{"A button", &OPTION_key_a, &OPTION_key_a_dirty},
|
||||
{"Start button", &OPTION_key_start, &OPTION_key_start_dirty},
|
||||
{"DPAD Up", &OPTION_key_dup, &OPTION_key_dup_dirty},
|
||||
{"DPAD Down", &OPTION_key_ddown, &OPTION_key_ddown_dirty},
|
||||
{"DPAD Left", &OPTION_key_dleft, &OPTION_key_dleft_dirty},
|
||||
{"DPAD Right", &OPTION_key_dright, &OPTION_key_dright_dirty},
|
||||
{NULL, NULL, NULL}, /* K_CONT_Z */
|
||||
{"Y button", &OPTION_key_y, &OPTION_key_y_dirty},
|
||||
{"X button", &OPTION_key_x, &OPTION_key_x_dirty},
|
||||
{NULL, NULL, NULL}, /* K_CONT_D */
|
||||
{NULL, NULL, NULL}, /* K_CONT_DPAD2_UP */
|
||||
{NULL, NULL, NULL}, /* K_CONT_DPAD2_DOWN */
|
||||
{NULL, NULL, NULL}, /* K_CONT_DPAD2_LEFT */
|
||||
{NULL, NULL, NULL}, /* K_CONT_DPAD2_RIGHT */
|
||||
{"Joystick X axis", &OPTION_key_joyx, &OPTION_key_joyx_dirty},
|
||||
{"Joystick Y axis", &OPTION_key_joyy, &OPTION_key_joyy_dirty},
|
||||
{"Left trigger", &OPTION_key_ltrig, &OPTION_key_ltrig_dirty},
|
||||
{"Right trigger", &OPTION_key_rtrig, &OPTION_key_rtrig_dirty},
|
||||
};
|
||||
const int NUM_BUTTONS = ARRAY_SIZE(BUTTONS);
|
||||
|
||||
/* host */
|
||||
DEFINE_OPTION_INT(audio, 1, "Enable audio");
|
||||
DEFINE_OPTION_INT(latency, 50, "Preferred audio latency in ms");
|
||||
DEFINE_PERSISTENT_OPTION_INT(latency, 50, "Preferred audio latency in ms");
|
||||
DEFINE_PERSISTENT_OPTION_INT(fullscreen, 0, "Start window fullscreen");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_a, 'k', "A button mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_b, 'l', "B button mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_x, 'j', "X button mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_y, 'i', "Y button mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_start, K_SPACE, "Start button mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_dup, 'w', "DPAD Up mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_ddown, 's', "DPAD Down mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_dleft, 'a', "DPAD Left mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_dright, 'd', "DPAD Right mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_joyx, 0, "Joystick X axis mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_joyy, 0, "Joystick Y axis mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_ltrig, 'o', "Left trigger mapping");
|
||||
DEFINE_PERSISTENT_OPTION_INT(key_rtrig, 'p', "Right trigger mapping");
|
||||
|
||||
/* emulator */
|
||||
DEFINE_PERSISTENT_OPTION_INT(debug, 1, "Show debug menu");
|
||||
|
@ -16,3 +63,6 @@ DEFINE_PERSISTENT_OPTION_STRING(broadcast, "ntsc", "System broadcast mode");
|
|||
|
||||
/* jit */
|
||||
DEFINE_OPTION_INT(perf, 0, "Create maps for compiled code for use with perf");
|
||||
|
||||
/* ui */
|
||||
DEFINE_PERSISTENT_OPTION_STRING(gamedir, "", "Directories to scan for games");
|
||||
|
|
|
@ -2,10 +2,38 @@
|
|||
|
||||
#include "core/option.h"
|
||||
|
||||
struct button_map {
|
||||
const char *desc;
|
||||
int *key;
|
||||
int *dirty;
|
||||
};
|
||||
|
||||
extern const int LATENCY_PRESETS[];
|
||||
extern const int NUM_LATENCY_PRESETS;
|
||||
|
||||
extern const char *ASPECT_RATIOS[];
|
||||
extern const int NUM_ASPECT_RATIOS;
|
||||
|
||||
extern struct button_map BUTTONS[];
|
||||
extern const int NUM_BUTTONS;
|
||||
|
||||
/* host */
|
||||
DECLARE_OPTION_INT(audio);
|
||||
DECLARE_OPTION_INT(latency);
|
||||
DECLARE_OPTION_INT(fullscreen);
|
||||
DECLARE_OPTION_INT(key_a);
|
||||
DECLARE_OPTION_INT(key_b);
|
||||
DECLARE_OPTION_INT(key_x);
|
||||
DECLARE_OPTION_INT(key_y);
|
||||
DECLARE_OPTION_INT(key_start);
|
||||
DECLARE_OPTION_INT(key_dup);
|
||||
DECLARE_OPTION_INT(key_ddown);
|
||||
DECLARE_OPTION_INT(key_dleft);
|
||||
DECLARE_OPTION_INT(key_dright);
|
||||
DECLARE_OPTION_INT(key_joyx);
|
||||
DECLARE_OPTION_INT(key_joyy);
|
||||
DECLARE_OPTION_INT(key_ltrig);
|
||||
DECLARE_OPTION_INT(key_rtrig);
|
||||
|
||||
/* emulator */
|
||||
DECLARE_OPTION_INT(debug);
|
||||
|
@ -19,4 +47,7 @@ DECLARE_OPTION_STRING(broadcast);
|
|||
/* jit */
|
||||
DECLARE_OPTION_INT(perf);
|
||||
|
||||
/* ui */
|
||||
DECLARE_OPTION_STRING(gamedir);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -690,7 +690,7 @@ int tracer_load(struct tracer *tracer, const char *path) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void tracer_keydown(struct tracer *tracer, int key, int16_t value) {
|
||||
int tracer_keydown(struct tracer *tracer, int key, int16_t value) {
|
||||
if (key == K_LEFT && value) {
|
||||
tracer_prev_context(tracer);
|
||||
} else if (key == K_RIGHT && value) {
|
||||
|
@ -700,6 +700,8 @@ void tracer_keydown(struct tracer *tracer, int key, int16_t value) {
|
|||
} else if (key == K_DOWN && value) {
|
||||
tracer_next_param(tracer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tracer_vid_destroyed(struct tracer *tracer) {
|
||||
|
|
|
@ -12,7 +12,7 @@ void tracer_destroy(struct tracer *tracer);
|
|||
|
||||
void tracer_vid_created(struct tracer *tracer, struct render_backend *r);
|
||||
void tracer_vid_destroyed(struct tracer *tracer);
|
||||
void tracer_keydown(struct tracer *tracer, int key, int16_t value);
|
||||
int tracer_keydown(struct tracer *tracer, int key, int16_t value);
|
||||
|
||||
int tracer_load(struct tracer *tracer, const char *path);
|
||||
void tracer_render_frame(struct tracer *tracer);
|
||||
|
|
Loading…
Reference in New Issue