Skip to content

HackerCorpLabs/nd100x

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

244 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nd100x

Build & Release RISC-V (Milk-V Duo) Latest Release Platforms

ND-100/CX minicomputer emulator written in C. Full CPU emulation with MMS1/MMS2 memory management, SMD and floppy disk controllers, HDLC networking, DAP debugger, telnet server, and a glassmorphism browser UI via WebAssembly.

For more information about the ND-100 series of minicomputers: https://www.ndwiki.org/wiki/ND-100

Try it in your browser

Run the emulator directly at https://nd100x.hackercorp.no/ — no download or install required. WebAssembly build with full terminal, debugger, and SINTRAN OS inspection tools.

Quick start

Pre-built binaries for Linux (x64, arm64), Windows (x64), macOS (arm64), and RISC-V (Milk-V Duo, musl) are on the Releases page.

Build from source on Linux:

sudo apt install -y build-essential cmake git libcurl4-openssl-dev libncurses-dev
git clone https://github.com/HackerCorpLabs/nd100x.git
cd nd100x && git submodule update --init --recursive
make release
build_release/bin/nd100x --boot=smd

Origins

This project (nd100x) is a fork of nd100em, started in 2025 by Ronny Hansen. It remains under the GNU General Public License (GPL v2 or later).

Based on nd100em version 0.2.4 by Per-Olof Astrom, Roger Abrahamsson, Zdravko Dimitrov, and Goran Axelsson. The original project can be found at https://github.com/tingox/nd100em and https://www.ndwiki.org/wiki/ND100_emulator_project.

Status

Version 1.0.7

The emulator is under active development.

  • Full ND-100/CX instruction set implemented (including BCD opcodes).
  • All test programs validate the CPU, Memory Management and Devices.
  • Boots SINTRAN L from SMD in 6-7 seconds on a modern machine.

Improvements

This project continues from nd100em version 0.2.4 and includes significant enhancements:

  • Opcode Improvements
    • Added support for missing opcodes
    • Fixed bugs in several instructions
  • Memory Management
    • Fully re-implemented with support for MMS1 and MMS2
    • Proper TRAP generation for Page Faults and Access Violations
  • IO Subsystem
    • Complete rewrite: now single-threaded and simplified
    • Old IO code has been removed
  • Supported IO Devices
    • Real-Time Clock (20ms tick emulation pending for full SINTRAN compatibility)
    • Console and additional terminals (up to 11 terminals, with telnet server for remote access)
    • Floppy (PIO and DMA) for 8" and 5.25" formats
    • SMD Hard Disk (75MB, 4 units)
    • Paper Tape Reader (buffer-based, BPUN file loading via CLI or Glass UI upload)
    • Paper Tape Punch (output to file and Glass UI hex/ASCII display with download)
    • Line Printer (CDC 9380, output to file and Glass UI window)
    • HDLC (High-Level Data Link Control) networking
  • Codebase Modernization
    • Removed requirement for libconfig and the supporting .conf file. All options are now given on the command line.
    • Refactored folder structure
    • Automatic function header generation via mkptypes (by Eric R. Smith)

Project Goals

  • Focus on ND-100 CPU and controllers.
    • The newer CPU's (ND-110 and ND-120) is mostly hardware/performance improvements, with some new opcodes to support SINTRAN and COBOL running with better performance.
    • Focus on getting these opcodes into this emulator has very low priority, as SINTRAN doesnt require an ND-110 or ND-120 CPU.
  • Refactor, re-structure and modernize code so its easier to extend
  • Multiple frontends and build targets
    • Native Linux, Windows and macOS builds
    • WebAssembly (WASM) Glass UI for running the emulator in the browser
    • RISC-V cross-compilation
    • DAP debugger integration for step-by-step debugging
  • Planned
    • Ethernet and SCSI device emulation

Project Structure

