#include #include #include #include #include #include #include "../../libretro.h" #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) static struct retro_hw_render_callback hw_render; #if defined(HAVE_PSGL) #define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES #define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES #define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT #elif defined(OSX_PPC) #define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT #define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT #define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT #else #define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER #define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE #define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0 #endif #define BASE_WIDTH 320 #define BASE_HEIGHT 240 #ifdef GLES #define MAX_WIDTH 1024 #define MAX_HEIGHT 1024 #else #define MAX_WIDTH 2048 #define MAX_HEIGHT 2048 #endif static unsigned width = BASE_WIDTH; static unsigned height = BASE_HEIGHT; void retro_init(void) {} void retro_deinit(void) {} unsigned retro_api_version(void) { return RETRO_API_VERSION; } void retro_set_controller_port_device(unsigned port, unsigned device) { (void)port; (void)device; } void retro_get_system_info(struct retro_system_info *info) { memset(info, 0, sizeof(*info)); info->library_name = "TestCore GL (FF)"; info->library_version = "v1"; info->need_fullpath = false; info->valid_extensions = NULL; // Anything is fine, we don't care. } void retro_get_system_av_info(struct retro_system_av_info *info) { info->timing = (struct retro_system_timing) { .fps = 60.0, .sample_rate = 30000.0, }; info->geometry = (struct retro_game_geometry) { .base_width = BASE_WIDTH, .base_height = BASE_HEIGHT, .max_width = MAX_WIDTH, .max_height = MAX_HEIGHT, .aspect_ratio = 4.0 / 3.0, }; } 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_environment_t environ_cb; static retro_input_poll_t input_poll_cb; static retro_input_state_t input_state_cb; void retro_set_environment(retro_environment_t cb) { environ_cb = cb; struct retro_variable variables[] = { { "testgl_resolution", #ifdef GLES "Internal resolution; 320x240|360x480|480x272|512x384|512x512|640x240|640x448|640x480|720x576|800x600|960x720|1024x768", #else "Internal resolution; 320x240|360x480|480x272|512x384|512x512|640x240|640x448|640x480|720x576|800x600|960x720|1024x768|1024x1024|1280x720|1280x960|1600x1200|1920x1080|1920x1440|1920x1600|2048x2048", #endif }, #ifdef CORE { "testgl_multisample", "Multisampling; 1x|2x|4x" }, #endif { NULL, NULL }, }; bool no_rom = true; cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_rom); cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); } 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_variables(void) { struct retro_variable var = { .key = "testgl_resolution", }; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { char *pch; char str[100]; snprintf(str, sizeof(str), "%s", var.value); pch = strtok(str, "x"); if (pch) width = strtoul(pch, NULL, 0); pch = strtok(NULL, "x"); if (pch) height = strtoul(pch, NULL, 0); fprintf(stderr, "[libretro-test]: Got size: %u x %u.\n", width, height); } #ifdef CORE var.key = "testgl_multisample"; var.value = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { switch (*var.value) { case '1': init_multisample(1); break; case '2': init_multisample(2); break; case '4': init_multisample(4); break; } } #endif } static unsigned frame_count; void retro_run(void) { bool updated = false; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) update_variables(); input_poll_cb(); if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)) { } float ratio = width / (float)height; glBindFramebuffer(RARCH_GL_FRAMEBUFFER, hw_render.get_current_framebuffer()); glClearColor(0.3, 0.4, 0.5, 1.0); glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef((float)frame_count * 2, 0.0f, 0.0f, 0.1f); glLoadIdentity(); glBegin(GL_TRIANGLES); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glVertex2f(-0.5f, -0.5f); glColor4f(1.0f, 1.0f, 0.0f, 1.0f); glVertex2f(0.5f, -0.5f); glColor4f(0.0f, 1.0f, 1.0f, 1.0f); glVertex2f(-0.5f, 0.5f); glColor4f(1.0f, 0.0f, 1.0f, 1.0f); glVertex2f(0.5f, 0.5f); glEnd(); frame_count++; video_cb(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0); } static void context_reset(void) { fprintf(stderr, "Context reset!\n"); rglgen_resolve_symbols(hw_render.get_proc_address); } static void context_destroy(void) { fprintf(stderr, "Context destroy!\n"); } #ifdef GLES static bool retro_init_hw_context(void) { #if defined(GLES31) hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES_VERSION; hw_render.version_major = 3; hw_render.version_minor = 1; #elif defined(GLES3) hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES3; #else hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES2; #endif hw_render.context_reset = context_reset; hw_render.context_destroy = context_destroy; hw_render.depth = true; hw_render.bottom_left_origin = true; if (!environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) return false; return true; } #else static bool retro_init_hw_context(void) { hw_render.context_type = RETRO_HW_CONTEXT_OPENGL; hw_render.context_reset = context_reset; hw_render.context_destroy = context_destroy; hw_render.depth = true; hw_render.bottom_left_origin = true; if (!environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) return false; return true; } #endif bool retro_load_game(const struct retro_game_info *info) { update_variables(); enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888; if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { fprintf(stderr, "XRGB8888 is not supported.\n"); return false; } if (!retro_init_hw_context()) { fprintf(stderr, "HW Context could not be initialized, exiting...\n"); return false; } fprintf(stderr, "Loaded game!\n"); (void)info; return true; } void retro_unload_game(void) {} 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) { (void)type; (void)info; (void)num; return false; } size_t retro_serialize_size(void) { return 0; } bool retro_serialize(void *data, size_t size) { (void)data; (void)size; return false; } bool retro_unserialize(const void *data, size_t size) { (void)data; (void)size; return false; } void *retro_get_memory_data(unsigned id) { (void)id; return NULL; } size_t retro_get_memory_size(unsigned id) { (void)id; return 0; } void retro_reset(void) {} void retro_cheat_reset(void) {} void retro_cheat_set(unsigned index, bool enabled, const char *code) { (void)index; (void)enabled; (void)code; }