diff --git a/Makefile b/Makefile index acbd1f586e..93238a1a9d 100644 --- a/Makefile +++ b/Makefile @@ -257,6 +257,8 @@ clean: rm -f audio/*.o rm -f conf/*.o rm -f gfx/*.o + rm -f gfx/fonts/*.o + rm -f gfx/context/*.o rm -f gfx/py_state/*.o rm -f record/*.o rm -f input/*.o diff --git a/Makefile.win b/Makefile.win index 9cde4ad3cc..9f282a6e90 100644 --- a/Makefile.win +++ b/Makefile.win @@ -94,7 +94,7 @@ ifeq ($(HAVE_DYLIB), 1) endif ifeq ($(HAVE_NETPLAY), 1) - DEFINES += -DHAVE_NETPLAY + DEFINES += -DHAVE_NETPLAY -DHAVE_NETWORK_CMD OBJ += netplay.o network_cmd.o LIBS += -lws2_32 endif @@ -184,6 +184,8 @@ clean: rm -f audio/xaudio-c/*.o rm -f conf/*.o rm -f gfx/*.o + rm -f gfx/context/*.o + rm -f gfx/fonts/*.o rm -f gfx/py_state/*.o rm -f record/*.o rm -f input/*.o diff --git a/config.def.h b/config.def.h index 2e986c59ed..8312bb3111 100644 --- a/config.def.h +++ b/config.def.h @@ -345,7 +345,7 @@ static const struct snes_keybind snes_keybinds_1[] = { { true, RARCH_CHEAT_INDEX_PLUS, SK_y, NO_BTN, AXIS_NONE }, { true, RARCH_CHEAT_INDEX_MINUS, SK_t, NO_BTN, AXIS_NONE }, { true, RARCH_CHEAT_TOGGLE, SK_u, NO_BTN, AXIS_NONE }, - { true, RARCH_SCREENSHOT, SK_PRINT, NO_BTN, AXIS_NONE }, + { true, RARCH_SCREENSHOT, SK_F8, NO_BTN, AXIS_NONE }, { true, RARCH_DSP_CONFIG, SK_c, NO_BTN, AXIS_NONE }, { true, RARCH_MUTE, SK_F9, NO_BTN, AXIS_NONE }, { true, RARCH_NETPLAY_FLIP, SK_i, NO_BTN, AXIS_NONE }, diff --git a/configure b/configure index 2c058a58ba..fc410d94ea 100755 --- a/configure +++ b/configure @@ -1,14 +1,10 @@ #!/bin/sh -echo "" - PACKAGE_NAME=retroarch PACKAGE_VERSION=0.9.6 . qb/qb.params.sh . qb/qb.comp.sh -. qb/config.libs.sh - - +. qb/qb.libs.sh diff --git a/console/fileio/file_browser.h b/console/fileio/file_browser.h index 8ebd074555..6fb77f70e1 100644 --- a/console/fileio/file_browser.h +++ b/console/fileio/file_browser.h @@ -18,6 +18,7 @@ #define FILEBROWSER_H_ #define MAXJOLIET 255 +#define MAX_DIR_STACK 25 #include #include @@ -28,7 +29,7 @@ #include #define FS_MAX_PATH 256 #define FS_MAX_FS_PATH_LENGTH 255 -#define MAX_FILE_LIMIT 30000 +#define MAX_FILE_LIMIT 8192 #elif defined(_XBOX) #define FS_MAX_PATH MAX_PATH #define FS_MAX_FS_PATH_LENGTH 2048 @@ -54,9 +55,9 @@ typedef struct uint32_t file_count; /* amount of files in current dir*/ uint32_t currently_selected; /* currently select browser entry*/ uint32_t directory_stack_size; - char dir[128][FS_MAX_FS_PATH_LENGTH]; /* info of the current directory*/ + char dir[MAX_DIR_STACK][FS_MAX_FS_PATH_LENGTH]; /* info of the current directory*/ DirectoryEntry cur[MAX_FILE_LIMIT]; /* current file listing*/ - char extensions[512]; /* allowed extensions*/ + char extensions[FS_MAX_PATH]; /* allowed extensions*/ } filebrowser_t; void filebrowser_new(filebrowser_t * filebrowser, const char * start_dir, const char * extensions); diff --git a/console/libretro_mgmt.c b/console/libretro_mgmt.c index b5995b4a24..48ed9a6dca 100644 --- a/console/libretro_mgmt.c +++ b/console/libretro_mgmt.c @@ -87,7 +87,7 @@ const char *rarch_manage_libretro_set_first_file(const char *libretro_path, cons //We need to set libretro to the first entry in the cores //directory so that it will be saved to the config file - char ** dir_list = dir_list_new(libretro_path, exe_ext); + char ** dir_list = dir_list_new(libretro_path, exe_ext, false); const char * retstr = NULL; const char * first_exe; diff --git a/console/salamander/main.c b/console/salamander/main.c index 429ea54178..8fb038e22e 100644 --- a/console/salamander/main.c +++ b/console/salamander/main.c @@ -87,9 +87,9 @@ static void find_and_set_first_file(void) // we can find in the RetroArch cores directory #if defined(_XBOX) - char ** dir_list = dir_list_new("game:\\", ".xex"); + char ** dir_list = dir_list_new("game:\\", ".xex", false); #elif defined(__CELLOS_LV2__) - char ** dir_list = dir_list_new(LIBRETRO_DIR_PATH, ".SELF"); + char ** dir_list = dir_list_new(LIBRETRO_DIR_PATH, ".SELF", false); #endif if (!dir_list) diff --git a/driver.c b/driver.c index 1c8dc38290..9f4fb80cdf 100644 --- a/driver.c +++ b/driver.c @@ -477,7 +477,7 @@ static void init_shader_dir(void) if (!*g_settings.video.shader_dir) return; - g_extern.shader_dir.elems = dir_list_new(g_settings.video.shader_dir, ".shader"); + g_extern.shader_dir.elems = dir_list_new(g_settings.video.shader_dir, ".shader", false); g_extern.shader_dir.size = 0; g_extern.shader_dir.ptr = 0; if (g_extern.shader_dir.elems) diff --git a/driver.h b/driver.h index 83659c5d61..fb94d9afd5 100644 --- a/driver.h +++ b/driver.h @@ -166,6 +166,10 @@ typedef struct video_driver #endif void (*set_rotation)(void *data, unsigned rotation); + void (*viewport_size)(void *data, unsigned *width, unsigned *height); + + // Reads out in BGR byte order (24bpp). + bool (*read_viewport)(void *data, uint8_t *buffer); } video_driver_t; typedef struct driver @@ -252,6 +256,8 @@ extern const input_driver_t input_linuxraw; #define video_xml_shader_func(path) driver.video->xml_shader(driver.video_data, path) #define video_set_rotation_func(rotate) driver.video->set_rotation(driver.video_data, rotate) #define video_set_aspect_ratio_func(aspect_idx) driver.video->set_aspect_ratio(driver.video_data, aspect_idx) +#define video_viewport_size_func(width, height) driver.video->viewport_size(driver.video_data, width, height) +#define video_read_viewport_func(buffer) driver.video->read_viewport(driver.video_data, buffer) #define video_free_func() driver.video->free(driver.video_data) #define input_init_func() driver.input->init() diff --git a/dynamic.c b/dynamic.c index c0d2a8d542..61120b5818 100644 --- a/dynamic.c +++ b/dynamic.c @@ -317,11 +317,18 @@ static bool environment_cb(unsigned cmd, void *data) } 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; default: diff --git a/file.h b/file.h index 2fce5e9f49..2ad5972181 100644 --- a/file.h +++ b/file.h @@ -43,7 +43,7 @@ bool init_rom_file(enum rarch_game_type type); // Returns a NULL-terminated list of files in a directory with full paths. // If ext is NULL, any file will be picked. // If non-NULL, only files with extension ext are added. -char **dir_list_new(const char *dir, const char *ext); +char **dir_list_new(const char *dir, const char *ext, bool include_dirs); void dir_list_free(char **dir_list); bool path_is_directory(const char *path); diff --git a/file_path.c b/file_path.c index c38f366aa9..009c56106c 100644 --- a/file_path.c +++ b/file_path.c @@ -43,7 +43,7 @@ #endif // Yep, this is C alright ;) -char **dir_list_new(const char *dir, const char *ext) +char **dir_list_new(const char *dir, const char *ext, bool include_dirs) { size_t cur_ptr = 0; size_t cur_size = 32; @@ -94,13 +94,29 @@ char **dir_list_new(const char *dir, const char *ext) { // Not a perfect search of course, but hopefully good enough in practice. #ifdef _WIN32 - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - continue; - if (ext && !strstr(ffd.cFileName, ext)) - continue; + if (include_dirs) + { + if (ext && !strstr(ffd.cFileName, ext) && !path_is_directory(ffd.cFileName)) + continue; + } + else + { + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + if (ext && !strstr(ffd.cFileName, ext)) + continue; + } #else - if (ext && !strstr(entry->d_name, ext)) - continue; + if (include_dirs) + { + if (ext && !strstr(entry->d_name, ext) && !path_is_directory(entry->d_name)) + continue; + } + else + { + if (ext && !strstr(entry->d_name, ext)) + continue; + } #endif dir_list[cur_ptr] = (char*)malloc(PATH_MAX); @@ -175,10 +191,6 @@ bool path_is_directory(const char *path) return false; return buf.st_mode & CELL_FS_S_IFDIR; -#elif defined(XENON) - // Dummy - (void)path; - return false; #else struct stat buf; if (stat(path, &buf) < 0) diff --git a/general.h b/general.h index 796079c323..fc59c3a0f2 100644 --- a/general.h +++ b/general.h @@ -169,6 +169,7 @@ struct settings char cheat_settings_path[PATH_MAX]; char screenshot_directory[PATH_MAX]; + char system_directory[PATH_MAX]; bool rewind_enable; size_t rewind_buffer_size; diff --git a/gfx/ext/rarch_video.h b/gfx/ext/rarch_video.h index 199e9ac604..d56d0ba000 100644 --- a/gfx/ext/rarch_video.h +++ b/gfx/ext/rarch_video.h @@ -24,7 +24,7 @@ extern "C" { #define RARCH_API_CALLTYPE #endif -#define RARCH_GRAPHICS_API_VERSION 2 +#define RARCH_GRAPHICS_API_VERSION 3 // Since we don't want to rely on C++ or C99 for a proper boolean type, // make sure return semantics are perfectly clear ... ;) @@ -204,7 +204,7 @@ typedef struct rarch_input_driver // The range of this is [0, 1], // where 0 means any displacement will register, // and 1 means the axis has to be pressed all the way to register. - void *(*init)(const int joypad_index[5], float axis_threshold); + void *(*init)(const int joypad_index[8], float axis_threshold); // Polls input. Called once every frame. void (*poll)(void *data); @@ -264,6 +264,16 @@ typedef struct rarch_video_driver // Needs to be defined to RARCH_GRAPHICS_API_VERSION. // This is used to detect API/ABI mismatches. int api_version; + + // The final image should be rotated counter-clockwise by rot * 90 degrees. + void (*set_rotation)(void *data, unsigned rot); + + // Gets the current width/height of the viewport. + void (*viewport_size)(void *data, unsigned *width, unsigned *height); + + // Reads the content of the viewport into memory. + // Tightly packed BGR888. Pitch is width * 3. + int (*read_viewport)(void *data, unsigned char *buffer); } rarch_video_driver_t; // Called by RetroArch on startup to get a driver handle. diff --git a/gfx/ext_gfx.c b/gfx/ext_gfx.c index 6f917bf0a3..be8736044e 100644 --- a/gfx/ext_gfx.c +++ b/gfx/ext_gfx.c @@ -183,9 +183,8 @@ static bool video_ext_frame(void *data, const void *frame, unsigned width, unsig static void *setup_input(ext_t *ext, const rarch_input_driver_t *driver) { - // TODO: Change external API to allow more players. To be done in next major ABI break. - int joypad_index[5]; - for (unsigned i = 0; i < 5; i++) + int joypad_index[8]; + for (unsigned i = 0; i < 8; i++) joypad_index[i] = g_settings.input.joypad_map[i] < 0 ? -1 : g_settings.input.joypad_map[i]; void *handle = driver->init(joypad_index, g_settings.input.axis_threshold); @@ -213,9 +212,11 @@ static bool setup_video(ext_t *ext, const video_info_t *video, const input_drive return false; } - const char *cg_shader = NULL; + const char *cg_shader = NULL; const char *xml_shader = NULL; + enum rarch_shader_type type = g_settings.video.shader_type; + if ((type == RARCH_SHADER_CG || type == RARCH_SHADER_AUTO) && *g_settings.video.cg_shader_path) cg_shader = g_settings.video.cg_shader_path; else if ((type == RARCH_SHADER_BSNES || type == RARCH_SHADER_AUTO) && *g_settings.video.bsnes_shader_path) @@ -247,25 +248,25 @@ static bool setup_video(ext_t *ext, const video_info_t *video, const input_drive gfx_window_title(title_buf, sizeof(title_buf)); rarch_video_info_t info = {0}; - info.width = video->width; - info.height = video->height; - info.fullscreen = video->fullscreen; - info.vsync = video->vsync; - info.force_aspect = video->force_aspect; - info.aspect_ratio = g_settings.video.aspect_ratio; - info.smooth = video->smooth; - info.input_scale = video->input_scale; - info.color_format = video->rgb32 ? RARCH_COLOR_FORMAT_ARGB8888 : RARCH_COLOR_FORMAT_XRGB1555; - info.xml_shader = xml_shader; - info.cg_shader = cg_shader; - info.ttf_font = font; - info.ttf_font_size = g_settings.video.font_size; - info.ttf_font_color = (font_color_r << 16) | (font_color_g << 8) | (font_color_b << 0); - info.title_hint = title_buf; + info.width = video->width; + info.height = video->height; + info.fullscreen = video->fullscreen; + info.vsync = video->vsync; + info.force_aspect = video->force_aspect; + info.aspect_ratio = g_settings.video.aspect_ratio; + info.smooth = video->smooth; + info.input_scale = video->input_scale; + info.color_format = video->rgb32 ? RARCH_COLOR_FORMAT_ARGB8888 : RARCH_COLOR_FORMAT_XRGB1555; + info.xml_shader = xml_shader; + info.cg_shader = cg_shader; + info.ttf_font = font; + info.ttf_font_size = g_settings.video.font_size; + info.ttf_font_color = (font_color_r << 16) | (font_color_g << 8) | (font_color_b << 0); + info.title_hint = title_buf; #ifdef HAVE_PYTHON - info.python_state_new = py_state_new; - info.python_state_get = py_state_get; + info.python_state_new = py_state_new; + info.python_state_get = py_state_get; info.python_state_free = py_state_free; #endif @@ -335,6 +336,24 @@ error: return NULL; } +static void video_set_rotation(void *data, unsigned rot) +{ + ext_t *ext = (ext_t*)data; + ext->driver->set_rotation(ext->handle, rot); +} + +static void video_viewport_size(void *data, unsigned *width, unsigned *height) +{ + ext_t *ext = (ext_t*)data; + ext->driver->viewport_size(ext->handle, width, height); +} + +static bool video_read_viewport(void *data, uint8_t *buffer) +{ + ext_t *ext = (ext_t*)data; + return ext->driver->read_viewport(ext->handle, buffer); +} + const video_driver_t video_ext = { video_ext_init, video_ext_frame, @@ -343,6 +362,10 @@ const video_driver_t video_ext = { video_ext_focus, NULL, video_ext_free, - "ext" + "ext", + + video_set_rotation, + video_viewport_size, + video_read_viewport, }; diff --git a/gfx/gl.c b/gfx/gl.c index 518ff7cd27..a1e76f41d2 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -46,6 +46,9 @@ #include "shader_glsl.h" #endif +extern const GLfloat vertexes_flipped[]; +extern const GLfloat white_color[]; + // Used for the last pass when rendering to the back buffer. const GLfloat vertexes_flipped[] = { 0, 0, @@ -440,20 +443,8 @@ void gl_set_projection(gl_t *gl, struct gl_ortho *ortho, bool allow_rotate) void gl_set_viewport(gl_t *gl, unsigned width, unsigned height, bool force_full, bool allow_rotate) { - unsigned vp_x_temp, vp_y_temp, vp_width_temp, vp_height_temp; - struct gl_ortho ortho = {0}; - - vp_x_temp = 0; - vp_y_temp = 0; - vp_width_temp = width; - vp_height_temp = height; - - ortho.left = 0.0f; - ortho.right = 1.0f; - ortho.bottom = 0.0f; - ortho.top = 1.0f; - ortho.znear = -1.0f; - ortho.zfar = 1.0f; + unsigned x = 0, y = 0; + struct gl_ortho ortho = {0, 1, 0, 1, -1, 1}; if (gl->keep_aspect && !force_full) { @@ -464,11 +455,10 @@ void gl_set_viewport(gl_t *gl, unsigned width, unsigned height, bool force_full, #ifdef RARCH_CONSOLE if (g_console.aspect_ratio_index == ASPECT_RATIO_CUSTOM) { - delta = (desired_aspect / device_aspect - 1.0) / 2.0 + 0.5; - vp_x_temp = g_console.viewports.custom_vp.x; - vp_y_temp = g_console.viewports.custom_vp.y; - vp_width_temp = g_console.viewports.custom_vp.width; - vp_height_temp = g_console.viewports.custom_vp.height; + x = g_console.viewports.custom_vp.x; + y = g_console.viewports.custom_vp.y; + width = g_console.viewports.custom_vp.width; + height = g_console.viewports.custom_vp.height; } else #endif @@ -481,31 +471,29 @@ void gl_set_viewport(gl_t *gl, unsigned width, unsigned height, bool force_full, else if (device_aspect > desired_aspect) { delta = (desired_aspect / device_aspect - 1.0) / 2.0 + 0.5; - vp_x_temp = (GLint)(width * (0.5 - delta)); - vp_width_temp = (GLint)(2.0 * width * delta); + x = (unsigned)(width * (0.5 - delta)); width = (unsigned)(2.0 * width * delta); } else { - delta = (device_aspect / desired_aspect - 1.0) / 2.0 + 0.5; - vp_y_temp = (GLint)(height * (0.5 - delta)); - vp_height_temp = (GLint)(2.0 * height * delta); + delta = (device_aspect / desired_aspect - 1.0) / 2.0 + 0.5; + y = (unsigned)(height * (0.5 - delta)); height = (unsigned)(2.0 * height * delta); } } } - glViewport(vp_x_temp, vp_y_temp, vp_width_temp, vp_height_temp); + glViewport(x, y, width, height); gl_set_projection(gl, &ortho, allow_rotate); - gl->vp_width = width; + gl->vp_width = width; gl->vp_height = height; // Set last backbuffer viewport. if (!force_full) { - gl->vp_out_width = width; + gl->vp_out_width = width; gl->vp_out_height = height; } @@ -1227,6 +1215,36 @@ static bool gl_xml_shader(void *data, const char *path) } #endif +#ifndef HAVE_RGL +static void gl_viewport_size(void *data, unsigned *width, unsigned *height) +{ + (void)data; + + GLint vp[4]; + glGetIntegerv(GL_VIEWPORT, vp); + + *width = vp[2]; + *height = vp[3]; +} + +static bool gl_read_viewport(void *data, uint8_t *buffer) +{ + (void)data; + + GLint vp[4]; + glGetIntegerv(GL_VIEWPORT, vp); + + glPixelStorei(GL_PACK_ALIGNMENT, get_alignment(vp[2])); + glPixelStorei(GL_PACK_ROW_LENGTH, vp[2]); + + glReadPixels(vp[0], vp[1], + vp[2], vp[3], + GL_BGR, GL_UNSIGNED_BYTE, buffer); + + return true; +} +#endif + #ifdef RARCH_CONSOLE static void gl_start(void) { @@ -1323,5 +1341,13 @@ const video_driver_t video_gl = { #endif gl_set_rotation, + +#ifndef HAVE_RGL + gl_viewport_size, + gl_read_viewport, +#else + NULL, + NULL, +#endif }; diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 6b43d7b8cf..be00556490 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -225,7 +225,7 @@ void gl_shader_use(unsigned index); void gl_set_projection(gl_t *gl, struct gl_ortho *ortho, bool allow_rotate); void gl_set_viewport(gl_t *gl, unsigned width, unsigned height, bool force_full, bool allow_rotate); -void gl_init_fbo(gl_t * gl, unsigned width, unsigned height); +void gl_init_fbo(gl_t *gl, unsigned width, unsigned height); void gl_deinit_fbo(gl_t *gl); #endif diff --git a/libretro.h b/libretro.h index e497aff58d..28ea262041 100755 --- a/libretro.h +++ b/libretro.h @@ -121,7 +121,7 @@ extern "C" { // Requests the frontend to shutdown. // Should only be used if game has a specific // way to shutdown the game from a menu item or similar. - + // #define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 // const unsigned * -- // Gives a hint to the frontend how demanding this implementation @@ -142,6 +142,15 @@ extern "C" { // as certain games an implementation can play might be // particularily demanding. // If called, it should be called in retro_load_game(). + // +#define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 + // const char ** -- + // Returns the "system" directory of the frontend. + // This directory can be used to store system specific ROMs such as BIOSes, configuration data, etc. + // The returned value can be NULL. + // If so, no such directory is defined, + // and it's up to the implementation to find a suitable directory. + struct retro_message { diff --git a/qb/config.libs.sh b/qb/config.libs.sh index f0d3c950f5..9300e8e183 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -1,19 +1,14 @@ -. qb/qb.libs.sh - -check_switch_c C99 -std=gnu99 -check_critical C99 "Cannot find C99 compatible compiler." +check_switch_c C99 -std=gnu99 "Cannot find C99 compatible compiler." check_switch_c NOUNUSED -Wno-unused-result -add_define_make NOUNUSED $HAVE_NOUNUSED +add_define_make NOUNUSED "$HAVE_NOUNUSED" # There are still broken 64-bit Linux distros out there. :) -if [ -d /usr/lib64 ]; then - add_library_dirs /usr/lib64 -fi +[ -d /usr/lib64 ] && add_library_dirs /usr/lib64 -if [ -d /opt/local/lib ]; then - add_library_dirs /opt/local/lib -fi +[ -d /opt/local/lib ] && add_library_dirs /opt/local/lib + +if [ "$OS" = 'BSD' ]; then DYLIB=-lc; else DYLIB=-ldl; fi if [ -d /opt/vc/lib ]; then add_library_dirs /opt/vc/lib @@ -26,45 +21,38 @@ else HAVE_RPI=no fi -if [ "$OS" = BSD ]; then - DYLIB=-lc -else - DYLIB=-ldl -fi -if [ -z "$LIBRETRO" ]; then - LIBRETRO="-lretro" -else +if [ "$LIBRETRO" ]; then echo "Explicit libsnes used, disabling dynamic libsnes loading ..." - HAVE_DYNAMIC=no + HAVE_DYNAMIC='no' +else LIBRETRO="-lretro" fi -if [ "$HAVE_DYNAMIC" != yes ]; then - check_lib_cxx RETRO $LIBRETRO retro_init $DYLIB - check_critical RETRO "Cannot find libretro." - add_define_make libretro $LIBRETRO -fi +[ "$HAVE_DYNAMIC" = 'yes' ] || { + check_lib_cxx RETRO "$LIBRETRO" retro_init "$DYLIB" "Cannot find libretro." + add_define_make libretro "$LIBRETRO" +} check_lib THREADS -lpthread pthread_create -check_lib DYLIB $DYLIB dlopen +check_lib DYLIB "$DYLIB" dlopen check_lib NETPLAY -lc socket -if [ "$HAVE_NETPLAY" = yes ]; then +if [ "$HAVE_NETPLAY" = 'yes' ]; then HAVE_GETADDRINFO=auto check_lib GETADDRINFO -lc getaddrinfo - if [ "$HAVE_GETADDRINFO" = yes ]; then - HAVE_SOCKET_LEGACY=no + if [ "$HAVE_GETADDRINFO" = 'yes' ]; then + HAVE_SOCKET_LEGACY='no' else - HAVE_SOCKET_LEGACY=yes + HAVE_SOCKET_LEGACY='yes' fi - HAVE_NETWORK_CMD=yes + HAVE_NETWORK_CMD='yes' else - HAVE_NETWORK_CMD=no + HAVE_NETWORK_CMD='no' fi check_lib GETOPT_LONG -lc getopt_long -if [ "$HAVE_DYLIB" = no ] && [ "$HAVE_DYNAMIC" = yes ]; then +if [ "$HAVE_DYLIB" = 'no' ] && [ "$HAVE_DYNAMIC" = 'yes' ]; then echo "Dynamic loading of libsnes is enabled, but your platform does not appear to have dlopen(), use --disable-dynamic or --with-libsnes=\"-lsnes\"". exit 1 fi @@ -93,31 +81,29 @@ check_pkgconf PULSE libpulse check_lib COREAUDIO "-framework AudioUnit" AudioUnitInitialize -check_pkgconf SDL sdl 1.2.10 -check_critical SDL "Cannot find SDL library." +check_pkgconf SDL sdl 1.2.10 "Cannot find SDL library." # On some distros, -lCg doesn't link against -lstdc++ it seems ... -if [ "$HAVE_OPENGL" != no ]; then +if [ "$HAVE_OPENGL" != 'no' ]; then check_lib_cxx CG -lCg cgCreateContext else echo "Ignoring Cg. OpenGL is not enabled." - HAVE_CG=no + HAVE_CG='no' fi check_pkgconf XML libxml-2.0 check_pkgconf SDL_IMAGE SDL_image -if [ "$HAVE_THREADS" != no ]; then - if [ "$HAVE_FFMPEG" != no ]; then +if [ "$HAVE_THREADS" != 'no' ]; then + if [ "$HAVE_FFMPEG" != 'no' ]; then check_pkgconf AVCODEC libavcodec check_pkgconf AVFORMAT libavformat check_pkgconf AVUTIL libavutil check_pkgconf SWSCALE libswscale - - ( [ "$HAVE_FFMPEG" = auto ] && ( [ "$HAVE_AVCODEC" = no ] || [ "$HAVE_AVFORMAT" = no ] || [ "$HAVE_AVUTIL" = no ] || [ "$HAVE_SWSCALE" = no ] ) && HAVE_FFMPEG=no ) || HAVE_FFMPEG=yes + ( [ "$HAVE_FFMPEG" = 'auto' ] && ( [ "$HAVE_AVCODEC" = 'no' ] || [ "$HAVE_AVFORMAT" = 'no' ] || [ "$HAVE_AVUTIL" = 'no' ] || [ "$HAVE_SWSCALE" = 'no' ] ) && HAVE_FFMPEG='no' ) || HAVE_FFMPEG='yes' fi - if [ "$HAVE_FFMPEG" = yes ]; then + if [ "$HAVE_FFMPEG" = 'yes' ]; then check_lib FFMPEG_ALLOC_CONTEXT3 "$AVCODEC_LIBS" avcodec_alloc_context3 check_lib FFMPEG_AVCODEC_OPEN2 "$AVCODEC_LIBS" avcodec_open2 check_lib FFMPEG_AVCODEC_ENCODE_AUDIO2 "$AVCODEC_LIBS" avcodec_encode_audio2 @@ -127,34 +113,33 @@ if [ "$HAVE_THREADS" != no ]; then check_lib FFMPEG_AVCODEC_ENCODE_VIDEO2 "$AVCODEC_LIBS" avcodec_encode_video2 fi - if [ "$HAVE_FFMPEG" = no ] && [ "$HAVE_X264RGB" = yes ]; then + if [ "$HAVE_FFMPEG" = 'no' ] && [ "$HAVE_X264RGB" = 'yes' ]; then echo "x264 RGB recording is enabled, but FFmpeg is not. --enable-x264rgb will not have any effect." fi else echo "Not building with threading support. Will skip FFmpeg." - HAVE_FFMPEG=no + HAVE_FFMPEG='no' fi -check_lib DYNAMIC $DYLIB dlopen +check_lib DYNAMIC "$DYLIB" dlopen check_pkgconf FREETYPE freetype2 check_pkgconf X11 x11 check_pkgconf XEXT xext -if [ "$HAVE_X11" = yes ] && [ "$HAVE_XEXT" = yes ]; then +if [ "$HAVE_X11" = 'yes' ] && [ "$HAVE_XEXT" = 'yes' ]; then check_pkgconf XVIDEO xv else echo "X11 or Xext not present. Skipping XVideo." - HAVE_XVIDEO=no + HAVE_XVIDEO='no' fi check_lib STRL -lc strlcpy check_pkgconf PYTHON python3 -add_define_make OS $OS +add_define_make OS "$OS" # Creates config.mk and config.h. VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY NETWORK_CMD SOCKET_LEGACY FBO STRL PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM FFMPEG_AVCODEC_ENCODE_AUDIO2 FFMPEG_AVCODEC_ENCODE_VIDEO2 X264RGB SINC BSV_MOVIE RPI" create_config_make config.mk $VARS -create_config_header config.h $VARS - +create_config_header config.h $VARS \ No newline at end of file diff --git a/qb/qb.comp.sh b/qb/qb.comp.sh index 3ff8f9c469..20324b4edb 100644 --- a/qb/qb.comp.sh +++ b/qb/qb.comp.sh @@ -4,66 +4,46 @@ TEMP_C=.tmp.c TEMP_CXX=.tmp.cxx TEMP_EXE=.tmp -ECHOBUF="Checking operating system ... " -OS="Win32" # whatever ;D -unamestr="`uname -a`" -if [ ! -z "`echo "$unamestr" | grep -i Linux`" ]; then - OS="Linux" -elif [ ! -z "`echo "$unamestr" | grep -i Darwin`" ]; then - OS="Darwin" -elif [ ! -z "`echo "$unamestr" | grep -i BSD`" ]; then - OS="BSD" -elif [ ! -z "`echo "$unamestr" | grep -i MINGW32`" ]; then - OS="MinGW" -elif [ ! -z "`echo "$unamestr" | grep -i NT`" ]; then - OS="Cygwin" -fi - -echo $ECHOBUF $OS +ECHOBUF="Checking operating system" +#echo -n "Checking operating system" +case "$(uname)" in + 'Linux') OS='Linux';; + *'BSD') OS='BSD';; + 'Darwin') OS='Darwin';; + 'MINGW32'*) OS='MinGW';; + 'CYGWIN'*) OS='Cygwin';; + *) OS="Win32";; +esac +echo "$ECHOBUF ... $OS" # Checking for working C compiler -if [ "$USE_LANG_C" = yes ]; then - echo "Checking for working C compiler ..." - if [ -z $CC ]; then - CC=`which gcc cc 2> /dev/null | grep ^/ | head -n 1` - fi - if [ -z $CC ]; then - echo "Could not find C compiler in path. Exiting ..." - exit 1 - fi - - ECHOBUF="Checking if $CC is a suitable compiler ..." - answer=no - echo "#include " > $TEMP_C - echo "int main(void) { puts(\"Hai world!\"); return 0; }" >> $TEMP_C - $CC -o $TEMP_EXE $TEMP_C 2>/dev/null >/dev/null && answer=yes - echo $ECHOBUF $answer - - rm -rf $TEMP_C $TEMP_EXE - - [ "$answer" = no ] && echo "Can't find suitable C compiler. Exiting ..." && exit 1 +if [ "$USE_LANG_C" = 'yes' ]; then + ECHOBUF="Checking for suitable working C compiler" +# echo -n "Checking for suitable working C compiler" + cat << EOF > "$TEMP_C" +#include +int main(void) { puts("Hai world!"); return 0; } +EOF + for CC in ${CC:=$(which gcc cc)} ''; do + "$CC" -o "$TEMP_EXE" "$TEMP_C" >/dev/null 2>&1 && break + done + [ "$CC" ] || { echo "$ECHOBUF ... Not found. Exiting."; exit 1;} + echo "$ECHOBUF ... $CC" + rm "$TEMP_C" "$TEMP_EXE" fi -# Checking for working C++ compiler -if [ "$USE_LANG_CXX" = "yes" ]; then - echo "Checking for working C++ compiler ..." - if [ -z $CXX ]; then - CXX=`which g++ c++ 2> /dev/null | grep ^/ | head -n 1` - fi - if [ -z $CXX ]; then - echo "Could not find C++ compiler in path. Exiting ..." - exit 1 - fi - - ECHOBUF="Checking if $CXX is a suitable compiler ..." - answer=no - echo "#include " > $TEMP_CXX - echo "int main() { std::cout << \"Hai guise\" << std::endl; return 0; }" >> $TEMP_CXX - $CXX -o $TEMP_EXE $TEMP_CXX 2>/dev/null >/dev/null && answer=yes - echo $ECHOBUF $answer - - rm -rf $TEMP_CXX $TEMP_EXE - - [ "$answer" = no ] && echo "Can't find suitable C++ compiler. Exiting ..." && exit 1 +# Checking for working C++ +if [ "$USE_LANG_CXX" = 'yes' ]; then + ECHOBUF="Checking for suitable working C++ compiler" +# echo -n "Checking for suitable working C++ compiler" + cat << EOF > "$TEMP_CXX" +#include +int main() { std::cout << "Hai guise" << std::endl; return 0; } +EOF + for CXX in ${CXX:=$(which g++ c++)} ''; do + "$CXX" -o "$TEMP_EXE" "$TEMP_CXX" >/dev/null 2>&1 && break + done + [ "$CXX" ] || { echo "$ECHOBUF ... Not found. Exiting."; exit 1;} + echo "$ECHOBUF ... $CXX" + rm "$TEMP_CXX" "$TEMP_EXE" fi - diff --git a/qb/qb.libs.sh b/qb/qb.libs.sh index aa1e2b12c3..15535f4057 100644 --- a/qb/qb.libs.sh +++ b/qb/qb.libs.sh @@ -1,352 +1,239 @@ +# echo -n is broken on recent OSX btw -PKG_CONF_PATH="" -PKG_CONF_USED="" -CONFIG_DEFINES="" -MAKEFILE_DEFINES="" -INCLUDE_DIRS="" -LIBRARY_DIRS="" -[ -z "$PREFIX" ] && PREFIX="/usr/local" +MAKEFILE_DEFINES='.MAKEFILE_DEFINES' +CONFIG_DEFINES='.CONFIG_DEFINES' +cat /dev/null > "$MAKEFILE_DEFINES" > "$CONFIG_DEFINES" +#cat /dev/null > "${MAKEFILE_DEFINES:=.MAKEFILE_DEFINES}" > "${CONFIG_DEFINES=.CONFIG_DEFINES}" + +[ "$PREFIX" ] || PREFIX="/usr/local" add_define_header() -{ - CONFIG_DEFINES="$CONFIG_DEFINES:@$1@$2@:" -} +{ echo "$1=$2" >> "$CONFIG_DEFINES";} add_define_make() -{ - MAKEFILE_DEFINES="$MAKEFILE_DEFINES:@$1@$2@:" -} +{ echo "$1=$2" >> "$MAKEFILE_DEFINES";} add_include_dirs() -{ - while [ ! -z "$1" ] - do - INCLUDE_DIRS="$INCLUDE_DIRS -I$1" - shift - done -} +{ while [ "$1" ]; do INCLUDE_DIRS="$INCLUDE_DIRS -I$1"; shift; done;} add_library_dirs() -{ - while [ ! -z "$1" ] - do - LIBRARY_DIRS="$LIBRARY_DIRS -L$1" - shift - done +{ while [ "$1" ]; do LIBRARY_DIRS="$LIBRARY_DIRS -L$1"; shift; done;} + +check_lib() #$1 = HAVE_$1 $2 = lib $3 = function in lib $4 = extralibs +{ tmpval="$(eval echo \$HAVE_$1)" + [ "$tmpval" = 'no' ] && return 0 + + if [ "$3" ]; then + ECHOBUF="Checking function $3 in ${2% }" + echo "void $3(void); int main(void) { $3(); return 0; }" > $TEMP_C + else + ECHOBUF="Checking existence of ${2% }" + echo "int main(void) { return 0; }" > $TEMP_C + fi + answer='no' +# echo -n "$ECHOBUF" + "$CC" -o "$TEMP_EXE" "$TEMP_C" $INCLUDE_DIRS $LIBRARY_DIRS $4 $CFLAGS $LDFLAGS $2 >/dev/null 2>&1 && answer='yes' + eval HAVE_$1="$answer"; echo "$ECHOBUF ... $answer" + rm "$TEMP_C" "$TEMP_EXE" >/dev/null 2>&1 + + [ "$tmpval" = 'yes' ] && [ "$answer" = 'no' ] && { + echo "Forced to build with library $2, but cannot locate. Exiting ..." + exit 1 + } } -check_lib() -{ - tmpval="HAVE_$1" - eval tmpval=\$$tmpval - [ "$tmpval" = "no" ] && return 0 +check_lib_cxx() #$1 = HAVE_$1 $2 = lib $3 = function in lib $4 = extralibs $5 = critical error message [checked only if non-empty] +{ tmpval="$(eval echo \$HAVE_$1)" + [ "$tmpval" = 'no' ] && return 0 - if [ -z "$3" ]; then - ECHOBUF="Checking existence of $2 ..." - echo "int main(void) { return 0; }" > $TEMP_C - else - ECHOBUF="Checking function $3 in $2 ..." - echo "void $3(void); int main(void) { $3(); return 0; }" > $TEMP_C - fi - - eval HAVE_$1=no - answer=no - - extralibs="$4" - - $CC -o $TEMP_EXE $TEMP_C $INCLUDE_DIRS $LIBRARY_DIRS $extralibs $CFLAGS $LDFLAGS $2 2>/dev/null >/dev/null && answer=yes && eval HAVE_$1=yes - - echo $ECHOBUF $answer - - rm -f $TEMP_C $TEMP_EXE - if [ "$tmpval" = "yes" ] && [ "$answer" = "no" ]; then - echo "Forced to build with library $2, but cannot locate. Exiting ..." - exit 1 - fi -} - -check_lib_cxx() -{ - tmpval="HAVE_$1" - eval tmpval=\$$tmpval - [ "$tmpval" = "no" ] && return 0 - - if [ -z "$3" ]; then - ECHOBUF="Checking existence of $2 ..." - echo "int main() { return 0; }" > $TEMP_CXX - else - ECHOBUF="Checking function $3 in $2 ..." - echo "extern \"C\" { void $3(void); } int main() { $3(); }" > $TEMP_CXX - fi - - eval HAVE_$1=no - answer=no - - extralibs="$4" - - $CXX -o $TEMP_EXE $TEMP_CXX $INCLUDE_DIRS $LIBRARY_DIRS $extralibs $CFLAGS $LDFLAGS $2 2>/dev/null >/dev/null && answer=yes && eval HAVE_$1=yes - - echo $ECHOBUF $answer - - rm -f $TEMP_CXX $TEMP_EXE - if [ "$tmpval" = "yes" ] && [ "$answer" = "no" ]; then - echo "Forced to build with library $2, but cannot locate. Exiting ..." - exit 1 - fi + if [ "$3" ]; then + ECHOBUF="Checking function $3 in ${2% }" + echo "extern \"C\" { void $3(void); } int main() { $3(); }" > $TEMP_CXX + else + ECHOBUF="Checking existence of ${2% }" + echo "int main() { return 0; }" > $TEMP_CXX + fi + answer='no' +# echo -n "$ECHOBUF" + "$CXX" -o "$TEMP_EXE" "$TEMP_CXX" $INCLUDE_DIRS $LIBRARY_DIRS $4 $CFLAGS $LDFLAGS $2 >/dev/null 2>&1 && answer='yes' + eval HAVE_$1="$answer"; echo "$ECHOBUF ... $answer" + rm "$TEMP_CXX" "$TEMP_EXE" >/dev/null 2>&1 + [ "$answer" = 'no' ] && { + [ "$5" ] && { echo "$5"; exit 1;} + [ "$tmpval" = 'yes' ] && { + echo "Forced to build with library $2, but cannot locate. Exiting ..." + exit 1 + } + + } } check_code_c() -{ - tmpval="HAVE_$1" - eval tmpval=\$$tmpval - [ "$tmpval" = "no" ] && return 0 +{ tmpval="$(eval echo \$HAVE_$1)" + [ "$tmpval" = 'no' ] && return 0 - ECHOBUF="Checking C code snippet \"$3\" ..." - eval HAVE_$1=no - answer=no - $CC -o $TEMP_EXE $TEMP_C $INCLUDE_DIRS $LIBRARY_DIRS $2 $CFLAGS $LDFLAGS 2>/dev/null >/dev/null && answer=yes && eval HAVE_$1=yes - - echo $ECHOBUF $answer - rm -f $TEMP_C $TEMP_EXE + ECHOBUF="Checking C code snippet \"$3\"" +# echo -n "Checking C code snippet \"$3\"" + answer='no' + "$CC" -o "$TEMP_EXE" "$TEMP_C" $INCLUDE_DIRS $LIBRARY_DIRS $2 $CFLAGS $LDFLAGS >/dev/null 2>&1 && answer='yes' + eval HAVE_$1="$answer"; echo "$ECHOBUF ... $answer" + rm "$TEMP_C" "$TEMP_EXE" >/dev/null 2>&1 } check_code_cxx() -{ - tmpval="HAVE_$1" - eval tmpval=\$$tmpval - [ "$tmpval" = "no" ] && return 0 +{ tmpval="$(eval echo \$HAVE_$1)" + [ "$tmpval" = 'no' ] && return 0 - ECHOBUF="Checking C++ code snippet \"$3\" ..." - eval HAVE_$1=no - answer=no - $CXX -o $TEMP_EXE $TEMP_CXX $INCLUDE_DIRS $LIBRARY_DIRS $2 $CXXFLAGS $LDFLAGS 2>/dev/null >/dev/null && answer=yes && eval HAVE_$1=yes - - echo $ECHOBUF $answer - rm -f $TEMP_CXX $TEMP_EXE + ECHOBUF="Checking C++ code snippet \"$3\"" +# echo -n "Checking C++ code snippet \"$3\"" + answer='no' + "$CXX" -o "$TEMP_EXE" "$TEMP_CXX" $INCLUDE_DIRS $LIBRARY_DIRS $2 $CXXFLAGS $LDFLAGS >/dev/null 2>&1 && answer='yes' + eval HAVE_$1="$answer"; echo "$ECHOBUF ... $answer" + rm "$TEMP_CXX" "$TEMP_EXE" >/dev/null 2>&1 } -locate_pkg_conf() -{ - ECHOBUF="Checking for pkg-config ... " - PKG_CONF_PATH="`which pkg-config | grep ^/ | head -n1`" - if [ -z $PKG_CONF_PATH ]; then - echo "not found" - echo "Cannot locate pkg-config. Exiting ..." - exit 1 - fi - echo $ECHOBUF $PKG_CONF_PATH +check_pkgconf() #$1 = HAVE_$1 $2 = package $3 = version $4 = critical error message [checked only if non-empty] +{ tmpval="$(eval echo \$HAVE_$1)" + [ "$tmpval" = 'no' ] && return 0 + + [ "$PKG_CONF_PATH" ] || { + ECHOBUF="Checking for pkg-config" +# echo -n "Checking for pkg-config" + for PKG_CONF_PATH in $(which pkg-config) ''; do [ "$PKG_CONF_PATH" ] && break; done + [ "$PKG_CONF_PATH" ] || { echo "Not found. Exiting ..."; exit 1;} + echo "$ECHOBUF ... $PKG_CONF_PATH" + } + + ECHOBUF="Checking presence of package $2" + [ "$3" ] && ECHOBUF="$ECHOBUF with minimum version $3" +# echo -n "$ECHOBUF ... " + answer='no' + pkg-config --atleast-version="${3:-0.0}" "$2" && { + answer='yes' + eval $1_CFLAGS=\"$(pkg-config $2 --cflags)\" + eval $1_LIBS=\"$(pkg-config $2 --libs)\" + } + + eval HAVE_$1="$answer"; echo "$ECHOBUF ... $answer" + PKG_CONF_USED="$PKG_CONF_USED $1" + [ "$answer" = 'no' ] && { + [ "$4" ] && { echo "$4"; exit 1;} + [ "$tmpval" = 'yes' ] && { + echo "Forced to build with package $2, but cannot locate. Exiting ..." + exit 1 + } + } } -check_pkgconf() -{ - [ -z "$PKG_CONF_PATH" ] && locate_pkg_conf - - tmpval="HAVE_$1" - eval tmpval=\$$tmpval - [ "$tmpval" = "no" ] && return 0 - - ECHOBUF="Checking presence of package $2" - eval HAVE_$1=no - eval $1_CFLAGS="" - eval $1_LIBS="" - answer=no - minver=0.0 - [ ! -z $3 ] && minver=$3 && ECHOBUF="$ECHOBUF with minimum version $minver" - ECHOBUF="$ECHOBUF ... " - pkg-config --atleast-version=$minver "$2" && eval HAVE_$1=yes && eval $1_CFLAGS='"`pkg-config $2 --cflags`"' && eval $1_LIBS='"`pkg-config $2 --libs`"' && answer=yes - echo $ECHOBUF $answer - - PKG_CONF_USED="$PKG_CONF_USED $1" - - if [ "$tmpval" = "yes" ] && [ "$answer" = "no" ]; then - echo "Forced to build with package $2, but cannot locate. Exiting ..." - exit 1 - fi +check_header() #$1 = HAVE_$1 $2 = header file +{ tmpval="$(eval echo \$HAVE_$1)" + [ "$tmpval" = 'no' ] && return 0 + ECHOBUF="Checking presence of header file $2" +# echo -n "Checking presence of header file $2" + cat << EOF > "$TEMP_C" +#include<$2> +int main(void) { return 0; } +EOF + answer='no' + "$CC" -o "$TEMP_EXE" "$TEMP_C" $INCLUDE_DIRS >/dev/null 2>&1 && answer='yes' + eval HAVE_$1="$answer"; echo "$ECHOBUF ... $answer" + rm "$TEMP_C" "$TEMP_EXE" >/dev/null 2>&1 + [ "$tmpval" = 'yes' ] && [ "$answer" = 'no' ] && { + echo "Build assumed that $2 exists, but cannot locate. Exiting ..." + exit 1 + } } -check_header() -{ - tmpval="HAVE_$1" - eval tmpval=\$$tmpval - [ "$tmpval" = "no" ] && return 0 - - ECHOBUF="Checking presence of header file $2 ..." - echo "#include<$2>" > $TEMP_C - echo "int main(void) { return 0; }" >> $TEMP_C - eval HAVE_$1=no - answer=no - - $CC -o $TEMP_EXE $TEMP_C $INCLUDE_DIRS 2>/dev/null >/dev/null && answer=yes && eval HAVE_$1=yes - - echo $ECHOBUF $answer - - rm -rf $TEMP_C $TEMP_EXE - if [ "$tmpval" = "yes" ] && [ "$answer" = "no" ]; then - echo "Build assumed that $2 exists, but cannot locate. Exiting ..." - exit 1 - fi +check_switch_c() #$1 = HAVE_$1 $2 = switch $3 = critical error message [checked only if non-empty] +{ ECHOBUF="Checking for availability of switch $2 in $CC" +# echo -n "Checking for availability of switch $2 in $CC " + echo "int main(void) { return 0; }" > $TEMP_C + answer='no' + "$CC" -o "$TEMP_EXE" "$TEMP_C" $2 >/dev/null 2>&1 && answer='yes' + eval HAVE_$1="$answer"; echo "$ECHOBUF ... $answer" + rm "$TEMP_C" "$TEMP_EXE" >/dev/null 2>&1 + [ "$answer" = 'no' ] && { + [ "$3" ] && { echo "$3"; exit 1;} + } } -check_switch_c() -{ - ECHOBUF="Checking for availability of switch $2 in $CC ..." - if [ -z "$CC" ]; then - echo "No C compiler, cannot check ..." - exit 1 - fi - echo "int main(void) { return 0; }" > $TEMP_C - eval HAVE_$1=no - answer=no - $CC -o $TEMP_EXE $TEMP_C $2 2>/dev/null >/dev/null && answer=yes && eval HAVE_$1=yes - - echo $ECHOBUF $answer - - rm -rf $TEMP_C $TEMP_EXE -} - -check_switch_cxx() -{ - ECHOBUF="Checking for availability of switch $2 in $CXX ... " - if [ -z "$CXX" ]; then - echo "No C++ compiler, cannot check ..." - exit 1 - fi - echo "int main() { return 0; }" > $TEMP_CXX - eval HAVE_$1=no - answer=no - $CXX -o $TEMP_EXE $TEMP_CXX $2 2>/dev/null >/dev/null && answer=yes && eval HAVE_$1=yes - - echo $ECHOBUF $answer - - rm -rf $TEMP_CXX $TEMP_EXE -} - -check_critical() -{ - val=HAVE_$1 - eval val=\$$val - if [ "$val" != "yes" ]; then - echo "$2" - exit 1 - fi -} - -output_define_header() -{ - arg1="`echo $2 | sed 's|^@\([^@]*\)@\([^@]*\)@$|\1|'`" - arg2="`echo $2 | sed 's|^@\([^@]*\)@\([^@]*\)@$|\2|'`" - - echo "#define $arg1 $arg2" >> "$outfile" +check_switch_cxx() #$1 = HAVE_$1 $2 = switch $3 = critical error message [checked only if non-empty] +{ ECHOBUF="Checking for availability of switch $2 in $CXX" +# echo -n "Checking for availability of switch $2 in $CXX" + echo "int main() { return 0; }" > $TEMP_CXX + answer='no' + "$CXX" -o "$TEMP_EXE" "$TEMP_CXX" "$2" >/dev/null 2>&1 && answer='yes' + eval HAVE_$1="$answer"; echo "$ECHOBUF ... $answer" + rm "$TEMP_CXX" "$TEMP_EXE" >/dev/null 2>&1 + [ "$answer" = 'no' ] && { + [ "$3" ] && { echo "$3"; exit 1;} + } } create_config_header() -{ - outfile="$1" - shift +{ outfile="$1"; shift - echo "Creating config header: $outfile" + echo "Creating config header: $outfile" + name=$(echo "QB_${outfile}__" | tr '.[a-z]' '_[A-Z]') + { echo "#ifndef $name" + echo "#define $name" + echo "" + echo "#define PACKAGE_NAME \"$PACKAGE_NAME\"" + echo "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" - name="`echo QB_${outfile}__ | sed 's|[\./]|_|g' | tr '[a-z]' '[A-Z]'`" - echo "#ifndef $name" > "$outfile" - echo "#define $name" >> "$outfile" - echo "" >> "$outfile" - echo "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >> "$outfile" - echo "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >> "$outfile" + while [ "$1" ]; do + case $(eval echo \$HAVE_$1) in + 'yes') echo "#define HAVE_$1 1";; + 'no') echo "/* #undef HAVE_$1 */";; + esac + shift + done - while [ ! -z "$1" ] - do - tmpval="HAVE_$1" - eval tmpval=\$$tmpval - if [ "$tmpval" = "yes" ]; then - echo "#define HAVE_$1 1" >> "$outfile" - elif [ "$tmpval" = "no" ]; then - echo "/* #undef HAVE_$1 */" >> "$outfile" - fi + while IFS='=' read VAR VAL; do echo "#define $VAR $VAL"; done < "$CONFIG_DEFINES" - shift - done - - echo "" >> "$outfile" - - tmpdefs="$CONFIG_DEFINES" - while [ ! -z "$tmpdefs" ] - do - subdefs="`echo $tmpdefs | sed 's|^:\(@[^@]*@[^@]*@\):.*$|\1|'`" - tmpdefs="`echo $tmpdefs | sed 's|^\W*$||'`" - tmpdefs="`echo $tmpdefs | sed 's|^:\(@[^@]*@[^@]*@\):||'`" - output_define_header "$outfile" "$subdefs" - done - - echo "#endif" >> "$outfile" -} - -output_define_make() -{ - arg1="`echo $2 | sed 's|^@\([^@]*\)@\([^@]*\)@$|\1|'`" - arg2="`echo $2 | sed 's|^@\([^@]*\)@\([^@]*\)@$|\2|'`" - - echo "$arg1 = $arg2" >> "$outfile" + echo "#endif" + } > "$outfile" } create_config_make() -{ - outfile="$1" - shift +{ outfile="$1"; shift - echo "Creating make config: $outfile" + echo "Creating make config: $outfile" - rm -rf "$outfile" - touch "$outfile" - if [ "$USE_LANG_C" = "yes" ]; then - echo "CC = $CC" >> "$outfile" - echo "CFLAGS = $CFLAGS" >> "$outfile" - fi - if [ "$USE_LANG_CXX" = "yes" ]; then - echo "CXX = $CXX" >> "$outfile" - echo "CXXFLAGS = $CXXFLAGS" >> "$outfile" - fi - echo "LDFLAGS = $LDFLAGS" >> "$outfile" - echo "INCLUDE_DIRS = $INCLUDE_DIRS" >> "$outfile" - echo "LIBRARY_DIRS = $LIBRARY_DIRS" >> "$outfile" - echo "PACKAGE_NAME = $PACKAGE_NAME" >> "$outfile" - echo "PACKAGE_VERSION = $PACKAGE_VERSION" >> "$outfile" - echo "PREFIX = $PREFIX" >> "$outfile" + { if [ "$USE_LANG_C" = 'yes' ]; then + echo "CC = $CC" + echo "CFLAGS = $CFLAGS" + fi + if [ "$USE_LANG_CXX" = 'yes' ]; then + echo "CXX = $CXX" + echo "CXXFLAGS = $CXXFLAGS" + fi + echo "LDFLAGS = $LDFLAGS" + echo "INCLUDE_DIRS = $INCLUDE_DIRS" + echo "LIBRARY_DIRS = $LIBRARY_DIRS" + echo "PACKAGE_NAME = $PACKAGE_NAME" + echo "PACKAGE_VERSION = $PACKAGE_VERSION" + echo "PREFIX = $PREFIX" - while [ ! -z "$1" ] - do - tmpval="HAVE_$1" - eval tmpval=\$$tmpval - if [ "$tmpval" = yes ]; then - echo "HAVE_$1 = 1" >> "$outfile" - elif [ "$tmpval" = no ]; then - echo "HAVE_$1 = 0" >> "$outfile" - fi - - if [ ! -z "`echo $PKG_CONF_USED | grep $1`" ]; then - tmpval="$1_CFLAGS" - eval tmpval=\$$tmpval - echo "$1_CFLAGS = $tmpval" >> "$outfile" - - tmpval="$1_LIBS" - eval tmpval=\$$tmpval - echo "$1_LIBS = $tmpval" >> "$outfile" - fi - - - shift - done - - echo "" >> "$outfile" - - tmpdefs="$MAKEFILE_DEFINES" - while [ ! -z "$tmpdefs" ] - do - subdefs="`echo $tmpdefs | sed 's|^:\(@[^@]*@[^@]*@\):.*$|\1|'`" - tmpdefs="`echo $tmpdefs | sed 's|^\W*$||'`" - tmpdefs="`echo $tmpdefs | sed 's|^:\(@[^@]*@[^@]*@\):||'`" - output_define_make "$outfile" "$subdefs" - done + while [ "$1" ]; do + case $(eval echo \$HAVE_$1) in + 'yes') echo "HAVE_$1 = 1";; + 'no') echo "HAVE_$1 = 0";; + esac + + case "$PKG_CONF_USED" in + *$1*) + echo "$1_CFLAGS = $(eval echo \$$1_CFLAGS)" + echo "$1_LIBS = $(eval echo \$$1_LIBS)" + ;; + esac + shift + done + while IFS='=' read VAR VAL; do echo "$VAR = $VAL"; done < "$MAKEFILE_DEFINES" + } > "$outfile" } +. qb/config.libs.sh +rm "$MAKEFILE_DEFINES" "$CONFIG_DEFINES" diff --git a/qb/qb.params.sh b/qb/qb.params.sh index c5669a0f28..13a962c946 100644 --- a/qb/qb.params.sh +++ b/qb/qb.params.sh @@ -23,49 +23,48 @@ EOF while IFS='=#' read VAR VAL COMMENT; do VAR=$(echo "${VAR##HAVE_}" | tr '[A-Z]' '[a-z]') case "$VAL" in - 'yes'*) echo "--disable-$VAR: $COMMENT";; - 'no'*) echo "--enable-$VAR: $COMMENT";; - 'auto'*) echo "--enable-$VAR: $COMMENT"; echo "--disable-$VAR";; - *) echo "--with-$VAR: $COMMENT";; + 'yes'*) + echo "--disable-$VAR: $COMMENT";; + 'no'*) + echo "--enable-$VAR: $COMMENT";; + 'auto'*) + echo "--enable-$VAR: $COMMENT" + echo "--disable-$VAR";; + *) + echo "--with-$VAR: $COMMENT";; esac done < 'qb/config.params.sh' } opt_exists() # $opt is returned if exists in OPTS -{ - opt=$(echo "$1" | tr '[a-z]' '[A-Z]') +{ opt=$(echo "$1" | tr '[a-z]' '[A-Z]') for OPT in $OPTS; do [ "$opt" = "$OPT" ] && return; done print_help; exit 1 } parse_input() # Parse stuff :V -{ - #OPTS contains all available options in config.params.sh - while IFS='=' read VAR dummy; do OPTS="$OPTS ${VAR##HAVE_}"; done < 'qb/config.params.sh' +{ OPTS=; while IFS='=' read VAR dummy; do OPTS="$OPTS ${VAR##HAVE_}"; done < 'qb/config.params.sh' +#OPTS contains all available options in config.params.sh - used to speedup +#things in opt_exists() while [ "$1" ]; do case "$1" in --prefix=*) PREFIX=${1##--prefix=};; - --enable-*) - opt_exists "${1##--enable-}" "$OPTS" + opt_exists "${1##--enable-}" eval "HAVE_$opt=yes" ;; - --disable-*) - opt_exists "${1##--disable-}" "$OPTS" + opt_exists "${1##--disable-}" eval "HAVE_$opt=no" ;; - --with-*) arg=${1##--with-} val=${arg##*=} - opt_exists "${arg%%=*}" "$OPTS" + opt_exists "${arg%%=*}" eval "$opt=$val" ;; - -h|--help) print_help; exit 0;; - *) print_help; exit 1;; esac shift @@ -74,6 +73,4 @@ parse_input() # Parse stuff :V . qb/config.params.sh -parse_input "$@" - - +parse_input "$@" diff --git a/retroarch.c b/retroarch.c index acc9ff50a1..10045a9533 100644 --- a/retroarch.c +++ b/retroarch.c @@ -95,22 +95,61 @@ static void set_fast_forward_button(bool new_button_state, bool new_hold_button_ } #ifdef HAVE_SCREENSHOTS +static bool take_screenshot_viewport(void) +{ + unsigned width = 0, height = 0; + video_viewport_size_func(&width, &height); + + if (!width || !height) + return false; + + uint8_t *buffer = (uint8_t*)malloc(width * height * 3); + if (!buffer) + return false; + + if (!video_read_viewport_func(buffer)) + { + free(buffer); + return false; + } + + // Data read from viewport is in bottom-up order, suitable for BMP. + if (!screenshot_dump(g_settings.screenshot_directory, + buffer, + width, height, width * 3, true)) + { + free(buffer); + return false; + } + + return true; +} + +static bool take_screenshot_raw(void) +{ + const uint16_t *data = (const uint16_t*)g_extern.frame_cache.data; + unsigned width = g_extern.frame_cache.width; + unsigned height = g_extern.frame_cache.height; + int pitch = g_extern.frame_cache.pitch; + + // Negative pitch is needed as screenshot takes bottom-up, + // but we use top-down. + return screenshot_dump(g_settings.screenshot_directory, + data + (height - 1) * (pitch >> 1), + width, height, -pitch, false); +} + static void take_screenshot(void) { if (!(*g_settings.screenshot_directory)) return; bool ret = false; - if (g_extern.frame_cache.data) - { - const uint16_t *data = (const uint16_t*)g_extern.frame_cache.data; - unsigned width = g_extern.frame_cache.width; - unsigned height = g_extern.frame_cache.height; - size_t pitch = g_extern.frame_cache.pitch; - ret = screenshot_dump(g_settings.screenshot_directory, - data, - width, height, pitch); - } + + if (driver.video->read_viewport && driver.video->viewport_size) + ret = take_screenshot_viewport(); + else if (g_extern.frame_cache.data) + ret = take_screenshot_raw(); const char *msg = NULL; if (ret) @@ -1500,7 +1539,7 @@ static void set_savestate_auto_index(void) unsigned max_index = 0; - char **dir_list = dir_list_new(dir, NULL); + char **dir_list = dir_list_new(dir, NULL, false); if (!dir_list) return; diff --git a/retroarch.cfg b/retroarch.cfg index 3cf0b40a3b..8781bfddef 100644 --- a/retroarch.cfg +++ b/retroarch.cfg @@ -26,6 +26,10 @@ # I.e.: "key1=value1;key2=value2;..." # environment_variables = +# Sets the "system" directory. +# Implementations can query for this directory to load BIOSes, system-specific configs, etc. +# system_directory = + #### Video # Video driver to use. "gl", "xvideo", "sdl" or "ext" (external API driver) diff --git a/screenshot.c b/screenshot.c index a62be875c3..5be6b7d8df 100644 --- a/screenshot.c +++ b/screenshot.c @@ -52,49 +52,70 @@ static void write_header(FILE *file, unsigned width, unsigned height) fwrite(header, 1, sizeof(header), file); } -static void dump_content(FILE *file, const uint16_t *frame, unsigned width, unsigned height, unsigned pitch) +static void dump_line_bgr(uint8_t *line, const uint8_t *src, unsigned width) { - pitch >>= 1; + memcpy(line, src, width * 3); +} + +static void dump_line_16(uint8_t *line, const uint16_t *src, unsigned width) +{ + for (unsigned i = 0; i < width; i++) + { + uint16_t pixel = *src++; + uint8_t b = (pixel >> 0) & 0x1f; + uint8_t g = (pixel >> 5) & 0x1f; + uint8_t r = (pixel >> 10) & 0x1f; + *line++ = (b << 3) | (b >> 2); + *line++ = (g << 3) | (g >> 2); + *line++ = (r << 3) | (r >> 2); + } +} + +static void dump_content(FILE *file, const void *frame, + int width, int height, int pitch, bool bgr24) +{ + const uint8_t *frame_bgr = (const uint8_t*)frame; + const uint16_t *frame16 = (const uint16_t*)frame; + + if (!bgr24) + pitch /= 2; + unsigned line_size = (width * 3 + 3) & ~3; uint8_t *line = (uint8_t*)calloc(1, line_size); if (!line) return; - // BMP likes reverse ordering for some reason :v - for (int j = height - 1; j >= 0; j--) + if (bgr24) // BGR24 byte order. Can directly copy. { - uint8_t *dst = line; - const uint16_t *src = frame + j * pitch; - for (unsigned i = 0; i < width; i++) + for (int j = 0; j < height; j++, frame_bgr += pitch) { - uint16_t pixel = *src++; - uint8_t b = (pixel >> 0) & 0x1f; - uint8_t g = (pixel >> 5) & 0x1f; - uint8_t r = (pixel >> 10) & 0x1f; - *dst++ = (b << 3) | (b >> 2); - *dst++ = (g << 3) | (g >> 2); - *dst++ = (r << 3) | (r >> 2); + dump_line_bgr(line, frame_bgr, width); + fwrite(line, 1, line_size, file); + } + } + else // ARGB1555 + { + for (int j = 0; j < height; j++, frame16 += pitch) + { + dump_line_16(line, frame16, width); + fwrite(line, 1, line_size, file); } - - fwrite(line, 1, line_size, file); } free(line); } -bool screenshot_dump(const char *folder, const uint16_t *frame, - unsigned width, unsigned height, unsigned pitch) +bool screenshot_dump(const char *folder, const void *frame, + unsigned width, unsigned height, int pitch, bool bgr24) { time_t cur_time; time(&cur_time); char timefmt[128]; - strftime(timefmt, sizeof(timefmt), "SSNES-%m%d-%H%M%S.bmp", localtime(&cur_time)); + strftime(timefmt, sizeof(timefmt), "RetroArch-%m%d-%H%M%S.bmp", localtime(&cur_time)); - char filename[256]; - strlcpy(filename, folder, sizeof(filename)); - strlcat(filename, "/", sizeof(filename)); - strlcat(filename, timefmt, sizeof(filename)); + char filename[PATH_MAX]; + snprintf(filename, sizeof(filename), "%s/%s", folder, timefmt); FILE *file = fopen(filename, "wb"); if (!file) @@ -104,9 +125,10 @@ bool screenshot_dump(const char *folder, const uint16_t *frame, } write_header(file, width, height); - dump_content(file, frame, width, height, pitch); + dump_content(file, frame, width, height, pitch, bgr24); fclose(file); return true; } + diff --git a/screenshot.h b/screenshot.h index f27d176964..50c5c87652 100644 --- a/screenshot.h +++ b/screenshot.h @@ -19,7 +19,7 @@ #include #include "boolean.h" -bool screenshot_dump(const char *folder, const uint16_t *frame, - unsigned width, unsigned height, unsigned pitch); +bool screenshot_dump(const char *folder, const void *frame, + unsigned width, unsigned height, int pitch, bool bgr24); #endif diff --git a/settings.c b/settings.c index f2ecd40be0..46a88dc17a 100644 --- a/settings.c +++ b/settings.c @@ -490,6 +490,7 @@ bool config_load_file(const char *path) else RARCH_WARN("savefile_directory is not a directory, ignoring ....\n"); } + if (!g_extern.has_set_state_path && config_get_array(conf, "savestate_directory", tmp_str, sizeof(tmp_str))) { if (path_is_directory(tmp_str)) @@ -501,6 +502,8 @@ bool config_load_file(const char *path) RARCH_WARN("savestate_directory is not a directory, ignoring ...\n"); } + CONFIG_GET_STRING(system_directory, "system_directory"); + config_read_keybinds_conf(conf); config_file_free(conf);