The project is organized into several key components:

  • src/cpu/ - CPU emulation implementation
  • src/devices/ - Device emulation (I/O, peripherals)
  • src/machine/ - Machine state and main emulation loop
  • src/ndlib/ - Supporting library functions (loading BPUN and a.out formats++)
  • src/debugger/ - DAP Debugger supporting functionality
  • src/frontend/ - User interface and emulator frontend(s)
  • tools/ - Development and build tools
  • images/ - Norsk-Data SMD disk, floppy and BPUN files.
  • build/ - Build output directory

Build Requirements

  • Linux (Ubuntu 22.04 or later) or macOS (12 Monterey or later)
  • GCC or Clang compiler
  • CMake 3.14+
  • Make build system
  • mkptypes tool (automatically built during compilation)

Installing dependencies on Ubuntu/Debian

On a clean Ubuntu install, run:

sudo apt update
sudo apt install -y build-essential cmake git libcurl4-openssl-dev libncurses-dev

What each package provides:

Package Purpose
build-essential gcc, g++, make
cmake CMake 3.14+ build system
git needed to clone the repo and fetch submodules
libcurl4-openssl-dev downloading floppy database images over HTTP/HTTPS
libncurses-dev F12 floppy-database browser and terminal UI

libcurl and ncurses are required on Linux builds — find_package(CURL REQUIRED) and find_package(Curses REQUIRED) in CMakeLists.txt will fail the configure step if they are missing. They are skipped automatically on RISC-V and WebAssembly builds.

Note on package names: older docs reference libncurses5-dev, which is no longer available on Ubuntu 24.04+ — use libncurses-dev instead.

On FreeBSD:

pkg install curl ncurses

Note: The floppy database browser requires an internet connection to download the catalog at runtime.

Building the Project

  1. Clone the repository:
git clone https://github.com/HackerCorpLabs/nd100x.git
cd nd100x

git submodule update --init --recursive
  1. Build the project:
  • For debug build (default):
make debug
  • For release build:
make release
  • For build with sanitizers:
make sanitize

Building on Windows

A native Windows build is produced via MinGW-w64 — either w64devkit (portable, no installer) or MSYS2 MINGW64. The CMake root picks up _WIN32 automatically and forces the Ninja generator.

Quick path (w64devkit):

  1. Download and extract w64devkit to C:\Utils\w64devkit\ (or set W64DEVKIT to wherever you unpacked it).

  2. From a regular cmd.exe at the repo root:

    build.bat debug

    That stages w64devkit\bin on PATH for the session, runs make debug, and leaves build\bin\nd100x.exe ready to run. Use build.bat release for an optimised build, build.bat clean to wipe build directories.

Current limitations on Windows (these are gated at build time; Linux is unaffected):

  • --debugger (DAP server) is unavailable — external/libdap uses POSIX-only socket headers and hasn't been ported yet.
  • --boot=aout is unavailable — external/libsymbols needs the same treatment.
  • The F12 floppy-database browser is compiled out — it uses ncurses, which w64devkit doesn't ship. Use --boot=bpun, --boot=floppy, or --boot=smd with a local image instead.
  • libcurl is optional. If missing, HTTP image-URL loads fall back to stubs; local disk images still work. Install mingw-w64-x86_64-curl under MSYS2 to restore URL loads.

BPUN, SMD, floppy boot and the telnet server all work natively on Windows.

Glass Web UI

The emulator includes a glassmorphism browser frontend (the "Glass UI") that runs the full ND-100 emulator in your browser. The live version at https://nd100x.hackercorp.no/ has been upgraded to use this layout.

Build and run locally:

make wasm-glass-run

Features include draggable/resizable floating windows, authentic Norsk Data TDV-2200/TDV-2215 terminal emulation via RetroTerm (with virtual TDV keyboard, VT100 also supported, xterm.js available by config), a full CPU debugger with breakpoints and disassembly, SINTRAN III operating system inspection tools, a hardware page table viewer, Line Printer and Paper Tape device windows, and 5 switchable color themes.

The Glass UI source lives in template-glass/ (1 HTML, 2 CSS, 35 JS modules, 1 JSON data file). For the full architecture reference, see GLASS.md.

Gateway Server

