The Pico-286 project is an endeavor to emulate a classic PC system, reminiscent of late 80s and early 90s computers, on the Raspberry Pi Pico (RP2040/RP2350 microcontroller). It aims to provide a lightweight and educational platform for experiencing retro computing and understanding low-level system emulation. ๐ฅ๏ธโจ
All graphics card emulations support standard text display modes for character-based applications:
๐ Standard Text Modes:
๐ Advanced CGA Text Modes (8088 MPH Demo Techniques):
The CGA emulation provides authentic IBM Color Graphics Adapter functionality, supporting the classic early PC graphics modes:
๐ฎ Graphics Modes:
The Hercules Graphics Card emulation recreates the popular monochrome high-resolution graphics standard:
๐ฅ๏ธ Graphics Mode:
The Enhanced Graphics Adapter emulation provides IBM EGA compatibility with full 16-color support:
๐ Enhanced Graphics Modes:
The Tandy Graphics Adapter emulation recreates the enhanced graphics capabilities of Tandy 1000 series computers:
๐ Enhanced Graphics Modes:
The VGA emulation provides comprehensive Video Graphics Array support with planar memory architecture and multiple advanced modes:
๐ Standard VGA Modes:
๐ง VGA Technical Features:
The emulator supports two primary types of storage: virtual disk images for standard DOS drives (A:, B:, C:, D:) and direct access to the host filesystem via a mapped network drive (H:).
The emulator supports up to two floppy disk drives (A: and B:) and up to two hard disk drives (C: and D:). Disk images are stored on the SD card.
The emulator expects the following file paths and names for the disk images:
\\XT\\fdd0.img\\XT\\fdd1.img\\XT\\hdd.img\\XT\\hdd2.imgImportant Notes:
For seamless file exchange, the emulator can map a directory from the host filesystem and present it as drive H: in the DOS environment. This feature is implemented through the standard DOS network redirector interface (INT 2Fh, Function 11h).
This is ideal for development, allowing you to edit files on your host machine and access them instantly within the emulator without modifying disk images.
The emulator intercepts file operations for drive H: and translates them into commands for the hostโs filesystem. To enable this drive, you must run the MAPDRIVE.COM utility within the emulator.
The mapped directory depends on the platform:
C:\\FASM directory by default./tmp directory by default.//XT// directory on the SD card.MAPDRIVE.COM UtilityThe tools/mapdrive.asm source file can be assembled into MAPDRIVE.COM using FASM. This utility registers drive H: with the DOS kernel as a network drive.
Prerequisite: Before using MAPDRIVE.COM, ensure your CONFIG.SYS file contains the line LASTDRIVE=H (or higher, e.g., LASTDRIVE=Z). This tells DOS to allocate space for drive letters up to H:, allowing MAPDRIVE.COM to successfully create the new drive.
To use it:
mapdrive.asm to mapdrive.com.mapdrive.com to your boot disk image (e.g., fdd0.img or hdd.img).MAPDRIVE.COM from the DOS command line.MAPDRIVE.COM to your AUTOEXEC.BAT to automatically map the drive on boot.The Pico-286 emulator is designed to run on Raspberry Pi Pico (RP2040) based hardware. ๐
The emulator automatically detects and configures various PSRAM hardware:
Memory Detection: Runtime PSRAM size detection (16MB, 8MB, 4MB, 1MB) with validation through test patterns
The emulator has a default GPIO pin configuration for its peripherals on the Raspberry Pi Pico. These are defined in CMakeLists.txt and can be modified there if needed.
| Peripheral | GPIO Pin(s) | Notes |
|---|---|---|
| VGA Output | 6 (base pin) | Sequential pins used for RGB |
| HDMI Output | 6 (base pin) | ย |
| NTSC TV Out | 22 | Composite video output |
| TFT Display | CS: 6, RST: 8, LED: 9, DC: 10, DATA: 12, CLK: 13 | ST7789 driver |
| SD Card | CS: 5, SCK: 2, MOSI: 3, MISO: 4 | SPI0 |
| PSRAM | CS: 18, SCK: 19, MOSI: 20, MISO: 21 | Generic external PSRAM |
| NES Gamepad | CLK: 14, DATA: 16, LAT: 15 | Used for mouse emulation if needed |
| I2S Audio | CLOCK: 17, PCM: 22 | ย |
| PWM Audio | Beeper: 28, L: 26, R: 27 | ย |
The emulatorโs resource allocation changes based on the target platform and build options.
RAM_SIZE)This is the amount of memory available to the emulated PC as conventional memory (e.g., the classic 640KB).
| Platform | Memory Configuration | Available RAM |
|---|---|---|
| Host | N/A | 640 KB |
| RP2350 | PSRAM (default) | 350 KB |
| RP2350 | Virtual Memory | 200 KB |
| RP2040 | PSRAM (default) | 116 KB |
| RP2040 | Virtual Memory | 72 KB |
SOUND_FREQUENCY)The audio quality depends on the platform and the chosen audio output method.
| Platform | Audio Option | Sample Rate |
|---|---|---|
| Any | HARDWARE_SOUND=ON |
44100 Hz |
| Host | Any other option | 44100 Hz |
| RP2350 | Any other option | 44100 Hz |
| RP2040 | Any other option | 22050 Hz |
To run more advanced DOS applications and games, the emulator supports two types of extended memory systems, providing memory beyond the conventional 640KB limit. The active system is chosen at compile time.
This is the high-performance default method, used when a hardware PSRAM chip is available.
ONBOARD_PSRAM=ON option. For external PSRAM, ensure the pinout is correct.This is a fallback system for hardware that lacks a PSRAM chip, primarily intended for memory-constrained RP2040 boards.
pagefile.sys located in the \\XT\\ directory on the SD card. The Picoโs internal RAM is used as a cache for memory โpagesโ. When the requested memory is not in the cache (a page fault), it is read from the SD card.TOTAL_VIRTUAL_MEMORY_KBS to a non-zero value (e.g., -DTOTAL_VIRTUAL_MEMORY_KBS=512). This will automatically disable the PSRAM driver.The emulator uses different architectures depending on the target platform to best utilize the available resources.
The Pico build takes full advantage of the RP2040/RP2350โs dual-core processor.
exec86) and handles user input from the PS/2 keyboard and NES gamepad.This division of labor ensures that the demanding CPU emulation does not interfere with smooth video and audio output.
The host builds (for Windows and Linux) are multi-threaded to separate tasks.
exec86) and handles the window and its events via the MiniFB library.QueryPerformanceCounter on Windows, clock_gettime on Linux) to trigger events like PIT timer interrupts, rendering updates, and audio sample generation at the correct frequencies.This architecture allows for accurate timing and responsive I/O on a non-real-time desktop operating system.
The project uses CMake with platform-specific configurations. All builds require exactly one display option and one audio option.
ENABLE_NTSC-TV=ON - NTSC TV output (locks CPU frequency to 315MHz)ENABLE_TFT=ON - TFT display output via ST7789ENABLE_VGA=ON - VGA outputENABLE_HDMI=ON - HDMI output (dynamic frequency: 504MHz for Pico2, 378MHz for others)ENABLE_I2S_SOUND=ON - I2S digital audio outputENABLE_PWM_SOUND=ON - PWM audio outputENABLE_HARDWARE_SOUND=ON - Hardware DAC audio outputONBOARD_PSRAM=ON - Use onboard PSRAM (RP2350 only)ONBOARD_PSRAM_GPIO=19 - GPIO pin for onboard PSRAMTOTAL_VIRTUAL_MEMORY_KBS=512 - Enable virtual memory instead of PSRAM. Note: Setting this to any value greater than 0 will disable PSRAM support.CPU_FREQ_MHZ=500 - Set CPU frequency (default varies by platform)FLASH_FREQ_MHZ=100 - Flash frequency configurationPSRAM_FREQ_MHZ=166 - PSRAM frequency timing# Clone the repository
git clone <repository-url>
cd pc
# Create build directory
mkdir build && cd build
# Configure for RP2350 with VGA and PWM audio
cmake -DCMAKE_BUILD_TYPE=Release \
-DPICO_PLATFORM=rp2350 \
-DENABLE_VGA=ON \
-DENABLE_PWM_SOUND=ON \
..
# Build
make -j$(nproc)
# Configure for RP2040 with TFT and I2S audio
cmake -DCMAKE_BUILD_TYPE=Release \
-DPICO_PLATFORM=rp2040 \
-DENABLE_TFT=ON \
-DENABLE_I2S_SOUND=ON \
..
# Build
make -j$(nproc)
# Install dependencies (Ubuntu/Debian)
sudo apt update
sudo apt install build-essential cmake git libx11-dev
# Clone and build
git clone <repository-url>
cd pc
mkdir build && cd build
# Configure for Linux host platform
cmake -DCMAKE_BUILD_TYPE=Release \
-DPICO_PLATFORM=host \
..
# Build
make -j$(nproc)
# Configure for host platform (development/testing)
cmake -DCMAKE_BUILD_TYPE=Release \
-DPICO_PLATFORM=host \
..
# Build
make -j$(nproc)
# On Windows with Visual Studio: cmake --build . --config Release
cmake -DCMAKE_BUILD_TYPE=Release \
-DPICO_PLATFORM=rp2040 \
-DTOTAL_VIRTUAL_MEMORY_KBS=512 \
-DENABLE_VGA=ON \
-DENABLE_PWM_SOUND=ON \
..
cmake -DCMAKE_BUILD_TYPE=Release \
-DPICO_PLATFORM=rp2350 \
-DENABLE_HDMI=ON \
-DENABLE_I2S_SOUND=ON \
-DCPU_FREQ_MHZ=504 \
-DFLASH_FREQ_MHZ=100 \
-DPSRAM_FREQ_MHZ=166 \
..
cmake -DCMAKE_BUILD_TYPE=Release \
-DPICO_PLATFORM=rp2350 \
-DENABLE_VGA=ON \
-DENABLE_PWM_SOUND=ON \
-DMURM20=ON \
..
# Build all firmware variants automatically
./build_all_firmwares.sh
# Merge RP2040/RP2350 firmware pairs
./merge_firmwares.sh
After successful compilation, build artifacts are placed in the bin/<platform>/<build_type>/ directory.
286 (Linux) or 286.exe (Windows).The firmware filename is dynamically generated to reflect the build configuration, following this pattern:
286-<platform>-F<flash>-P<psram>-<cpu_freq>-<display>-<audio>.uf2
<platform>: RP2040 or RP2350.F<flash>: Flash frequency (e.g., F100 for 100MHz).P<psram>: PSRAM frequency (e.g., P166 for 166MHz).<cpu_freq>: CPU frequency in MHz (e.g., 504MHz).<display>: TFT, VGA, HDMI, or NTSC.<audio>: I2S, PWM, or HW (Hardware).Example Filenames:
286-RP2350-F100-P166-504MHz-HDMI-I2S.uf2 (Pico2 with HDMI, Butter-PSRAM)286-RP2350-F100-P166-378MHz-VGA-PWM.uf2 (Pico2 with VGA, external PSRAM)286-RP2040-F100-P166-366MHz-VGA-PWM.uf2 (RP2040 with VGA)The following files are generated:
.uf2: The firmware file for flashing to the Pico..elf: The executable file for debugging..bin: The raw binary file..uf2 file to the mounted RPI-RP2 driveCreate the required directory structure on your SD card:
SD Card Root/
โโโ XT/
โโโ fdd0.img # Floppy Drive A:
โโโ fdd1.img # Floppy Drive B: (optional)
โโโ hdd.img # Hard Drive C:
โโโ hdd2.img # Hard Drive D: (optional)
Place disk images in the project root directory:
# From your project directory (pc/)
# Place disk images directly in the root:
cp your-boot-disk.img fdd0.img # Floppy Drive A:
cp your-floppy2.img fdd1.img # Floppy Drive B: (optional)
cp your-harddisk.img hdd.img # Hard Drive C:
cp your-harddisk2.img hdd2.img # Hard Drive D: (optional)
# Run from build directory
cd build
../bin/host/Release/286 # Linux
# or ../bin/host/Release/286.exe # Windows
Supported disk image sizes:
Build fails with โdisplay/audio option requiredโ:
ENABLE_* option is set for both display and audioLinux build fails with โX11 not foundโ:
sudo apt install libx11-devsudo dnf install libX11-devel (Fedora) or sudo pacman -S libx11 (Arch)Host build shows โDISK: ERROR: cannot open disk fileโ:
chmod 644 *.imgls -la *.imgLinux emulator window appears but shows black screen:
fdd0.imgOut of memory errors on RP2040:
-DTOTAL_VIRTUAL_MEMORY_KBS=512HDMI not working:
ENABLE_HDMI=ON - 504MHz for Pico2, 378MHz for others)PSRAM detection issues:
Performance issues:
boards/ directory for reference designsCMakeLists.txt compile definitionsVIDEO_MODES.md for detailed mode specificationsBUILDING.md for comprehensive build instructionsrelease.md for latest changelog and improvementsContributions to the Pico-286 project are welcome! Please refer to the CONTRIBUTING.md file (to be created) for guidelines. ๐ช
This project is licensed under the MIT License. See the LICENSE file for details.