Skip to content

Releases: moronigranja/alabaster-android

RadicalFish Ports v0.8.0

Choose a tag to compare

@moronigranja moronigranja released this 04 Oct 19:51

v0.8.0

One app, two games: the port now runs CrossCode as well as Alabaster Dawn, and it is called
RadicalFish Ports. Same package and key as before, so it updates in place.

  • CrossCode. A second, different engine (Cubic Impact 0.5): boots to its title screen in the desktop
    harness. On a phone its GPU cost, audio and pad mapping are still open.
  • An entry screen with a card per game — its own title art, both folder paths, its own saves folder,
    and a ⋮ with Help: what to copy and Create a home-screen link. A folder that has gone is
    marked, not silently claimed.
  • Saves in either shape: copy the game's save folder whole (Saves/…, Default/…) or its contents
    flat — the port reads both, and saves travel back to the PC with no renaming.
  • Keyboard for CrossCode: its bindings are indexed by the legacy keyCode, which the port now sets.
  • Picture position (Top/Centre/Bottom) for both engines, and dynamic sticks on the on-screen pad.
  • A new launcher icon — a circuit fish on a slate field, fit to the adaptive-icon safe circle.

Issues ·
fuller notes

Alabaster Dawn Android port v0.7.7

Choose a tag to compare

@moronigranja moronigranja released this 01 Oct 02:20

v0.7.7

