Repository navigation
Conversation
…in and achievement views - EmulatorCatalog: per-emulator Android package ids, launch styles, RetroArch cores - RomLink model + IRomLinkStore (atomic JSON) and RomLinkRules (generation/extension → emulator) - IEmulatorLauncher implemented on Android: RetroArch RetroActivityFuture extras, melonDS EmulatorActivity PATH extra, VIEW+URI fallback, library screen for emulators without a handoff - Emulators tab: one chip per emulator with install/link state, tap links, Link all installed - Cartridge identity menu: Play (launch ROM), Link ROM…, Unlink ROM - RetroAchievements: credential store in secure storage, web API client (API_GetGameInfoAndUserProgress, API_GetGameList, API_GetUserSummary), offline progress cache, Gen 1-5 game resolution by console + edition-exact title match, Awards page with sign-in and per-game achievement cards - Home: Emulators and Awards cards; manifest gains INTERNET and package <queries> Co-authored-by: Varonal <Varonal@users.noreply.github.com>
- TrophyEngine: pure rules turning SaveScanFacts (dex caught/seen/total, shiny species held, Pokémon owned, playtime hours, dex percent) into TrophyStates - TrophyCatalog: the 37 mainline games (Gen 1-9) with uniform ladders per generation — dex milestones, spotter tiers, shiny hunter, playtime, collector, and Dex Master - JsonTrophyStore: atomic JSON persistence; unlocks are permanent and locked progress keeps its best measured value; RemoveGame clears one game's states only - TrophyScanService: reads every linked save through the engine (same path as the Museum's dex editor) and updates the store - TrophiesPage: one overview card per linked game (percent, unlocked/total), tap or A for the detailed ladder, green unlocked rows with measured progress - Home gains the Trophies card; 30 domain tests cover the engine, catalogue and store Co-authored-by: Varonal <Varonal@users.noreply.github.com>
Emulators tab, ROM linking and launcher, RetroAchievements integration
…watcher - TrophyKind.Manual: feats the bytes cannot prove (champion, bosses, event legendaries), per-generation ladders in TrophyManualCatalog; the row confirms, never scans, and relocking forgets the state (ITrophyStore.Remove) - TrophiesPage: manual rows open a confirm dialog (unlock/relock), scan ladders and manual ladders share one id space - Second screen: SecondScreenOwner.Trophies claims the lower display while the Trophies page is open; TrophyLadder payload feeds a new TrophiesLadderView (title, percent, unlocked/locked rows) that swaps in like the Autopilot route map - TrophyWatcherService: on app resume (typically back from an emulator) the linked saves are re-scanned off the UI thread and newly unlocked trophies are announced once; AndroidTrophyNotifier shows a channel notification (InboxStyle, Pokéball small icon), POST_NOTIFICATIONS added to the manifest - 12 new domain tests: manual ladders per generation, manual never unlocks from scans, id-space uniqueness, champion in every game, Remove isolation Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The Domain's Describe rule must not reach into the App's display names; it now uses the catalogue's own kind label, so the Domain builds standalone again. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…easure test EmulatorsPage needs PKForge.App.Services for PadButton/IPadHandler (removed with an overzealous cleanup); the measure theory now asserts the kind's own number instead of a threshold-derived value that mixed up caught and threshold cases. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…ixes - SaveIdentitySheet/AndroidEmulatorLauncher: using PKForge.App.ViewModels (SaveDescriptions) - SaveIdentitySheet: rename the Play binding variable (CS0136 shadowing) - AndroidEmulatorLauncher: Java.Lang.SecurityException (CS0246) - AndroidTrophyNotifier: pin NotificationManagerCompat nullability, BigTextStyle instead of the InboxStyle minefield (CS8602) - HttpRetroAchievementsClient: HasString helper — DateEarned nullability (CS0019) - TrophiesPage: explicit List<TrophyDefinition> instead of the spread expression (CS9176) - EmulatorsPage: ScaleToAsync, ScaleTo is deprecated (CS0618) Co-authored-by: Varonal <Varonal@users.noreply.github.com>
SaveIdentitySheet carried the ViewModels using twice (my dedupe pattern did not match the insertion order); the launcher and the notifier now pin Platform.AppContext and the notification builder instead of dereferencing nullable bindings. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
Every NotificationCompat setter returns Builder? in the AndroidX binding, so the fluent chain was four nullable dereferences; the builder is now pinned once and configured one call per statement. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…t strings - ConsoleEmulatorLink: one emulator per console, chosen among the installed ones in the Emulators tab's new console section; the library and the cartridge ROM link read it first, so no save is needed to bind a console to an emulator - AndroidRomScanner: direct filesystem scan of the ES-DE tree (/storage/emulated/0/ROMs, retrogamecorps/ES-DE-Directories layout) — Pokemon-named files per console folder, edition parsed out of the file name; MANAGE_EXTERNAL_STORAGE in the manifest and the All-files settings screen opened once on first launch - RomLibraryPage: one Scan button over every console folder, one Play row per ROM that launches through the console's bound emulator (path launch, no SAF) - The cartridge Link ROM menu offers the library's matching ROM first, the SAF picker as the manual fallback - AppStrings + LanguageRules: French by default (persisted choice over the device locale), covering the new surfaces; +29 domain tests (name parsing, console rules, bindings store, language fallback chain) Co-authored-by: Varonal <Varonal@users.noreply.github.com>
JsonRomLibraryStore.Persist passed the nullable _path straight to File.Move; the console store's pattern check is now applied there too. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…ue-type enums FirstOrDefault over EmulatorKind returns RetroArch (the 0 default) when nothing is installed, so the ?? never fired and a nullable pattern could not match a value type; the library launch and the cartridge link now compare against default explicitly. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
AppStrings grows the Home surfaces (games, bank, settings, link and storage menus, rescan, scan report, share logs, second screen, music, misc, filter, quit dialog); the switch cases match on the AppStrings values so FR and EN both route correctly. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
SavePickerViewModel's status lines (scan progress, link results, connection, per- emulator folder guidance) and SaveIdentitySheet's whole menu (open, play, link ROM, rename, color, set game, hide, reset, read-only) now read from AppStrings; the constants became localized properties and the switch cases match on their values. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The trophies scan readouts and confirm flows, the RA sign-in/sign-out/status lines (view and view model), and the restore-points page (title, dialogs, hardcore duplication-risk flow) all read from AppStrings now. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The slot action menu (summary, edit, evolve, Poképark, move, duplicate, bank moves, exports, QR, RNG, lock/release), the legality repairs, the box manager and the sort dialogs now read from AppStrings; every display/case pair stays coherent (the when clauses parenthesise the ternaries). Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…linking From the PlayHub bundle (the same app's parallel phase): - Launcher: one URI per launch (content ids pass through, plain paths become file://), RetroArch gets its full documented contract (EXTRA_CONTENT + RETROARCH_LOAD_CONTENT_PATH + EXTRA_GAME_LABEL + EXTRA_CORE_PATH with the generation's core, ActionMain + data+type) instead of the bare RetroActivityFuture extra that black-screened; melonDS also answers its F-Droid package (io.github.melonds), Azahar answers org.azahar.azahar, Eden also answers Sudachi, yuzu, Ryujinx and Skyline - EmulatorSaveFolders + DirectSaveScanner: the standard save folders per emulator (RetroArch/saves, melonDS, Azahar, Eden, ...), so linking an emulator never asks 'which folder?' — the tap scans them directly and the SAF flow only runs as the fallback, with the expected folders named in the status line - The library page gets the PlayHub card design: artwork (GameArt) with the cartridge mark as fallback, generation · console subtitle, rounded Paper cards - Manifest: the new packages are visible to the package queries Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The rewritten launcher logged through bare AppLog (Services.AppLog), the Home menus left a bare Fr after the i18n pass, and the file-name converter's nullable pattern kept the variable unassigned on the false branch. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…le catalog Launcher, back to each family's documented contract (the generic URI handoff broke the working ones): RetroArch → explicit RetroActivityFuture + ROM + LIBRETRO + CONFIGFILE extras (the libretro CLI contract); melonDS → EmulatorActivity + PATH (its README contract); Azahar/Citra/Eden → ACTION_VIEW with the ROM URI so the game loads instead of just opening the app. Library page: the row's BindingContext was never set (only the artwork had one), which is why the cards showed images without text; now every binding reads the row. The list shows the whole catalog with a colored owned/missing label — owned games first with their ROM and console subtitle, the rest as muted missing cards. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…ork everywhere Launcher: PlayHub's exact approach — SetPackage on every intent, never an explicit ComponentName (a component that does not match the installed build dies silently with SecurityException). RetroArch: MAIN + ROM data + EXTRA_CONTENT pair + core hint; melonDS: VIEW + PATH extra, package-scoped; Azahar/Citra/Eden: VIEW with the ROM URI so the game loads. Nothing resolving opens the emulator's own library. Library: catalog order (Gen 1-9, release order), artwork loads on every card (owned and missing) with the cartridge mark as placeholder — the images without text came from the row's missing BindingContext, now every binding reads the row. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
Scope labels (whole bank / this box), the slot actions (summary, duplicate, release, exports, Showdown paste, create), and the create/paste era-picker flow — the goto case became an upfront session bootstrap so the switch routes on the translated values (goto case needs a constant). Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…e catalog
melonDS: back to VIEW + URI (the PlayHub contract that loaded games); the PATH
extra is the desktop/Pegasus contract and the installed builds ignore it, which
is why the emulator opened without the game.
RomNameRules: the scanner now recognises No-Intro release numbers
('1636 - Pokemon Emerald (Independent).gba'), bare edition names ('emerald.gba')
and French dumps ('Version Émeraude', 'Rouge Feu'); FrenchEditionName maps every
French edition to the catalog's English one (art, trophies and RA all key on it),
so French GBA ROMs light up in the library instead of staying grey.
Home wizard translated (welcome, get started, which-version).
Co-authored-by: Varonal <Varonal@users.noreply.github.com>
- RomLibraryPage: the _roms collection was write-only (the launch reads the row's rom directly); removed, along with its unused import - EmulatorsPage: the direct save scan built a new DirectSaveScanner per tap through the service locator; the engine comes through the constructor now and the scanner is a field, like every other dependency - SaveIdentitySheet: the ROM menu's remaining literals translated (pick a file instead / pick a ROM file / the chooser hint) - Tests: the GameName and LooksLikePokemon cases are consolidated into FrenchEditionNameTests (English, French, No-Intro, bare names, rejects non- Pokémon files) — 22 cases locking the parser chain; the duplicated theories in RomNameRulesTests are gone, its generation map stays Co-authored-by: Varonal <Varonal@users.noreply.github.com>
EmulatorsPage: the clean-up pass renamed the second 'folders' local into the same
scope; it is 'expected' now (and the stale duplicated status lines are gone).
Two real bugs the 5 failing tests exposed:
- JsonConsoleEmulatorStore.Find used GetValueOrDefault, which returns RetroArch
(the enum's 0) for an unset console: every unbound console read as bound to
RetroArch. TryGetValue now answers null for a missing binding.
- FrenchEditionName.ToEnglish returned the file's own casing for a bare English
name ('emerald.gba' showed 'emerald'); the catalog casing is restored.
The three remaining failures were stale expectations, updated to the catalogue's
current contracts: Azahar and Eden document a VIEW handoff (the game loads), and
melonDS's primary package is the F-Droid io.github.melonds (the Play fork follows
in PackageIds).
Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…uration Azahar: the vanilla build's package is org.azahar_emu.azahar (the ID changed in 2125.0; the Play build kept io.github.lime3ds.android) — 'Azahar not linked' was the catalogue naming a package nothing installs. The 3DS extension order puts .cci first: Azahar dropped .3ds support. melonDS: the Beacon-verified configuration — explicit EmulatorActivity component, ROM as data, plus the 'uri' and 'PATH' string extras together. One caveat its README states: the ROM must appear in melonDS's own library first. RetroArch: the content extras take a plain ROM path, never a file:// URI — the URI made it open and idle on a black screen. Manifest: the vanilla Azahar package joins the queries. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The launch failure had one root cause: FLAG_GRANT_READ_URI_PERMISSION does nothing on file:// URIs — the grant exists only for ContentProvider URIs. Every emulator received an unreadable URI and opened its library instead of the game. The launcher now serves ROMs through a FileProvider (content://), keeping the plain path in the RetroArch/melonDS string extras where those emulators read paths themselves. The overlapping text on the unowned game cards and both Emulators rows: the Grid children never had their columns assigned, so text stacked over the artwork. The 3DS scan also accepts the n3ds and 3dscloud folder names. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The upstream README described the save editor; this one leads with what the fork adds: the emulator/ROM launcher, the trophies/museum pipeline and the planned game companion, with a checked roadmap (done/in progress/planned) and the local build instructions. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The tools menu (battle prep, bag, world, trainer card/records/profiles), the slot fields (species, shiny, held item, gender), the exports/imports (Showdown, modified save, share as file), the box operations (sort, select, empty, delete) and the summary menu — with the display/case pairs kept coherent and the already-translated ternaries un-nested. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
While an emulator owns the foreground, PKForge's lower screen shows the launched game's companion: its name, dex progress and restore points. The Play sites (cartridge menu and library) start the companion after a successful handoff; the watcher's resume scan stops it when the player comes back. The companion yields to nothing — when it is up, every PKForge surface hides (the emulator is in front). - GameCompanion record + IGameCompanionStore (Domain), GameCompanionStore (App, observable session state), GameCompanionView (the lower-screen surface) - SecondScreenOwner.Companion joins the routes; the swap reads the store directly rather than the claims stack (no PKForge page is in front during emulation) - StartForGameAsync is fully async: the restore points come from IBackupService, the dex fills in with the watcher's first scan back Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The sort-criteria and gender switch expressions got translated labels as arm patterns, which C# rejects (a switch arm needs a constant or a pattern). Both become var/when arms comparing the translated label, the same shape the switch statements already use. A sweep confirms no other ternary sits in a switch-arm position anywhere in the Views. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
- The locked-boxes guard had its translated labels without parentheses, so the ternary bound to the || instead of the ==: parenthesised comparisons now. - The companion pattern variable 'active' was only definitely-assigned inside the pattern but read after the if: the store and its Current are separate locals. - GameCompanionView was missing the Services using (AppStrings lives there). Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The bool flag cannot tell the compiler the nullable record is set; the pattern
'is { } shownCompanion' narrows it where it is used.
Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The content-loading extras (EXTRA_CONTENT/RETROARCH_LOAD_CONTENT_PATH/CONFIGFILE) were a different contract than the CLI one; the documented pair frontends use is ROM + LIBRETRO on a MAIN/LAUNCHER intent scoped to the package. The core hint is only sent when the generation names one (GB/GBC → gambatte, GBA → mGBA): a null LIBRETRO would load nothing, so unknowns let RetroArch pair the core itself. melonDS keeps the Beacon-verified component + data + uri/PATH extras. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The game will run in PKForge itself, in-process, so the companion reads its memory live (party, bag, battle) instead of waiting for a save scan. This commit lays the foundation; the build script produces the .so and the engine/UI come next. - Domain: IEmbeddedCore (load, runFrame, copyFrame, setKeys, readBytes, save/load state) + GbaKeys bitmask — the contract every surface programs against - Android: MgbaNative — P/Invoke over the flat C shim, int returns only (no C bool marshalling), UTF-8 strings, no struct layouts - tools/build-mgba: jni_bridge.c — the flat shim over mGBA 0.10.5's mCore API, every signature from core.h; one PkforgeCore handle (core + pinned video buffer, freed together); build.sh — pinned mGBA tarball, the PokeDaisy CMake flags, arm64-v8a, output packed by csproj as an optional AndroidNativeLibrary (absent library = the Play screen keeps its external-emulator path) Co-authored-by: Varonal <Varonal@users.noreply.github.com>
GitHub Action: on pushes touching the shim (plus a weekly cron), the ubuntu runner builds the mGBA 0.10.5 static lib and the JNI shim for arm64-v8a, verifies the ELF targets ARM aarch64, commits the .so into the app's Libraries/ (the csproj packs it as an AndroidNativeLibrary) and uploads it as an artifact. Hardening found on the way: - MgbaCore.cs was missing (the write that built it never landed) — restored, with the byte-level RGBA copy verified against interface.h (color_t is 0x00BBGGRR little-endian = R,G,B,X bytes = SkiaSharp's Rgba8888 row) - jni_bridge read_bytes: the block info lookup now bounds-checks against the block's end (not a compound literal), the memcpy offset stays inside the block - build.sh: the cmake --build target guess removed (build all; the static lib path is the standard output name), clang resolved through the NDK prebuilt dir with a find fallback, -landroid added, bash -n clean Co-authored-by: Varonal <Varonal@users.noreply.github.com>
Audit of the whole repo (Domain, Engine, Infrastructure, App) with full test runs - nothing left unverified. Fixes: - RomLinks referenced App's SaveDescriptions.EmulatorName, breaking the Domain build; EmulatorCatalog.Name(EmulatorKind) is now the single source of truth and SaveDescriptions.EmulatorName delegates to it. - ApplyEdit/ApplyInstructions/SetOriginalTrainerName passed untrimmed names to PKHeX setters, overflowing the per-format string buffers; nicknames and OT names are now trimmed to MaxStringLengthNickname/MaxStringLengthTrainer (10 Gen 1-5, 12 Gen 6+, 5 for Japanese Gen 1/2). LegalizerService's nickname restore uses the same trim. - TrophyScanService measured playtime from the shelf string even when the save has its own counter; the save's trainer stats now win. - AppUpdate prerelease comparison used ordinal string compare (beta.10 < beta.2); now SemVer: numeric identifiers compare numerically, numeric ranks below alphanumeric, more dot-identifiers win a shared-prefix tie. - HttpRetroAchievementsClient treated the mere presence of DateEarned as an unlock; RA's current API omits the field when locked, but older responses returned an empty string. Parsing moved to RetroAchievementsJson in Domain (unit tested): a unlock requires a non-empty string. Empty-object achievement sets (RA issue #484) and missing fields are handled. - App build breaks: EmulatorsPage missed using PKForge.App.Services (IPadHandler, PadButton); AndroidEmulatorLauncher missed using PKForge.App.ViewModels (SaveDescriptions) and caught System.SecurityException instead of Java.Lang.SecurityException; SaveIdentitySheet had a CS0136 shadowed local; EmulatorsPage used obsolete ScaleTo (CS0618 as error); TrophiesPage had an unused field (CS0169 as error); HttpRetroAchievementsClient had a duplicate using (CS0105). - Removed dead SaveEngine.UnboundNotEditable. - Fixed incoherent TrophyTests expectation (DexCaught measured 60, expected 59). Tests: - NicknameLimitTests: per-generation nickname/OT truncation round-trips through real blank sessions, incl. Japanese Gen 1 (6-byte buffers, kana-only table). - RetroAchievementsJsonTests: earned/locked/empty-string/null DateEarned, softcore-only, missing fields, empty set, id ordering, error shapes. - AppUpdateRulesTests: prerelease ordering cases. - RomLinkTests: stable emulator display names and RomLinkRules.Describe. Verified locally: Domain 952/952, Engine 992/992, Debug and Release APK builds (maui-android + Android SDK 36 + Temurin 17) all succeed. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
audit: fix build breaks, buffer overflows, RA parsing and SemVer compare
…into vibe/embedded-mgba-core Co-authored-by: Varonal <Varonal@users.noreply.github.com>
The PR #1 merge had taken only part of vibe/emulators-rom-launcher-ra: the 12 commits after 0f99547 (the in-game companion, the French pass, the launch fixes, the library page itself) never reached main, which is why main had neither RomLibraryPage nor the companion. This merge brings them in alongside the audit PR #2, and resolves TrophiesPage in favour of the column fix — without Grid.SetColumn the glyph, title and value all stack in column 0 (the reported one-column layout). Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…d Play wiring The option-A spike, complete enough to run a game end-to-end: - EmbeddedEngine: the emu thread paces at the GBA's exact 59.7275 Hz with an accumulating deadline (no drift), drains the core's audio into an AudioTrack (32768 Hz PCM16 stereo, ~116 ms buffer, blocking writes — the audio clocks the loop, the PokeDaisy-verified pattern), and publishes each frame as an SKBitmap - EmbeddedGameSession: the facade owning core+engine; TryStart returns null when the .so is absent so the external emulators stay the fallback - EmbeddedGamePage: integer-scaled pixel-crisp blit (letterboxed), the pad's IPadHandler/IPadReleaseHandler mapped to GBA bits (X/Y fold to B/A) - RomLibraryPage Play: GB/GBC/GBA try the embedded path first with the .sav beside the ROM, then fall back to the external emulator - TrophiesPage: the row's Grid columns were never assigned — the reported one-column layout; fixed - jni_bridge: the audio drain (blip_samples_avail/blip_read_samples verified against blip_buf.c's own source; interleaves L,R for AudioTrack's frame layout) Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…e SkiaSharp using - EmbeddedCore.cs had never landed on disk (the session's first write went missing, like MgbaCore.cs before it): the IEmbeddedCore contract and GbaKeys are restored verbatim, so MgbaCore's 'implements' resolves again - AllowUnsafeBlocks=true: the LibraryImport source generator emits unsafe interop stubs (SYSLIB1062); the App project was the only one without it - EmbeddedGamePage: SKPaintSurfaceEventArgs lives in SkiaSharp.Views.Maui, not .Controls — the using the existing SkiaSharp pages all carry Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…iaSharp 3 DrawImage, MemoryMarshal, IPadHandler interfaces, Path ambiguity Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…net10.0-android DiagnosticBuild) - AudioContentType has no Game member: use Music (enum members: Unknown/Speech/Music/Movie/Sonification) - Java builder Set* methods return Builder? and Build() returns nullable: assign to locals, null-forgive Build() - CA1416: AudioTrack.Builder requires API 23+ while minSdk is 21 — pragma disable around the builder, same pattern as AppUpdateService - SkiaSharp 3.116: SKCanvas.DrawImage needs SKImage, not SKBitmap — keep a SKImage view via SKImage.FromBitmap(frame) swapped under the frame lock - ByteBuffer.Order(ByteOrder) nullable param: null-forgive LittleEndian - Span<byte>.As<uint>() does not exist: MemoryMarshal.Cast<byte,uint> - EmbeddedGamePage: declare IPadHandler + IPadReleaseHandler so GamepadRouter.Push/Remove accept it - RomLibraryPage: System.IO.Path disambiguation vs Microsoft.Maui.Controls.Shapes.Path Verified: dotnet build PKForge.sln (0 warnings, 0 errors), DiagnosticBuild APK produced; unit tests show only the 2 pre-existing failures also present on main. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…lumn fix - Build libpkforge_mgba.so for arm64-v8a here (NDK r29, mGBA 0.10.5 static) and commit it: the APK now packs the shim (verified: lib/arm64-v8a/libpkforge_mgba.so in org.pkforge.app.debug.apk), so GB/GBC/GBA ROMs run in-process with no external emulator. jni_bridge.c: mgba-util/vfile.h -> vfs.h (0.10.5 header layout). - PokéDaisy live companion: LiveGbaCompanion reads the running core's SRAM at 0x0E000000 (SAV3 sector layout: active slot, dex flags at 0x28/0x5C, party at sector 1+0x234, playtime at 0x0C) and EmbeddedGamePage publishes a snapshot every second to GameCompanionStore.Live; the second screen shows it over the companion. - TrophiesLadderView: assign Grid columns explicitly (glyph/title/detail stacked in column 0 without Grid.SetColumn — the reported one-column layout). - README roadmap updated: native GB/GBA + live companion marked done, DS core next. - 5 new xunit tests for LiveGbaCompanion (dex/party/playtime, slot, capping, null paths). Verified: dotnet build PKForge.sln 0 warnings 0 errors; DiagnosticBuild APK contains the .so; LiveGbaCompanion tests 5/5; suite shows only the 2 pre-existing failures also on main. Co-authored-by: Varonal <Varonal@users.noreply.github.com>
Co-authored-by: Varonal <Varonal@users.noreply.github.com>
Co-authored-by: Varonal <Varonal@users.noreply.github.com>
Varonal
force-pushed
the
vibe/embedded-mgba-core
branch
from
October 30, 2026 16:43
04867fe to
db378b5
Compare
…ved for those consoles Root cause of 'lancer un jeu GBA ouvre RetroArch': the embedded path was a fallback tried *after* the bound/installed external emulator, and the Emulators tab still offered RetroArch/Linkboy/PizzaBoy for GB/GBC/GBA. - EmulatorKind.Embedded = 10 (new, appended — persisted values never renumbered): PKForge itself, 'installed' when libpkforge_mgba.so is packed (EmulatorCatalog.EmbeddedCoreAvailable, probed once at startup in MauiProgram). - ConsoleRules.EmulatorsFor + RomLinkRules.EmulatorsForRom: GB/GBC/GBA (Gen 1-3) now return [Embedded] only. DS/3DS/GC/Switch unchanged. - RomLibraryPage.LaunchAsync: GB/GBC/GBA go embedded first and only; the external path is unreachable for them (clear message if the .so is missing). - SaveIdentitySheet: Play on a linked Gen 1-3 ROM opens EmbeddedGamePage; linking a Gen 1-3 ROM stores EmulatorKind.Embedded; texts updated. - EmulatorsPage: GB/GBC/GBA console rows removed (no external binding offered). - RetroArch's advertised systems now 'DS' only; Embedded advertises GB/GBC/GBA. - Tests updated (RomLinkTests, ConsoleRulesTests): Gen 1-3 prefer Embedded, GB counts as installed with no packages. Verified: dotnet build PKForge.sln 0 warnings 0 errors; DiagnosticBuild APK still packs libpkforge_mgba.so; targeted tests pass (68/69 before the melonDS package-id fix, then full suite = only the 2 pre-existing ICU-less failures). Co-authored-by: Varonal <Varonal@users.noreply.github.com>
…/GBA) The previous commit removed GB/GBC/GBA rows and made EmulatorsFor return [Embedded], but the guard lived only at call sites and a stale persisted binding could still be read. Now the rule is centralized and enforced: - ConsoleRules.RunsInApp(console): single source of truth for consoles PKForge runs itself. RomLibraryPage.LaunchAsync, EmulatorsPage (row list + picker), and SaveIdentitySheet.LinkRomAsync all branch on it before ever touching IConsoleEmulatorStore or an installed external emulator. - EmulatorsPage.ChooseConsoleEmulatorAsync filters out EmulatorKind.Embedded from candidates, so even a hand-edited binding cannot offer it. - New tests: InAppConsolesNeverOfferAnExternalEmulator (GB/GBC/GBA candidates are exactly [Embedded]), ExternalConsolesAreNotMarkedInApp, and GenOneToThreeRomsHaveEmbeddedAsTheirOnlyRoute. Verified: build PKForge.sln 0 warnings 0 errors; DiagnosticBuild APK packs libpkforge_mgba.so; 79/79 targeted tests pass; full suites show only the 2 pre-existing ICU-less sandbox failures (green on CI). Co-authored-by: Varonal <Varonal@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.