The gateway (tools/nd100-gateway/gateway.js) bridges the browser-based WASM emulator to local resources that a browser cannot access directly: disk images on the local filesystem, TCP terminal clients (PuTTY, telnet), and HDLC serial links.

Remote terminal (PuTTY/telnet) --TCP--> Gateway --WebSocket--> WASM Worker
Disk I/O sub-worker            --WebSocket--> Gateway --fs read/write--> local .IMG files
HDLC TCP client                --TCP--> Gateway --WebSocket--> WASM Worker

All traffic is multiplexed over a single WebSocket connection using a binary frame protocol (first byte = message type). Disk I/O uses block-level read/write requests — full disk images are never transferred over the wire.

cd tools/nd100-gateway
npm install
node gateway.js --static ../../build_wasm_glass/bin --verbose

Configuration is in tools/nd100-gateway/gateway.conf.json: WebSocket port (default 8765), TCP terminal port (default 5001), HDLC channel ports, and paths to SMD/floppy disk images. The --static flag serves the Glass UI with the required COOP/COEP headers for SharedArrayBuffer support.

Updating Git submodules

Sometimes the submodules are updated and you need to manually refresh them

  • git submodule update --init --recursive

Command Line Options for nd100x

The emulator supports the following command line options:

Usage: build/bin/nd100x [options]

Options:
  -b,      --boot=TYPE    Boot type (bp, bpun, aout, floppy, smd)
  -i,      --image=FILE   Image file to load (aout, bpun, floppy only)
           --smd0=FILE    SMD unit 0 disk image (default: SMD0.IMG)
           --smd1=FILE    SMD unit 1 disk image (default: SMD1.IMG)
           --smd2=FILE    SMD unit 2 disk image (default: SMD2.IMG)
           --smd3=FILE    SMD unit 3 disk image (default: SMD3.IMG)
  -s,      --start=ADDR   Start address (default: 0)
  -a,      --disasm       Enable disassembly output
  -d,      --debugger     Enable DAP debugger
  -p PORT, --port=PORT    Set debugger port (default: 4711)
  -S,      --smd-debug    Enable SMD disk controller debug log (stderr)
  -t,      --trace        Enable CPU execution trace to stderr
  -n N,    --max-instr=N  Stop after N instructions
  -B ADDR, --breakpoint=ADDR  Stop at address (octal/hex/decimal)
  -T ADDR, --text-start=ADDR  Text segment load address for a.out (default: 0)
  -v,      --verbose      Enable verbose output
  -P DIR,  --printdir=DIR  Printer output directory (default: ./prints/)
  -D DIR,  --tapedir=DIR   Paper tape output directory (default: ./tapes/)
  -e FILE, --tape=FILE     Paper tape reader input file (.bpun)
  -N[PORT],--telnet[=PORT] Enable telnet server (default port: 9000)
  -r TYPE, --printer=TYPE  Printer emulation: text (default), escp, laser
  -f FMT,  --printformat=FMT  Output format: txt (default), pdf
  -H CFG,  --hdlc=CFG     Enable HDLC controller (up to 4x)
                          Server: --hdlc=N:PORT  (N=1-4)
                          Client: --hdlc=N:HOST:PORT
  -O,      --overlay-deposit Deposit data_click at phys word 1 for kernel boot-info
  -R[N],   --ring-dump[=N]  Dump last N instructions on halt/crash (default: 50, max: 512)
  -Z[MHZ], --throttle[=MHZ] Throttle CPU to real-time speed (default: 0.5275 MHz)
  -h,      --help         Show this help message

Examples:
  build/bin/nd100x --boot=bpun --image=test.bpun
  build/bin/nd100x --boot=floppy --image=disk.img --start=0x1000 --disasm
  build/bin/nd100x --debugger
  build/bin/nd100x --hdlc=1:1362                  # HDLC 1 server on port 1362
  build/bin/nd100x --hdlc=1:192.168.1.10:1362     # HDLC 1 client
  build/bin/nd100x --boot=smd --smd0=myboot.img --smd1=data.img
  build/bin/nd100x --hdlc=1:5000 --hdlc=2:5001    # Two HDLC devices
  build/bin/nd100x --boot=smd --telnet=9000        # SINTRAN with telnet server
  build/bin/nd100x --boot=smd --throttle           # Real-time CPU speed

