static bool gfx_ctx_init(void) { struct android_app *android_app = (struct android_app*)g_android; const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; EGLint num_config; EGLint egl_version_major, egl_version_minor; EGLint format; EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; RARCH_LOG("Initializing context\n"); if ((g_egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) { RARCH_ERR("eglGetDisplay failed.\n"); goto error; } if (!eglInitialize(g_egl_dpy, &egl_version_major, &egl_version_minor)) { RARCH_ERR("eglInitialize failed.\n"); goto error; } RARCH_LOG("[ANDROID/EGL]: EGL version: %d.%d\n", egl_version_major, egl_version_minor); if (!eglChooseConfig(g_egl_dpy, attribs, &g_config, 1, &num_config)) { RARCH_ERR("eglChooseConfig failed.\n"); goto error; } int var = eglGetConfigAttrib(g_egl_dpy, g_config, EGL_NATIVE_VISUAL_ID, &format); if (!var) { RARCH_ERR("eglGetConfigAttrib failed: %d.\n", var); goto error; } ANativeWindow_setBuffersGeometry(android_app->window, 0, 0, format); if (!(g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, android_app->window, 0))) { RARCH_ERR("eglCreateWindowSurface failed.\n"); goto error; } if (!(g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, 0, context_attributes))) { RARCH_ERR("eglCreateContext failed.\n"); goto error; } if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx)) { RARCH_ERR("eglMakeCurrent failed.\n"); goto error; } ALooper *looper = ALooper_forThread(); if (!looper) ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); return true; error: RARCH_ERR("EGL error: %d.\n", eglGetError()); gfx_ctx_destroy(); return false; }
static void *gdi_gfx_init(const video_info_t *video, const input_driver_t **input, void **input_data) { unsigned full_x, full_y; gfx_ctx_input_t inp; gfx_ctx_mode_t mode; const gfx_ctx_driver_t *ctx_driver = NULL; unsigned win_width = 0, win_height = 0; unsigned temp_width = 0, temp_height = 0; settings_t *settings = config_get_ptr(); gdi_t *gdi = (gdi_t*)calloc(1, sizeof(*gdi)); *input = NULL; *input_data = NULL; gdi_video_width = video->width; gdi_video_height = video->height; gdi_rgb32 = video->rgb32; gdi_video_bits = video->rgb32 ? 32 : 16; if (video->rgb32) gdi_video_pitch = video->width * 4; else gdi_video_pitch = video->width * 2; gdi_gfx_create(); ctx_driver = video_context_driver_init_first(gdi, settings->video.context_driver, GFX_CTX_GDI_API, 1, 0, false); if (!ctx_driver) goto error; video_context_driver_set((const gfx_ctx_driver_t*)ctx_driver); RARCH_LOG("Found GDI context: %s\n", ctx_driver->ident); video_context_driver_get_video_size(&mode); full_x = mode.width; full_y = mode.height; mode.width = 0; mode.height = 0; RARCH_LOG("Detecting screen resolution %ux%u.\n", full_x, full_y); win_width = video->width; win_height = video->height; if (video->fullscreen && (win_width == 0) && (win_height == 0)) { win_width = full_x; win_height = full_y; } mode.width = win_width; mode.height = win_height; mode.fullscreen = video->fullscreen; if (!video_context_driver_set_video_mode(&mode)) goto error; mode.width = 0; mode.height = 0; video_context_driver_get_video_size(&mode); temp_width = mode.width; temp_height = mode.height; mode.width = 0; mode.height = 0; /* Get real known video size, which might have been altered by context. */ if (temp_width != 0 && temp_height != 0) video_driver_set_size(&temp_width, &temp_height); video_driver_get_size(&temp_width, &temp_height); RARCH_LOG("GDI: Using resolution %ux%u\n", temp_width, temp_height); inp.input = input; inp.input_data = input_data; video_context_driver_input_driver(&inp); if (settings->video.font_enable) font_driver_init_osd(NULL, false, FONT_DRIVER_RENDER_GDI); RARCH_LOG("[GDI]: Init complete.\n"); return gdi; error: video_context_driver_destroy(); if (gdi) free(gdi); return NULL; }
/** * recording_init: * * Initializes recording. * * Returns: true (1) if successful, otherwise false (0). **/ bool recording_init(void) { char recording_file[PATH_MAX_LENGTH] = {0}; struct ffemu_params params = {0}; global_t *global = global_get_ptr(); driver_t *driver = driver_get_ptr(); settings_t *settings = config_get_ptr(); struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); const struct retro_hw_render_callback *hw_render = (const struct retro_hw_render_callback*)video_driver_callback(); bool *recording_enabled = recording_is_enabled(); if (!*recording_enabled) return false; if (global->inited.core.type == CORE_TYPE_DUMMY) { RARCH_WARN("%s\n", msg_hash_to_str(MSG_USING_LIBRETRO_DUMMY_CORE_RECORDING_SKIPPED)); return false; } if (!settings->video.gpu_record && hw_render->context_type) { RARCH_WARN("%s.\n", msg_hash_to_str(MSG_HW_RENDERED_MUST_USE_POSTSHADED_RECORDING)); return false; } RARCH_LOG("%s: FPS: %.4f, Sample rate: %.4f\n", msg_hash_to_str(MSG_CUSTOM_TIMING_GIVEN), (float)av_info->timing.fps, (float)av_info->timing.sample_rate); strlcpy(recording_file, global->record.path, sizeof(recording_file)); if (global->record.use_output_dir) fill_pathname_join(recording_file, global->record.output_dir, global->record.path, sizeof(recording_file)); params.out_width = av_info->geometry.base_width; params.out_height = av_info->geometry.base_height; params.fb_width = av_info->geometry.max_width; params.fb_height = av_info->geometry.max_height; params.channels = 2; params.filename = recording_file; params.fps = av_info->timing.fps; params.samplerate = av_info->timing.sample_rate; params.pix_fmt = (video_driver_get_pixel_format() == RETRO_PIXEL_FORMAT_XRGB8888) ? FFEMU_PIX_ARGB8888 : FFEMU_PIX_RGB565; params.config = NULL; if (*global->record.config) params.config = global->record.config; if (settings->video.gpu_record && driver->video->read_viewport) { struct video_viewport vp = {0}; video_driver_viewport_info(&vp); if (!vp.width || !vp.height) { RARCH_ERR("Failed to get viewport information from video driver. " "Cannot start recording ...\n"); return false; } params.out_width = vp.width; params.out_height = vp.height; params.fb_width = next_pow2(vp.width); params.fb_height = next_pow2(vp.height); if (settings->video.force_aspect && (video_driver_get_aspect_ratio() > 0.0f)) params.aspect_ratio = video_driver_get_aspect_ratio(); else params.aspect_ratio = (float)vp.width / vp.height; params.pix_fmt = FFEMU_PIX_BGR24; global->record.gpu_width = vp.width; global->record.gpu_height = vp.height; RARCH_LOG("%s %u x %u\n", msg_hash_to_str(MSG_DETECTED_VIEWPORT_OF), vp.width, vp.height); global->record.gpu_buffer = (uint8_t*)malloc(vp.width * vp.height * 3); if (!global->record.gpu_buffer) return false; } else { if (global->record.width || global->record.height) { params.out_width = global->record.width; params.out_height = global->record.height; } if (settings->video.force_aspect && (video_driver_get_aspect_ratio() > 0.0f)) params.aspect_ratio = video_driver_get_aspect_ratio(); else params.aspect_ratio = (float)params.out_width / params.out_height; if (settings->video.post_filter_record && video_driver_frame_filter_alive()) { unsigned max_width = 0; unsigned max_height = 0; if (video_driver_frame_filter_is_32bit()) params.pix_fmt = FFEMU_PIX_ARGB8888; else params.pix_fmt = FFEMU_PIX_RGB565; rarch_softfilter_get_max_output_size( video_driver_frame_filter_get_ptr(), &max_width, &max_height); params.fb_width = next_pow2(max_width); params.fb_height = next_pow2(max_height); } } RARCH_LOG("%s %s @ %ux%u. (FB size: %ux%u pix_fmt: %u)\n", msg_hash_to_str(MSG_RECORDING_TO), global->record.path, params.out_width, params.out_height, params.fb_width, params.fb_height, (unsigned)params.pix_fmt); if (!record_driver_init_first(&driver->recording, &driver->recording_data, ¶ms)) { RARCH_ERR("%s\n", msg_hash_to_str(MSG_FAILED_TO_START_RECORDING)); event_command(EVENT_CMD_GPU_RECORD_DEINIT); return false; } return true; }
static unsigned get_xml_shaders(const char *path, struct shader_program *prog, size_t size) { LIBXML_TEST_VERSION; xmlParserCtxtPtr ctx = xmlNewParserCtxt(); if (!ctx) { RARCH_ERR("Failed to load libxml2 context.\n"); return false; } RARCH_LOG("Loading XML shader: %s\n", path); xmlDocPtr doc = xmlCtxtReadFile(ctx, path, NULL, 0); xmlNodePtr head = NULL; xmlNodePtr cur = NULL; unsigned num = 0; if (!doc) { RARCH_ERR("Failed to parse XML file: %s\n", path); goto error; } if (ctx->valid == 0) { RARCH_ERR("Cannot validate XML shader: %s\n", path); goto error; } head = xmlDocGetRootElement(doc); for (cur = head; cur; cur = cur->next) { if (cur->type != XML_ELEMENT_NODE) continue; if (strcmp((const char*)cur->name, "shader") != 0) continue; char attr[64]; xml_get_prop(attr, sizeof(attr), cur, "language"); if (strcmp(attr, "GLSL") != 0) continue; xml_get_prop(attr, sizeof(attr), cur, "style"); glsl_modern = strcmp(attr, "GLES2") == 0; if (glsl_modern) RARCH_LOG("[GL]: Shader reports a GLES2 style shader.\n"); break; } if (!cur) // We couldn't find any GLSL shader :( goto error; memset(prog, 0, sizeof(struct shader_program) * size); // Iterate to check if we find fragment and/or vertex shaders. for (cur = cur->children; cur && num < size; cur = cur->next) { if (cur->type != XML_ELEMENT_NODE) continue; char *content = xml_get_content(cur); if (!content) continue; if (strcmp((const char*)cur->name, "vertex") == 0) { if (prog[num].vertex) { RARCH_ERR("Cannot have more than one vertex shader in a program.\n"); free(content); goto error; } content = xml_replace_if_file(content, path, cur, "src"); if (!content) { RARCH_ERR("Shader source file was provided, but failed to read.\n"); goto error; } prog[num].vertex = content; } else if (strcmp((const char*)cur->name, "fragment") == 0) { if (glsl_modern && !prog[num].vertex) { RARCH_ERR("Modern GLSL was chosen and vertex shader was not provided. This is an error.\n"); free(content); goto error; } content = xml_replace_if_file(content, path, cur, "src"); if (!content) { RARCH_ERR("Shader source file was provided, but failed to read.\n"); goto error; } prog[num].fragment = content; if (!get_xml_attrs(&prog[num], cur)) { RARCH_ERR("XML shader attributes do not comply with specifications.\n"); goto error; } num++; } else if (strcmp((const char*)cur->name, "texture") == 0) { free(content); if (!get_texture_image(path, cur)) { RARCH_ERR("Texture image failed to load.\n"); goto error; } } else if (strcmp((const char*)cur->name, "import") == 0) { free(content); if (!get_import_value(cur)) { RARCH_ERR("Import value is invalid.\n"); goto error; } } #ifdef HAVE_PYTHON else if (strcmp((const char*)cur->name, "script") == 0) { free(content); if (!get_script(path, cur)) { RARCH_ERR("Script is invalid.\n"); goto error; } } #endif } if (num == 0) { RARCH_ERR("Couldn't find vertex shader nor fragment shader in XML file.\n"); goto error; } xmlFreeDoc(doc); xmlFreeParserCtxt(ctx); return num; error: RARCH_ERR("Failed to load XML shader ...\n"); if (doc) xmlFreeDoc(doc); xmlFreeParserCtxt(ctx); return 0; }
static void *xdk_d3d_init(const video_info_t *video, const input_driver_t **input, void **input_data) { HRESULT ret; if (driver.video_data) { xdk_d3d_video_t *d3d = (xdk_d3d_video_t*)driver.video_data; // Reinitialize textures as we might have changed pixel formats. xdk_d3d_reinit_textures(d3d, video); return driver.video_data; } //we'll just use driver.video_data throughout here because it needs to //exist when we delegate initing to the context file driver.video_data = (xdk_d3d_video_t*)calloc(1, sizeof(xdk_d3d_video_t)); if (!driver.video_data) return NULL; xdk_d3d_video_t *d3d = (xdk_d3d_video_t*)driver.video_data; d3d->vsync = video->vsync; d3d->tex_w = RARCH_SCALE_BASE * video->input_scale; d3d->tex_h = RARCH_SCALE_BASE * video->input_scale; #if defined(_XBOX1) d3d->ctx_driver = gfx_ctx_init_first(GFX_CTX_DIRECT3D8_API, 8, 0); #elif defined(_XBOX360) d3d->ctx_driver = gfx_ctx_init_first(GFX_CTX_DIRECT3D9_API, 9, 0); #endif if (d3d->ctx_driver) { D3DPRESENT_PARAMETERS d3dpp; xdk_d3d_generate_pp(&d3dpp, video); ret = d3d->d3d_device->CreateDevice(0, D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3d->d3d_render_device); if (ret != S_OK) RARCH_ERR("Failed at CreateDevice.\n"); RD3DDevice_Clear(d3d->d3d_render_device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0); } else { free(d3d); return NULL; } RARCH_LOG("Found D3D context: %s\n", d3d->ctx_driver->ident); xdk_d3d_init_textures(d3d, video); #if defined(_XBOX1) // use an orthogonal matrix for the projection matrix D3DXMATRIX mat; D3DXMatrixOrthoOffCenterLH(&mat, 0, d3d->win_width , d3d->win_height , 0, 0.0f, 1.0f); d3d->d3d_render_device->SetTransform(D3DTS_PROJECTION, &mat); // use an identity matrix for the world and view matrices D3DXMatrixIdentity(&mat); d3d->d3d_render_device->SetTransform(D3DTS_WORLD, &mat); d3d->d3d_render_device->SetTransform(D3DTS_VIEW, &mat); ret = d3d->d3d_render_device->CreateVertexBuffer(4 * sizeof(DrawVerticeFormats), D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_MANAGED, &d3d->vertex_buf); if (ret != S_OK) { RARCH_ERR("[xdk_d3d_init::] Failed at CreateVertexBuffer.\n"); return NULL; } const DrawVerticeFormats init_verts[] = { { -1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, { -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, }; BYTE *verts_ptr; RD3DVertexBuffer_Lock(d3d->vertex_buf, 0, 0, &verts_ptr, 0); memcpy(verts_ptr, init_verts, sizeof(init_verts)); RD3DVertexBuffer_Unlock(d3d->vertex_buf); RD3DDevice_SetVertexShader(d3d->d3d_render_device, D3DFVF_XYZ | D3DFVF_TEX1); #elif defined(_XBOX360) ret = d3d->d3d_render_device->CreateVertexBuffer(4 * sizeof(DrawVerticeFormats), 0, 0, 0, &d3d->vertex_buf, NULL); if (ret != S_OK) { RARCH_ERR("[xdk_d3d_init::] Failed at CreateVertexBuffer.\n"); return NULL; } static const DrawVerticeFormats init_verts[] = { { -1.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, -1.0f, 1.0f, 1.0f }, { -1.0f, 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 0.0f }, }; void *verts_ptr; RD3DVertexBuffer_Lock(d3d->vertex_buf, 0, 0, &verts_ptr, 0); memcpy(verts_ptr, init_verts, sizeof(init_verts)); RD3DVertexBuffer_Unlock(d3d->vertex_buf); static const D3DVERTEXELEMENT VertexElements[] = { { 0, 0 * sizeof(float), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 2 * sizeof(float), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() }; ret = d3d->d3d_render_device->CreateVertexDeclaration(VertexElements, &d3d->v_decl); if (ret != S_OK) { RARCH_ERR("[xdk_d3d_init::] Failed at CreateVertexDeclaration.\n"); } #endif d3d->ctx_driver->get_video_size(&d3d->win_width, &d3d->win_height); RARCH_LOG("Detecting screen resolution: %ux%u.\n", d3d->win_width, d3d->win_height); d3d->ctx_driver->swap_interval(d3d->vsync ? 1 : 0); #ifdef HAVE_HLSL if (!hlsl_shader_init()) { RARCH_ERR("Shader init failed.\n"); d3d->ctx_driver->destroy(); free(d3d); return NULL; } RARCH_LOG("D3D: Loaded %u program(s).\n", d3d->shader->num_shaders()); #endif #if 0 /* ifdef HAVE_FBO */ xdk_d3d_init_fbo(d3d); #endif xdk_d3d_set_rotation(d3d, g_extern.console.screen.orientation); //really returns driver.video_data to driver.video_data - see comment above return d3d; }
static bool environment_cb(unsigned cmd, void *data) { switch (cmd) { case RETRO_ENVIRONMENT_GET_OVERSCAN: *(bool*)data = !g_settings.video.crop_overscan; RARCH_LOG("Environ GET_OVERSCAN: %u\n", (unsigned)!g_settings.video.crop_overscan); break; case RETRO_ENVIRONMENT_GET_CAN_DUPE: *(bool*)data = true; RARCH_LOG("Environ GET_CAN_DUPE: true\n"); break; case RETRO_ENVIRONMENT_GET_VARIABLE: { struct retro_variable *var = (struct retro_variable*)data; RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key); if (g_extern.system.core_options) core_option_get(g_extern.system.core_options, var); else var->value = NULL; RARCH_LOG("\t%s\n", var->value ? var->value : "N/A"); break; } case RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE: *(bool*)data = g_extern.system.core_options ? core_option_updated(g_extern.system.core_options) : false; break; case RETRO_ENVIRONMENT_SET_VARIABLES: { RARCH_LOG("Environ SET_VARIABLES.\n"); if (g_extern.system.core_options) { core_option_flush(g_extern.system.core_options); core_option_free(g_extern.system.core_options); } const struct retro_variable *vars = (const struct retro_variable*)data; const char *options_path = g_settings.core_options_path; char buf[PATH_MAX]; if (!*options_path && *g_extern.config_path) { fill_pathname_resolve_relative(buf, g_extern.config_path, ".retroarch-core-options.cfg", sizeof(buf)); options_path = buf; } g_extern.system.core_options = core_option_new(options_path, vars); break; } case RETRO_ENVIRONMENT_SET_MESSAGE: { const struct retro_message *msg = (const struct retro_message*)data; RARCH_LOG("Environ SET_MESSAGE: %s\n", msg->msg); if (g_extern.msg_queue) msg_queue_push(g_extern.msg_queue, msg->msg, 1, msg->frames); break; } case RETRO_ENVIRONMENT_SET_ROTATION: { unsigned rotation = *(const unsigned*)data; RARCH_LOG("Environ SET_ROTATION: %u\n", rotation); if (!g_settings.video.allow_rotate) break; g_extern.system.rotation = rotation; if (driver.video && driver.video->set_rotation) { if (driver.video_data) video_set_rotation_func(rotation); } else return false; break; } case RETRO_ENVIRONMENT_SHUTDOWN: RARCH_LOG("Environ SHUTDOWN.\n"); g_extern.system.shutdown = true; break; case RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL: g_extern.system.performance_level = *(const unsigned*)data; RARCH_LOG("Environ PERFORMANCE_LEVEL: %u.\n", g_extern.system.performance_level); break; case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY: *(const char **)data = *g_settings.system_directory ? g_settings.system_directory : NULL; RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n", g_settings.system_directory); break; case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT: { enum retro_pixel_format pix_fmt = *(const enum retro_pixel_format*)data; switch (pix_fmt) { case RETRO_PIXEL_FORMAT_0RGB1555: RARCH_LOG("Environ SET_PIXEL_FORMAT: 0RGB1555.\n"); break; case RETRO_PIXEL_FORMAT_RGB565: RARCH_LOG("Environ SET_PIXEL_FORMAT: RGB565.\n"); break; case RETRO_PIXEL_FORMAT_XRGB8888: RARCH_LOG("Environ SET_PIXEL_FORMAT: XRGB8888.\n"); break; default: return false; } g_extern.system.pix_fmt = pix_fmt; break; } case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS: { memset(g_extern.system.input_desc_btn, 0, sizeof(g_extern.system.input_desc_btn)); const struct retro_input_descriptor *desc = (const struct retro_input_descriptor*)data; for (; desc->description; desc++) { if (desc->port >= MAX_PLAYERS) continue; if (desc->device != RETRO_DEVICE_JOYPAD) // Ignore all others for now. continue; if (desc->id >= RARCH_FIRST_CUSTOM_BIND) continue; g_extern.system.input_desc_btn[desc->port][desc->id] = desc->description; } static const char *libretro_btn_desc[] = { "B (bottom)", "Y (left)", "Select", "Start", "D-Pad Up", "D-Pad Down", "D-Pad Left", "D-Pad Right", "A (right)", "X (up)", "L", "R", "L2", "R2", "L3", "R3", }; RARCH_LOG("Environ SET_INPUT_DESCRIPTORS:\n"); for (unsigned p = 0; p < MAX_PLAYERS; p++) { for (unsigned id = 0; id < RARCH_FIRST_CUSTOM_BIND; id++) { const char *desc = g_extern.system.input_desc_btn[p][id]; if (desc) { RARCH_LOG("\tRetroPad, Player %u, Button \"%s\" => \"%s\"\n", p + 1, libretro_btn_desc[id], desc); } } } break; } case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK: { RARCH_LOG("Environ SET_KEYBOARD_CALLBACK.\n"); const struct retro_keyboard_callback *info = (const struct retro_keyboard_callback*)data; g_extern.system.key_event = info->callback; break; } case RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE: RARCH_LOG("Environ SET_DISK_CONTROL_INTERFACE.\n"); g_extern.system.disk_control = *(const struct retro_disk_control_callback*)data; break; case RETRO_ENVIRONMENT_SET_HW_RENDER: { RARCH_LOG("Environ SET_HW_RENDER.\n"); struct retro_hw_render_callback *cb = (struct retro_hw_render_callback*)data; switch (cb->context_type) { case RETRO_HW_CONTEXT_NONE: RARCH_LOG("Requesting no HW context.\n"); break; #if defined(HAVE_OPENGLES2) case RETRO_HW_CONTEXT_OPENGLES2: RARCH_LOG("Requesting OpenGLES2 context.\n"); driver.video = &video_gl; break; case RETRO_HW_CONTEXT_OPENGL: RARCH_ERR("Requesting OpenGL context, but RetroArch is compiled against OpenGLES2. Cannot use HW context.\n"); return false; #elif defined(HAVE_OPENGL) case RETRO_HW_CONTEXT_OPENGLES2: RARCH_ERR("Requesting OpenGLES2 context, but RetroArch is compiled against OpenGL. Cannot use HW context.\n"); return false; case RETRO_HW_CONTEXT_OPENGL: RARCH_LOG("Requesting OpenGL context.\n"); driver.video = &video_gl; break; #endif default: RARCH_LOG("Requesting unknown context.\n"); return false; } cb->get_current_framebuffer = driver_get_current_framebuffer; cb->get_proc_address = driver_get_proc_address; memcpy(&g_extern.system.hw_render_callback, cb, sizeof(*cb)); break; } case RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME: { bool state = *(const bool*)data; RARCH_LOG("Environ SET_SUPPORT_NO_GAME: %s.\n", state ? "yes" : "no"); g_extern.system.no_game = state; break; } default: RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd); return false; } return true; }
static bool get_xml_attrs(struct shader_program *prog, xmlNodePtr ptr) { prog->scale_x = 1.0; prog->scale_y = 1.0; prog->type_x = prog->type_y = RARCH_SCALE_INPUT; prog->valid_scale = false; // Check if shader forces a certain texture filtering. char attr[64]; if (xml_get_prop(attr, sizeof(attr), ptr, "filter")) { if (strcmp(attr, "nearest") == 0) { prog->filter = RARCH_GL_NEAREST; RARCH_LOG("XML: Shader forces GL_NEAREST.\n"); } else if (strcmp(attr, "linear") == 0) { prog->filter = RARCH_GL_LINEAR; RARCH_LOG("XML: Shader forces GL_LINEAR.\n"); } else RARCH_WARN("XML: Invalid property for filter.\n"); } else prog->filter = RARCH_GL_NOFORCE; // Check for scaling attributes *lots of code <_<* char attr_scale[64], attr_scale_x[64], attr_scale_y[64]; char attr_size[64], attr_size_x[64], attr_size_y[64]; char attr_outscale[64], attr_outscale_x[64], attr_outscale_y[64]; xml_get_prop(attr_scale, sizeof(attr_scale), ptr, "scale"); xml_get_prop(attr_scale_x, sizeof(attr_scale_x), ptr, "scale_x"); xml_get_prop(attr_scale_y, sizeof(attr_scale_y), ptr, "scale_y"); xml_get_prop(attr_size, sizeof(attr_size), ptr, "size"); xml_get_prop(attr_size_x, sizeof(attr_size_x), ptr, "size_x"); xml_get_prop(attr_size_y, sizeof(attr_size_y), ptr, "size_y"); xml_get_prop(attr_outscale, sizeof(attr_outscale), ptr, "outscale"); xml_get_prop(attr_outscale_x, sizeof(attr_outscale_x), ptr, "outscale_x"); xml_get_prop(attr_outscale_y, sizeof(attr_outscale_y), ptr, "outscale_y"); unsigned x_attr_cnt = 0, y_attr_cnt = 0; if (*attr_scale) { float scale = strtod(attr_scale, NULL); prog->scale_x = scale; prog->scale_y = scale; prog->valid_scale = true; prog->type_x = prog->type_y = RARCH_SCALE_INPUT; RARCH_LOG("Got scale attr: %.1f\n", scale); x_attr_cnt++; y_attr_cnt++; } if (*attr_scale_x) { float scale = strtod(attr_scale_x, NULL); prog->scale_x = scale; prog->valid_scale = true; prog->type_x = RARCH_SCALE_INPUT; RARCH_LOG("Got scale_x attr: %.1f\n", scale); x_attr_cnt++; } if (*attr_scale_y) { float scale = strtod(attr_scale_y, NULL); prog->scale_y = scale; prog->valid_scale = true; prog->type_y = RARCH_SCALE_INPUT; RARCH_LOG("Got scale_y attr: %.1f\n", scale); y_attr_cnt++; } if (*attr_size) { prog->abs_x = prog->abs_y = strtoul(attr_size, NULL, 0); prog->valid_scale = true; prog->type_x = prog->type_y = RARCH_SCALE_ABSOLUTE; RARCH_LOG("Got size attr: %u\n", prog->abs_x); x_attr_cnt++; y_attr_cnt++; } if (*attr_size_x) { prog->abs_x = strtoul(attr_size_x, NULL, 0); prog->valid_scale = true; prog->type_x = RARCH_SCALE_ABSOLUTE; RARCH_LOG("Got size_x attr: %u\n", prog->abs_x); x_attr_cnt++; } if (*attr_size_y) { prog->abs_y = strtoul(attr_size_y, NULL, 0); prog->valid_scale = true; prog->type_y = RARCH_SCALE_ABSOLUTE; RARCH_LOG("Got size_y attr: %u\n", prog->abs_y); y_attr_cnt++; } if (*attr_outscale) { float scale = strtod(attr_outscale, NULL); prog->scale_x = scale; prog->scale_y = scale; prog->valid_scale = true; prog->type_x = prog->type_y = RARCH_SCALE_VIEWPORT; RARCH_LOG("Got outscale attr: %.1f\n", scale); x_attr_cnt++; y_attr_cnt++; } if (*attr_outscale_x) { float scale = strtod(attr_outscale_x, NULL); prog->scale_x = scale; prog->valid_scale = true; prog->type_x = RARCH_SCALE_VIEWPORT; RARCH_LOG("Got outscale_x attr: %.1f\n", scale); x_attr_cnt++; } if (*attr_outscale_y) { float scale = strtod(attr_outscale_y, NULL); prog->scale_y = scale; prog->valid_scale = true; prog->type_y = RARCH_SCALE_VIEWPORT; RARCH_LOG("Got outscale_y attr: %.1f\n", scale); y_attr_cnt++; } if (x_attr_cnt > 1) return false; if (y_attr_cnt > 1) return false; return true; }
static bool gfx_ctx_ps3_init(void *data) { gfx_ctx_ps3_data_t *ps3 = (gfx_ctx_ps3_data_t*) calloc(1, sizeof(gfx_ctx_ps3_data_t)); (void)data; if (!ps3) return false; #if defined(HAVE_PSGL) PSGLinitOptions options = { .enable = PSGL_INIT_MAX_SPUS | PSGL_INIT_INITIALIZE_SPUS, .maxSPUs = 1, .initializeSPUs = GL_FALSE, }; /* Initialize 6 SPUs but reserve 1 SPU as a raw SPU for PSGL. */ sys_spu_initialize(6, 1); psglInit(&options); PSGLdeviceParameters params; params.enable = PSGL_DEVICE_PARAMETERS_COLOR_FORMAT | PSGL_DEVICE_PARAMETERS_DEPTH_FORMAT | PSGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE; params.colorFormat = GL_ARGB_SCE; params.depthFormat = GL_NONE; params.multisamplingMode = GL_MULTISAMPLING_NONE_SCE; if (g_extern.console.screen.resolutions.current.id) { params.enable |= PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT; params.width = gfx_ctx_ps3_get_resolution_width(g_extern.console.screen.resolutions.current.id); params.height = gfx_ctx_ps3_get_resolution_height(g_extern.console.screen.resolutions.current.id); g_extern.console.screen.pal_enable = false; if (params.width == 720 && params.height == 576) { RARCH_LOG("[PSGL Context]: 720x576 resolution detected, setting MODE_VIDEO_PAL_ENABLE.\n"); g_extern.console.screen.pal_enable = true; } } if (g_extern.console.screen.pal60_enable) { RARCH_LOG("[PSGL Context]: Setting temporal PAL60 mode.\n"); params.enable |= PSGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE; params.enable |= PSGL_DEVICE_PARAMETERS_RESC_RATIO_MODE; params.rescPalTemporalMode = RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE; params.rescRatioMode = RESC_RATIO_MODE_FULLSCREEN; } ps3->gl_device = psglCreateDeviceExtended(¶ms); ps3->gl_context = psglCreateContext(); psglMakeCurrent(ps3->gl_context, ps3->gl_device); psglResetCurrentContext(); #endif g_extern.console.screen.pal_enable = cellVideoOutGetResolutionAvailability( CELL_VIDEO_OUT_PRIMARY, CELL_VIDEO_OUT_RESOLUTION_576, CELL_VIDEO_OUT_ASPECT_AUTO, 0); gfx_ctx_ps3_get_available_resolutions(); driver.video_context_data = ps3; return true; } static bool gfx_ctx_ps3_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { (void)data; return true; }
bool load_state(const char *path) { unsigned i; void *buf = NULL; ssize_t size = read_file(path, &buf); RARCH_LOG("Loading state: \"%s\".\n", path); if (size < 0) { RARCH_ERR("Failed to load state from \"%s\".\n", path); return false; } bool ret = true; RARCH_LOG("State size: %u bytes.\n", (unsigned)size); struct sram_block *blocks = NULL; unsigned num_blocks = 0; if (g_settings.block_sram_overwrite && g_extern.savefiles && g_extern.savefiles->size) { RARCH_LOG("Blocking SRAM overwrite.\n"); blocks = (struct sram_block*) calloc(g_extern.savefiles->size, sizeof(*blocks)); if (blocks) { num_blocks = g_extern.savefiles->size; for (i = 0; i < num_blocks; i++) blocks[i].type = g_extern.savefiles->elems[i].attr.i; } } for (i = 0; i < num_blocks; i++) blocks[i].size = pretro_get_memory_size(blocks[i].type); for (i = 0; i < num_blocks; i++) if (blocks[i].size) blocks[i].data = malloc(blocks[i].size); /* Backup current SRAM which is overwritten by unserialize. */ for (i = 0; i < num_blocks; i++) { if (blocks[i].data) { const void *ptr = pretro_get_memory_data(blocks[i].type); if (ptr) memcpy(blocks[i].data, ptr, blocks[i].size); } } ret = pretro_unserialize(buf, size); /* Flush back. */ for (i = 0; i < num_blocks; i++) { if (blocks[i].data) { void *ptr = pretro_get_memory_data(blocks[i].type); if (ptr) memcpy(ptr, blocks[i].data, blocks[i].size); } } for (i = 0; i < num_blocks; i++) free(blocks[i].data); free(blocks); return ret; }
static bool gfx_ctx_qnx_init(void *data) { EGLint num_config; EGLint egl_version_major, egl_version_minor; EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; int angle, size[2]; int usage, format = SCREEN_FORMAT_RGBX8888; /* Create a screen context that will be used to * create an EGL surface to receive libscreen events */ RARCH_LOG("Initializing screen context...\n"); if (!screen_ctx) { screen_create_context(&screen_ctx, 0); if (screen_request_events(screen_ctx) != BPS_SUCCESS) { RARCH_ERR("screen_request_events failed.\n"); goto screen_error; } if (navigator_request_events(0) != BPS_SUCCESS) { RARCH_ERR("navigator_request_events failed.\n"); goto screen_error; } if (navigator_rotation_lock(false) != BPS_SUCCESS) { RARCH_ERR("navigator_location_lock failed.\n"); goto screen_error; } } usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION; RARCH_LOG("Initializing context\n"); if ((g_egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) { RARCH_ERR("eglGetDisplay failed.\n"); goto error; } if (!eglInitialize(g_egl_dpy, &egl_version_major, &egl_version_minor)) { RARCH_ERR("eglInitialize failed.\n"); goto error; } if (!eglBindAPI(EGL_OPENGL_ES_API)) { RARCH_ERR("eglBindAPI failed.\n"); goto error; } RARCH_LOG("[BLACKBERRY QNX/EGL]: EGL version: %d.%d\n", egl_version_major, egl_version_minor); if (!eglChooseConfig(g_egl_dpy, attribs, &g_config, 1, &num_config)) goto error; g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, context_attributes); if (g_egl_ctx == EGL_NO_CONTEXT) goto error; if (g_use_hw_ctx) { g_egl_hw_ctx = eglCreateContext(g_egl_dpy, g_config, g_egl_ctx, context_attributes); RARCH_LOG("[Android/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx); if (g_egl_hw_ctx == EGL_NO_CONTEXT) goto error; } if(!screen_win) { if (screen_create_window(&screen_win, screen_ctx)) { RARCH_ERR("screen_create_window failed:.\n"); goto error; } } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format)) { RARCH_ERR("screen_set_window_property_iv [SCREEN_PROPERTY_FORMAT] failed.\n"); goto error; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage)) { RARCH_ERR("screen_set_window_property_iv [SCREEN_PROPERTY_USAGE] failed.\n"); goto error; } if (screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp)) { RARCH_ERR("screen_get_window_property_pv [SCREEN_PROPERTY_DISPLAY] failed.\n"); goto error; } int screen_resolution[2]; if (screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution)) { RARCH_ERR("screen_get_window_property_iv [SCREEN_PROPERTY_SIZE] failed.\n"); goto error; } #ifndef HAVE_BB10 angle = atoi(getenv("ORIENTATION")); screen_display_mode_t screen_mode; if (screen_get_display_property_pv(screen_disp, SCREEN_PROPERTY_MODE, (void**)&screen_mode)) { RARCH_ERR("screen_get_display_property_pv [SCREEN_PROPERTY_MODE] failed.\n"); goto error; } if (screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size)) { RARCH_ERR("screen_get_window_property_iv [SCREEN_PROPERTY_BUFFER_SIZE] failed.\n"); goto error; } int buffer_size[2] = {size[0], size[1]}; if ((angle == 0) || (angle == 180)) { if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) || ((screen_mode.width < screen_mode.height) && (size[0] > size[1]))) { buffer_size[1] = size[0]; buffer_size[0] = size[1]; } } else if ((angle == 90) || (angle == 270)) { if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) || ((screen_mode.width < screen_mode.height && size[0] < size[1]))) { buffer_size[1] = size[0]; buffer_size[0] = size[1]; } } else { RARCH_ERR("Navigator returned an unexpected orientation angle.\n"); goto error; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size)) { RARCH_ERR("screen_set_window_property_iv [SCREEN_PROPERTY_BUFFER_SIZE] failed.\n"); goto error; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle)) { RARCH_ERR("screen_set_window_property_iv [SCREEN_PROPERTY_ROTATION] failed.\n"); goto error; } #endif if (screen_create_window_buffers(screen_win, WINDOW_BUFFERS)) { RARCH_ERR("screen_create_window_buffers failed.\n"); goto error; } if (!(g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, screen_win, 0))) { RARCH_ERR("eglCreateWindowSurface failed.\n"); goto error; } if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx)) { RARCH_ERR("eglMakeCurrent failed.\n"); goto error; } return true; error: RARCH_ERR("EGL error: %d.\n", eglGetError()); gfx_ctx_qnx_destroy(data); screen_error: screen_stop_events(screen_ctx); return false; }
static void handle_screen_event(void *data, bps_event_t *event) { int type; qnx_input_t *qnx = (qnx_input_t*)data; screen_event_t screen_event = screen_event_get_event(event); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &type); switch(type) { case SCREEN_EVENT_MTOUCH_TOUCH: case SCREEN_EVENT_MTOUCH_RELEASE: case SCREEN_EVENT_MTOUCH_MOVE: process_touch_event(data, screen_event, type); break; case SCREEN_EVENT_KEYBOARD: process_keyboard_event(data, screen_event, type); break; #ifdef HAVE_BB10 case SCREEN_EVENT_GAMEPAD: case SCREEN_EVENT_JOYSTICK: process_gamepad_event(data, screen_event, type); break; case SCREEN_EVENT_DEVICE: { // A device was attached or removed. screen_device_t device; int attached, type, i; screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DEVICE, (void**)&device); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ATTACHED, &attached); if (attached) screen_get_device_property_iv(device, SCREEN_PROPERTY_TYPE, &type); if (attached && (type == SCREEN_EVENT_GAMEPAD || type == SCREEN_EVENT_JOYSTICK || type == SCREEN_EVENT_KEYBOARD)) { for (i = 0; i < MAX_PADS; ++i) { if (!qnx->devices[i].handle) { qnx->devices[i].handle = device; loadController(data, &qnx->devices[i]); break; } } } else { for (i = 0; i < MAX_PADS; ++i) { if (device == qnx->devices[i].handle) { RARCH_LOG("Device %s: Disconnected.\n", qnx->devices[i].id); initController(data, &qnx->devices[i]); break; } } } } break; #endif default: break; } }
rarch_resampler_t *resampler_new(void) { RARCH_LOG("Hermite resampler [C]\n"); return (rarch_resampler_t*)calloc(1, sizeof(rarch_resampler_t)); }
static bool winxinput_joypad_init(void) { unsigned i, autoconf_pad; g_winxinput_dll = NULL; // Find the correct path to load the DLL from. // Usually this will be from the system directory, // but occasionally a user may wish to use a third-party // wrapper DLL (such as x360ce); support these by checking // the working directory first. // No need to check for existance as we will be checking LoadLibrary's // success anyway. const char *version = "1.4"; g_winxinput_dll = LoadLibrary("xinput1_4.dll"); // Using dylib_* complicates building joyconfig. if (!g_winxinput_dll) { g_winxinput_dll = LoadLibrary("xinput1_3.dll"); version = "1.3"; } if (!g_winxinput_dll) { RARCH_ERR("Failed to load XInput, ensure DirectX and controller drivers are up to date.\n"); return false; } RARCH_LOG("Found XInput v%s.\n", version); // If we get here then an xinput DLL is correctly loaded. // First try to load ordinal 100 (XInputGetStateEx). g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, (const char*)100); g_winxinput_guide_button_supported = true; if (!g_XInputGetStateEx) { // no ordinal 100. (Presumably a wrapper.) Load the ordinary // XInputGetState, at the cost of losing guide button support. g_winxinput_guide_button_supported = false; g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, "XInputGetState"); if (!g_XInputGetStateEx) { RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); FreeLibrary(g_winxinput_dll); return false; // DLL was loaded but did not contain the correct function. } RARCH_WARN("XInput: No guide button support.\n"); } g_XInputSetState = (XInputSetState_t) GetProcAddress(g_winxinput_dll, "XInputSetState"); if (!g_XInputSetState) { RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); FreeLibrary(g_winxinput_dll); return false; // DLL was loaded but did not contain the correct function. } // Zero out the states for (i = 0; i < 4; ++i) memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state)); // Do a dummy poll to check which controllers are connected. XINPUT_STATE dummy_state; for (i = 0; i < 4; ++i) { g_winxinput_states[i].connected = !(g_XInputGetStateEx(i, &dummy_state) == ERROR_DEVICE_NOT_CONNECTED); if (g_winxinput_states[i].connected) RARCH_LOG("Found XInput controller, player #%u\n", i); } if ((!g_winxinput_states[0].connected) && (!g_winxinput_states[1].connected) && (!g_winxinput_states[2].connected) && (!g_winxinput_states[3].connected)) return false; g_xinput_block_pads = true; // We're going to have to be buddies with dinput if we want to be able // to use XI and non-XI controllers together. if (!dinput_joypad.init()) { g_xinput_block_pads = false; return false; } for (autoconf_pad = 0; autoconf_pad < MAX_PLAYERS; autoconf_pad++) { if (pad_index_to_xplayer_index(autoconf_pad) > -1) { strlcpy(g_settings.input.device_names[autoconf_pad], winxinput_joypad_name(autoconf_pad), sizeof(g_settings.input.device_names[autoconf_pad])); input_config_autoconfigure_joypad(autoconf_pad, winxinput_joypad_name(autoconf_pad), winxinput_joypad.ident); } } return true; }
static void *alsa_thread_init(const char *device, unsigned rate, unsigned latency) { alsa_thread_t *alsa = (alsa_thread_t*)calloc(1, sizeof(alsa_thread_t)); snd_pcm_hw_params_t *params = NULL; snd_pcm_sw_params_t *sw_params = NULL; const char *alsa_dev = device ? device : "default"; unsigned latency_usec = latency * 1000 / 2; unsigned channels = 2; unsigned periods = 4; snd_pcm_uframes_t buffer_size; snd_pcm_format_t format; if (!alsa) return NULL; TRY_ALSA(snd_pcm_open(&alsa->pcm, alsa_dev, SND_PCM_STREAM_PLAYBACK, 0)); TRY_ALSA(snd_pcm_hw_params_malloc(¶ms)); alsa->has_float = alsathread_find_float_format(alsa->pcm, params); format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16; TRY_ALSA(snd_pcm_hw_params_any(alsa->pcm, params)); TRY_ALSA(snd_pcm_hw_params_set_access( alsa->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED)); TRY_ALSA(snd_pcm_hw_params_set_format(alsa->pcm, params, format)); TRY_ALSA(snd_pcm_hw_params_set_channels(alsa->pcm, params, channels)); TRY_ALSA(snd_pcm_hw_params_set_rate(alsa->pcm, params, rate, 0)); TRY_ALSA(snd_pcm_hw_params_set_buffer_time_near( alsa->pcm, params, &latency_usec, NULL)); TRY_ALSA(snd_pcm_hw_params_set_periods_near( alsa->pcm, params, &periods, NULL)); TRY_ALSA(snd_pcm_hw_params(alsa->pcm, params)); /* Shouldn't have to bother with this, * but some drivers are apparently broken. */ if (snd_pcm_hw_params_get_period_size(params, &alsa->period_frames, NULL)) snd_pcm_hw_params_get_period_size_min( params, &alsa->period_frames, NULL); RARCH_LOG("ALSA: Period size: %d frames\n", (int)alsa->period_frames); if (snd_pcm_hw_params_get_buffer_size(params, &buffer_size)) snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size); RARCH_LOG("ALSA: Buffer size: %d frames\n", (int)buffer_size); alsa->buffer_size = snd_pcm_frames_to_bytes(alsa->pcm, buffer_size); alsa->period_size = snd_pcm_frames_to_bytes(alsa->pcm, alsa->period_frames); TRY_ALSA(snd_pcm_sw_params_malloc(&sw_params)); TRY_ALSA(snd_pcm_sw_params_current(alsa->pcm, sw_params)); TRY_ALSA(snd_pcm_sw_params_set_start_threshold( alsa->pcm, sw_params, buffer_size / 2)); TRY_ALSA(snd_pcm_sw_params(alsa->pcm, sw_params)); snd_pcm_hw_params_free(params); snd_pcm_sw_params_free(sw_params); alsa->fifo_lock = slock_new(); alsa->cond_lock = slock_new(); alsa->cond = scond_new(); alsa->buffer = fifo_new(alsa->buffer_size); if (!alsa->fifo_lock || !alsa->cond_lock || !alsa->cond || !alsa->buffer) goto error; alsa->worker_thread = sthread_create(alsa_worker_thread, alsa); if (!alsa->worker_thread) { RARCH_ERR("error initializing worker thread"); goto error; } return alsa; error: RARCH_ERR("ALSA: Failed to initialize...\n"); if (params) snd_pcm_hw_params_free(params); if (sw_params) snd_pcm_sw_params_free(sw_params); alsa_thread_free(alsa); return NULL; }
static bool create_softfilter_graph(rarch_softfilter_t *filt, enum retro_pixel_format in_pixel_format, unsigned max_width, unsigned max_height, softfilter_simd_mask_t cpu_features, unsigned threads) { unsigned input_fmts, input_fmt, output_fmts, i = 0; struct config_file_userdata userdata; char key[64], name[64]; (void)i; key[0] = name[0] = '\0'; snprintf(key, sizeof(key), "filter"); if (!config_get_array(filt->conf, key, name, sizeof(name))) { RARCH_ERR("Could not find 'filter' array in config.\n"); return false; } if (filt->num_plugs == 0) { RARCH_ERR("No filter plugs found. Exiting...\n"); return false; } filt->impl = softfilter_find_implementation(filt, name); if (!filt->impl) { RARCH_ERR("Could not find implementation.\n"); return false; } userdata.conf = filt->conf; /* Index-specific configs take priority over ident-specific. */ userdata.prefix[0] = key; userdata.prefix[1] = filt->impl->short_ident; /* Simple assumptions. */ filt->pix_fmt = in_pixel_format; input_fmts = filt->impl->query_input_formats(); switch (in_pixel_format) { case RETRO_PIXEL_FORMAT_XRGB8888: input_fmt = SOFTFILTER_FMT_XRGB8888; break; case RETRO_PIXEL_FORMAT_RGB565: input_fmt = SOFTFILTER_FMT_RGB565; break; default: return false; } if (!(input_fmt & input_fmts)) { RARCH_ERR("Softfilter does not support input format.\n"); return false; } output_fmts = filt->impl->query_output_formats(input_fmt); /* If we have a match of input/output formats, use that. */ if (output_fmts & input_fmt) filt->out_pix_fmt = in_pixel_format; else if (output_fmts & SOFTFILTER_FMT_XRGB8888) filt->out_pix_fmt = RETRO_PIXEL_FORMAT_XRGB8888; else if (output_fmts & SOFTFILTER_FMT_RGB565) filt->out_pix_fmt = RETRO_PIXEL_FORMAT_RGB565; else { RARCH_ERR("Did not find suitable output format for softfilter.\n"); return false; } filt->max_width = max_width; filt->max_height = max_height; filt->impl_data = filt->impl->create( &softfilter_config, input_fmt, input_fmt, max_width, max_height, threads != RARCH_SOFTFILTER_THREADS_AUTO ? threads : cpu_features_get_core_amount(), cpu_features, &userdata); if (!filt->impl_data) { RARCH_ERR("Failed to create softfilter state.\n"); return false; } threads = filt->impl->query_num_threads(filt->impl_data); if (!threads) { RARCH_ERR("Invalid number of threads.\n"); return false; } filt->threads = threads; RARCH_LOG("Using %u threads for softfilter.\n", threads); filt->packets = (struct softfilter_work_packet*) calloc(threads, sizeof(*filt->packets)); if (!filt->packets) { RARCH_ERR("Failed to allocate softfilter packets.\n"); return false; } #ifdef HAVE_THREADS filt->thread_data = (struct filter_thread_data*) calloc(threads, sizeof(*filt->thread_data)); if (!filt->thread_data) return false; for (i = 0; i < threads; i++) { filt->thread_data[i].userdata = filt->impl_data; filt->thread_data[i].done = true; filt->thread_data[i].lock = slock_new(); if (!filt->thread_data[i].lock) return false; filt->thread_data[i].cond = scond_new(); if (!filt->thread_data[i].cond) return false; filt->thread_data[i].thread = sthread_create( filter_thread_loop, &filt->thread_data[i]); if (!filt->thread_data[i].thread) return false; } #endif return true; }
static bool load_content(const struct retro_subsystem_info *special, const struct string_list *content) { unsigned i; bool ret = true; struct string_list* additional_path_allocs = string_list_new(); struct retro_game_info *info = (struct retro_game_info*) calloc(content->size, sizeof(*info)); if (!info) return false; for (i = 0; i < content->size; i++) { const char *path = content->elems[i].data; int attr = content->elems[i].attr.i; bool need_fullpath = attr & 2; bool require_content = attr & 4; if (require_content && !*path) { RARCH_LOG("libretro core requires content, but nothing was provided.\n"); ret = false; goto end; } info[i].path = *path ? path : NULL; if (!need_fullpath && *path) { /* Load the content into memory. */ RARCH_LOG("Loading content file: %s.\n", path); /* First content file is significant, attempt to do patching, * CRC checking, etc. */ long size = i == 0 ? read_content_file(path, (void**)&info[i].data) : read_file(path, (void**)&info[i].data); if (size < 0) { RARCH_ERR("Could not read content file \"%s\".\n", path); ret = false; goto end; } info[i].size = size; } else { RARCH_LOG("Content loading skipped. Implementation will" " load it on its own.\n"); if (need_fullpath && path_contains_compressed_file(path)) { RARCH_LOG("Compressed file in case of need_fullpath." "Now extracting to temporary directory.\n"); if ((!strcmp(g_settings.extraction_directory,"")) || !path_is_directory(g_settings.extraction_directory)) { RARCH_ERR("Tried extracting to extraction directory, but " "extraction directory was not set or found. Exiting.\n"); rarch_assert(false); } char new_path[PATH_MAX]; union string_list_elem_attr attr; attr.i = 0; fill_pathname_join(new_path,g_settings.extraction_directory, path_basename(path),sizeof(new_path)); read_compressed_file(path,NULL,new_path); string_list_append(additional_path_allocs,new_path,attr); info[i].path = additional_path_allocs->elems [additional_path_allocs->size -1 ].data; /* g_extern.temporary_content is initialized in init_content_file * The following part takes care of cleanup of the unzipped files * after exit. */ rarch_assert(g_extern.temporary_content != NULL); string_list_append(g_extern.temporary_content, new_path, attr); } } } if (special) ret = pretro_load_game_special(special->id, info, content->size); else ret = pretro_load_game(*content->elems[0].data ? info : NULL); if (!ret) RARCH_ERR("Failed to load game.\n"); end: for (i = 0; i < content->size; i++) free((void*)info[i].data); string_list_free(additional_path_allocs); free(info); return ret; }
static void load_symbols(bool is_dummy) { if (is_dummy) { SYM_DUMMY(retro_init); SYM_DUMMY(retro_deinit); SYM_DUMMY(retro_api_version); SYM_DUMMY(retro_get_system_info); SYM_DUMMY(retro_get_system_av_info); SYM_DUMMY(retro_set_environment); SYM_DUMMY(retro_set_video_refresh); SYM_DUMMY(retro_set_audio_sample); SYM_DUMMY(retro_set_audio_sample_batch); SYM_DUMMY(retro_set_input_poll); SYM_DUMMY(retro_set_input_state); SYM_DUMMY(retro_set_controller_port_device); SYM_DUMMY(retro_reset); SYM_DUMMY(retro_run); SYM_DUMMY(retro_serialize_size); SYM_DUMMY(retro_serialize); SYM_DUMMY(retro_unserialize); SYM_DUMMY(retro_cheat_reset); SYM_DUMMY(retro_cheat_set); SYM_DUMMY(retro_load_game); SYM_DUMMY(retro_load_game_special); SYM_DUMMY(retro_unload_game); SYM_DUMMY(retro_get_region); SYM_DUMMY(retro_get_memory_data); SYM_DUMMY(retro_get_memory_size); } else { #ifdef HAVE_DYNAMIC if (path_is_directory(g_settings.libretro)) { char libretro_core_buffer[PATH_MAX]; if (!find_first_libretro(libretro_core_buffer, sizeof(libretro_core_buffer), g_settings.libretro, g_extern.fullpath)) { RARCH_ERR("libretro_path is a directory, but no valid libretro implementation was found.\n"); rarch_fail(1, "load_dynamic()"); } strlcpy(g_settings.libretro, libretro_core_buffer, sizeof(g_settings.libretro)); } // Need to use absolute path for this setting. It can be saved to ROM history, // and a relative path would break in that scenario. path_resolve_realpath(g_settings.libretro, sizeof(g_settings.libretro)); RARCH_LOG("Loading dynamic libretro from: \"%s\"\n", g_settings.libretro); lib_handle = dylib_load(g_settings.libretro); if (!lib_handle) { RARCH_ERR("Failed to open dynamic library: \"%s\"\n", g_settings.libretro); rarch_fail(1, "load_dynamic()"); } #endif SYM(retro_init); SYM(retro_deinit); SYM(retro_api_version); SYM(retro_get_system_info); SYM(retro_get_system_av_info); SYM(retro_set_environment); SYM(retro_set_video_refresh); SYM(retro_set_audio_sample); SYM(retro_set_audio_sample_batch); SYM(retro_set_input_poll); SYM(retro_set_input_state); SYM(retro_set_controller_port_device); SYM(retro_reset); SYM(retro_run); SYM(retro_serialize_size); SYM(retro_serialize); SYM(retro_unserialize); SYM(retro_cheat_reset); SYM(retro_cheat_set); SYM(retro_load_game); SYM(retro_load_game_special); SYM(retro_unload_game); SYM(retro_get_region); SYM(retro_get_memory_data); SYM(retro_get_memory_size); } }
static void frontend_ps3_get_environment_settings(int *argc, char *argv[], void *args, void *params_data) { #ifndef IS_SALAMANDER bool original_verbose = verbosity_is_enabled(); verbosity_enable(); #endif (void)args; #ifndef IS_SALAMANDER #if defined(HAVE_LOGGER) logger_init(); #elif defined(HAVE_FILE_LOGGER) retro_main_log_file_init("/retroarch-log.txt"); #endif #endif int ret; unsigned int get_type; unsigned int get_attributes; CellGameContentSize size; char dirName[CELL_GAME_DIRNAME_SIZE] = {0}; #ifdef HAVE_MULTIMAN /* not launched from external launcher, set default path */ // second param is multiMAN SELF file if(path_file_exists(argv[2]) && *argc > 1 && (!strcmp(argv[2], EMULATOR_CONTENT_DIR))) { multiman_detected = true; RARCH_LOG("Started from multiMAN, auto-game start enabled.\n"); } else #endif #ifndef IS_SALAMANDER if (*argc > 1 && !string_is_empty(argv[1])) { static char path[PATH_MAX_LENGTH]; *path = '\0'; struct rarch_main_wrap *args = (struct rarch_main_wrap*)params_data; if (args) { strlcpy(path, argv[1], sizeof(path)); args->touched = true; args->no_content = false; args->verbose = false; args->config_path = NULL; args->sram_path = NULL; args->state_path = NULL; args->content_path = path; args->libretro_path = NULL; RARCH_LOG("argv[0]: %s\n", argv[0]); RARCH_LOG("argv[1]: %s\n", argv[1]); RARCH_LOG("argv[2]: %s\n", argv[2]); RARCH_LOG("Auto-start game %s.\n", argv[1]); } } else RARCH_WARN("Started from Salamander, auto-game start disabled.\n"); #endif memset(&size, 0x00, sizeof(CellGameContentSize)); ret = cellGameBootCheck(&get_type, &get_attributes, &size, dirName); if(ret < 0) { RARCH_ERR("cellGameBootCheck() Error: 0x%x.\n", ret); } else { char content_info_path[PATH_MAX_LENGTH] = {0}; RARCH_LOG("cellGameBootCheck() OK.\n"); RARCH_LOG("Directory name: [%s].\n", dirName); RARCH_LOG(" HDD Free Size (in KB) = [%d] Size (in KB) = [%d] System Size (in KB) = [%d].\n", size.hddFreeSizeKB, size.sizeKB, size.sysSizeKB); switch(get_type) { case CELL_GAME_GAMETYPE_DISC: RARCH_LOG("RetroArch was launched on Optical Disc Drive.\n"); break; case CELL_GAME_GAMETYPE_HDD: RARCH_LOG("RetroArch was launched on HDD.\n"); break; } if((get_attributes & CELL_GAME_ATTRIBUTE_APP_HOME) == CELL_GAME_ATTRIBUTE_APP_HOME) RARCH_LOG("RetroArch was launched from host machine (APP_HOME).\n"); ret = cellGameContentPermit(content_info_path, g_defaults.dir.port); #ifdef HAVE_MULTIMAN if (multiman_detected) { fill_pathname_join(content_info_path, "/dev_hdd0/game/", EMULATOR_CONTENT_DIR, sizeof(content_info_path)); fill_pathname_join(g_defaults.dir.port, content_info_path, "USRDIR", sizeof(g_defaults.dir.port)); } #endif if(ret < 0) RARCH_ERR("cellGameContentPermit() Error: 0x%x\n", ret); else { RARCH_LOG("cellGameContentPermit() OK.\n"); RARCH_LOG("content_info_path : [%s].\n", content_info_path); RARCH_LOG("usrDirPath : [%s].\n", g_defaults.dir.port); } strlcpy(g_defaults.dir.content_history, g_defaults.dir.port, sizeof(g_defaults.dir.content_history)); fill_pathname_join(g_defaults.dir.core, g_defaults.dir.port, "cores", sizeof(g_defaults.dir.core)); fill_pathname_join(g_defaults.dir.core_info, g_defaults.dir.port, "cores", sizeof(g_defaults.dir.core_info)); fill_pathname_join(g_defaults.dir.savestate, g_defaults.dir.core, "savestates", sizeof(g_defaults.dir.savestate)); fill_pathname_join(g_defaults.dir.sram, g_defaults.dir.core, "savefiles", sizeof(g_defaults.dir.sram)); fill_pathname_join(g_defaults.dir.system, g_defaults.dir.core, "system", sizeof(g_defaults.dir.system)); fill_pathname_join(g_defaults.dir.shader, g_defaults.dir.core, "shaders_cg", sizeof(g_defaults.dir.shader)); fill_pathname_join(g_defaults.path.config, g_defaults.dir.port, file_path_str(FILE_PATH_MAIN_CONFIG), sizeof(g_defaults.path.config)); fill_pathname_join(g_defaults.dir.overlay, g_defaults.dir.core, "overlays", sizeof(g_defaults.dir.overlay)); fill_pathname_join(g_defaults.dir.assets, g_defaults.dir.core, "assets", sizeof(g_defaults.dir.assets)); fill_pathname_join(g_defaults.dir.cursor, g_defaults.dir.core, "database/cursors", sizeof(g_defaults.dir.cursor)); fill_pathname_join(g_defaults.dir.database, g_defaults.dir.core, "database/rdb", sizeof(g_defaults.dir.database)); fill_pathname_join(g_defaults.dir.playlist, g_defaults.dir.core, "playlists", sizeof(g_defaults.dir.playlist)); } #ifndef IS_SALAMANDER if (original_verbose) verbosity_enable(); else verbosity_disable(); #endif }
bool gl_glsl_init(const char *path) { #if !defined(HAVE_OPENGLES2) && !defined(HAVE_OPENGL_MODERN) && !defined(__APPLE__) // Load shader functions. LOAD_GL_SYM(CreateProgram); LOAD_GL_SYM(UseProgram); LOAD_GL_SYM(CreateShader); LOAD_GL_SYM(DeleteShader); LOAD_GL_SYM(ShaderSource); LOAD_GL_SYM(CompileShader); LOAD_GL_SYM(AttachShader); LOAD_GL_SYM(DetachShader); LOAD_GL_SYM(LinkProgram); LOAD_GL_SYM(GetUniformLocation); LOAD_GL_SYM(Uniform1i); LOAD_GL_SYM(Uniform1f); LOAD_GL_SYM(Uniform2fv); LOAD_GL_SYM(Uniform4fv); LOAD_GL_SYM(UniformMatrix4fv); LOAD_GL_SYM(GetShaderiv); LOAD_GL_SYM(GetShaderInfoLog); LOAD_GL_SYM(GetProgramiv); LOAD_GL_SYM(GetProgramInfoLog); LOAD_GL_SYM(DeleteProgram); LOAD_GL_SYM(GetAttachedShaders); LOAD_GL_SYM(GetAttribLocation); LOAD_GL_SYM(EnableVertexAttribArray); LOAD_GL_SYM(DisableVertexAttribArray); LOAD_GL_SYM(VertexAttribPointer); RARCH_LOG("Checking GLSL shader support ...\n"); bool shader_support = pglCreateProgram && pglUseProgram && pglCreateShader && pglDeleteShader && pglShaderSource && pglCompileShader && pglAttachShader && pglDetachShader && pglLinkProgram && pglGetUniformLocation && pglUniform1i && pglUniform1f && pglUniform2fv && pglUniform4fv && pglUniformMatrix4fv && pglGetShaderiv && pglGetShaderInfoLog && pglGetProgramiv && pglGetProgramInfoLog && pglDeleteProgram && pglGetAttachedShaders && pglGetAttribLocation && pglEnableVertexAttribArray && pglDisableVertexAttribArray && pglVertexAttribPointer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); return false; } #endif unsigned num_progs = 0; struct shader_program progs[RARCH_GLSL_MAX_SHADERS] = {{0}}; #ifdef HAVE_XML if (path) { num_progs = get_xml_shaders(path, progs, RARCH_GLSL_MAX_SHADERS - 1); if (num_progs == 0) { RARCH_ERR("Couldn't find any valid shaders in XML file.\n"); return false; } } else #endif { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); num_progs = 1; progs[0].vertex = strdup(stock_vertex_modern); progs[0].fragment = strdup(stock_fragment_modern); glsl_modern = true; } #ifdef HAVE_OPENGLES2 if (!glsl_modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); return false; } #endif struct shader_program stock_prog = {0}; stock_prog.vertex = strdup(glsl_modern ? stock_vertex_modern : stock_vertex_legacy); stock_prog.fragment = strdup(glsl_modern ? stock_fragment_modern : stock_fragment_legacy); if (!compile_programs(&gl_program[0], &stock_prog, 1)) { RARCH_ERR("GLSL stock programs failed to compile.\n"); return false; } for (unsigned i = 0; i < num_progs; i++) { gl_filter_type[i + 1] = progs[i].filter; gl_scale[i + 1].type_x = progs[i].type_x; gl_scale[i + 1].type_y = progs[i].type_y; gl_scale[i + 1].scale_x = progs[i].scale_x; gl_scale[i + 1].scale_y = progs[i].scale_y; gl_scale[i + 1].abs_x = progs[i].abs_x; gl_scale[i + 1].abs_y = progs[i].abs_y; gl_scale[i + 1].valid = progs[i].valid_scale; } if (!compile_programs(&gl_program[1], progs, num_progs)) return false; #ifdef HAVE_XML // RetroArch custom two-pass with two different files. if (num_progs == 1 && *g_settings.video.second_pass_shader && g_settings.video.render_to_texture) { unsigned secondary_progs = get_xml_shaders(g_settings.video.second_pass_shader, progs, 1); if (secondary_progs == 1) { compile_programs(&gl_program[2], progs, 1); num_progs++; } else { RARCH_ERR("Did not find exactly one valid shader in secondary shader file.\n"); return false; } } #endif for (unsigned i = 0; i <= num_progs; i++) find_uniforms(gl_program[i], &gl_uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error()) RARCH_WARN("Detected GL error in GLSL.\n"); #endif #ifdef HAVE_XML if (gl_tracker_info_cnt > 0) { struct state_tracker_info info = {0}; info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM); info.info = gl_tracker_info; info.info_elem = gl_tracker_info_cnt; #ifdef HAVE_PYTHON info.script = gl_script_program; info.script_class = *gl_tracker_script_class ? gl_tracker_script_class : NULL; info.script_is_file = false; #endif gl_state_tracker = state_tracker_init(&info); if (!gl_state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } #endif glsl_enable = true; gl_num_programs = num_progs; gl_program[gl_num_programs + 1] = gl_program[0]; gl_uniforms[gl_num_programs + 1] = gl_uniforms[0]; gl_glsl_reset_attrib(); return true; }
static void patch_rom(uint8_t **buf, ssize_t *size) { uint8_t *ret_buf = *buf; ssize_t ret_size = *size; const char *patch_desc = NULL; const char *patch_path = NULL; patch_error_t err = PATCH_UNKNOWN; patch_func_t func = NULL; ssize_t patch_size = 0; void *patch_data = NULL; bool success = false; if (g_extern.ups_pref + g_extern.bps_pref + g_extern.ips_pref > 1) { RARCH_WARN("Several patches are explicitly defined, ignoring all ...\n"); return; } bool allow_bps = !g_extern.ups_pref && !g_extern.ips_pref; bool allow_ups = !g_extern.bps_pref && !g_extern.ips_pref; bool allow_ips = !g_extern.ups_pref && !g_extern.bps_pref; if (allow_ups && *g_extern.ups_name && (patch_size = read_file(g_extern.ups_name, &patch_data)) >= 0) { patch_desc = "UPS"; patch_path = g_extern.ups_name; func = ups_apply_patch; } else if (allow_bps && *g_extern.bps_name && (patch_size = read_file(g_extern.bps_name, &patch_data)) >= 0) { patch_desc = "BPS"; patch_path = g_extern.bps_name; func = bps_apply_patch; } else if (allow_ips && *g_extern.ips_name && (patch_size = read_file(g_extern.ips_name, &patch_data)) >= 0) { patch_desc = "IPS"; patch_path = g_extern.ips_name; func = ips_apply_patch; } else { RARCH_LOG("Did not find a valid ROM patch.\n"); return; } RARCH_LOG("Found %s file in \"%s\", attempting to patch ...\n", patch_desc, patch_path); size_t target_size = ret_size * 4; // Just to be sure ... uint8_t *patched_rom = (uint8_t*)malloc(target_size); if (!patched_rom) { RARCH_ERR("Failed to allocate memory for patched ROM ...\n"); goto error; } err = func((const uint8_t*)patch_data, patch_size, ret_buf, ret_size, patched_rom, &target_size); if (err == PATCH_SUCCESS) { RARCH_LOG("ROM patched successfully (%s).\n", patch_desc); success = true; } else RARCH_ERR("Failed to patch %s: Error #%u\n", patch_desc, (unsigned)err); if (success) { free(ret_buf); *buf = patched_rom; *size = target_size; } if (patch_data) free(patch_data); return; error: *buf = ret_buf; *size = ret_size; if (patch_data) free(patch_data); }
static bool get_texture_image(const char *shader_path, xmlNodePtr ptr) { if (gl_teximage_cnt >= MAX_TEXTURES) { RARCH_WARN("Too many texture images. Ignoring ...\n"); return true; } bool linear = true; char filename[PATH_MAX]; char filter[64]; char id[64]; xml_get_prop(filename, sizeof(filename), ptr, "file"); xml_get_prop(filter, sizeof(filter), ptr, "filter"); xml_get_prop(id, sizeof(id), ptr, "id"); struct texture_image img; if (!*id) { RARCH_ERR("Could not find ID in texture.\n"); return false; } if (!*filename) { RARCH_ERR("Could not find filename in texture.\n"); return false; } if (strcmp(filter, "nearest") == 0) linear = false; char tex_path[PATH_MAX]; fill_pathname_resolve_relative(tex_path, shader_path, (const char*)filename, sizeof(tex_path)); RARCH_LOG("Loading texture image from: \"%s\" ...\n", tex_path); if (!texture_image_load(tex_path, &img)) { RARCH_ERR("Failed to load texture image from: \"%s\"\n", tex_path); return false; } strlcpy(gl_teximage_uniforms[gl_teximage_cnt], (const char*)id, sizeof(gl_teximage_uniforms[0])); glGenTextures(1, &gl_teximage[gl_teximage_cnt]); pglActiveTexture(GL_TEXTURE0 + gl_teximage_cnt + 1); glBindTexture(GL_TEXTURE_2D, gl_teximage[gl_teximage_cnt]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, BORDER_FUNC); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, BORDER_FUNC); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(GL_TEXTURE_2D, 0, RARCH_GL_INTERNAL_FORMAT32, img.width, img.height, 0, RARCH_GL_TEXTURE_TYPE32, RARCH_GL_FORMAT32, img.pixels); pglActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); free(img.pixels); gl_teximage_cnt++; return true; }
static ssize_t read_rom_file(FILE *file, void **buf) { ssize_t ret = 0; uint8_t *ret_buf = NULL; if (file == NULL) // stdin { #if defined(_WIN32) && !defined(_XBOX) _setmode(0, O_BINARY); #endif RARCH_LOG("Reading ROM from stdin ...\n"); size_t buf_size = 0xfffff; // Some initial guesstimate. size_t buf_ptr = 0; uint8_t *rom_buf = (uint8_t*)malloc(buf_size); if (rom_buf == NULL) { RARCH_ERR("Couldn't allocate memory.\n"); return -1; } for (;;) { size_t ret = fread(rom_buf + buf_ptr, 1, buf_size - buf_ptr, stdin); buf_ptr += ret; // We've reached the end if (buf_ptr < buf_size) break; rom_buf = (uint8_t*)realloc(rom_buf, buf_size * 2); if (rom_buf == NULL) { RARCH_ERR("Couldn't allocate memory.\n"); return -1; } buf_size *= 2; } ret_buf = rom_buf; ret = buf_ptr; } else { fseek(file, 0, SEEK_END); ret = ftell(file); rewind(file); void *rom_buf = malloc(ret); if (rom_buf == NULL) { RARCH_ERR("Couldn't allocate memory.\n"); return -1; } if (fread(rom_buf, 1, ret, file) < (size_t)ret) { RARCH_ERR("Didn't read whole file.\n"); free(rom_buf); return -1; } ret_buf = (uint8_t*)rom_buf; } if (!g_extern.block_patch) { // Attempt to apply a patch. patch_rom(&ret_buf, &ret); } g_extern.cart_crc = crc32_calculate(ret_buf, ret); sha256_hash(g_extern.sha256, ret_buf, ret); RARCH_LOG("CRC32: 0x%x, SHA256: %s\n", (unsigned)g_extern.cart_crc, g_extern.sha256); *buf = ret_buf; return ret; }
static void frontend_ctr_get_environment_settings(int *argc, char *argv[], void *args, void *params_data) { (void)args; #ifndef IS_SALAMANDER #if defined(HAVE_LOGGER) logger_init(); #elif defined(HAVE_FILE_LOGGER) global_t *global = global_get_ptr(); global->log_file = fopen("sdmc:/retroarch/retroarch-log.txt", "w"); #endif #endif fill_pathname_basedir(g_defaults.dir.port, elf_path_cst, sizeof(g_defaults.dir.port)); RARCH_LOG("port dir: [%s]\n", g_defaults.dir.port); fill_pathname_join(g_defaults.dir.core_assets, g_defaults.dir.port, "downloads", sizeof(g_defaults.dir.core_assets)); fill_pathname_join(g_defaults.dir.assets, g_defaults.dir.port, "media", sizeof(g_defaults.dir.assets)); fill_pathname_join(g_defaults.dir.core, g_defaults.dir.port, "cores", sizeof(g_defaults.dir.core)); fill_pathname_join(g_defaults.dir.core_info, g_defaults.dir.port, "cores", sizeof(g_defaults.dir.core_info)); fill_pathname_join(g_defaults.dir.savestate, g_defaults.dir.core, "savestates", sizeof(g_defaults.dir.savestate)); fill_pathname_join(g_defaults.dir.sram, g_defaults.dir.core, "savefiles", sizeof(g_defaults.dir.sram)); fill_pathname_join(g_defaults.dir.system, g_defaults.dir.core, "system", sizeof(g_defaults.dir.system)); fill_pathname_join(g_defaults.dir.playlist, g_defaults.dir.core, "playlists", sizeof(g_defaults.dir.playlist)); fill_pathname_join(g_defaults.dir.remap, g_defaults.dir.port, "remaps", sizeof(g_defaults.dir.remap)); fill_pathname_join(g_defaults.path.config, g_defaults.dir.port, "retroarch.cfg", sizeof(g_defaults.path.config)); #ifndef IS_SALAMANDER #if 0 if (argv[1] && (argv[1][0] != '\0')) { static char path[PATH_MAX_LENGTH]; struct rarch_main_wrap *args = NULL; *path = '\0'; args = (struct rarch_main_wrap*)params_data; if (args) { strlcpy(path, argv[1], sizeof(path)); args->touched = true; args->no_content = false; args->verbose = false; args->config_path = NULL; args->sram_path = NULL; args->state_path = NULL; args->content_path = path; args->libretro_path = NULL; RARCH_LOG("argv[0]: %s\n", argv[0]); RARCH_LOG("argv[1]: %s\n", argv[1]); RARCH_LOG("argv[2]: %s\n", argv[2]); RARCH_LOG("Auto-start game %s.\n", argv[1]); } } #endif #endif }
bool load_state(const char *path) { RARCH_LOG("Loading state: \"%s\".\n", path); void *buf = NULL; ssize_t size = read_file(path, &buf); if (size < 0) { RARCH_ERR("Failed to load state from \"%s\".\n", path); return false; } bool ret = true; RARCH_LOG("State size: %u bytes.\n", (unsigned)size); void *block_buf[2] = {NULL, NULL}; int block_type[2] = {-1, -1}; size_t block_size[2] = {0}; if (g_settings.block_sram_overwrite) { RARCH_LOG("Blocking SRAM overwrite.\n"); switch (g_extern.game_type) { case RARCH_CART_NORMAL: block_type[0] = RETRO_MEMORY_SAVE_RAM; block_type[1] = RETRO_MEMORY_RTC; break; case RARCH_CART_BSX: case RARCH_CART_BSX_SLOTTED: block_type[0] = RETRO_MEMORY_SNES_BSX_RAM; block_type[1] = RETRO_MEMORY_SNES_BSX_PRAM; break; case RARCH_CART_SUFAMI: block_type[0] = RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM; block_type[1] = RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM; break; case RARCH_CART_SGB: block_type[0] = RETRO_MEMORY_SNES_GAME_BOY_RAM; block_type[1] = RETRO_MEMORY_SNES_GAME_BOY_RTC; break; } } for (unsigned i = 0; i < 2; i++) if (block_type[i] != -1) block_size[i] = pretro_get_memory_size(block_type[i]); for (unsigned i = 0; i < 2; i++) if (block_size[i]) block_buf[i] = malloc(block_size[i]); // Backup current SRAM which is overwritten by unserialize. for (unsigned i = 0; i < 2; i++) { if (block_buf[i]) { const void *ptr = pretro_get_memory_data(block_type[i]); if (ptr) memcpy(block_buf[i], ptr, block_size[i]); } } ret = pretro_unserialize(buf, size); // Flush back :D for (unsigned i = 0; i < 2 && ret; i++) { if (block_buf[i]) { void *ptr = pretro_get_memory_data(block_type[i]); if (ptr) memcpy(ptr, block_buf[i], block_size[i]); } } for (unsigned i = 0; i < 2; i++) if (block_buf[i]) free(block_buf[i]); free(buf); return ret; }
py_state_t *py_state_new(const char *script, unsigned is_file, const char *pyclass) { py_state_t *handle; PyObject *hook; RARCH_LOG("Initializing Python runtime ...\n"); PyImport_AppendInittab("rarch", &PyInit_Retro); Py_Initialize(); RARCH_LOG("Initialized Python runtime.\n"); handle = (py_state_t*)calloc(1, sizeof(*handle)); hook = NULL; handle->main = PyImport_AddModule("__main__"); if (!handle->main) goto error; Py_INCREF(handle->main); if (is_file) { /* Have to hack around the fact that the FILE struct * isn't standardized across environments. * PyRun_SimpleFile() breaks on Windows because it's * compiled with MSVC. */ ssize_t len; char *script_ = NULL; bool ret = filestream_read_file (script, (void**)&script_, &len); if (!ret || len < 0) { RARCH_ERR("Python: Failed to read script\n"); free(script_); goto error; } PyRun_SimpleString(script_); free(script_); } else { char *script_ = align_program(script); if (script_) { PyRun_SimpleString(script_); free(script_); } } RARCH_LOG("Python: Script loaded.\n"); handle->dict = PyModule_GetDict(handle->main); if (!handle->dict) { RARCH_ERR("Python: PyModule_GetDict() failed.\n"); goto error; } Py_INCREF(handle->dict); hook = PyDict_GetItemString(handle->dict, pyclass); if (!hook) { RARCH_ERR("Python: PyDict_GetItemString() failed.\n"); goto error; } handle->inst = PyObject_CallFunction(hook, NULL); if (!handle->inst) { RARCH_ERR("Python: PyObject_CallFunction() failed.\n"); goto error; } Py_INCREF(handle->inst); return handle; error: PyErr_Print(); PyErr_Clear(); py_state_free(handle); return NULL; }
static bool load_roms(unsigned rom_type, const char **rom_paths, size_t roms) { bool ret = true; if (roms == 0) return false; if (roms > MAX_ROMS) return false; void *rom_buf[MAX_ROMS] = {NULL}; ssize_t rom_len[MAX_ROMS] = {0}; struct retro_game_info info[MAX_ROMS] = {{NULL}}; char *xml_buf = load_xml_map(g_extern.xml_name); FILE *rom_file = NULL; if (rom_paths[0]) { RARCH_LOG("Loading ROM file: %s.\n", rom_paths[0]); rom_file = fopen(rom_paths[0], "rb"); } if (!g_extern.system.info.need_fullpath) { if ((rom_len[0] = read_rom_file(rom_file, &rom_buf[0])) == -1) { RARCH_ERR("Could not read ROM file.\n"); ret = false; goto end; } RARCH_LOG("ROM size: %u bytes.\n", (unsigned)rom_len[0]); } else { if (!rom_file) { RARCH_ERR("Implementation requires a full path to be set, cannot load ROM from stdin. Aborting ...\n"); ret = false; goto end; } RARCH_LOG("ROM loading skipped. Implementation will load it on its own.\n"); } info[0].path = rom_paths[0]; info[0].data = rom_buf[0]; info[0].size = rom_len[0]; info[0].meta = xml_buf; for (size_t i = 1; i < roms; i++) { if (rom_paths[i] && !g_extern.system.info.need_fullpath && (rom_len[i] = read_file(rom_paths[i], &rom_buf[i])) == -1) { RARCH_ERR("Could not read ROM file: \"%s\".\n", rom_paths[i]); ret = false; goto end; } info[i].path = rom_paths[i]; info[i].data = rom_buf[i]; info[i].size = rom_len[i]; } if (rom_type == 0) ret = pretro_load_game(&info[0]); else ret = pretro_load_game_special(rom_type, info, roms); if (!ret) RARCH_ERR("Failed to load game.\n"); end: for (unsigned i = 0; i < MAX_ROMS; i++) free(rom_buf[i]); free(xml_buf); if (rom_file) fclose(rom_file); return ret; }
static void *audio_ext_init(const char *device, unsigned rate, unsigned latency) { if (!(*g_settings.audio.external_driver)) { RARCH_ERR("Please define an external audio driver.\n"); return NULL; } audio_ext_t *ext = (audio_ext_t*)calloc(1, sizeof(*ext)); if (!ext) return NULL; rarch_audio_driver_info_t info = {0}; const rarch_audio_driver_t *(*plugin_load)(void) = NULL; ext->lib = dylib_load(g_settings.audio.external_driver); if (!ext->lib) { RARCH_ERR("Failed to load external library \"%s\"\n", g_settings.audio.external_driver); goto error; } plugin_load = (const rarch_audio_driver_t *(*)(void))dylib_proc(ext->lib, "rarch_audio_driver_init"); if (!plugin_load) { RARCH_ERR("Failed to find symbol \"rarch_audio_driver_init\" in plugin.\n"); goto error; } ext->driver = plugin_load(); if (!ext->driver) { RARCH_ERR("Received invalid driver from plugin.\n"); goto error; } RARCH_LOG("Loaded external audio driver: \"%s\"\n", ext->driver->ident ? ext->driver->ident : "Unknown"); if (ext->driver->api_version != RARCH_AUDIO_API_VERSION) { RARCH_ERR("API mismatch in external audio plugin. RetroArch: %d, Plugin: %d ...\n", RARCH_AUDIO_API_VERSION, ext->driver->api_version); goto error; } info.device = device; info.sample_rate = rate; info.latency = latency; ext->handle = ext->driver->init(&info); if (!ext->handle) { RARCH_ERR("Failed to init audio driver.\n"); goto error; } if (ext->driver->sample_rate) g_settings.audio.out_rate = ext->driver->sample_rate(ext->handle); if (!g_settings.audio.sync) ext->driver->set_nonblock_state(ext->handle, RARCH_TRUE); return ext; error: audio_ext_free(ext); return NULL; }
static void* rmenu_xui_init(void) { HRESULT hr; TypefaceDescriptor typeface = {0}; menu_handle_t *menu = (menu_handle_t*)calloc(1, sizeof(*menu)); if (!menu) return NULL; d3d_video_t *d3d= (d3d_video_t*)driver.video_data; if (d3d->resolution_hd_enable) RARCH_LOG("HD menus enabled.\n"); D3DPRESENT_PARAMETERS d3dpp; video_info_t video_info = {0}; video_info.vsync = g_settings.video.vsync; video_info.force_aspect = false; video_info.smooth = g_settings.video.smooth; video_info.input_scale = 2; video_info.fullscreen = true; video_info.rgb32 = false; d3d_make_d3dpp(d3d, &video_info, &d3dpp); hr = app.InitShared(d3d->dev, &d3dpp, XuiPNGTextureLoader); if (FAILED(hr)) { RARCH_ERR("Failed initializing XUI application.\n"); goto error; } /* Register font */ typeface.szTypeface = L"Arial Unicode MS"; typeface.szLocator = L"file://game:/media/rarch.ttf"; typeface.szReserved1 = NULL; hr = XuiRegisterTypeface( &typeface, TRUE ); if (FAILED(hr)) { RARCH_ERR("Failed to register default typeface.\n"); goto error; } hr = XuiLoadVisualFromBinary( L"file://game:/media/rarch_scene_skin.xur", NULL); if (FAILED(hr)) { RARCH_ERR("Failed to load skin.\n"); goto error; } hr = XuiSceneCreate(d3d->resolution_hd_enable ? L"file://game:/media/hd/" : L"file://game:/media/sd/", L"rarch_main.xur", NULL, &root_menu); if (FAILED(hr)) { RARCH_ERR("Failed to create scene 'rarch_main.xur'.\n"); goto error; } current_menu = root_menu; hr = XuiSceneNavigateFirst(app.GetRootObj(), current_menu, XUSER_INDEX_FOCUS); if (FAILED(hr)) { RARCH_ERR("XuiSceneNavigateFirst failed.\n"); goto error; } if (driver.video_data && driver.video_poke && driver.video_poke->set_texture_enable) driver.video_poke->set_texture_frame(driver.video_data, NULL, true, 0, 0, 1.0f); xui_msg_queue = msg_queue_new(16); return menu; error: free(menu); return NULL; }
/* Initializes and loads a content file for the currently * selected libretro core. */ bool content_init(void) { content_information_ctx_t content_ctx; bool ret = true; char *error_string = NULL; rarch_system_info_t *sys_info = NULL; settings_t *settings = config_get_ptr(); temporary_content = string_list_new(); runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &sys_info); content_ctx.temporary_content = temporary_content; content_ctx.history_list_enable = false; content_ctx.directory_system = NULL; content_ctx.directory_cache = NULL; content_ctx.valid_extensions = NULL; content_ctx.block_extract = false; content_ctx.need_fullpath = false; content_ctx.set_supports_no_game_enable = false; content_ctx.subsystem.data = NULL; content_ctx.subsystem.size = 0; if (sys_info) { content_ctx.history_list_enable = settings->history_list_enable; content_ctx.set_supports_no_game_enable = settings->set_supports_no_game_enable; if (!string_is_empty(settings->directory.system)) content_ctx.directory_system = strdup(settings->directory.system); if (!string_is_empty(settings->directory.cache)) content_ctx.directory_cache = strdup(settings->directory.cache); if (!string_is_empty(sys_info->info.valid_extensions)) content_ctx.valid_extensions = strdup(sys_info->info.valid_extensions); content_ctx.block_extract = sys_info->info.block_extract; content_ctx.need_fullpath = sys_info->info.need_fullpath; content_ctx.subsystem.data = sys_info->subsystem.data; content_ctx.subsystem.size = sys_info->subsystem.size; } if ( !temporary_content || !content_file_init(&content_ctx, error_string)) { content_deinit(); ret = false; goto end; } _content_is_inited = true; end: if (content_ctx.directory_system) free(content_ctx.directory_system); if (content_ctx.directory_cache) free(content_ctx.directory_cache); if (content_ctx.valid_extensions) free(content_ctx.valid_extensions); if (error_string) { if (ret) { RARCH_LOG("%s\n", error_string); } else { RARCH_ERR("%s\n", error_string); } runloop_msg_queue_push(error_string, 2, ret ? 1 : 180, true); free(error_string); } return ret; }
static void gfx_ctx_set_swap_interval(unsigned interval) { RARCH_LOG("gfx_ctx_set_swap_interval(%d).\n", interval); eglSwapInterval(g_egl_dpy, interval); }