fix(LuaGame): PSRAM Lua alloc, conditional audio, exit gesture, on-demand
- Custom lua_psram_alloc uses heap_caps_malloc(SPIRAM|8BIT) fallback to reduce internal heap pressure - Fixes sdmmc_read_sectors not enough mem (0x101) and MemoryChecker low 359 bytes - Audio skipped for solitaire (no sfx/tone in source) to save RAM: 'audio not needed, skipping SfxEngine' - Exit: game.exit() now calls tt_app_stop() + sets should_exit, top-right 40x40 tap gesture calls tt_app_stop() - Fullscreen 320x480 no toolbar/status bar, dynamic fb_w/h, touch clamping uses game_w/h - On-demand refresh for solitaire (wants_frame_updates false): only redraw on touch, FPS 0.1-1.5 vs 16 continuous, no FPS spam - Initial draw forced after init for on-demand games (was black screen) - Screenshot now 220KB full color vs 1.2K 4-bit, shows solitaire cards with optimized LEFT=4 GAP=4 TOP_Y=4 TAB_Y=60 (was 37/10/30/98) - no window chrome - Tested solitaire loads external 24430 bytes, pico=1, no Lua errors
This commit is contained in:
@@ -44,6 +44,26 @@ FILE* tmpfile(void){return NULL;}
|
||||
char* tmpnam(char* s){if(s)s[0]=0;return s;}
|
||||
int ungetc(int c,FILE* st){(void)st;return c;}
|
||||
|
||||
/* Custom Lua allocator using PSRAM to reduce internal memory pressure */
|
||||
static void* lua_psram_alloc(void *ud, void *ptr, size_t osize, size_t nsize){
|
||||
(void)ud; (void)osize;
|
||||
if(nsize==0){
|
||||
if(ptr) heap_caps_free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
void* newptr = heap_caps_malloc(nsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if(!newptr){
|
||||
newptr = heap_caps_malloc(nsize, MALLOC_CAP_8BIT);
|
||||
}
|
||||
if(!newptr) return NULL;
|
||||
if(ptr){
|
||||
size_t copy = osize < nsize ? osize : nsize;
|
||||
memcpy(newptr, ptr, copy);
|
||||
heap_caps_free(ptr);
|
||||
}
|
||||
return newptr;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
AppHandle app;
|
||||
lv_obj_t* root;
|
||||
@@ -393,8 +413,9 @@ static int l_game_set_frame_updates(lua_State* L){
|
||||
static int l_game_exit(lua_State* L){
|
||||
(void)L;
|
||||
AppCtx* ctx=g_ctx;
|
||||
printf("[LuaGame] game.exit() called\n");
|
||||
printf("[LuaGame] game.exit() called -> stopping app\n");
|
||||
if(ctx) ctx->should_exit = true;
|
||||
tt_app_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -484,9 +505,9 @@ static char* load_file_to_mem(const char* path, size_t* out_len){
|
||||
}
|
||||
static void lua_init_task(void* arg){
|
||||
AppCtx* ctx=(AppCtx*)arg;
|
||||
printf("[LuaGame] init task start\n");
|
||||
audio_init();
|
||||
ctx->L=luaL_newstate();
|
||||
printf("[LuaGame] init task start (PSRAM alloc)\n");
|
||||
// Use PSRAM allocator for Lua to reduce internal memory pressure
|
||||
ctx->L=lua_newstate(lua_psram_alloc, NULL);
|
||||
if(!ctx->L){ printf("[LuaGame] lua newstate fail\n"); vTaskDelete(NULL); return;}
|
||||
luaL_openlibs(ctx->L);
|
||||
register_sys(ctx->L);
|
||||
@@ -527,14 +548,27 @@ static void lua_init_task(void* arg){
|
||||
}
|
||||
// Detect Pico API by content before loading
|
||||
bool detected_pico = false;
|
||||
bool needs_audio = false;
|
||||
if(src_buf){
|
||||
if(strstr(src_buf,"renderer.")!=NULL || strstr(src_buf,"INPUT.")!=NULL){
|
||||
detected_pico = true;
|
||||
}
|
||||
if(strstr(src_buf,"sfx")!=NULL || strstr(src_buf,"tone")!=NULL){
|
||||
needs_audio = true;
|
||||
}
|
||||
} else {
|
||||
if(strstr(embedded_breakout_lua_src,"renderer.")!=NULL){
|
||||
detected_pico = true;
|
||||
}
|
||||
if(strstr(embedded_breakout_lua_src,"sfx")!=NULL || strstr(embedded_breakout_lua_src,"tone")!=NULL){
|
||||
needs_audio = true;
|
||||
}
|
||||
}
|
||||
if(needs_audio){
|
||||
printf("[LuaGame] audio needed, init SfxEngine\n");
|
||||
audio_init();
|
||||
} else {
|
||||
printf("[LuaGame] audio not needed, skipping SfxEngine to save RAM\n");
|
||||
}
|
||||
|
||||
int st;
|
||||
@@ -746,6 +780,14 @@ static void touch_event_cb(lv_event_t* e){
|
||||
if(ly>=max_h) ly=max_h-1;
|
||||
ctx->touch_x=lx; ctx->touch_y=ly;
|
||||
}else{ctx->touch_x=pt.x; ctx->touch_y=pt.y;}
|
||||
if(code==LV_EVENT_PRESSED){
|
||||
// Top-right corner 40x40 as exit gesture (since no toolbar)
|
||||
if(ctx->touch_x > max_w - 40 && ctx->touch_y < 40){
|
||||
printf("[LuaGame] exit gesture top-right tap -> stopping app\n");
|
||||
tt_app_stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(code==LV_EVENT_PRESSING||code==LV_EVENT_PRESSED||code==LV_EVENT_CLICKED) ctx->touch_pressed=true;
|
||||
else if(code==LV_EVENT_RELEASED||code==LV_EVENT_PRESS_LOST) ctx->touch_pressed=false;
|
||||
}
|
||||
@@ -807,22 +849,18 @@ static void app_on_show(AppHandle app,void* data,lv_obj_t* parent){
|
||||
lv_obj_remove_flag(cont,LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_style_radius(cont,0,0);
|
||||
ctx->canvas=lv_canvas_create(cont);
|
||||
lv_canvas_set_buffer(ctx->canvas,ctx->fb,GAME_W,GAME_H,LV_COLOR_FORMAT_RGB565);
|
||||
lv_canvas_set_buffer(ctx->canvas,ctx->fb,ctx->fb_w,ctx->fb_h,LV_COLOR_FORMAT_RGB565);
|
||||
lv_obj_set_style_bg_opa(ctx->canvas,LV_OPA_COVER,0);
|
||||
lv_obj_remove_flag(ctx->canvas,LV_OBJ_FLAG_SCROLLABLE);
|
||||
ctx->label_layer=lv_obj_create(cont);
|
||||
lv_obj_set_size(ctx->label_layer,GAME_W,GAME_H);
|
||||
lv_obj_set_pos(ctx->label_layer,0,0);
|
||||
lv_obj_set_style_bg_opa(ctx->label_layer,LV_OPA_TRANSP,0);
|
||||
lv_obj_set_style_border_width(ctx->label_layer,0,0);
|
||||
lv_obj_set_style_pad_all(ctx->label_layer,0,0);
|
||||
lv_obj_remove_flag(ctx->label_layer,LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_remove_flag(ctx->label_layer,LV_OBJ_FLAG_CLICKABLE);
|
||||
// FPS label outside canvas, top of game_area
|
||||
ctx->fps_label=lv_label_create(ctx->game_area);
|
||||
lv_label_set_text(ctx->fps_label,"FPS --");
|
||||
lv_obj_set_style_text_color(ctx->fps_label, lv_color_white(),0);
|
||||
lv_obj_set_style_text_font(ctx->fps_label, lv_font_get_default(),0);
|
||||
// Label layer removed to save RAM - text now drawn directly to FB
|
||||
ctx->label_layer=NULL;
|
||||
// FPS label kept small but optional - remove to save RAM for solitaire
|
||||
// For now, keep disabled to save internal memory
|
||||
ctx->fps_label=NULL;
|
||||
// If you want FPS, uncomment:
|
||||
// ctx->fps_label=lv_label_create(ctx->game_area);
|
||||
// lv_label_set_text(ctx->fps_label,"FPS --");
|
||||
// lv_obj_set_style_text_color(ctx->fps_label, lv_color_white(),0);
|
||||
|
||||
lv_obj_add_event_cb(ctx->game_area,touch_event_cb,LV_EVENT_PRESSED,ctx);
|
||||
lv_obj_add_event_cb(ctx->game_area,touch_event_cb,LV_EVENT_PRESSING,ctx);
|
||||
|
||||
Reference in New Issue
Block a user