diff --git a/Makefile.wiiu b/Makefile.wiiu index 2c835fbac8..296cff5406 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -60,7 +60,7 @@ else OBJ := $(filter-out $(BLACKLIST),$(OBJ)) OBJ += gfx/drivers/wiiu_gfx.o -# OBJ += gfx/drivers_font/wiiu_font.o + OBJ += gfx/drivers_font/wiiu_font.o # OBJ += menu/drivers_display/menu_display_wiiu.o OBJ += input/drivers/wiiu_input.o OBJ += input/drivers_joypad/wiiu_joypad.o diff --git a/gfx/common/gx2_common.h b/gfx/common/gx2_common.h new file mode 100644 index 0000000000..93fffc9f41 --- /dev/null +++ b/gfx/common/gx2_common.h @@ -0,0 +1,85 @@ + + +#include + +#include "wiiu/tex_shader.h" + + +#undef _X +#undef _B + +#define _X 0x00 +#define _Y 0x01 +#define _Z 0x02 +#define _W 0x03 +#define _R 0x00 +#define _G 0x01 +#define _B 0x02 +#define _A 0x03 +#define _0 0x04 +#define _1 0x05 +#define GX2_COMP_SEL(c0, c1, c2, c3) (((c0) << 24) | ((c1) << 16) | ((c2) << 8) | (c3)) + +#define COLOR_ABGR(r, g, b, a) (((unsigned)(a) << 24) | ((b) << 16) | ((g) << 8) | ((r) << 0)) + +//#define GX2_CAN_ACCESS_DATA_SECTION + +typedef struct +{ + int width; + int height; + GX2TVRenderMode mode; +} wiiu_render_mode_t; + +typedef struct +{ + float x; + float y; +}position_t; + +typedef struct +{ + float u; + float v; +}tex_coord_t; + +typedef struct +{ + tex_shader_t* shader; + struct + { + GX2Texture texture; + int width; + int height; + bool enable; + position_t* position; + tex_coord_t* tex_coord; + } menu; + + GX2Sampler sampler_nearest; + GX2Sampler sampler_linear; + GX2Texture texture; + position_t* position; + tex_coord_t* tex_coord; + int width; + int height; + + + void* drc_scan_buffer; + void* tv_scan_buffer; + GX2ColorBuffer color_buffer; + GX2ContextState* ctx_state; + void* cmd_buffer; + + wiiu_render_mode_t render_mode; + video_viewport_t vp; + int frames; + OSTime last_vsync; + bool vsync; + bool rgb32; + bool smooth; + unsigned rotation; + bool keep_aspect; + bool should_resize; + +} wiiu_video_t; diff --git a/gfx/drivers/wiiu_gfx.c b/gfx/drivers/wiiu_gfx.c index 41da81ad3e..5619fd1397 100644 --- a/gfx/drivers/wiiu_gfx.c +++ b/gfx/drivers/wiiu_gfx.c @@ -30,89 +30,13 @@ #include "../../menu/menu_driver.h" #endif +#include "gfx/common/gx2_common.h" #include "system/memory.h" -#include "tex_shader.h" #include "wiiu_dbg.h" #include "../font_driver.h" -#undef _X -#undef _B - -#define _X 0x00 -#define _Y 0x01 -#define _Z 0x02 -#define _W 0x03 -#define _R 0x00 -#define _G 0x01 -#define _B 0x02 -#define _A 0x03 -#define _0 0x04 -#define _1 0x05 -#define GX2_COMP_SEL(c0, c1, c2, c3) (((c0) << 24) | ((c1) << 16) | ((c2) << 8) | (c3)) - -//#define GX2_CAN_ACCESS_DATA_SECTION - -typedef struct -{ - int width; - int height; - GX2TVRenderMode mode; -} wiiu_render_mode_t; - -typedef struct -{ - float x; - float y; -}position_t; - -typedef struct -{ - float u; - float v; -}tex_coord_t; - -typedef struct -{ - tex_shader_t* shader; - struct - { - GX2Texture texture; - int width; - int height; - bool enable; - position_t* position; - tex_coord_t* tex_coord; - } menu; - - GX2Sampler sampler_nearest; - GX2Sampler sampler_linear; - GX2Texture texture; - position_t* position; - tex_coord_t* tex_coord; - int width; - int height; - - - void* drc_scan_buffer; - void* tv_scan_buffer; - GX2ColorBuffer color_buffer; - GX2ContextState* ctx_state; - void* cmd_buffer; - - wiiu_render_mode_t render_mode; - video_viewport_t vp; - int frames; - OSTime last_vsync; - bool vsync; - bool rgb32; - bool smooth; - unsigned rotation; - bool keep_aspect; - bool should_resize; - -} wiiu_video_t; static const wiiu_render_mode_t wiiu_render_mode_map[] = { @@ -503,6 +427,10 @@ static void* wiiu_gfx_init(const video_info_t* video, driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, &refresh_rate); + font_driver_init_osd(wiiu, false, + video->is_threaded, + FONT_DRIVER_RENDER_WIIU); + return wiiu; } @@ -686,9 +614,14 @@ static bool wiiu_gfx_frame(void* data, const void* frame, GX2SetPixelSampler(&wiiu->sampler_linear, wiiu->shader->sampler.location); GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); - GX2DrawDone(); } + if (msg) + font_driver_render_msg(video_info, NULL, msg, NULL); + + if (wiiu->menu.enable) + GX2DrawDone(); + GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_DRC); GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_TV); @@ -841,6 +774,11 @@ static void wiiu_gfx_set_osd_msg(void* data, const char* msg, const void* params, void* font) { + wiiu_video_t* wiiu = (wiiu_video_t*)data; + + if (wiiu) + font_driver_render_msg(video_info, font, msg, params); + } static const video_poke_interface_t wiiu_poke_interface = diff --git a/gfx/drivers_font/wiiu_font.c b/gfx/drivers_font/wiiu_font.c new file mode 100644 index 0000000000..29f8b4225b --- /dev/null +++ b/gfx/drivers_font/wiiu_font.c @@ -0,0 +1,433 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * 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 "gfx/font_driver.h" +#include "gfx/video_driver.h" +#include "gfx/common/gx2_common.h" +#include "system/memory.h" +#include "wiiu/wiiu_dbg.h" + +#include "verbosity.h" + +typedef struct +{ + GX2Texture texture; + const font_renderer_driver_t* font_driver; + void* font_data; + struct + { + position_t* positions; + tex_coord_t* tex_coords; + int size; + int current; + }vertex_cache; +} wiiu_font_t; + +static void* wiiu_font_init_font(void* data, const char* font_path, + float font_size, bool is_threaded) +{ + int i; + struct font_atlas* atlas = NULL; + wiiu_font_t* font = (wiiu_font_t*)calloc(1, sizeof(*font)); + + if (!font) + return NULL; + + if (!font_renderer_create_default((const void**)&font->font_driver, + &font->font_data, font_path, font_size)) + { + RARCH_WARN("Couldn't initialize font renderer.\n"); + free(font); + return NULL; + } + + atlas = font->font_driver->get_atlas(font->font_data); + font->texture.surface.width = atlas->width; + font->texture.surface.height = atlas->height; + font->texture.surface.depth = 1; + font->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; + font->texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; + font->texture.viewNumSlices = 1; + + font->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8; + font->texture.compMap = GX2_COMP_SEL(_R, _R, _R, _R); + + GX2CalcSurfaceSizeAndAlignment(&font->texture.surface); + GX2InitTextureRegs(&font->texture); + font->texture.surface.image = MEM1_alloc(font->texture.surface.imageSize, + font->texture.surface.alignment); + + for (i = 0; (i < atlas->height) && (i < font->texture.surface.height); i++) + memcpy(font->texture.surface.image + (i * font->texture.surface.pitch), + atlas->buffer + (i * atlas->width), atlas->width); + + GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, font->texture.surface.image, + font->texture.surface.imageSize); + + atlas->dirty = false; + + font->vertex_cache.size = 0x1000; + font->vertex_cache.positions = MEM2_alloc(font->vertex_cache.size * sizeof(position_t), GX2_VERTEX_BUFFER_ALIGNMENT); + font->vertex_cache.tex_coords = MEM2_alloc(font->vertex_cache.size * sizeof(tex_coord_t), GX2_VERTEX_BUFFER_ALIGNMENT); + + return font; +} + +static void wiiu_font_free_font(void* data, bool is_threaded) +{ + wiiu_font_t* font = (wiiu_font_t*)data; + + if (!font) + return; + + if (font->font_driver && font->font_data) + font->font_driver->free(font->font_data); + + MEM1_free(font->texture.surface.image); + MEM2_free(font->vertex_cache.positions); + MEM2_free(font->vertex_cache.tex_coords); + free(font); +} + +static int wiiu_font_get_message_width(void* data, const char* msg, + unsigned msg_len, float scale) +{ + wiiu_font_t* font = (wiiu_font_t*)data; + + unsigned i; + int delta_x = 0; + + if (!font) + return 0; + + for (i = 0; i < msg_len; i++) + { + const char* msg_tmp = &msg[i]; + unsigned code = utf8_walk(&msg_tmp); + unsigned skip = msg_tmp - &msg[i]; + + if (skip > 1) + i += skip - 1; + + const struct font_glyph* glyph = + font->font_driver->get_glyph(font->font_data, code); + + if (!glyph) /* Do something smarter here ... */ + glyph = font->font_driver->get_glyph(font->font_data, '?'); + + if (!glyph) + continue; + + delta_x += glyph->advance_x; + } + + return delta_x * scale; +} + +static void wiiu_font_render_line( + video_frame_info_t *video_info, + wiiu_font_t* font, const char* msg, unsigned msg_len, + float scale, const unsigned int color, float pos_x, + float pos_y, unsigned text_align) +{ + unsigned i; + wiiu_video_t* wiiu = (wiiu_video_t*)video_driver_get_ptr(false); + unsigned width = video_info->width; + unsigned height = video_info->height; + int x = roundf(pos_x * width); + int y = roundf((1.0f - pos_y) * height); + int delta_x = 0; + int delta_y = 0; + + if(font->vertex_cache.size < (msg_len * 4)) + return; + + switch (text_align) + { + case TEXT_ALIGN_RIGHT: + x -= wiiu_font_get_message_width(font, msg, msg_len, scale); + break; + + case TEXT_ALIGN_CENTER: + x -= wiiu_font_get_message_width(font, msg, msg_len, scale) / 2; + break; + } + + if ((font->vertex_cache.size - font->vertex_cache.current) < (msg_len * 4)) + font->vertex_cache.current = 0; + + position_t* pos = font->vertex_cache.positions + font->vertex_cache.current; + tex_coord_t* coord = font->vertex_cache.tex_coords + font->vertex_cache.current; + + for (i = 0; i < msg_len; i++) + { + int off_x, off_y, tex_x, tex_y, width, height; + const char* msg_tmp = &msg[i]; + unsigned code = utf8_walk(&msg_tmp); + unsigned skip = msg_tmp - &msg[i]; + + if (skip > 1) + i += skip - 1; + + const struct font_glyph* glyph = + font->font_driver->get_glyph(font->font_data, code); + + if (!glyph) /* Do something smarter here ... */ + glyph = font->font_driver->get_glyph(font->font_data, '?'); + + if (!glyph) + continue; + + off_x = glyph->draw_offset_x; + off_y = glyph->draw_offset_y; + tex_x = glyph->atlas_offset_x; + tex_y = glyph->atlas_offset_y; + width = glyph->width; + height = glyph->height; + + + float x0 = x + off_x + delta_x * scale; + float y0 = y + off_y + delta_y * scale; + float u0 = tex_x; + float v0 = tex_y; + float x1 = x0 + width * scale; + float y1 = y0 + height * scale; + float u1 = u0 + width; + float v1 = v0 + height; + + pos[0].x = (2.0f * x0 / wiiu->color_buffer.surface.width) - 1.0f; + pos[0].y = (2.0f * y0 / wiiu->color_buffer.surface.height) - 1.0f; + pos[1].x = (2.0f * x1 / wiiu->color_buffer.surface.width) - 1.0f;; + pos[1].y = (2.0f * y0 / wiiu->color_buffer.surface.height) - 1.0f; + pos[2].x = (2.0f * x1 / wiiu->color_buffer.surface.width) - 1.0f;; + pos[2].y = (2.0f * y1 / wiiu->color_buffer.surface.height) - 1.0f; + pos[3].x = (2.0f * x0 / wiiu->color_buffer.surface.width) - 1.0f;; + pos[3].y = (2.0f * y1 / wiiu->color_buffer.surface.height) - 1.0f; + pos += 4; + + coord[0].u = u0 / font->texture.surface.width; + coord[0].v = v1 / font->texture.surface.height; + coord[1].u = u1 / font->texture.surface.width; + coord[1].v = v1 / font->texture.surface.height; + coord[2].u = u1 / font->texture.surface.width; + coord[2].v = v0 / font->texture.surface.height; + coord[3].u = u0 / font->texture.surface.width; + coord[3].v = v0 / font->texture.surface.height; + coord += 4; + + delta_x += glyph->advance_x; + delta_y += glyph->advance_y; + } + + int count = pos - font->vertex_cache.positions - font->vertex_cache.current; + + if (!count) + return; + + GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, font->vertex_cache.positions + font->vertex_cache.current, count * sizeof(position_t)); + GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, font->vertex_cache.tex_coords + font->vertex_cache.current, count * sizeof(tex_coord_t)); + + +#if 0 + printf("%s\n", msg); + DEBUG_VAR(color); +#endif + + GX2SetAttribBuffer(0, font->vertex_cache.size * sizeof(position_t), sizeof(position_t), font->vertex_cache.positions); + GX2SetAttribBuffer(1, font->vertex_cache.size * sizeof(tex_coord_t), sizeof(tex_coord_t), font->vertex_cache.tex_coords); + + GX2SetPixelTexture(&font->texture, wiiu->shader->sampler.location); + GX2SetPixelSampler(&wiiu->sampler_linear, wiiu->shader->sampler.location); + + GX2SetBlendConstantColor(((color >> 0) & 0xFF) / 255.0f, ((color >> 8) & 0xFF) / 255.0f, + ((color >> 16) & 0xFF) / 255.0f, ((color >> 24) & 0xFF) / 255.0f); + + GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_MODE_BLEND_FACTOR, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD, + GX2_ENABLE, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD); + + GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, count, font->vertex_cache.current, 1); + + GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD, + GX2_ENABLE, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD); + + font->vertex_cache.current = pos - font->vertex_cache.positions; +} + +static void wiiu_font_render_message( + video_frame_info_t *video_info, + wiiu_font_t* font, const char* msg, float scale, + const unsigned int color, float pos_x, float pos_y, + unsigned text_align) +{ + int lines = 0; + float line_height; + + if (!msg || !*msg) + return; + + /* If the font height is not supported just draw as usual */ + if (!font->font_driver->get_line_height) + { + wiiu_font_render_line(video_info, font, msg, strlen(msg), + scale, color, pos_x, pos_y, text_align); + return; + } + + line_height = scale / font->font_driver->get_line_height(font->font_data); + + for (;;) + { + const char* delim = strchr(msg, '\n'); + + /* Draw the line */ + if (delim) + { + unsigned msg_len = delim - msg; + wiiu_font_render_line(video_info, font, msg, msg_len, + scale, color, pos_x, pos_y - (float)lines * line_height, + text_align); + msg += msg_len + 1; + lines++; + } + else + { + unsigned msg_len = strlen(msg); + wiiu_font_render_line(video_info, font, msg, msg_len, + scale, color, pos_x, pos_y - (float)lines * line_height, + text_align); + break; + } + } +} + +static void wiiu_font_render_msg( + video_frame_info_t *video_info, + void* data, const char* msg, + const void* userdata) +{ + float x, y, scale, drop_mod, drop_alpha; + int drop_x, drop_y; + unsigned max_glyphs; + enum text_alignment text_align; + unsigned color, color_dark, r, g, b, alpha, r_dark, g_dark, b_dark, alpha_dark; + wiiu_font_t * font = (wiiu_font_t*)data; + const struct font_params* params = (const struct font_params*)userdata; + unsigned width = video_info->width; + unsigned height = video_info->height; + + if (!font || !msg || !*msg) + return; + + if (params) + { + x = params->x; + y = params->y; + scale = params->scale; + text_align = params->text_align; + drop_x = params->drop_x; + drop_y = params->drop_y; + drop_mod = params->drop_mod; + drop_alpha = params->drop_alpha; + r = FONT_COLOR_GET_RED(params->color); + g = FONT_COLOR_GET_GREEN(params->color); + b = FONT_COLOR_GET_BLUE(params->color); + alpha = FONT_COLOR_GET_ALPHA(params->color); + color = params->color; + } + else + { + x = video_info->font_msg_pos_x; + y = video_info->font_msg_pos_y; + scale = 1.0f; + text_align = TEXT_ALIGN_LEFT; + + r = (video_info->font_msg_color_r * 255); + g = (video_info->font_msg_color_g * 255); + b = (video_info->font_msg_color_b * 255); + alpha = 255; + color = COLOR_ABGR(r, g, b, alpha); + + drop_x = -2; + drop_y = -2; + drop_mod = 0.3f; + drop_alpha = 1.0f; + } + + max_glyphs = strlen(msg); + + if (drop_x || drop_y) + max_glyphs *= 2; + + if (drop_x || drop_y) + { + r_dark = r * drop_mod; + g_dark = g * drop_mod; + b_dark = b * drop_mod; + alpha_dark = alpha * drop_alpha; + color_dark = COLOR_ABGR(r_dark, g_dark, b_dark, alpha_dark); + + wiiu_font_render_message(video_info, font, msg, scale, color_dark, + x + scale * drop_x / width, y + + scale * drop_y / height, text_align); + } + + wiiu_font_render_message(video_info, font, msg, scale, + color, x, y, text_align); +} + +static const struct font_glyph* wiiu_font_get_glyph( + void* data, uint32_t code) +{ + wiiu_font_t* font = (wiiu_font_t*)data; + + if (!font || !font->font_driver) + return NULL; + + if (!font->font_driver->ident) + return NULL; + + return font->font_driver->get_glyph((void*)font->font_driver, code); +} + +static void wiiu_font_flush_block(unsigned width, unsigned height, void* data) +{ + (void)data; +} + +static void wiiu_font_bind_block(void* data, void* userdata) +{ + (void)data; +} + + +font_renderer_t wiiu_font = +{ + wiiu_font_init_font, + wiiu_font_free_font, + wiiu_font_render_msg, + "wiiufont", + wiiu_font_get_glyph, + wiiu_font_bind_block, + wiiu_font_flush_block, + wiiu_font_get_message_width, +}; diff --git a/gfx/font_driver.c b/gfx/font_driver.c index 0ae613bcb1..215ad505ae 100644 --- a/gfx/font_driver.c +++ b/gfx/font_driver.c @@ -337,6 +337,37 @@ static bool ctr_font_init_first( } #endif +#ifdef WIIU +static const font_renderer_t *wiiu_font_backends[] = { + &wiiu_font, + NULL +}; + +static bool wiiu_font_init_first( + const void **font_driver, void **font_handle, + void *video_data, const char *font_path, + float font_size, bool is_threaded) +{ + unsigned i; + + for (i = 0; wiiu_font_backends[i]; i++) + { + void *data = wiiu_font_backends[i]->init( + video_data, font_path, font_size, + is_threaded); + + if (!data) + continue; + + *font_driver = wiiu_font_backends[i]; + *font_handle = data; + return true; + } + + return false; +} +#endif + static bool font_init_first( const void **font_driver, void **font_handle, void *video_data, const char *font_path, float font_size, @@ -372,6 +403,11 @@ static bool font_init_first( return ctr_font_init_first(font_driver, font_handle, video_data, font_path, font_size, is_threaded); #endif +#ifdef WIIU + case FONT_DRIVER_RENDER_WIIU: + return wiiu_font_init_first(font_driver, font_handle, + video_data, font_path, font_size, is_threaded); +#endif #ifdef HAVE_CACA case FONT_DRIVER_RENDER_CACA: return caca_font_init_first(font_driver, font_handle, diff --git a/gfx/font_driver.h b/gfx/font_driver.h index b1046c28a3..172f0b586e 100644 --- a/gfx/font_driver.h +++ b/gfx/font_driver.h @@ -33,6 +33,7 @@ enum font_driver_render_api FONT_DRIVER_RENDER_DIRECT3D_API, FONT_DRIVER_RENDER_VITA2D, FONT_DRIVER_RENDER_CTR, + FONT_DRIVER_RENDER_WIIU, FONT_DRIVER_RENDER_VULKAN_API, FONT_DRIVER_RENDER_CACA, FONT_DRIVER_RENDER_GDI, @@ -179,6 +180,7 @@ extern font_renderer_t d3d_xdk1_font; extern font_renderer_t d3d_win32_font; extern font_renderer_t vita2d_vita_font; extern font_renderer_t ctr_font; +extern font_renderer_t wiiu_font; extern font_renderer_t vulkan_raster_font; extern font_renderer_t caca_font; extern font_renderer_t gdi_font; diff --git a/griffin/griffin.c b/griffin/griffin.c index cb1d35139e..dc04328eef 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -391,6 +391,10 @@ FONTS #include "../gfx/drivers_font/ctr_font.c" #endif +#if defined(WIIU) +#include "../gfx/drivers_font/wiiu_font.c" +#endif + #if defined(HAVE_CACA) #include "../gfx/drivers_font/caca_font.c" #endif diff --git a/wiiu/include/wiiu/gx2/enum.h b/wiiu/include/wiiu/gx2/enum.h index e6cd3c7977..05d71379ee 100644 --- a/wiiu/include/wiiu/gx2/enum.h +++ b/wiiu/include/wiiu/gx2/enum.h @@ -72,6 +72,8 @@ typedef enum GX2BlendMode GX2_BLEND_MODE_INV_SRC1_COLOR = 16, GX2_BLEND_MODE_SRC1_ALPHA = 17, GX2_BLEND_MODE_INV_SRC1_ALPHA = 18, + GX2_BLEND_MODE_BLEND_ALPHA = 19, + GX2_BLEND_MODE_INV_BLEND_ALPHA = 20, } GX2BlendMode; typedef enum GX2BlendCombineMode diff --git a/wiiu/system/imports.h b/wiiu/system/imports.h index 3a8db13ced..f5f06d82bc 100644 --- a/wiiu/system/imports.h +++ b/wiiu/system/imports.h @@ -132,6 +132,7 @@ IMPORT(GX2SetScissor); IMPORT(GX2SetDepthOnlyControl); IMPORT(GX2SetColorControl); IMPORT(GX2SetBlendControl); +IMPORT(GX2SetBlendConstantColor); IMPORT(GX2SetCullOnlyControl); IMPORT(GX2CalcFetchShaderSizeEx); IMPORT(GX2InitFetchShaderEx);