diff --git a/workspace/all/bootlogo/bootlogo.c b/workspace/all/bootlogo/bootlogo.c index 57a36a0b3..0f153b0e4 100644 --- a/workspace/all/bootlogo/bootlogo.c +++ b/workspace/all/bootlogo/bootlogo.c @@ -91,7 +91,7 @@ int main(int argc, char *argv[]) PWR_setCPUSpeed(CPU_SPEED_MENU); - screen = GFX_init(MODE_MAIN); + screen = GFX_init(MODE_MENU); PAD_init(); PWR_init(); diff --git a/workspace/all/clock/clock.c b/workspace/all/clock/clock.c index 38970b455..65534c336 100644 --- a/workspace/all/clock/clock.c +++ b/workspace/all/clock/clock.c @@ -22,7 +22,7 @@ enum { int main(int argc , char* argv[]) { PWR_setCPUSpeed(CPU_SPEED_MENU); - SDL_Surface* screen = GFX_init(MODE_MAIN); + SDL_Surface* screen = GFX_init(MODE_MENU); PAD_init(); PWR_init(); InitSettings(); diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index aff5d06cc..f17801d4c 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -281,14 +281,14 @@ int GFX_updateColors(void) { // We are currently micro managing all of these screen-mapped colors, // should just move this to the caller. - THEME_COLOR1 = mapUint(CFG_getColor(1)); - THEME_COLOR2 = mapUint(CFG_getColor(2)); - THEME_COLOR3 = mapUint(CFG_getColor(3)); - THEME_COLOR4 = mapUint(CFG_getColor(4)); - THEME_COLOR5 = mapUint(CFG_getColor(5)); - THEME_COLOR6 = mapUint(CFG_getColor(6)); - THEME_COLOR7 = mapUint(CFG_getColor(7)); - ALT_BUTTON_TEXT_COLOR = uintToColour(CFG_getColor(3)); + THEME_COLOR1 = mapUint(CFG_getColor(COLOR_MAIN)); + THEME_COLOR2 = mapUint(CFG_getColor(COLOR_ACCENT)); + THEME_COLOR3 = mapUint(CFG_getColor(COLOR_ACCENT2)); + THEME_COLOR4 = mapUint(CFG_getColor(COLOR_LIST_TEXT)); + THEME_COLOR5 = mapUint(CFG_getColor(COLOR_LIST_TEXT_SELECTED)); + THEME_COLOR6 = mapUint(CFG_getColor(COLOR_HINT)); + THEME_COLOR7 = mapUint(CFG_getColor(COLOR_BACKGROUND)); + ALT_BUTTON_TEXT_COLOR = uintToColour(CFG_getColor(COLOR_ACCENT2)); return 0; } @@ -308,6 +308,11 @@ SDL_Surface *GFX_init(int mode) CFG_init(GFX_loadSystemFont, GFX_updateColors); + // by default, we will clear with whatever background color the user prefers + // if MODE_MENU /e.g. minarch, clear with default black) + if(mode == MODE_MAIN) + GFX_setClearColor(mapUint(CFG_getColor(COLOR_BACKGROUND))); + // We always have to symlink, does not depend on NTP being enabled PLAT_initTimezones(); PLAT_setCurrentTimezone(PLAT_getCurrentTimezone()); @@ -1823,7 +1828,7 @@ void GFX_blitMessage(TTF_Font *font, char *msg, SDL_Surface *dst, SDL_Rect *dst_ if (len) { - text = TTF_RenderUTF8_Blended_Wrapped(font, line, COLOR_WHITE, dst_rect->w); + text = TTF_RenderUTF8_Blended_Wrapped(font, line, uintToColour(CFG_getColor(COLOR_LIST_TEXT)), dst_rect->w); int x = dst_rect->x; x += (dst_rect->w - text->w) / 2; SDL_BlitSurface(text, NULL, dst, &(SDL_Rect){x, y}); diff --git a/workspace/all/common/api.h b/workspace/all/common/api.h index 3d5bdf097..1cef108f1 100644 --- a/workspace/all/common/api.h +++ b/workspace/all/common/api.h @@ -279,6 +279,7 @@ SDL_Surface* GFX_init(int mode); #define GFX_scrollTextTexture PLAT_scrollTextTexture // (TTF_Font* font, const char* in_name,int x, int y, int w, int h, SDL_Color color, float transparency, SDL_mutex* fontMutex); #define GFX_flipHidden PLAT_flipHidden //(void) #define GFX_GL_screenCapture PLAT_GL_screenCapture //(void) +#define GFX_setClearColor PLAT_setClearColor //(uint32_t color) void GFX_setMode(int mode); int GFX_hdmiChanged(void); @@ -659,6 +660,7 @@ void PLAT_flip(SDL_Surface* screen, int sync); void PLAT_GL_Swap(); void GFX_GL_Swap(); unsigned char* PLAT_GL_screenCapture(int* outWidth, int* outHeight); +void PLAT_setClearColor(uint32_t color); void PLAT_GPU_Flip(); void PLAT_setShaders(int nr); void PLAT_resetShaders(); diff --git a/workspace/all/common/config.c b/workspace/all/common/config.c index f47c4e32d..368464b94 100644 --- a/workspace/all/common/config.c +++ b/workspace/all/common/config.c @@ -401,13 +401,13 @@ void CFG_init(FontLoad_callback_t cb, ColorSet_callback_t ccb) } // load gfx related stuff until we drop the indirection - CFG_setColor(1, CFG_getColor(1)); - CFG_setColor(2, CFG_getColor(2)); - CFG_setColor(3, CFG_getColor(3)); - CFG_setColor(4, CFG_getColor(4)); - CFG_setColor(5, CFG_getColor(5)); - CFG_setColor(6, CFG_getColor(6)); - CFG_setColor(7, CFG_getColor(7)); + CFG_setColor(1, CFG_getColor(COLOR_MAIN)); + CFG_setColor(2, CFG_getColor(COLOR_ACCENT)); + CFG_setColor(3, CFG_getColor(COLOR_ACCENT2)); + CFG_setColor(4, CFG_getColor(COLOR_LIST_TEXT)); + CFG_setColor(5, CFG_getColor(COLOR_LIST_TEXT_SELECTED)); + CFG_setColor(6, CFG_getColor(COLOR_HINT)); + CFG_setColor(7, CFG_getColor(COLOR_BACKGROUND)); // avoid reloading the font if not neccessary if (!fontLoaded) CFG_setFontId(CFG_getFontId()); @@ -1024,31 +1024,31 @@ void CFG_get(const char *key, char *value) } else if (strcmp(key, "color1") == 0) { - sprintf(value, "\"0x%06X\"", CFG_getColor(1)); + sprintf(value, "\"0x%06X\"", CFG_getColor(COLOR_MAIN)); } else if (strcmp(key, "color2") == 0) { - sprintf(value, "\"0x%06X\"", CFG_getColor(2)); + sprintf(value, "\"0x%06X\"", CFG_getColor(COLOR_ACCENT)); } else if (strcmp(key, "color3") == 0) { - sprintf(value, "\"0x%06X\"", CFG_getColor(3)); + sprintf(value, "\"0x%06X\"", CFG_getColor(COLOR_ACCENT2)); } else if (strcmp(key, "color4") == 0) { - sprintf(value, "\"0x%06X\"", CFG_getColor(4)); + sprintf(value, "\"0x%06X\"", CFG_getColor(COLOR_LIST_TEXT)); } else if (strcmp(key, "color5") == 0) { - sprintf(value, "\"0x%06X\"", CFG_getColor(5)); + sprintf(value, "\"0x%06X\"", CFG_getColor(COLOR_LIST_TEXT_SELECTED)); } else if (strcmp(key, "color6") == 0) { - sprintf(value, "\"0x%06X\"", CFG_getColor(6)); + sprintf(value, "\"0x%06X\"", CFG_getColor(COLOR_HINT)); } else if (strcmp(key, "color7") == 0) { - sprintf(value, "\"0x%06X\"", CFG_getColor(7)); + sprintf(value, "\"0x%06X\"", CFG_getColor(COLOR_BACKGROUND)); } else if (strcmp(key, "radius") == 0) { diff --git a/workspace/all/common/config.h b/workspace/all/common/config.h index 56c74ffaf..3665fd8c3 100644 --- a/workspace/all/common/config.h +++ b/workspace/all/common/config.h @@ -71,6 +71,17 @@ enum { RA_SORT_COUNT }; +// Theme colors +enum { + COLOR_MAIN = 1, + COLOR_ACCENT = 2, + COLOR_ACCENT2 = 3, + COLOR_LIST_TEXT = 4, + COLOR_LIST_TEXT_SELECTED = 5, + COLOR_HINT = 6, + COLOR_BACKGROUND = 7 +}; + typedef struct { // Theme @@ -161,6 +172,13 @@ typedef struct #define CFG_DEFAULT_COLOR5 0x000000U #define CFG_DEFAULT_COLOR6 0xffffffU #define CFG_DEFAULT_COLOR7 0x000000U +#define CFG_DEFAULT_COLOR_MAIN CFG_DEFAULT_COLOR1 +#define CFG_DEFAULT_COLOR_ACCENT CFG_DEFAULT_COLOR2 +#define CFG_DEFAULT_COLOR_ACCENT2 CFG_DEFAULT_COLOR3 +#define CFG_DEFAULT_COLOR_LIST_TEXT CFG_DEFAULT_COLOR4 +#define CFG_DEFAULT_COLOR_LIST_TEXT_SELECTED CFG_DEFAULT_COLOR5 +#define CFG_DEFAULT_COLOR_HINT CFG_DEFAULT_COLOR6 +#define CFG_DEFAULT_COLOR_BACKGROUND CFG_DEFAULT_COLOR7 #define CFG_DEFAULT_THUMBRADIUS 20 // unscaled! #define CFG_DEFAULT_SHOWCLOCK false #define CFG_DEFAULT_CLOCK24H true diff --git a/workspace/all/common/generic_video.c b/workspace/all/common/generic_video.c index 0d68a74ef..5cb253a5f 100644 --- a/workspace/all/common/generic_video.c +++ b/workspace/all/common/generic_video.c @@ -35,6 +35,17 @@ static int finalScaleFilter=GL_LINEAR; static int reloadShaderTextures = 1; static int shaderResetRequested = 0; +static SDL_BlendMode getPremultipliedBlendMode(void) { + return SDL_ComposeCustomBlendMode( + SDL_BLENDFACTOR_ONE, + SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, + SDL_BLENDOPERATION_ADD, + SDL_BLENDFACTOR_ONE, + SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, + SDL_BLENDOPERATION_ADD + ); +} + // shader stuff typedef struct Shader { @@ -91,12 +102,13 @@ static struct VID_Context { SDL_Texture* overlay; SDL_Surface* screen; SDL_GLContext gl_context; - + GFX_Renderer* blit; // yeesh int width; int height; int pitch; int sharpness; + uint32_t clear_color; } vid; static int device_width; @@ -229,7 +241,7 @@ GLuint link_program(GLuint vertex_shader, GLuint fragment_shader, const char* ca void* binary = malloc(binaryLength); glGetProgramBinary(program, binaryLength, NULL, &binaryFormat, binary); - mkdir(SDCARD_PATH "/.shadercache", 0755); + mkdir(SDCARD_PATH "/.shadercache", 0755); f = fopen(cache_path, "wb"); if (f) { fwrite(&binaryFormat, sizeof(GLenum), 1, f); @@ -434,7 +446,7 @@ GLuint load_shader_from_file(GLenum type, const char* filename, const char* path void PLAT_initShaders() { SDL_GL_MakeCurrent(vid.window, vid.gl_context); glViewport(0, 0, device_width, device_height); - + GLuint vertex; GLuint fragment; @@ -452,7 +464,7 @@ void PLAT_initShaders() { vertex = load_shader_from_file(GL_VERTEX_SHADER, "noshader.glsl",SYSSHADERS_FOLDER); fragment = load_shader_from_file(GL_FRAGMENT_SHADER, "noshader.glsl",SYSSHADERS_FOLDER); g_noshader = link_program(vertex, fragment,"noshader.glsl"); - + LOG_info("default shaders loaded, %i\n\n",g_shader_default); } @@ -503,7 +515,7 @@ SDL_Surface* PLAT_initVideo(void) { //SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE); SDL_InitSubSystem(SDL_INIT_VIDEO); SDL_ShowCursor(0); - + // SDL_version compiled; // SDL_version linked; // SDL_VERSION(&compiled); @@ -530,7 +542,7 @@ SDL_Surface* PLAT_initVideo(void) { // } // SDL_GetCurrentDisplayMode(0, &mode); // LOG_info("Current display mode: %ix%i (%s)\n", mode.w,mode.h, SDL_GetPixelFormatName(mode.format)); - + int w = FIXED_WIDTH; int h = FIXED_HEIGHT; int p = FIXED_PITCH; @@ -572,33 +584,39 @@ SDL_Surface* PLAT_initVideo(void) { vid.target_layer3 = SDL_CreateTexture(vid.renderer,SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET , w,h); vid.target_layer4 = SDL_CreateTexture(vid.renderer,SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET , w,h); vid.target_layer5 = SDL_CreateTexture(vid.renderer,SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET , w,h); - + vid.target = NULL; // only needed for non-native sizes - + vid.screen = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_ARGB8888); + SDL_BlendMode premult = getPremultipliedBlendMode(); SDL_SetSurfaceBlendMode(vid.screen, SDL_BLENDMODE_BLEND); - SDL_SetTextureBlendMode(vid.stream_layer1, SDL_BLENDMODE_BLEND); - SDL_SetTextureBlendMode(vid.target_layer2, SDL_BLENDMODE_BLEND); - SDL_SetTextureBlendMode(vid.target_layer3, SDL_BLENDMODE_BLEND); - SDL_SetTextureBlendMode(vid.target_layer4, SDL_BLENDMODE_BLEND); + SDL_SetTextureBlendMode(vid.stream_layer1, premult); + SDL_SetTextureBlendMode(vid.target_layer2, premult); + SDL_SetTextureBlendMode(vid.target_layer3, SDL_BLENDMODE_BLEND); // straight alpha game art + SDL_SetTextureBlendMode(vid.target_layer4, premult); SDL_SetTextureBlendMode(vid.target_layer5, SDL_BLENDMODE_BLEND); - + vid.width = w; vid.height = h; vid.pitch = p; - + SDL_transparentBlack = SDL_MapRGBA(vid.screen->format, 0, 0, 0, 0); - + PLAT_setClearColor(SDL_transparentBlack); + device_width = w; device_height = h; device_pitch = p; - + vid.sharpness = SHARPNESS_SOFT; - + return vid.screen; } +void PLAT_setClearColor(uint32_t color) { + vid.clear_color = color; +} + #define MAX_SHADER_PRAGMAS 32 void loadShaderPragmas(Shader *shader, const char *shaderSource) { shader->pragmas = calloc(MAX_SHADER_PRAGMAS, sizeof(ShaderParam)); @@ -631,14 +649,14 @@ void PLAT_updateShader(int i, const char *filename, int *scale, int *filter, int GLuint vertex_shader1 = load_shader_from_file(GL_VERTEX_SHADER, filename,SHADERS_FOLDER "/glsl"); GLuint fragment_shader1 = load_shader_from_file(GL_FRAGMENT_SHADER, filename,SHADERS_FOLDER "/glsl"); - + // Link the shader program if (shader->shader_p != 0) { LOG_info("Deleting previous shader %i\n",shader->shader_p); glDeleteProgram(shader->shader_p); } shader->shader_p = link_program(vertex_shader1, fragment_shader1,filename); - + shader->u_FrameDirection = glGetUniformLocation( shader->shader_p, "FrameDirection"); shader->u_FrameCount = glGetUniformLocation( shader->shader_p, "FrameCount"); shader->u_OutputSize = glGetUniformLocation( shader->shader_p, "OutputSize"); @@ -702,7 +720,7 @@ void PLAT_setShaders(int nr) { static void clearVideo(void) { for (int i=0; i<3; i++) { SDL_RenderClear(vid.renderer); - SDL_FillRect(vid.screen, NULL, SDL_transparentBlack); + SDL_FillRect(vid.screen, NULL, vid.clear_color); SDL_RenderCopy(vid.renderer, vid.stream_layer1, NULL, NULL); SDL_RenderPresent(vid.renderer); } @@ -753,7 +771,7 @@ void PLAT_clearVideo(SDL_Surface* screen) { SDL_FillRect(screen, NULL, SDL_transparentBlack); } void PLAT_clearAll(void) { - // ok honestely mixing SDL and OpenGL is really bad, but hey it works just got to sometimes clear gpu stuff and pull context back to SDL + // ok honestely mixing SDL and OpenGL is really bad, but hey it works just got to sometimes clear gpu stuff and pull context back to SDL // so yeah clear all layers and pull a flip() to make it switch back to SDL before clearing PLAT_clearLayers(0); PLAT_flip(vid.screen,0); @@ -761,8 +779,8 @@ void PLAT_clearAll(void) { PLAT_flip(vid.screen,0); // then do normal SDL clearing stuff - PLAT_clearVideo(vid.screen); - SDL_SetRenderDrawColor(vid.renderer, 0, 0, 0, 0); + PLAT_clearVideo(vid.screen); + SDL_SetRenderDrawColor(vid.renderer, 0, 0, 0, 0); SDL_RenderClear(vid.renderer); } @@ -791,9 +809,9 @@ static int hard_scale = 4; // TODO: base src size, eg. 160x144 can be 4 static void resizeVideo(int w, int h, int p) { if (w==vid.width && h==vid.height && p==vid.pitch) return; - + // TODO: minarch disables crisp (and nn upscale before linear downscale) when native, is this true? - + if (w>=device_width && h>=device_height) hard_scale = 1; // else if (h>=160) hard_scale = 2; // limits gba and up to 2x (seems sufficient for 640x480) else hard_scale = 4; @@ -802,11 +820,11 @@ static void resizeVideo(int w, int h, int p) { SDL_DestroyTexture(vid.stream_layer1); if (vid.target) SDL_DestroyTexture(vid.target); - + // SDL_SetHintWithPriority(SDL_HINT_RENDER_SCALE_QUALITY, vid.sharpness==SHARPNESS_SOFT?"1":"0", SDL_HINT_OVERRIDE); vid.stream_layer1 = SDL_CreateTexture(vid.renderer,SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w,h); - SDL_SetTextureBlendMode(vid.stream_layer1, SDL_BLENDMODE_BLEND); - + SDL_SetTextureBlendMode(vid.stream_layer1, getPremultipliedBlendMode()); + if (vid.sharpness==SHARPNESS_CRISP) { // SDL_SetHintWithPriority(SDL_HINT_RENDER_SCALE_QUALITY, "1", SDL_HINT_OVERRIDE); vid.target = SDL_CreateTexture(vid.renderer,SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w * hard_scale,h * hard_scale); @@ -814,7 +832,7 @@ static void resizeVideo(int w, int h, int p) { else { vid.target = NULL; } - + vid.width = w; vid.height = h; @@ -831,7 +849,7 @@ SDL_Surface* PLAT_resizeVideo(int w, int h, int p) { void PLAT_setSharpness(int sharpness) { if(sharpness==1) { finalScaleFilter=GL_LINEAR; - } + } else { finalScaleFilter = GL_NEAREST; } @@ -882,9 +900,9 @@ static void updateEffect(void) { int curr_type = effect.type; int curr_color = effect.color; pthread_mutex_unlock(&video_prep_mutex); - + if (next_scale==curr_scale && next_type==curr_type && next_color==curr_color) return; // unchanged - + // Update effect state with mutex protection pthread_mutex_lock(&video_prep_mutex); int live_scale = effect.scale; @@ -897,10 +915,10 @@ static void updateEffect(void) { int effect_color = effect.color; int live_type = effect.live_type; pthread_mutex_unlock(&video_prep_mutex); - + if (effect_type==EFFECT_NONE) return; // disabled if (effect_type==live_type && effect_scale==live_scale && effect_color==live_color) return; // already loaded - + int opacity = 128; // 1 - 1/2 = 50% if (effect_type==EFFECT_LINE) { if (effect_scale<3) { @@ -954,7 +972,7 @@ static void updateEffect(void) { } } effectUpdated = 1; - + } int screenx = 0; int screeny = 0; @@ -965,7 +983,7 @@ void PLAT_setOffsetX(int x) { } void PLAT_setOffsetY(int y) { if (y < 0 || y > 128) return; - screeny = y - 64; + screeny = y - 64; LOG_info("screeny: %i %i\n",screeny,y); } static int overlayUpdated=0; @@ -978,7 +996,7 @@ void PLAT_setOverlay(const char* filename, const char* tag) { free(overlay_path); overlay_path = NULL; } - + pthread_mutex_lock(&video_prep_mutex); overlayUpdated=1; pthread_mutex_unlock(&video_prep_mutex); @@ -1011,7 +1029,7 @@ void applyRoundedCorners(SDL_Surface* surface, SDL_Rect* rect, int radius) { SDL_Rect target = {0, 0, surface->w, surface->h}; if (rect) target = *rect; - + Uint32 transparent_black = SDL_MapRGBA(fmt, 0, 0, 0, 0); // Fully transparent black const int xBeg = target.x; @@ -1032,9 +1050,12 @@ void applyRoundedCorners(SDL_Surface* surface, SDL_Rect* rect, int radius) { void PLAT_clearLayers(int layer) { if(layer==0 || layer==1) { + uint32_t bg = vid.clear_color; SDL_SetRenderTarget(vid.renderer, vid.target_layer1); + SDL_SetRenderDrawColor(vid.renderer, (bg >> 16) & 0xFF, (bg >> 8) & 0xFF, bg & 0xFF, 255); SDL_RenderClear(vid.renderer); } + SDL_SetRenderDrawColor(vid.renderer, 0, 0, 0, 0); if(layer==0 || layer==2) { SDL_SetRenderTarget(vid.renderer, vid.target_layer2); SDL_RenderClear(vid.renderer); @@ -1056,12 +1077,12 @@ void PLAT_clearLayers(int layer) { } void PLAT_drawOnLayer(SDL_Surface *inputSurface, int x, int y, int w, int h, float brightness, bool maintainAspectRatio,int layer) { - if (!inputSurface || !vid.target_layer1 || !vid.renderer) return; + if (!inputSurface || !vid.target_layer1 || !vid.renderer) return; SDL_Texture* tempTexture = SDL_CreateTexture(vid.renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_TARGET, - inputSurface->w, inputSurface->h); + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_TARGET, + inputSurface->w, inputSurface->h); if (!tempTexture) { LOG_error("Failed to create temporary texture: %s\n", SDL_GetError()); @@ -1102,12 +1123,12 @@ void PLAT_drawOnLayer(SDL_Surface *inputSurface, int x, int y, int w, int h, flo SDL_SetTextureColorMod(tempTexture, r, g, b); // Aspect ratio handling - SDL_Rect srcRect = { 0, 0, inputSurface->w, inputSurface->h }; - SDL_Rect dstRect = { x, y, w, h }; + SDL_Rect srcRect = { 0, 0, inputSurface->w, inputSurface->h }; + SDL_Rect dstRect = { x, y, w, h }; if (maintainAspectRatio) { float aspectRatio = (float)inputSurface->w / (float)inputSurface->h; - + if (w / (float)h > aspectRatio) { dstRect.w = (int)(h * aspectRatio); } else { @@ -1169,7 +1190,7 @@ void PLAT_animateSurface( else SDL_SetRenderTarget(vid.renderer, vid.target_layer4); - SDL_SetRenderDrawColor(vid.renderer, 0, 0, 0, 0); + SDL_SetRenderDrawColor(vid.renderer, 0, 0, 0, 0); SDL_RenderClear(vid.renderer); SDL_Rect srcRect = { 0, 0, inputSurface->w, inputSurface->h }; @@ -1188,7 +1209,7 @@ int PLAT_textShouldScroll(TTF_Font* font, const char* in_name,int max_width, SDL if (fontMutex) SDL_LockMutex(fontMutex); TTF_SizeUTF8(font, in_name, &text_width, NULL); if (fontMutex) SDL_UnlockMutex(fontMutex); - + if (text_width <= max_width) { return 0; } else { @@ -1304,7 +1325,7 @@ void PLAT_animateSurfaceOpacity( } SDL_UpdateTexture(tempTexture, NULL, inputSurface->pixels, inputSurface->pitch); - SDL_SetTextureBlendMode(tempTexture, SDL_BLENDMODE_BLEND); + SDL_SetTextureBlendMode(tempTexture, SDL_BLENDMODE_BLEND); const int fps = 60; const int frame_delay = 1000 / fps; @@ -1560,12 +1581,12 @@ void PLAT_flipHidden() { void PLAT_flip(SDL_Surface* IGNORED, int ignored) { // dont think we need this here tbh - // SDL_RenderClear(vid.renderer); + // SDL_RenderClear(vid.renderer); if (!vid.blit) { resizeVideo(device_width, device_height, FIXED_PITCH); // !!!??? SDL_UpdateTexture(vid.stream_layer1, NULL, vid.screen->pixels, vid.screen->pitch); SDL_RenderCopy(vid.renderer, vid.target_layer1, NULL, NULL); - SDL_RenderCopy(vid.renderer, vid.target_layer2, NULL, NULL); + SDL_RenderCopy(vid.renderer, vid.target_layer2, NULL, NULL); SDL_RenderCopy(vid.renderer, vid.stream_layer1, NULL, NULL); SDL_RenderCopy(vid.renderer, vid.target_layer3, NULL, NULL); SDL_RenderCopy(vid.renderer, vid.target_layer4, NULL, NULL); @@ -1573,7 +1594,7 @@ void PLAT_flip(SDL_Surface* IGNORED, int ignored) { SDL_RenderPresent(vid.renderer); return; } - + // Safety check: ensure texture dimensions match blit buffer dimensions if (vid.width != vid.blit->true_w || vid.height != vid.blit->true_h) { // Texture size doesn't match buffer, clear blit and use screen buffer instead @@ -1589,7 +1610,7 @@ void PLAT_flip(SDL_Surface* IGNORED, int ignored) { SDL_RenderPresent(vid.renderer); return; } - + SDL_UpdateTexture(vid.stream_layer1, NULL, vid.blit->src, vid.blit->src_p); SDL_Texture* target = vid.stream_layer1; @@ -1598,7 +1619,7 @@ void PLAT_flip(SDL_Surface* IGNORED, int ignored) { int w = vid.blit->src_w; int h = vid.blit->src_h; if (vid.sharpness == SHARPNESS_CRISP) { - + SDL_SetRenderTarget(vid.renderer, vid.target); SDL_RenderCopy(vid.renderer, vid.stream_layer1, NULL, NULL); SDL_SetRenderTarget(vid.renderer, NULL); @@ -1613,7 +1634,7 @@ void PLAT_flip(SDL_Surface* IGNORED, int ignored) { SDL_Rect* dst_rect = &(SDL_Rect){0, 0, device_width, device_height}; setRectToAspectRatio(dst_rect); - + SDL_RenderCopy(vid.renderer, target, src_rect, dst_rect); SDL_RenderPresent(vid.renderer); @@ -1702,9 +1723,9 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex if (shader->u_FrameDirection >= 0) glUniform1i(shader->u_FrameDirection, 1); if (shader->u_FrameCount >= 0) glUniform1i(shader->u_FrameCount, frame_count); if (shader->u_OutputSize >= 0) glUniform2f(shader->u_OutputSize, dst_width, dst_height); - if (shader->u_TextureSize >= 0) glUniform2f(shader->u_TextureSize, shader->texw, shader->texh); - if (shader->OrigInputSize >= 0) glUniform2f(shader->OrigInputSize, shader->srcw, shader->srch); - if (shader->u_InputSize >= 0) glUniform2f(shader->u_InputSize, shader->srcw, shader->srch); + if (shader->u_TextureSize >= 0) glUniform2f(shader->u_TextureSize, shader->texw, shader->texh); + if (shader->OrigInputSize >= 0) glUniform2f(shader->OrigInputSize, shader->srcw, shader->srch); + if (shader->u_InputSize >= 0) glUniform2f(shader->u_InputSize, shader->srcw, shader->srch); for (int i = 0; i < shader->num_pragmas; ++i) { glUniform1f(shader->pragmas[i].uniformLocation, shader->pragmas[i].value); } @@ -1726,14 +1747,14 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex *target_texture = 0; shader->updated = 1; } - if (*target_texture==0 || shader->updated || reloadShaderTextures) { - + if (*target_texture==0 || shader->updated || reloadShaderTextures) { + // if(target_texture) { // glDeleteTextures(1,target_texture); // } if(*target_texture==0) glGenTextures(1, target_texture); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, *target_texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); @@ -1745,7 +1766,7 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex if (fbo == 0) { glGenFramebuffers(1, &fbo); } - + // Always bind before attaching to avoid stale state after swaps glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -1761,7 +1782,7 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex if (status != GL_FRAMEBUFFER_COMPLETE) { LOG_error("Framebuffer incomplete: 0x%X\n", status); } - + } else { glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -1780,9 +1801,9 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex } glViewport(x, y, dst_width, dst_height); - - if (shader->texLocation >= 0) glUniform1i(shader->texLocation, 0); - + + if (shader->texLocation >= 0) glUniform1i(shader->texLocation, 0); + if (shader->texelSizeLocation >= 0) { glUniform2fv(shader->texelSizeLocation, 1, texelSize); last_texelSize[0] = texelSize[0]; @@ -1809,7 +1830,7 @@ int prepareFrameThread(void *data) { pthread_mutex_lock(&video_prep_mutex); int effect_updated = effectUpdated; pthread_mutex_unlock(&video_prep_mutex); - + if (effect_updated) { LOG_info("effect updated %s\n",effect_path); if(effect_path) { @@ -1819,7 +1840,7 @@ int prepareFrameThread(void *data) { converted = SDL_ConvertSurfaceFormat(tmp, SDL_PIXELFORMAT_RGBA32, 0); SDL_FreeSurface(tmp); } - + pthread_mutex_lock(&video_prep_mutex); frame_prep.loaded_effect = converted; effectUpdated = 0; @@ -1833,13 +1854,13 @@ int prepareFrameThread(void *data) { pthread_mutex_unlock(&video_prep_mutex); } } - + // Check if effect is disabled pthread_mutex_lock(&video_prep_mutex); int effect_type = effect.type; SDL_Surface* loaded_effect = frame_prep.loaded_effect; pthread_mutex_unlock(&video_prep_mutex); - + if(effect_type == EFFECT_NONE && loaded_effect != 0) { pthread_mutex_lock(&video_prep_mutex); frame_prep.loaded_effect = 0; @@ -1851,7 +1872,7 @@ int prepareFrameThread(void *data) { pthread_mutex_lock(&video_prep_mutex); int overlay_updated = overlayUpdated; pthread_mutex_unlock(&video_prep_mutex); - + if (overlay_updated) { LOG_info("overlay updated\n"); @@ -1862,7 +1883,7 @@ int prepareFrameThread(void *data) { converted = SDL_ConvertSurfaceFormat(tmp, SDL_PIXELFORMAT_RGBA32, 0); SDL_FreeSurface(tmp); } - + pthread_mutex_lock(&video_prep_mutex); frame_prep.loaded_overlay = converted; frame_prep.overlay_ready = 1; @@ -1877,7 +1898,7 @@ int prepareFrameThread(void *data) { } } - SDL_Delay(120); + SDL_Delay(120); } return 0; } @@ -1894,7 +1915,7 @@ void PLAT_GL_Swap() { if (prepare_thread == NULL) { LOG_error("Error creating background thread: %s\n", SDL_GetError()); - return; + return; } } @@ -1928,9 +1949,9 @@ void PLAT_GL_Swap() { if (src_texture) { glDeleteTextures(1, &src_texture); src_texture = 0; } src_w_last = src_h_last = 0; last_w = last_h = 0; - if (effect_tex) { - glDeleteTextures(1, &effect_tex); - effect_tex = 0; + if (effect_tex) { + glDeleteTextures(1, &effect_tex); + effect_tex = 0; effect_w = effect_h = 0; // Force reload by marking as ready again if effect is active pthread_mutex_lock(&video_prep_mutex); @@ -1939,9 +1960,9 @@ void PLAT_GL_Swap() { } pthread_mutex_unlock(&video_prep_mutex); } - if (overlay_tex) { - glDeleteTextures(1, &overlay_tex); - overlay_tex = 0; + if (overlay_tex) { + glDeleteTextures(1, &overlay_tex); + overlay_tex = 0; overlay_w = overlay_h = 0; // Force reload if we had an overlay pthread_mutex_lock(&video_prep_mutex); @@ -1958,7 +1979,7 @@ void PLAT_GL_Swap() { int effect_ready = frame_prep.effect_ready; SDL_Surface* loaded_effect = frame_prep.loaded_effect; pthread_mutex_unlock(&video_prep_mutex); - + if (effect_ready) { if(loaded_effect) { if(!effect_tex) glGenTextures(1, &effect_tex); @@ -1986,7 +2007,7 @@ void PLAT_GL_Swap() { int overlay_ready = frame_prep.overlay_ready; SDL_Surface* loaded_overlay = frame_prep.loaded_overlay; pthread_mutex_unlock(&video_prep_mutex); - + if (overlay_ready) { if(loaded_overlay) { if(!overlay_tex) glGenTextures(1, &overlay_tex); @@ -1998,7 +2019,7 @@ void PLAT_GL_Swap() { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, loaded_overlay->w, loaded_overlay->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, loaded_overlay->pixels); overlay_w = loaded_overlay->w; overlay_h = loaded_overlay->h; - + } else { if (overlay_tex) { glDeleteTextures(1, &overlay_tex); @@ -2116,9 +2137,9 @@ void PLAT_GL_Swap() { } else { //LOG_info("Shader Pass: Scale to screen (pipeline size: %d)\n", nrofshaders); - runShaderPass(src_texture, - g_shader_default, - NULL, + runShaderPass(src_texture, + g_shader_default, + NULL, dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h, &(Shader){.srcw = vid.blit->src_w, .srch = vid.blit->src_h, .texw = vid.blit->src_w, .texh = vid.blit->src_h}, 0, GL_NONE); @@ -2154,7 +2175,7 @@ void PLAT_GL_Swap() { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, notif.surface->w, notif.surface->h, GL_RGBA, GL_UNSIGNED_BYTE, notif.surface->pixels); notif.dirty = 0; } - + if (notif.tex && notif.surface) { runShaderPass( notif.tex, @@ -2215,7 +2236,7 @@ unsigned char* PLAT_GL_screenCapture(int* outWidth, int* outHeight) { glViewport(0, 0, device_width, device_height); GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); - + int width = viewport[2]; int height = viewport[3]; diff --git a/workspace/all/ledcontrol/ledcontrol.c b/workspace/all/ledcontrol/ledcontrol.c index 98759a6ce..b8344ba98 100644 --- a/workspace/all/ledcontrol/ledcontrol.c +++ b/workspace/all/ledcontrol/ledcontrol.c @@ -227,7 +227,7 @@ int main(int argc, char *argv[]) memcpy(lightnames, default_names, sizeof(default_names)); // Copy values } - SDL_Surface* screen = GFX_init(MODE_MENU); + SDL_Surface* screen = GFX_init(MODE_MAIN); PAD_init(); PWR_init(); diff --git a/workspace/all/nextui/nextui.c b/workspace/all/nextui/nextui.c index c2d921059..4b943b835 100644 --- a/workspace/all/nextui/nextui.c +++ b/workspace/all/nextui/nextui.c @@ -69,7 +69,7 @@ static void Array_reverse(Array* self) { } } static void Array_free(Array* self) { - free(self->items); + free(self->items); free(self); } static void Array_yoink(Array* self, Array* other) { @@ -228,7 +228,7 @@ static void getUniqueName(Entry* entry, char* out_name) { char* filename = strrchr(entry->path, '/')+1; char emu_tag[256]; getEmuName(entry->path, emu_tag); - + char *tmp; strcpy(out_name, entry->name); tmp = out_name + strlen(out_name); @@ -242,7 +242,7 @@ static void getUniqueName(Entry* entry, char* out_name) { static void Directory_index(Directory* self) { int is_collection = prefixMatch(COLLECTIONS_PATH, self->path); int skip_index = exactMatch(FAUX_RECENT_PATH, self->path) || is_collection; // not alphabetized - + Hash* map = NULL; char map_path[256]; sprintf(map_path, "%s/map.txt", is_collection ? COLLECTIONS_PATH : self->path); @@ -266,7 +266,7 @@ static void Directory_index(Directory* self) { } } fclose(file); - + int resort = 0; int filter = 0; for (int i = 0; i < self->entries->count; i++) { @@ -280,7 +280,7 @@ static void Directory_index(Directory* self) { if (!filter && hide(entry->name)) filter = 1; } } - + if (filter) { Array* entries = Array_new(); for (int i = 0; i < self->entries->count; i++) { @@ -297,7 +297,7 @@ static void Directory_index(Directory* self) { if (resort) EntryArray_sort(self->entries); } } - + Entry* prior = NULL; int alpha = -1; int index = 0; @@ -311,7 +311,7 @@ static void Directory_index(Directory* self) { entry->name = strdup(alias); } } - + if (prior != NULL && exactMatch(prior->name, entry->name)) { free(prior->unique); free(entry->unique); @@ -343,7 +343,7 @@ static void Directory_index(Directory* self) { } entry->alpha = index; } - + prior = entry; } @@ -360,7 +360,7 @@ static Array* getEntries(char* path); static Directory* Directory_new(char* path, int selected) { char display_name[256]; getDisplayName(path, display_name); - + Directory* self = malloc(sizeof(Directory)); self->path = strdup(path); self->name = strdup(display_name); @@ -424,7 +424,7 @@ static Recent* Recent_new(char* path, char* alias) { char emu_name[256]; getEmuName(sd_path, emu_name); - + self->path = strdup(path); self->alias = alias ? strdup(alias) : NULL; self->available = hasEmu(emu_name); @@ -521,12 +521,12 @@ static Entry* entryFromPakName(char* pak_name) // Check in Emus sprintf(pak_path, "%s/Emus/%s.pak", PAKS_PATH, pak_name); - if(exists(pak_path)) + if(exists(pak_path)) return Entry_newNamed(pak_path, ENTRY_PAK, pak_name); // Check in platform Emus sprintf(pak_path, "%s/Emus/%s/%s.pak", SDCARD_PATH, PLATFORM, pak_name); - if(exists(pak_path)) + if(exists(pak_path)) return Entry_newNamed(pak_path, ENTRY_PAK, pak_name); return NULL; @@ -547,31 +547,31 @@ static int hasCue(char* dir_path, char* cue_path) { // NOTE: dir_path not rom_pa } static int hasM3u(char* rom_path, char* m3u_path) { // NOTE: rom_path not dir_path char* tmp; - + strcpy(m3u_path, rom_path); tmp = strrchr(m3u_path, '/') + 1; tmp[0] = '\0'; - + // path to parent directory char base_path[256]; strcpy(base_path, m3u_path); - + tmp = strrchr(m3u_path, '/'); tmp[0] = '\0'; - + // get parent directory name char dir_name[256]; tmp = strrchr(m3u_path, '/'); strcpy(dir_name, tmp); - + // dir_name is also our m3u file name - tmp = m3u_path + strlen(m3u_path); + tmp = m3u_path + strlen(m3u_path); strcpy(tmp, dir_name); // add extension tmp = m3u_path + strlen(m3u_path); strcpy(tmp, ".m3u"); - + return exists(m3u_path); } @@ -590,7 +590,7 @@ static int hasRecents(void) { Recent* recent = Recent_new(disc_path, NULL); if (recent->available) has += 1; Array_push(recents, recent); - + char parent_path[256]; strcpy(parent_path, disc_path); char* tmp = strrchr(parent_path, '/') + 1; @@ -607,9 +607,9 @@ static int hasRecents(void) { normalizeNewline(line); trimTrailingNewlines(line); if (strlen(line)==0) continue; // skip empty lines - + // LOG_info("line: %s\n", line); - + char* path = line; char* alias = NULL; char* tmp = strchr(line,'\t'); @@ -617,7 +617,7 @@ static int hasRecents(void) { tmp[0] = '\0'; alias = tmp+1; } - + char sd_path[256]; sprintf(sd_path, "%s%s", SDCARD_PATH, path); if (exists(sd_path)) { @@ -629,7 +629,7 @@ static int hasRecents(void) { strcpy(parent_path, path); char* tmp = strrchr(parent_path, '/') + 1; tmp[0] = '\0'; - + int found = 0; for (int i=0; icount; i++) { char* path = parent_paths->items[i]; @@ -639,12 +639,12 @@ static int hasRecents(void) { } } if (found) continue; - + Array_push(parent_paths, strdup(parent_path)); } - + // LOG_info("path:%s alias:%s\n", path, alias); - + Recent* recent = Recent_new(path, alias); if (recent->available) has += 1; Array_push(recents, recent); @@ -653,16 +653,16 @@ static int hasRecents(void) { } fclose(file); } - + saveRecents(); - + StringArray_free(parent_paths); return has>0; } static int hasCollections(void) { int has = 0; if (!exists(COLLECTIONS_PATH)) return has; - + DIR *dh = opendir(COLLECTIONS_PATH); struct dirent *dp; while((dp = readdir(dh)) != NULL) { @@ -679,10 +679,10 @@ static int hasRoms(char* dir_name) { char rom_path[256]; getEmuName(dir_name, emu_name); - + // check for emu pak if (!hasEmu(emu_name)) return has; - + // check for at least one non-hidden file (we're going to assume it's a rom) sprintf(rom_path, "%s/%s/", ROMS_PATH, dir_name); DIR *dh = opendir(rom_path); @@ -833,7 +833,7 @@ static Array* getQuickToggles(void) { Entry *settings = entryFromPakName("Settings"); if (settings) Array_push(entries, settings); - + Entry *store = entryFromPakName("Pak Store"); if (store) Array_push(entries, store); @@ -854,7 +854,7 @@ static Array* getQuickToggles(void) { static Array* getRoot(void) { Array* root = Array_new(); - if (hasRecents() && CFG_getShowRecents()) + if (hasRecents() && CFG_getShowRecents()) Array_push(root, Entry_new(FAUX_RECENT_PATH, ENTRY_DIR)); Array *entries = getRoms(); @@ -886,7 +886,7 @@ static Entry* entryFromRecent(Recent* recent) { if(!recent || !recent->available) return NULL; - + char sd_path[256]; sprintf(sd_path, "%s%s", SDCARD_PATH, recent->path); int type = suffixMatch(".pak", sd_path) ? ENTRY_PAK : ENTRY_ROM; // ??? @@ -918,13 +918,13 @@ static Array* getCollection(char* path) { normalizeNewline(line); trimTrailingNewlines(line); if (strlen(line)==0) continue; // skip empty lines - + char sd_path[256]; sprintf(sd_path, "%s%s", SDCARD_PATH, line); if (exists(sd_path)) { int type = suffixMatch(".pak", sd_path) ? ENTRY_PAK : ENTRY_ROM; // ??? Array_push(entries, Entry_new(sd_path, type)); - + // char emu_name[256]; // getEmuName(sd_path, emu_name); // if (hasEmu(emu_name)) { @@ -937,16 +937,16 @@ static Array* getCollection(char* path) { return entries; } static Array* getDiscs(char* path){ - + // TODO: does path have SDCARD_PATH prefix? - + Array* entries = Array_new(); - + char base_path[256]; strcpy(base_path, path); char* tmp = strrchr(base_path, '/') + 1; tmp[0] = '\0'; - + // TODO: limit number of discs supported (to 9?) FILE* file = fopen(path, "r"); if (file) { @@ -956,10 +956,10 @@ static Array* getDiscs(char* path){ normalizeNewline(line); trimTrailingNewlines(line); if (strlen(line)==0) continue; // skip empty lines - + char disc_path[256]; sprintf(disc_path, "%s%s", base_path, line); - + if (exists(disc_path)) { disc += 1; Entry* entry = Entry_new(disc_path, ENTRY_ROM); @@ -981,7 +981,7 @@ static int getFirstDisc(char* m3u_path, char* disc_path) { // based on getDiscs( strcpy(base_path, m3u_path); char* tmp = strrchr(base_path, '/') + 1; tmp[0] = '\0'; - + FILE* file = fopen(m3u_path, "r"); if (file) { char line[256]; @@ -989,9 +989,9 @@ static int getFirstDisc(char* m3u_path, char* disc_path) { // based on getDiscs( normalizeNewline(line); trimTrailingNewlines(line); if (strlen(line)==0) continue; // skip empty lines - + sprintf(disc_path, "%s%s", base_path, line); - + if (exists(disc_path)) found = 1; break; } @@ -1042,7 +1042,7 @@ static int isConsoleDir(char* path) { strcpy(parent_dir, path); tmp = strrchr(parent_dir, '/'); tmp[0] = '\0'; - + return exactMatch(parent_dir, ROMS_PATH); } @@ -1055,8 +1055,8 @@ static Array* getEntries(char* path){ char* tmp = strrchr(collated_path, '('); // 1 because we want to keep the opening parenthesis to avoid collating "Game Boy Color" and "Game Boy Advance" into "Game Boy" // but conditional so we can continue to support a bare tag name as a folder name - if (tmp) tmp[1] = '\0'; - + if (tmp) tmp[1] = '\0'; + DIR *dh = opendir(ROMS_PATH); if (dh!=NULL) { struct dirent *dp; @@ -1068,7 +1068,7 @@ static Array* getEntries(char* path){ if (hide(dp->d_name)) continue; if (dp->d_type!=DT_DIR) continue; strcpy(tmp, dp->d_name); - + if (!prefixMatch(collated_path, full_path)) continue; addEntries(entries, full_path); } @@ -1076,7 +1076,7 @@ static Array* getEntries(char* path){ } } else addEntries(entries, path); // just a subfolder - + EntryArray_sort(entries); return entries; } @@ -1132,9 +1132,9 @@ static void readyResumePath(char* rom_path, int type) { has_preview = 0; char path[256]; strcpy(path, rom_path); - + if (!prefixMatch(ROMS_PATH, path)) return; - + char auto_path[256]; if (type==ENTRY_DIR) { if (!hasCue(path, auto_path)) { // no cue? @@ -1144,7 +1144,7 @@ static void readyResumePath(char* rom_path, int type) { } strcpy(path, auto_path); // cue or m3u if one exists } - + if (!suffixMatch(".m3u", path)) { char m3u_path[256]; if (hasM3u(path, m3u_path)) { @@ -1152,14 +1152,14 @@ static void readyResumePath(char* rom_path, int type) { strcpy(path, m3u_path); } } - + char emu_name[256]; getEmuName(path, emu_name); - + char rom_file[256]; tmp = strrchr(path, '/') + 1; strcpy(rom_file, tmp); - + sprintf(slot_path, "%s/.minui/%s/%s.txt", SHARED_USERDATA_PATH, emu_name, rom_file); // /.userdata/.minui//.ext.txt can_resume = exists(slot_path); @@ -1183,32 +1183,32 @@ static int autoResume(void) { // NOTE: bypasses recents if (!exists(AUTO_RESUME_PATH)) return 0; - + char path[256]; getFile(AUTO_RESUME_PATH, path, 256); unlink(AUTO_RESUME_PATH); sync(); - + // make sure rom still exists char sd_path[256]; sprintf(sd_path, "%s%s", SDCARD_PATH, path); if (!exists(sd_path)) return 0; - + // make sure emu still exists char emu_name[256]; getEmuName(sd_path, emu_name); - + char emu_path[256]; getEmuPath(emu_name, emu_path); - + if (!exists(emu_path)) return 0; - + // putFile(LAST_PATH, FAUX_RECENT_PATH); // saveLast() will crash here because top is NULL char act[256]; sprintf(act, "gametimectl.elf start '%s'", escapeSingleQuotes(sd_path)); system(act); - + char cmd[256]; // dont escape sd_path again because it was already escaped for gametimectl and function modifies input str aswell sprintf(cmd, "'%s' '%s'", escapeSingleQuotes(emu_path), sd_path); @@ -1218,29 +1218,29 @@ static int autoResume(void) { } static void openPak(char* path) { - // NOTE: escapeSingleQuotes() modifies the passed string + // NOTE: escapeSingleQuotes() modifies the passed string // so we need to save the path before we call that // if (prefixMatch(ROMS_PATH, path)) { // addRecent(path); // } saveLast(path); - + char cmd[256]; sprintf(cmd, "'%s/launch.sh'", escapeSingleQuotes(path)); queueNext(cmd); } static void openRom(char* path, char* last) { LOG_info("openRom(%s,%s)\n", path, last); - + char sd_path[256]; strcpy(sd_path, path); - + char m3u_path[256]; int has_m3u = hasM3u(sd_path, m3u_path); - + char recent_path[256]; strcpy(recent_path, has_m3u ? m3u_path : sd_path); - + if (has_m3u && suffixMatch(".m3u", sd_path)) { getFirstDisc(m3u_path, sd_path); } @@ -1257,7 +1257,7 @@ static void openRom(char* path, char* last) { if (has_m3u) { char rom_file[256]; strcpy(rom_file, strrchr(m3u_path, '/') + 1); - + // get disc for state char disc_path_path[256]; sprintf(disc_path_path, "%s/.minui/%s/%s.%s.txt", SHARED_USERDATA_PATH, emu_name, rom_file, slot); // /.userdata/arm-480/.minui//.ext.0.txt @@ -1276,11 +1276,11 @@ static void openRom(char* path, char* last) { } } else putInt(RESUME_SLOT_PATH,8); // resume hidden default state - + char emu_path[256]; getEmuPath(emu_name, emu_path); - - // NOTE: escapeSingleQuotes() modifies the passed string + + // NOTE: escapeSingleQuotes() modifies the passed string // so we need to save the path before we call that addRecent(recent_path, recent_alias); // yiiikes saveLast(last==NULL ? sd_path : last); @@ -1447,7 +1447,7 @@ static void openDirectory(char* path, int auto_launch) { top = Directory_new(path, selected); top->start = start; top->end = end ? end : ((top->entries->countentries->count : MAIN_ROW_COUNT); - + Array_push(stack, top); } else { @@ -1507,10 +1507,10 @@ static void Entry_open(Entry* self) { if (prefixMatch(COLLECTIONS_PATH, top->path)) { char* tmp; char filename[256]; - + tmp = strrchr(self->path, '/'); if (tmp) strcpy(filename, tmp+1); - + char last_path[256]; sprintf(last_path, "%s/%s", top->path, filename); last = last_path; @@ -1546,23 +1546,23 @@ static void loadLast(void) { // call after loading root directory char last_path[256]; getFile(LAST_PATH, last_path, 256); - + char full_path[256]; strcpy(full_path, last_path); - + char* tmp; char filename[256]; tmp = strrchr(last_path, '/'); if (tmp) strcpy(filename, tmp); - + Array* last = Array_new(); while (!exactMatch(last_path, SDCARD_PATH)) { Array_push(last, strdup(last_path)); - + char* slash = strrchr(last_path, '/'); last_path[(slash-last_path)] = '\0'; } - + while (last->count>0) { char* path = Array_pop(last); if (!exactMatch(path, ROMS_PATH)) { // romsDir is effectively root as far as restoring state after a game @@ -1573,10 +1573,10 @@ static void loadLast(void) { // call after loading root directory tmp = strrchr(collated_path, '('); if (tmp) tmp[1] = '\0'; // 1 because we want to keep the opening parenthesis to avoid collating "Game Boy Color" and "Game Boy Advance" into "Game Boy" } - + for (int i=0; ientries->count; i++) { Entry* entry = top->entries->items[i]; - + // NOTE: strlen() is required for collated_path, '\0' wasn't reading as NULL for some reason if (exactMatch(entry->path, path) || (strlen(collated_path) && prefixMatch(collated_path, entry->path)) || (prefixMatch(COLLECTIONS_PATH, full_path) && suffixMatch(filename, entry->path))) { top->selected = i; @@ -1589,7 +1589,7 @@ static void loadLast(void) { // call after loading root directory } } if (last->count==0 && !exactMatch(entry->path, FAUX_RECENT_PATH) && !(!exactMatch(entry->path, COLLECTIONS_PATH) && prefixMatch(COLLECTIONS_PATH, entry->path))) break; // don't show contents of auto-launch dirs - + if (entry->type==ENTRY_DIR) { openDirectory(entry->path, 0); break; @@ -1599,7 +1599,7 @@ static void loadLast(void) { // call after loading root directory } free(path); // we took ownership when we popped it } - + StringArray_free(last); if (top->selected >= 0 && top->selected < top->entries->count) { @@ -1664,7 +1664,7 @@ typedef struct finishedTask { int targetY; int targetTextY; int move_y; - int move_w; + int move_w; int move_h; int frames; int done; @@ -1680,7 +1680,7 @@ typedef struct AnimTask { int startY; int targetY; int targetTextY; - int move_w; + int move_w; int move_h; int frames; AnimTaskCallback callback; @@ -1759,7 +1759,6 @@ static void updatePillTextSurface(const char* entry_name, int move_w, SDL_Color 0, crop_rect.w, crop_rect.h, screen->format->BitsPerPixel, screen->format->format ); if (cropped) { - SDL_SetSurfaceBlendMode(converted, SDL_BLENDMODE_NONE); SDL_BlitSurface(converted, &crop_rect, cropped, NULL); } SDL_FreeSurface(converted); @@ -1809,7 +1808,7 @@ void enqueueBGTask(LoadBackgroundTask* task) { } else { taskBGQueueHead = taskBGQueueTail = node; } - + currentBGQueueSize++; SDL_CondSignal(bgqueueCond); SDL_UnlockMutex(bgqueueMutex); @@ -1843,7 +1842,7 @@ void enqueueThumbTask(LoadBackgroundTask* task) { } else { taskThumbQueueHead = taskThumbQueueTail = node; } - + currentThumbQueueSize++; SDL_CondSignal(thumbqueueCond); SDL_UnlockMutex(thumbqueueMutex); @@ -1973,17 +1972,17 @@ void onThumbLoaded(SDL_Surface* surface) { SDL_UnlockMutex(thumbMutex); return; } - - + + thumbbmp = surface; int img_w = thumbbmp->w; int img_h = thumbbmp->h; double aspect_ratio = (double)img_h / img_w; - int max_w = (int)(screen->w * CFG_getGameArtWidth()); - int max_h = (int)(screen->h * 0.6); + int max_w = (int)(screen->w * CFG_getGameArtWidth()); + int max_h = (int)(screen->h * 0.6); int new_w = max_w; - int new_h = (int)(new_w * aspect_ratio); - + int new_h = (int)(new_w * aspect_ratio); + if (new_h > max_h) { new_h = max_h; new_w = (int)(new_h / aspect_ratio); @@ -2003,7 +2002,7 @@ int pilltargetY =0; int pilltargetTextY =0; void animcallback(finishedTask *task) { SDL_LockMutex(animMutex); - pillRect = task->dst; + pillRect = task->dst; if(pillRect.w > 0 && pillRect.h > 0) { pilltargetY = +screen->w; // move offscreen if(task->done) { @@ -2021,21 +2020,21 @@ bool pillanimdone = false; int animWorker(void* unused) { while (!SDL_AtomicGet(&workerThreadsShutdown)) { SDL_LockMutex(animqueueMutex); - while (!animTaskQueueHead && !SDL_AtomicGet(&workerThreadsShutdown)) { - SDL_CondWait(animqueueCond, animqueueMutex); - } - if (SDL_AtomicGet(&workerThreadsShutdown)) { - SDL_UnlockMutex(animqueueMutex); - break; - } - AnimTaskNode* node = animTaskQueueHead; - animTaskQueueHead = node->next; - if (!animTaskQueueHead) animTtaskQueueTail = NULL; + while (!animTaskQueueHead && !SDL_AtomicGet(&workerThreadsShutdown)) { + SDL_CondWait(animqueueCond, animqueueMutex); + } + if (SDL_AtomicGet(&workerThreadsShutdown)) { + SDL_UnlockMutex(animqueueMutex); + break; + } + AnimTaskNode* node = animTaskQueueHead; + animTaskQueueHead = node->next; + if (!animTaskQueueHead) animTtaskQueueTail = NULL; SDL_UnlockMutex(animqueueMutex); - AnimTask* task = node->task; + AnimTask* task = node->task; finishedTask* finaltask = (finishedTask*)malloc(sizeof(finishedTask)); - int total_frames = task->frames; + int total_frames = task->frames; for (int frame = 0; frame <= total_frames; frame++) { // Check for shutdown at start of each frame if (SDL_AtomicGet(&workerThreadsShutdown)) break; @@ -2045,7 +2044,7 @@ int animWorker(void* unused) { int current_x = task->startX + (int)((task->targetX - task->startX) * t); int current_y = task->startY + (int)(( task->targetY - task->startY) * t); - + SDL_Rect moveDst = { current_x, current_y, task->move_w, task->move_h }; finaltask->dst = moveDst; finaltask->entry_name = task->entry_name; @@ -2063,13 +2062,13 @@ int animWorker(void* unused) { } frameReady = false; SDL_UnlockMutex(frameMutex); - + } SDL_LockMutex(animqueueMutex); if (!animTaskQueueHead) animTtaskQueueTail = NULL; currentAnimQueueSize--; // <-- add this SDL_UnlockMutex(animqueueMutex); - + SDL_LockMutex(animMutex); pillanimdone = true; free(finaltask); @@ -2081,7 +2080,7 @@ void enqueueanmimtask(AnimTask* task) { AnimTaskNode* node = (AnimTaskNode*)malloc(sizeof(AnimTaskNode)); node->task = task; node->next = NULL; - + SDL_LockMutex(animqueueMutex); pillanimdone = false; // If queue is full, drop the oldest task (head) @@ -2123,7 +2122,7 @@ void initImageLoaderPool() { SDL_AtomicSet(&workerThreadsShutdown, 0); SDL_AtomicSet(&animationDrawAtomic, 1); SDL_AtomicSet(&needDrawAtomic, 0); - + thumbqueueMutex = SDL_CreateMutex(); bgqueueMutex = SDL_CreateMutex(); bgqueueCond = SDL_CreateCond(); @@ -2145,13 +2144,13 @@ void initImageLoaderPool() { void cleanupImageLoaderPool() { // Signal all worker threads to exit (atomic set for thread safety) SDL_AtomicSet(&workerThreadsShutdown, 1); - + // Wake up all waiting threads if (bgqueueCond) SDL_CondSignal(bgqueueCond); if (thumbqueueCond) SDL_CondSignal(thumbqueueCond); if (animqueueCond) SDL_CondSignal(animqueueCond); if (flipCond) SDL_CondSignal(flipCond); // Wake up animWorker if stuck waiting for frame flip - + // Wait for all worker threads to finish if (bgLoadThread) { SDL_WaitThread(bgLoadThread, NULL); @@ -2165,10 +2164,10 @@ void cleanupImageLoaderPool() { SDL_WaitThread(animWorkerThread, NULL); animWorkerThread = NULL; } - + // Small delay to ensure llvmpipe/OpenGL threads have completed any pending operations SDL_Delay(10); - + // Acquire and release each mutex before destroying to ensure no thread is in a critical section // This creates a memory barrier and ensures proper synchronization if (bgqueueMutex) { SDL_LockMutex(bgqueueMutex); SDL_UnlockMutex(bgqueueMutex); } @@ -2179,7 +2178,7 @@ void cleanupImageLoaderPool() { if (animMutex) { SDL_LockMutex(animMutex); SDL_UnlockMutex(animMutex); } if (frameMutex) { SDL_LockMutex(frameMutex); SDL_UnlockMutex(frameMutex); } if (fontMutex) { SDL_LockMutex(fontMutex); SDL_UnlockMutex(fontMutex); } - + // Destroy mutexes and condition variables if (bgqueueMutex) SDL_DestroyMutex(bgqueueMutex); if (thumbqueueMutex) SDL_DestroyMutex(thumbqueueMutex); @@ -2189,12 +2188,12 @@ void cleanupImageLoaderPool() { if (animMutex) SDL_DestroyMutex(animMutex); if (frameMutex) SDL_DestroyMutex(frameMutex); if (fontMutex) SDL_DestroyMutex(fontMutex); - + if (bgqueueCond) SDL_DestroyCond(bgqueueCond); if (thumbqueueCond) SDL_DestroyCond(thumbqueueCond); if (animqueueCond) SDL_DestroyCond(animqueueCond); if (flipCond) SDL_DestroyCond(flipCond); - + // Set pointers to NULL after destruction bgqueueMutex = NULL; thumbqueueMutex = NULL; @@ -2215,24 +2214,24 @@ int main (int argc, char *argv[]) { // LOG_info("time from launch to:\n"); // unsigned long main_begin = SDL_GetTicks(); // unsigned long first_draw = 0; - + if (autoResume()) return 0; // nothing to do - + simple_mode = exists(SIMPLE_MODE_PATH); LOG_info("NextUI\n"); InitSettings(); - + screen = GFX_init(MODE_MAIN); - // LOG_info("- graphics init: %lu\n", SDL_GetTicks() - main_begin); - +// LOG_info("- graphics init: %lu\n", SDL_GetTicks() - main_begin); + PAD_init(); // LOG_info("- input init: %lu\n", SDL_GetTicks() - main_begin); VIB_init(); PWR_init(); if (!HAS_POWER_BUTTON && !simple_mode) PWR_disableSleep(); // LOG_info("- power init: %lu\n", SDL_GetTicks() - main_begin); - + // start my threaded image loader :D initImageLoaderPool(); Menu_init(); @@ -2258,7 +2257,7 @@ int main (int argc, char *argv[]) { // make sure we have no running games logged as active anymore (we might be launching back into the UI here) system("gametimectl.elf stop_all"); - + GFX_setVsync(VSYNC_STRICT); PAD_reset(); @@ -2297,16 +2296,16 @@ int main (int argc, char *argv[]) { while (!quit) { GFX_startFrame(); unsigned long now = SDL_GetTicks(); - + PAD_poll(); - + int selected = top->selected; int total = top->entries->count; - + PWR_update(&dirty, &show_setting, NULL, NULL); - + int is_online = PWR_isOnline(); - if (was_online!=is_online) + if (was_online!=is_online) dirty = 1; was_online = is_online; @@ -2466,7 +2465,7 @@ int main (int argc, char *argv[]) { } else if (PAD_tappedSelect(now)) { currentScreen = SCREEN_GAMESWITCHER; - switcher_selected = 0; + switcher_selected = 0; dirty = 1; } else if (total>0) { @@ -2480,7 +2479,7 @@ int main (int argc, char *argv[]) { selected = total-1; int start = total - MAIN_ROW_COUNT; top->start = (start<0) ? 0 : start; - top->end = total; + top->end = total; } else if (selectedstart) { top->start -= 1; @@ -2533,7 +2532,7 @@ int main (int argc, char *argv[]) { } } } - + if (PAD_justRepeated(BTN_L1) && !PAD_isPressed(BTN_R1) && !PWR_ignoreSettingInput(BTN_L1, show_setting)) { // previous alpha Entry* entry = top->entries->items[selected]; int i = entry->alpha-1; @@ -2560,21 +2559,21 @@ int main (int argc, char *argv[]) { } } } - + if (selected!=top->selected) { top->selected = selected; dirty = 1; } Entry* entry = top->entries->items[top->selected]; - - if (dirty && total>0) + + if (dirty && total>0) readyResume(entry); if (total>0 && can_resume && PAD_justReleased(BTN_RESUME)) { should_resume = 1; Entry_open(entry); - + dirty = 1; } else if (total>0 && PAD_justPressed(BTN_A)) { @@ -2592,11 +2591,11 @@ int main (int argc, char *argv[]) { animationdirection = SLIDE_RIGHT; total = top->entries->count; dirty = 1; - + if (total>0) readyResume(top->entries->items[top->selected]); } } - + if(dirty) { SDL_Surface *tmpOldScreen = NULL; SDL_Surface * switcherSur = NULL; @@ -2611,9 +2610,9 @@ int main (int argc, char *argv[]) { if(lastScreen==SCREEN_GAME || lastScreen==SCREEN_OFF) { GFX_clearLayers(LAYER_ALL); } - else { + else { GFX_clearLayers(LAYER_TRANSITION); - if(lastScreen!=SCREEN_GAMELIST) + if(lastScreen!=SCREEN_GAMELIST) GFX_clearLayers(LAYER_THUMBNAIL); GFX_clearLayers(LAYER_SCROLLTEXT); GFX_clearLayers(LAYER_IDK2); @@ -2630,11 +2629,12 @@ int main (int argc, char *argv[]) { Entry *current = qm_row == 0 ? quick->items[qm_col] : quickActions->items[qm_col]; char newBgPath[MAX_PATH]; char fallbackBgPath[MAX_PATH]; + sprintf(newBgPath, SDCARD_PATH "/.media/quick_%s%s.png", current->name, !strcmp(current->name,"Wifi") && !CFG_getWifi() || // wifi or wifi_off, based on state !strcmp(current->name,"Bluetooth") && !CFG_getBluetooth() ? "_off" : ""); // bluetooth or bluetooth_off, based on state sprintf(fallbackBgPath, SDCARD_PATH "/.media/quick.png"); - + // background if(!exists(newBgPath)) strncpy(newBgPath, fallbackBgPath, sizeof(newBgPath) - 1); @@ -2643,11 +2643,11 @@ int main (int argc, char *argv[]) { strncpy(folderBgPath, newBgPath, sizeof(folderBgPath) - 1); startLoadFolderBackground(newBgPath, onBackgroundLoaded, NULL); } - + // buttons (duped and trimmed from below) if (show_setting && !GetHDMI()) GFX_blitHardwareHints(screen, show_setting); else GFX_blitButtonGroup((char*[]){ BTN_SLEEP==BTN_POWER?"POWER":"MENU","SLEEP", NULL }, 0, screen, 0); - + GFX_blitButtonGroup((char*[]){ "B","BACK", "A","OPEN", NULL }, 1, screen, 1); if(CFG_getShowQuickswitcherUI()) { @@ -2669,7 +2669,7 @@ int main (int argc, char *argv[]) { int item_size = SCALE1(MENU_ITEM_SIZE); int item_extra_y = item_space_y - item_size; int item_space_x = screen->w - SCALE1(PADDING + MENU_MARGIN_X + MENU_MARGIN_X + PADDING); - // extra left margin for the first item in order to properly center all of them in the + // extra left margin for the first item in order to properly center all of them in the // available space int item_inset_x = (item_space_x - SCALE1(qm_slots * MENU_ITEM_SIZE + (qm_slots - 1) * MENU_ITEM_MARGIN)) / 2; @@ -2693,7 +2693,7 @@ int main (int argc, char *argv[]) { item_color = THEME_COLOR1; icon_color = THEME_COLOR5; } - + GFX_blitRectColor(ASSET_STATE_BG, screen, &item_rect, item_color); char icon_path[MAX_PATH]; @@ -2702,8 +2702,8 @@ int main (int argc, char *argv[]) { if(bmp) { SDL_Surface* converted = SDL_ConvertSurfaceFormat(bmp, screen->format->format, 0); if (converted) { - SDL_FreeSurface(bmp); - bmp = converted; + SDL_FreeSurface(bmp); + bmp = converted; } } if(bmp) { @@ -2766,9 +2766,9 @@ int main (int argc, char *argv[]) { int y = item_rect.y; x += (SCALE1(PILL_SIZE) - rect.w) / 2; y += (SCALE1(PILL_SIZE) - rect.h) / 2; - + GFX_blitAssetColor(asset, NULL, screen, &(SDL_Rect){x,y}, icon_color); - + ox += item_rect.w + SCALE1(MENU_TOGGLE_MARGIN); } } @@ -2786,7 +2786,7 @@ int main (int argc, char *argv[]) { GFX_clearLayers(LAYER_ALL); ox = 0; oy = 0; - + // For all recents with resumable state (i.e. has savegame), show game switcher carousel if(recents->count > 0) { Entry *selectedEntry = entryFromRecent(recents->items[switcher_selected]); @@ -2794,7 +2794,7 @@ int main (int argc, char *argv[]) { // title pill { int max_width = screen->w - SCALE1(PADDING * 2) - ow; - + char display_name[256]; int text_width = GFX_truncateText(font.large, selectedEntry->name, display_name, max_width, SCALE1(BUTTON_PADDING*2)); max_width = MIN(max_width, text_width); @@ -2830,22 +2830,22 @@ int main (int argc, char *argv[]) { if(has_preview) { // lotta memory churn here - + SDL_Surface* bmp = IMG_Load(preview_path); SDL_Surface* raw_preview = SDL_ConvertSurfaceFormat(bmp, screen->format->format, 0); if (raw_preview) { - SDL_FreeSurface(bmp); - bmp = raw_preview; + SDL_FreeSurface(bmp); + bmp = raw_preview; } if(bmp) { int aw = screen->w; int ah = screen->h; int ax = 0; int ay = 0; - + float aspectRatio = (float)bmp->w / (float)bmp->h; float screenRatio = (float)screen->w / (float)screen->h; - + if (screenRatio > aspectRatio) { aw = (int)(screen->h * aspectRatio); ah = screen->h; @@ -2855,13 +2855,13 @@ int main (int argc, char *argv[]) { } ax = (screen->w - aw) / 2; ay = (screen->h - ah) / 2; - + if(lastScreen == SCREEN_GAME) { // need to flip once so streaming_texture1 is updated GFX_flipHidden(); GFX_animateSurfaceOpacity(bmp,0,0,screen->w,screen->h,0,255,CFG_getMenuTransitions() ? 150:20,LAYER_ALL); - } else if(lastScreen == SCREEN_GAMELIST) { - + } else if(lastScreen == SCREEN_GAMELIST) { + GFX_drawOnLayer(blackBG,0,0,screen->w,screen->h,1.0f,0,LAYER_BACKGROUND); GFX_drawOnLayer(bmp,ax,ay,aw, ah,1.0f,0,LAYER_BACKGROUND); GFX_flipHidden(); @@ -2871,19 +2871,19 @@ int main (int argc, char *argv[]) { GFX_drawOnLayer(tmpOldScreen,0,0,screen->w, screen->h,1.0f,0,LAYER_ALL); GFX_animateSurface(tmpNewScreen,0,0-screen->h,0,0,screen->w,screen->h,CFG_getMenuTransitions() ? 100:20,255,255,LAYER_BACKGROUND); SDL_FreeSurface(tmpNewScreen); - + } else if(lastScreen == SCREEN_GAMESWITCHER) { GFX_flipHidden(); GFX_drawOnLayer(blackBG,0,0,screen->w, screen->h,1.0f,0,LAYER_BACKGROUND); - if(gsanimdir == SLIDE_LEFT) + if(gsanimdir == SLIDE_LEFT) GFX_animateSurface(bmp,ax+screen->w,ay,ax,ay,aw,ah,CFG_getMenuTransitions() ? 80:20,0,255,LAYER_ALL); else if(gsanimdir == SLIDE_RIGHT) GFX_animateSurface(bmp,ax-screen->w,ay,ax,ay,aw,ah,CFG_getMenuTransitions() ? 80:20,0,255,LAYER_ALL); - + GFX_drawOnLayer(bmp,ax,ay,aw,ah,1.0f,0,LAYER_BACKGROUND); } else if(lastScreen == SCREEN_QUICKMENU) { GFX_flipHidden(); - GFX_drawOnLayer(blackBG,0,0,screen->w, screen->h,1.0f,0,LAYER_BACKGROUND); + GFX_drawOnLayer(blackBG,0,0,screen->w, screen->h,1.0f,0,LAYER_BACKGROUND); GFX_drawOnLayer(bmp,ax,ay,aw,ah,1.0f,0,LAYER_BACKGROUND); } SDL_FreeSurface(bmp); // Free after rendering @@ -2892,14 +2892,14 @@ int main (int argc, char *argv[]) { else { SDL_Rect preview_rect = {ox,oy,screen->w,screen->h}; SDL_Surface * tmpsur = SDL_CreateRGBSurfaceWithFormat(0,screen->w,screen->h,screen->format->BitsPerPixel,screen->format->format); - SDL_FillRect(tmpsur, &preview_rect, SDL_MapRGBA(screen->format,0,0,0,255)); + SDL_FillRect(tmpsur, &preview_rect, CFG_getColor(COLOR_BACKGROUND)); if(lastScreen == SCREEN_GAME) { GFX_animateSurfaceOpacity(tmpsur,0,0,screen->w,screen->h,255,0,CFG_getMenuTransitions() ? 150:20,LAYER_BACKGROUND); - } else if(lastScreen == SCREEN_GAMELIST) { + } else if(lastScreen == SCREEN_GAMELIST) { GFX_animateSurface(tmpsur,0,0-screen->h,0,0,screen->w,screen->h,CFG_getMenuTransitions() ? 100:20,255,255,LAYER_ALL); } else if(lastScreen == SCREEN_GAMESWITCHER) { GFX_flipHidden(); - if(gsanimdir == SLIDE_LEFT) + if(gsanimdir == SLIDE_LEFT) GFX_animateSurface(tmpsur,0+screen->w,0,0,0,screen->w,screen->h,CFG_getMenuTransitions() ? 80:20,0,255,LAYER_ALL); else if(gsanimdir == SLIDE_RIGHT) GFX_animateSurface(tmpsur,0-screen->w,0,0,0,screen->w,screen->h,CFG_getMenuTransitions() ? 80:20,0,255,LAYER_ALL); @@ -2915,7 +2915,7 @@ int main (int argc, char *argv[]) { GFX_blitMessage(font.large, "No Recents", screen, &preview_rect); GFX_blitButtonGroup((char*[]){ "B","BACK", NULL }, 1, screen, 1); } - + GFX_flipHidden(); if(switcherSur) SDL_FreeSurface(switcherSur); @@ -2929,22 +2929,22 @@ int main (int argc, char *argv[]) { char tmp_path[MAX_PATH]; strncpy(tmp_path, entry->path, sizeof(tmp_path) - 1); tmp_path[sizeof(tmp_path) - 1] = '\0'; - + char* res_name = strrchr(tmp_path, '/'); if (res_name) res_name++; char path_copy[1024]; strncpy(path_copy, entry->path, sizeof(path_copy) - 1); path_copy[sizeof(path_copy) - 1] = '\0'; - + char* rompath = dirname(path_copy); - + char res_copy[1024]; strncpy(res_copy, res_name, sizeof(res_copy) - 1); res_copy[sizeof(res_copy) - 1] = '\0'; - + char* dot = strrchr(res_copy, '.'); - if (dot) *dot = '\0'; + if (dot) *dot = '\0'; static int lastType = -1; @@ -2972,7 +2972,7 @@ int main (int argc, char *argv[]) { } startLoadFolderBackground(tmppath, onBackgroundLoaded, NULL); } - } + } else if(strcmp(defaultBgPath, folderBgPath) != 0 && exists(defaultBgPath)) { strncpy(folderBgPath, defaultBgPath, sizeof(folderBgPath) - 1); startLoadFolderBackground(defaultBgPath, onBackgroundLoaded, NULL); @@ -2988,10 +2988,10 @@ int main (int argc, char *argv[]) { snprintf(thumbpath, sizeof(thumbpath), "%s/.media/%s.png", rompath, res_copy); had_thumb = 0; startLoadThumb(thumbpath, onThumbLoaded, NULL); - int max_w = (int)(screen->w - (screen->w * CFG_getGameArtWidth())); - int max_h = (int)(screen->h * 0.6); + int max_w = (int)(screen->w - (screen->w * CFG_getGameArtWidth())); + int max_h = (int)(screen->h * 0.6); int new_w = max_w; - int new_h = max_h; + int new_h = max_h; if(exists(thumbpath)) { ox = (int)(max_w) - SCALE1(BUTTON_MARGIN*5); had_thumb = 1; @@ -3004,11 +3004,11 @@ int main (int argc, char *argv[]) { // buttons if (show_setting && !GetHDMI()) GFX_blitHardwareHints(screen, show_setting); else if (can_resume) GFX_blitButtonGroup((char*[]){ "X","RESUME", NULL }, 0, screen, 0); - else GFX_blitButtonGroup((char*[]){ + else GFX_blitButtonGroup((char*[]){ BTN_SLEEP==BTN_POWER?"POWER":"MENU", - BTN_SLEEP==BTN_POWER||simple_mode?"SLEEP":"INFO", + BTN_SLEEP==BTN_POWER||simple_mode?"SLEEP":"INFO", NULL }, 0, screen, 0); - + if (total==0) { if (stack->count>1) { GFX_blitButtonGroup((char*[]){ "B","BACK", NULL }, 0, screen, 1); @@ -3037,13 +3037,13 @@ int main (int argc, char *argv[]) { bool row_is_selected = (j == selected_row); bool row_is_top = (i == top->start); bool row_has_moved = (previous_row != selected_row || previous_depth != stack->count); - if (row_is_top && !(had_thumb)) + if (row_is_top && !(had_thumb)) available_width -= ow; trimSortingMeta(&entry_name); if (entry_unique) // Only render if a unique name exists trimSortingMeta(&entry_unique); - + char display_name[256]; int text_width = GFX_getTextWidth(font.large, entry_unique ? entry_unique : entry_name, display_name, available_width, SCALE1(BUTTON_PADDING * 2)); int max_width = MIN(available_width, text_width); @@ -3056,7 +3056,7 @@ int main (int argc, char *argv[]) { text_color = uintToColour(THEME_COLOR5_255); notext = 1; } - + SDL_LockMutex(fontMutex); SDL_Surface* text = TTF_RenderUTF8_Blended(font.large, entry_name, text_color); SDL_Surface* text_unique = TTF_RenderUTF8_Blended(font.large, display_name, COLOR_DARK_TEXT); @@ -3068,9 +3068,9 @@ int main (int argc, char *argv[]) { GFX_resetScrollText(); bool should_animate = previous_depth == stack->count; SDL_LockMutex(animMutex); - if(globalpill) { - SDL_FreeSurface(globalpill); - globalpill=NULL; + if(globalpill) { + SDL_FreeSurface(globalpill); + globalpill=NULL; } globalpill = SDL_CreateRGBSurfaceWithFormat(SDL_SWSURFACE, max_width, SCALE1(PILL_SIZE), FIXED_DEPTH, screen->format->format); GFX_blitPillDark(ASSET_WHITE_PILL, globalpill, &(SDL_Rect){0,0, max_width, SCALE1(PILL_SIZE)}); @@ -3083,7 +3083,7 @@ int main (int argc, char *argv[]) { task->targetX = SCALE1(BUTTON_MARGIN); task->targetY = SCALE1(targetY+PADDING); task->targetTextY = SCALE1(PADDING + targetY) + text_offset_y; - pilltargetTextY = +screen->w; + pilltargetTextY = task->targetTextY; task->move_w = max_width; task->move_h = SCALE1(PILL_SIZE); task->frames = should_animate && CFG_getMenuAnimations() ? 3:1; @@ -3105,7 +3105,7 @@ int main (int argc, char *argv[]) { // update cpu surface here first GFX_clearLayers(LAYER_ALL); folderbgchanged=1; - + GFX_flipHidden(); GFX_animateSurface(switcherSur,0,0,0,0-screen->h,screen->w,screen->h,CFG_getMenuTransitions() ? 100:20,255,255,LAYER_BACKGROUND); animationdirection = ANIM_NONE; @@ -3114,7 +3114,7 @@ int main (int argc, char *argv[]) { if(lastScreen==SCREEN_OFF) { GFX_animateSurfaceOpacity(blackBG,0,0,screen->w,screen->h,255,0,CFG_getMenuTransitions() ? 200:20,LAYER_THUMBNAIL); } - + previous_row = selected_row; previous_depth = stack->count; } @@ -3122,13 +3122,19 @@ int main (int argc, char *argv[]) { // TODO: for some reason screen's dimensions end up being 0x0 in GFX_blitMessage... GFX_blitMessage(font.large, "Empty folder", screen, &(SDL_Rect){0,0,screen->w,screen->h}); //, NULL); } - + lastScreen = SCREEN_GAMELIST; } if(animationdirection != ANIM_NONE) { if(CFG_getMenuTransitions()) { - GFX_clearLayers(LAYER_BACKGROUND); + SDL_LockMutex(bgMutex); + if(folderbgbmp) { + GFX_drawOnLayer(folderbgbmp, 0, 0, screen->w, screen->h, 1.0f, 0, LAYER_BACKGROUND); + } else { + GFX_clearLayers(LAYER_BACKGROUND); + } + SDL_UnlockMutex(bgMutex); folderbgchanged = 1; GFX_clearLayers(LAYER_TRANSITION); GFX_flipHidden(); @@ -3149,8 +3155,9 @@ int main (int argc, char *argv[]) { if(folderbgchanged) { if(folderbgbmp) GFX_drawOnLayer(folderbgbmp,0, 0, screen->w, screen->h,1.0f,0,LAYER_BACKGROUND); - else + else { GFX_clearLayers(LAYER_BACKGROUND); + } folderbgchanged = 0; } SDL_UnlockMutex(bgMutex); @@ -3160,8 +3167,9 @@ int main (int argc, char *argv[]) { if(folderbgchanged) { if(folderbgbmp) GFX_drawOnLayer(folderbgbmp,0, 0, screen->w, screen->h,1.0f,0,LAYER_BACKGROUND); - else + else { GFX_clearLayers(LAYER_BACKGROUND); + } folderbgchanged = 0; } SDL_UnlockMutex(bgMutex); @@ -3170,11 +3178,11 @@ int main (int argc, char *argv[]) { int img_w = thumbbmp->w; int img_h = thumbbmp->h; double aspect_ratio = (double)img_h / img_w; - int max_w = (int)(screen->w * CFG_getGameArtWidth()); - int max_h = (int)(screen->h * 0.6); + int max_w = (int)(screen->w * CFG_getGameArtWidth()); + int max_h = (int)(screen->h * 0.6); int new_w = max_w; - int new_h = (int)(new_w * aspect_ratio); - + int new_h = (int)(new_w * aspect_ratio); + if (new_h > max_h) { new_h = max_h; new_w = (int)(new_h / aspect_ratio); @@ -3192,11 +3200,11 @@ int main (int argc, char *argv[]) { GFX_clearLayers(LAYER_TRANSITION); GFX_clearLayers(LAYER_SCROLLTEXT); - + SDL_LockMutex(animMutex); if (list_show_entry_names) { GFX_drawOnLayer(globalpill, pillRect.x, pillRect.y, globallpillW, globalpill->h, 1.0f, 0, LAYER_TRANSITION); - // GFX_drawOnLayer(globalText, SCALE1(PADDING+BUTTON_PADDING), pilltargetTextY, globalText->w, globalText->h, 1.0f, 0, LAYER_SCROLLTEXT); + GFX_drawOnLayer(globalText, SCALE1(PADDING+BUTTON_PADDING), pilltargetTextY, globalText->w, globalText->h, 1.0f, 0, LAYER_SCROLLTEXT); } SDL_UnlockMutex(animMutex); } @@ -3213,8 +3221,9 @@ int main (int argc, char *argv[]) { if(folderbgchanged) { if(folderbgbmp) GFX_drawOnLayer(folderbgbmp,0, 0, screen->w, screen->h,1.0f,0,LAYER_BACKGROUND); - else + else { GFX_clearLayers(LAYER_BACKGROUND); + } folderbgchanged = 0; } SDL_UnlockMutex(bgMutex); @@ -3223,18 +3232,18 @@ int main (int argc, char *argv[]) { int img_w = thumbbmp->w; int img_h = thumbbmp->h; double aspect_ratio = (double)img_h / img_w; - - int max_w = (int)(screen->w * CFG_getGameArtWidth()); - int max_h = (int)(screen->h * 0.6); - + + int max_w = (int)(screen->w * CFG_getGameArtWidth()); + int max_h = (int)(screen->h * 0.6); + int new_w = max_w; - int new_h = (int)(new_w * aspect_ratio); - + int new_h = (int)(new_w * aspect_ratio); + if (new_h > max_h) { new_h = max_h; new_w = (int)(new_h / aspect_ratio); } - + int target_x = screen->w-(new_w + SCALE1(BUTTON_MARGIN*3)); int target_y = (int)(screen->h * 0.50); int center_y = target_y - (new_h / 2); // FIX: use new_h instead of thumbbmp->h @@ -3273,7 +3282,7 @@ int main (int argc, char *argv[]) { int text_width = GFX_getTextWidth(font.large, entry_text, cached_display_name, available_width, SCALE1(BUTTON_PADDING * 2)); int max_width = MIN(available_width, text_width); int text_offset_y = (SCALE1(PILL_SIZE) - TTF_FontHeight(font.large) + 1) >> 1; - + GFX_clearLayers(LAYER_SCROLLTEXT); if (list_show_entry_names) { GFX_scrollTextTexture( @@ -3298,13 +3307,13 @@ int main (int argc, char *argv[]) { } SDL_UnlockMutex(animMutex); PLAT_GPU_Flip(); - } + } } else { GFX_sync(); } dirty = 0; - } + } else { // want to draw only if needed SDL_LockMutex(bgqueueMutex); @@ -3320,7 +3329,7 @@ int main (int argc, char *argv[]) { SDL_UnlockMutex(thumbqueueMutex); SDL_UnlockMutex(bgqueueMutex); } - + SDL_LockMutex(frameMutex); frameReady = true; SDL_CondSignal(flipCond); @@ -3344,20 +3353,20 @@ int main (int argc, char *argv[]) { quit = 1; } } - + Menu_quit(); PWR_quit(); PAD_quit(); - + // Cleanup worker threads and their synchronization primitives cleanupImageLoaderPool(); - + GFX_quit(); // Cleanup video subsystem first to stop GPU threads - + // Now safe to free surfaces after GPU threads are stopped if(blackBG) SDL_FreeSurface(blackBG); if (folderbgbmp) SDL_FreeSurface(folderbgbmp); if (thumbbmp) SDL_FreeSurface(thumbbmp); - + QuitSettings(); -} \ No newline at end of file +} diff --git a/workspace/all/settings/settings.cpp b/workspace/all/settings/settings.cpp index 5717b7790..75fb44a20 100644 --- a/workspace/all/settings/settings.cpp +++ b/workspace/all/settings/settings.cpp @@ -281,33 +281,33 @@ int main(int argc, char *argv[]) [](const std::any &value){ CFG_setFontId(std::any_cast(value)); }, []() { CFG_setFontId(CFG_DEFAULT_FONT_ID);}}, new MenuItem{ListItemType::Color, "Main Color", "The color used to render main UI elements.", colors, color_strings, - []() -> std::any{ return CFG_getColor(1); }, - [](const std::any &value){ CFG_setColor(1, std::any_cast(value)); }, - []() { CFG_setColor(1, CFG_DEFAULT_COLOR1);}}, + []() -> std::any{ return CFG_getColor(COLOR_MAIN); }, + [](const std::any &value){ CFG_setColor(COLOR_MAIN, std::any_cast(value)); }, + []() { CFG_setColor(COLOR_MAIN, CFG_DEFAULT_COLOR1);}}, new MenuItem{ListItemType::Color, "Primary Accent Color", "The color used to highlight important things in the user interface.", colors, color_strings, - []() -> std::any{ return CFG_getColor(2); }, - [](const std::any &value){ CFG_setColor(2, std::any_cast(value)); }, - []() { CFG_setColor(2, CFG_DEFAULT_COLOR2);}}, + []() -> std::any{ return CFG_getColor(COLOR_ACCENT); }, + [](const std::any &value){ CFG_setColor(COLOR_ACCENT, std::any_cast(value)); }, + []() { CFG_setColor(COLOR_ACCENT, CFG_DEFAULT_COLOR2);}}, new MenuItem{ListItemType::Color, "Secondary Accent Color", "A secondary highlight color.", colors, color_strings, - []() -> std::any{ return CFG_getColor(3); }, - [](const std::any &value){ CFG_setColor(3, std::any_cast(value)); }, - []() { CFG_setColor(3, CFG_DEFAULT_COLOR3);}}, + []() -> std::any{ return CFG_getColor(COLOR_ACCENT2); }, + [](const std::any &value){ CFG_setColor(COLOR_ACCENT2, std::any_cast(value)); }, + []() { CFG_setColor(COLOR_ACCENT2, CFG_DEFAULT_COLOR3);}}, new MenuItem{ListItemType::Color, "Hint info Color", "Color for button hints and info", colors, color_strings, - []() -> std::any{ return CFG_getColor(6); }, - [](const std::any &value){ CFG_setColor(6, std::any_cast(value)); }, - []() { CFG_setColor(6, CFG_DEFAULT_COLOR6);}}, + []() -> std::any{ return CFG_getColor(COLOR_HINT); }, + [](const std::any &value){ CFG_setColor(COLOR_HINT, std::any_cast(value)); }, + []() { CFG_setColor(COLOR_HINT, CFG_DEFAULT_COLOR6);}}, new MenuItem{ListItemType::Color, "List Text", "List text color", colors, color_strings, - []() -> std::any{ return CFG_getColor(4); }, - [](const std::any &value){ CFG_setColor(4, std::any_cast(value)); }, - []() { CFG_setColor(4, CFG_DEFAULT_COLOR4);}}, + []() -> std::any{ return CFG_getColor(COLOR_LIST_TEXT); }, + [](const std::any &value){ CFG_setColor(COLOR_LIST_TEXT, std::any_cast(value)); }, + []() { CFG_setColor(COLOR_LIST_TEXT, CFG_DEFAULT_COLOR4);}}, new MenuItem{ListItemType::Color, "List Text Selected", "List selected text color", colors, color_strings, - []() -> std::any { return CFG_getColor(5); }, - [](const std::any &value) { CFG_setColor(5, std::any_cast(value)); }, - []() { CFG_setColor(5, CFG_DEFAULT_COLOR5);}}, - //new MenuItem{ListItemType::Color, "Background color", "Main UI background color", colors, color_strings, - //[]() -> std::any { return CFG_getColor(7); }, - //[](const std::any &value) { CFG_setColor(7, std::any_cast(value)); }, - //[]() { CFG_setColor(7, CFG_DEFAULT_COLOR7);}}, + []() -> std::any { return CFG_getColor(COLOR_LIST_TEXT_SELECTED); }, + [](const std::any &value) { CFG_setColor(COLOR_LIST_TEXT_SELECTED, std::any_cast(value)); }, + []() { CFG_setColor(COLOR_LIST_TEXT_SELECTED, CFG_DEFAULT_COLOR5);}}, + new MenuItem{ListItemType::Color, "Background Color", "Background color used when no background image is set.", colors, color_strings, + []() -> std::any { return CFG_getColor(COLOR_BACKGROUND); }, + [](const std::any &value) { CFG_setColor(COLOR_BACKGROUND, std::any_cast(value)); }, + []() { CFG_setColor(COLOR_BACKGROUND, CFG_DEFAULT_COLOR7);}}, new MenuItem{ListItemType::Generic, "Show battery percentage", "Show battery level as percent in the status pill", {false, true}, on_off, []() -> std::any { return CFG_getShowBatteryPercent(); }, [](const std::any &value) { CFG_setShowBatteryPercent(std::any_cast(value)); }, @@ -852,6 +852,9 @@ int main(int argc, char *argv[]) if(bgbmp) { SDL_Rect image_rect = {0, 0, ctx.screen->w, ctx.screen->h}; SDL_BlitSurface(bgbmp, NULL, ctx.screen, &image_rect); + } else { + uint32_t bgc = CFG_getColor(COLOR_BACKGROUND); + SDL_FillRect(ctx.screen, NULL, SDL_MapRGB(ctx.screen->format, (bgc >> 16) & 0xFF, (bgc >> 8) & 0xFF, bgc & 0xFF)); } int ow = 0;