From 11459880660b99fd31f810326bd552dec4d12c2f Mon Sep 17 00:00:00 2001 From: Shaun Inman Date: Sun, 15 Jan 2023 20:19:59 -0500 Subject: [PATCH] api refactor - handles power related input and state - handles battery and settings rendering --- src/clock/main.c | 12 ++- src/common/api.c | 257 +++++++++++++++++++++++++++++++++++---------- src/common/api.h | 14 ++- src/minarch/main.c | 163 +++++++++++++++++----------- src/minui/main.c | 186 ++++++-------------------------- 5 files changed, 360 insertions(+), 272 deletions(-) diff --git a/src/clock/main.c b/src/clock/main.c index 7533df2..d3fbf8e 100644 --- a/src/clock/main.c +++ b/src/clock/main.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "defines.h" #include "utils.h" @@ -21,7 +22,8 @@ enum { }; int main(int argc , char* argv[]) { - SDL_Surface* screen = GFX_init(); + SDL_Surface* screen = GFX_init(MODE_MAIN); + InitSettings(); // TODO: make use of SCALE1() SDL_Surface* digits = SDL_CreateRGBSurface(SDL_SWSURFACE, 240,32, 16, 0,0,0,0); @@ -132,6 +134,7 @@ int main(int argc , char* argv[]) { int option_count = 7; int dirty = 1; + int show_setting = 0; while(!quit) { unsigned long frame_start = SDL_GetTicks(); @@ -224,6 +227,8 @@ int main(int argc , char* argv[]) { } } + POW_update(&dirty, &show_setting); + if (dirty) { dirty = 0; @@ -231,6 +236,9 @@ int main(int argc , char* argv[]) { // render GFX_clear(screen); + + GFX_blitHardwareGroup(screen, show_setting); + GFX_blitButtonGroup((char*[]){ "SELECT",show_24hour?"12 HOUR":"24 HOUR", NULL }, screen, 0); GFX_blitButtonGroup((char*[]){ "B","CANCEL", "A","SET", NULL }, screen, 1); @@ -295,6 +303,8 @@ int main(int argc , char* argv[]) { GFX_quit(); + // TODO: if (seconds_selected==tm.tm_sec) refresh tm and update seconds_selected + if (save_changes) { char cmd[512]; snprintf(cmd, sizeof(cmd), "date -u -s '%d-%d-%d %d:%d:%d';hwclock --utc -w", year_selected, month_selected, day_selected, hour_selected, minute_selected, seconds_selected); diff --git a/src/common/api.c b/src/common/api.c index 446cbf2..f279298 100644 --- a/src/common/api.c +++ b/src/common/api.c @@ -113,6 +113,7 @@ struct owlfb_mem_info { /////////////////////////////// static struct GFX_Context { + int mode; int fb; int pitch; int buffer; @@ -153,11 +154,13 @@ GFX_Fonts font; /////////////////////////////// -SDL_Surface* GFX_init(void) { +SDL_Surface* GFX_init(int mode) { SDL_Init(SDL_INIT_VIDEO); SDL_ShowCursor(0); TTF_Init(); - + + gfx.mode = mode; + // we're drawing to the (triple-buffered) framebuffer directly // but we still need to set video mode to initialize input events SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_DEPTH, SDL_HWSURFACE); @@ -246,6 +249,10 @@ void GFX_quit(void) { TTF_CloseFont(font.tiny); SDL_FreeSurface(gfx.assets); +#ifdef GFX_ENABLE_VSYNC + int arg = 1; + ioctl(gfx.fb, OWLFB_WAITFORVSYNC, &arg); +#endif GFX_clearAll(); munmap(gfx.map, gfx.map_size); close(gfx.fb); @@ -403,63 +410,123 @@ void GFX_blitButton(char* hint, char*button, SDL_Surface* dst, SDL_Rect* dst_rec 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); } - -void GFX_blitABButtons(char* a, char* b, SDL_Surface* dst) { - int ox; - int oy; - int ow; - char* hint; - char* button; - - 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); - oy = SCREEN_HEIGHT - SCALE1(PADDING + PILL_SIZE); - - if (b) { - hint = b; - 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; +void GFX_blitMessage(char* msg, SDL_Surface* dst, SDL_Rect* dst_rect) { + if (dst_rect==NULL) { + dst_rect = &(SDL_Rect){0,0,SCREEN_WIDTH,SCREEN_HEIGHT}; } - - - hint = a; - 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, dst, &(SDL_Rect){ - ox, - oy, - ow, - SCALE1(PILL_SIZE) - }); - ox += SCALE1(BUTTON_MARGIN); - oy += SCALE1(BUTTON_MARGIN); - for (int i=0; i=TEXT_BOX_MAX_ROWS) return; // TODO: bail + rows[row_count++] = tmp+1; + } + + int rendered_height = SCALE1(LINE_HEIGHT) * row_count; + int y = dst_rect->y; + y += (dst_rect->h - rendered_height) / 2; + + char line[256]; + for (int i=0; ix; + x += (dst_rect->w - text->w) / 2; + SDL_BlitSurface(text, NULL, dst, &(SDL_Rect){x,y}); + SDL_FreeSurface(text); + } + y += SCALE1(LINE_HEIGHT); } } +int GFX_blitHardwareGroup(SDL_Surface* dst, int show_setting) { + int ox; + int oy; + int ow = 0; + + int setting_value; + int setting_min; + int setting_max; + + if (show_setting) { + ow = SCALE1(PILL_SIZE + SETTINGS_WIDTH + PADDING + 4); + ox = SCREEN_WIDTH - SCALE1(PADDING) - ow; + oy = SCALE1(PADDING); + GFX_blitPill(gfx.mode==MODE_MAIN ? ASSET_DARK_GRAY_PILL : ASSET_BLACK_PILL, dst, &(SDL_Rect){ + ox, + oy, + ow, + SCALE1(PILL_SIZE) + }); + + if (show_setting==1) { + setting_value = GetBrightness(); + setting_min = BRIGHTNESS_MIN; + setting_max = BRIGHTNESS_MAX; + } + else { + setting_value = GetVolume(); + setting_min = VOLUME_MIN; + setting_max = VOLUME_MAX; + } + + 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, dst, &(SDL_Rect){ax,ay}); + + ox += SCALE1(PILL_SIZE); + oy += SCALE1((PILL_SIZE - SETTINGS_SIZE) / 2); + GFX_blitPill(ASSET_BAR_BG, dst, &(SDL_Rect){ + ox, + oy, + SCALE1(SETTINGS_WIDTH), + SCALE1(SETTINGS_SIZE) + }); + + float percent = ((float)(setting_value-setting_min) / (setting_max-setting_min)); + if (show_setting==1 || setting_value>0) { + GFX_blitPill(ASSET_BAR, dst, &(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(gfx.mode==MODE_MAIN ? ASSET_DARK_GRAY_PILL : ASSET_BLACK_PILL, dst, &(SDL_Rect){ + ox, + oy, + ow, + SCALE1(PILL_SIZE) + }); + GFX_blitBattery(dst, &(SDL_Rect){ox,oy}); + } + + return ow; +} int GFX_blitButtonGroup(char** pairs, SDL_Surface* dst, int align_right) { int ox; int oy; @@ -493,7 +560,7 @@ int GFX_blitButtonGroup(char** pairs, SDL_Surface* dst, int align_right) { ow += SCALE1(BUTTON_MARGIN); if (align_right) ox -= ow; - GFX_blitPill(ASSET_DARK_GRAY_PILL, dst, &(SDL_Rect){ + GFX_blitPill(gfx.mode==MODE_MAIN ? ASSET_DARK_GRAY_PILL : ASSET_BLACK_PILL, dst, &(SDL_Rect){ ox, oy, ow, @@ -753,6 +820,79 @@ int PAD_justRepeated(int btn) { return pad.just_repeated & btn; } /////////////////////////////// +// TODO: separate settings/battery and power management? +void POW_update(int* _dirty, int* _show_setting, POW_callback_t before_sleep, POW_callback_t after_sleep) { + int dirty = _dirty ? *_dirty : 0; + int show_setting = _show_setting ? *_show_setting : 0; + + static unsigned long cancel_start = 0; + static unsigned long power_start = 0; + + static unsigned long setting_start = 0; + static unsigned long charge_start = 0; + static int was_charging = -1; + if (was_charging==-1) was_charging = POW_isCharging(); + + unsigned long now = SDL_GetTicks(); + if (cancel_start==0) cancel_start = now; + if (charge_start==0) charge_start = now; + + if (PAD_anyPressed()) cancel_start = now; + + #define CHARGE_DELAY 1000 + if (dirty || now-charge_start>=CHARGE_DELAY) { + int is_charging = POW_isCharging(); + if (was_charging!=is_charging) { + was_charging = is_charging; + dirty = 1; + } + charge_start = now; + } + + if (power_start && now-power_start>=1000) { + if (before_sleep) before_sleep(); + POW_powerOff(); + } + if (PAD_justPressed(BTN_SLEEP)) { + power_start = now; + } + + #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)) { + if (before_sleep) before_sleep(); + POW_fauxSleep(); + if (after_sleep) after_sleep(); + + cancel_start = SDL_GetTicks(); + power_start = 0; + dirty = 1; + } + + int was_dirty = dirty; // dirty list (not including settings/battery) + + #define SETTING_DELAY 500 + if (show_setting && now-setting_start>=SETTING_DELAY && !PAD_isPressed(BTN_MENU)) { + show_setting = 0; + dirty = 1; + } + + if (PAD_justRepeated(BTN_VOL_UP) || PAD_justRepeated(BTN_VOL_DN) || PAD_justPressed(BTN_MENU)) { + setting_start = now; + if (PAD_isPressed(BTN_MENU)) { + show_setting = 1; + } + else { + show_setting = 2; + } + } + if (show_setting) dirty = 1; // shm is slow or keymon is catching input on the next frame + + if (_dirty) *_dirty = dirty; + if (_show_setting) *_show_setting = show_setting; +} + static int can_poweroff = 1; void POW_disablePowerOff(void) { can_poweroff = 0; @@ -760,6 +900,13 @@ void POW_disablePowerOff(void) { void POW_powerOff(void) { if (can_poweroff) { + char* msg = exists(AUTO_RESUME_PATH) ? "Quicksave created,\npowering off" : "Powering off"; + GFX_clear(gfx.screen); + GFX_blitMessage(msg, gfx.screen, NULL); + GFX_flip(gfx.screen); + sleep(2); + + // actual shutdown system("echo u > /proc/sysrq-trigger"); system("echo s > /proc/sysrq-trigger"); system("echo o > /proc/sysrq-trigger"); diff --git a/src/common/api.h b/src/common/api.h index 9d5f565..1ac17e5 100644 --- a/src/common/api.h +++ b/src/common/api.h @@ -59,7 +59,12 @@ typedef struct GFX_Fonts { } GFX_Fonts; extern GFX_Fonts font; -SDL_Surface* GFX_init(void); +enum { + MODE_MAIN, + MODE_MENU, +}; + +SDL_Surface* GFX_init(int mode); void GFX_clear(SDL_Surface* screen); void GFX_clearAll(void); void GFX_startFrame(void); @@ -74,7 +79,9 @@ 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); -void GFX_blitABButtons(char* a, char* b, SDL_Surface* dst); +void GFX_blitMessage(char* msg, SDL_Surface* dst, SDL_Rect* dst_rect); + +int GFX_blitHardwareGroup(SDL_Surface* dst, int show_setting); int GFX_blitButtonGroup(char** hints, SDL_Surface* dst, int align_right); /////////////////////////////// @@ -148,6 +155,9 @@ int PAD_justRepeated(int btn); /////////////////////////////// +// TODO: rename PLAT_*? +typedef void (*POW_callback_t)(void); +void POW_update(int* dirty, int* show_setting, POW_callback_t before_sleep, POW_callback_t after_sleep); void POW_disablePowerOff(void); void POW_powerOff(void); void POW_fauxSleep(void); diff --git a/src/minarch/main.c b/src/minarch/main.c index a0e5775..e115ea4 100644 --- a/src/minarch/main.c +++ b/src/minarch/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -215,6 +216,21 @@ error: sync(); } +static void State_autosave(void) { + int last_state_slot = state_slot; + state_slot = AUTO_RESUME_SLOT; + State_write(); + state_slot = last_state_slot; +} +static void State_resume(void) { + if (!exists(RESUME_SLOT_PATH)) return; + + int last_state_slot = state_slot; + state_slot = getInt(RESUME_SLOT_PATH); + unlink(RESUME_SLOT_PATH); + State_read(); + state_slot = last_state_slot; +} /////////////////////////////// @@ -763,20 +779,23 @@ static size_t audio_sample_batch_callback(const int16_t *data, size_t frames) { return SND_batchSamples((const SND_Frame*)data, frames); }; +static void Menu_beforeSleep(void); +static void Menu_afterSleep(void); + static uint32_t buttons = 0; static void input_poll_callback(void) { PAD_poll(); - // TODO: tmp (L)oad and w(R)ite state - if (PAD_isPressed(BTN_MENU)) { - if (PAD_justPressed(BTN_L1)) State_read(); - else if (PAD_justPressed(BTN_R1)) State_write(); - } - - // TODO: tmp - if (PAD_justReleased(BTN_POWER)) { - quit = 1; - } + + + + // TODO: too heavy? maybe but regardless, + // this will cause it to go to sleep after + // 30 seconds--even while playing! + POW_update(NULL,NULL, Menu_beforeSleep, Menu_afterSleep); + + + if (PAD_justReleased(BTN_MENU)) { show_menu = 1; @@ -941,68 +960,90 @@ void Menu_init(void) { void Menu_quit(void) { SDL_FreeSurface(menu.overlay); } +void Menu_beforeSleep(void) { + State_autosave(); + putFile(AUTO_RESUME_PATH, game.path + strlen(SDCARD_PATH)); +} +void Menu_afterSleep(void) { + unlink(AUTO_RESUME_PATH); +} void Menu_loop(void) { PAD_reset(); // current screen is on the previous buffer - // TODO: copy current screen to restore before exiting - // TODO: create a second copy to use as backdrop with static elements? (eg. 50% black overlay, button hints, etc) - SDL_Surface* backing = GFX_getBufferCopy(); - SDL_BlitSurface(backing, NULL, screen, NULL); - SDL_BlitSurface(menu.overlay, NULL, screen, NULL); - // battery - int ow = SCALE1(PILL_SIZE); - int ox = SCREEN_WIDTH - SCALE1(PADDING) - ow; - int oy = SCALE1(PADDING); - GFX_blitPill(ASSET_BLACK_PILL, screen, &(SDL_Rect){ - ox, - oy, - ow, - SCALE1(PILL_SIZE) - }); - GFX_blitBattery(screen, &(SDL_Rect){ox,oy}); - - // title - char display_name[MAX_PATH]; - getDisplayName(game.name, display_name); - - SDL_Surface* text = TTF_RenderUTF8_Blended(font.large, display_name, COLOR_WHITE); - int max_width = MIN(SCREEN_WIDTH - SCALE1(PADDING * 2) - ow, text->w+SCALE1(12*2)); - GFX_blitPill(ASSET_BLACK_PILL, screen, &(SDL_Rect){ - SCALE1(PADDING), - SCALE1(PADDING), - max_width, - SCALE1(PILL_SIZE) - }); - - SDL_BlitSurface(text, &(SDL_Rect){ - 0, - 0, - max_width-SCALE1(12*2), - text->h - }, screen, &(SDL_Rect){ - SCALE1(PADDING+12), - SCALE1(PADDING+4) - }); - SDL_FreeSurface(text); - - // TODO: these need an overlay mode to use a BLACK background - GFX_blitButtonGroup((char*[]){ "POWER","SLEEP", NULL }, screen, 0); - GFX_blitButtonGroup((char*[]){ "B","BACK", "A","OKAY", NULL }, screen, 1); - - GFX_flip(screen); + // displau name + char rom_name[MAX_PATH]; + getDisplayName(game.path, rom_name); + int show_setting = 0; + int menu_dirty = 1; + int menu_start = SDL_GetTicks(); while (show_menu) { PAD_poll(); - if (PAD_anyPressed()) show_menu = 0; + + // TODO: tmp (L)oad and w(R)ite state + if (PAD_justPressed(BTN_L1)) { + State_read(); + show_menu = 0; + } + else if (PAD_justPressed(BTN_R1)) { + State_write(); + show_menu = 0; + } + + if (PAD_justPressed(BTN_B)) show_menu = 0; + if (PAD_justPressed(BTN_X)) { + show_menu = 0; + quit = 1; // TODO: tmp + } + + POW_update(&menu_dirty, &show_setting, Menu_beforeSleep, Menu_afterSleep); + + if (menu_dirty) { + SDL_BlitSurface(backing, NULL, screen, NULL); + SDL_BlitSurface(menu.overlay, NULL, screen, NULL); + + int ow = GFX_blitHardwareGroup(screen, show_setting); + + SDL_Surface* text = TTF_RenderUTF8_Blended(font.large, rom_name, COLOR_WHITE); + int max_width = MIN(SCREEN_WIDTH - SCALE1(PADDING * 2) - ow, text->w+SCALE1(12*2)); + GFX_blitPill(ASSET_BLACK_PILL, screen, &(SDL_Rect){ + SCALE1(PADDING), + SCALE1(PADDING), + max_width, + SCALE1(PILL_SIZE) + }); + SDL_BlitSurface(text, &(SDL_Rect){ + 0, + 0, + max_width-SCALE1(12*2), + text->h + }, screen, &(SDL_Rect){ + SCALE1(PADDING+12), + SCALE1(PADDING+4) + }); + SDL_FreeSurface(text); + + GFX_blitButtonGroup((char*[]){ "POWER","SLEEP", NULL }, screen, 0); + GFX_blitButtonGroup((char*[]){ "B","BACK", "A","OKAY", NULL }, screen, 1); + + GFX_flip(screen); + menu_dirty = 0; + } + else { + // slow down to 60fps + unsigned long frame_duration = SDL_GetTicks() - menu_start; + #define kTargetFrameDuration 17 + if (frame_durationentries->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; - } + 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; } } } @@ -1356,12 +1343,10 @@ int main (int argc, char *argv[]) { 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; - } + if (total>0 && can_resume && PAD_justReleased(BTN_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]); @@ -1378,126 +1363,16 @@ int main (int argc, char *argv[]) { if (total>0) readyResume(top->entries->items[top->selected]); } - unsigned long now = SDL_GetTicks(); - if (PAD_anyPressed()) cancel_start = now; - - #define CHARGE_DELAY 1000 - if (dirty || now-charge_start>=CHARGE_DELAY) { - int is_charging = POW_isCharging(); - if (was_charging!=is_charging) { - was_charging = is_charging; - dirty = 1; - } - charge_start = now; - } - - if (power_start && now-power_start>=1000) { - POW_powerOff(); - quit = 1; - break; - } - if (PAD_justPressed(BTN_SLEEP)) { - power_start = now; - } - - #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)) - { - POW_fauxSleep(); - cancel_start = SDL_GetTicks(); - power_start = 0; - dirty = 1; - } - - int was_dirty = dirty; // dirty list (not including settings/battery) - - int old_setting = show_setting; - int old_value = setting_value; - - #define SETTING_DELAY 500 - if (show_setting && now-setting_start>=SETTING_DELAY && !PAD_isPressed(BTN_MENU)) { - show_setting = 0; - dirty = 1; - } - - if (PAD_justRepeated(BTN_VOL_UP) || PAD_justRepeated(BTN_VOL_DN) || PAD_justPressed(BTN_MENU)) { - setting_start = now; - if (PAD_isPressed(BTN_MENU)) { - show_setting = 1; - } - else { - show_setting = 2; - } - } - if (show_setting) dirty = 1; // shm is slow or keymon is catching input on the next frame + POW_update(&dirty, &show_setting, NULL, NULL); if (dirty) { GFX_clear(screen); int ox; int oy; - int ow = 0; - - if (show_setting) { - 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 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}); - - 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 { - 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}); - } + int ow = GFX_blitHardwareGroup(screen, show_setting); + // list if (total>0) { int selected_row = top->selected - top->start; for (int i=top->start,j=0; iend; i++,j++) { @@ -1532,9 +1407,10 @@ int main (int argc, char *argv[]) { } } else { - // GFX_blitBodyCopy("Empty folder", screen, &(SDL_Rect){0,0,SCREEN_WIDTH,SCREEN_HEIGHT}); + GFX_blitMessage("Empty folder", screen, NULL); } + // buttons if (show_setting) { GFX_blitButtonGroup((char*[]){ "MENU","BRIGHTNESS", NULL }, screen, 0); }