The water was not being drawn on any device, and the port's own safety net was why.

  • Water, everywhere. The engine keeps v_barycentric alive with vec3(-1e30) in fragment shaders; the
    water fragments run at mediump, which cannot hold 1e30, so where the varying is garbage the branch
    fired and the fragment returned before drawing. The water shaders are served at highp in both stages now.
  • Water links on Mali again. Two lib/water.glsl uniforms took each stage's default precision; the water
    fragments are served with the vertex stage's — only on devices whose own compiler refused the game's
    declarations, because serving it elsewhere breaks Adreno's link instead.
  • The array lift is served on every device, instead of asking the document-start probe first: the probe
    can accept declarations the engine then refuses, and that costs a frozen boot (issue #5), while lifting is
    free — the same declarations, spelled the way the game's own vertex shaders spell them.
  • A shader the engine refuses now says which bytes it was served.
  • 40 fps rung on the battery switch's slider (20/30/40/45/60).
  • window= and canvas= in the diagnostics facts, for "the picture doesn't fill the screen" reports.

Issues ·
fuller notes

Alabaster Dawn Android port v0.7.6

Choose a tag to compare

@moronigranja moronigranja released this 30 Sep 21:52

v0.7.6

The shader the Mali phone in issue #4 still refused — and with it that phone's boot stall — now serves in the
one spelling its own compiler measured as accepted.

  • The post pass's ramp is named instead of constructed. analog-filter.frag builds its colour ramp as an
    array constructor passed as an argument (colorRamp(noise.r, vec3[5](…))). On that driver an array
    temporary inherits no element precision in any spelling of its brackets, which the phone's own self-test
    showed case by case: vec3[5](, the unsized vec3[](, and a qualified parameter all came back
    S0032: no default precision defined for variable 'vec3[5]', while naming the ramp and assigning it
    element by element compiles. The port serves that now — the game's own five values, in its order — and only
    to a device whose own compiler refused the game's declarations. That refusal was the whole of its boot
    stall (pending 105 (shader=1 …), first pending texturedpost/analog-filter).
  • The spelling self-test now asks what still answers something: each shader the port lifts, twice — the
    game's bytes and the port's — instead of fourteen candidate spellings the device has since settled.

Under ANGLE nothing changes on that device: the gate finds the game's own bytes compile there, and the
game boots and plays.

issue #4 ·
fuller notes

Alabaster Dawn Android port v0.7.5

Choose a tag to compare

@moronigranja moronigranja released this 30 Sep 16:01

v0.7.5

A fix to v0.7.4's new spelling test, found by running it on a real phone — and the same test now answers
cleanly.

  • Two defects in the spelling test, both visible only on hardware. One: game copies whose shader files
    use Windows line endings (the maintainer's own phone, and quite possibly others) made the multi-line
    cases come back unavailable while the single-line ones worked — the test now normalises line endings
    the way the port's own rewrite already did. Two: a case that could not be built put the word null into
    the shader it handed the driver, and the resulting syntax error read like a driver refusal. A case that
    cannot be built now fails as a whole and says so, instead of looking like a refusal.
  • Verified on a phone: the panel button, the case building, the compiles on the engine's own context,
    the record lines and the summary — shader self-test: 14 cases, 14 compile.
  • Everything else is the same as v0.7.4.

Using it: start the game first (the test needs the running page — the setup screen's Troubleshoot shows
the record but cannot run the test), then Back → Troubleshoot → Test shader spellings, and Share
what comes back.

Detail: FINDINGS §22.11,
fuller notes,
issue #4.

Alabaster Dawn Android port v0.7.1

Choose a tag to compare

@moronigranja moronigranja released this 30 Sep 13:19

v0.7.1

Two things: the battery switch grew the rates a phone actually needs, and the shader whose compilation
freezes the boot on Mali is served the spelling that driver accepts.

  • The frame-rate switch now has a rate slider — 20 / 30 / 45 / 60 fps, shown under the switch only
    while it is on, with the labels on a strip under the bar. The shim's requestAnimationFrame gate takes
    the number rather than a fixed 30, and because a display presents only on a vsync it takes the next
    vsync up
    : on a 60 Hz panel 45 is 30 (22.2 ms → the next vsync is 33.3 ms), on a 120 Hz one it is 40.
    Verified on the S22 Ultra (SM-S908U1, Android 16, release build over an older one, both folder
    grants kept): moving the slider changed the running game live, in one process, with no reload —
    20 → the on-screen readout and the shim's own count both 20 fps, 30 → 30 fps, 45 → 30 fps
    (that panel), 60 → 60 fps, switch off → 60 fps; the row appears and disappears with the switch,
    and the rate survives a switch off/on cycle and a relaunch (frame limit on: 20 fps,
    ENGINE fps: limited to 20 fps in the new pid). Behind it: FpsLimitTest and the shim harness'
    six cap checks among its 53.
  • A Mali front end that refuses the game's array declarations is served the spelling it accepts
    (issue #4). The device's own record named it: S0032: no default precision defined for variable 'vec3[5]' / 'vec4[4]' — this driver does not carry a shader's declared default precision onto an
    array written type[size] name, which is valid ES 3.0 (a strict front end and ANGLE accept all the
    served shaders, and the same bug is reported for other Mali generations in Godot and elsewhere). The
    port now serves the five fragment-stage files with the declarator spelling — vec4[4] waves →
    vec4 waves[4], the one vec3[5](…) constructor without its size, and the one array return type
    through an out parameter — and only to a device whose own compiler refuses them, decided by a
    document-start probe (shader arrays: the page's compiler rejects them -> lifting them, then one
    array declarations lifted in … per file). Verified by unit tests, glslangValidator on the expanded
    originals and the lifted ones, and a boot A/B in Chromium through the port's own shim (both boot
    complete, 1 757 resources, 154 shader compiles, 0 compile and 0 link failures, identical active
    uniforms and attributes for the four affected programs). Not confirmed on Mali hardware — this
    project has none, and the next record from that device is what closes it.

Alabaster Dawn Android port v0.7.0

Choose a tag to compare

@moronigranja moronigranja released this 30 Sep 04:16

v0.7.0

The device pass that issue #3 started: the shaders are served better on the GPUs phones actually
have, and two things the phone needed came out of it.

  • The GUI's shaded fills are no longer striped. The game's GUI shaders declare precision mediump float while every world shader is highp; desktop GL promotes mediump, a mobile GPU does not, and
    the GUI's screen-space and tiled maths then quantises into a visible stripe pattern on the shaded
    fills (the selected menu row, the slider track) at the same base colour the desktop build renders
    flat. The port now serves those four GUI shaders as highp — ES 3.0 guarantees it in both stages.
  • The terrain's grid of dots is served finer. The dots are the engine's own ordered dither — a 4x4
    threshold table indexed by the art pixel, discarded binary, so at a fade of 0.5 half the fragments
    are thrown away and the unlit layer behind shows. On a phone panel, where an art pixel is two or
    three device pixels, a 4-cell repeat reads as a grid over the terrain (issue #3). The engine's own
    solid.frag and the water's radial dither already index by the render pixel; those five shaders
    are now served that way too.
  • The port no longer rewrites shaders on devices that never needed it. ShaderSlots decided from
    the driver's reported MAX_VERTEX_UNIFORM_VECTORS, so a device at the GLES3 minimum of 256 got every
    vertex shader rewritten — even where its compiler packs two vec2 slots per vec4 and would have
    linked the game's own table, which is what Adreno does. The decision is now a link: the shim
    compiles the two shapes the game's shaders have and the port follows what actually links. On the
    Fold 7 the record reads 256-slot links, gui two-table links -> TEX_SLOT_COUNT 256 with nothing
    rewritten at all.
  • Reset resolution, in the port's Troubleshoot panel next to Share and Close. The Resolution
    option is the one setting that can leave the port unusable by being slow — the engine never caps it,
    and 2560x1440 renders 8.3x the pixels of the ladder's 960x540 default — so the button drops the
    game's stored value (it lives in the WebView's localStorage, not in the game's files) and the next
    start boots at the default rung. The record also carries the resolution it is running at now.
  • A switch to limit the frame rate to 30 fps, for battery. The port is GPU-bound, and the shim can
    gate the page's requestAnimationFrame — the engine's only frame driver — to one frame per interval;
    the game logic keeps its 60 Hz fixed step, because the engine's clock reads performance.now()
    itself. Verified live on the Fold 7: the readout went 30 fps · 960x540 → 60 fps · 960x540 →
    30 fps · 960x540 as the row was toggled, in one session, with no reload.
  • Exit leaves the app in the task list. The exit deliberately ends the process (a fresh WebView
    renderer is what makes the next launch clean), but it no longer finishes the task, which is what
    used to drop the app out of recents. dumpsys activity recents still lists it after an Exit, and
    tapping that card starts a new process on the setup screen.
  • A shader the device's compiler rejects now names itself in the record. The engine logs a failed
    compile as console groups — the file's path and the compiler's own message are the group titles —
    and the port only forwarded console.error/warn, so a device-only shader failure arrived as a line
    of shader code with the file and the reason missing. Both are in the diagnostics record now, which is
    what a report like the Mali one on the community needs. No fix for that report yet: the message is
    the missing piece, and the port now captures it.

Full release notes: docs/release-notes-0.7.0.md
Install, requirements and known limitations: README

Alabaster Dawn Android port v0.6.1

Choose a tag to compare

@moronigranja moronigranja released this 29 Sep 22:49

v0.6.1

A bugfix for the side menu's picture position: with the picture aligned Top or Bottom, mouse
clicks landed nowhere near the thing clicked. Centre was unaffected.

  • The port moved the picture where the engine could not see it. The engine's own mouse mapping
    (Input.getMouseCoordsC + DISPLAY_SCALE.transformMouse) reads the canvas element's offsetTop
    and then subtracts a centred letterbox (deltaY/2) from it — the engine believes the picture sits
    in the middle of the canvas element. The port changed only object-position, which moves the
    picture inside the element without moving the element, so every click was interpreted deltaY/2
    below the picture: half the black band. On a 1080x2340 phone at the default 640x360 rung that is
    866 px — the click lands on another part of the screen.
  • Now the element's layout box moves (top = desired − deltaY/2) and the picture stays centred
    inside it, which is the box the engine measures from, so both sides agree again. Works in both
    display scales (sharp-pixels off and on), is recomputed every frame, and changes nothing about
    the picture's size or where it is drawn — only where the input thinks it is.
  • Verified by booting the real engine in a browser and driving its own input pipeline with real mouse
    events: the same point on the picture now maps to the same game coordinate in Top, Centre and
    Bottom. The old code mapped the picture's centre to y = -280.8 instead of y = 180 in the same
    harness. node android/tools/test-shim-diagnostics.mjs grew 11 checks for this (24/24 green; 7 of
    them fail against the pre-fix shim).

Nothing else changed.

Full release notes: docs/release-notes-0.6.1.md
Install, requirements and known limitations: README

Alabaster Dawn Android port v0.6.0

Choose a tag to compare

@moronigranja moronigranja released this 29 Sep 15:57

v0.6.0

Mouse and keyboard now work in the game, and the port fixes a Back-press bug that made the side
menu unusable on Android 13+.

  • A mouse works. A click on the game was being swallowed by the on-screen pad — a mouse click is
    a touch event for Android's dispatch (MotionEvent.isTouchEvent(), libs/input/Input.cpp), and
    the pad claimed every DOWN while it was drawn. The pad now recognises a pointer tool
    (TOOL_TYPE_MOUSE) and returns false for it, so the click falls through to the WebView exactly
    like a finger on empty space. Hover and scroll already reached the page; they now also count as
    input.
  • A keyboard works. Keys already reached the page, but the engine matches its bindings on
    event.code alone and Chromium derives code from the scan code — a key event with no scan code
    arrives as code: "" and plays nothing. The port now dispatches the DOM event the page should have
    got, with a proper code/key, for every key it can name (letters, digits, arrows,
    Enter/NumpadEnter, Escape, Space, Tab, Shift/Ctrl/Alt, F1-F12); a key that carries a scan code keeps
    the WebView's own path. WASD/arrows move the character and Enter activates menus.
  • The overlay hides for both, not just for a controller: the side menu's switch is now
    "Hide pad with external input" and its status line "External input: active|idle". The stored
    preference key is unchanged, so existing installs keep their setting.
  • Back works again on Android 13+. The port registers an OnBackInvokedCallback for the gesture
    and also handled the Back key; on Android 13+ the framework delivers a Back key to both, so one
    press opened the side menu and closed it again in the same dispatch. The callback now owns Back
    from API 33 up, and the key is only acted on below 33. This is the "the physical Back button does
    not open the menu" report from an AYN Odin 3.

Verified on a Galaxy S22 Ultra (Android 16 / API 36): a mouse click on the title screen's New Game
highlights and opens it, a click and a key both hide the controls and the pill row, a held D walks
the character, touch still drives the pad, and turning the switch off leaves the pad drawn while the
mouse and keyboard are used. ./gradlew :app:testDebugUnitTest and
node android/tools/test-shim-diagnostics.mjs are green.

Full release notes: docs/release-notes-0.6.0.md
Install, requirements and known limitations: README

Alabaster Dawn Android port v0.5.1

Choose a tag to compare

@moronigranja moronigranja released this 27 Sep 01:54

v0.5.1

Fixes for running the game's Steam demo through the port, found by running it.

  • The demo's Resolution menu named resolutions it does not render. The port rewrites the game's
    resolution ladder to add a 960x540 rung; the demo's bundle has no such ladder (its own is left
    alone, correctly), but the option labels were rewritten anyway — 1280x720 → 960x540 and
    1920x1080 → 1280x720. The two rewrites now move together: a build that does not use the
    release's ladder keeps its own truthful labels. The release build is unchanged.
  • The demo no longer litters your saves folder. The demo-era engine builds its save paths
    Windows-style (\Saves\Default\); the bridge treated those as save-relative and SAF rewrote the
    illegal characters, creating _Saves_, _Saves_Default_, _Saves_Backups_, _Saves_Backups2_ in
    the folder you picked while the demo's own saves went nowhere. Both separators now resolve onto the
    same Saves/ layout, and mkdir is refused outside the save root like every other file call.
  • Removed a dead branch in the resolution-option rewrite (it computed a default and returned the old
    text, so it never did anything).

Full release notes: docs/release-notes-0.5.1.md
Install, requirements and known limitations: README

Alabaster Dawn Android port v0.5

Choose a tag to compare

@moronigranja moronigranja released this 27 Sep 01:36

v0.5

  • Exiting the game works. The title screen's Exit and System.quit were shim no-ops, so the
    engine hid its own menu and waited for a process exit that never came — the frozen picture that
    ends issue #1. Both now leave the app.
  • Exit ends the app process, so the next launch is a fresh process with a fresh WebView renderer.
    The old "swipe it out of recents first or the second start comes up black" workaround is gone.
  • The side menu (Back) is now one uniform, full-width, icon-led list — the whole row is the tap
    target, and the current picture position is a filled pill.
  • The port's version is on the setup screen and in the side menu's status block.
  • The record names the game's build too, not just the port's: game 0.1.0-10 Early Access.

Full release notes: docs/release-notes-0.5.md
Install, requirements and known limitations: README