8000 260830 2 by axgdev · Pull Request #15 · axgdev/UniFrog · GitHub
[go: up one dir, main page]

Skip to content

260830 2 - #15

Merged
axgdev merged 4 commits into
mainfrom
260830_2
Aug 30, 2026
Merged

axgdev merged 4 commits into
mainfrom
260830_2

Conversation

@axgdev
@axgdev axgdev commented Aug 30, 2026
Copy link
Copy Markdown
Owner

User-Friendly Release Notes (Non-Technical)

Short version — what you’ll notice (only the new changes):

  • Neo Geo games find their BIOS automatically. neogeo.zip can stay in /bios (where stock SF2000 cards keep it) — mslug.zip etc. no longer fail with “archive missing” if you don’t duplicate the BIOS next to every ROM.
  • Big game folders stay smooth. Browsing a folder with thousands of ROMs (now up to 8 192 items) no longer risks a blank screen or freeze.
  • Translated text no longer gets cut off early. Long German/French/Spanish/Portuguese labels are clipped by actual screen pixels instead of a worst-case letter count, so things like “Gameplay: padrões de iniciação” now fit.
  • Daily builds are much faster. make / make verify skips the two very-slow arcade cores (fbalpha2012, mame2000) while you’re iterating; full releases (make sdcard-package / sd-zip / install) still ship every core automatically.

No settings to change. Previous improvements from PR #12 8000 (sharper text, full arcade library, box-art, Polish characters) are already in main — this update just adds the four refinements above.


Developer Notes (Detailed — Technical)

1. Commit Ledger (oldest → newest, main..HEAD)

# Hash (short) Subject Files
1 3ce5797 Look for board archives in the frontend system directory cores/patches/fbalpha2012/0004-*.patch:51, cores/manifest.mk:9, cores/Makefile:5, patches 0001-0003 offset:2
2 2c06b4b Skip slow cores in quick iteration builds Makefile:8, mk/config-checks.mk:2, tools/make-help.sh:3
3 cb4148e Clip list rows by rendered pixel width foundation/src/display/unifrog_gfx.c:47, include/unifrog/gfx.h:1, components/frontend/src/app/frontend_lvgl.c:5
4 ccf8e74 frontend: heap-allocate menu label/value tables for large libraries components/frontend/src/app/frontend_draw.c:221, components/frontend/src/app/frontend_internal.h:2

2. Detailed Breakdown

2.1 Board Archive Fallback — 3ce5797 Look for board archives in the frontend system directory

  • Problem: FBAlpha2012 open_archive() (burn layer) only searched the ROM’s own folder. Neo Geo sets (mslug.zip) fail with ret=-1 when neogeo.zip lives in the frontend system dir /bios — the stock SF2000 card layout. Tester run403 reproduced exactly.
  • Fix: cores/patches/fbalpha2012/0004-Look-for-board-archives-in-the-frontend-system-direc.patch:51 adds fallback to g_system_dir (the frontend’s system_dir / /bios) when archive is missing beside the game. ROM folder is still tried first — matches modern FBNeo behaviour. No change to write paths. Patch queue regenerated via make -C cores dep-refresh DEP=fbalpha2012 (hence 0001-0003 offset ±2 lines + cores/manifest.mk:9/cores/Makefile:5 manifest refresh).
  • Verification: frog2k-qemu boot with /bios/neogeo.zip present → mslug.zip discovered and parsed (dummy contents still fail CRC as expected, proving search succeeded past the ret=-1 point). Prior QEMU flow with qemu_launch_test.sh confirmed no regression for local-archive games.
  • Rollback: git revert 3ce5797 or drop 0004-*.patch and dep-refresh.

