2009 · Phone · Meizu

Meizu M8

From message pump to multitouch on Windows CE. A 480×720 BGRA framebuffer over GDI.

Hardware-tested hostGuest · QuickJS + native corehosts/meizu-m8/

Meizu's first phone was announced in 2007 and went on sale in China in February 2009: a 3.4-inch 720×480 capacitive multi-touch display at 255 ppi, a Samsung ARM11 at 667 MHz, 256 MB of RAM, and Meizu's own Mymobile interface on a Windows CE 6.0 kernel. It sold around 100,000 units in its first two months.

PocketJS runs on it as a single Windows CE ARM executable: QuickJS, the app and its assets, and the Rust software renderer in one PocketJS.exe that copies a native 480×720 BGRA framebuffer to the LCD through GDI without stretching. Deployment goes over the phone's ActiveSync serial function through PPP and RAPI — no firmware is flashed.

Processor
Samsung ARM11 · 667 MHz
Memory
256 MB
Display
720 × 480
A Meizu M8 showing the Wikipedia portal in its browser
A Meizu M8 showing the Wikipedia portal in its browser. Photo: Crimson05 (de.wikipedia) · Public domain
01

Hardware

curated here · sources below

Compute

SoC
Samsung S3C6410
CPU
ARM1176JZF-S (ARM11), 667 MHz
RAM
256 MB
Storage
8 / 16 GB flash

Display & input

Display
3.4″ LCD, 720 × 480, 255 ppi, 3:2, 16.6 M colours
Touch
Capacitive multi-touch
Sensors
Ambient light, accelerometer, proximity
Camera
3.2 MP with autofocus

Connectivity

Radio
Quad-band GSM, GPRS, EDGE
Wireless
Wi-Fi (M8SE / later firmware), Bluetooth
Ports
Mini-USB (USB 2.0), 3.5 mm
Battery
1200 mAh removable

Body

Dimensions
105 × 58 × 11.8 mm
Weight
118 g
Released
Announced 2007 · on sale 18 February 2009 (China)
OS
Windows CE 6.0 kernel with Meizu Mymobile UI
02

PocketJS on this machine

Guest · QuickJS + native core

What runs

The native build uses a digest-pinned CeGCC container and a clean pinned QuickJS checkout; the Meizu SDK archive is not a build input. The host turns WinCE messages into wide touch coordinates, closes cleanly on Home or Escape so the shell can regain the display, registers a build-qualified MiniOneShell icon and deploys over the phone's WceUsbSh ActiveSync serial function through macOS pppd, an isolated D-Bus and SynCE dccm.

What is proven

Status requires advancing guest frames, successful GDI composites and matching 480×720 logical and physical viewports; acceptance additionally requires a completed touch sequence and a changed hero_tap action. capture retrieves the device-generated 480×720 framebuffer BMP.

Record

  1. v0.10.1

    Windows CE runs a real Solid guest on the Meizu M8; the field report follows the port from the first clipped frame to the native result.

Profile · as declared by the demo manifestsource ↗
Profile
meizu-m8 (private, host ABI 8)
Logical viewport
480 × 720
Raster density
Requires
  • input.touch
  • text.glyphs.baked

Acquisition reports

04

Example code

upstream source · highlighted at build time
apps/meizu-m8-demo/app.tsxtsx · 16 lines · @6c43f49

The 480×720 touch demo.

import Hero from "../hero/app.tsx";
import { reportAppAction } from "@pocketjs/framework/host";

export default function MeizuM8Hero() {
  return (
    <Hero
      actionLabel="Tap Hero"
      deviceLabel="running on a 2009 Windows CE touchscreen."
      headline="JSX on M8"
      largeLayout
      onAction={(count) => reportAppAction("hero_tap", count)}
      presentationHz={60}
      runtimeLabel="RUST + QUICKJS + GDI"
    />
  );
}
05

Bring-up guide

upstream documents · rendered verbatim

Toolchain, build, deploy and acceptance are owned by pocket-stack/pocketjs. The documents below are rendered from the pinned checkout without edits; relative links point back into the repository at the same revision.

Meizu M8 / M8SE

2 min read · 495 words

Build in the CeGCC container, USB bridge and PPP session, deploy, status, accept, capture.

rendered verbatim fromdocs/MEIZU_M8.md@ 6c43f49raw ↗

PocketJS runs on the original Meizu M8 as a Windows CE 6 ARM application. The host embeds QuickJS and the Rust software renderer in one PocketJS.exe, then copies its native 480×720 BGRA framebuffer to the 480×720 LCD with GDI without stretching. Host ABI 8 uses its wide touch-word format for the full native coordinate range.

The PocketJS window is not system-topmost. Pressing Home or Escape closes it so the Windows CE shell can regain the display.

The port targets the USB identity 0547:2720, exposed by the phone as MEIZU M8SE USB Serial. USB deployment uses the phone's WceUsbSh ActiveSync serial function, PPP, and RAPI; it does not flash firmware or modify a partition.

Build

Install Docker, Bun, Rustup, libusb, GLib, D-Bus, gettext, Autoconf, Automake, and libtool. The native build uses the digest-pinned CeGCC container and a clean pinned QuickJS checkout; the Meizu SDK archive is not a build input.

bun install --frozen-lockfile
bun meizu-m8 doctor
bun meizu-m8 build
bun meizu-m8 setup-rapi

The native compiler image, Rust nightly, QuickJS revision, SynCE revision, SDK checksum, USB endpoints, and device addresses are pinned. dist/meizu-m8/build-receipt.json records the inputs and the resulting executable digest.

USB connection and deployment

Enable USB synchronization on the phone and connect it directly with a data-capable mini-USB cable. Run bun meizu-m8 usb-probe only as a descriptor and handshake check; it consumes the current CLIENT handshake, so reconnect the cable before starting a full session.

The host-side USB bridge exposes a pseudo-terminal. Start it with bun meizu-m8 usb-bridge and keep that terminal open. Its first line is PTY=/dev/ttysNNN. In a second terminal, run bun meizu-m8 session /dev/ttysNNN with that exact path and approve the macOS administrator prompt. Then turn USB synchronization off and on without unplugging the cable.

The session command makes macOS pppd answer the phone's CLIENT message with CLIENTSERVER and negotiate 192.168.131.1:192.168.131.129. It starts an isolated D-Bus instance, runs SynCE dccm, and registers the legacy ActiveSync device. Keep both terminals open while deploying.

bun meizu-m8 deploy
bun meizu-m8 status
bun meizu-m8 accept
bun meizu-m8 capture

deploy creates \Program Files\PocketJS, runs a helper that attempts to terminate only earlier PocketJS.exe and PocketJS-*.exe processes, and copies a build-ID-qualified executable. It derives the M8's 80×80 shell icon from the shipped iPhone 2G PocketJS icon, copies it under a build-ID-qualified path, and writes the HKLM\SOFTWARE\Meizu\MiniOneShell\Main\PocketJS values required by the M8 SDK. The current build therefore appears as PocketJS in the phone's main shell without reusing a stale cached icon. Status and framebuffer receipts use build-ID-qualified paths, so an earlier process cannot overwrite the current build's evidence. status requires advancing guest frames, successful GDI composites, and the resolved 480×720 logical and physical viewports. capture retrieves the current build's device-generated framebuffer BMP from \Temp and rejects a frame that is not 480×720.

Tap the blue Hero control before running accept. Acceptance requires action_name=hero_tap, a positive action value and sequence, and a completed touch sequence in the live device status.

Photo

Wikimedia Commons · Meizu m8 wikipedia.jpg — Crimson05 (de.wikipedia), Public domain.