Boot Types:

  • smd: SMD disk boot (default)
  • bp: Boot program
  • bpun: Boot program unprotected
  • aout: BSD 2.11 a.out format
  • floppy: Floppy disk boot

Block devices (Floppy and SMD)

Default image file names (looked up in the current directory):

  • Floppy: FLOPPY.IMG
  • SMD: SMD0.IMG, SMD1.IMG, SMD2.IMG, SMD3.IMG

SMD images can be overridden per unit with --smd0=FILE through --smd3=FILE. Other floppy images can be mounted at runtime via the F12 menu.

Running SINTRAN in the Emulator

The emulator requires a system image file (SMD0.IMG) to run. Place the image file in the project root directory.

To boot a SINTRAN image from an SMD disk

build/bin/nd100x --boot=smd 

Read more about how to boot sintran

Boot Animation

Booting TPE-MON from floppy and running test programs

The emulator requires a floppy image to boot from. Place the image file in the current directory.

cp images/Nd-210523I01-XX-01D.img FLOPPY.IMG
build/bin/nd100x --boot=floppy

Now you have access to test programs like CONFIG, PAGING, INSTRUCTION and more.

I/O Devices

Paper Tape Reader (I/O 0400-0403)

Reads BPUN tape images loaded via the --tape CLI option or the Glass UI file upload. Used by TPE and SINTRAN as logical device 2.

Paper Tape Punch (I/O 0410-0413)

Accumulates punched output in memory. In native mode, output is saved to files in the tape directory (default: ./tapes/). In the Glass UI, a hex/ASCII display shows punched bytes with a download button.

Line Printer (I/O 0430-0433)

CDC 9380 line printer emulation. In native mode, output is saved to files in the print directory (default: ./prints/). In the Glass UI, a dedicated window shows printer output in real-time.

HDLC Controller

COM 5025-based HDLC (High-Level Data Link Control) communication controller. Up to 4 HDLC devices can be configured, each operating as either a TCP server or client for point-to-point serial links. Supports DMA transfers, CRC calculation, and full interrupt handling. Enable with --hdlc=N:PORT (server) or --hdlc=N:HOST:PORT (client). Live status monitoring available via the F12 menu.

Virtual Screen Switching (Native)

Press Alt+1 through Alt+9 to switch directly between virtual screens (Console, terminals, Line Printer, Paper Tape Punch, Log). Press F12 for the unified menu offering Floppy Database Browser, Virtual Screen Selector, HDLC Status, CPU Speed, Pending Connections viewer, and About screen. Only terminal screens accept keyboard input; device screens are output-only.

Telnet Server (Native)

Enable with --telnet[=PORT] (default port 9000). Provides remote terminal access to terminals 8-11. Multiple clients can connect simultaneously and select from available terminals. Features include:

  • Non-blocking accept with concurrent pending client handling
  • 60-second auto-disconnect for idle pending connections
  • Live monitoring of pending connections with rx/tx byte stats (via F12 menu)
  • Per-terminal rx/tx byte counters visible in the Virtual Screen Selector
  • Press Enter to auto-connect to the first available terminal
  • Race-safe selection: if two clients pick the same terminal, the second gets a "busy" message and a refreshed list instead of a silent redirect
  • Immediate disconnect with message when no terminals are free

Floppy Menu

The emulator includes a built-in floppy disk browser that allows you to browse and mount floppy disk images from the ND100 floppy database.

Accessing the Menu

While the emulator is running, press F12 to open the floppy menu.

Menu Animation

Menu Features

  • Browse Database: View all available floppy disk images from the online database
  • Search Functionality: Search for floppies by name, reference, or directory content
  • Detailed Information: View detailed information about each floppy including description, reference and directory content
  • Mount Capability: Mount selected floppy disks to floppy drive units 0, 1 or 2

Requirements

  • Internet connection (required to download floppy database).
  • Terminal that supports F12 key

