mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-01-12 13:51:27 +00:00
367 lines
7.9 KiB
C
367 lines
7.9 KiB
C
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include <glsym/glsym.h>
|
|
|
|
#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;
|
|
}
|
|
|