{"id":35788288,"url":"https://github.com/avwohl/mpm2","last_synced_at":"2026-01-13T20:50:35.370Z","repository":{"id":329586074,"uuid":"1120107386","full_name":"avwohl/mpm2","owner":"avwohl","description":"MP/M II Emulator for Z80 - Multi-user operating system emulator","archived":false,"fork":false,"pushed_at":"2026-01-08T06:09:26.000Z","size":11159,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-08T08:52:21.718Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Assembly","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/avwohl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-20T14:01:07.000Z","updated_at":"2026-01-08T06:09:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/avwohl/mpm2","commit_stats":null,"previous_names":["avwohl/mpm2"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/avwohl/mpm2","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fmpm2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fmpm2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fmpm2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fmpm2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/avwohl","download_url":"https://codeload.github.com/avwohl/mpm2/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fmpm2/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28400233,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-07T07:24:04.427Z","updated_at":"2026-01-13T20:50:35.365Z","avatar_url":"https://github.com/avwohl.png","language":"Assembly","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MP/M II Emulator\n\nA Z80-based MP/M II emulator with SSH terminal access. Multiple users can connect simultaneously to run CP/M-compatible software.\n\n**[MP/M II Command Reference](docs/mpm2_summary.pdf)** - Complete guide to all commands and utilities\n\n## Quick Start\n\n```bash\n# Build with DRI binaries (default, fast)\n./scripts/build_all.sh\n\n# Or build from source (requires uplm80/um80/ul80)\n./scripts/build_all.sh --tree=src\n\n# Run with local console\n./build/mpm2_emu -l -d A:disks/mpm2_system.img\n\n# Or run with SSH access (connect from another terminal)\n./build/mpm2_emu -d A:disks/mpm2_system.img\nssh -p 2222 user@localhost\n```\n\n## Binary Installation\n\nPre-built packages are available for Linux systems. Download the appropriate package and disk image from the [Releases](https://github.com/avwohl/mpm2/releases) page.\n\n### Debian/Ubuntu (.deb)\n\n```bash\n# Download and install\nwget https://github.com/avwohl/mpm2/releases/latest/download/mpm2-emu_0.3.0_amd64.deb\nsudo dpkg -i mpm2-emu_0.3.0_amd64.deb\nsudo apt-get install -f  # Install dependencies if needed\n\n# Download disk image\nwget https://github.com/avwohl/mpm2/releases/latest/download/mpm2_system.img\n\n# Run\nmpm2_emu -l -d A:mpm2_system.img\n```\n\n### Fedora/RHEL (.rpm)\n\n```bash\n# Download and install\nwget https://github.com/avwohl/mpm2/releases/latest/download/mpm2-emu-0.3.0-1.x86_64.rpm\nsudo dnf install ./mpm2-emu-0.3.0-1.x86_64.rpm\n\n# Download disk image\nwget https://github.com/avwohl/mpm2/releases/latest/download/mpm2_system.img\n\n# Run\nmpm2_emu -l -d A:mpm2_system.img\n```\n\n### What's in the Packages\n\n| Package | Contents |\n|---------|----------|\n| `.deb` / `.rpm` | `mpm2_emu` emulator binary |\n| `mpm2_system.img` | Pre-built 8MB disk image with MP/M II and utilities |\n\nThe disk image is required - it contains the MP/M II operating system, boot loader, and standard utilities.\n\n## Prerequisites\n\n### Required Dependencies\n\n| Dependency | Purpose | Installation |\n|------------|---------|--------------|\n| CMake 3.16+ | Build system | `brew install cmake` or `apt install cmake` |\n| C++17 compiler | Compile emulator | Xcode (macOS) or `apt install g++` |\n| Python 3 | Build scripts, um80/ul80 | Usually pre-installed |\n| cpmemu | Z80 CPU emulator + disk tools | Clone from github.com/avwohl/cpmemu |\n\n### External Repositories (must be cloned separately)\n\n```bash\n# Clone these as siblings to mpm2/\ncd ~/src  # or wherever you keep source\n\n# Z80 CPU emulator (required)\ngit clone https://github.com/avwohl/cpmemu.git\n\n# um80/ul80 - MACRO-80 compatible assembler/linker (required)\ngit clone https://github.com/avwohl/um80_and_friends.git\ncd um80_and_friends\npip install -e .  # Installs um80 and ul80 commands\ncd ..\n\n# uplm80 - PL/M-80 cross-compiler (required for --tree=src builds)\ngit clone https://github.com/avwohl/uplm80.git\ncd uplm80\npip install -e .  # Installs uplm80 command\ncd ..\n\n# MP/M II distribution files are included in the mpm2_external/ directory\n```\n\n### Optional: SSH Support\n\nFor network access via SSH (recommended for multi-user):\n\n```bash\n# macOS\nbrew install libssh\n\n# Linux (Debian/Ubuntu)\nsudo apt install libssh-dev\n```\n\n## Building\n\nThe project supports two binary trees:\n\n| Tree | Description | Requirements |\n|------|-------------|--------------|\n| `dri` | Original DRI binaries (default) | None - binaries included |\n| `src` | Build from source code | uplm80, um80, ul80 |\n\n```bash\ncd mpm2\n\n# Build with DRI binaries (fast, recommended)\n./scripts/build_all.sh\n\n# Build from source (compiles PL/M and assembly)\n./scripts/build_all.sh --tree=src\n```\n\nBuild steps:\n1. **[src only] build_src.sh** - Compile source code to bin/src/\n2. **build_hd1k.sh** - Creates 8MB disk image with binaries from selected tree\n3. **build_asm.sh** - Assembles LDRBIOS and BNKXIOS, builds C++ emulator, writes boot sector\n4. **gensys.sh** - Runs GENSYS to create MPM.SYS (4 consoles, 7 memory banks)\n\nOutput: `disks/mpm2_system.img` - bootable disk with MP/M II\n\n### Building from Source\n\nWhen using `--tree=src`, all utilities are compiled from the original Digital Research\nsource code using modern cross-compilers:\n\n- **uplm80** - PL/M-80 to Z80 assembly compiler\n- **um80** - MACRO-80 compatible assembler\n- **ul80** - LINK-80 compatible linker\n\nThe source build system supports local modifications in `src/overrides/` that take\nprecedence over the original source. For example, the MPMLDR has its serial number\ncheck disabled in `src/overrides/MPMLDR/MPMLDR.PLM`.\n\nWith `--tree=src`, the entire MP/M II operating system is built from source. Only 4\ndevelopment tools are binary-only (no source available):\n\n| Binary | Purpose | Note |\n|--------|---------|------|\n| RMAC.COM | Relocatable Macro Assembler | Replaced by um80 |\n| LINK.COM | Linker | Replaced by ul80 |\n| LIB.COM | Library Manager | Not needed for build |\n| XREF.COM | Cross Reference | Not needed for build |\n\nThese are included on the disk for completeness but are not used in the build process.\n\nTo build just the source binaries without creating a disk:\n```bash\n./scripts/build_src.sh\n```\n\n### Modern GENSYS\n\nThe original DRI GENSYS.COM has a bug in its relocation code (LDRLWR.ASM) that\ncorrupts SPR/BRS files when code size doesn't align well with 128-byte sectors.\nThe bug is most severe at exactly 1024 bytes where 100% of relocation uses garbage.\n\n**The Bug:** LDRLWR.ASM loads `ceil(prgsiz/128)` sectors, which includes code plus\nextra bytes from rounding. It uses these extra bytes as the relocation bitmap. When\nmore bitmap is needed, it should read from disk - but the detection check compares\nthe bitmap pointer against an unrelated buffer address (`bitmap+128`) instead of\nchecking if it exceeded the loaded data. Result: garbage is used instead of the\nactual bitmap.\n\nThis project uses a Python replacement (`tools/gensys.py`) that reads the complete\nbitmap directly from the SPR file and applies it correctly:\n\n- Fixes the bitmap relocation bug for all file sizes\n- Reads configuration from JSON instead of interactive prompts\n- Generates identical MPM.SYS output for valid inputs\n- Supports RSP modules with banked code (BRS files)\n\n### SSH Setup\n\nGenerate host key and configure user authentication:\n\n```bash\nmkdir -p keys\n\n# Generate host key (required for SSH)\nssh-keygen -t rsa -b 2048 -m PEM -f keys/ssh_host_rsa_key -N ''\n```\n\n**Authentication options:**\n\n| Mode | Configuration | Use Case |\n|------|--------------|----------|\n| Public key | `keys/authorized_keys` | Production - add user public keys |\n| Open access | `--no-auth` flag | Development - accept any connection |\n\nFor public key authentication, add authorized public keys:\n```bash\n# Add your key\ncat ~/.ssh/id_rsa.pub \u003e\u003e keys/authorized_keys\n\n# Or multiple users\ncat user1.pub user2.pub \u003e\u003e keys/authorized_keys\n```\n\nFor development/testing without authentication:\n```bash\n./build/mpm2_emu --no-auth -d A:disks/mpm2_system.img\n```\n\n## Running\n\n```bash\n./build/mpm2_emu [options] -d A:diskimage\n\nOptions:\n  -d, --disk A:FILE           Mount disk image (required)\n  -l, --local                 Local console mode (output to stdout)\n  -w, --http [IP:]PORT        HTTP server address (default: 8000, 0 to disable)\n                              Can be repeated for multiple listeners\n  --log FILE                  Access log file (default: mpm2.log)\n  -p, --port [IP:]PORT        SSH listen address (default: 2222)\n                              Can be repeated for multiple listeners\n                              Use [IPv6]:PORT for IPv6 addresses\n  -k, --key FILE              Host key file (default: keys/ssh_host_rsa_key)\n  -a, --authorized-keys FILE  Authorized keys file (default: keys/authorized_keys)\n  -n, --no-auth               Disable SSH authentication (accept any connection)\n  -t, --timeout SECS          Timeout for debugging\n  -h, --help                  Show help\n```\n\nThe emulator boots from sector 0 of the disk mounted as drive A.\n\n### Examples\n\n```bash\n# Local console - see output directly\n./build/mpm2_emu -l -d A:disks/mpm2_system.img\n\n# SSH mode - connect via ssh (requires keys/authorized_keys)\n./build/mpm2_emu -d A:disks/mpm2_system.img\nssh -p 2222 user@localhost\n\n# SSH mode without authentication (development only)\n./build/mpm2_emu --no-auth -d A:disks/mpm2_system.img\n\n# Bind to specific IP address\n./build/mpm2_emu -p 127.0.0.1:2222 -w 127.0.0.1:8000 -d A:disks/mpm2_system.img\n\n# Multiple listeners (IPv4 and IPv6)\n./build/mpm2_emu -p 127.0.0.1:2222 -p '[::1]:2222' -w 8000 -d A:disks/mpm2_system.img\n```\n\n## SFTP File Transfer\n\nThe emulator includes an integrated SFTP server for transferring files to and from the MP/M II disk. This allows you to use standard SFTP clients to upload, download, and manage files.\n\n### Connecting\n\n```bash\n# Connect with sftp (same port as SSH terminal)\nsftp -P 2222 user@localhost\n```\n\n### Path Format\n\nSFTP paths use the format `/\u003cdrive\u003e.\u003cuser\u003e/\u003cfilename\u003e`:\n\n| Path | Description |\n|------|-------------|\n| `/A.0/` | Drive A, user 0 |\n| `/B.3/TEST.COM` | Drive B, user 3, file TEST.COM |\n| `/A.0/*.TXT` | Wildcard pattern for .TXT files |\n\n### Supported Commands\n\n| Command | Description |\n|---------|-------------|\n| `ls /A.0/` | List directory |\n| `get /A.0/FILE.TXT` | Download file |\n| `put local.txt /A.0/FILE.TXT` | Upload file |\n| `rm /A.0/FILE.TXT` | Delete file |\n| `rename /A.0/OLD.TXT /A.0/NEW.TXT` | Rename file |\n\n### Example Session\n\n```bash\nsftp -P 2222 user@localhost\nsftp\u003e ls /A.0/\n/A.0/GENHEX.COM     /A.0/LIB.COM     /A.0/LINK.COM\nsftp\u003e put myfile.txt /A.0/MYFILE.TXT\nUploading myfile.txt to /A.0/MYFILE.TXT\nsftp\u003e ls /A.0/MYFILE.TXT\n/A.0/MYFILE.TXT\nsftp\u003e quit\n```\n\n### How It Works\n\nSFTP operations are handled by an RSP (Resident System Process) running inside MP/M II. The C++ emulator receives SFTP protocol messages and forwards them to the Z80 RSP via a bridge interface. The RSP performs actual file operations using BDOS calls, ensuring proper file locking and consistency with MP/M II processes.\n\nFiles involved:\n- `asm/sftp_brs.plm` - Z80 RSP code (PL/M-80)\n- `asm/sftp_glue.asm` - Assembly glue for BDOS calls\n- `src/sftp_bridge.cpp` - C++ request/reply bridge\n- `src/ssh_session_libssh.cpp` - SFTP protocol handling\n\n## HTTP File Browser\n\nThe emulator includes a read-only HTTP server for browsing and downloading files from MP/M II disks using a web browser.\n\n### Accessing\n\nOpen in any web browser:\n```\nhttp://localhost:8000/\n```\n\n### Path Format\n\n| Path | Description |\n|------|-------------|\n| `/` | List mounted drives |\n| `/a/` | Drive A, all users |\n| `/a.0/` | Drive A, user 0 only |\n| `/a/file.txt` | Download file from drive A |\n| `/a.0/file.txt` | Download file from drive A, user 0 |\n\n- URLs are case-insensitive (`/A/FILE.TXT` and `/a/file.txt` both work)\n- Directory listings show filenames in lowercase\n- Text files (.txt, .asm, .plm, etc.) are served with Unix line endings (CR stripped)\n\n### Configuration\n\n```bash\n# Default: HTTP on port 8000\n./build/mpm2_emu -d A:disks/mpm2_system.img\n\n# Custom port\n./build/mpm2_emu -w 8080 -d A:disks/mpm2_system.img\n\n# Disable HTTP server\n./build/mpm2_emu -w 0 -d A:disks/mpm2_system.img\n```\n\n### How It Works\n\nHTTP file operations share the same RSP bridge as SFTP. When an HTTP request arrives, it queues a file request to the Z80 RSP, which performs the actual disk read via BDOS calls. Requests from HTTP and SFTP clients are serialized to ensure consistent access.\n\n## Access Logging\n\nThe emulator logs HTTP, SSH, and SFTP access to a file (default: `mpm2.log`):\n\n```\n2026-01-06 23:21:19 [HTTP] 127.0.0.1 GET /\n2026-01-06 23:21:26 [SSH] 127.0.0.1 connected\n2026-01-06 23:21:26 [SSH] 127.0.0.1 auth user=test method=none\n2026-01-06 23:21:26 [SSH] 127.0.0.1 exec command=exit\n2026-01-06 23:21:29 [SSH] 127.0.0.1 disconnected\n```\n\nEach log entry includes:\n- ISO timestamp (YYYY-MM-DD HH:MM:SS)\n- Service type (HTTP, SSH, SFTP)\n- Client IP address\n- Event details (request path, auth method, command, etc.)\n\nTo use a different log file:\n```bash\n./build/mpm2_emu --log /var/log/mpm2.log -d A:disks/mpm2_system.img\n```\n\n## Project Structure\n\n```\nmpm2/\n├── scripts/\n│   ├── build_all.sh      # Master build script (--tree=dri|src)\n│   ├── build_src.sh      # Build from source code\n│   ├── build_hd1k.sh     # Create disk image with MP/M II files\n│   ├── build_asm.sh      # Assemble Z80 code, build C++, write boot sector\n│   └── gensys.sh         # Generate MPM.SYS\n├── bin/\n│   ├── dri/              # Original DRI binaries (.COM, .PRL, .SPR)\n│   └── src/              # Source-built binaries (generated)\n├── src/\n│   ├── overrides/        # Source code modifications\n│   │   ├── MPMLDR/       # MPMLDR with disabled serial check\n│   │   └── NUCLEUS/      # Kernel source overrides\n│   └── cpm_runtime.mac   # Runtime support for PL/M programs\n├── tools/\n│   ├── build.py          # Source build script (Python)\n│   ├── gensys.py         # MP/M II system generator (replaces DRI GENSYS)\n│   └── dri_patch.py      # Binary patching tool\n├── asm/\n│   ├── coldboot.asm      # Boot sector (loads MPMLDR + LDRBIOS)\n│   ├── ldrbios.asm       # Loader BIOS for boot phase\n│   ├── bnkxios.asm       # Runtime XIOS (I/O port dispatch)\n│   ├── sftp_brs.plm      # SFTP RSP banked code (PL/M-80)\n│   ├── sftp_glue.asm     # SFTP assembly glue for BDOS calls\n│   └── sftp_brs_header.asm # SFTP RSP header and entry point\n├── src/                  # C++ emulator source\n│   ├── main.cpp          # Entry point and main loop\n│   ├── http_server.cpp   # HTTP file browser\n│   ├── sftp_bridge.cpp   # SFTP/HTTP to Z80 bridge\n│   └── ssh_session_libssh.cpp # SSH/SFTP server\n├── include/              # C++ headers\n│   ├── logger.h          # Access logging\n├── build/                # CMake build directory (generated)\n├── disks/                # Disk images (generated)\n└── mpm2_external/        # MP/M II source and distribution\n    ├── mpm2src/          # Original source code\n    └── mpm2dist/         # Original binaries\n```\n\n## How It Works\n\nMP/M II is Digital Research's multi-user, multi-tasking operating system for Z80. This emulator:\n\n1. Boots from disk sector 0 (cold boot loader)\n2. Loads MPMLDR and LDRBIOS from reserved tracks\n3. MPMLDR loads MPM.SYS into high memory\n4. Provides 7 memory banks (48KB user + 16KB common each)\n5. Runs 60Hz timer interrupts for task switching\n6. Exposes 4 consoles via SSH connections\n\nThe XIOS uses I/O port traps - Z80 code does `OUT (0xE0), A` and the emulator intercepts to handle disk, console, and system functions.\n\n## Troubleshooting\n\n### \"MPM SYS ?\" error on boot\nRun `./scripts/gensys.sh` to regenerate MPM.SYS with matching serial numbers.\n\n### Build fails with \"um80 not found\"\nInstall um80/ul80: `pip install -e path/to/um80_and_friends`\n\n### SSH connection refused\nEnsure the emulator is running and check if port 2222 is available.\n\n### No output after boot\nUse `-l` flag for local console mode to see boot messages.\n\n## License\n\nGPL-3.0-or-later\n\n## References\n\n- [MP/M II Command Reference](docs/mpm2_summary.pdf) - Quick reference for all commands\n- [MP/M II System Guide](mpm2_external/docs/) - Original Digital Research documentation\n- [RomWBW](https://github.com/wwarthen/RomWBW) - hd1k disk format\n- [cpmemu](https://github.com/avwohl/cpmemu) - Z80 emulator with cpm_disk.py utility\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favwohl%2Fmpm2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Favwohl%2Fmpm2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favwohl%2Fmpm2/lists"}