Floppy database is available directly at https://ndlib.hackercorp.no/

Assembling your own programs

Using the assembly tool from Ragge nd100-as you can compile ND assembly to a.out format and load into the emulator.

This assembler is following the AT&T syntax so it differs a bit from the ND-100 MAC assembler.

lda foo
sta bar
opcom


bar: .word 11
foo: .word 22

Remember to end your code with 'opcom' to make the emulator stop executing your code.

Overview of all assembly instructions

Multiple systems

The nd100x emulator has been compuiled and tested on multiple different systems. For more information, read the Tested systems document

Releases (GitHub Actions)

Pre-built binaries for Linux, Windows, macOS, and RISC-V (Milk-V Duo) are produced automatically by .github/workflows/build-release.yml. The workflow runs on every push to main and on pull requests as a CI check, and publishes a GitHub Release whenever a tag matching v* is pushed.

Artifact Target How it's built
nd100x-linux-x64.tar.gz Linux x86_64 (glibc 2.35+) ubuntu-22.04, apt-installed build-essential cmake libcurl4-openssl-dev libncurses-dev, make release
nd100x-linux-arm64.tar.gz Linux aarch64 (glibc 2.35+) ubuntu-22.04-arm (GitHub-hosted ARM runner), same toolchain as x64
nd100x-linux-riscv64.tar.gz RISC-V 64 Linux musl (Milk-V Duo, CV1800B/C906) ubuntu-22.04 cross-compile using Milk-V's host-tools toolchain (riscv64-unknown-linux-musl-gcc, -march=rv64gc -mabi=lp64d); smoke-tested with qemu-user-static
nd100x-windows-x64.zip Windows 64-bit windows-latest, MSYS2 MINGW64 (mingw-w64-x86_64-gcc + ninja), make release
nd100x-macos-arm64.tar.gz macOS Apple Silicon macos-latest, Homebrew cmake, make release
SHA256SUMS.txt All of the above sha256sum over every release artifact — verify with sha256sum -c SHA256SUMS.txt

The Windows zip contains nd100x.exe plus every non-system DLL the exe depends on (libcurl + its transitive deps, libgcc_s_seh-1, libwinpthread-1, ...), the repo's bundled images/ directory, README.md, and LICENSE. DLL discovery is driven by ldd so the bundle tracks whatever MSYS2 ships — no hardcoded list to maintain.

The Linux and macOS tarballs bundle just the nd100x binary plus images/, README.md, and LICENSE. They link dynamically against libcurl and libncurses; install those at runtime via your distro's package manager (see Installing dependencies on Ubuntu/Debian).

Cutting a release

Tag-driven, no manual button pressing:

git tag v1.0.7
git push origin v1.0.7

The tag push fans out to all build jobs in parallel (Linux x64/arm64, Windows x64, macOS arm64, and RISC-V Milk-V Duo). Once they finish, the release job downloads every artifact, repackages each one in its native format (.zip for Windows, .tar.gz for Linux/macOS/RISC-V), generates SHA256SUMS.txt, and publishes a GitHub Release with auto-generated release notes (commit log since the previous tag, contributor list, "What's Changed" links).

If a build job fails the release is not published — needs: [build-linux, build-windows, build-macos, build-riscv] blocks the publish step until every platform succeeds, and fail_on_unmatched_files aborts if any expected artifact is missing.

Manual dispatch and CI runs

  • Push to main — runs every build job as a CI check; no release is created.
  • Pull request to main — same, plus concurrency.cancel-in-progress: true cancels superseded PR builds to save runner minutes.
  • Actions → Build & Release → Run workflow (workflow_dispatch) — manual dry build, no release published.

License

See the LICENSE file for detailed licensing information.

Contributing

See the CONTRIBUTING.md file for more information

TODO

  • OPCOM implementation
    • Emulation of OPCOM for memory inspection when CPU is in STOP mode.
    • Currently STOP mode exits the emulator
  • Clean up code and standardise on 8,16,32 and 64 bit signed and unsigned names for types

About

ND-100 Emulator written in C

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors