J2ME · RISC-V RV32IM Emulation

Run ELF & Lua
inside retro terminals

OpenTTY brings a full Unix-like environment to J2ME feature phones. Execute RISC-V binaries, Lua scripts, manage processes, and experience modern CLI on old devices.

Lua J2ME · ELF loader · Dynamic linking
root@opentty:~/home/#
$ uname -a
Nokia 6233 (OpenTTY 1.18.1) main/mod 2026-1.18.1-03x27 - CLDC-1.1 MIDP-2.0

$ ./hello.elf
Hello from RISC-V ELF on J2ME!

$ lua -e 'print(os.date())'
Tue Apr 30 16:20:01 2026

$ ps
PID  PROCESS
1    init
1420 lua script.lua
status: running

Designed for constrained devices,
powerful emulation

OpenTTY provides an unprecedented experience on J2ME phones: ELF loader, dynamic linking, POSIX syscalls, and full Lua environment.

RISC-V ELF Loader

Full RV32IM ELF interpreter. Support for PT_LOAD, dynamic sections, GOT/PLT relocation, and syscall translation layer.

Lua J2ME

Complete Lua interpreter with coroutines, tables, metatables, and custom modules: `os`, `io`, `socket`, `graphics`, `audio`, `push` API.

Virtual FS & RMS

In-memory filesystem, persistent RMS storage, `/bin`, `/etc`, `/home`, and real FileConnection for memory cards. Full Unix-like paths.

Network Sockets

TCP/UDP socket support, HTTP client, socket server API. Connect, bind, send/receive syscalls mapped to J2ME GCF.

GUI & Graphics

Interactive UI via `graphics` module: Forms, Lists, TextFields, Images, Commands with callback handlers, LCDUI integration.

Process isolation

Multi-process model with UIDs, signalling, priority handling, and kernel IPC via request() mechanism. Sandboxed execution.

Hybrid execution engine

The core of OpenTTY includes a lightweight RISC-V RV32IM interpreter that reads ELF binaries, relocates symbols, resolves dynamic libraries, and traps syscalls. Combined with the Lua runtime, it offers both compiled C applications and scripting.

  • Dynamic Linking: DT_NEEDED, GOT/PLT, R_RISCV_JUMP_SLOT and R_RISCV_GLOB_DAT
  • RV32IM core: Integer, load/store, branch, system, and M-extension instructions
  • Signal handling & setjmp/longjmp
  • POSIX emulation: open, read, write, mmap, fork, execve, socket, futex
Explore source code
Dynamic relocation demo
// ELF relocation handling (Java)
switch(type) {
  case R_RISCV_JUMP_SLOT:
    writeIntLE(memory, offset, resolveSymbol(symName));
    break;
  case R_RISCV_GLOB_DAT:
    symAddr = resolveSymbol(symName);
    writeIntLE(memory, offset, symAddr);
    break;
}
// RISC-V system instruction
0x00000073 : ecall
OpenTTY implements RISC-V RELA relocations, dynamic symbol tables, and a generic syscall dispatcher.

"OpenTTY brings the Unix philosophy to feature phones. It's more than a terminal — it's a full development and runtime environment for RISC-V binaries and Lua, all running inside the JVM."


J2ME ecosystem
MIDP 2.0 / CLDC 1.1 compatible
Modular design

ELF loader – independent bytecode interpreter – posix file abstraction – Lua FFI – graphics toolkit. Everything structured for extensions and lightweight memory usage (dynamic heap, 1MB base memory).

#RISCV #LuaJIT-like #RecordStoreFS #Socket API

Building OpenTTY from Source Code

Compile with sdkcli.jar on a computer or directly on your mobile device using the on-device SDK

Compile with sdkcli.jar

Download sdkcli.jar, open a terminal in the OpenTTY repository folder, and run the SDK CLI to build the project.

Or build on your device

Open the OpenTTY source folder in the on-device SDK. Ensure all Java files are present.

Start the build

Press the Build button (🛠️ hammer icon) and wait for compilation to finish.

Output Files

After success, check the dist/ folder:

  • OpenTTY.jar – main executable
  • OpenTTY.jad – descriptor file
Installation

Method 1: Open OpenTTY.jar directly → install → launch.

Method 2: Use OpenTTY.jad for devices that prefer JAD installers.

✅ After install, find "OpenTTY" in your apps → start terminal.
Troubleshooting: verify source files & memory
JAD vs JAR: try alternate method
MIDP-2.0 / CLDC-1.1 required

Start building with OpenTTY

Get the latest release, browse the repository, or test the web proxy. All resources are open-source and community-driven.

Quick setup
# download sdkcli.jar from http://opentty.fun/sdkcli.jar
# then run it from the OpenTTY repository folder
 $ java -jar sdkcli.jar

 # or compile on-device
 $ open the OpenTTY folder in the on-device SDK
 $ click Build (🛠️)

# output: dist/OpenTTY.jar + OpenTTY.jad
# install on any MIDP 2.0 device