From cf44917afaca6cde74cdcdd060902479c80809ce Mon Sep 17 00:00:00 2001 From: Shaun Inman Date: Fri, 13 Jan 2023 20:19:25 -0500 Subject: [PATCH] implemented most (all?) of MinUI plus required API removed simple mode and version screen (for now at least) --- src/common/api.c | 198 ++++++++++++++++- src/common/api.h | 45 ++++ src/common/defines.h | 50 ++++- src/minui/main.c | 508 +++++++++++++++++++++++++------------------ 4 files changed, 575 insertions(+), 226 deletions(-) diff --git a/src/common/api.c b/src/common/api.c index b90298c..458a2ee 100644 --- a/src/common/api.c +++ b/src/common/api.c @@ -123,8 +123,33 @@ static struct GFX_Context { struct fb_fix_screeninfo finfo; SDL_Surface* screen; + SDL_Surface* assets; } gfx; +static SDL_Rect asset_rects[] = { + [ASSET_WHITE_PILL] = (SDL_Rect){SCALE4( 1, 1,30,30)}, + [ASSET_BLACK_PILL] = (SDL_Rect){SCALE4(33, 1,30,30)}, + [ASSET_DARK_GRAY_PILL] = (SDL_Rect){SCALE4(65, 1,30,30)}, + [ASSET_BUTTON] = (SDL_Rect){SCALE4( 1,33,20,20)}, + [ASSET_PAGE_BG] = (SDL_Rect){SCALE4(64,33,15,15)}, + [ASSET_STATE_BG] = (SDL_Rect){SCALE4(23,54, 8, 8)}, + [ASSET_PAGE] = (SDL_Rect){SCALE4(39,54, 6, 6)}, + [ASSET_BAR] = (SDL_Rect){SCALE4(33,58, 4, 4)}, + [ASSET_BAR_BG] = (SDL_Rect){SCALE4(15,55, 4, 4)}, + [ASSET_DOT] = (SDL_Rect){SCALE4(33,54, 2, 2)}, + + [ASSET_BRIGHTNESS] = (SDL_Rect){SCALE4(23,33,19,19)}, + [ASSET_VOLUME_MUTE] = (SDL_Rect){SCALE4(44,33,10,16)}, + [ASSET_VOLUME] = (SDL_Rect){SCALE4(44,33,18,16)}, + [ASSET_BATTERY] = (SDL_Rect){SCALE4(47,51,17,10)}, + [ASSET_BATTERY_LOW] = (SDL_Rect){SCALE4(66,51,17,10)}, + [ASSET_BATTERY_FILL] = (SDL_Rect){SCALE4(81,33,12, 6)}, + [ASSET_BATTERY_FILL_LOW]= (SDL_Rect){SCALE4( 1,55,12, 6)}, + [ASSET_BATTERY_BOLT] = (SDL_Rect){SCALE4(81,41,12, 6)}, +}; +static uint32_t asset_rgbs[ASSET_COLORS]; +GFX_Fonts font; + /////////////////////////////// SDL_Surface* GFX_init(void) { @@ -183,8 +208,47 @@ SDL_Surface* GFX_init(void) { // return screen gfx.screen = SDL_CreateRGBSurfaceFrom(gfx.map + gfx.buffer_size * gfx.buffer, SCREEN_WIDTH,SCREEN_HEIGHT, SCREEN_DEPTH,SCREEN_PITCH, 0,0,0,0); + + RGB_WHITE = SDL_MapRGB(gfx.screen->format, TRIAD_WHITE); + RGB_BLACK = SDL_MapRGB(gfx.screen->format, TRIAD_BLACK); + RGB_LIGHT_GRAY = SDL_MapRGB(gfx.screen->format, TRIAD_LIGHT_GRAY); + RGB_DARK_GRAY = SDL_MapRGB(gfx.screen->format, TRIAD_DARK_GRAY); + + asset_rgbs[ASSET_WHITE_PILL] = RGB_WHITE; + asset_rgbs[ASSET_BLACK_PILL] = RGB_BLACK; + asset_rgbs[ASSET_DARK_GRAY_PILL]= RGB_DARK_GRAY; + asset_rgbs[ASSET_BUTTON] = RGB_WHITE; + asset_rgbs[ASSET_PAGE_BG] = RGB_WHITE; + asset_rgbs[ASSET_STATE_BG] = RGB_WHITE; + asset_rgbs[ASSET_PAGE] = RGB_BLACK; + asset_rgbs[ASSET_BAR] = RGB_WHITE; + asset_rgbs[ASSET_BAR_BG] = RGB_BLACK; + asset_rgbs[ASSET_DOT] = RGB_LIGHT_GRAY; + + char asset_path[MAX_PATH]; + sprintf(asset_path, RES_PATH "/assets@%ix.png", SCREEN_SCALE); + gfx.assets = IMG_Load(asset_path); + + font.large = TTF_OpenFont(FONT_PATH, SCALE1(FONT_LARGE)); + font.medium = TTF_OpenFont(FONT_PATH, SCALE1(FONT_MEDIUM)); + font.small = TTF_OpenFont(FONT_PATH, SCALE1(FONT_SMALL)); + font.tiny = TTF_OpenFont(FONT_PATH, SCALE1(FONT_TINY)); + return gfx.screen; } +void GFX_quit(void) { + TTF_CloseFont(font.large); + TTF_CloseFont(font.medium); + TTF_CloseFont(font.small); + TTF_CloseFont(font.tiny); + + SDL_FreeSurface(gfx.assets); + GFX_clearAll(); + munmap(gfx.map, gfx.map_size); + close(gfx.fb); + SDL_Quit(); +} + void GFX_clear(SDL_Surface* screen) { memset(screen->pixels, 0, gfx.buffer_size); } @@ -216,11 +280,116 @@ void GFX_flip(SDL_Surface* screen) { screen->pixels = gfx.map + (gfx.buffer * gfx.buffer_size); #endif } -void GFX_quit(void) { - GFX_clearAll(); - munmap(gfx.map, gfx.map_size); - close(gfx.fb); - SDL_Quit(); + +void GFX_blitAsset(int asset, SDL_Rect* src_rect, SDL_Surface* dst, SDL_Rect* dst_rect) { + SDL_Rect* rect = &asset_rects[asset]; + SDL_Rect adj_rect = { + .x = rect->x, + .y = rect->y, + .w = rect->w, + .h = rect->h, + }; + if (src_rect) { + adj_rect.x += src_rect->x; + adj_rect.y += src_rect->y; + adj_rect.w = src_rect->w; + adj_rect.h = src_rect->h; + } + SDL_BlitSurface(gfx.assets, &adj_rect, dst, dst_rect); +} +void GFX_blitPill(int asset, SDL_Surface* dst, SDL_Rect* dst_rect) { + int x = dst_rect->x; + int y = dst_rect->y; + int w = dst_rect->w; + int h = dst_rect->h; + + int r = h / 2; + if (w < h) w = h; + w -= h; + + GFX_blitAsset(asset, &(SDL_Rect){0,0,r,h}, dst, &(SDL_Rect){x,y}); + x += r; + if (w>0) { + SDL_FillRect(dst, &(SDL_Rect){x,y,w,h}, asset_rgbs[asset]); + x += w; + } + GFX_blitAsset(asset, &(SDL_Rect){r,0,r,h}, dst, &(SDL_Rect){x,y}); +} +void GFX_blitBattery(SDL_Surface* dst, SDL_Rect* dst_rect) { + SDL_Rect rect = asset_rects[ASSET_BATTERY]; + int x = dst_rect->x; + int y = dst_rect->y; + x += (SCALE1(PILL_SIZE) - (rect.w + SCREEN_SCALE)) / 2; + y += (SCALE1(PILL_SIZE) - rect.h) / 2; + + if (POW_isCharging()) { + GFX_blitAsset(ASSET_BATTERY, NULL, dst, &(SDL_Rect){x,y}); + GFX_blitAsset(ASSET_BATTERY_BOLT, NULL, dst, &(SDL_Rect){x+SCALE1(3),y+SCALE1(2)}); + } + else { + int percent = POW_getBattery(); + GFX_blitAsset(percent<=10?ASSET_BATTERY_LOW:ASSET_BATTERY, NULL, dst, &(SDL_Rect){x,y}); + + rect = asset_rects[ASSET_BATTERY_FILL]; + SDL_Rect clip = rect; + clip.w *= percent; + clip.w /= 100; + if (clip.w<=0) return; + clip.x = rect.w - clip.w; + clip.y = 0; + + GFX_blitAsset(percent<=20?ASSET_BATTERY_FILL_LOW:ASSET_BATTERY_FILL, &clip, dst, &(SDL_Rect){x+SCALE1(3)+clip.x,y+SCALE1(2)}); + } +} +int GFX_getButtonWidth(char* hint, char* button) { + int button_width = 0; + int width; + + if (strlen(button)==1) { + button_width += SCALE1(BUTTON_SIZE); + } + else { + button_width += SCALE1(BUTTON_SIZE) / 2; + TTF_SizeUTF8(font.tiny, button, &width, NULL); + button_width += width; + } + button_width += SCALE1(BUTTON_MARGIN); + + TTF_SizeUTF8(font.small, hint, &width, NULL); + button_width += width + SCALE1(BUTTON_MARGIN); + return button_width; +} +void GFX_blitButton(char* hint, char*button, SDL_Surface* dst, SDL_Rect* dst_rect) { + SDL_Surface* text; + int ox = 0; + + // button + if (strlen(button)==1) { + GFX_blitAsset(ASSET_BUTTON, NULL, dst, dst_rect); + + // label + text = TTF_RenderUTF8_Blended(font.medium, button, COLOR_BUTTON_TEXT); + SDL_BlitSurface(text, NULL, dst, &(SDL_Rect){dst_rect->x+(SCALE1(BUTTON_SIZE)-text->w)/2,dst_rect->y+(SCALE1(BUTTON_SIZE)-text->h)/2}); + ox += SCALE1(BUTTON_SIZE); + SDL_FreeSurface(text); + } + else { + text = TTF_RenderUTF8_Blended(font.tiny, button, COLOR_BUTTON_TEXT); + GFX_blitPill(ASSET_BUTTON, dst, &(SDL_Rect){dst_rect->x,dst_rect->y,SCALE1(BUTTON_SIZE)/2+text->w,SCALE1(BUTTON_SIZE)}); + ox += SCALE1(BUTTON_SIZE)/4; + + SDL_BlitSurface(text, NULL, dst, &(SDL_Rect){ox+dst_rect->x,dst_rect->y+(SCALE1(BUTTON_SIZE)-text->h)/2,text->w,text->h}); + ox += text->w; + ox += SCALE1(BUTTON_SIZE)/4; + SDL_FreeSurface(text); + } + + ox += SCALE1(BUTTON_MARGIN); + + // hint text + text = TTF_RenderUTF8_Blended(font.small, hint, COLOR_WHITE); + SDL_BlitSurface(text, NULL, dst, &(SDL_Rect){ox+dst_rect->x,dst_rect->y+(SCALE1(BUTTON_SIZE)-text->h)/2,text->w,text->h}); + SDL_FreeSurface(text); } /////////////////////////////// @@ -507,9 +676,9 @@ void POW_fauxSleep(void) { GFX_clear(gfx.screen); PAD_reset(); POW_enterSleep(); - // TODO: pause keymon + system("killall -STOP keymon.elf"); POW_waitForWake(); - // TODO: resume keymon + system("killall -CONT keymon.elf"); POW_exitSleep(); } int POW_preventAutosleep(void) { @@ -517,4 +686,19 @@ int POW_preventAutosleep(void) { } int POW_isCharging(void) { return getInt("/sys/class/power_supply/battery/charger_online"); +} +int POW_getBattery(void) { + // return getInt("/sys/class/power_supply/battery/capacity"); // this is really inaccurate + + int i = getInt("/sys/class/power_supply/battery/voltage_now") / 10000; // ~320-420 + i = MIN(MAX(0, i-320), 100); // TODO: smooth this value before returning ala Mini + + // eh + // if (i>80) return 100; + // else if (i>60) return 80; + // else if (i>40) return 60; + // else if (i>20) return 40; + // else if (i>10) return 20; + // else if (i>5) return 10; + return i; } \ No newline at end of file diff --git a/src/common/api.h b/src/common/api.h index d0897eb..90afc8b 100644 --- a/src/common/api.h +++ b/src/common/api.h @@ -25,6 +25,43 @@ void LOG_note(int level, const char* fmt, ...); /////////////////////////////// +uint32_t RGB_WHITE; +uint32_t RGB_BLACK; +uint32_t RGB_LIGHT_GRAY; +uint32_t RGB_DARK_GRAY; + +enum { + ASSET_WHITE_PILL, + ASSET_BLACK_PILL, + ASSET_DARK_GRAY_PILL, + ASSET_BUTTON, + ASSET_PAGE_BG, + ASSET_STATE_BG, + ASSET_PAGE, + ASSET_BAR, + ASSET_BAR_BG, + ASSET_DOT, + + ASSET_COLORS, + + ASSET_BRIGHTNESS, + ASSET_VOLUME_MUTE, + ASSET_VOLUME, + ASSET_BATTERY, + ASSET_BATTERY_LOW, + ASSET_BATTERY_FILL, + ASSET_BATTERY_FILL_LOW, + ASSET_BATTERY_BOLT, +}; + +typedef struct GFX_Fonts { + TTF_Font* large; // menu + TTF_Font* medium; // single char button label + TTF_Font* small; // button hint + TTF_Font* tiny; // multi char button label +} GFX_Fonts; +extern GFX_Fonts font; + SDL_Surface* GFX_init(void); void GFX_clear(SDL_Surface* screen); void GFX_clearAll(void); @@ -32,6 +69,13 @@ void GFX_startFrame(void); void GFX_flip(SDL_Surface* screen); void GFX_quit(void); +// NOTE: all dimensions should be pre-scaled +void GFX_blitAsset(int asset, SDL_Rect* src_rect, SDL_Surface* dst, SDL_Rect* dst_rect); +void GFX_blitPill(int asset, SDL_Surface* dst, SDL_Rect* dst_rect); +void GFX_blitBattery(SDL_Surface* dst, SDL_Rect* dst_rect); +int GFX_getButtonWidth(char* hint, char* button); +void GFX_blitButton(char* hint, char*button, SDL_Surface* dst, SDL_Rect* dst_rect); + /////////////////////////////// typedef struct SND_Frame { @@ -85,6 +129,7 @@ void POW_powerOff(void); void POW_fauxSleep(void); int POW_preventAutosleep(void); int POW_isCharging(void); +int POW_getBattery(void); /////////////////////////////// diff --git a/src/common/defines.h b/src/common/defines.h index e1aca2c..20c6f02 100644 --- a/src/common/defines.h +++ b/src/common/defines.h @@ -43,10 +43,28 @@ #define RESUME_SLOT_PATH "/tmp/mmenu_slot.txt" #define AUTO_RESUME_PATH USERDATA_PATH "/.miniui/auto_resume.txt" #define AUTO_RESUME_SLOT "9" -#define ENABLE_SIMPLE_MODE_PATH USERDATA_PATH "/enable-simple-mode" -#define SCREEN_WIDTH 640 -#define SCREEN_HEIGHT 480 +#define TRIAD_WHITE 0xff,0xff,0xff +#define TRIAD_BLACK 0x00,0x00,0x00 +#define TRIAD_LIGHT_GRAY 0x7f,0x7f,0x7f +#define TRIAD_DARK_GRAY 0x26,0x26,0x26 + +#define TRIAD_LIGHT_TEXT 0xcc,0xcc,0xcc +#define TRIAD_DARK_TEXT 0x66,0x66,0x66 +#define TRIAD_BUTTON_TEXT 0x99,0x99,0x99 + +#define COLOR_WHITE (SDL_Color){TRIAD_WHITE} +#define COLOR_BLACK (SDL_Color){TRIAD_BLACK} +#define COLOR_LIGHT_TEXT (SDL_Color){TRIAD_LIGHT_TEXT} +#define COLOR_DARK_TEXT (SDL_Color){TRIAD_DARK_TEXT} +#define COLOR_BUTTON_TEXT (SDL_Color){TRIAD_BUTTON_TEXT} + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 +#define SCREEN_SCALE 2 // SCREEN_HEIGHT / 240 + +#define BASE_WIDTH 320 +#define BASE_HEIGHT 240 // SNES (stretched to 4:3) // #define SCREEN_WIDTH 1024 @@ -60,11 +78,24 @@ // #define SCREEN_WIDTH 768 // #define SCREEN_HEIGHT 576 -#define SCREEN_DEPTH 16 -#define SCREEN_BPP 2 -#define SCREEN_PITCH SCREEN_WIDTH * SCREEN_BPP +#define SCREEN_DEPTH 16 +#define SCREEN_BPP 2 +#define SCREEN_PITCH (SCREEN_WIDTH * SCREEN_BPP) -#define MAIN_ROW_COUNT 7 +// all before scale +#define PILL_SIZE 30 +#define BUTTON_SIZE 20 +#define BUTTON_MARGIN ((PILL_SIZE - BUTTON_SIZE) / 2) +#define SETTINGS_SIZE 4 +#define SETTINGS_WIDTH 80 + +#define MAIN_ROW_COUNT 6 // SCREEN_HEIGHT / (PILL_SIZE * SCREEN_SCALE) - 2 (floor and subtract 1 if not an integer) +#define PADDING 10 // PILL_SIZE / 3 (or non-integer part of the previous calculatiom divided by three) + +#define FONT_LARGE 16 // menu +#define FONT_MEDIUM 14 // single char button label +#define FONT_SMALL 12 // button hint +#define FONT_TINY 10 // multi char button label /////////////////////////////// @@ -74,4 +105,9 @@ #define MAX(a, b) (a) > (b) ? (a) : (b) #define MIN(a, b) (a) < (b) ? (a) : (b) +#define SCALE1(a) ((a)*SCREEN_SCALE) +#define SCALE2(a,b) ((a)*SCREEN_SCALE),((b)*SCREEN_SCALE) +#define SCALE4(a,b,c,d) ((a)*SCREEN_SCALE),((b)*SCREEN_SCALE),((c)*SCREEN_SCALE),((d)*SCREEN_SCALE) + + #endif \ No newline at end of file diff --git a/src/minui/main.c b/src/minui/main.c index ae88638..fe1c2e4 100644 --- a/src/minui/main.c +++ b/src/minui/main.c @@ -362,7 +362,6 @@ static Directory* top; static Array* stack; // DirectoryArray static Array* recents; // RecentArray -static int is_simple = 0; static int quit = 0; static int can_resume = 0; static int should_resume = 0; // set to 1 on BTN_RESUME but only if can_resume==1 @@ -694,7 +693,7 @@ static Array* getRoot(void) { char tools_path[256]; sprintf(tools_path, "%s/Tools", SDCARD_PATH); - if (!is_simple && exists(tools_path)) Array_push(root, Entry_new(tools_path, ENTRY_DIR)); + if (exists(tools_path)) Array_push(root, Entry_new(tools_path, ENTRY_DIR)); return root; } @@ -1233,8 +1232,6 @@ static void Menu_quit(void) { int main (int argc, char *argv[]) { if (autoResume()) return 0; // nothing to do - is_simple = exists(ENABLE_SIMPLE_MODE_PATH); - dump("MinUI"); SDL_Surface* screen = GFX_init(); @@ -1245,20 +1242,18 @@ int main (int argc, char *argv[]) { Menu_init(); - // TODO: tmp - TTF_Font* font = TTF_OpenFont(FONT_PATH, 32); - PAD_reset(); int dirty = 1; int was_charging = POW_isCharging(); unsigned long charge_start = SDL_GetTicks(); - int show_version = 0; int show_setting = 0; // 1=brightness,2=volume + unsigned long setting_start = 0; int setting_value = 0; int setting_min = 0; int setting_max = 0; - int delay_start = 0; int delay_select = 0; + int autoscroll_id = -1; + int autoscroll_ox = 0; unsigned long cancel_start = SDL_GetTicks(); unsigned long power_start = 0; while (!quit) { @@ -1270,131 +1265,118 @@ int main (int argc, char *argv[]) { int selected = top->selected; int total = top->entries->count; - if (show_version) { - if (PAD_justPressed(BTN_B) || PAD_justPressed(BTN_MENU)) { - show_version = 0; - dirty = 1; + if (total>0) { + if (PAD_justRepeated(BTN_UP)) { + selected -= 1; + if (selected<0) { + selected = total-1; + int start = total - MAIN_ROW_COUNT; + top->start = (start<0) ? 0 : start; + top->end = total; + } + else if (selectedstart) { + top->start -= 1; + top->end -= 1; + } + } + else if (PAD_justRepeated(BTN_DOWN)) { + selected += 1; + if (selected>=total) { + selected = 0; + top->start = 0; + top->end = (total=top->end) { + top->start += 1; + top->end += 1; + } + } + if (PAD_justRepeated(BTN_LEFT)) { + selected -= MAIN_ROW_COUNT; + if (selected<0) { + selected = 0; + top->start = 0; + top->end = (totalstart) { + top->start -= MAIN_ROW_COUNT; + if (top->start<0) top->start = 0; + top->end = top->start + MAIN_ROW_COUNT; + } + } + else if (PAD_justRepeated(BTN_RIGHT)) { + selected += MAIN_ROW_COUNT; + if (selected>=total) { + selected = total-1; + int start = total - MAIN_ROW_COUNT; + top->start = (start<0) ? 0 : start; + top->end = total; + } + else if (selected>=top->end) { + top->end += MAIN_ROW_COUNT; + if (top->end>total) top->end = total; + top->start = top->end - MAIN_ROW_COUNT; + } } } - else { - if (!is_simple && PAD_justPressed(BTN_MENU)) { - show_version = 1; - dirty = 1; - } - - if (total>0) { - if (PAD_justRepeated(BTN_UP)) { - selected -= 1; - if (selected<0) { - selected = total-1; - int start = total - MAIN_ROW_COUNT; - top->start = (start<0) ? 0 : start; - top->end = total; - } - else if (selectedstart) { - top->start -= 1; - top->end -= 1; - } - } - else if (PAD_justRepeated(BTN_DOWN)) { - selected += 1; - if (selected>=total) { - selected = 0; - top->start = 0; - top->end = (total=top->end) { - top->start += 1; - top->end += 1; - } - } - if (PAD_justRepeated(BTN_LEFT)) { - selected -= MAIN_ROW_COUNT; - if (selected<0) { - selected = 0; - top->start = 0; - top->end = (totalstart) { - top->start -= MAIN_ROW_COUNT; - if (top->start<0) top->start = 0; + + if (!PAD_isPressed(BTN_START) && !PAD_isPressed(BTN_SELECT)) { + if (PAD_justRepeated(BTN_L1)) { // previous alpha + Entry* entry = top->entries->items[selected]; + int i = entry->alpha-1; + if (i>=0) { + selected = top->alphas->items[i]; + if (total>MAIN_ROW_COUNT) { + top->start = selected; top->end = top->start + MAIN_ROW_COUNT; - } - } - else if (PAD_justRepeated(BTN_RIGHT)) { - selected += MAIN_ROW_COUNT; - if (selected>=total) { - selected = total-1; - int start = total - MAIN_ROW_COUNT; - top->start = (start<0) ? 0 : start; - top->end = total; - } - else if (selected>=top->end) { - top->end += MAIN_ROW_COUNT; if (top->end>total) top->end = total; top->start = top->end - MAIN_ROW_COUNT; } } } - - if (!PAD_isPressed(BTN_START) && !PAD_isPressed(BTN_SELECT)) { - if (PAD_justRepeated(BTN_L1)) { // previous alpha - Entry* entry = top->entries->items[selected]; - int i = entry->alpha-1; - if (i>=0) { - selected = top->alphas->items[i]; - if (total>MAIN_ROW_COUNT) { - top->start = selected; - top->end = top->start + MAIN_ROW_COUNT; - if (top->end>total) top->end = total; - top->start = top->end - MAIN_ROW_COUNT; - } - } - } - else if (PAD_justRepeated(BTN_R1)) { // next alpha - Entry* entry = top->entries->items[selected]; - int i = entry->alpha+1; - if (ialphas->count) { - selected = top->alphas->items[i]; - if (total>MAIN_ROW_COUNT) { - top->start = selected; - top->end = top->start + MAIN_ROW_COUNT; - if (top->end>total) top->end = total; - top->start = top->end - MAIN_ROW_COUNT; - } + else if (PAD_justRepeated(BTN_R1)) { // next alpha + Entry* entry = top->entries->items[selected]; + int i = entry->alpha+1; + if (ialphas->count) { + selected = top->alphas->items[i]; + if (total>MAIN_ROW_COUNT) { + top->start = selected; + top->end = top->start + MAIN_ROW_COUNT; + if (top->end>total) top->end = total; + top->start = top->end - MAIN_ROW_COUNT; } } } - - if (selected!=top->selected) { - top->selected = selected; - dirty = 1; - } - - if (dirty && total>0) readyResume(top->entries->items[top->selected]); - - if (total>0 && PAD_justReleased(BTN_RESUME)) { - if (can_resume) { - should_resume = 1; - Entry_open(top->entries->items[top->selected]); - dirty = 1; - } - } - else if (total>0 && PAD_justPressed(BTN_A)) { - Entry_open(top->entries->items[top->selected]); - total = top->entries->count; - dirty = 1; + } - if (total>0) readyResume(top->entries->items[top->selected]); - } - else if (PAD_justPressed(BTN_B) && stack->count>1) { - closeDirectory(); - total = top->entries->count; + if (selected!=top->selected) { + top->selected = selected; + dirty = 1; + } + + if (dirty && total>0) readyResume(top->entries->items[top->selected]); + + if (total>0 && PAD_justReleased(BTN_RESUME)) { + if (can_resume) { + should_resume = 1; + Entry_open(top->entries->items[top->selected]); dirty = 1; - // can_resume = 0; - if (total>0) readyResume(top->entries->items[top->selected]); } } + else if (total>0 && PAD_justPressed(BTN_A)) { + Entry_open(top->entries->items[top->selected]); + total = top->entries->count; + dirty = 1; + + if (total>0) readyResume(top->entries->items[top->selected]); + } + else if (PAD_justPressed(BTN_B) && stack->count>1) { + closeDirectory(); + total = top->entries->count; + dirty = 1; + // can_resume = 0; + if (total>0) readyResume(top->entries->items[top->selected]); + } unsigned long now = SDL_GetTicks(); if (PAD_anyPressed()) cancel_start = now; @@ -1421,7 +1403,7 @@ int main (int argc, char *argv[]) { #define SLEEP_DELAY 30000 if (now-cancel_start>=SLEEP_DELAY && POW_preventAutosleep()) cancel_start = now; - if (now-cancel_start>=SLEEP_DELAY || PAD_justReleased(BTN_SLEEP)) // || PAD_justPressed(BTN_MENU)) + if (now-cancel_start>=SLEEP_DELAY || PAD_justReleased(BTN_SLEEP)) { POW_fauxSleep(); cancel_start = SDL_GetTicks(); @@ -1433,115 +1415,217 @@ int main (int argc, char *argv[]) { int old_setting = show_setting; int old_value = setting_value; - show_setting = 0; - if (PAD_isPressed(BTN_START) && PAD_isPressed(BTN_SELECT)) { - // buh + + #define BRIGHTNESS_DELAY 500 + if (show_setting && now-setting_start>=BRIGHTNESS_DELAY && !PAD_isPressed(BTN_MENU)) { + show_setting = 0; + dirty = 1; } - else if (PAD_isPressed(BTN_START) && !delay_start) { - show_setting = 1; - setting_value = GetBrightness(); - setting_min = BRIGHTNESS_MIN; - setting_max = BRIGHTNESS_MAX; + + if (PAD_justPressed(BTN_VOL_UP) || PAD_justPressed(BTN_VOL_DN) || PAD_justPressed(BTN_MENU)) { + setting_start = now; + if (PAD_isPressed(BTN_MENU)) { + show_setting = 1; + } + else { + show_setting = 2; + } } - else if (PAD_isPressed(BTN_SELECT) && !delay_select) { - show_setting = 2; - setting_value = GetVolume(); - setting_min = VOLUME_MIN; - setting_max = VOLUME_MAX; - } - if (old_setting!=show_setting || old_value!=setting_value) dirty = 1; + if (show_setting) dirty = 1; // shm is slow or keymon is catching input on the next frame if (dirty) { GFX_clear(screen); - + + int ox; + int oy; + int ow = 0; + if (show_setting) { - // GFX_blitSettings(screen, Screen.main.settings.x, Screen.main.settings.y, show_setting==1?0:(setting_value>0?1:2), setting_value,setting_min,setting_max); - } - else { - // GFX_blitBattery(screen, Screen.main.battery.x, Screen.main.battery.y); - } - // GFX_blitRule(screen, Screen.main.rule.top_y); - - if (show_version) { - if (!version) { - // char release[256]; - // getFile("./version.txt", release, 256); - char* release = "20230102"; - - // char *tmp,*commit; - // commit = strrchr(release, '\n'); - // commit[0] = '\0'; - // commit = strrchr(release, '\n')+1; - // tmp = strchr(release, '\n'); - // tmp[0] = '\0'; - char* commit = "deadbeef"; - - SDL_Surface* release_txt = TTF_RenderUTF8_Blended(font, "Release", (SDL_Color){0xff,0xff,0xff}); // was gold - SDL_Surface* version_txt = TTF_RenderUTF8_Blended(font, release, (SDL_Color){0xff,0xff,0xff}); - SDL_Surface* commit_txt = TTF_RenderUTF8_Blended(font, "Commit", (SDL_Color){0xff,0xff,0xff}); // was gold - SDL_Surface* hash_txt = TTF_RenderUTF8_Blended(font, commit, (SDL_Color){0xff,0xff,0xff}); + ow = SCALE1(PILL_SIZE + SETTINGS_WIDTH + PADDING + 4); + ox = SCREEN_WIDTH - SCALE1(PADDING) - ow; + oy = SCALE1(PADDING); + GFX_blitPill(ASSET_DARK_GRAY_PILL, screen, &(SDL_Rect){ + ox, + oy, + ow, + SCALE1(PILL_SIZE) + }); - int x = version_txt->w + 12; - int w = x + version_txt->w; - int h = 96; // * 2; - version = SDL_CreateRGBSurface(0,w,h,16,0,0,0,0); + int asset = show_setting==1?ASSET_BRIGHTNESS:(setting_value>0?ASSET_VOLUME:ASSET_VOLUME_MUTE); + int ax = ox + (show_setting==1 ? SCALE1(6) : SCALE1(8)); + int ay = oy + (show_setting==1 ? SCALE1(5) : SCALE1(7)); + GFX_blitAsset(asset, NULL, screen, &(SDL_Rect){ax,ay}); - SDL_BlitSurface(release_txt, NULL, version, &(SDL_Rect){0, 0}); - SDL_BlitSurface(version_txt, NULL, version, &(SDL_Rect){x,0}); - SDL_BlitSurface(commit_txt, NULL, version, &(SDL_Rect){0,48}); - SDL_BlitSurface(hash_txt, NULL, version, &(SDL_Rect){x,48}); - - SDL_FreeSurface(release_txt); - SDL_FreeSurface(version_txt); - SDL_FreeSurface(commit_txt); - SDL_FreeSurface(hash_txt); - } - SDL_BlitSurface(version, NULL, screen, &(SDL_Rect){(640-version->w)/2,(480-version->h)/2}); - } - else { - if (total>0) { - int selected_row = top->selected - top->start; - for (int i=top->start,j=0; iend; i++,j++) { - Entry* entry = top->entries->items[i]; - char* display_name = entry->unique ? entry->unique : entry->name; - SDL_Color text_color = {0xff,0xff,0xff}; - if (j==selected_row) { - SDL_FillRect(screen, &(SDL_Rect){0,16+(j*64),SCREEN_WIDTH,64}, SDL_MapRGB(screen->format, 0xff,0xff,0xff)); - text_color = (SDL_Color){0x00,0x00,0x00}; - } - SDL_Surface* text = TTF_RenderUTF8_Blended(font, display_name, text_color); - SDL_BlitSurface(text, &(SDL_Rect){0,0,SCREEN_WIDTH-32,text->h}, screen, &(SDL_Rect){16,16+(j*64)+8}); - SDL_FreeSurface(text); - - // GFX_blitMenu(screen, entry->name, entry->path, entry->unique, j, selected_row); - } + ox += SCALE1(PILL_SIZE); + oy += SCALE1((PILL_SIZE - SETTINGS_SIZE) / 2); + GFX_blitPill(ASSET_BAR_BG, screen, &(SDL_Rect){ + ox, + oy, + SCALE1(SETTINGS_WIDTH), + SCALE1(SETTINGS_SIZE) + }); + + if (show_setting==1) { + setting_value = GetBrightness(); + setting_min = BRIGHTNESS_MIN; + setting_max = BRIGHTNESS_MAX; } else { - // GFX_blitBodyCopy(screen, "Empty folder", 0,0,Screen.width,Screen.height); + setting_value = GetVolume(); + setting_min = VOLUME_MIN; + setting_max = VOLUME_MAX; } + float percent = ((float)(setting_value-setting_min) / (setting_max-setting_min)); + if (show_setting==1 || setting_value>0) { + GFX_blitPill(ASSET_BAR, screen, &(SDL_Rect){ + ox, + oy, + SCALE1(SETTINGS_WIDTH) * percent, + SCALE1(SETTINGS_SIZE) + }); + } + } + else { + ow = SCALE1(PILL_SIZE); + ox = SCREEN_WIDTH - SCALE1(PADDING) - ow; + oy = SCALE1(PADDING); + GFX_blitPill(ASSET_DARK_GRAY_PILL, screen, &(SDL_Rect){ + ox, + oy, + ow, + SCALE1(PILL_SIZE) + }); + GFX_blitBattery(screen, &(SDL_Rect){ox,oy}); } - // GFX_blitRule(screen, Screen.main.rule.bottom_y); - if (can_resume && !show_version) { - // if (strlen(HINT_RESUME)>1) GFX_blitPill(screen, HINT_RESUME, "RESUME", Screen.buttons.left, Screen.buttons.top); - // else GFX_blitButton(screen, HINT_RESUME, "RESUME", Screen.buttons.left, Screen.buttons.top, Screen.button.text.ox_X); - } - else { - // GFX_blitPill(screen, HINT_SLEEP, "SLEEP", Screen.buttons.left, Screen.buttons.top); - } - - if (show_version) { - // GFX_blitButton(screen, "B", "BACK", -Screen.buttons.right, Screen.buttons.top, Screen.button.text.ox_B); - } - else if (total==0) { - if (stack->count>1) { - // GFX_blitButton(screen, "B", "BACK", -Screen.buttons.right, Screen.buttons.top, Screen.button.text.ox_B); + if (total>0) { + int selected_row = top->selected - top->start; + for (int i=top->start,j=0; iend; i++,j++) { + Entry* entry = top->entries->items[i]; + char* display_name = entry->unique ? entry->unique : entry->name; + int max_width = SCREEN_WIDTH - SCALE1(PADDING * 2); + if (i==top->start) max_width -= ow; // + SCALE1(PADDING); + + SDL_Color text_color = COLOR_WHITE; + + if (j==selected_row) { + GFX_blitPill(ASSET_WHITE_PILL, screen, &(SDL_Rect){ + SCALE1(PADDING), + SCALE1(PADDING+(j*PILL_SIZE)), + max_width, + SCALE1(PILL_SIZE) + }); + text_color = COLOR_BLACK; + } + SDL_Surface* text = TTF_RenderUTF8_Blended(font.large, display_name, text_color); + // TODO: handle auto-scrolling + SDL_BlitSurface(text, &(SDL_Rect){ + 0, + 0, + max_width-SCALE1(12*2), + text->h + }, screen, &(SDL_Rect){ + SCALE1(PADDING+12), + SCALE1(PADDING+(j*PILL_SIZE)+4) + }); + SDL_FreeSurface(text); } } else { - // int button_width = GFX_blitButton(screen, "A", "OPEN", -Screen.buttons.right, Screen.buttons.top, Screen.button.text.ox_A); + // GFX_blitBodyCopy("Empty folder", screen, &(SDL_Rect){0,0,SCREEN_WIDTH,SCREEN_HEIGHT}); + } + + char* hint; + char* button; + if (show_setting) { + hint = "BRIGHTNESS"; + button = "MENU"; + } + else if (can_resume) { + hint = "RESUME"; + button = "X"; + } + else { + hint = "SLEEP"; + button = "POWER"; + } + ox = SCALE1(PADDING); + oy = SCREEN_HEIGHT - SCALE1(PADDING + PILL_SIZE); + GFX_blitPill(ASSET_DARK_GRAY_PILL, screen, &(SDL_Rect){ + ox, + oy, + SCALE1(BUTTON_MARGIN * 2) + GFX_getButtonWidth(hint, button), + SCALE1(PILL_SIZE) + }); + GFX_blitButton(hint, button, screen, &(SDL_Rect){ + ox + SCALE1(BUTTON_MARGIN), + oy + SCALE1(BUTTON_MARGIN) + }); + + if (total==0) { if (stack->count>1) { - // GFX_blitButton(screen, "B", "BACK", -(Screen.buttons.right+button_width+Screen.buttons.gutter),Screen.buttons.top, Screen.button.text.ox_B); + hint = "BACK"; + button = "B"; + ow = GFX_getButtonWidth(hint, button); + ox = SCREEN_WIDTH - ow - SCALE1(PADDING); + oy = SCREEN_HEIGHT - SCALE1(PADDING + PILL_SIZE); + GFX_blitPill(ASSET_DARK_GRAY_PILL, screen, &(SDL_Rect){ + ox, + oy, + SCALE1(BUTTON_MARGIN * 2) + ow, + SCALE1(PILL_SIZE) + }); + GFX_blitButton(hint, button, screen, &(SDL_Rect){ + ox + SCALE1(BUTTON_MARGIN), + oy + SCALE1(BUTTON_MARGIN) + }); + } + } + else { + struct Hint { + char* hint; + char* button; + int ow; + } hints[3]; + int w = 0; // individual button dimension + int h = 0; // hints index + ow = 0; // full pill width + ox = SCREEN_WIDTH - SCALE1(PADDING); + + if (stack->count>1) { + hint = "BACK"; + button = "B"; + w = GFX_getButtonWidth(hint, button); + hints[h].hint = hint; + hints[h].button = button; + hints[h].ow = w; + h += 1; + ow += SCALE1(BUTTON_MARGIN) + w; + } + + hint = "OPEN"; + button = "A"; + w = GFX_getButtonWidth(hint, button); + hints[h].hint = hint; + hints[h].button = button; + hints[h].ow = w; + h += 1; + ow += SCALE1(BUTTON_MARGIN) + w; + + ow += SCALE1(BUTTON_MARGIN); + ox -= ow; + GFX_blitPill(ASSET_DARK_GRAY_PILL, screen, &(SDL_Rect){ + ox, + oy, + ow, + SCALE1(PILL_SIZE) + }); + + ox += SCALE1(BUTTON_MARGIN); + oy += SCALE1(BUTTON_MARGIN); + for (int i=0; i