diff --git a/Makefile.common b/Makefile.common index a76c417441..d956dc5ec3 100644 --- a/Makefile.common +++ b/Makefile.common @@ -357,6 +357,10 @@ endif # XMB and GLUI are always enabled if supported and not explicitly disabled ifeq ($(HAVE_RGUI)$(HAVE_GL_CONTEXT), 11) + ifeq ($(HAVE_ZARCH),) + HAVE_ZARCH = 1 + endif + ifeq ($(HAVE_GLUI),) HAVE_GLUI = 1 endif @@ -365,8 +369,9 @@ ifeq ($(HAVE_RGUI)$(HAVE_GL_CONTEXT), 11) HAVE_XMB = 1 endif else - HAVE_GLUI = 0 - HAVE_XMB = 0 + HAVE_ZARCH = 0 + HAVE_GLUI = 0 + HAVE_XMB = 0 endif ifeq ($(HAVE_RGUI), 1) @@ -377,6 +382,10 @@ ifeq ($(HAVE_GLUI), 1) OBJ += menu/drivers/glui.o DEFINES += -DHAVE_GLUI endif +ifeq ($(HAVE_ZARCH), 1) + OBJ += menu/drivers/zarch.o + DEFINES += -DHAVE_ZARCH +endif ifeq ($(HAVE_XMB), 1) OBJ += menu/drivers/xmb.o DEFINES += -DHAVE_XMB diff --git a/griffin/griffin.c b/griffin/griffin.c index c52ca4bdf3..34065cf6bc 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -810,6 +810,10 @@ MENU #include "../menu/drivers/glui.c" #endif +#ifdef HAVE_ZARCH +#include "../menu/drivers/zarch.c" +#endif + #endif #ifdef HAVE_COMMAND diff --git a/menu/drivers/zarch.c b/menu/drivers/zarch.c new file mode 100644 index 0000000000..42c8d5de76 --- /dev/null +++ b/menu/drivers/zarch.c @@ -0,0 +1,949 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2015 - Daniel De Matteis + * Copyright (C) 2014-2015 - Jean-AndrĂ© Santoni + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../menu.h" +#include "../menu_entry.h" +#include "../menu_display.h" +#include "../../runloop_data.h" + +#include "../../gfx/video_thread_wrapper.h" +#include "../../gfx/font_driver.h" +#include "../../gfx/video_texture.h" +#include "../menu_video.h" + +const uint32_t ZUI_NORMAL = FONT_COLOR_RGBA(0x5b, 0x5d, 0x5a, 255); +const uint32_t ZUI_HILITE = FONT_COLOR_RGBA(0xa4, 0x00, 0x5d, 255); +const uint32_t ZUI_PRESS = FONT_COLOR_RGBA(0x43, 0x47, 0x48, 255); +const uint32_t ZUI_BARBG = FONT_COLOR_RGBA(0x05, 0x47, 0xdf, 255); + +const uint32_t ZUI_FG_NORMAL = ~0; +const uint32_t ZUI_BG_PANEL = FONT_COLOR_RGBA( 0, 0, 0 , 32); +const uint32_t ZUI_BG_SCREEN = FONT_COLOR_RGBA( 22, 57, 81, 255); +const uint32_t ZUI_BG_HILITE = FONT_COLOR_RGBA( 57, 153, 189, 255); + +typedef struct zarch_handle +{ + bool rendering; + settings_t *set; + menu_handle_t *menu; + math_matrix_4x4 mvp; + unsigned width; + unsigned height; + gfx_font_raster_block_t tmp_block; + unsigned hash; + + struct { + unsigned active; + unsigned hot; + } item; + + gfx_coord_array_t ca; + + struct + { + int16_t x; + int16_t y; + bool left; + bool right; + bool oldleft; + bool oldright; + int wheel; + } mouse; + + /* LAY_ROOT's "Load" file browser */ + struct string_list *load_dlist; + char *load_cwd; + int load_dlist_first; + + + /* LAY_PICK_CORE */ + int pick_first; + char pick_content[PATH_MAX_LENGTH]; + const core_info_t *pick_cores; + size_t pick_supported; + + void *fb_buf; + float font_size; + int header_height; +} zui_t; + +static float zui_strwidth(zui_t *zui, const char *text, float scale) +{ + driver_t *driver = (driver_t*)driver_get_ptr(); + return driver->font_osd_driver->get_message_width(zui->fb_buf, text, strlen(text), scale); +} + +static void zui_begin(zui_t *zui) +{ + driver_t *driver = (driver_t*)driver_get_ptr(); + gl_t *gl = (gl_t*)driver->video_data; + + zui->rendering = true; + + zui->hash = 0; + zui->item.hot = 0; + + + glViewport(0, 0, zui->width, zui->height); + gl->shader->set_mvp(gl, &zui->mvp); + + /* why do i need this? */ + const struct retro_keybind *binds[MAX_USERS]; + zui->mouse.left = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT); + zui->mouse.right = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT); + zui->mouse.wheel = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_WHEELDOWN) - + input_driver_state(binds, 0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_WHEELUP); + + int dx = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X); + int dy = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y); + + zui->mouse.x += dx; + zui->mouse.y += dy; + + zui->ca.coords.vertices = 0; + + zui->tmp_block.carr.coords.vertices = 0; + menu_display_font_bind_block(zui->menu, driver->font_osd_driver, &zui->tmp_block); + + +} + +void zui_finish(zui_t *zui) +{ + driver_t *driver = (driver_t*)driver_get_ptr(); + gl_t *gl = (gl_t*)driver->video_data; + + if (!zui->mouse.left) + zui->item.active = 0; + else if (zui->item.active == 0) + zui->item.active = -1; + + if (gl) /* it's null when we load a core :( */ + { + glBindTexture(GL_TEXTURE_2D, 0); + + gl->shader->set_coords(&zui->ca); + + glEnable(GL_BLEND); + glDrawArrays(GL_TRIANGLES, 0, zui->ca.coords.vertices); + + menu_display_font_flush_block(zui->menu, driver->font_osd_driver); + + glDisable(GL_BLEND); + + gl->shader->set_mvp(gl, &gl->mvp_no_rot); + } + + zui->rendering = false; +} + +static bool check_hit(zui_t *zui, int x1, int y1, int x2, int y2) +{ + unsigned mx = zui->mouse.x; + unsigned my = zui->mouse.y; + + return mx >= x1 && mx <= x2 && my >= y1 && my <= y2; +} + +static bool mouse_down(zui_t *zui) +{ + return zui->mouse.left; +} + +static bool mouse_up(zui_t *zui) +{ + return !mouse_down(zui); +} + +static bool check_button_down(zui_t *zui, unsigned id, int x1, int y1, int x2, int y2) +{ + bool result = false; + bool inside = check_hit(zui, x1, y1, x2, y2); + + if (inside) + zui->item.hot = id; + + if (zui->item.hot == id && mouse_down(zui)) + { + result = true; + zui->item.active = id; + } + + return result; +} + +static bool check_button_up(zui_t *zui, unsigned id, int x1, int y1, int x2, int y2) +{ + bool result = false; + bool inside = check_hit(zui, x1, y1, x2, y2); + + if (inside) + zui->item.hot = id; + + if (zui->item.active == id && mouse_up(zui)) + { + if (zui->item.hot == id) + result = true; + + zui->item.active = 0; + } + + check_button_down(zui, id, x1, y1, x2, y2); + + return result; +} + +static unsigned zui_hash(zui_t *zui, const char *s) +{ + unsigned hval = zui->hash; + while(*s!=0) + { + hval+=*s++; + hval+=(hval<<10); + hval^=(hval>>6); + hval+=(hval<<3); + hval^=(hval>>11); + hval+=(hval<<15); + } + return zui->hash = hval; +} + +static uint32_t zui_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return FONT_COLOR_RGBA(r, g, b, a); +} + +static void zui_set_color(GLfloat *rgbaf, size_t count, uint32_t color) +{ + while (count--) + { + *rgbaf++ = FONT_COLOR_GET_RED(color) / 255.0f; + *rgbaf++ = FONT_COLOR_GET_GREEN(color) / 255.0f; + *rgbaf++ = FONT_COLOR_GET_BLUE(color) / 255.0f; + *rgbaf++ = FONT_COLOR_GET_ALPHA(color) / 255.0f; + } +} + +static void zui_draw_text(zui_t *zui, uint32_t color, int x, int y, const char *text) +{ + struct font_params params = {0}; + + /* need to use height-y because the gl font renderer uses a different mvp */ + params.x = x / (float)zui->width; + params.y = (zui->height - y) / (float)zui->height; + params.scale = 1.0; + params.color = color; + params.full_screen = true; + params.text_align = TEXT_ALIGN_LEFT; + + video_driver_set_osd_msg(text, ¶ms, zui->fb_buf); +} + +static void zui_push_quad(zui_t *zui, uint32_t color, int x1, int y1, int x2, int y2) +{ + const GLfloat vertex[4 * 2] = { + x1 / (float)zui->width, y1 / (float)zui->height, + x2 / (float)zui->width, y1 / (float)zui->height, + x1 / (float)zui->width, y2 / (float)zui->height, + x2 / (float)zui->width, y2 / (float)zui->height, + }; + + const GLfloat tex_coord[4 * 2] = { + 0, 1, + 1, 1, + 0, 0, + 1, 0, + }; + + GLfloat colors[4 * 4]; + zui_set_color(colors, 4, color); + + gfx_coords_t coords; + coords.color = colors; + coords.vertex = vertex; + coords.tex_coord = tex_coord; + coords.lut_tex_coord = tex_coord; + coords.vertices = 3; + + gfx_coord_array_add(&zui->ca, &coords, 3); + + coords.color += 4; + coords.vertex += 2; + coords.tex_coord += 2; + coords.lut_tex_coord += 2; + + gfx_coord_array_add(&zui->ca, &coords, 3); +} + +static float randf(float min, float max) +{ + return (rand() * ((max - min) / RAND_MAX)) + min; +} + +static float scalef(float val, float oldmin, float oldmax, float newmin, float newmax) +{ + return (((val - oldmin) * (newmax - newmin)) / (oldmax - oldmin)) + newmin; +} + +static void zui_snow(zui_t *zui) +{ +#define NPARTICLES 100 + typedef struct { + float x, y; + float xspeed, yspeed; + uint8_t alpha; + bool alive; + } part_t; + static part_t particles[NPARTICLES]; + static bool initialized = false; + static int timeout = 0; + + unsigned i, j, max_gen = 2; + + if (!initialized) + { + memset(particles, 0, sizeof(particles)); + initialized = true; + } + + for (i = 0; i < NPARTICLES; ++i) + { + part_t *p = &particles[i]; + if (p->alive) + { + p->y += p->yspeed; + p->x += scalef(zui->mouse.x, 0, zui->width, -0.3, 0.3) + p->xspeed; + + p->alive = p->y >= 0 && p->y < (int)zui->height && p->x >= 0 && p->x < (int)zui->width; + } + else if (max_gen > 0 && timeout <= 0) + { + p->xspeed = randf(-0.2, 0.2); + p->yspeed = randf(1, 2); + p->y = 0; + p->x = rand() % (int)zui->width; + p->alpha = randf(8, 32); + p->alive = true; + + max_gen--; + } + } + + if (max_gen == 0) + timeout = 3; + else + timeout--; + + j = 0; + for (i = 0; i < NPARTICLES; ++i) + { + part_t *p = &particles[i]; + + if (!p->alive) + continue; + + zui_push_quad(zui, FONT_COLOR_RGBA(255, 255, 255, randf(0, 100) > 90 ? p->alpha/2 : p->alpha), + p->x-2, p->y-2, p->x+2, p->y+2); + + j++; + } +} + +static bool zui_button_full(zui_t *zui, int x1, int y1, int x2, int y2, const char *label) +{ + unsigned id = zui_hash(zui, label); +// int x2 = x1 + zui_strwidth(zui, label, 1.0) + 16; + bool active = check_button_up(zui, id, x1, y1, x2, y2); + uint32_t bg = ZUI_BG_PANEL; + + if (zui->item.active == id || zui->item.hot == id) + bg = ZUI_BG_HILITE; + + zui_push_quad(zui, bg, x1, y1, x2, y2); + zui_draw_text(zui, ZUI_FG_NORMAL, x1+8, y1 + 18, label); + + return active; +} + +static bool zui_button(zui_t *zui, int x1, int y1, const char *label) +{ + return zui_button_full(zui, x1, y1, x1 + zui_strwidth(zui, label, 1.0) + 16, y1 + 30, label); +} + +static bool zui_list_item(zui_t *zui, int x1, int y1, const char *label) +{ + unsigned id = zui_hash(zui, label); + int x2 = x1 + zui->width/2; + int y2 = y1 + 30; + + bool active = check_button_up(zui, id, x1, y1, x2, y2); + uint32_t bg = ZUI_BG_PANEL; + + if (zui->item.active == id || zui->item.hot == id) + bg = ZUI_BG_HILITE; + + zui_push_quad(zui, bg, x1, y1, x2, y2); + zui_draw_text(zui, ZUI_FG_NORMAL, 8, y1 + 18, label); + + return active; +} + +typedef struct { + unsigned active; + int x, y; + int width; + int height; /* unused */ + int tabline_size; + bool update_width; + bool vertical; + int tab_width; +} zui_tabbed_t; + +static void zui_tabbed_begin(zui_t *zui, zui_tabbed_t *tab, int x, int y) +{ + tab->x = x; + tab->y = y; + tab->tabline_size = 30 + 4; +} + +static bool zui_tab(zui_t *zui, zui_tabbed_t *tab, const char *label) +{ + unsigned id = zui_hash(zui, label); + int width = tab->tab_width; + + if (!width) + width = zui_strwidth(zui, label, 1.0) + 16; + + int x1 = tab->x; + int y1 = tab->y; + int x2 = x1 + width; + int y2 = y1 + 30; + + bool active = check_button_up(zui, id, x1, y1, x2, y2); + uint32_t bg = ZUI_BG_PANEL; + + if (zui->item.active == id || tab->active == ~0) + tab->active = id; + + if (tab->active == id || zui->item.active == id || zui->item.hot == id) + bg = ZUI_BG_HILITE; + + zui_push_quad(zui, bg, x1+0, y1+0, x2, y2); + zui_draw_text(zui, ZUI_FG_NORMAL, x1+8, y1 + 18, label); + + if (tab->vertical) + { + tab->y += y2 - y1; + } + else + { + tab->x = x2; + } + + return active || tab->active == id; +} + +static enum { + LAY_HOME, + LAY_PICK_CORE, + LAY_SETTINGS +} layout = LAY_HOME; + + +void render_lay_root(global_t *global, zui_t *zui) +{ + static zui_tabbed_t tabbed = {~0}; + zui_tabbed_begin(zui, &tabbed, 0, 0); + + tabbed.width = zui->width/2; + + if (zui_tab(zui, &tabbed, "Recent")) + { + unsigned size = min(zui->height/30-2, content_playlist_size(g_defaults.history)); + unsigned i = 0; + + for (i = 0; i < size; ++i) + { + const char *path = NULL; + const char *label = NULL; + const char *core_name = NULL; + const char *crc32 = NULL; + + content_playlist_get_index(g_defaults.history, i, + &path, &label, NULL, &core_name, &crc32, NULL); + + if (!label) + { + if (path) + label = path_basename(path); + else + label = core_name; + } + + zui_list_item(zui, 0, tabbed.tabline_size + i * 30, label); + } + } + + if (zui_tab(zui, &tabbed, "Load")) + { + if (!zui->load_cwd) + zui->load_cwd = strdup(zui->set->menu_content_directory); + + if (!zui->load_dlist) + { + zui->load_dlist = dir_list_new(zui->load_cwd, global->core_info.current->supported_extensions, true, true); + dir_list_sort(zui->load_dlist, true); + zui->load_dlist_first = 0; + } + + unsigned cwd_offset = min(strlen(zui->load_cwd), 30); + + zui_draw_text(zui, ZUI_FG_NORMAL, 60, tabbed.tabline_size + 5 + 18, &zui->load_cwd[strlen(zui->load_cwd) - cwd_offset]); + + if (zui_button(zui, 0, tabbed.tabline_size + 5, "HOME")) + { + char tmp[PATH_MAX_LENGTH]; + fill_pathname_expand_special(tmp, "~", sizeof(tmp)); + + free(zui->load_cwd); + zui->load_cwd = strdup(tmp); + + dir_list_free(zui->load_dlist); + zui->load_dlist = NULL; + } + + if (zui->load_dlist) + { + if (zui_list_item(zui, 0, tabbed.tabline_size + 40, "^ ..")) + { + path_basedir(zui->load_cwd); + if (zui->load_cwd[strlen(zui->load_cwd)-1] == '/') + zui->load_cwd[strlen(zui->load_cwd)-1] = 0; + + dir_list_free(zui->load_dlist); + zui->load_dlist = NULL; + } + else + { + unsigned size = zui->load_dlist->size; + unsigned i, j = 1; + + unsigned skip = 0; + for (i = 0; i < size; ++i) + { + const char *basename = path_basename(zui->load_dlist->elems[i].data); + if (basename[0] == '.') + skip++; + else + break; + } + + zui->load_dlist_first += zui->mouse.wheel; + + if (zui->load_dlist_first < 0) + zui->load_dlist_first = 0; + else if (zui->load_dlist_first > size - 5) + zui->load_dlist_first = size - 5; + + zui->load_dlist_first = min(max(zui->load_dlist_first, 0), size - 5 - skip); + + for (i = skip + zui->load_dlist_first; i < size; ++i) + { + if (j > 10) + break; + + const char *path = zui->load_dlist->elems[i].data; + const char *basename = path_basename(path); + char label[PATH_MAX_LENGTH]; + + *label = 0; + strncat(label, " ", sizeof(label)-1); + strncat(label, basename, sizeof(label)-1); + + if (path_is_directory(path)) + strncat(label, "/", sizeof(label)-1); + + if (zui_list_item(zui, 0, tabbed.tabline_size + 40 + j * 30, label)) + { + if (path_is_directory(path)) + { + free(zui->load_cwd); + zui->load_cwd = strdup(path); + dir_list_free(zui->load_dlist); + zui->load_dlist = NULL; + break; + } + else + { + zui->pick_cores = NULL; + zui->pick_supported = 0; + strncpy(zui->pick_content, path, sizeof(zui->pick_content)-1); + core_info_list_get_supported_cores(global->core_info.list, path, + &zui->pick_cores, &zui->pick_supported); + layout = LAY_PICK_CORE; + break; + } + } + j++; + } + } + } + } + else if (zui->load_dlist) + { + dir_list_free(zui->load_dlist); + zui->load_dlist = NULL; + } + + zui_push_quad(zui, ZUI_BG_HILITE, 0, 30, zui->width/2, 30+4); +} + +void render_sidebar(zui_t *zui) +{ + static zui_tabbed_t tabbed = {~0}; + tabbed.vertical = true; + tabbed.tab_width = 100; + + zui_tabbed_begin(zui, &tabbed, zui->width - 100, 30); + + int width = 100; + int x1 = zui->width - width; + int y1 = 30; + + if (zui_button_full(zui, x1, y1, x1 + width, y1 + 30, "Home")) + layout = LAY_HOME; + + y1 += 30; + + if (zui_button_full(zui, x1, y1, x1 + width, y1 + 30, "Settings")) + layout = LAY_SETTINGS; + + y1 += 30; + + if (zui_button_full(zui, x1, y1, x1 + width, y1 + 30, "Exit")) + exit(0); +} + +static void zui_render(zui_t *zui) +{ + if (zui->rendering) + return; + + zui_begin(zui); + global_t *global = global_get_ptr(); + + + zui_push_quad(zui, ZUI_BG_SCREEN, 0, 0, zui->width, zui->height); + zui_snow(zui); + + render_sidebar(zui); + + if (layout == LAY_HOME) + { + render_lay_root(global, zui); + } + else if (layout == LAY_PICK_CORE) + { + if (zui->pick_supported == 1) + { + fputs("Core loading is not implemented yet, sorry.", stderr); + layout = LAY_HOME; + } + else + { + zui_draw_text(zui, ~0, 8, 18, "Select a core: "); + + if (zui_button(zui, 0, 18 + zui->font_size, "<- Back")) + layout = LAY_HOME; + + if (zui->pick_supported) + { + unsigned i, j = 0; + zui->pick_first += zui->mouse.wheel; + zui->pick_first = min(max(zui->pick_first, 0), zui->pick_supported - 5); + + for (i = zui->pick_first; i < zui->pick_supported; ++i) + { + if (j > 10) + break; + + if (zui_list_item(zui, 0, 60 + j * 30, zui->pick_cores[i].display_name)) + { + fputs("Core loading is not implemented yet, sorry.", stderr); + layout = LAY_HOME; + break; + } + j++; + } + } + else + { + zui_list_item(zui, 0, 60, "Content unsupported"); + } + } + } + + + + zui_finish(zui); +} + +static void zarch_draw_cursor(gl_t *gl, float x, float y) +{ +// zarch_render_quad(gl, x-5, y-5, 10, 10, 1, 1, 1, 1); +} +static void zarch_get_message(const char *message) +{ + +} + +static void zarch_render(void) +{ + int bottom; + unsigned width, height; + zui_t *zarch = NULL; + menu_handle_t *menu = menu_driver_get_ptr(); + settings_t *settings = config_get_ptr(); + + if (!menu || !menu->userdata) + return; + + video_driver_get_size(&width, &height); + +} + +static void zarch_frame(void) +{ + zui_t *zui = NULL; + menu_handle_t *menu = menu_driver_get_ptr(); + gl_t *gl = (gl_t*)driver_get_ptr()->video_data; + + rarch_assert(menu); + rarch_assert(gl); + + zui = (zui_t*)menu->userdata; + zui->set = config_get_ptr(); + zui->menu = menu; + + video_driver_get_size(&zui->width, &zui->height); + +// menu_display_set_viewport(); + + menu_display_ctl(MENU_DISPLAY_CTL_FONT_BUF, &zui->fb_buf); + + zui_render(zui); + + /* fetch it again in case the pointer was invalidated by a core load */ + gl = (gl_t*)driver_get_ptr()->video_data; + + if (zui->set->menu.mouse.enable) + zarch_draw_cursor(gl, zui->mouse.x, zui->mouse.y); + + gl->shader->use(gl, GL_SHADER_STOCK_BLEND); + +// menu_display_unset_viewport(); +} + +static void *zarch_init(void) +{ + zui_t *zui = NULL; + const video_driver_t *video_driver = NULL; + menu_handle_t *menu = NULL; + settings_t *settings = config_get_ptr(); + gl_t *gl = (gl_t*) + video_driver_get_ptr(&video_driver); + + if (video_driver != &video_gl || !gl) + { + RARCH_ERR("Cannot initialize GLUI menu driver: gl video driver is not active.\n"); + return NULL; + } + + if (settings->menu.mouse.enable) + { + RARCH_WARN("Forcing menu_mouse_enable=false\n"); + settings->menu.mouse.enable = false; + } + + menu = (menu_handle_t*)calloc(1, sizeof(*menu)); + + if (!menu) + goto error; + + menu->userdata = (zui_t*)calloc(1, sizeof(zui_t)); + + if (!menu->userdata) + goto error; + + zui = (zui_t*)menu->userdata; + + int tmpi; + tmpi = 1000; + menu_display_ctl(MENU_DISPLAY_CTL_SET_HEADER_HEIGHT, &tmpi); + + tmpi = 14; + menu_display_ctl(MENU_DISPLAY_CTL_SET_FONT_SIZE, &tmpi); + + zui->header_height = 1000;//dpi / 3; + zui->font_size = 14; + + if (settings->menu.wallpaper[0] != '\0') + rarch_main_data_msg_queue_push(DATA_TYPE_IMAGE, + settings->menu.wallpaper, "cb_menu_wallpaper", 0, 1, true); + + zui->ca.allocated = 0; + + matrix_4x4_ortho(&zui->mvp, 0, 1, 1, 0, 0, 1); + + return menu; +error: + if (menu) + free(menu); + return NULL; +} + +static void zarch_free(void *data) +{ + gl_t *gl = NULL; + const struct font_renderer *font_driver = NULL; + menu_handle_t *menu = (menu_handle_t*)data; + driver_t *driver = driver_get_ptr(); + zui_t *zarch = (zui_t*)menu->userdata; + + if (!zarch || !menu) + return; + + gfx_coord_array_free(&zarch->tmp_block.carr); + + gl = (gl_t*)video_driver_get_ptr(NULL); + + font_driver = gl ? (const struct font_renderer*)driver->font_osd_driver : NULL; + + if (font_driver && font_driver->bind_block) + font_driver->bind_block(driver->font_osd_data, NULL); + + if (menu->userdata) + free(menu->userdata); +} + +static void zarch_context_bg_destroy(zui_t *zarch) +{ +} + +static void zarch_context_destroy(void) +{ + gl_t *gl = (gl_t*)video_driver_get_ptr(NULL); + zui_t *zarch = NULL; + menu_handle_t *menu = menu_driver_get_ptr(); + driver_t *driver = driver_get_ptr(); + + if (!menu || !menu->userdata || !gl || !driver) + return; + + zarch = (zui_t*)menu->userdata; + + menu_display_free_main_font(); + + zarch_context_bg_destroy(zarch); +} + +static bool zarch_load_wallpaper(void *data, menu_image_type_t type) +{ + zui_t *zarch = NULL; + menu_handle_t *menu = menu_driver_get_ptr(); + + if (!menu || !menu->userdata) + return false; + + zarch = (zui_t*)menu->userdata; + + zarch_context_bg_destroy(zarch); + +// zarch->textures.bg.id = video_texture_load(data, +// TEXTURE_BACKEND_OPENGL, TEXTURE_FILTER_MIPMAP_LINEAR); +// zarch_allocate_white_texture(zarch); + + return true; +} + +static void zarch_context_reset(void) +{ + zui_t *zui = NULL; + menu_handle_t *menu = menu_driver_get_ptr(); + settings_t *settings = config_get_ptr(); + const char *font_path = NULL; + + if (!menu || !menu->userdata || !settings) + return; + + zui = (zui_t*)menu->userdata; + font_path = settings->video.font_enable ? settings->video.font_path : NULL; + + if (!menu_display_init_main_font(menu, font_path, zui->font_size)) + RARCH_WARN("Failed to load font."); + + zarch_context_bg_destroy(zui); +// zarch_allocate_white_texture(zarch); + + rarch_main_data_msg_queue_push(DATA_TYPE_IMAGE, + settings->menu.wallpaper, "cb_menu_wallpaper", 0, 1, true); +} + +menu_ctx_driver_t menu_ctx_zarch = { + NULL, + zarch_get_message, + zarch_render, + zarch_frame, + zarch_init, + zarch_free, + zarch_context_reset, + zarch_context_destroy, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + zarch_load_wallpaper, + "zarch", + MENU_VIDEO_DRIVER_OPENGL, + NULL, +}; diff --git a/menu/menu_driver.c b/menu/menu_driver.c index 6eb4c0ff6b..e0493e1a63 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -38,6 +38,9 @@ static const menu_ctx_driver_t *menu_ctx_drivers[] = { #endif #if defined(HAVE_RGUI) &menu_ctx_rgui, +#endif +#if defined(HAVE_ZARCH) + &menu_ctx_zarch, #endif &menu_ctx_null, NULL diff --git a/menu/menu_driver.h b/menu/menu_driver.h index c1c2916048..e079645d00 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -147,6 +147,7 @@ extern menu_ctx_driver_t menu_ctx_rmenu_xui; extern menu_ctx_driver_t menu_ctx_rgui; extern menu_ctx_driver_t menu_ctx_glui; extern menu_ctx_driver_t menu_ctx_xmb; +extern menu_ctx_driver_t menu_ctx_zarch; extern menu_ctx_driver_t menu_ctx_null; /** diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 90b36d80f8..367d57dbdf 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -388,15 +388,17 @@ check_lib MMAP "$CLIB" mmap check_pkgconf PYTHON python3 -if [ "$HAVE_GLUI" != 'no' ] || [ "$HAVE_XMB" != 'no' ]; then +if [ "$HAVE_GLUI" != 'no' ] || [ "$HAVE_XMB" != 'no' ] || [ "$HAVE_ZARCH" != 'no' ]; then if [ "$HAVE_RGUI" = 'no' ]; then HAVE_GLUI=no HAVE_XMB=no - echo "Notice: RGUI not available, GLUI and XMB will be disabled." + HAVE_ZARCH=no + echo "Notice: RGUI not available, GLUI, XMB and ZARCH will be disabled." elif [ "$HAVE_OPENGL" = 'no' ] && [ "$HAVE_GLES" = 'no' ]; then HAVE_GLUI=no HAVE_XMB=no - echo "Notice: GL/GLES not available, XMB and GLUI will be disabled." + HAVE_ZARCH=no + echo "Notice: GL/GLES not available, XMB, GLUI and ZARCH will be disabled." fi fi @@ -406,6 +408,6 @@ add_define_make OS "$OS" # Creates config.mk and config.h. add_define_make GLOBAL_CONFIG_DIR "$GLOBAL_CONFIG_DIR" -VARS="RGUI LAKKA GLUI XMB ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO CORETEXT PULSE SDL SDL2 D3D9 DINPUT LIBUSB XINPUT DSOUND XAUDIO OPENGL EXYNOS DISPMANX SUNXI OMAP GLES GLES3 VG EGL KMS GBM DRM DYLIB GETOPT_LONG THREADS CG LIBXML2 ZLIB DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE FREETYPE STB_FONT XKBCOMMON XVIDEO X11 XEXT XF86VM XINERAMA WAYLAND MALI_FBDEV VIVANTE_FBDEV NETWORKING NETPLAY NETWORK_CMD STDIN_CMD COMMAND SOCKET_LEGACY FBO STRL STRCASESTR MMAP PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM FFMPEG_AVCODEC_ENCODE_AUDIO2 SWRESAMPLE FFMPEG_AVCODEC_ENCODE_VIDEO2 BSV_MOVIE VIDEOCORE NEON FLOATHARD FLOATSOFTFP UDEV V4L2 AV_CHANNEL_LAYOUT 7ZIP PARPORT IMAGEVIEWER COCOA AVFOUNDATION CORELOCATION IOHIDMANAGER LIBRETRODB QT" +VARS="RGUI LAKKA GLUI ZARCH XMB ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO CORETEXT PULSE SDL SDL2 D3D9 DINPUT LIBUSB XINPUT DSOUND XAUDIO OPENGL EXYNOS DISPMANX SUNXI OMAP GLES GLES3 VG EGL KMS GBM DRM DYLIB GETOPT_LONG THREADS CG LIBXML2 ZLIB DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE FREETYPE STB_FONT XKBCOMMON XVIDEO X11 XEXT XF86VM XINERAMA WAYLAND MALI_FBDEV VIVANTE_FBDEV NETWORKING NETPLAY NETWORK_CMD STDIN_CMD COMMAND SOCKET_LEGACY FBO STRL STRCASESTR MMAP PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM FFMPEG_AVCODEC_ENCODE_AUDIO2 SWRESAMPLE FFMPEG_AVCODEC_ENCODE_VIDEO2 BSV_MOVIE VIDEOCORE NEON FLOATHARD FLOATSOFTFP UDEV V4L2 AV_CHANNEL_LAYOUT 7ZIP PARPORT IMAGEVIEWER COCOA AVFOUNDATION CORELOCATION IOHIDMANAGER LIBRETRODB QT" create_config_make config.mk $VARS create_config_header config.h $VARS