Skip to content

feat(blackberry): add the Classic native QNX and Android Runtime hosts - #298

Merged
doodlewind merged 2 commits into
pocket-stack:mainfrom
HalfSweet:feat/blackberry-classic
Aug 20, 2026
Merged

feat(blackberry): add the Classic native QNX and Android Runtime hosts#298
doodlewind merged 2 commits into
pocket-stack:mainfrom
HalfSweet:feat/blackberry-classic

Conversation

@HalfSweet

@HalfSweet HalfSweet commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Adds BlackBerry Classic (SQC100, BlackBerry 10.3) as a private PocketJS target family with two hosts over one shared contract.

hosts/blackberry-qnx hosts/blackberry-android
Process BB10 Core Native ELF (libscreen + BPS + EGL/GLES2) in an unsigned development BAR Android 4.3 / API 18 APK: GLSurfaceView Activity over one JNI armeabi-v7a library
Install rooted Classic (unsigned dev BAR) stock Classic (APK sideload)
Hardware status first device run recorded (SQC100-4, 10.3.3.3216); re-accepted on the same device after the input path moved to the shared state machine no device result recorded yet
Tool bun blackberry-qnx setup|doctor|build|install|device-status bun blackberry-android setup|doctor|build

Shared by both hosts:

  • tools/blackberry-classic-profile.ts — private targets blackberry-qnx-dev and blackberry-android-dev: 720×720 physical, 360×360 logical at raster density 2, host ABI 9, input.buttons + input.touch + text.glyphs.baked. apps/blackberry-classic-demo is the Hero wrapper both build.
  • Package identity from the plan. ResolvedBuildPlan.app now carries version next to id/title; HostBuildInputs exposes app {id, title, version} (and POCKETJS_APP_ID/TITLE/VERSION in the host environment). packageIdentity (tools/native-host-build.ts) maps it onto the platform — id with -_ (dev.pocket_stack.blackberry_classic_demo), version verbatim, versionCode/buildId = major·1e6 + minor·1e3 + patch (0.1.1 → 1001). AndroidManifest.xml, strings.xml, and bar-descriptor.xml are @POCKET_…@ templates rendered at build time; the toolchain JSONs no longer carry package/version fields; both tools verify the produced APK badging / BAR manifest against the derived identity. Plan fixtures regenerated.
  • hosts/iphone2g/pocket_spec.h — generated from contracts/spec/spec.ts by contracts/spec/gen-c.ts (POCKET_BTN_*, POCKET_ANALOG_CENTER), byte-compared in tests/contract.ts; both hosts and the bridge use it instead of hand-written masks.
  • hosts/iphone2g/pocket_input.{c,h} — the input state machine both hosts feed: key down = one press edge (auto-repeat does not re-press) + held; relative motion pulses a d-pad direction once per threshold crossing and resets the axis (QNX: integer joystick displacement, threshold 1; Android: scroll/trackball deltas, threshold 0.35); the primary button is CIRCLE with its own held state; one tracked touch contact, latch set only on down, release reported at the next sample, second finger ignored. Unit-tested with the host compiler (tests/pocket-input.test.tstests/fixtures/pocket-input-test.c).
  • pocket_runtime_tick(const PocketRuntimeInput *) in hosts/iphone2g/pocket_runtime.c — exactly one guest turn + one core tick; both hosts call it. The N-tick form is internal; pocket_runtime_frame/pocket_runtime_frame_ticks remain for the iPhone 2G/4S and Windows CE hosts. Also pocket_runtime_gl_reset (GL resources dropped for re-initialization after context loss), POCKET_ANALOG_CENTER from the generated header, and one shared rust_eh_personality.c shim.
  • The engine/symbian no-std core with the GLES2 DrawList backend (bare-platform): QNX through the checked-in armv7-qnx-eabi.json target with build-std, Android through armv7-linux-androideabi.
  • Both native hosts take POCKET_LOGICAL_WIDTH/HEIGHT, target id, host ABI, and raster density from the resolved plan.

Native QNX host: hosts/blackberry-qnx/main.c (BPS event loop, libscreen keyboard / multi-touch / SCREEN_EVENT_JOYSTICK trackpad, navigator system keys, data/pocketjs-qnx.status receipt), bar-descriptor.xml template, tools/blackberry-qnx.ts (digest-pinned accupara/bbndk image, offline compile + BAR packaging, blackberry-deploy install/status), tools/blackberry-qnx/build.sh, quickjs-qnx.patch (no <stdatomic.h>, no malloc_usable_size on QNX).

