An open-source emulator and architectural-analysis toolkit for Nokia DCT3-era phones — the 3310, 3210, 3410, 5210, 6210, 6250, 7110, 8210, 8250, 8810, 8850 and their siblings. It boots real firmware in the browser and in a native SDL GUI, faithfully modelling the MAD2 platform ASIC, the CCONT power controller, the TMS320C54x DSP, the PCD8544/SED-class LCD, the keypad matrix, the SIM, and the internal + external EEPROM.
Beyond the phone UI:
- GSM registration on a synthetic network; voice calls; SMS send and receive.
- WAP browsing over a circuit-switched-data bearer, with settings delivered by binary SMS.
- Offline provisioning of the factory identity records (IMEI, FAID, SIMlock, security code) into the emulated EEPROM.
- An MBUS service bus, usable by period Nokia service tools over a null-modem COM port.
A historical software-preservation project: it documents and re-hosts the behaviour of obsolete, ~25-year-old hardware for offline educational analysis.
Implementation constraint. Behaviour is modelled at the silicon level; firmware is not patched. There are no forced self-test verdicts and no trampolines. Every write into MCU RAM is a mailbox write: the DSP↔MCU message ring, its head and tail pointers, the COBBA staging cell, the codeblock request/reply cells. Provisioned identity records are decoded and judged by firmware code, and on the 5110 by the real C54x mask ROM running the DCT3 security cipher.
Known deviation. EF_LOCI is cleared from the SIM on every boot. ROM-4 implements
registration only as a full Location Update, so a card holding a valid location camps without
registering. Contacts and messages are unaffected. SWSIM_KEEP_LOCI=1 disables the clear. This
may account for the models below that reach standby without registering. Everything else
outstanding is under Open items.
Firmware — bring your own
This repository contains no copyrighted firmware, flash dumps, or EEPROM images, and a pre-commit hook + CI check keep it that way. You must supply your own legitimately-obtained
.flsimage.
Drop a flash image in and point a target at it:
# Native ./build/dct3_boot_trace_gui "Nokia 3310 NR1 v5.79.fls" # Web — either rebuild the module with your image baked in: make all WEB_FW="Nokia 3310 NR1 v5.79.fls" # ...or leave the module firmware-free and load an image from the web UI at runtime.
Bootability and radio capability by model
How far each model gets today. Model and version are read from the flash header, so nothing is hardcoded per image.
Boot: ✅ reaches a usable screen (standby, or a normal interactive prompt such as the factory Security-code entry) · 🟡 reaches Contact Service, or a lock it can't clear faithfully · 🔴 stalls early.
Net / Calls / SMS / WAP: ✅ works · 🟡 partial · ❓ untested · — not applicable. Not applicable covers two cases: the handset's own firmware has no such feature (only models with a WAP browser can browse), or its DSP engine doesn't implement it. The GSM stack lives in the ROM-6 engine. ROM-4 does camp and registration only, with no calls, SMS or circuit-switched data.
| Model | Code / ver | DSP | Boot | Net | Calls | SMS | WAP | Notes |
|---|---|---|---|---|---|---|---|---|
| 2100 | NAM-2 v5.84 | ROM-6 | 🟡 | ❓ | ❓ | ❓ | ❓ | Security-code screen; rejects the EEPROM-baked code (12345). Nothing past it tested. See #3 |
| 3210 | NSE-8 v6.00 | ROM-4 | ✅ | ✅ | — | — | — | Registered standby. Requires the CCONT persistent-ready bit model and the security-level record provisioned to its erased default; 12345 still accepted if re-enabled. No-SIM boots to "Insert SIM card". Keypad matrix RE'd from the firmware keymap table (wiring differs from the 3310) |
| 3310 | NHM-5 v5.79 | ROM-6 | ✅ | ✅ | ✅ | ✅ | — | Reference baseline, pinned byte-identical by make guard. No WAP browser in this firmware |
| 3330 | NHM-6 v4.50 | ROM-6 | ✅ | ✅ | ✅ | ✅ | ✅ | Factory code 12345 → first-boot Time wizard. Verdict/upload cells resolve per-build via the NHM family signatures. WAP over CSD and OTA settings SMS both confirmed |
| 3350 | NHM-9 v5.22 | ROM-6 | ✅ | ✅ | ✅ | ✅ | — | Requires a valid identity: the common library image ships an empty EEPROM partition. Graft a donor NHM 'EEPROM' block first (tools/graft_eeprom_block.py, 3330 donor validated). Otherwise as the 3330 |
| 3410 | NHM-2 v5.46 | ROM-6 | ✅ | ✅ | ✅ | ✅ | ✅ | CSD / WAP / OTA reference target. Open: minor set-time clock-tick gap |
| 5110 | NSE-1 v5.30 | ROM-4 | ✅ | 🔴 | — | — | — | Local security passes under the C54x co-sim (DSP54_COSIM=1): the mask ROM decodes and judges the provisioned SIMlock, IMEI and FLASH-ID records, reaching standby. Web HLE DSP also reaches standby. Open: no registration |
| 5110i | NSE-2 v5.53 | ROM-4 | 🟡 | — | — | — | — | 2 MB 5110 refresh. Contact Service on the borrowed 5110 EEPROM; a 5110i-specific record self-test is not provisioned |
| 5130 | NSK-1 v5.30 | ROM-4 | ✅ | 🔴 | — | — | — | 5110 sibling (Xpress-on). Standby. Open: no registration |
| 5190 | NSB-1 v6.71 | ROM-4 | ✅ | 🔴 | — | — | — | Standby. Open: no registration |
| 5210 | NSM-5 v5.40 | ROM-6 | ✅ | ✅ | ✅ | ✅ | ❓ | WAP untested |
| 5510 | NPM-5 v3.50 | ROM-6 | 🔴 | — | — | — | — | Early power-off. Memory map unresolved |
| 6110 | NSE-3 v5.48 | ROM-4 | ✅ | ✅ | — | — | — | Registered standby. Requires the stored security-settings checksum re-derived from the blob's own identity |
| 6130 | NSK-3 v5.61 | ROM-4 | ✅ | 🔴 | — | — | — | 6110 sibling. Standby without registering, unlike the 6110 and 6150 on the same config. Open, cause unknown |
| 6150 | NSM-1 v5.23 | ROM-4 | ✅ | ✅ | — | — | — | 6110 sibling (2 MB, own external-EEPROM blob). Registered standby |
| 6190 | NSB-3 v6.13 | ROM-4 | 🟡 | — | — | — | — | Contact Service. The US NSB build fails an extra judged self-test element. RE pending |
| 6210 | NPE-3 v5.56 | ROM-6 | ✅ | ✅ | ✅ | ✅ | ✅ | Self-test resolves via the DSP block-ack pump setting the upload flag plus a ROM-6 self-test-complete responder posting the firmware's own ack. WAP over CSD confirmed |
| 6250 | NHM-3 v5.00 | ROM-6 | ✅ | ✅ | ✅ | ✅ | ✅ | 6210 sibling. Additionally needs a repair of this library image's inconsistent RF-calibration checksum and the DSP-in-reset status-bit model |
| 7110 | NSE-5 v5.00 | ROM-4 | ✅ | ✅ | — | — | — | SED1565 display; RE'd keypad and Navi roller (mouse-wheel or arrows scroll, press to select). Slow boot, then key-navigable registered standby. Has a WAP browser but binds ROM-4, so no CSD bearer |
| 8210 | NSM-3 v5.31 | ROM-6 | ✅ | ✅ | ✅ | ✅ | — | Security-code screen at boot. Registers with correct EEPROM security settings |
| 8250 | NSM-3D v6.02 | ROM-6 | ✅ | ✅ | ✅ | ✅ | — | As the 8210 |
| 8290 | NSB-7 v5.22 | ROM-6 | 🟡 | — | — | — | — | Contact Service. DSP-upload handshake RE pending |
| 8810 | NSE-6 v6.02 | ROM-4 | ✅ | ✅ | — | — | — | 6110-family slider (2 MB, own external-EEPROM blob). Registered standby, keypad interactive. Slide cover not modelled |
| 8850 | NSM-2 v5.31 | ROM-6 | ✅ | ✅ | ✅ | ✅ | — | NSM Family-A reference. As the 8210 |
| 8855 | NSM-4 v5.13 | ROM-6 | ✅ | ❓ | ❓ | ❓ | ❓ | Standby. Radio untested |
| 8890 | NSB-6 v12.16 | ROM-6 | 🟡 | — | — | — | — | Contact Service (US-band 8850) |
Nineteen of the 26 registered models boot to a usable state, and fifteen of those register on a synthetic test network with an operator name and signal bars.
Features
Emulation core
- Vendored mGBA ARM interpreter (big-endian-corrected for DCT3), driving the real firmware instruction-for-instruction — no HLE of the application layer.
- MAD2 platform model (
src/mad2/): the ASIC bus, interrupt/FIQ controller, timers, RTC, Intel/Sharp CFI flash FSM, internal + I²C external EEPROM, and the MBUS/FBUS USART. - CCONT power/RTC/ADC controller with the interrupt→event measurement protocol.
- 26 model profiles (
src/models/) selecting memory map, LCD controller, battery/ADC windows, keypad matrix, and DSP variant at runtime from the flash header.
DSP
- Faithful TMS320C54x co-simulation via a vendored qemu-calypso-lineage interpreter
(
third_party/c54x/), running the recovered DSP image with demand-paged overlay uploads. The MCU↔DSP HPI mailbox, boot handshake, self-test and keep-alive are modelled as on real silicon. On the 5110 the mask ROM runs the DCT3 local-security path, decoding the provisioned SIMlock records and reporting its own verdict. Required C54x interpreter fixes:RSBX/SSBXdecode (F6Bx/F7Bx, previously swallowing0xF0B0OR A,-16,A),MVDProuted throughprog_writeso mask ROM rejects writes,dmadauto-increment underRPTforMVDK/MVKD/MVDM/MVMD, and three ALU/control-flow corrections used by the identity cipher. - High-level DSP responders split by ROM revision for models where the co-sim isn't wired.
Peripherals & I/O
- LCD: PCD8544-class framebuffer, rendered to the browser canvas, the SDL window, or PNG.
- Keypad: matrix scan with IRQ-driven debounce and auto-repeat modelling.
- Audio: a unified mixer over the buzzer and a PCM channel. Keypad tones and DTMF come from the DSP: synthesised from the mailbox tone oscillators under the HLE DSP, and delivered as PCM samples from the DSP itself under the C54x co-sim.
- SIM: a software card driven through the modelled SIMI UART, with a real ATR, ISO-7816 PPS, and GSM 11.11 T=0 down to the byte pacing and the procedure-byte handshake. See below.
- Battery, charger, LEDs, vibra exposed to both front-ends.
- Radio: a synthetic GSM cell driven over the DSP↔MCU mailbox (System Information, paging, immediate assignment, LAPDm) carrying registration, voice calls, SMS, and a minimal circuit-switched-data bearer.
GSM network, calls, SMS and WAP
- Registration: every ROM-6 model that boots registers on the synthetic network; ROM-4 models camp and register too, apart from the 5110 family.
- Calls and SMS on the ROM-6 engine, including CP/RP, SMS-DELIVER,
EF_SMSstorage and Smart-Messaging ringtones. - CSD and WAP: an RLP peer, PPP, and a WAP gateway that fetches real pages and compiles WML
1.1 to WBXML so forms work. It isn't keyed to a model: it lives in the shared ROM-6 engine and
arms on the decoded UDI bearer in the handset's own
SETUP. The limit is whether a given firmware has a WAP browser and a settings receiver. Confirmed on the 3330, 3410, 6210 and 6250. - OTA settings provisioning: WAP settings arrive over binary SMS rather than being typed in.
Factory provisioning and the DCT3 security codec
- Offline provisioning of the I²C external EEPROM for the ROM-4 phones (3210, 5110, 5110i, 5130, 5190, 6110, 6130, 6150, 8810). No donor handset or service cable. Writes a coherent IMEI, the FLASH-ID/FAID record, both SIMlock parts, the security code and every checksum the boot validator compares; firmware reads, decodes and judges them. This is what takes the 3210, 6110, 6150 and 8810 to a registered standby. The Security-code prompt on those models is an identity-sum vs stored-checksum mismatch, not a FAID failure.
- The security codec is open (
src/services/dct3_calcul.c): the record codec for all four modes (MSID, FLASH-ID, Lock, IMEI). Tables transcribed, with one published-source error corrected:IMEI_DEFbyte 9 is0xFF, recovered by inverse-decoding a real service-tool write.tools/dct3_calcul.pyholds the offline inverse used to mint an MSID. - The SIMlock transport pad is derived, not measured, from the firmware routine that builds
it (5110 v5.30
0x25792C..0x2579A2: pairwise 16-bit products, a bit-reversed complement key, then a 24-byte XOR). Valid for any pinned identity. - A pinned MSID under both HLE engines. ROM-4 and ROM-6 responders answer the local-security
identity query (
{74 34}) from a per-model MSID carrying the correct COBBA signature, selected by DSP generation. - The emulator issues the MBUS provisioning commands itself; no external tool required.
src/services/identity_provision.cbuilds theB8/BA/B6(selector0x4F) frames a Windows service tool sends, byte-identical in form to captured NokTool traffic, and feeds them into the MBUS RX FIFO by the same path the host serial bridge uses. Firmware service handlers decode them and write the EEPROM. No EEPROM offsets are poked, so records land wherever the build keeps them. Run it from the web UI button or withREPROVISION=1(REPROVISION_AT=sets the trigger step,REPROVISION=verifyreads the identity back without writing). Requires the phone past startup in normal mode. A run with no reply times out rather than half-writing.
Front-ends
- Web (
web/): cycle-paced WASM build, per-model phone-shell UI, runs in any browser. - Native SDL GUI: desktop shell with the phone photo, live keypad, and LCD.
- Android (
android/): native JNI build for real feature-phone-shaped Android handsets (e.g. the HMD Terra M) — no phone-shell chrome, since the hardware already looks like one. Nokia 3410 only for now; seeandroid/README.md. - A null-modem COM port: the emulator can expose its MBUS service bus as a real serial port, so period Nokia service tools drive the handset unmodified. NokTool, Rolis, Koci, NFREE and the DCT3 EEPROM tools run under Wine and talk to the phone over MBUS as they would to hardware on a service cable. See below.
- Headless harnesses:
dct3_boot_trace(instrumented native run with an always-on post-mortem that labels every halt PC, message and reset reason) andtools/nav.mjs(deterministic browser-paced harness that plays a key script over emulated time and renders the framebuffer to PNG).
Analysis toolchain
- Symbol store (
tools/symbols/): per-firmware-build address/name/message database with a lookup CLI and a scratch→promote workflow. disfw: an annotated disassembler that reads the symbol store and decodes effective addresses, cmp-gates, jump tables, and message IDs inline.- NokiX-compatible script runner (
tools/nokix/) for applying diagnostic overlays and auto-locating symbols.
Quick start
# Web (committed WASM core runs as-is; rebuilding needs emscripten) make all && make serve # serves web/ on http://localhost:8000 # Native SDL GUI (needs SDL2) make gui ./build/dct3_boot_trace_gui "your-firmware.fls" # Headless boot observation make trace ./build/dct3_boot_trace "your-firmware.fls" 250000000 # Annotated disassembler make disfw ./build/disfw "your-firmware.fls" 0x002EEBAE 12 # Real-SIM bridge (optional; needs an ESP32 flashed with esp32/simbridge/) make simprobe ./build/simprobe /dev/ttyUSB0 atr # Tests make test # native regression suite (68 checks + dbgcon) make guard # byte-identical boot guard (needs your firmware images)
Driving the emulator with period service tools
The emulated MBUS service bus can be presented to the host as a serial port. Unmodified Nokia service software (NokTool, Rolis, Koci, NFREE, the DCT3 EEPROM tools) then connects to the handset, reads its IMEI, dumps and rewrites its EEPROM, and runs the service commands it would against hardware on a service cable.
Optional: provisioning does not require it. Use it to drive the phone with period software, or to cross-check provisioning against a genuine tool.
MBUSBRIDGE=1 MBUSLOG=1 ./build/dct3_boot_trace_gui "your-firmware.fls" # [mbus-bridge] tty0tty: emulator=/dev/tnt0 tool COM=/dev/tnt1 (real DTR/RTS/DCD)
Requirements
- A null-modem tty pair with real modem control lines.
MBUSBRIDGE=1claims the first free tty0tty pair: the emulator opens the even end (/dev/tnt0), the tool connects to the odd end (/dev/tnt1). The service tools drive DTR/RTS/DSR/DCD/CTS, so real lines are what remove the need for anLD_PRELOADshim. Build the module once (cd tty0tty/module && make), thensudo insmod tty0tty.ko && sudo chmod 666 /dev/tnt*per boot.MBUSPORT=<dev>uses a specific device;MBUSPTY=1falls back to a bare PTY, which has no modem lines and does need the shim. - Wine, with the tool end mapped to a COM port. Point
COM3at the odd end, with eitherwine reg add 'HKLM\Software\Wine\Ports' /v COM3 /d /dev/tnt1 /forln -sf /dev/tnt1 ~/.wine/dosdevices/com3, then connect the tool on COM3 / MBUS. - The right Wine prefix per tool. NokTool needs a true 32-bit (Win9x) prefix, since it uses
LDT/win9x facilities WoW64 doesn't provide. The DCT3 EEPROM tool is VB6 and needs
msvbvm60plus a registeredmscomctl.ocx. Rolis, Koci and NFREE are plain Win32 PE32 apps and run in a normal prefix.faid.exeis a console tool, so launch it viawineconsolefor a window. - A powered-off start.
GUIPWROFF=1boots the GUI with the phone off, which is what the tools expect; tappto power on once connected.
MBUSLOG=1 prints every byte in both directions, which is the quickest way to see whether a
tool's handshake is landing.
Persistence
Every persisted non-SIM setting lives in one store per handset. Which medium that store uses splits the range into two mutually exclusive families — a handset has one or the other, never both — but the two hold the same class of data: settings, clock, factory identity (IMEI, FAID, SIMlock, security code) and RF calibration.
| Family | Store | Models |
|---|---|---|
| External I²C 24Cxx EEPROM | a separate 2 KB device, no in-flash PMM partition | 3210, 5110, 5110i, 5130, 5190, 6110, 6130, 6150, 6190, 8810 |
| In-flash PMM partition | a partition inside the .fls image; the offset is per-model, not a constant |
everything else |
The I²C family is the ROM-4 models with one exception: the 7110 is ROM-4 but flash-PMM based, so it sits in the second group.
Capacity is what differs. 2 KB of EEPROM cannot hold what a PMM partition can, so the J2ME game store is PMM-only. Phonebook storage varies by model: some keep contacts in the PMM, others only on the SIM.
The SIM card filesystem (contacts, SMS, Kc, FPLMN) is a separate store, independent of that
split and present on every model.
In the browser all of them persist automatically.
| UI | Store | Key | Default |
|---|---|---|---|
Phone shell (web/next/) |
IndexedDB | per model + image | on |
Diagnostic (web/) |
localStorage | per image | off |
IndexedDB rather than localStorage: the 3410's NVRAM partition alone is 576 KB, and base64 in UTF-16 puts several models past the ~5 MB localStorage origin quota. The diagnostic UI defaults off so boots stay reproducible.
Two behaviours to be aware of:
- The SIM card is keyed per origin, not per image, so it follows you across model switches. The PMM and I²C EEPROM snapshots are keyed per image.
- A region is saved only if the firmware programmed it this session. Auto-save runs every few seconds, on tab hide and on unload. DCT3 holds many settings in a working-RAM shadow and flushes on a real trigger, so an uncommitted change has not moved the write counter. The Save button forces a write.
Wipe saved settings (dct3ResetEeprom()) clears the NVRAM, EEPROM and SIM snapshots. Uploaded
games and UI preferences are separate and survive. A provisioned identity is an ordinary EEPROM
change and persists like any other write.
Natively nothing persists unless asked; a boot_trace run discards its flash writes at exit.
EE5110SAVE=out.bin ./build/dct3_boot_trace "<fw>.fls" 40000000 # dump the external EEPROM EE5110=out.bin ./build/dct3_boot_trace "<fw>.fls" 250000000 # ...and load it back node tools/nav.mjs "<fw>.fls" --simsave card.bin # snapshot the SIM at exit node tools/nav.mjs "<fw>.fls" --simload card.bin # mount it at boot
The in-flash PMM partition has no native save knob. Manipulate it offline with eeprom_tool:
inspect, extract, merge, provision, set the IMEI or security code, list or add J2ME games.
It reads the real store format, selecting the active block by sequence number rather than position
and replaying the append journal that trails the flat image. Readers that skip either step report
stale values.
Working RAM does not persist; a reboot is modelled as a fresh power-on. Neither do the device-model flags, so the front-ends re-apply SIM presence and PIN settings after a reboot.
The SIM
Electrical and transport. The SIMI UART (MAD2 registers 0x36–0x3F) is modelled with the
FIQ6 receive and transmit-empty interrupts and the FIQ7 card-detect edges; bit assignments were
taken from the firmware's FIQ6 handler. Bytes are paced at ~960 characters/second, one per
~1.04 ms (SIMPACE=0 for instant). Work-waiting time is modelled. PPS is answered by echoing the
frame. T=0 reassembles transmit chunks into whole APDUs and acknowledges case-3 commands with the
procedure byte once per command; acknowledging per chunk desynchronises the link (a 176-byte SMS
record update arrives as twelve chunks) and surfaces later as a spurious "Insert SIM card".
Two card backends. The default is a software SIM on the vendored swSIM/swICC stack: a full
GSM 11.11 filesystem across DF_TELECOM and three application DFs, with COMP128 for
RUN GSM ALGORITHM. Local to this project: the electrical layer, the T=0 transport, and five
patches to the upstream card required for DCT3 SIM init — TERMINAL PROFILE and
READ RECORD / UPDATE RECORD under GSM class byte A0 (upstream returned 6D00), a SELECT that
reports record length so the phone can learn ADN and SMS geometry, and SELECT-by-file-id resolving
current-DF-first so EF_LOCI does not collapse across the three application DFs. SWSIM=0
selects the synthetic EF table instead, 21 files with geometry taken from a captured real card.
Presence and identity. A SIM is inserted by default; SIMABSENT=1 (or --sim 0 headless)
models an empty tray. The IMSI is selected by DSP engine: ROM-6 uses the reference identity
208-01, ROM-4 the lock-exempt test identity 001-01. The two therefore show different operator
names in the table above. The synthetic cell broadcasts the fitted card's PLMN rather than a fixed
one.
PIN. CHV1 is fully modelled on the synthetic backend: enable, disable, change, verify,
unblock, try counters, the always-readable file whitelist, and the file-characteristics bits the
phone reads to determine whether a PIN is required (SIMPIN, SIMPUK, SIMPINON). Upstream
swSIM does not implement PINs, so the PIN controls are inert on the default backend; SWSIM=0
exercises that path.
Writable files. Contacts (EF_ADN), messages (EF_SMS), SMS parameters and service centre,
MSISDN, and any transparent file. On the software card these are filesystem writes surviving a
reboot and, in the browser, a page reload. On the synthetic backend they go to a copy-on-write RAM
overlay wiped every boot; an unwritten file keeps no overlay, which is what holds the
byte-identical boot guard stable. EF_LOCI is the exception noted at the top of this README.
Talking to a physical SIM card
An optional bridge lets the emulated phone use a real SIM. The tap is at APDU level: the emulator
hands each command to tools/sim_bridge.c, which owns the T=0 state machine and drives a thin
ESP32 reader over USB (sketch in esp32/simbridge/). The reader clocks the card at 3.5712 MHz and
speaks ISO 7816. Protocol decisions stay on the host, so they can be logged and changed without
reflashing.
Every APDU is shadow-compared: the emulator computes the synthetic answer, runs the real card,
logs MATCH or DIFF, then feeds one to the firmware. This is the mechanism for aligning the
software card with silicon. A mute card reads as absent rather than falling back to the synthetic
one, so a reader with no card fitted gives "Insert SIM card". SIMBRIDGE_IMSI=<digits> rewrites
the IMSI in the real card's response in transit, isolating whether a rejection is IMSI-driven.
make simprobe builds a standalone CLI (ping, atr, iccid, imsi, apdu <hex>) for
hardware bring-up. Limits: only the direct convention is supported, so an inverse-convention
(TS=0x3F) card will not talk; and the reference wiring powers the card from the ESP32's 3.3 V
rail through a series resistor — adequate for
bench work, but a proper 3.0 V load switch and an open-drain buffer are wanted for anything
beyond it.
Open items
Filed in the issue tracker:
- Clock does not advance after being set, all models (#1).
- Charger connected: no animating charge bars, and the phone may show "Not Charging" (#2).
- 2100: the Security-code screen rejects the EEPROM-baked code 12345 (#3).
Accessory and backlight modelling:
- Headset accessory detection is incomplete. Standby shows "Headset" on the 5110, 5130, 5190, 6110, 6130, 6150, 6210, 6250 and 8810, i.e. the accessory reads as permanently connected.
- Backlight control lines are not mapped on the 3210, 7110 and 8810. These models drive the keypad and LCD backlights from a single control line; later models split the two for independent control, which is what makes the rhythmic-backlight effects possible.
Radio and SIM:
EF_LOCIis cleared on every boot, because ROM-4 implements registration only as a full Location Update.- The 6130 reaches standby without registering, unlike the 6110 and 6150 on the same config.
- The 5110 family (5110, 5130, 5190) reaches standby without registering.
- Radio is untested on the 8855 and the 2100.
- The real-SIM bridge supports only the direct convention; inverse-convention (
TS=0x3F) cards will not talk.
Not modelled, and wanted:
- IrDA (#7).
- A more generic SIM layer, e.g. onomondo or osmo-remsim (#6).
- A real GSM connection via Osmocom rather than the synthetic cell (#5).
Acknowledgements
This project stands on two decades of open Nokia DCT3 reverse-engineering. It would not exist without the people and projects that mapped this hardware first:
- blacksphere — the collective of hackers who reverse-engineered the DCT3 debug interfaces, firmware and hardware, and crucially the DSP↔CPU interface (the GSM L1/L2 boundary) that our DSP co-simulation models. The foundational work that made all of this tractable.
- g3gg0 (Georg Hofstetter) — MADos, the alternative open-source DCT3 firmware/OS
(LGPL-2.1). Ground-truth for the DSP block layout and the MCU↔DSP mailbox; our DSP blocks are
byte-identical to its
dspblocks/. - Vitaly Nevzorov (original author, 2002) and [Yak] (2005) — NokiX, the DCT3
firmware-modification SDK: it patches an original flash image via Rexx scripts and can compile
new C functionality and inject it into the firmware, emitting a modified flash. Our
tools/nokix/script runner and symbol auto-locator descend from its LOCATE scripts. (NokiX modifies firmware; it is not a flasher.) - AlexD — the 5110 DSP ROM4 dump. The recovered TMS320C54x DSP image that our C54x co-simulation actually executes traces back to this work.
- osmocom-bb — the open Calypso DSP API, the Rosetta stone for the MCU↔DSP mailbox.
- gnokii / Gammu (and
dct3trac) — the FBUS/MBUS service-protocol RE and the NHM-5 trace dictionary that names our broker events. - Jumar Macato (jmacato) — direct contributor: built the phone-side DSP engine behind the GSM network emulation (registration, SMS, incoming calls) and the event-driven DSP runtime. The GSM signalling (RR/MM/CC over LAPDm and the MDI ring format), the DSP↔MCU camp/registration handshake our faithful DSP engine models, and the consolidated NHM-5 register-and-protocol reference for RTC and SMS (CP/RP, SMS-DELIVER, EF_SMS storage, Smart-Messaging ringtones) are the ground-truth this network layer is built on.
- bitplane — nokia-dct3-re: DCT3 reverse engineering and a MAME driver, whose 3210 DSP message-format documentation informed the DSP↔MCU modelling and the external-EEPROM FAID provisioning here.
Vendored third-party code (see third_party/ for licenses):
- mGBA ARM core — Vicki Pfau (endrift), adapted to DCT3's big-endian ARM (MPL-2.0).
- qemu-calypso / bbaranoff C54x — the TMS320C54x interpreter our DSP co-sim is built on (GPL-2).
- swSIM / swICC — software SIM stack, © 2024 Tomasz Lisowski (BSD-3-Clause;
third_party/swsim/,third_party/swicc/). - stb_image — Sean Barrett.
Any errors or misattributions here are ours, not theirs — corrections welcome.
Licensing
Released under the GNU General Public License v2 (see LICENSE). The native builds
statically link the GPL-2 C54x DSP interpreter under third_party/c54x/, which makes GPL-2 the
governing license for the combined native binaries.