A purpose-built, single-title browser edition of the original 240 × 320 Java ME game — preserving its execution path inside a responsive handheld interface for desktop, phone and tablet.
▶ PLAY THE LIVE BUILD · Project scope · Architecture · Local development · Rights & distribution
This is not a game catalogue, a user-facing JAR loader or a claim of universal Java ME compatibility. The repository is a production integration designed, configured and tested around one title: Lucha Libre: Desafío Total.
The project runs the original Java ME program logic through a custom, menu-free FreeJ2ME launcher and CheerpJ, then presents the native LCD surface inside a purpose-built web handheld. The result preserves the original state machine, timing, AI, animation, audio triggers, keypad semantics and RMS save behavior while making the game feel at home on modern browsers.
The underlying launcher, input bridge, responsive controller and local packaging method are deliberately reusable engineering patterns. Their current configuration, however, assumes this game's 240 × 320 portrait display, keypad behavior, canvas geometry, assets and presentation. Replacing the JAR alone does not create a verified edition of another game.
Live production capture — the original LCD surface is rendered before the screenshot is taken.
| Phone · portrait | Phone · landscape |
![]() |
![]() |
Tablet landscape — native game surface on the left, complete Java ME controller on the right.
Lucha is best described as a single-game Java ME web edition with a reusable runtime integration layer. It is intentionally delivered as a finished experience for one game rather than as an emulator portal.
| Layer | Reuse potential | Current Lucha-specific assumptions |
|---|---|---|
| FreeJ2ME + CheerpJ execution path | Broadly reusable for compatible MIDP software | Runtime compatibility still depends on the APIs used by each JAR |
| Menu-free Java launcher | Reusable | Fixed 240 × 320 portrait LCD and this project's lifecycle expectations |
| JavaScript input bridge | Largely reusable | Verified against this game's keypad and soft-key behavior |
| Multitouch controller | Largely reusable | Labels and action emphasis are tailored to this game |
| RMS persistence | Standard Java ME behavior | Save namespace follows the MIDlet suite and remains browser-origin specific |
| LCD canvas integration | Reusable technique | Candidate ranking currently targets a 3:4 game surface |
| Single-HTML assembly | Reusable packaging method | Input paths, output name and embedded payloads are currently project-specific |
| Website, identity and documentation | Intentionally game-specific | Designed exclusively around Desafío Total |
A similar 2D MIDP 2.0 title may require only modest adaptation, but every new JAR still needs explicit validation for display size, orientation, key codes, audio, RMS behavior, vendor APIs and browser rendering. Games that depend on 3D engines, Bluetooth, networking, camera APIs, DRM or manufacturer-specific extensions may require substantial compatibility work.
This distinction is intentional: the reusable technology stays beneath the surface, while the public product remains a focused, zero-menu edition of one preserved game.
|
The MIDlet is executed rather than visually recreated. Gameplay behavior comes from the original Java bytecode and resources. |
A custom Java launcher bypasses emulator menus, file pickers, title bars and configuration windows. |
|
The browser presents CheerpJ's native 3:4 LCD canvas directly. There is no pixel-copy mirror, color conversion or transformed AWT window. |
Keyboard and multitouch events are serialized into a Java object proxy and delivered directly to FreeJ2ME's input platform. |
|
Desktop keeps the full collectible-handheld presentation. Touch devices receive a complete keypad with dedicated portrait and landscape compositions. |
A lightweight synthesized switch sound and optional vibration pulse reinforce button presses. Sound and haptics have independent persistent switches. |
|
Known CheerpJ startup ranges are prefetched concurrently while the game shell remains responsive, reducing the serial runtime-loading penalty on cold mobile starts. |
The private/local build pipeline can package the web shell, launcher, compatibility engine and a legally supplied MIDlet into one HTML document. |
| Action | Desktop | Touch controller |
|---|---|---|
| Move / menu navigation | ↑ ↓ ← → |
D-pad |
| Confirm / primary action | Enter |
OK / center D-pad |
| Secondary action | 0 |
0 · ACTION |
| Left / right soft keys | Q / W |
SOFT L / SOFT R |
| Java ME keypad | 0–9, *, # |
Complete 12-key pad |
| Pause / resume | P |
PAUSE |
| Restart | RESET |
RESET |
| Immersive mode | Browser fullscreen | FULLSCREEN |
| Control feedback settings | FEEDBACK |
FEEDBACK |
The touch controller supports simultaneous pointers and explicit press/release delivery, so diagonals and held actions behave like hardware keys rather than ordinary web buttons. The separate BUTTON SOUND and HAPTIC PULSE settings are stored locally; vibration is automatically marked unavailable on browsers that do not expose the Vibration API. The same panel contains an expandable local startup report for comparing CheerpJ initialization, input-bridge, first-canvas and total-ready timings without remote analytics.
The original game uses Java ME RMS through a record store named SAVE. FreeJ2ME writes that data into CheerpJ's persistent /files filesystem, preserving the MIDlet's own serialization and load/save decisions rather than introducing a replacement save format.
Creation, mutation, startup loading and page-reload persistence have been verified on the production Chromium path. The local single-HTML build has also been verified to retain the same RMS file across reloads in Chromium. The web RESET action reloads the runtime and does not delete save data.
RMS storage is local to the browser profile and origin. The custom domain, Vercel aliases and a local file:// build therefore have separate saves. Clearing site data, using an ephemeral/private profile or moving to another device does not carry progress automatically; no cloud synchronization is provided.
The project does not restore or emulate retired Gameloft Live, IGP, operator portal or promotional services. Those original external links are separate from local gameplay and RMS persistence, and no replacement server backend is included.
| Environment | Composition | Primary goal |
|---|---|---|
| Desktop / laptop | Full handheld + keyboard guide + game dossier | Collectible-console presentation |
| Short desktop viewport | Compact masthead and dynamically scaled LCD | Keep the complete LCD above the fold |
| Phone portrait | LCD above a complete virtual keypad | One-handed visibility, two-thumb control |
| Phone landscape | LCD left, controller right | Maximum playable screen size |
| Tablet portrait | Enlarged LCD and centered control deck | Comfortable distance and larger targets |
| Tablet landscape | Large split-screen gamepad layout | Console-like play |
Responsive geometry has been checked at 320×568, 390×844, 430×932, 844×390, 768×1024, 1024×768, 1366×768, and 1920×1080 without horizontal overflow.
flowchart LR
MIDLET[Original MIDlet JAR] --> FJ2ME[FreeJ2ME compatibility layer]
FJ2ME --> LAUNCHER[EmbeddedFreeJ2ME launcher]
LAUNCHER --> CJ[CheerpJ 4.3 runtime]
CJ --> LCD[Native AWT LCD canvas]
LCD --> SHELL[Responsive web handheld]
KEYBOARD[Desktop keyboard] --> SERIAL[Serialized JS input bridge]
TOUCH[Multitouch controller] --> SERIAL
SERIAL --> PROXY[CheerpJ Java object proxy]
PROXY --> PLATFORM[MobilePlatform input state]
MIDlet Canvas
→ FreeJ2ME BufferedImage
→ one complete AWT drawImage operation
→ native CheerpJ LCD canvas
→ direct browser presentation
The mobile rendering path intentionally avoids canvas.drawImage() mirroring. Mirroring introduced browser color-space conversion and still exposed unstable AWT composition. The final implementation moves the correct 3:4 LCD canvas into the presentation viewport and keeps it as the only visible game surface.
A critical mobile flicker fix also removed the launcher's per-frame clear operation. The previous sequence:
g.fillRect(...);
g.drawImage(...);could be flushed as two visible browser operations on mobile Chromium. The stable path uses one full-surface draw:
g.drawImage(platform.getLCD(), 0, 0, null);prototype/
├── index.html # Semantic game-site and handheld markup
├── styles.css # Arena, console and responsive device layouts
├── app.js # Runtime boot, LCD integration and input bridge
└── assets/fighters/ # Two presentation-only character sticker composites
runtime/
├── build.sh # Java launcher build
└── src/io/github/asideproject/lucha/
└── EmbeddedFreeJ2ME.java # Menu-free FreeJ2ME host
tools/
└── build-dist.py # Private/local single-HTML packager
docs/
├── ARCHITECTURE.md
├── ROADMAP.md
└── assets/ # Live README captures and presentation artwork
- A modern Chromium, Safari or Firefox browser
- Python 3
- JDK 8+ with
javacandjar - A local copy of
L1games/J2ME-On-Web - A legally obtained copy of the original MIDlet JAR
git clone [email protected]:a-side-project/lucha.git
cd luchavendor/j2me-on-web/
reference/original/jar/app.jar
These paths are intentionally ignored by Git. Ensure the J2ME-On-Web checkout provides:
vendor/j2me-on-web/app/freej2me.jar
vendor/j2me-on-web/cheerpj/4.3/loader.js
./runtime/build.shnpx http-server . -p 4274 -a 127.0.0.1 -c-1Open:
http://127.0.0.1:4274/prototype/
Append ?touch=1 to force the touch-first layout on a desktop browser.
python3 tools/build-dist.pyThe generated file is written to:
dist/Lucha-Libre-Desafio-Total.html
The distribution directory is local-only because its payload may contain third-party runtime code and the user-supplied game binary.
- Original behavior is the reference. Runtime bytecode and observed emulator behavior take priority over visual approximation.
- The LCD is a protected surface. Decorative effects never blend over the mobile game canvas.
- No permanent compositor polling. Canvas discovery is bounded and locks onto the best 3:4 source.
- Input ordering is explicit. Press and release events share a serialized promise chain.
- Feedback is additive, not invasive. Web control sounds and haptics never alter the MIDlet audio path or input semantics.
- Startup work is parallelized deliberately. A runtime-generated CheerpJ resource manifest prefetches only ranges observed during boot.
- Touch capability beats viewport guessing. Layout selection uses pointer capability, touch points and orientation.
- Generated payloads stay private. Public source and local binary assembly remain separate concerns.
- Reuse never implies compatibility. Every additional MIDlet requires its own resolution, input, API, audio, save and rendering validation.
- The product remains single-title. Reusable internals do not turn the public experience into a JAR picker or generic emulator portal.
The production build is hosted on Vercel and served through a dedicated custom domain:
HTTP is redirected to HTTPS, with certificate management and HSTS handled at the edge.
This repository contains the independently written web shell, launcher source, responsive controls, build tooling and technical documentation. It also includes two small presentation-only character sticker composites derived from original sprite data so the single-game interface can visually represent its subject. Those images remain third-party game artwork and are not relicensed by this project.
It intentionally does not include:
- the original Gameloft MIDlet JAR;
- bulk extracted artwork, audio, sprite sheets or other game asset sets;
- reverse-engineered/decompiled game source;
- vendored FreeJ2ME or CheerpJ runtime payloads;
- generated single-file distributions containing those materials.
Lucha Libre: Desafío Total, its program, artwork, audio, title, characters and related assets belong to their respective rights holders, including Gameloft. FreeJ2ME and CheerpJ remain subject to their own licenses and usage terms. CheerpJ Community Edition is intended for personal and non-business use; other use requires an appropriate license from Leaning Technologies.
See THIRD_PARTY_NOTICES.md for additional details.
LUCHA — THE BELL RINGS AGAIN.
One game. One ring. Zero emulator menus.