Android Runtime host: hosts/blackberry-android/app (PocketActivity.java + jni/runtime.c, callbacks into the shared state machine under one mutex, one guest tick per onDrawFrame), tools/blackberry-android.ts (SDK archives unpacked from Google's repository per host OS with published SHA-1s — Platform 18, Build-Tools 35.0.0, NDK r23c; JDK 17 via the digest-pinned eclipse-temurin image; v1-only APK signing; NDK prebuilt chosen by host platform).

Registration: package.json files/scripts, tests/npm-package.test.ts, tests/platform-contracts.test.ts, tests/test-suite.test.ts, tools/test.ts; tests/blackberry-classic.test.ts (profile resolution for both targets incl. viewport.policy/companions, negative admission, plan-derived identity mapping, demo type-check, toolchain-pin cross-checks); docs/BLACKBERRY_CLASSIC.md.

Verified: bun tools/test.ts --stage=unit (the one failure, iphone2g-toolchain.test.ts, is a local GPG fixture-commit issue), bun tests/contract.ts; on macOS (Apple silicon) — bun blackberry-qnx setup && bun blackberry-qnx build (unsigned BAR, ARM ELF against libbps/libscreen/libEGL/libGLESv2, Package-Name: dev.pocket_stack.blackberry_classic_demo, Package-Version: 0.1.1.1001) and bun blackberry-android setup && bun blackberry-android build (v1-signed APK, package: name='dev.pocket_stack.blackberry_classic_demo' versionCode='1001' versionName='0.1.1') both complete.

Not in this PR (next PRs): moving the shared C bridge out of hosts/iphone2g/ and renaming engine/symbian; the new shared files (pocket_spec.h, pocket_input.{c,h}, rust_eh_personality.c) sit next to the bridge so that move carries them in one git mv; lifting the generic parts of tools/native-host-build.ts into the Meizu tool.

@HalfSweet
HalfSweet force-pushed the feat/blackberry-classic branch from d2d0c6a to cb1eb85 Compare August 18, 2026 16:07
@HalfSweet HalfSweet changed the title feat(blackberry): consolidate the Classic QNX and Android Runtime hosts feat(blackberry): add the Classic native QNX and Android Runtime hosts Aug 18, 2026
@HalfSweet
HalfSweet force-pushed the feat/blackberry-classic branch from cb1eb85 to 2612f3b Compare August 18, 2026 16:32
@HalfSweet
HalfSweet marked this pull request as ready for review August 18, 2026 16:36
@HalfSweet
HalfSweet force-pushed the feat/blackberry-classic branch from accad19 to 546c815 Compare August 19, 2026 09:31
Add the BlackBerry Classic (SQC100, BlackBerry 10.3) as a private target
family with two hosts over one shared contract:

- hosts/blackberry-qnx: BB10 Core Native host (libscreen + BPS +
  EGL/GLES2), unsigned development BAR built and packaged in the
  digest-pinned BBNDK image, installed with blackberry-deploy on a rooted
  Classic. First device run recorded (SQC100-4, 10.3.3.3216).
- hosts/blackberry-android: Android Runtime (API 18) host, v1-signed APK
  with a JNI armeabi-v7a library over the same QuickJS bridge and Rust
  core, sideloaded on a stock Classic.
- tools/blackberry-classic-profile.ts registers blackberry-qnx-dev and
  blackberry-android-dev (720x720 physical, 360x360 logical at density 2,
  host ABI 9); apps/blackberry-classic-demo is the Hero wrapper both hosts
  build; tools/native-host-build.ts holds the pinned QuickJS checkout,
  guest bundle, and package-identity steps native host tools share.
- The resolved plan carries app.version next to id and title, and
  HostBuildInputs exposes app {id, title, version}: the Android manifest,
  strings, and BAR descriptor are templates rendered from that identity
  (id with `-` -> `_`, version verbatim, versionCode/buildId from the
  version), so no host holds a second copy of the package identity.
- hosts/iphone2g/pocket_spec.h is generated from contracts/spec/spec.ts
  (gen-c.ts, drift-guarded by tests/contract.ts); both hosts take the
  portable button mask from it.
- hosts/iphone2g/pocket_input.{c,h}: the input state machine both hosts
  feed (key edges, relative-axis pulses, primary button, one tracked touch
  contact whose latch fires only on down), unit-tested with the host
  compiler in tests/pocket-input.test.ts.
- hosts/iphone2g/pocket_runtime.c gains pocket_runtime_tick (one guest turn
  + one core tick, the frame contract new hosts call) and
  pocket_runtime_gl_reset; the N-tick form stays internal behind the legacy
  iPhone/Windows CE entry points.
- Both native hosts take the logical viewport, target id, host ABI, and
  raster density from the resolved plan.
- tools/blackberry-android.ts unpacks the pinned SDK archives per host OS
  (Platform 18, Build-Tools 35.0.0, NDK r23c; published SHA-1s), pulls the
  pinned JDK image, and picks the NDK prebuilt by platform; tools/
  blackberry-qnx.ts builds offline in the container and deploys over the
  device address.
- tests/blackberry-classic.test.ts, docs/BLACKBERRY_CLASSIC.md, and the
  package/test registrations.
@HalfSweet
HalfSweet force-pushed the feat/blackberry-classic branch from 546c815 to 5d292a3 Compare August 19, 2026 09:37
@doodlewind
doodlewind merged commit e091f95 into pocket-stack:main Aug 20, 2026
1 check passed
@doodlewind

Copy link
Copy Markdown
Collaborator

Thanks for the feat!

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.

2 participants