From d8e10028f33068ad81a885288fcc95169b3550ad Mon Sep 17 00:00:00 2001 From: Ignacio Sanchez Gines <863613+drhelius@users.noreply.github.com> Date: Thu, 2 Jan 2025 20:47:15 +0100 Subject: [PATCH] [libretro] Basic structure for libretro core --- platforms/libretro/Makefile | 2 +- platforms/libretro/Makefile.common | 4 +- platforms/libretro/libretro.cpp | 553 ++++++++++++++--------------- 3 files changed, 278 insertions(+), 281 deletions(-) diff --git a/platforms/libretro/Makefile b/platforms/libretro/Makefile index 6fdb559..7d9084a 100644 --- a/platforms/libretro/Makefile +++ b/platforms/libretro/Makefile @@ -370,4 +370,4 @@ uninstall: rm $(DESTDIR)$(libdir)/$(LIBRETRO_INSTALL_DIR)/$(TARGET) rm $(DESTDIR)$(libdir)/$(LIBRETRO_INSTALL_DIR)/$(TARGET_NAME).libretro -.PHONY: clean install uninstall +.PHONY: clean install uninstall \ No newline at end of file diff --git a/platforms/libretro/Makefile.common b/platforms/libretro/Makefile.common index c027c2b..2690b7a 100644 --- a/platforms/libretro/Makefile.common +++ b/platforms/libretro/Makefile.common @@ -1,4 +1,4 @@ -SOURCES_C := $(SOURCE_DIR)/miniz/miniz.c \ +SOURCES_C := $(SOURCE_DIR)/miniz/miniz.c SOURCES_CXX := $(CORE_DIR)/libretro.cpp \ $(SOURCE_DIR)/audio.cpp \ @@ -11,4 +11,4 @@ SOURCES_CXX := $(CORE_DIR)/libretro.cpp \ $(SOURCE_DIR)/huc6280_psg.cpp \ $(SOURCE_DIR)/huc6280.cpp \ $(SOURCE_DIR)/input.cpp \ - $(SOURCE_DIR)/memory.cpp \ + $(SOURCE_DIR)/memory.cpp diff --git a/platforms/libretro/libretro.cpp b/platforms/libretro/libretro.cpp index b9b916e..5ac0438 100644 --- a/platforms/libretro/libretro.cpp +++ b/platforms/libretro/libretro.cpp @@ -23,41 +23,47 @@ #include #include #include - -#include #include "libretro.h" - #include "../../src/geargrafx.h" -#ifdef _WIN32 -static const char slash = '\\'; -#else -static const char slash = '/'; -#endif +// #ifdef _WIN32 +// static const char slash = '\\'; +// #else +// static const char slash = '/'; +// #endif -#define MAX_PADS 2 +#define RETRO_DEVICE_PCE_PAD RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0) + +#define MAX_PADS 1 #define JOYPAD_BUTTONS 8 +static retro_environment_t environ_cb; +static retro_video_refresh_t video_cb; +static retro_audio_sample_t audio_cb; +static retro_audio_sample_batch_t audio_batch_cb; +static retro_input_poll_t input_poll_cb; +static retro_input_state_t input_state_cb; + static struct retro_log_callback logging; static retro_log_printf_t log_cb; + static char retro_system_directory[4096]; static char retro_game_path[4096]; -// TODO -static s16 audio_buf[1]; +static s16 audio_buf[GG_AUDIO_BUFFER_SIZE]; static int audio_sample_count = 0; + static int current_screen_width = 0; static int current_screen_height = 0; -static float current_aspect_ratio = 0; -static bool allow_up_down = false; -static bool libretro_supports_bitmasks; +static float current_aspect_ratio = 0.0f; static float aspect_ratio = 0.0f; -static GeargrafxCore* core; -static u8* frame_buffer; +static bool allow_up_down = false; -static int joypad[MAX_PADS][JOYPAD_BUTTONS]; -static int joypre[MAX_PADS][JOYPAD_BUTTONS]; +static bool libretro_supports_bitmasks; +static int joypad_current[MAX_PADS][JOYPAD_BUTTONS]; +static int joypad_old[MAX_PADS][JOYPAD_BUTTONS]; +static unsigned input_device[MAX_PADS]; static GG_Keys keymap[] = { GG_KEY_UP, @@ -70,6 +76,14 @@ static GG_Keys keymap[] = { GG_KEY_RUN }; +static GeargrafxCore* core; +static u8* frame_buffer; + +static void set_controller_info(void); +static void update_input(void); +static void set_variabless(void); +static void check_variables(void); + static void fallback_log(enum retro_log_level level, const char *fmt, ...) { (void)level; @@ -79,14 +93,48 @@ static void fallback_log(enum retro_log_level level, const char *fmt, ...) va_end(va); } -static const struct retro_variable vars[] = { - { "geargrafx_aspect_ratio", "Aspect Ratio (restart); 1:1 PAR|4:3 DAR|16:9 DAR|16:10 DAR" }, - { "geargrafx_up_down_allowed", "Allow Up+Down / Left+Right; Disabled|Enabled" }, - { "geargrafx_no_sprite_limit", "No Sprite Limit; Disabled|Enabled" }, - { NULL } -}; +static int IsButtonPressed(int joypad_bits, int button) +{ + return (joypad_bits & (1 << button)) ? 1 : 0; +} -static retro_environment_t environ_cb; + +unsigned retro_api_version(void) +{ + return RETRO_API_VERSION; +} + +void retro_set_audio_sample(retro_audio_sample_t cb) +{ + audio_cb = cb; +} + +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) +{ + audio_batch_cb = cb; +} + +void retro_set_input_poll(retro_input_poll_t cb) +{ + input_poll_cb = cb; +} + +void retro_set_input_state(retro_input_state_t cb) +{ + input_state_cb = cb; +} + +void retro_set_video_refresh(retro_video_refresh_t cb) +{ + video_cb = cb; +} + +void retro_set_environment(retro_environment_t cb) +{ + environ_cb = cb; + set_controller_info(); + set_variabless(); +} void retro_init(void) { @@ -96,27 +144,29 @@ void retro_init(void) log_cb = fallback_log; const char *dir = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) { + if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) snprintf(retro_system_directory, sizeof(retro_system_directory), "%s", dir); - } - else { + else snprintf(retro_system_directory, sizeof(retro_system_directory), "%s", "."); - } log_cb(RETRO_LOG_INFO, "%s (%s) libretro\n", GG_TITLE, GG_VERSION); core = new GeargrafxCore(); - -#ifdef PS2 - core->Init(GG_PIXEL_BGR555); -#else core->Init(GG_PIXEL_RGB565); -#endif frame_buffer = new u8[HUC6270_MAX_RESOLUTION_WIDTH * HUC6270_MAX_RESOLUTION_HEIGHT * 2]; - audio_sample_count = 0; + for (int i = 0; i < MAX_PADS; i++) + { + for (int j = 0; j < JOYPAD_BUTTONS; j++) + { + joypad_current[i][j] = 0; + joypad_old[i][j] = 0; + } + } + + for (int i = 0; i < MAX_PADS; i++) + input_device[i] = RETRO_DEVICE_PCE_PAD; libretro_supports_bitmasks = environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL); } @@ -127,46 +177,37 @@ void retro_deinit(void) SafeDelete(core); } -unsigned retro_api_version(void) +void retro_reset(void) { - return RETRO_API_VERSION; + log_cb(RETRO_LOG_DEBUG, "Resetting...\n"); + + check_variables(); + core->ResetROM(true); } void retro_set_controller_port_device(unsigned port, unsigned device) { - log_cb(RETRO_LOG_DEBUG, "Plugging device %u into port %u.\n", device, port); - - struct retro_input_descriptor joypad[] = { - - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "I" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "II" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Run" }, - - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "I" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "II" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Run" }, - - { 0, 0, 0, 0, NULL } - }; + if (port >= MAX_PADS) + { + log_cb(RETRO_LOG_DEBUG, "retro_set_controller_port_device invalid port number: %u\n", port); + return; + } - struct retro_input_descriptor desc[] = { - { 0, 0, 0, 0, NULL } - }; + input_device[port] = device; - if (device == RETRO_DEVICE_JOYPAD) - environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, joypad); - else - environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); + switch ( device ) + { + case RETRO_DEVICE_NONE: + log_cb(RETRO_LOG_INFO, "Controller %u: Unplugged\n", port); + break; + case RETRO_DEVICE_PCE_PAD: + case RETRO_DEVICE_JOYPAD: + log_cb(RETRO_LOG_INFO, "Controller %u: PCE Pad\n", port); + break; + default: + log_cb(RETRO_LOG_DEBUG, "Setting descriptors for unsupported device.\n"); + break; + } } void retro_get_system_info(struct retro_system_info *info) @@ -178,12 +219,6 @@ void retro_get_system_info(struct retro_system_info *info) info->valid_extensions = "pce|sgx|bin|rom"; } -static retro_video_refresh_t video_cb; -static retro_audio_sample_t audio_cb; -static retro_audio_sample_batch_t audio_batch_cb; -static retro_input_poll_t input_poll_cb; -static retro_input_state_t input_state_cb; - void retro_get_system_av_info(struct retro_system_av_info *info) { GG_Runtime_Info runtime_info; @@ -201,171 +236,15 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->timing.sample_rate = 44100.0; } -void retro_set_environment(retro_environment_t cb) -{ - environ_cb = cb; - - static const struct retro_controller_description port_1[] = { - { "ColecoVision", RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0) }, - }; - - static const struct retro_controller_description port_2[] = { - { "ColecoVision", RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0) }, - }; - - static const struct retro_controller_info ports[] = { - { port_1, 1 }, - { port_2, 1 }, - { NULL, 0 }, - }; - - environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports); - - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)vars); -} - -void retro_set_audio_sample(retro_audio_sample_t cb) -{ - audio_cb = cb; -} - -void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) -{ - audio_batch_cb = cb; -} - -void retro_set_input_poll(retro_input_poll_t cb) -{ - input_poll_cb = cb; -} - -void retro_set_input_state(retro_input_state_t cb) -{ - input_state_cb = cb; -} - -void retro_set_video_refresh(retro_video_refresh_t cb) -{ - video_cb = cb; -} - -static void update_input(void) -{ - int16_t joypad_bits[MAX_PADS]; - - input_poll_cb(); - - if (libretro_supports_bitmasks) - { - for (int j = 0; j < MAX_PADS; j++) - joypad_bits[j] = input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); - } - else - { - for (int j = 0; j < MAX_PADS; j++) - { - joypad_bits[j] = 0; - for (int i = 0; i < (RETRO_DEVICE_ID_JOYPAD_R3+1); i++) - joypad_bits[j] |= input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, i) ? (1 << i) : 0; - } - } - - // Copy previous state - for (int j = 0; j < MAX_PADS; j++) - { - for (int i = 0; i < JOYPAD_BUTTONS; i++) - joypre[j][i] = joypad[j][i]; - } - - // Get current state - for (int j = 0; j < MAX_PADS; j++) - { - if (allow_up_down) - { - joypad[j][0] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_UP) ? 1 : 0; - joypad[j][1] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN) ? 1 : 0; - joypad[j][2] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT) ? 1 : 0; - joypad[j][3] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT) ? 1 : 0; - } - else - { - joypad[j][0] = (joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_UP)) && ((joypre[j][0] == 1) || !(joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN))) ? 1 : 0; - joypad[j][1] = (joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN)) && ((joypre[j][1] == 1) || !(joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_UP))) ? 1 : 0; - joypad[j][2] = (joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT)) && ((joypre[j][2] == 1) || !(joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT))) ? 1 : 0; - joypad[j][3] = (joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT)) && ((joypre[j][3] == 1) || !(joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT))) ? 1 : 0; - } - joypad[j][4] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_A) ? 1 : 0; - joypad[j][5] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_B) ? 1 : 0; - joypad[j][6] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_SELECT) ? 1 : 0; - joypad[j][7] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_START) ? 1 : 0; - } - - for (int j = 0; j < MAX_PADS; j++) - { - for (int i = 0; i < JOYPAD_BUTTONS; i++) - { - if (joypad[j][i] != joypre[j][i]) - { - if (joypad[j][i] == 1) - core->KeyPressed(static_cast(j), keymap[i]); - else - core->KeyReleased(static_cast(j), keymap[i]); - } - } - } -} - -static void check_variables(void) -{ - struct retro_variable var = {0}; - - var.key = "geargrafx_up_down_allowed"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "Enabled") == 0) - allow_up_down = true; - else - allow_up_down = false; - } - - var.key = "geargrafx_aspect_ratio"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "1:1 PAR") == 0) - aspect_ratio = 0.0f; - else if (strcmp(var.value, "4:3 DAR") == 0) - aspect_ratio = 4.0f / 3.0f; - else if (strcmp(var.value, "16:9 DAR") == 0) - aspect_ratio = 16.0f / 9.0f; - else if (strcmp(var.value, "16:10 DAR") == 0) - aspect_ratio = 16.0f / 10.0f; - else - aspect_ratio = 0.0f; - } - - var.key = "geargrafx_no_sprite_limit"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - core->GetHuC6270()->SetNoSpriteLimit(strcmp(var.value, "Enabled") == 0); - } -} - void retro_run(void) { - bool updated = false; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) - { + bool core_options_updated = false; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &core_options_updated) && core_options_updated) check_variables(); - } update_input(); + audio_sample_count = 0; core->RunToVBlank(frame_buffer, audio_buf, &audio_sample_count); GG_Runtime_Info runtime_info; @@ -393,20 +272,15 @@ void retro_run(void) if (audio_sample_count > 0) audio_batch_cb(audio_buf, audio_sample_count / 2); - - audio_sample_count = 0; -} - -void retro_reset(void) -{ - check_variables(); - core->ResetROM(true); } bool retro_load_game(const struct retro_game_info *info) { check_variables(); + snprintf(retro_game_path, sizeof(retro_game_path), "%s", info->path); + log_cb(RETRO_LOG_INFO, "Loading game: %s\n", retro_game_path); + if (!core->LoadROMFromBuffer(reinterpret_cast(info->data), info->size)) { log_cb(RETRO_LOG_ERROR, "Invalid or corrupted ROM.\n"); @@ -420,37 +294,9 @@ bool retro_load_game(const struct retro_game_info *info) return false; } - snprintf(retro_game_path, sizeof(retro_game_path), "%s", info->path); - - struct retro_memory_descriptor descs[4]; - - memset(descs, 0, sizeof(descs)); - - // TODO - // // BIOS - // descs[0].ptr = core->GetMemory()->GetBios(); - // descs[0].start = 0x0000; - // descs[0].len = 0x2000; - // // EXPANSION - // descs[1].ptr = NULL; - // descs[1].start = 0x2000; - // descs[1].len = 0x4000; - // // RAM - // descs[2].ptr = core->GetMemory()->GetRam(); - // descs[2].start = 0x6000; - // descs[2].len = 0x0400; - // // CART - // descs[3].ptr = core->GetCartridge()->GetROM(); - // descs[3].start = 0x8000; - // descs[3].len = 0x8000; - - struct retro_memory_map mmaps; - mmaps.descriptors = descs; - mmaps.num_descriptors = sizeof(descs) / sizeof(descs[0]); - environ_cb(RETRO_ENVIRONMENT_SET_MEMORY_MAPS, &mmaps); - - bool achievements = true; - environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS, &achievements); + Cartridge* cart = core->GetCartridge(); + log_cb(RETRO_LOG_INFO, "CRC: %08X\n", cart->GetCRC()); + log_cb(RETRO_LOG_INFO, "System: %s\n", cart->IsSGX() ? "Super Grafx" : "PC Engine"); return true; } @@ -465,17 +311,18 @@ unsigned retro_get_region(void) return RETRO_REGION_NTSC; } -bool retro_load_game_special(unsigned type, const struct retro_game_info *info, size_t num) +bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) { + (void)game_type; + (void)info; + (void)num_info; return false; } size_t retro_serialize_size(void) { - size_t size = 0; // TODO - //core->SaveState(NULL, size); - return size; + return 0; } bool retro_serialize(void *data, size_t size) @@ -512,7 +359,7 @@ size_t retro_get_memory_size(unsigned id) case RETRO_MEMORY_SAVE_RAM: return 0; case RETRO_MEMORY_SYSTEM_RAM: - return 0x400; + return 0; } return 0; @@ -527,3 +374,153 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) { // TODO } + +static void set_controller_info(void) +{ + static const struct retro_controller_description port[] = { + { "Joypad Auto", RETRO_DEVICE_JOYPAD }, + { "Joypad Port Empty", RETRO_DEVICE_NONE }, + { "PC engine Pad", RETRO_DEVICE_PCE_PAD } + }; + + static const struct retro_controller_info ports[] = { + { port, 3 }, + { NULL, 0 } + }; + + environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports); + + struct retro_input_descriptor joypad[] = { + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "I" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "II" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Run" }, + + { 0, 0, 0, 0, NULL } + }; + + environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, joypad); +} + +static void update_input(void) +{ + int16_t joypad_bits[MAX_PADS]; + + input_poll_cb(); + + if (libretro_supports_bitmasks) + { + for (int j = 0; j < MAX_PADS; j++) + joypad_bits[j] = input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); + } + else + { + for (int j = 0; j < MAX_PADS; j++) + { + joypad_bits[j] = 0; + for (int i = 0; i < (RETRO_DEVICE_ID_JOYPAD_R3+1); i++) + joypad_bits[j] |= input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, i) ? (1 << i) : 0; + } + } + + // Copy previous state + for (int j = 0; j < MAX_PADS; j++) + { + for (int i = 0; i < JOYPAD_BUTTONS; i++) + joypad_old[j][i] = joypad_current[j][i]; + } + + // Get current state + for (int j = 0; j < MAX_PADS; j++) + { + if (allow_up_down) + { + joypad_current[j][0] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_UP) ? 1 : 0; + joypad_current[j][1] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN) ? 1 : 0; + joypad_current[j][2] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT) ? 1 : 0; + joypad_current[j][3] = joypad_bits[j] & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT) ? 1 : 0; + } + else + { + joypad_current[j][0] = (IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_UP) && IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_DOWN)) ? 1 : 0; + joypad_current[j][1] = (IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_DOWN) && IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_UP)) ? 1 : 0; + joypad_current[j][2] = (IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_LEFT) && IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_RIGHT)) ? 1 : 0; + joypad_current[j][3] = (IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_RIGHT) && IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_LEFT)) ? 1 : 0; + } + joypad_current[j][4] = IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_A); + joypad_current[j][5] = IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_B); + joypad_current[j][6] = IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_SELECT); + joypad_current[j][7] = IsButtonPressed(joypad_bits[j], RETRO_DEVICE_ID_JOYPAD_START); + } + + for (int j = 0; j < MAX_PADS; j++) + { + for (int i = 0; i < JOYPAD_BUTTONS; i++) + { + if (joypad_current[j][i] != joypad_old[j][i]) + { + if (joypad_current[j][i]) + core->KeyPressed(static_cast(j), keymap[i]); + else + core->KeyReleased(static_cast(j), keymap[i]); + } + } + } +} + +static void set_variabless(void) +{ + struct retro_variable vars[] = { + { "geargrafx_aspect_ratio", "Aspect Ratio (restart); 1:1 PAR|4:3 DAR|16:9 DAR|16:10 DAR" }, + { "geargrafx_up_down_allowed", "Allow Up+Down / Left+Right; Disabled|Enabled" }, + { "geargrafx_no_sprite_limit", "No Sprite Limit; Disabled|Enabled" }, + { NULL } + }; + + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)vars); +} + +static void check_variables(void) +{ + struct retro_variable var = {0}; + + var.key = "geargrafx_up_down_allowed"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "Enabled") == 0) + allow_up_down = true; + else + allow_up_down = false; + } + + var.key = "geargrafx_aspect_ratio"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "1:1 PAR") == 0) + aspect_ratio = 0.0f; + else if (strcmp(var.value, "4:3 DAR") == 0) + aspect_ratio = 4.0f / 3.0f; + else if (strcmp(var.value, "16:9 DAR") == 0) + aspect_ratio = 16.0f / 9.0f; + else if (strcmp(var.value, "16:10 DAR") == 0) + aspect_ratio = 16.0f / 10.0f; + else + aspect_ratio = 0.0f; + } + + var.key = "geargrafx_no_sprite_limit"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + core->GetHuC6270()->SetNoSpriteLimit(strcmp(var.value, "Enabled") == 0); + } +}