Repository navigation
Releases: moronigranja/alabaster-android
Release list
RadicalFish Ports v0.8.0
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.
Alabaster Dawn Android port v0.7.7
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_barycentricalive withvec3(-1e30)in fragment shaders; the
water fragments run atmediump, which cannot hold1e30, so where the varying is garbage the branch
fired and the fragment returned before drawing. The water shaders are served athighpin both stages now. - Water links on Mali again. Two
lib/water.glsluniforms 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=andcanvas=in the diagnostics facts, for "the picture doesn't fill the screen" reports.
Alabaster Dawn Android port v0.7.6
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.fragbuilds 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 unsizedvec3[](, 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 pendingtexturedpost/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.
Alabaster Dawn Android port v0.7.5
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 wordnullinto
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
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'srequestAnimationFramegate 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 panel45is 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 both20 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 fpsin the new pid). Behind it:FpsLimitTestand 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 writtentype[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 onevec3[5](…)constructor without its size, and the one array return type
through anoutparameter — 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,glslangValidatoron 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
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 floatwhile every world shader ishighp; 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 ashighp— 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.fragand 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.
ShaderSlotsdecided from
the driver's reportedMAX_VERTEX_UNIFORM_VECTORS, so a device at the GLES3 minimum of 256 got every
vertex shader rewritten — even where its compiler packs twovec2slots pervec4and 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 reads256-slot links, gui two-table links -> TEX_SLOT_COUNT 256with 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'slocalStorage, 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'srequestAnimationFrame— 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 readsperformance.now()
itself. Verified live on the Fold 7: the readout went30 fps · 960x540→60 fps · 960x540→
30 fps · 960x540as 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 recentsstill 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 forwardedconsole.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
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'soffsetTop
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 onlyobject-position, which moves the
picture inside the element without moving the element, so every click was interpreteddeltaY/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-pixelsoff 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 toy = -280.8instead ofy = 180in the same
harness.node android/tools/test-shim-diagnostics.mjsgrew 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
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 returnsfalsefor 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.codealone and Chromium derivescodefrom the scan code — a key event with no scan code
arrives ascode: ""and plays nothing. The port now dispatches the DOM event the page should have
got, with a propercode/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
OnBackInvokedCallbackfor 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
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→960x540and
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
sameSaves/layout, andmkdiris 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
v0.5
- Exiting the game works. The title screen's Exit and
System.quitwere 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