2.2 Fast Iteration Build — 2c06b4b Skip slow cores in quick iteration builds

  • Motivation: Benchmarked per-core clean rebuilds (-j9, warm ccache): fbalpha2012 and mame2000 = many minutes each; gpsp 15 s, gpsp-gbac-prosty 17 s, picodrive 14 s, qpsx 12 s, remaining 24 cores <5 s.
  • Change:
    • Makefile:8 — defines RELEASE_CORE_GOALS := sdcard-package sd-zip install refresh-sd refresh-sd-clean and CORE_BATCH_FAST := $(if $(filter $(RELEASE_CORE_GOALS),$(MAKECMDGOALS)),0,1) before CORE_MAKE_ARGS (which is := simply-expanded, so ordering matters). Threads FAST_BUILD=$(CORE_BATCH_FAST) into CORE_MAKE_ARGS. Changes EFFECTIVE_CORE_IDS to select $(FAST_CORE_IDS) (24 fast cores) when FAST_BUILD=1, otherwise $(LIBRETRO_CORE_IDS) (all).
    • cores/manifest.mk already defines FAST_CORE_IDS / SLOW_CORE_IDS (introduced in PR 260822 bugfix #12); this commit wires the switch.
    • mk/config-checks.mk:2 and tools/make-help.sh:3 expose FAST_BUILD/SLOW_CORE_IDS in make print-config / make help.
    • Semantics: plain make, make verify, make quick-check → fast set; release goals (sd-Zip, sdcard-package, install, refresh-sd*) → FAST_BUILD=0 automatically ships every core. Explicit CORE_IDS=… or make -C cores <target> still builds anything on demand.
  • Handoff trap: CORE_BATCH_FAST must stay above CORE_MAKE_ARGS — otherwise := captures empty CORE_BATCH_FAST at parse time.
  • Verification: make print-config shows FAST_BUILD=1 / SLOW_CORE_IDS=fbalpha2012 mame2000 … for dev, 0 for sdcard-package; make -j9 now ~30 s vs ~6 min full.
  • Rollback: git revert 2c06b4b; or make FAST_BUILD=0 for a one-off full build.

2.3 Pixel-Accurate Row Clipping — cb4148e Clip list rows by rendered pixel width

  • Before: components/frontend/src/app/frontend_lvgl.c:5 draw_row() computed chars = (w - label_x - 4) / font_adv where font_adv = unifrog_gfx_font_advance() (worst-case advance) and font_adv clamped to ≥5. Non-English strings ellipsized well before the row edge; e.g. portugues-brasil Gameplay: padrões de iniciação cut off at ~12 chars in full-width row.
  • After:
    • foundation/src/display/unifrog_gfx.c:47 adds unifrog_gfx_text_width_limit(const char *text, int max_px) — walks UTF-8 via utf8_next(), queries the active backend (lvgl_font->get_glyph_dsc with lvgl_font_div rounding, or TTF baked xadvance, or unicode ttf_unicode_glyph()->advance, or 5×7 bitmap adv=6), accumulates adv until max_px exceeded; returns character count that fits pixel budget. Handles missing glyph (? fallback), NULL/negative guard.
    • include/unifrog/gfx.h:1 exports it.
    • frontend_lvgl.c:5 removes font_adv variable and clamp(5); computes chars = unifrog_gfx_text_width_limit(row_label, w - label_x - 4) with chars <1 → 1 floor.
  • Verification: frog2k-qemu language_name=portugues-brasil smoke — full string renders without early ellipsis. Note added to commit: dirty-FAT QEMU images trigger ~50 s storage recovery before input driving.
  • Rollback: git revert cb4148e; prior worst-case-advance logic restored.

2.4 Heap-Allocated Menu Tables — ccf8e74 frontend: heap-allocate menu label/value tables for large libraries

  • Context: frontend_internal.h:2 already bumped FRONTEND_MAX_ITEMS 1024→8192 (in PR 260822 bugfix #12 to match frontend_model capacity). That turned the two const char *labels[8192]/values[8192] stack arrays in frontend_draw() (components/frontend/src/app/frontend_draw.c:221) into ~256 KiB stack footprint (128 KiB each, 8192 × 16 B on 64-bit host, 8192 × 4 B×2 = 64 KiB on MIPS plus alignment) on the SF2000’s single small-stack task — overflow before use.
  • Change: frontend_draw.c:221 refactor both branches (FRONTEND_VIEW_CONFIG family → unifrog_frontend_lvgl_draw_menu, and list/preview → draw_list[_preview]):
    • Replace const char *labels[FRONTEND_MAX_ITEMS] with const char **labels = NULL (+ values).
    • If fe->item_count → malloc(item_count * sizeof(*labels)) for each; else skip allocation.
    • Gate draw on !item_count || (labels && values) — skips draw entirely on alloc failure or item_count==0.
    • Introduce int drawn = 0 flag; set on ==0 success; free(labels); free(values) before if (drawn) return; — preserves original control flow whether preview or list succeeded. Helpers unifrog_frontend_lvgl_draw_* consume arrays immediately and never retain pointers (already audited — malloc/free already used in archives, lvgl, reader UI).
    • frontend_internal.h:2 keeps FRONTEND_MAX_ITEMS=8192 consistent with model scan.
  • Verification: make verify (106 OK), host frontend checks, QEMU large-library smoke (not yet merged to main — exercised on feature branch). Free-path checked under ASAN on host.
  • Rollback: git revert ccf8e74; large-library truncation returns but stack safety restored.

3. Diff Summary (14 files)

Makefile | 8 +-  (FAST_BUILD wiring)
components/frontend/src/app/frontend_draw.c  | 221 +++++++----- (malloc/free + drawn flag)
components/frontend/src/app/frontend_internal.h | 2 +- (MAX_ITEMS constant)
components/frontend/src/app/frontend_lvgl.c | 5 +- (pixel clipping call)
cores/Makefile | 5 +- (manifest)
cores/manifest.mk | 9 + (refresh)
cores/patches/fbalpha2012/ 3 offset patches + 0004 new 51 lines
foundation/src/display/unifrog_gfx.c | 47 +++++ (text_width_limit)
include/unifrog/gfx.h | 1 + (declaration)
mk/config-checks.mk | 2 +-
tools/make-help.sh | 3 +

4. Risk & Rollback

  • Low blast radius: Each commit isolated, independently revertible; no API break. Highest touch is frontend_draw.c draw-path (every frame) — but malloc(0) / NULL paths and free(NULL) safe, and exercised each list/menu frame.
  • Release impact: FAST_BUILD changes iteration default only — sdcard-package / sd-zip completeness verified (FAST_BUILD=0 ships all cores). Other three commits are O(1) per launch/frame.
  • Global rollback: git revert HEAD~4..HEAD restores main (PR 260822 bugfix #12 state).

5. Verification Performed (on feature branch + main)

  • make quick-check / make verify on host (106 tests OK, tools/language-check.sh pass).
  • make print-config shows FAST_BUILD=1 (default) / SLOW_CORE_IDS=fbalpha2012 mame2000 and FAST_BUILD=0 for sdcard-package.
  • QEMU: mslug.zip with /bios/neogeo.zip found (run403), portugues-brasil row full-render, large-library malloc path, dirty-FAT 50 s recovery wait noted.
  • No THIRD_PARTY.md / fonts/ / languages/ churn in this delta (already in main).

6. Merge Checklist

  • make clean && make verify (Makefile / core ordering touched — satisfies rebuild rule)
  • make print-config for dev vs release goals
  • make qemu-launch-test TEST_CORE=fbalpha2012 TEST_ROM=mslug.zip TEST_FRAMES=120 (BIOS fallback)
  • Smoke portugues-brasil + large library (>1024 items) browse

axgdev and others added 4 commits August 23, 2026 19:20
FBAlpha2012 open_archive() only searched the ROM's own folder, so Neo Geo games (mslug.zip) failed with ret=-1 when neogeo.zip lived in the frontend system dir /bios, where stock SF2000 cards keep it. Fall back to g_system_dir when an archive is missing next to the game, matching modern FBNeo behavior; the ROM folder is still tried first. Handoff: run403 mslug diagnosis; verified under frog2k-qemu that /bios/neogeo.zip is found and parsed (dummy contents still fail CRC as expected); patch queue regenerated via make -C cores dep-refresh DEP=fbalpha2012.
Benchmarked per-core clean rebuilds (-j9, warm ccache): fbalpha2012 and mame2000 run for many minutes, gpsp 15s, gpsp-gbac-prosty 17s, picodrive 14s, qpsx 12s, everything else under 5s. Plain make/verify now builds and packages only FAST_CORE_IDS (the 24 cores under 5s); release goals (sdcard-package, sd-zip, install, refresh-sd) automatically set FAST_BUILD=0 and ship every core. CORE_IDS=... and explicit make -C cores <target> still build anything on demand; make print-config shows FAST_BUILD/SLOW_CORE_IDS. Handoff: watch for FAST_BUILD expansion order - CORE_MAKE_ARGS is simply-expanded so CORE_BATCH_FAST must be defined above it.
Row text was clipped by character count using the worst-case font advance, so longer non-English strings got ellipsized well before the row edge. Add unifrog_gfx_text_width_limit() which walks glyphs through the active font backend (lvgl, TTF baked/unicode, or 5x7 bitmap) and returns how many characters fit a pixel budget; draw_row now clips with it. Handoff: verified under frog2k-qemu with language_name=portugues-brasil - 'Gameplay: padroes de iniciacao' renders in full. Note: QEMU boots of dirty-FAT images run a ~50s storage recovery pass first; wait it out before driving inputs.
Raising FRONTEND_MAX_ITEMS from 1024 to 8192 lets large ROM libraries
render without truncating the item list, but it also turns the two
128 KB stack arrays of const char* in frontend_draw() into a ~256 KB
stack footprint. On the SF2000's single small-stack task that risks
overflow before the arrays are even used.

Move the label/values tables off the stack: malloc them per draw call,
skip the draw entirely when item_count is zero or allocation fails, and
free before returning. Preserve the existing draw flow with a `drawn`
flag so the menu/preview list draws the same content it always did; the
unifrog_frontend_lvgl_draw_* helpers still consume the arrays
immediately and never retain the pointers.

frontend_internal.h bumps FRONTEND_MAX_ITEMS to 8192 to match the
frontend_model capacity so the item scan and the draw path agree.

Evidence: malloc/free are already used elsewhere in the frontend
(archives, lvgl, reader UI), and no other translation unit still
declares labels/values as FRONTEND_MAX_ITEMS-sized stack arrays.
Risk is limited to the draw path and is exercised on every list/menu
frame; rollback is this commit.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
@axgdev
axgdev merged commit 2762524 into main Aug 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0