diff --git a/dosbox-x/README.md b/dosbox-x/README.md new file mode 100644 index 00000000..136645c3 --- /dev/null +++ b/dosbox-x/README.md @@ -0,0 +1,484 @@ + +# DOSBox‑X Windows 98/3.1 Launcher — Current Design & Usage + +This component contains `winplay.sh` — the DOSBox‑X based Windows 9x launcher used by RetroDECK. The README below documents the current, tested implementation and recommended workflows. + +Summary of the current approach +- The launcher uses DOSBox‑X's cvhdmake tooling to create *linked differencing children* in the guest runtime (recommended) for per-game write layers. Base image creation / formatting (mkfs) still uses DOSBox‑X's imgmake where required. +- The launcher builds a temporary config file (TMP_CONF) **per run** which is passed last to DOSBox‑X so it overrides the base config when needed. +- Filenames used for per-game layers and saves are sanitized to avoid spaces and problematic characters. + +Why this README changed +- Previous flows attempted `vhdmake -diff` for differencing children inside DOSBox‑X; that exposed instabilities in some DOSBox‑X builds (double-free / mount failures). The current, supported runtime approach is to create per-game differencing children from inside DOSBox‑X using `cvhdmake -f -l ` (written into the generated `[autoexec]`). Packaging on the host also uses `cvhdmake` as the single supported host-side packaging tool for differencing children. Base image creation/formatting is still done using `imgmake` / `mkfs` where appropriate. + +--- + +Table of contents +- Key concepts +- Image layering and recommended commands +- Config merging & precedence +- Autoexec sequence created by the launcher +- Troubleshooting and common failures +- Examples + +--- + +Key concepts +- Base image — `win98.vhd` (or `win31.vhd`) shared by all games for that OS. + - Differencing child — a per-game image that stores only writes relative to the base. The child is created in the guest runtime using `cvhdmake -f -l ` as part of the autoexec; the child is then mounted as C: (so it holds both game files and savedata), keeping the base pristine. +- Save layer — optional per-game save overlay. + +Image layering and recommended commands +------------------------------------- +The approach used by the launcher is layered and lightweight: + +1) Base OS: `win98.vhd` created once (sparse file, preformatted). Created using `imgmake -t hd -size` (via `winplay.sh --makefs`). +2) Per-run write-layer / differencing child: created inside DOSBox‑X using `cvhdmake -f -l ` (written into the generated `[autoexec]`) and then mounted as C: — this keeps the base image pristine and stores all game data/saves inside the per-game child. + +Inside the generated autoexec you will typically see (these lines are written to TMP_CONF — not executed by the host shell): + +``` +cvhdmake -f -l "/path/to/base.vhd" "/path/to/game_child.vhd" +IMGMOUNT C "/path/to/base.vhd" -b "/path/to/game_child.vhd" -t hdd +IMGMOUNT D "/path/to/game.iso" -t cdrom # optional +BOOT -l C: +``` + +- Notes: +- The runtime per-game child is created with `cvhdmake -f -l ` inside the generated `[autoexec]`. This keeps the base image unchanged and stores all writes in the per-game child which is mounted on C: (so it contains both game files and savedata). +- Using `vhdmake -diff` in runtime autoexec is not recommended (it caused crashes in some DOSBox‑X builds) and therefore is avoided. + - Some DOSBox‑X builds have shown instability when `cvhdmake` or other differencing creation commands run inside the guest (e.g. double‑free in CreateDifferencing). To avoid runtime crashes, `winplay.sh` will attempt to create the per‑game child on the host (using `cvhdmake` invoked from the host DOSBox‑X) before falling back to in‑guest creation. You can also explicitly pre-create the per‑game child on the host with: + +```bash +./winplay.sh --package-game "GameName" +``` + +This is the recommended workaround when the DOSBox‑X runtime in your environment has unreliable in‑guest VHD creation support. +- The child can use any extension recognized by the DOSBox‑X binary in your runtime (`.uhd`, `.vhd`). This script historically uses `.vhd` for compatibility but `.uhd` as an extension is also used; consider consistent extension conventions if you want to change it. + +Config merging & precedence +-------------------------- +`winplay.sh` constructs a temporary config (`TMP_CONF`) for each run. Current logic: + +- If `os_configs/$WIN_VERSION.conf` exists (eg `os_configs/win98.conf`), `TMP_CONF` is created from that file. Otherwise it is created by copying the base config (`$dosbox_x_config`). +- The launcher then removes comments and rewrites an empty `[autoexec]` section in `TMP_CONF` ready to be populated. +- DOSBox‑X is invoked with multiple `-conf` arguments. Order matters — later config files override earlier ones: + + `dosbox-x -conf /path/to/dosbox-x.conf -conf /path/to/winplay.conf` + +Where `winplay.conf` (TMP_CONF) is the last config — its settings will win in case of duplicates. + +Autoexec generation and content +------------------------------ +`generate_autoexec()` in the script writes a fresh `[autoexec]` block into `TMP_CONF`. The launcher writes the differencing `cvhdmake -f -l ` call into `[autoexec]` and the IMGMOUNT command that mounts the per-game child on C:. The per-game child references the base image internally so the base does not require an explicit drive letter; the launcher then copies the BAT (AutoRun), mounts extra devices (CDs, floppies) and finally writes `BOOT -l C:`. All these commands are written into the config (not run by the host shell). + +Filename sanitization +--------------------- +To avoid issues caused by spaces and special characters when creating or referencing VHDs, `winplay.sh` sanitizes filenames used for per-game layers and save files. Sanitisation replaces path separators and runs of non-alphanumeric characters with underscores and falls back to `unnamed` if the input is empty. + +Troubleshooting +--------------- + - double-free / crash during `vhdmake -diff` — do not use `vhdmake -diff` inside autoexec; create differencing children with `cvhdmake -f -l ` instead. The runtime and packaging flows use `cvhdmake` as the single supported path for differencing children. +- IMGMOUNT cannot create drive from file / sanity check failure — verify the image was created with `imgmake` and that the boot sector and partition table are valid. +- If DOSBox‑X cannot open a logfile or complains about missing logs it may be due to file path variables inside the environment or sandboxing (Flatpak). Not critical for launch but helpful to investigate for debugging. + +Examples & quick checks +----------------------- +Example local test to validate config merging (no DOSBox launch required): + +```bash +export dosbox_x_config=/tmp/base.conf +export OS_CONFIG_DIR=/tmp/os_configs +export WIN_VERSION=win98 +export XDG_CACHE_HOME=/tmp/winplay-test +mkdir -p $XDG_CACHE_HOME/dosbox-x /tmp/os_configs +printf 'dynamic=false +cpu=auto +' > /tmp/base.conf +printf 'dynamic=true +' > /tmp/os_configs/win98.conf +# Launch with a dummy game to trigger config creation (script will write TMP_CONF) +bash ./winplay.sh --game Dummy +# Inspect the generated TMP_CONF; it should contain 'dynamic=true' (OS override wins) +sed -n '1,200p' /tmp/winplay-test/dosbox-x/winplay.conf +``` + +Contributing & maintainers +-------------------------- +If you intend to modify the runtime VHD creation behaviour or change the layering approach, keep these points in mind: + +- Prefer `cvhdmake -f -l` for runtime and packaging differencing children. `vhdmake -diff` remains problematic on some DOSBox‑X builds. +- Any change to TMP_CONF construction will impact how runtime overrides behave — ordering of `-conf` is important. +- Keep filename sanitisation behaviour consistent if you add alternate storage locations or extensions. + +--- + +If you want, I can add a diagram showing the final `-conf` order, the `[autoexec]` sequence and an example of how C:/ D:/ E:/ get assigned. Want that as an additional section? +# DOSBox-X Windows 98/3.1 Game Launcher Setup Guide + +This directory contains tools and scripts to set up Windows 98/3.1 environments for DOS gaming in DOSBox-X within RetroDECK. + +## VHD Disk Images + +### Automatic VHD Creation + +VHD disk images are created automatically on first use as **sparse files** in the `$bios_path` folder: +- `$bios_path/win98.vhd` (4GB fixed, FAT32, ~8MB on disk initially) +- `$bios_path/win31.vhd` (512MB fixed, FAT16, ~280KB on disk initially) + +**The VHD images are created on-demand** - they don't need to be pre-created or manually placed. + +**IMPORTANT - Sparse Files Explained:** +- Your **file manager will show 4GB and 512MB** respectively +- Your **actual disk usage is only ~8.3MB** for both files combined initially +- The empty space is not allocated to disk - DOSBox-X sees the full size, but no space is actually used +- As Windows writes data during installation, the files will grow on disk, but only actual data consumes space + +### Disk Size Specifications + +| OS | Image | Size | File System | On-Disk Size | Notes | +|---|---|---|---|---|---| +| Windows 98 | win98.vhd | 4GB | FAT32 | ~8MB (sparse) | Maximum era-appropriate for Windows 98 | +| Windows 3.1 | win31.vhd | 512MB | FAT16 | ~280KB (sparse) | FAT16 more reliable than FAT12 for larger disks | + +** IMPORTANT - Sparse Files:** + +| What You See | What's Real | +|---|---| +| File manager: 4GB + 512MB = 4.5GB total | Actual disk: ~8.3MB total (grows as needed) | +| DOSBox-X sees: Full 4GB + 512MB drives | Filesystem usage: only what's written | + +These are **sparse files** - they appear as full size to DOSBox-X but only use actual disk space as Windows writes data to them. Don't be alarmed if your file manager shows 4GB - that's normal for sparse files. + +### Manual VHD Creation + +To manually create or recreate VHD images, use the `--makefs` argument with `winplay.sh`: + +```bash +# Create Windows 98 base image (4GB FAT32) +./winplay.sh --makefs win98 + +# Create Windows 3.1 base image (512MB FAT16) +./winplay.sh --makefs win31 +``` + +These commands: +1. Create sparse VHD images using `mkfs.fat` with `--mbr=y` flag + - File manager will show 4GB and 512MB + - Actual disk usage: only ~8-280KB initially +2. Use proper FAT formatting tool (`mkfs.fat`) for reliability +3. Create proper MBR partition table automatically +4. Create images in `$bios_path/` for use by RetroDECK + +The result is a pre-formatted disk image that DOSBox-X recognizes immediately. + +**Automatic Creation:** + +VHD images are created automatically during first use. Simply run: +```bash +./winplay.sh --install win98 --cd-rom /path/to/WIN98SE.iso +``` + +If the base VHD doesn't exist, it will be created automatically before installation begins. + +**Requirements:** +- `mkfs.fat` binary available at `$component_path/bin/mkfs.fat` (inside flatpak) +- Or system-wide at `/usr/sbin/mkfs.fat` (for testing outside flatpak) + +## Quick Start + +### 1. Create Windows 98 Base (Optional) + +The base VHD will be created automatically, but you can pre-create it: + +```bash +./winplay.sh --makefs win98 +``` + +This creates a 4GB FAT32 sparse VHD at `$bios_path/win98.vhd` + +### 2. Install Windows 98 + +Using the `winplay.sh` script: + +```bash +./winplay.sh --install win98 --cd-rom /path/to/WIN98SE.iso +``` + +This will: +1. Create win98.vhd automatically if it doesn't exist +2. Mount it as C: drive +3. Mount the Windows 98 CD-ROM as D: drive +4. Start Windows 98 Setup + +User can now complete the installation + +### 2. Install Games + +Once Windows 98 is installed: + +```bash +./winplay.sh --install "GameName" --cd-rom /path/to/game.iso +``` + +### 3. Launch Games + +```bash +./winplay.sh win98 "GameName" +``` + +All this is integrated in the Configurator however, so the users should just use the Configurator function to install the Windows versions and then the games. + +## Architecture + +### VHD Layering System + +The system uses a **3-layer VHD stacking architecture** for efficient storage and game isolation: + +``` +Layer 1 (Base OS): win98.vhd ← Shared by all games + ← Windows 98 OS installation (read-mostly) + ← Size: 4GB (sparse, ~512MB-1GB typical) + ↓ +Layer 2 (Game): gamename.vhd ← Game-specific layer + ← Game files and settings + ← Size: Variable per game + ↓ +(Two-layer model) The design uses only: + - Base OS (win98.vhd) and + - Per‑game child image (gamename.vhd) which holds both game files and user data +``` + +### How Layering Works + +1. **Layer 1 (Base OS)** - `win98.vhd` + - Contains the Windows 98 operating system + - Pre-formatted and shared across all games + - Mounted as read-mostly (changes are sparse) + - Size: 4GB fixed (sparse file, minimal disk usage) + +2. **Layer 2 (Game-specific)** - `gamename.vhd` + - Contains game files and game-specific configurations + - Created fresh for each game + - Mounted on top of the base OS + - Size: Variable based on game files + +3. **(Removed)** - Separate save data layer is not used. Saves are stored inside the per-game VHD. + +### Storage & Distribution + +| Layer | Location | Purpose | Size | Distribution | +|---|---|---|---|---| +| Base OS | `$bios_path/win98.vhd` | Shared Windows 98 OS | 4GB sparse | Included with RetroDECK | +| Game Layer | `$roms_path//.vhd` | Game-specific files (layered VHD) | Variable | Per-game package | +| (No separate saves layer) | `N/A` | User save files live inside the per-game VHD | variable | User-specific | + +### IMGMOUNT Configuration + +The `winplay.sh` script uses DOSBox-X's IMGMOUNT command with geometry specification: + +```bash +# During OS installation +IMGMOUNT C "$VHD_BASE_PATH" -t hdd -geometry 512 63 255 -size 512,63,255,65 + +# During game installation (with game layer) +IMGMOUNT C "$VHD_BASE_PATH" -b "$game_layer" -t hdd -geometry 512 63 255 -size 512,63,255,65 + +# During game launch (base + per-game child) +IMGMOUNT C "$VHD_BASE_PATH" -b "$game_layer" -t hdd -geometry 512 63 255 -size 512,63,255,65 +``` + +**Parameters:** +- `-t hdd` - Mount as hard drive +- `-b` - Stack additional layers (can be repeated) +- `-geometry 512 63 255` - Explicit disk geometry (512 bytes/sector, 63 sectors/track, 255 heads) +- `-size 512,63,255,65` - Geometry specification for proper detection + +## File Structure + +## File Structure + +``` +dosbox-x/ +├── assets/ +│ ├── winplay.sh # Main launcher script (with integrated mkfs functions) +│ ├── create_formatted_vhd.sh # Standalone script for batch VHD creation (optional) +│ └── README.md # This file +├── bin/ +│ └── mkfs.fat # mkfs.fat binary (from dosfstools, bundled) +├── component_functions.sh +├── component_launcher.sh +├── component_manifest.json +├── component_prepare.sh +├── component_recipe.json +└── ... +``` + +## How it Works + +### VHD Image Generation + +The `winplay.sh` script includes integrated functions `mkfs_win98()` and `mkfs_win31()` that create pre-formatted VHD images: + +1. **Creates sparse files** - Only actual data uses disk space (~8-280KB initially) + - File manager shows full size (4GB/512MB) + - Actual disk usage grows as Windows writes data +2. **Uses mkfs.fat** - Proper FAT formatting tool ensures reliability + - Automatically finds mkfs.fat at `$component_path/bin/mkfs.fat` (inside flatpak) +3. **Creates MBR + FAT table** - Uses `mkfs.fat --mbr=y` for proper partition table +4. **Automatic on first use** - VHD is created automatically if missing during `--install` + +The result is a pre-formatted disk image that DOSBox-X and Windows recognize immediately. + +### winplay.sh Launcher + +The `winplay.sh` script orchestrates the entire workflow: + +**Modes of operation (how drives map):** + +1. **Install OS** (`--install win98`) + - Mounts base VHD (Layer 1) as C: for installation + - Mounts Windows 98 CD-ROM as D: during the install + - Runs Windows Setup + - Creates formatted OS installation + +2. **Install Game** (`--install GameName`) + - Ensures base VHD (Layer 1) is present + - Prepares the per-game child VHD path (Layer 2) but the actual child is created in the guest runtime when first launched + - Mounts CD-ROM(s) on D: (or the next available drive) to run the installer inside Windows + - Installer should be run with the per-game child mounted as C: (the child contains OS+game during runtime) + +3. **Launch Game** (`win98 GameName`) + - Runtime will ensure a per-game writeable child exists and mount that child as C: (C: holds OS+game+saves) + - Additional hard disks and CD-ROM images supplied to the launcher will be mounted starting at D: (D, E, F ...) + - Boots into Windows and runs the launcher BAT from C: + +## Troubleshooting + +### "IMGMOUNT: cannot create drive from file" with "Sanity check fail: Root directory count == 0" + +**Problem:** DOSBox-X cannot recognize the VHD format because the BIOS Parameter Block (BPB) in the boot sector is invalid. + +**Solution:** This issue has been fixed in the current `create_formatted_vhd.py` script. The BPB now includes: +- Proper **Root directory count**: 224 for FAT12 (not 0) +- Correct **Media descriptor**: 0xF0 for FAT12, 0xF8 for FAT32 +- Valid **FAT count**: 2 (two copies for redundancy) +- Proper **32-bit total sectors** field for disks larger than 64KB + +If you're still seeing this error: +1. Delete the old images: `rm vhd_images/*.vhd` +2. Regenerate them: `python3 create_formatted_vhd.py ./vhd_images/` +3. Verify the boot sector signature: `hexdump -C vhd_images/win31.vhd | head -5` + - Should show `eb 3c 90 4d 53 44 4f 53` at offset 0x7e00 (sector 63) + +### "IMGMOUNT: cannot create drive from file" + +This indicates DOSBox-X cannot read the VHD format. Solutions: + +1. Verify VHD signature (should start with `eb 3c 90 4d 53 44 4f 53`): + ```bash + hexdump -C vhd_images/win98.vhd | head -1 + ``` + +2. Regenerate the images: + ```bash + python3 create_formatted_vhd.py ./vhd_images/ + ``` + +3. Verify DOSBox-X version supports raw VHD images (v0.75.0+) + +### "No partition in use in MBR" + +The VHD's MBR partition table is invalid. Regenerate: + +```bash +python3 create_formatted_vhd.py ./vhd_images/ +``` + +### Windows 98 doesn't recognize the drive + +Make sure the geometry parameters are correct in winplay.sh: + +```bash +IMGMOUNT C ... -geometry 512 63 255 -size 512,63,255,65 +``` + +These parameters help DOSBox-X properly detect the disk. + +## Storage Locations in RetroDECK + +| Component | Path | Purpose | +|---|---|---| +| Base OS VHD | `$bios_path/win98.vhd` | Shared Windows 98 OS | +| Game Layer | `$roms_path//.vhd` | Game-specific files (layered VHD) | +| (No separate saves layer) | `N/A` | User save files live inside the per-game VHD | + +## Technical Details + +### Sparse File Format + +Sparse files are a filesystem feature where unwritten sections don't consume disk space: + +``` +win98.vhd File Structure: +├── MBR (512 bytes) - written to disk ✓ +├── Padding (63*512 bytes) - written to disk ✓ +├── Boot sector (512 bytes) - written to disk ✓ +├── FAT structures (~2KB) - written to disk ✓ +├── [3.99 GB of empty space] - NOT written to disk ✗ ← Sparse area! +└── End marker (1 byte) - written to disk ✓ +``` + +**Result - Dual Perspective:** + +| Perspective | Size | Notes | +|---|---|---| +| **File Manager** | 4GB | Shows apparent/logical size | +| **Actual Disk** | ~40KB | Only written sections use space | +| **DOSBox-X** | 4GB | Sees the full size | +| **Growing** | Dynamic | Expands automatically as Windows writes data | + +**Why This Matters:** +- You can distribute a 4GB disk image using only 40KB download +- No need to pre-allocate 4GB on your hard drive when installing +- As Windows 98 installation progresses, the file grows on disk (only using space for actual data) +- You never waste 4GB for a disk that only uses 500MB of data + +### Disk Geometry + +DOSBox-X needs proper disk geometry for correct operation: + +| Parameter | Value | Purpose | +|---|---|---| +| Bytes per sector | 512 | Standard sector size | +| Sectors per track | 63 | CHS addressing limit | +| Heads | 255 | CHS addressing limit | +| Size spec | 512,63,255,65 | DOSBox-X geometry detection | + +These values represent a standard IDE drive configuration from the Windows 98 era. + +### FAT Filesystem Initialization + +Each VHD includes proper FAT initialization: + +**FAT32 (Windows 98):** +- Boot sector with extended BPB +- Two FAT tables for redundancy +- FSInfo sector for free space tracking +- Root directory at cluster 2 + +**FAT16 (Windows 3.1):** +- Boot sector with extended BPB +- Two FAT tables for redundancy +- Root directory in fixed location +- Media descriptor: 0xF8 (fixed media) +- Supports up to 2GB (512MB practical for Windows 3.1) +- Created with `mkfs.fat -F 16 --mbr=y` + + +## See Also + +- `winplay.sh --help` - Detailed usage and examples +- RetroDECK Documentation - https://github.com/RetroDECK/RetroDECK +- DOSBox-X Documentation - https://dosbox-x.com/ +- DOSBox-X GitHub Issues - https://github.com/joncampbell123/dosbox-x/issues diff --git a/dosbox-x/component_functions.sh b/dosbox-x/component_functions.sh new file mode 100755 index 00000000..5d280dcd --- /dev/null +++ b/dosbox-x/component_functions.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +component_name="$(basename "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")" +component_config="/app/retrodeck/components/$component_name/rd_config" + +dosbox_x_config="$XDG_CONFIG_HOME/dosbox-x/dosbox-x.conf" # Base config always appended to the WinPlay! calls. If we need to tweak something globally for all systems, this is the spot. +dosbox_x_mapper="$XDG_CONFIG_HOME/dosbox-x/mapper-dosbox-x.map" # DosBox-X default controls mapper file +dosbox_x_os_configs_dir="$component_config/os_configs" # WinPlay! will use the configs in this folder as pre-configured templates to generate temporary configs for OS installation and running, if we need to tweak something globally for a system, this is the spot +dosbox_x_generated_conf="$XDG_CONFIG_HOME/dosbox-x/generated.conf" # Used by WinPlay! to generate temporary configs for OS installation and running, this is disposable and will be delete/overwritten multiple times +winplay="open_component dosbox-x" + +_prepare_component::dosbox-x() { + local action="$1" + shift + + local component_config="$(get_own_component_path)/rd_config" + + case "$action" in + + reset) + log i "----------------------" + log i "Preparing $component_name" + log i "----------------------" + + create_dir "$XDG_CONFIG_HOME/dosbox-x" + cp -fT "$component_config/dosbox-x.conf" "$dosbox_x_config" + + # Default General Storage + create_dir "$storage_path/windows/dosbox-x" + set_setting_value "$dosbox_x_config" "working directory default" "$storage_path/windows/dosbox-x" "dosbox-x" + + # Logs path + create_dir "$logs_path/dosbox-x" + set_setting_value "$dosbox_x_config" "logfile" "$logs_path/dosbox-x/dosbox-x.log" "dosbox-x" + ;; + + esac + +} + + +dosbox_x_install_win98() { + log i "DosBox-X Windows 98 Installer started" + if [ -f "$storage_path/dosbox-x/win98.vhd" ]; then + log i "Existing Windows 98 installation found." + rd_zenity --question --text="An existing Windows 98 installation was found at \"$storage_path/dosbox-x/win98.vhd\".\n\nDo you want to run this existing installation instead of creating a new one?" --ok-label="Use Existing" --cancel-label="Create New" + if [ $? -eq 0 ]; then + log i "User chose to use the existing Windows 98 installation for DOSBox-X" + dosbox_x_run_win98 + return + else + log i "User chose to create a new Windows 98 installation for DOSBox-X, existing installation will be overwritten" + rd_zenity --question --text="Are you sure you want to create a new Windows 98 installation? This will overwrite the existing installation and all its data at \"$storage_path/dosbox-x/win98.vhd\"." --ok-label="Yes, Create New" --cancel-label="No, Keep Existing" + if [ $? -ne 0 ]; then + log i "User aborted creating a new Windows 98 installation for DOSBox-X, existing installation will be kept" + return + else + log i "User confirmed creating a new Windows 98 installation for DOSBox-X" + rm -f "$storage_path/dosbox-x/win98.vhd" + fi + fi + fi + rd_zenity --info --text="This will create a disk layer in DOSBox-X on which you can install Windows 98.\nPlease select the CD-ROM image file for Windows 98 installation.\n\nNOTE: you will need a legit Windows 98 CD Key to complete the installation." --ok-label="Proceed" --cancel-label="Abort" + win98_cdrom=$(file_browse "This will install Windows 98 in DOSBox-X.\nSelect the CD-ROM image file for Windows 98 installation") || exit 0 + $winplay --makefs win98 + if ( $winplay --install win98 --cd-rom "$win98_cdrom" ); then + log i "Windows 98 installation completed successfully" + rd_zenity --info --text="First step of Windows 98 installation completed successfully.\n\nNow Windows 98 will boot.\nPlease prepare the environment like setting your desired resolution and colors.\nWhen finished please turn off Windows 98 from the Start menu to end the installation and save the changes to the disk layer." + dosbox_x_run_win98 + rd_zenity --info --text="Windows 98 installation completed successfully.\nYou can now run install games in this Windows 98 environment using the 'DOSBox-X: Install Windows 98 Game' option in the Configurator." + else + log i "Windows 98 installation aborted" + fi +} + +dosbox_x_run_win98() { + log i "DosBox-X starting Windows 98 layer" + rd_zenity --info --text="WARNING: editing Windows 98 Installation might cause to break already installed games.\nMake sure to backup your Windows 98 installation layer before making any changes." + $winplay --desktop win98 +} +dosbox_x_install_win98_game() { + log i "DosBox-X Windows 98 Game Installer started" + rd_zenity --question --text="This will install the selected game for Windows 98 in DOSBox-X.\nMake sure your Windows 98 installation is ready.\n\nAre you installing your game from a CD-ROM or a Floppy disk image?" --switch --extra-button="CD-ROM" --extra-button="Floppy Disk" --extra-button="Abort" + case $? in + 0) + local media_type="cd-rom" + local pretty_media_type="CD-ROM" + log i "User selected CD-ROM installation for Windows 98 game" + ;; + 1) + local media_type="floppy" + local pretty_media_type="Floppy Disk" + log i "User selected Floppy Disk installation for Windows 98 game" + ;; + 2) log i "Windows 98 game installation aborted by user" + exit 0 + esac + game_image_path="$(file_browse "Select the $pretty_media_type image file for $game installation")" + local game="$(basename "$game_image_path" | sed 's/\.[^.]*$//')" + game="$(rd_zenity --entry --text="Enter the name of the game you want to install" --entry-text="$game" --title="Game Name Input")" + if ( ! $(rd_zenity --info --text="The game folder will be located in \"$roms_path/win98/$game\".\n\nProceed with the installation?" --ok-label="Proceed" --cancel-label="Abort") ); then + log i "User confirmed game installation for Windows 98 game: \"$game\" in \"$roms_path/win98/$game\" folder" + else + log i "Windows 98 game \"$game\" installation aborted by user" + return + fi + log d running command: $winplay --install win98 --$media_type "$game_image_path" + if ( $winplay --install win98 --$media_type "$game_image_path" ); then + log i "Windows 98 game \"$game\" installation completed" + rd_zenity --info --text="Windows 98 game \"$game\" installation completed.\nYou can now run install games in this Windows 98 environment using the 'DOSBox-X: Install Windows 98 Game' option in the Configurator." + else + log i "Windows 98 game \"$game\" installation aborted by user" + fi +} \ No newline at end of file diff --git a/dosbox-x/component_launcher.sh b/dosbox-x/component_launcher.sh new file mode 100755 index 00000000..9608c9cf --- /dev/null +++ b/dosbox-x/component_launcher.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Setting component name and path based on the directory name +export component_name="$(basename "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")" +export component_path="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd)" + +# Set LD_LIBRARY_PATH +export LD_LIBRARY_PATH="$component_path/lib:$ffmpeg_path/25.08:$rd_shared_libs:$rd_shared_libs/org.freedesktop.Platform/25.08/:$rd_shared_libs/org.gnome.Platform/49/:$rd_shared_libs/org.freedesktop.Platform/25.08/:${DEFAULT_LD_LIBRARY_PATH}" +export QT_PLUGIN_PATH="$rd_shared_libs/org.freedesktop.Platform/25.08/plugins/:${QT_PLUGIN_PATH}" +export QT_QPA_PLATFORM_PLUGIN_PATH="$rd_shared_libs/org.freedesktop.Platform/25.08/plugins/platforms/:${QT_QPA_PLATFORM_PLUGIN_PATH}" + +log i "RetroDECK is now launching $component_name" +log d "Library path is: $LD_LIBRARY_PATH" +log d "QT plugin path is: $QT_PLUGIN_PATH" +log d "QT QPA PLATFORM plugin path is: $QT_QPA_PLATFORM_PLUGIN_PATH" + +exec "$component_path/bin/winplay.sh" "$@" diff --git a/dosbox-x/component_manifest.json b/dosbox-x/component_manifest.json new file mode 100644 index 00000000..4ca9fab4 --- /dev/null +++ b/dosbox-x/component_manifest.json @@ -0,0 +1,48 @@ +{ + "dosbox-x": { + "name": "DOSBox-X", + "url_rdwiki": "https://retrodeck.readthedocs.io/en/latest/wiki_engine_guides/dosbox-x/dosbox-x-guide/", + "url_webpage": "https://dosbox-x.com/", + "url_donation_purchase": "", + "url_source": "https://github.com/joncampbell123/dosbox-x", + "description": "DOSBox-X is a DOS, Windows 3.x and 9x emulator.", + "component_type": "Emulator", + "system_friendly_name": [ + "Microsoft Windows 3x", + "Microsoft Windows 9x", + "Microsoft DOS" + ], + "system": [ + "windows3x", + "windows9x", + "dos" + ], + "configurator_menus": { + "tools": { + "dosbox_x":{ + "dosbox_x_install_win98": { + "name": "WinPlay! Install Windows 98", + "description": "Install Windows 98 in DOSBox-X emulator.", + "command": { + "zenity": "dosbox_x_install_win98" + } + }, + "dosbox_x_run_win98": { + "name": "WinPlay! Run Windows 98", + "description": "Run the Windows 98 base layer in DOSBox-X emulator.", + "command": { + "zenity": "dosbox_x_run_win98" + } + }, + "dosbox_x_install_win98_game": { + "name": "WinPlay! Install Windows 98 Game", + "description": "Install a Windows 98 game in DOSBox-X emulator.", + "command": { + "zenity": "dosbox_x_install_win98_game" + } + } + } + } + } + } +} diff --git a/dosbox-x/component_recipe.json b/dosbox-x/component_recipe.json new file mode 100755 index 00000000..d34ad62b --- /dev/null +++ b/dosbox-x/component_recipe.json @@ -0,0 +1,77 @@ +{ + "dosbox-x": [ + { + "source_url": "com.dosbox_x.DOSBox-X", + "source_type": "flatpak_id", + "version": "$DOSBOX_X_DESIRED_VERSION", + "dest": "user", + "extraction_type": "flatpak", + "assets": [ + { + "type": "dir", + "source": "bin", + "dest": "bin" + }, + { + "type": "create", + "dest": "component_version", + "contents": "$SOURCE_VERSION" + }, + { + "type": "dir", + "source": "$REPO_ROOT/$COMPONENT_NAME/rd_assets/winplay", + "dest": "bin" + }, + { + "type": "dir", + "source": "$REPO_ROOT/$COMPONENT_NAME/rd_assets/rd_config", + "dest": "rd_config" + }, + { + "type": "file", + "source": "$REPO_ROOT/$COMPONENT_NAME/component_functions.sh", + "dest": "$COMPONENT_ARTIFACT_ROOT" + }, + { + "type": "file", + "source": "$REPO_ROOT/$COMPONENT_NAME/component_launcher.sh", + "dest": "$COMPONENT_ARTIFACT_ROOT" + }, + { + "type": "file", + "source": "$REPO_ROOT/$COMPONENT_NAME/component_manifest.json", + "dest": "$COMPONENT_ARTIFACT_ROOT" + }, + { + "type": "file", + "source": "$REPO_ROOT/$COMPONENT_NAME/component_recipe.json", + "dest": "$COMPONENT_ARTIFACT_ROOT" + } + ], + "libs": [ + { + "library": "libslirp.so.0", + "source": "lib", + "dest": "shared-libs" + }, + { + "library": "libfluidsynth.so.3", + "source": "lib", + "dest": "shared-libs" + }, + { + "library": "libSDL3.so.0", + "runtime_name": "org.freedesktop.Platform", + "runtime_version": "25.08", + "dest": "shared-libs" + }, + { + "library": "libc.so.6", + "runtime_name": "org.freedesktop.Platform", + "runtime_version": "25.08", + "dest": "shared-libs" + } + ] + } + ] +} \ No newline at end of file diff --git a/dosbox-x/rd_assets/later/os_configs/win30.conf b/dosbox-x/rd_assets/later/os_configs/win30.conf new file mode 100644 index 00000000..b5231b66 --- /dev/null +++ b/dosbox-x/rd_assets/later/os_configs/win30.conf @@ -0,0 +1,30 @@ +[sdl] +autolock=true + +[dosbox] +title=Windows 3.0 +memsize=16 +machine=svga_et4000 + +[dos] +hard drive data rate limit=0 +floppy drive data rate limit=0 + +[cpu] +cputype=pentium +core=normal + +[sblaster] +sbtype=sbpro1 + +[pci] +voodoo=false + +[ide, primary] +int13fakeio=true +int13fakev86io=false + +[render] +scaler=none + +[autoexec] diff --git a/dosbox-x/rd_assets/later/os_configs/win95.conf b/dosbox-x/rd_assets/later/os_configs/win95.conf new file mode 100644 index 00000000..28568f6d --- /dev/null +++ b/dosbox-x/rd_assets/later/os_configs/win95.conf @@ -0,0 +1,42 @@ +[sdl] +autolock=true + +[dosbox] +title=Windows 95 +memsize=480 + +[video] +vmemsize=8 +vesa modelist width limit=0 +vesa modelist height limit=0 + +[dos] +# Set 'ver=7.1' if using Win95 OSR2 (95B) or later +ver=7.0 +hard drive data rate limit=0 +floppy drive data rate limit=0 + +[cpu] +cputype=pentium_mmx +core=normal +turbo = false + +[sblaster] +sbtype=sb16vibra + +[fdc, primary] +int13fakev86io=true + +[ide, primary] +int13fakeio=true +int13fakev86io=true + +[ide, secondary] +int13fakeio=true +int13fakev86io=true +cd-rom insertion delay=4000 + +[render] +scaler=none + +[autoexec] diff --git a/dosbox-x/rd_assets/later/os_configs/win95osr2.conf b/dosbox-x/rd_assets/later/os_configs/win95osr2.conf new file mode 100644 index 00000000..7eccab44 --- /dev/null +++ b/dosbox-x/rd_assets/later/os_configs/win95osr2.conf @@ -0,0 +1,41 @@ +[sdl] +autolock=true + +[dosbox] +title=Windows 95 OSR2 - 2.5 +memsize=480 + +[video] +vmemsize=8 +vesa modelist width limit=0 +vesa modelist height limit=0 + +[dos] +ver=7.1 +hard drive data rate limit=0 +floppy drive data rate limit=0 + +[cpu] +cputype=pentium_mmx +core=normal +turbo = false + +[sblaster] +sbtype=sb16vibra + +[fdc, primary] +int13fakev86io=true + +[ide, primary] +int13fakeio=true +int13fakev86io=true + +[ide, secondary] +int13fakeio=true +int13fakev86io=true +cd-rom insertion delay=4000 + +[render] +scaler=none + +[autoexec] diff --git a/dosbox-x/rd_assets/later/os_configs/winme.conf b/dosbox-x/rd_assets/later/os_configs/winme.conf new file mode 100644 index 00000000..9419e7d2 --- /dev/null +++ b/dosbox-x/rd_assets/later/os_configs/winme.conf @@ -0,0 +1,41 @@ +[sdl] +autolock=true + +[dosbox] +title=Windows ME +memsize=512 + +[video] +vmemsize=8 +vesa modelist width limit=0 +vesa modelist height limit=0 + +[dos] +ver=8.0 +lfn=false +hard drive data rate limit=0 +floppy drive data rate limit=0 + +[cpu] +cputype=pentium_mmx +core=normal + +[sblaster] +sbtype=sb16vibra + +[fdc, primary] +int13fakev86io=false + +[ide, primary] +int13fakeio=true +int13fakev86io=false + +[ide, secondary] +int13fakeio=true +int13fakev86io=false +cd-rom insertion delay=4000 + +[render] +scaler=none + +[autoexec] diff --git a/dosbox-x/rd_assets/old/old_winplay.sh b/dosbox-x/rd_assets/old/old_winplay.sh new file mode 100755 index 00000000..eccee308 --- /dev/null +++ b/dosbox-x/rd_assets/old/old_winplay.sh @@ -0,0 +1,1524 @@ +#!/bin/bash + +source /app/libexec/global.sh + +# This script launches DOSBox-X with a Windows 98/3.1 image and autostarts games +# It prepares a temporary configuration and BAT file for game installation and launching + +# NOTE: logging helper `log()` is provided by the surrounding framework and +# is intentionally not defined here to avoid duplicate definitions. Use the +# framework-provided logger (e.g., log i "message"). +# INITIALIZATION FUNCTIONS +# ============================================================================ + +init_globals() { + # VHD layer paths - save_path should be provided by RetroDECK framework + # - OS Layer: $storage_path/dosbox-x/$WIN_VERSION.vhd + # - Game Layer: $roms_path//.vhd + # (Per-game VHD is the single writable layer for the game — it contains + # the game files and any save files created by the title.) + ESDE_SYSTEM_NAME="" + + # Initialize mode flags + INSTALL_MODE=0 + INSTALL_NAME="" + MAKEFS_MODE=0 + MAKEFS_VERSION="" + DESKTOP_MODE=0 + DESKTOP_VERSION="" + FORCE_RECREATE=0 + PACK_MODE=0 + PACK_GAME_NAME="" + FLOPPIES=() + CDROMS=() + HDISKS=() + WIN_VERSION="" + GAME_PATH="" + # When set, do not create/copy the run_game launcher into the guest's + # startup. Useful for performing installations / maintenance (we still + # delete existing Startup items so the environment is clean). + NO_LAUNCHER=0 + # If set, generate the TMP_CONF and print it, but do not launch DOSBox-X + DUMP_CONF=0 + + # Files / folders which should be scanned last when searching C:\ in + # generated launcher BATs. Items here are considered "low priority" and + # skipped in the first search pass (scanned in the second pass). The + # user asked to keep "My Documents" / "Documenti" for the late pass so + # they are included by default. + EXEC_SEARCH_LATE=("WINDOWS" "PROGRAM FILES" "MY DOCUMENTS" "DOCUMENTI") + # Optional exec target (filename or full C:\ path) — if set the launcher + # will attempt to find and execute this program in the guest. + EXEC_ARG="" + + # Initialize runtime variables + IS_OS_INSTALL=0 + GAME_NAME_FOR_DIR="" + VHD_GAME_LAYER="" + # (No separate savedata/write-layer variable — per-game VHD stores both + # game files and save files.) + OS_CONFIG_DIR="" + VHD_BASE_PATH="" + TMP_CONF="" + LAUNCHER_DIR="" + # Virtual size (MB) used for per-OS game layers and save overlays. This + # will be set later (usually in setup_paths) based on WIN_VERSION. + VHD_OS_SIZE_MB="" + # Driver-copy behaviour during OS installs: minimal|all|none + DRIVER_COPY_MODE="minimal" + # This script runs inside the Flatpak runtime — do not attempt to use + # host-only tools (qemu-img) here. All VHD creation/fallbacks must rely + # on the bundled DOSBox-X imgmake invocation. +} + +setup_paths() { + log d "Looking for OS config files in component path first: $component_path/rd_config/os_configs" + OS_CONFIG_DIR="${component_path:-}/rd_config/os_configs" + if [[ ! -d "$OS_CONFIG_DIR" ]]; then + OS_CONFIG_DIR="${dosbox_x_os_configs_dir:-$OS_CONFIG_DIR}" + fi + + VHD_BASE_PATH="$storage_path/dosbox-x/$WIN_VERSION.vhd" + TMP_CONF="$XDG_CACHE_HOME/dosbox-x/winplay.conf" + # Choose the default virtual size for layers and per-system path name based on WIN_VERSION. + case "${WIN_VERSION,,}" in + win98*) VHD_OS_SIZE_MB=4096 ;; + win31*) VHD_OS_SIZE_MB=512 ;; + *) VHD_OS_SIZE_MB=4096 ;; + esac + + case "${WIN_VERSION,,}" in + win98*) ESDE_SYSTEM_NAME="windows9x" ;; + win31*) ESDE_SYSTEM_NAME="windows3x" ;; + *) ESDE_SYSTEM_NAME="windows9x" ;; + esac + + # Two-layer model in effect: per-game VHD contains both the installed + # game and its save files (no separate saves directory or VHD). + + # If roms_path is not supplied by the framework, default to a sane location + # in the user's home to avoid creating files at the root (e.g. /windows9x/...) + if [[ -z "${roms_path:-}" ]]; then + roms_path="${XDG_DATA_HOME:-$HOME/.local/share}/retrodeck/roms" + log w "roms_path not set — defaulting to: $roms_path" + fi + mkdir -p "$XDG_CACHE_HOME/dosbox-x" +} + +setup_launcher_dir() { + local launcher_base_dir="$XDG_CACHE_HOME/dosbox-x" + local launcher_tmp_dir=$(mktemp -d "${launcher_base_dir}/tmp.XXXX") + LAUNCHER_DIR="$launcher_tmp_dir/launcher" + + # Cleanup on exit + trap "rm -rf '$launcher_tmp_dir' 2>/dev/null || true" EXIT +} + +# Sanitize a game/whatever name so it is safe to use as a filename for VHDs +# Replaces path separators and runs of non-alphanumeric/.-_ with a single '_' +# Keeps the basename readable but removes spaces and other problematic characters +sanitize_vhd_basename() { + local name="$1" + # Ensure there is a value + if [[ -z "$name" ]]; then + echo "unnamed" + return 0 + fi + + # Replace path separators with underscores and collapse any sequence of + # characters that are not a-zA-Z0-9, dot, underscore or hyphen into a single '_' + local safe + safe=$(printf '%s' "$name" | sed -E 's|/|_|g' | sed -E 's/[^A-Za-z0-9._-]+/_/g' | sed -E 's/^_+|_+$//g') + + # Fallback when sanitization strips everything + if [[ -z "$safe" ]]; then + safe="unnamed" + fi + + echo "$safe" +} + +# ============================================================================ +# ARGUMENT PARSING +# ============================================================================ + +parse_arguments() { + while [[ $# -gt 0 ]]; do + case "$1" in + --desktop) + DESKTOP_MODE=1 + if [[ -z "$2" || "$2" == --* ]]; then + log e "--desktop requires an argument (win98 or win31)" + exit 1 + fi + DESKTOP_VERSION="$2" + shift 2 + ;; + --package-game) + PACK_MODE=1 + if [[ -z "$2" || "$2" == --* ]]; then + log e "--package-game requires a game name argument" + exit 1 + fi + PACK_GAME_NAME="$2" + shift 2 + ;; + --makefs) + MAKEFS_MODE=1 + if [[ -z "$2" || "$2" == --* ]]; then + log e "--makefs requires an argument (win98 or win31)" + exit 1 + fi + MAKEFS_VERSION="$2" + shift 2 + ;; + --install) + INSTALL_MODE=1 + if [[ -z "$2" || "$2" == --* ]]; then + log e "--install requires an argument (Windows version or game name)" + echo "Usage: $0 --install [--cd-rom /path/to/cd.iso ...]" + exit 1 + fi + INSTALL_NAME="$2" + shift 2 + ;; + --cd-rom) + if [[ -z "$2" ]]; then + log e "--cd-rom requires an argument (path to ISO)" + exit 1 + fi + CDROMS+=("$2") + shift 2 + ;; + --cdrom) + if [[ -z "$2" ]]; then + log e "--cdrom requires an argument (path to ISO)" + exit 1 + fi + CDROMS+=("$2") + shift 2 + ;; + --floppy) + if [[ -z "$2" ]]; then + log e "--floppy requires an argument (path to floppy image)" + exit 1 + fi + FLOPPIES+=("$2") + shift 2 + ;; + --hd) + if [[ -z "$2" ]]; then + log e "--hd requires an argument (path to hard disk image)" + exit 1 + fi + HDISKS+=("$2") + shift 2 + ;; + --help|-h) + show_help + exit 0 + ;; + --dump-conf) + DUMP_CONF=1 + shift + ;; + --exec) + if [[ -z "$2" || "$2" == --* ]]; then + log e "--exec requires an argument (file name or full path like C:\\PATH\\EXE)" + exit 1 + fi + EXEC_ARG="$2" + shift 2 + ;; + --nolauncher) + NO_LAUNCHER=1 + shift + ;; + --*) + log e "Unknown option: $1" + exit 1 + ;; + *) + if [[ -z "$WIN_VERSION" ]]; then + WIN_VERSION="$1" + elif [[ -z "$GAME_PATH" ]]; then + GAME_PATH="$1" + fi + shift + ;; + esac + done +} + +validate_arguments() { + # Set default Windows version + WIN_VERSION="${WIN_VERSION:-win98}" + + # Validate required arguments + if [[ $INSTALL_MODE -eq 0 && $DESKTOP_MODE -eq 0 && -z "$GAME_PATH" ]]; then + log e "No game path provided, --install, or --desktop specified!" + log i "Usage:" + log i " $0 win98 GameName (launch game)" + log i " $0 --install GameName (install game)" + log i " $0 --desktop win98 (desktop mode)" + log i "Use '$0 --help' for more information." + exit 1 + fi +} + +show_help() { + cat <<'HELP' +winplay.sh - Windows 98/3.1 game launcher with VHD layering for DOSBox-X + +USAGE: + winplay.sh --makefs win98 (Create Windows 98 VHD) + winplay.sh --makefs win31 (Create Windows 3.1 VHD) + winplay.sh --desktop win98 (Launch Windows 98 desktop) + winplay.sh --desktop win31 (Launch Windows 3.1 desktop) + winplay.sh --install win98 --cd-rom /path/to/WIN98SE.iso (Install Windows 98) + winplay.sh --install GameName --cd-rom /path/to/game.iso (Install game to base OS) + winplay.sh --game GameName --os win98 --cd-rom /path/to/game.iso (Play/install game) + winplay.sh --game GameName --cd-rom /path/to/game.iso (Play/install game with default win98) + winplay.sh --help (Show this help) + +UNIFIED GAME MODE: + --game Launch or install a game (creates per-game VHD layer) + First run: installs the game; subsequent runs: plays the game + --os Windows version for the game (default: win98) + --cd-rom Mount ISO/CD-ROM image (multiple allowed) + --cdrom Alias for --cd-rom + +CREATE FILESYSTEM IMAGES / LAYER NAMING: + OS Layer: --makefs win98 Create 4GB FAT32 sparse VHD for Windows 98 at $storage_path/dosbox-x/win98.vhd + --makefs win31 Create 512MB FAT16 sparse VHD for Windows 3.1 at $storage_path/dosbox-x/win31.vhd + + Naming conventions: + - OS Layer: $storage_path/dosbox-x/$WIN_VERSION.vhd + - Game Layer: $roms_path//.vhd + - (No separate saves layer — save files will be stored inside the Game Layer VHD) + +DESKTOP MODE (WARNING): + --desktop win98 Launch Windows 98 base OS desktop (NO GAME) + --desktop win31 Launch Windows 3.1 base OS desktop (NO GAME) + + ALL CHANGES MADE IN DESKTOP MODE ARE PERMANENT AND AFFECT THE BASE IMAGE! + Any modifications, installations, or configurations will persist across all games. + Use only for system setup or troubleshooting. + NOT recommended for normal use - use --game for games instead. + +PARAMETERS: + --makefs Create pre-formatted VHD images + --desktop Launch OS desktop (changes are permanent!) + --game Launch/install game (unified mode) + --os Windows version (default: win98) + --cd-rom Mount ISO/CD-ROM image (multiple allowed) + --cdrom Alias for --cd-rom + --install Install Windows version or game (legacy) + --package-game Packaging-mode: create differencing VHD for (host only) + --drivers Control driver-copy during OS install (default: minimal) + --help, -h Show this help + --nolauncher Do not create/copy run_game launcher into guest Startup (still deletes existing Startup files) + --exec Search C: (or run full path) and execute found file inside guest + --dump-conf Generate and print TMP_CONF then exit (no DOSBox-X launch) + +EXAMPLES: + ./winplay.sh --makefs win98 + ./winplay.sh --install win98 --cd-rom ~/images/WIN98SE.iso + ./winplay.sh --game "Doom" --cd-rom ~/images/doom-cd.iso + ./winplay.sh --game "Doom" (replay, CD-ROM not needed) + ./winplay.sh --game "SimCity" --os win95 --cd-rom ~/images/simcity.iso + ./winplay.sh --desktop win98 + ./winplay.sh --exec "DOOM.EXE" (search C: and run DOOM.EXE) + ./winplay.sh --exec "C:\\ROM2\\ROM2.EXE" (directly run provided full path) + +HELP +} + +# Self-test mode (disabled by default). Set WINPLAY_SELFTEST=1 to run a few +# quick checks for sanitize_vhd_basename without launching DOSBox-X. +if [[ "${WINPLAY_SELFTEST:-0}" == "1" ]]; then + echo "Running winplay.sh self-tests (sanitize_vhd_basename)" + test_inputs=("Rages of Mages II" "a/../weird*name" " " "game.name.vhd") + for t in "${test_inputs[@]}"; do + printf '%-30s -> %s\n' "$t" "$(sanitize_vhd_basename "$t")" + done + exit 0 +fi + +# ============================================================================ +# ENVIRONMENT VARIABLE PROCESSING (for framework integration) +# ============================================================================ + +extract_args_from_environment() { + # If no CLI arguments provided, check for framework-provided environment variables + if [[ $# -eq 0 ]]; then + local env_args=() + + # Check for action environment variables + if [[ -n "${DOSBOX_ACTION:-}" ]]; then + env_args+=("--${DOSBOX_ACTION}") + [[ -n "${DOSBOX_ACTION_VALUE:-}" ]] && env_args+=("${DOSBOX_ACTION_VALUE}") + fi + + # Check for CD-ROM environment variables + if [[ -n "${DOSBOX_CDROM:-}" ]]; then + env_args+=("--cdrom" "${DOSBOX_CDROM}") + fi + + if [[ ${#env_args[@]} -gt 0 ]]; then + log d "Extracted arguments from environment: ${env_args[@]}" + printf '%s\n' "${env_args[@]}" + return 0 + fi + fi + + # Return CLI arguments as-is + printf '%s\n' "$@" + return 0 +} + + +# ============================================================================ +# MODE HANDLERS: --makefs +# ============================================================================ + +mkfs_win98() { + local target_path="${1:-$storage_path/dosbox-x/win98.vhd}" + local size_mb=4096 + + mkdir -p "$(dirname "$target_path")" + + if [[ -f "$target_path" ]]; then + log w "VHD already exists: $target_path (skipping)" + return 0 + fi + + log i "Creating Windows 98 VHD: $target_path (${size_mb}MB, FAT32)" + + # Use DOSBox-X imgmake to create a dynamic VHD + # This is native to DOSBox-X and fully compatible + if ! "$component_path/bin/dosbox-x" -c "imgmake -t hd -size $size_mb \"$target_path\"" -c "exit" > /dev/null 2>&1; then + log e "Failed to create VHD with imgmake" + rm -f "$target_path" + return 1 + fi + + local disk_blocks=$(stat -c%b "$target_path" 2>/dev/null || echo 0) + local disk_usage_kb=$((disk_blocks * 512 / 1024)) + local size_str=$([[ $disk_usage_kb -lt 1024 ]] && echo "${disk_usage_kb}KB" || echo "$((disk_usage_kb / 1024))MB") + + log i "✓ Windows 98 VHD created (sparse: ~${size_str} on disk)" + return 0 +} + +mkfs_win31() { + local target_path="${1:-$storage_path/dosbox-x/win31.vhd}" + local size_mb=512 + + mkdir -p "$(dirname "$target_path")" + + if [[ -f "$target_path" ]]; then + log w "VHD already exists: $target_path (skipping)" + return 0 + fi + + log i "Creating Windows 3.1 VHD: $target_path (${size_mb}MB, FAT16)" + + # Use DOSBox-X imgmake to create a dynamic VHD + # This is native to DOSBox-X and fully compatible + if ! "$component_path/bin/dosbox-x" -c "imgmake -t hd -size $size_mb \"$target_path\"" -c "exit" > /dev/null 2>&1; then + log e "Failed to create VHD with imgmake" + rm -f "$target_path" + return 1 + fi + + local disk_blocks=$(stat -c%b "$target_path" 2>/dev/null || echo 0) + local disk_usage_kb=$((disk_blocks * 512 / 1024)) + local size_str=$([[ $disk_usage_kb -lt 1024 ]] && echo "${disk_usage_kb}KB" || echo "$((disk_usage_kb / 1024))MB") + + log i "✓ Windows 3.1 VHD created (sparse: ~${size_str} on disk)" + return 0 +} + +handle_makefs_mode() { + case "$MAKEFS_VERSION" in + win98) + mkfs_win98 "$storage_path/dosbox-x/win98.vhd" + exit $? + ;; + win31) + mkfs_win31 "$storage_path/dosbox-x/win31.vhd" + exit $? + ;; + *) + log e "Unknown version for --makefs: $MAKEFS_VERSION (must be win98 or win31)" + exit 1 + ;; + esac +} + +# ============================================================================ +# VHD MANAGEMENT +# ============================================================================ + +verify_os_config() { + local config_file="$OS_CONFIG_DIR/$WIN_VERSION.conf" + if [[ ! -f "$config_file" ]]; then + log e "Windows version '$WIN_VERSION' not recognized (missing config: $config_file)" + log i "Supported versions are (from: $OS_CONFIG_DIR):" + if [[ -d "$OS_CONFIG_DIR" ]]; then + for cfg in "$OS_CONFIG_DIR"/*.conf; do + echo " - $(basename "$cfg" .conf)" + done + else + echo " (no os_configs directory found at $OS_CONFIG_DIR)" + fi + exit 1 + fi +} + +create_game_layer_vhd() { + local game_name="$1" + # Prepare the path for the per-game VHD layer (game + saves unified). + # This file is created as a differencing VHD backed by base.vhd. + # All game files and saves go into this single layer. + # Build both the raw filename and a sanitized filename. If a file already + # exists using the original (possibly spaced) name, prefer it to remain + # backwards-compatible. Otherwise use the sanitized version to avoid + # problematic characters causing downstream issues (vhdmake/creation). + local sanitized_name + sanitized_name=$(sanitize_vhd_basename "$game_name") + local game_layer_orig="$roms_path/$ESDE_SYSTEM_NAME/${game_name}.vhd" + local game_layer_safe="$roms_path/$ESDE_SYSTEM_NAME/${sanitized_name}.vhd" + + local game_layer + if [[ -f "$game_layer_orig" ]]; then + game_layer="$game_layer_orig" + else + game_layer="$game_layer_safe" + fi + mkdir -p "$(dirname "$game_layer")" + + # VHD creation happens inside autoexec via vhdmake (vhdmake is DOSBox-X internal command, not external) + # Just return the path; vhdmake in autoexec will create it on first launch + if [[ ! -f "$game_layer" ]]; then + log i "Game-layer VHD path prepared (will be created by vhdmake in autoexec): $game_layer" + else + log i "Game-layer VHD already exists: $game_layer" + fi + + echo "$game_layer" +} + +# Packaging-time helper: create a differencing VHD for game_name using qemu-img +# This is intended to run during build/packaging on the host (not in Flatpak runtime) +create_packaged_game_layer_vhd() { + local game_name="$1" + # Prefer sanitized filenames but preserve existing files with the original + # name (backwards compatibility). This avoids packaging/creation issues with + # strange characters or spaces in filenames. + local sanitized_name + sanitized_name=$(sanitize_vhd_basename "$game_name") + local game_layer_orig="$roms_path/$ESDE_SYSTEM_NAME/${game_name}.vhd" + local game_layer_safe="$roms_path/$ESDE_SYSTEM_NAME/${sanitized_name}.vhd" + + local game_layer + if [[ -f "$game_layer_orig" ]]; then + game_layer="$game_layer_orig" + else + game_layer="$game_layer_safe" + fi + + if [[ -z "$VHD_BASE_PATH" || ! -f "$VHD_BASE_PATH" ]]; then + log e "Base VHD not found at: $VHD_BASE_PATH — cannot package game layer" + return 1 + fi + + mkdir -p "$(dirname "$game_layer")" + + if [[ -f "$game_layer" && $FORCE_RECREATE -ne 1 ]]; then + log w "Game-layer already exists: $game_layer (use -f/--force to recreate)" + echo "$game_layer" + return 0 + fi + + # Prefer the DOSBox-X vhdmake / imgmake tooling to create linked images + # as that's the native implementation known to produce chains compatible + # with DOSBox-X. Try component_path/bin/dosbox-x first, then PATH dosbox-x, + # then fall back to qemu-img (some formats don't support backing-file). + local dosbox_exec="" + if [[ -x "${component_path:-}/bin/dosbox-x" ]]; then + dosbox_exec="${component_path}/bin/dosbox-x" + elif command -v dosbox-x >/dev/null 2>&1; then + dosbox_exec="dosbox-x" + fi + + if [[ -n "$dosbox_exec" ]]; then + log i "Packaging: creating differencing VHD via DOSBox-X vhdmake: $game_layer -> backing $VHD_BASE_PATH" + rm -f "$game_layer" 2>/dev/null || true + local outtmp + outtmp=$(mktemp) + # Use vhdmake with '-l base child' to create a linked VHD + # Use -f (force/create) to ensure a child is created if missing and + # inherits geometry from the parent VHD. This helps avoid "cannot + # extract geometry" errors at runtime. + "$dosbox_exec" -c "vhdmake -f -l \"$VHD_BASE_PATH\" \"$game_layer\"" -c "exit" >"$outtmp" 2>&1 + local vhdmake_ec=$? + if [[ $vhdmake_ec -eq 0 && -s "$game_layer" ]]; then + log i "Packaged game-layer created via DOSBox-X: $game_layer" + rm -f "$outtmp" 2>/dev/null || true + echo "$game_layer" + return 0 + else + log w "DOSBox-X vhdmake failed (exit=$vhdmake_ec) — output (first 4k):" + head -c 4096 "$outtmp" | sed 's/^/ /' + rm -f "$outtmp" 2>/dev/null || true + # fallthrough to try qemu-img if available + fi + fi + + if command -v qemu-img >/dev/null 2>&1; then + log i "Packaging: attempting fallback via qemu-img: $game_layer -> backing $VHD_BASE_PATH" + rm -f "$game_layer" 2>/dev/null || true + # Some formats don't allow backing_file on create (vpc), so try a qcow2 + # child (good for packing) and, if necessary, convert to vpc. + local tmp_child_qcow="$game_layer.qcow2" + if qemu-img create -f qcow2 -o backing_file="$VHD_BASE_PATH" "$tmp_child_qcow" >/dev/null 2>&1; then + # Convert to vpc format if DOSBox-X requires vhd/vpc + if qemu-img convert -O vpc "$tmp_child_qcow" "$game_layer" >/dev/null 2>&1; then + rm -f "$tmp_child_qcow" 2>/dev/null || true + log i "Packaged game-layer created via qemu-img (qcow2->vpc): $game_layer" + echo "$game_layer" + return 0 + else + log w "qemu-img convert -> vpc failed; leaving qcow2 child at: $tmp_child_qcow" + echo "$tmp_child_qcow" + return 0 + fi + else + log e "qemu-img create (qcow2 backing) failed — cannot create differencing child for: $game_layer" + return 1 + fi + fi + + log e "No supported host tool found to create reliable differencing VHD (tried DOSBox-X vhdmake and qemu-img)" + return 1 +} + +# ============================================================================ +# AUTOEXEC GENERATION +# ============================================================================ + +generate_autoexec_install_os() { + local conf_file="$1" + + log i "Windows OS Installation Mode" + log i "VHD is pre-formatted and ready for Setup" + + if [[ ${#CDROMS[@]} -eq 0 ]]; then + log e "Installation requires a CD-ROM image!" + log e "Usage: $0 --install $WIN_VERSION --cd-rom /path/to/setup.iso" + exit 1 + fi + + # Defer startup cleanup to the later install phase to avoid duplicate + # operations; a consolidated cleanup is emitted closer to the actual + # installation step below. + # present across reboots during installation — start from D: because C: is taken + # Mount the pre-formatted OS VHD as C: so Setup can detect/boot the target + cat <> "$conf_file" +IMGMOUNT C "$VHD_BASE_PATH" -t hdd +EOF + mount_disks "$conf_file" "D" + + # Optionally copy drivers from the CD to the Windows system directory to + # reduce prompts during installation. Controlled by --drivers {minimal|all|none} + if [[ "${DRIVER_COPY_MODE}" != "none" ]]; then + if [[ "${DRIVER_COPY_MODE}" == "all" ]]; then + cat <<'EOF' >> "$conf_file" +REM Copy as many files as possible from the CD to C:\WINDOWS\SYSTEM +IF NOT EXIST C:\WINDOWS\SYSTEM MD C:\WINDOWS\SYSTEM +REM Copy full WIN98 and DRIVERS directories (recursive copy where available) +IF EXIST D:\WIN98 XCOPY D:\WIN98 C:\WINDOWS\SYSTEM /E /Y >NUL 2>NUL +IF EXIST D:\DRIVERS XCOPY D:\DRIVERS C:\WINDOWS\SYSTEM /E /Y >NUL 2>NUL +REM Also copy any root-level device files that might be directly requested +IF EXIST D:\*.VXD COPY /Y D:\*.VXD C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\*.DRV COPY /Y D:\*.DRV C:\WINDOWS\SYSTEM >NUL 2>NUL +EOF + else + # 'minimal' behaviour (copy specific likely-needed files only) + cat <<'EOF' >> "$conf_file" +REM Copy driver files (if present) from CD to C:\WINDOWS\SYSTEM +IF NOT EXIST C:\WINDOWS\SYSTEM MD C:\WINDOWS\SYSTEM +REM Copy specific driver/file types commonly requested by installers +IF EXIST D:\*CSPMAN*.DLL COPY /Y D:\*CSPMAN*.DLL C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\WIN98\*CSPMAN*.DLL COPY /Y D:\WIN98\*CSPMAN*.DLL C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\WIN98\*.VXD COPY /Y D:\WIN98\*.VXD C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\WIN98\*.DRV COPY /Y D:\WIN98\*.DRV C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\WIN98\*.DLL COPY /Y D:\WIN98\*.DLL C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\WIN98\*.ACV COPY /Y D:\WIN98\*.ACV C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\WIN98\*.CSP COPY /Y D:\WIN98\*.CSP C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\DRIVERS\*.VXD COPY /Y D:\DRIVERS\*.VXD C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\DRIVERS\*.DRV COPY /Y D:\DRIVERS\*.DRV C:\WINDOWS\SYSTEM >NUL 2>NUL +REM Attempt also from common root locations +IF EXIST D:\*.VXD COPY /Y D:\*.VXD C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\*.DRV COPY /Y D:\*.DRV C:\WINDOWS\SYSTEM >NUL 2>NUL +EOF + fi + fi + + cat <> "$conf_file" +ECHO --nolauncher: Startup cleanup performed; run_game.bat will NOT be installed +REM --nolauncher: debug list BEFORE removal (shows if file exists) +DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" +DIR "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" +DEL /F /Q "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" 2>NUL +DEL /F /Q "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" 2>NUL +REM --nolauncher: debug list AFTER removal (verify gone) +DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" +DIR "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" +ECHO D: drive contains Setup +D: +SETUP.EXE +GOTO END_INSTALL +:WINDOWS_FOUND +ECHO Windows installation detected, booting it +BOOT C: +:END_INSTALL +C: +RUNDLL32.EXE USER.EXE,ExitWindows +EOF + log i "Setup: VHD mounted, ready for installation" +} + +generate_autoexec_launch() { + local conf_file="$1" + local game_layer="$2" + local launcher_dir="$3" + + log i "Creating autoexec for game launch (eXoWin9x-style: C=write-layer, D=game)" + + # Prefer explicit parameters from the caller, but fall back to global + # variables for compatibility with older flows. + local game_layer="${game_layer:-$GAME_VHD_PATH}" + + # C: = differencing VHD for Windows/save files (write layer, backed by base.vhd) + # D: = game VHD or directory + # New sequence (safer): prefer creating the differencing child *outside* + # the booting DOSBox-X instance (host-side packaging via create_packaged_game_layer_vhd) + # because creating differencing children in-guest has been observed to + # crash some DOSBox-X builds. If host-side creation is not possible the + # autoexec uses VHDMAKE -f -l as an in-guest fallback (less safe on some builds). + # If the per-game child VHD already exists (for example created by the + # host-side packaging helper) avoid creating it in-guest — creating + # differencing images inside a running DOSBox-X instance can be unstable + # for some builds. Only call VHDMAKE in-guest if the child does not exist. + if [[ ! -f "$game_layer" ]]; then + cat >> "$conf_file" <> "$conf_file" <NUL + DEL /F /Q "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" 2>NUL + # --nolauncher: debug list AFTER removal (C:) + DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" + DIR "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" + # --nolauncher: debug list BEFORE removal (D:) + DIR "D:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" + DIR "D:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" + DEL /F /Q "D:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" 2>NUL + DEL /F /Q "D:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" 2>NUL + # --nolauncher: debug list AFTER removal (D:) + DIR "D:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" + DIR "D:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" + # Unmount temporary mounts + MOUNT -u D + MOUNT -u C +) ELSE ( + # Child missing: mount base only and clean its Startup + IMGMOUNT C "$VHD_BASE_PATH" -t hdd + # --nolauncher: debug list BEFORE removal (C: child-missing) + DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" + DIR "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" + DEL /F /Q "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" 2>NUL + DEL /F /Q "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" 2>NUL + # --nolauncher: debug list AFTER removal (C: child-missing) + DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" + DIR "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" + MOUNT -u C +) +EOF + fi + + cat >> "$conf_file" <> "$conf_file" + # Remove previous startup items (8.3 + long name variants) + # debug list BEFORE removal + DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\" + DEL /F /Q "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" 2>NUL + # debug list AFTER removal + DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" +EOF + + # Only copy the launcher into Startup when this invocation is a + # game launch (GAME_PATH) or an explicit --exec target (EXEC_ARG). + # Desktop-mode without a target should not copy anything. + if [[ -n "$EXEC_ARG" || -n "$GAME_PATH" ]]; then + cat >> "$conf_file" <<'EOF' +MOUNT A "$launcher_dir" +COPY A:\run_game.bat "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" +MOUNT -u A +EOF + else + # No game or exec target present — do not copy the launcher. + cat >> "$conf_file" <<'EOF' +REM No --game or --exec provided: skipping copy into guest Startup +EOF + fi + else + cat >> "$conf_file" <<'EOF' +# --nolauncher: skipping copy of run_game.bat into guest Startup (maintenance mode) +# --nolauncher: Startup cleanup performed; run_game.bat will NOT be installed +EOF + fi + + # Mount CD-ROMs/hard disks starting from D: (C: is taken by stacked OS+game) + mount_disks "$conf_file" "D" + + cat <> "$conf_file" +#BOOT -l C: +EOF + + log i "Autoexec ready: C=write-layer, D=game, E+=CD/HD/floppy" +} + +generate_autoexec_desktop() { + local conf_file="$1" + local vhd_base_path="$2" + + log i "Mounting base OS for desktop mode" + + # Mount the base VHD as C: + cat <> "$conf_file" +IMGMOUNT C "$vhd_base_path" -t hdd +EOF + + # If maintenance mode is active, remove any leftover launcher from + # the base image's Startup folder and print a visible confirmation. + if [[ "$NO_LAUNCHER" -eq 1 ]]; then + cat <<'EOF' >> "$conf_file" +REM Remove previous startup items when --nolauncher is active (8.3 + long-name) +DEL /F /Q "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" 2>NUL +DEL /F /Q "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" 2>NUL +ECHO --nolauncher: Startup cleanup performed; run_game.bat will NOT be installed +EOF + else + # When not in maintenance mode, copy the freshly-created launcher into + # the base image so Desktop mode sees an updated run_game.bat. + # Only attempt to mount/copy the launcher into the base image when the + # temporary launcher actually exists on the host. This avoids creating a + # benign placeholder and ensures we only overwrite when we have real data. + # Only update base Startup when we have an actual launcher and + # the invocation supplied a game or an --exec target. Desktop-mode + # without a target must not write launchers into the base image. + if [[ ( -n "$EXEC_ARG" || -n "$GAME_PATH" ) && -f "$LAUNCHER_DIR/run_game.bat" ]]; then + cat >> "$conf_file" <NUL + DEL /F /Q "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" 2>NUL + REM debug list AFTER removal + DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" + DIR "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" + IF EXIST A:\run_game.bat ( COPY A:\run_game.bat "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" ) + MOUNT -u A +ECHO --nolauncher: Startup updated with new run_game.bat +EOF + else + # Nothing to copy — ensure we don't perform any change when no + # launcher was generated for desktop mode. + log d "No launcher present at: $LAUNCHER_DIR/run_game.bat — skipping desktop Startup update" + fi + fi + + # Mount disks starting from D: (C: is already used by VHD) + mount_disks "$conf_file" "D" + + cat <> "$conf_file" +BOOT C: +EOF + + log i "Mounted base OS as C: (desktop mode)" +} + +mount_disks() { + local conf_file="$1" + local next_drive="${2:-C}" + + # Mount floppy disks on A: and B: + if [[ ${#FLOPPIES[@]} -gt 0 ]]; then + if [[ ${#FLOPPIES[@]} -eq 1 ]]; then + local floppy_cmd="IMGMOUNT A \"${FLOPPIES[0]}\" -t floppy" + cat <> "$conf_file" +REM Mount floppy disk +$floppy_cmd +EOF + log i "Added floppy mount: A: (${FLOPPIES[0]})" + else + local floppy_cmd="IMGMOUNT A \"${FLOPPIES[0]}\" \"${FLOPPIES[1]}\" -t floppy" + cat <> "$conf_file" +REM Mount floppy disks +$floppy_cmd +EOF + log i "Added floppy mounts: A: (${FLOPPIES[0]}), B: (${FLOPPIES[1]})" + if [[ ${#FLOPPIES[@]} -gt 2 ]]; then + log w "Warning: Only first 2 floppy disks supported (A: and B:). Ignoring remaining ${#FLOPPIES[@]}-2 floppy(ies)" + fi + fi + fi + + # Mount hard disks starting from current next_drive + for hd_path in "${HDISKS[@]}"; do + local hd_drive="$next_drive" + local hd_cmd="IMGMOUNT $hd_drive \"$hd_path\" -t hdd" + cat <> "$conf_file" +REM Mount hard disk +$hd_cmd +EOF + log i "Added hard disk mount: $hd_drive: ($hd_path)" + # Increment drive letter + next_drive=$(printf "\\$(printf '%03o' $(($(printf '%d' "'$next_drive") + 1)))") + done + + # Mount CD-ROMs on the remaining drive letters + if [[ ${#CDROMS[@]} -gt 0 ]]; then + local imgmount_cmd="IMGMOUNT $next_drive" + for iso_path in "${CDROMS[@]}"; do + imgmount_cmd="$imgmount_cmd \"$iso_path\"" + done + imgmount_cmd="$imgmount_cmd -t cdrom" + + cat <> "$conf_file" +REM Mount CD-ROMs +$imgmount_cmd +EOF + + log i "Added CD-ROM mount: $next_drive: (${#CDROMS[@]} image(s))" + fi +} + +# ============================================================================ +# CONFIG GENERATION +# ============================================================================ + +create_launcher_bat() { + local launcher_dir="$1" + local exec_arg="${2:-}" + local launcher_bat="$launcher_dir/run_game.bat" + + mkdir -p "$launcher_dir" + + local game_filename=$(basename "$GAME_PATH") + local game_filename_dos=$(echo "$game_filename" | tr '[:lower:]' '[:upper:]') + + # If no exec_arg and no GAME_PATH (desktop mode) do NOT create a + # placeholder launcher — the user requested removal of the placeholder + # behavior. Simply return and leave launcher_dir empty (nothing to copy). + if [[ -z "$exec_arg" && -z "${GAME_PATH:-}" ]]; then + log d "No exec target and no GAME_PATH: skipping launcher creation (desktop placeholder removed)" + return 0 + fi + + # Create launcher BAT with proper Windows CRLF line endings using printf. + # If an exec target was supplied, produce a search-and-run BAT that uses + # the bash-side EXEC_SEARCH_LATE array to keep low-priority directories for + # the second pass. + if [[ -n "$exec_arg" ]]; then + { + printf '%s\r\n' "REM Launcher for --exec target" + printf '%s\r\n' "@ECHO OFF" + printf '%s\r\n' "CLS" + printf '%s\r\n' "SET TARGET=%s" "$exec_arg" + + # Direct path check + printf '%s\r\n' 'echo %TARGET% | find ":" >NUL' + printf '%s\r\n' 'if NOT ERRORLEVEL 1 (' + printf '%s\r\n' ' if exist "%TARGET%" (' + printf '%s\r\n' ' START /WAIT "" "%TARGET%"' + printf '%s\r\n' ' goto :END_EXEC' + printf '%s\r\n' ' ) else (' + printf '%s\r\n' ' ECHO Could not find "%TARGET%" — aborting' + printf '%s\r\n' ' goto :END_EXEC' + printf '%s\r\n' ' )' + printf '%s\r\n' ')' + + # First pass: search C:\ and avoid low-priority locations + printf '%s\r\n' '' + printf '%s\r\n' 'REM First pass: search C:\\ and skip low-priority directories' + printf '%s\r\n' 'set FOUND=' + printf '%s\r\n' 'for /r C:\\ %%F in (%TARGET%) do (' + + # nested checks created from bash-side EXEC_SEARCH_LATE + for pat in "${EXEC_SEARCH_LATE[@]}"; do + printf '%s\r\n' " echo %%F | find /i '\\${pat}\\' >NUL" >> "$launcher_bat" + printf '%s\r\n' " if errorlevel 1 (" >> "$launcher_bat" + done + + printf '%s\r\n' ' set FOUND=%%F' + printf '%s\r\n' ' goto :RUN_FOUND' + + # Close nested ifs + for _ in "${EXEC_SEARCH_LATE[@]}"; do + printf '%s\r\n' ' )' >> "$launcher_bat" + done + + printf '%s\r\n' ')' + + # Second pass: accept low-priority locations + printf '%s\r\n' '' + printf '%s\r\n' 'REM Second pass: accept any locations (including low-priority dirs)' + printf '%s\r\n' 'for /r C:\\ %%F in (%TARGET%) do (' >> "$launcher_bat" + printf '%s\r\n' ' set FOUND=%%F' >> "$launcher_bat" + printf '%s\r\n' ' goto :RUN_FOUND' >> "$launcher_bat" + printf '%s\r\n' ')' >> "$launcher_bat" + + printf '%s\r\n' '' >> "$launcher_bat" + printf '%s\r\n' 'ECHO Could not find %TARGET% on C:\\' >> "$launcher_bat" + printf '%s\r\n' 'goto :END_EXEC' >> "$launcher_bat" + printf '%s\r\n' '' >> "$launcher_bat" + printf '%s\r\n' ':RUN_FOUND' >> "$launcher_bat" + printf '%s\r\n' 'ECHO Found %FOUND%' >> "$launcher_bat" + printf '%s\r\n' 'START /WAIT "" "%FOUND%"' >> "$launcher_bat" + printf '%s\r\n' '' >> "$launcher_bat" + printf '%s\r\n' ':END_EXEC' >> "$launcher_bat" + printf '%s\r\n' '' >> "$launcher_bat" + printf '%s\r\n' 'REM Program finished' >> "$launcher_bat" + printf '%s\r\n' 'RUNDLL32.EXE USER.EXE,ExitWindows' >> "$launcher_bat" + } > "$launcher_bat" + else + # Default behaviour: run main game in C:\ + { + printf '%s\r\n' "REM Launcher for game" + printf '%s\r\n' "@ECHO OFF" + printf '%s\r\n' "CLS" + printf '%s\r\n' "REM Execute the game from C: (per-game child). No fallback — C: must contain the game." \ + "IF EXIST C:\\$game_filename_dos (" \ + " C:" \ + " START /WAIT $game_filename_dos" \ + ") ELSE (" \ + " ECHO Could not find $game_filename_dos on C: — aborting" \ + ")" + printf '%s\r\n' "REM Game finished" + printf '%s\r\n' "RUNDLL32.EXE USER.EXE,ExitWindows" + } > "$launcher_bat" + fi + + log d "Created launcher BAT at: $launcher_bat" +} + +prepare_config() { + rm -f "$TMP_CONF" + # Create TMP_CONF from the OS-specific config (if available). The launch + # order will be: -conf $dosbox_x_config -conf $TMP_CONF so that entries in + # the OS-specific config override the base. If no OS config is available, + # fall back to copying the base config so runtime writers (eg set_setting_value) + # can operate on TMP_CONF. + if [[ -n "$OS_CONFIG_DIR" && -n "$WIN_VERSION" && -f "$OS_CONFIG_DIR/$WIN_VERSION.conf" ]]; then + log d "Preparing TMP_CONF from OS config: $OS_CONFIG_DIR/$WIN_VERSION.conf" + cp "$OS_CONFIG_DIR/$WIN_VERSION.conf" "$TMP_CONF" + elif [[ -f "$dosbox_x_config" ]]; then + log d "No OS config found; using base dosbox config as TMP_CONF: $dosbox_x_config" + cp "$dosbox_x_config" "$TMP_CONF" + else + > "$TMP_CONF" + fi + + # Strip all comments (full-line and inline '#' comments) from the temporary + # config so the runtime-only TMP_CONF is clean and doesn't contain commented + # configuration values. This removes the '#' and everything after it on a + # line then drops blank lines. + if [[ -f "$TMP_CONF" ]]; then + awk '{ sub(/#.*/, ""); if (match($0,/[^[:space:]]/)) print }' "$TMP_CONF" > "${TMP_CONF}.no_comments" && mv "${TMP_CONF}.no_comments" "$TMP_CONF" + log d "Stripped comments from temporary config: $TMP_CONF" + fi + # Remove [autoexec] section and everything after it, then add fresh [autoexec] + sed -i '/^\[autoexec\]/,$d' "$TMP_CONF" + + cat <> "$TMP_CONF" +[autoexec] +EOF +} + +generate_autoexec() { + if [[ $DESKTOP_MODE -eq 1 ]]; then + # In desktop mode we want to update the base image's Startup with + # a fresh launcher unless NO_LAUNCHER is active. Previously the + # script skipped creating the launcher in desktop mode which left + # stale run_game.bat files in the base VHD. Create it here so the + # subsequent autoexec can copy it into C:\Startup. + # Only create a launcher when not in maintenance mode AND the + # invocation actually requests a launcher (either --exec or a + # positional GAME_PATH). This prevents creating empty launcher + # directories during desktop-only invocations. + if [[ "$NO_LAUNCHER" -eq 0 && ( -n "$EXEC_ARG" || -n "$GAME_PATH" ) ]]; then + create_launcher_bat "$LAUNCHER_DIR" "$EXEC_ARG" + else + log i "--nolauncher active: skipping creation of run_game.bat for desktop mode" + fi + generate_autoexec_desktop "$TMP_CONF" "$VHD_BASE_PATH" + elif [[ $INSTALL_MODE -eq 1 ]]; then + if [[ $IS_OS_INSTALL -eq 1 ]]; then + generate_autoexec_install_os "$TMP_CONF" + fi + else + # Only create a launcher when not in maintenance mode and when we + # have either an explicit exec target or a game path (normal game + # launch). Avoid creating launcher artifacts otherwise. + if [[ "$NO_LAUNCHER" -eq 0 && ( -n "$EXEC_ARG" || -n "$GAME_PATH" ) ]]; then + create_launcher_bat "$LAUNCHER_DIR" "$EXEC_ARG" + else + log i "--nolauncher active: skipping creation of run_game.bat (maintenance mode)" + fi + # Pass the prepared game-layer and write-layer into the autoexec generator. + # The generator will fall back to globals if either is empty. + generate_autoexec_launch "$TMP_CONF" "$VHD_GAME_LAYER" "$LAUNCHER_DIR" + fi +} + +log_config() { + log d "Launching DOSBox-X with the following config:" + log d "-----------------------------------" + awk '/^\[autoexec\]/ {print_flag=1; print; next} /^\[/ {print_flag=0} print_flag' "$TMP_CONF" + log d "-----------------------------------" + echo "" +} + +# ============================================================================ +# MODE HANDLERS: --install +# ============================================================================ + +handle_install_os() { + local os_config_dir="$1" + local vhd_base_path="$2" + + IS_OS_INSTALL=1 + WIN_VERSION="$INSTALL_NAME" + log i "OS install mode: Installing $WIN_VERSION" + configurator_generic_dialog "RetroDECK - Installing $WIN_VERSION" "Please follow the Windows Setup prompts to install the operating system and set it up for your needings.\nYou might want to change the desktop resolution and the colors.\n\nThe installation will start in TURBO mode, but any key input will disable it, please re-enable it during the loading bars to speed them up." + # Treat the install name exactly as provided by the user. The only + # special-case: if the name ends with .vhd (any case) strip that suffix + # because we will append ".vhd" ourselves when creating the game layer + # file. This keeps behaviour simple and predictable for callers. + GAME_NAME_FOR_DIR="$INSTALL_NAME" + # If the user passed a path, use only the basename so we always create the + # layer VHD under roms_path//.vhd rather than creating + # nested directories under the roms path. + if [[ "$GAME_NAME_FOR_DIR" == */* ]]; then + GAME_NAME_FOR_DIR="$(basename "$GAME_NAME_FOR_DIR")" + fi + + # Strip trailing .vhd if present so callers can pass either "name" or + # "name.vhd" — we still always create .vhd later. + if [[ "${GAME_NAME_FOR_DIR,,}" == *.vhd ]]; then + GAME_NAME_FOR_DIR="${GAME_NAME_FOR_DIR%.[vV][hH][dD]}" + fi + log i "Game install mode: Installing $GAME_NAME_FOR_DIR" + + if [[ ! -f "$vhd_base_path" ]]; then + log e "Windows VHD not found at: $vhd_base_path" + log e "Please install the Windows image first using: $0 --install $WIN_VERSION" + exit 1 + fi + + # Try to create a game-layer using the explicit install name + log d "Attempting game-layer creation with requested install name: '$GAME_NAME_FOR_DIR'" + + # If VHD wasn't created and a CD-ROM was provided, fall back to deriving the + # game name from the first CD-ROM image's basename (strip extension). This is + # convenient when callers pass an install name that differs from the CD's + # filename — e.g. user typed 'Rages of Mages II' but ISO is 'Rage of Mages II...'. + if [[ -z "$VHD_GAME_LAYER" || ! -f "$VHD_GAME_LAYER" ]]; then + if [[ ${#CDROMS[@]} -gt 0 ]]; then + local iso_basename + iso_basename="$(basename "${CDROMS[0]}")" + iso_basename="${iso_basename%.*}" + # Strip trailing .vhd if someone used weird filenames like name.vhd.iso + if [[ "${iso_basename,,}" == *.vhd ]]; then + iso_basename="${iso_basename%.[vV][hH][dD]}" + fi + + # Only try fallback if the name differs from the supplied name + if [[ "$iso_basename" != "$GAME_NAME_FOR_DIR" ]]; then + log i "Primary game-layer creation did not succeed; falling back to ISO-derived name: '$iso_basename'" + GAME_NAME_FOR_DIR="$iso_basename" + VHD_GAME_LAYER=$(create_game_layer_vhd "$GAME_NAME_FOR_DIR") + else + log w "Game-layer not created by either requested name or ISO basename; no VHD prepared." + fi + else + log w "Game-layer creation failed and no CD-ROM provided to derive a name from." + fi + fi +} + +handle_install_mode() { + local os_config_dir="$1" + local vhd_base_path="$2" + + if [[ -f "$os_config_dir/$INSTALL_NAME.conf" ]]; then + handle_install_os "$os_config_dir" "$vhd_base_path" + else + handle_install_game "$vhd_base_path" + fi +} + +# ============================================================================ +# MODE HANDLERS: --desktop +# ============================================================================ + +handle_desktop_mode() { + log w "DESKTOP MODE - ALL CHANGES ARE PERMANENT TO BASE IMAGE!" + log w "Any modifications will persist across all games." + log w "Use only for troubleshooting/configuration." + + WIN_VERSION="$DESKTOP_VERSION" + log i "Desktop mode: Launching base OS" +} + +# ============================================================================ +# MODE HANDLERS: normal launch +# ============================================================================ + +handle_launch_mode() { + local game_path="$1" + local roms_path_base="$2" + + GAME_NAME_FOR_DIR="$game_path" + log i "Launch mode: Launching $GAME_NAME_FOR_DIR" + + + + # Following eXoWin9x architecture: + # Two-layer layout for this component: + # - C: = per-game writeable child mounted stacked on the OS base (contains OS, game files and save files) + # - D: reserved for additional devices (CD-ROMs, extra HDs provided to the launcher) + + # Two-layer model: per-game VHD is the single writeable layer (contains + # installed game and save files). We store per-game VHD under roms_path so + # GAME_VHD_PATH is used both for game files and save files. + local sanitized_game_name + sanitized_game_name=$(sanitize_vhd_basename "$GAME_NAME_FOR_DIR") + + # D: game layer - check both new and old layouts for compatibility + local alt_game_vhd="$roms_path_base/$ESDE_SYSTEM_NAME/$GAME_NAME_FOR_DIR.vhd" + local alt_game_vhd_safe="$roms_path_base/$ESDE_SYSTEM_NAME/$sanitized_game_name.vhd" + local old_game_vhd="$roms_path_base/$ESDE_SYSTEM_NAME/$GAME_NAME_FOR_DIR/game-layer.vhd" + + if [[ -f "$old_game_vhd" ]]; then + GAME_VHD_PATH="$old_game_vhd" + log i "Using existing game VHD (old layout): $old_game_vhd" + elif [[ -f "$alt_game_vhd" ]]; then + GAME_VHD_PATH="$alt_game_vhd" + log i "Using existing game VHD (D: - original name): $alt_game_vhd" + else + GAME_VHD_PATH="$alt_game_vhd_safe" + log i "Game VHD path (D:): $GAME_VHD_PATH" + mkdir -p "$(dirname "$GAME_VHD_PATH")" + fi + + if [ ! -f "$GAME_VHD_PATH" ]; then + log i "Game VHD not found — attempting host-side creation (safer than in-guest)" + + # Try to create the differencing child on the host (invoking dosbox-x + # or qemu-img externally). Creating the VHD outside the booting + # instance avoids known crashes in some DOSBox-X builds when the + # create happens in-guest. + local created_vhd + created_vhd=$(create_packaged_game_layer_vhd "$GAME_NAME_FOR_DIR" 2>/dev/null || true) + + if [[ -n "$created_vhd" && -f "$created_vhd" ]]; then + GAME_VHD_PATH="$created_vhd" + log i "Game VHD successfully created on host: $GAME_VHD_PATH" + else + log w "Host-side creation attempt failed — falling back to in-guest auto-creation (may be unstable on some DOSBox-X builds)" + configurator_generic_dialog "RetroDECK - Game Install" "A per-game VHD $(basename \"$GAME_VHD_PATH\") will be created and used as the single writable game image.\n\nPlease install your game into C:\\ inside the Windows environment — the per-game VHD will be mounted as C: and contains the OS, the game and any save files the game creates.\n\nIf you want to preserve install and save data, backup the per-game VHD file after installation." + log i "First-time game launch: user instructed to install game in C:\\ (in-guest create fallback)" + fi + fi +} + +# ============================================================================ +# MAIN SCRIPT +# ============================================================================ + +main() { + init_globals + + # Extract arguments from either CLI or environment + local final_args + mapfile -t final_args < <(extract_args_from_environment "$@") + + # Pre-filter flags that should not be interpreted as positional + # arguments (e.g. --nolauncher). Remove them from final_args so the + # subsequent dispatch logic doesn't treat them as game names. + local filtered_args=() + for ((i=0; i<${#final_args[@]}; i++)); do + case "${final_args[$i]}" in + --nolauncher) + NO_LAUNCHER=1 + ;; + --dump-conf) + DUMP_CONF=1 + ;; + *) + filtered_args+=("${final_args[$i]}") + ;; + esac + done + # Replace final_args with the filtered list + final_args=("${filtered_args[@]:-}") + + # Route based on first argument + case "${final_args[0]}" in + --help|-h) + show_help + exit 0 + ;; + --desktop) + DESKTOP_MODE=1 + DESKTOP_VERSION="${final_args[1]}" + if [[ -z "$DESKTOP_VERSION" || "$DESKTOP_VERSION" == --* ]]; then + log e "--desktop requires an argument (win98 or win31)" + exit 1 + fi + WIN_VERSION="$DESKTOP_VERSION" + ;; + --package-game) + PACK_MODE=1 + PACK_GAME_NAME="${final_args[1]}" + if [[ -z "$PACK_GAME_NAME" || "$PACK_GAME_NAME" == --* ]]; then + log e "--package-game requires a game name" + exit 1 + fi + ;; + --makefs) + MAKEFS_MODE=1 + MAKEFS_VERSION="${final_args[1]}" + if [[ -z "$MAKEFS_VERSION" || "$MAKEFS_VERSION" == --* ]]; then + log e "--makefs requires an argument (win98 or win31)" + exit 1 + fi + handle_makefs_mode + ;; + --install) + INSTALL_MODE=1 + INSTALL_NAME="${final_args[1]}" + if [[ -z "$INSTALL_NAME" || "$INSTALL_NAME" == --* ]]; then + log e "--install requires an argument" + exit 1 + fi + # Check if it's a Windows version or a game + if [[ -f "$OS_CONFIG_DIR/$INSTALL_NAME.conf" ]]; then + WIN_VERSION="$INSTALL_NAME" + else + WIN_VERSION="${WIN_VERSION:-win98}" + fi + # Parse remaining args for --cdrom/--cd-rom, --floppy, --hd, -f flag and --drivers + for ((i=2; i<${#final_args[@]}; i++)); do + if [[ "${final_args[$i]}" == "--cd-rom" || "${final_args[$i]}" == "--cdrom" ]]; then + ((i++)) + CDROMS+=("${final_args[$i]}") + elif [[ "${final_args[$i]}" == "--floppy" ]]; then + ((i++)) + FLOPPIES+=("${final_args[$i]}") + elif [[ "${final_args[$i]}" == "--hd" ]]; then + ((i++)) + HDISKS+=("${final_args[$i]}") + elif [[ "${final_args[$i]}" == "-f" ]]; then + FORCE_RECREATE=1 + elif [[ "${final_args[$i]}" == "--drivers" ]]; then + ((i++)) + DRIVER_COPY_MODE="${final_args[$i]}" + if [[ ! "${DRIVER_COPY_MODE}" =~ ^(minimal|all|none)$ ]]; then + log e "Invalid --drivers option: ${DRIVER_COPY_MODE} (must be minimal|all|none)" + exit 1 + fi + fi + done + ;; + --game) + # Game launch/install mode (unified) + GAME_PATH="${final_args[1]}" + if [[ -z "$GAME_PATH" || "$GAME_PATH" == --* ]]; then + log e "--game requires a game name argument" + exit 1 + fi + WIN_VERSION="${WIN_VERSION:-win98}" + # Parse remaining args for --os, --cdrom, --floppy, --hd, etc. + for ((i=2; i<${#final_args[@]}; i++)); do + if [[ "${final_args[$i]}" == "--os" ]]; then + ((i++)) + WIN_VERSION="${final_args[$i]}" + elif [[ "${final_args[$i]}" == "--cd-rom" || "${final_args[$i]}" == "--cdrom" ]]; then + ((i++)) + CDROMS+=("${final_args[$i]}") + elif [[ "${final_args[$i]}" == "--floppy" ]]; then + ((i++)) + FLOPPIES+=("${final_args[$i]}") + elif [[ "${final_args[$i]}" == "--hd" ]]; then + ((i++)) + HDISKS+=("${final_args[$i]}") + elif [[ "${final_args[$i]}" == "--drivers" ]]; then + ((i++)) + DRIVER_COPY_MODE="${final_args[$i]}" + if [[ ! "${DRIVER_COPY_MODE}" =~ ^(minimal|all|none)$ ]]; then + log e "Invalid --drivers option: ${DRIVER_COPY_MODE} (must be minimal|all|none)" + exit 1 + fi + fi + done + ;; + *) + # Game launch mode (legacy: first arg is game name, default win98) + if [[ -z "${final_args[0]}" ]]; then + log e "No game path provided, --install, --game, or --desktop specified!" + log i "Usage:" + log i " $0 --game GameName --cdrom '...iso' (launch/install game)" + log i " $0 --install GameName (install OS or game)" + log i " $0 --desktop win98 (desktop mode)" + log i "Use '$0 --help' for more information." + exit 1 + fi + WIN_VERSION="${WIN_VERSION:-win98}" + GAME_PATH="${final_args[0]}" + ;; + esac + + # Ensure a default WIN_VERSION when not supplied + WIN_VERSION="${WIN_VERSION:-win98}" + + # Common setup + setup_paths + setup_launcher_dir + # If packaging-only mode was requested, skip runtime verification and run the + # host packaging helper (must be executed during develop/packaging). + if [[ $PACK_MODE -eq 1 ]]; then + if [[ -z "$PACK_GAME_NAME" ]]; then + log e "--package-game requires a game name" + exit 1 + fi + create_packaged_game_layer_vhd "$PACK_GAME_NAME" + exit $? + fi + + verify_os_config + + # Packaging-only flow (run on host during packaging). + if [[ $PACK_MODE -eq 1 ]]; then + if [[ -z "$PACK_GAME_NAME" ]]; then + log e "--package-game requires a game name" + exit 1 + fi + create_packaged_game_layer_vhd "$PACK_GAME_NAME" + exit $? + fi + + # Execute mode + case 1 in + $DESKTOP_MODE) + handle_desktop_mode + ;; + $MAKEFS_MODE) + exit 0 + ;; + $INSTALL_MODE) + handle_install_mode "$OS_CONFIG_DIR" "$VHD_BASE_PATH" + ;; + *) + handle_launch_mode "$GAME_PATH" "$roms_path" + ;; + esac + + # Prepare and launch + prepare_config + generate_autoexec + log_config + + # If requested, dump the temporary config and exit (useful for debugging) + if [[ "$DUMP_CONF" -eq 1 ]]; then + log i "--dump-conf active: printing generated TMP_CONF and exiting" + cat "$TMP_CONF" + exit 0 + fi + + # Build DOSBox-X command with optional overrides; pass base config first + # then the OS-specific TMP_CONF so the last file wins for duplicate settings. + local dosbox_cmd=("$component_path/bin/dosbox-x") + if [[ -f "$dosbox_x_config" ]]; then + dosbox_cmd+=("-conf" "$dosbox_x_config") + fi + # TMP_CONF is created from OS config (or from base when OS config missing) + dosbox_cmd+=("-conf" "$TMP_CONF") + + # Disable dynamic CPU during OS installation for stability and enable TURBO. + # Prefer to write these values to the temporary config (TMP_CONF) using + # set_setting_value when available; fall back to CLI -set overrides otherwise. + if [[ $INSTALL_MODE -eq 1 && $IS_OS_INSTALL -eq 1 ]]; then + # Persist the stabilization and performance settings into the temporary + # configuration file so DOSBox-X reads them from config during startup. + # We assume set_setting_value is available in the environment. + log i "Applying cpu settings to temporary config ($TMP_CONF) via set_setting_value" + set_setting_value "$TMP_CONF" "dynamic" "false" "dosbox-x" "cpu" || \ + log w "Failed to set TMP_CONF dynamic=false via set_setting_value" + set_setting_value "$TMP_CONF" "turbo" "true" "dosbox-x" "cpu" || \ + log w "Failed to set TMP_CONF turbo=true via set_setting_value" + fi + + # Final messages + if [[ $INSTALL_MODE -eq 1 && $IS_OS_INSTALL -eq 1 ]]; then + log i "Windows installation environment ready!" + log i "Once complete, install games with: $0 --install " + fi + + echo "" + + # Run DOSBox-X directly (dynamic=false is enabled earlier during OS install) + "${dosbox_cmd[@]}" +} + +main "$@" + +log d "Config file used:\n$(cat "$TMP_CONF")" \ No newline at end of file diff --git a/dosbox-x/rd_assets/rd_config/dosbox-x.conf b/dosbox-x/rd_assets/rd_config/dosbox-x.conf new file mode 100644 index 00000000..c8961341 --- /dev/null +++ b/dosbox-x/rd_assets/rd_config/dosbox-x.conf @@ -0,0 +1,1348 @@ +# This is the configuration file for DOSBox-X 2025.05.03. (Please use the latest version of DOSBox-X) +# Lines starting with a # are comment lines and are ignored by DOSBox-X. +# They are used to (briefly) document the effect of each option. +# To write out ALL options, use command 'config -all' with -wc or -writeconf options. + +[sdl] +# fullscreen: Start DOSBox-X directly in fullscreen. (Press [F11/F12]+F to go back) +# fulldouble: Use double buffering in fullscreen. It can reduce screen flickering, but it can also result in a slow DOSBox-X. +# fullresolution: What resolution to use for fullscreen: original, desktop or a fixed size (e.g. 1024x768). +# Using your monitor's native resolution with aspect=true might give the best results. +# If you end up with small window on a large screen, try an output different from surface. +# windowresolution: Scale the window to this size IF the output device supports hardware scaling. +# (output=surface does not!) +# windowposition: Set the window position at startup in the positionX,positionY format (e.g.: 1300,200). +# The window will be centered with "," (or empty), and will be in the original position with "-". +# display: Specify a screen/display number to use for a multi-screen setup (0 = default). +# output: What video system to use for output (surface = software (SDL_Surface); openglnb = OpenGL nearest; openglpp = OpenGL perfect; ttf = TrueType font output). +# Possible values: default, surface, overlay, ttf, opengl, openglnb, openglhq, openglpp, gamelink, ddraw, direct3d. +# videodriver: Forces a video driver (e.g. windib/windows, directx, x11, fbcon, dummy, etc) for the SDL library to use. +# transparency: Set the transparency of the DOSBox-X screen (both windowed and full-screen modes, on SDL2 and Windows SDL1 builds). +# The valid value is from 0 (no transparency, the default setting) to 90 (high transparency). +# maximize: If set, the DOSBox-X window will be maximized at start (SDL2 and Windows SDL1 builds only; use fullscreen for TTF output). +# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) +# autolock_feedback: Autolock status feedback type, i.e. visual, auditive, none. +# Possible values: none, beep, flash. +# middle_unlock: Whether you can press the middle mouse button to unlock the mouse when the mouse has been locked. +# If set to "manual", it works only with "autolock=false"; if set to "auto", it works only with "autolock=true". +# Possible values: none, manual, auto, both. +# clip_mouse_button: Select the mouse button or use arrow keys for the shared clipboard copy/paste function. +# The default mouse button is "right", which means using the right mouse button to select text, copy to and paste from the host clipboard. +# Set to "middle" to use the middle mouse button, "arrows" to use arrow keys instead of a mouse button, or "none" to disable this feature. +# For "arrows", press Home key (or Fn+Shift+Left on Mac laptops) to start selection, and End key (or Fn+Shift+Right on Mac laptops) to end selection. +# Possible values: none, middle, right, arrows. +# clip_key_modifier: Change the keyboard modifier for the shared clipboard copy/paste function using a mouse button or arrow keys. +# The default modifier is "shift" (both left and right shift keys). Set to "none" if no modifier is desired. +# Possible values: none, ctrl, lctrl, rctrl, alt, lalt, ralt, shift, lshift, rshift, ctrlalt, ctrlshift, altshift, lctrlalt, lctrlshift, laltshift, rctrlalt, rctrlshift, raltshift. +# clip_paste_bios: Specify whether to use BIOS keyboard functions for the clipboard pasting instead of the keystroke method. +# For pasting clipboard text into Windows 3.x/9x applications (e.g. Notepad), make sure to use the keystroke method. +# Possible values: true, false, 1, 0, default. +# clip_paste_speed: Set keyboard speed for pasting text from the shared clipboard. +# If the default setting of 30 causes lost keystrokes, increase the number. +# Or experiment with decreasing the number for applications that accept keystrokes quickly. +# sensitivity: Mouse sensitivity. The optional second parameter specifies vertical sensitivity (e.g. 100,-50). +# usesystemcursor: Use the mouse cursor of the host system instead of drawing a DOS mouse cursor. Activated when the mouse is not locked. +# mouse_emulation: When is mouse emulated ? +# integration: when not locked +# locked: when locked +# always: every time +# never: at no time +# If disabled, the mouse position in DOSBox-X is exactly where the host OS reports it. +# When using a high DPI mouse, the emulation of mouse movement can noticeably reduce the +# sensitiveness of your device, i.e. the mouse is slower but more precise. +# Possible values: integration, locked, always, never. +# mouse_wheel_key: Convert mouse wheel movements into keyboard presses such as arrow keys. +# 0: disabled; 1: up/down arrows; 2: left/right arrows; 3: PgUp/PgDn keys. +# 4: Ctrl+up/down arrows; 5: Ctrl+left/right arrows; 6: Ctrl+PgUp/PgDn keys. +# 7: Ctrl+W/Z, as supported by text editors like WordStar and MS-DOS EDIT. +# Putting a minus sign in front will disable the conversion for guest systems. +# waitonerror: Wait before closing the console if DOSBox-X has an error. +# priority: Priority levels for DOSBox-X. Second entry behind the comma is for when DOSBox-X is not focused/minimized. +# pause is only valid for the second entry. +# Possible values: lowest, lower, normal, higher, highest, pause. +# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the default value. +# usescancodes: Avoid usage of symkeys, in favor of scancodes. Might not work on all operating systems. +# If set to "auto" (default), it is enabled when using non-US keyboards in SDL1 builds. +# Possible values: true, false, 1, 0, auto. +# overscan: Width of the overscan border (0 to 10) for the "surface" output. +# titlebar: Change the string displayed in the DOSBox-X title bar. +# showbasic: If set, DOSBox-X will show basic information including the DOSBox-X version number and current running speed in the title bar. +# showdetails: If set, DOSBox-X will show the cycles count (FPS) and emulation speed relative to realtime in the title bar. +# showmenu: Whether to show the menu bar (if supported). Default true. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> raw_mouse_input; mapperfile_sdl1; mapperfile_sdl2; forcesquarecorner; gamelink master; gamelink snoop +# +fullscreen = false +fulldouble = false +fullresolution = original +windowresolution = original +windowposition = - +display = 0 +output = default +videodriver = +transparency = 0 +maximize = false +autolock = true +autolock_feedback = beep +middle_unlock = manual +clip_mouse_button = right +clip_key_modifier = shift +clip_paste_bios = default +clip_paste_speed = 30 +sensitivity = 100 +usesystemcursor = false +mouse_emulation = locked +mouse_wheel_key = -1 +waitonerror = true +priority = higher,normal +mapperfile = mapper-dosbox-x.map +usescancodes = auto +overscan = 0 +titlebar = +showbasic = true +showdetails = false +showmenu = true + +[log] +# logfile: file where the log messages will be saved to +# debuggerrun: The run mode when the DOSBox-X Debugger starts. +# Possible values: debugger, normal, watch. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> vga; vgagfx; vgamisc; int10; sblaster; dma_control; fpu; cpu; paging; fcb; files; ioctl; exec; dosmisc; pit; keyboard; pic; mouse; bios; gui; misc; io; pci; sst; int21; fileio +# +logfile = $logs_path/dosbox-x/dosbox-x.log +debuggerrun = debugger + +[dosbox] +# language: Select a language file for DOSBox-X to use. Encoded with either UTF-8 or a DOS code page. +# You can set code page either in the language file or with "country" setting in [config] section. +# title: Additional text to place in the title bar of the window. +# logo text: Text to place at the bottom of the screen during the startup logo. Text will line wrap automatically. +# To explicitly break to the next line, put \n in the string. +# logo: Location of PNG images to use in place of the DOSBox-X logo at startup. +# This is the path of the base file name. For example logo=subdir\sets\007\logo +# with machine=vgaonly will use subdir\sets\007\logo224x224.png as the logo. +# fastbioslogo: If set, DOSBox-X will skip the BIOS screen by activating fast BIOS logo mode (without 1-second pause). +# startbanner: If set (default), DOSBox-X will display the welcome banner when it starts. +# bannercolortheme: You can specify a different background color theme for the welcome banner from the default one. +# Possible values: default, black, red, green, yellow, blue, magenta, cyan, white. +# configuration tool theme: Theme for the configuration tool. +# If not set, host dark mode setting will be followed. +# +# Possible values: Windows Default, Arizona, Black Leather Jacket, Bordeaux, Cinnamon, Designer, Emerald City, Fluorescent, HotDog Stand, LCD Default Screen Settings, LCD Reversed - Dark, LCD Reversed - Light, Mahogany, Monochrome, Ocean, Pastel, Patchwork, Plasma Power Saver, Rugby, The Blues, Tweed, Valentine, Wingtips. +# dpi aware: Set this option (auto by default) to indicate to your OS that DOSBox-X is DPI aware. +# If it is not set, Windows Vista/7/8/10 and higher may upscale the DOSBox-X window +# on higher resolution monitors which is probably not what you want. +# Possible values: true, false, 1, 0, auto. +# quit warning: Set this option to indicate whether DOSBox-X should show a warning message when the user tries to close its window. +# If set to auto (default), DOSBox-X will warn if a DOS program, game or a guest system is currently running. +# If set to autofile, DOSBox-X will warn if there are open file handles or a guest system is currently running. +# Possible values: true, false, 1, 0, auto, autofile. +# working directory option: Select an option for DOSBox-X's working directory when it runs. +# autoprompt: DOSBox-X will auto-decide whether to prompt for a working directory. +# config: DOSBox-X will use the primary config file directory as the working directory. +# custom: Specify a working directory via the "working directory default" option. +# default: Similar to autoprompt, but DOSBox-X will ask whether to save the selected folder. +# force: Similar to "custom", while overriding -defaultdir command-line option if used. +# noprompt: DOSBox-X uses the current directory and never prompts for a working directory. +# program: DOSBox-X will use the DOSBox-X program directory as the working directory. +# prompt: DOSBox-X will always ask the user to select a working directory when it runs. +# userconfig: DOSBox-X will use its user configuration directory as the working directory. +# Possible values: autoprompt, config, custom, default, force, noprompt, program, prompt, userconfig. +# working directory default: The default directory to act as DOSBox-X's working directory. See also the setting "working directory option". +# For working directory option=prompt, the specified directory becomes the default directory for the folder selection. +# show advanced options: If set, the Configuration Tool will display all config options (including advanced ones) by default. +# resolve config path: If set to true, DOSBox-X will resolve options containing paths in the config file (except [autoexec] section). +# This includes environment variables (%VAR% [DOS/Windows] or ${VAR} [Linux/macOS] and tilde (~) in Linux/macOS. +# If set to dosvar, DOSBox-X forces to resolve DOS-style environment variables (%VAR%) in all platforms (and tilde). +# If set to tilde, DOSBox-X will only resolve tilde (~) in Linux/macOS but will not resolve environment variables. +# Possible values: true, false, dosvar, tilde, 1, 0. +# hostkey: By default, DOSBox-X uses the mapper-defined host key, which defaults to F11 on Windows and F12 on other platforms. +# You may alternatively specify a host key with this setting and bypass the host key as defined in the mapper. +# This can also be done from the menu ("Main" => "Select host key"). +# Possible values: ctrlalt, ctrlshift, altshift, mapper. +# mapper send key: Select the key the mapper SendKey function will send. +# Possible values: winlogo, winmenu, alttab, ctrlesc, ctrlbreak, ctrlaltdel. +# ime: Enables support for the system input methods (IME) for inputting characters in Windows and Linux builds. +# If set to auto, this feature is only enabled if DOSBox-X starts with a Chinese/Japanese/Korean code page. +# Possible values: true, false, 1, 0, auto. +# synchronize time: If set, DOSBox-X will try to automatically synchronize time with the host, unless you decide to change the date/time manually. +# machine: The type of machine DOSBox-X tries to emulate. +# Possible values: mda, cga, cga_mono, cga_rgb, cga_composite, cga_composite2, hercules, hercules_plus, hercules_incolor, hercules_color, tandy, pcjr, pcjr_composite, pcjr_composite2, amstrad, ega, ega200, jega, mcga, vgaonly, svga_s3, svga_s386c928, svga_s3vision864, svga_s3vision868, svga_s3vision964, svga_s3vision968, svga_s3trio32, svga_s3trio64, svga_s3trio64v+, svga_s3virge, svga_s3virgevx, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe, vesa_oldvbe10, pc98, pc9801, pc9821, svga_ati_egavgawonder, svga_ati_vgawonder, svga_ati_vgawonderplus, svga_ati_vgawonderxl, svga_ati_vgawonderxl24, svga_ati_mach8, svga_ati_mach32, svga_ati_mach64, fm_towns. +# captures: Directory where things like wave, midi, screenshot get captured. +# autosave: Enable the auto-save state feature. Specify a time interval in seconds, and optionally a save slot or start and end save slots. +# For example, "autosave=10 11-20" will set a 10-second time interval for auto-saving, and the save slots used will be between 11 and 20. +# You can additionally specify up to 9 programs for this feature, e.g. "autosave=10 11-20 EDIT:21-30 EDITOR:35" for "EDIT" and "EDITOR". +# Putting a minus sign (-) before the time interval causes the auto-saving function to not be activated at start. +# saveslot: Select the default save slot (1-100) to save/load states. +# savefile: Select the default save file to save/load states. If specified it will be used instead of the save slot. +# saveremark: If set, the save state feature will ask users to enter remarks when saving a state. +# forceloadstate: If set, DOSBox-X will load a saved state even if it finds there is a mismatch in the DOSBox-X version, machine type, program name and/or the memory size. +# a20: A20 gate emulation mode. +# The on/off/on_fake/off_fake options are intended for testing and debugging DOS development, +# or to emulate obscure hardware, or to work around potential extended memory problems with DOS programs. +# on_fake/off_fake are intended to test whether a program carries out a memory test to ensure the A20 +# gate is set as intended (as HIMEM.SYS does). If it goes by the gate bit alone, it WILL crash. +# This parameter is also changeable from the builtin A20GATE command. +# fast Emulate A20 gating by remapping the first 64KB @ 1MB boundary (fast, mainline DOSBox behavior) +# mask Emulate A20 gating by masking memory I/O address (accurate) +# off Lock A20 gate off (Software/OS cannot enable A20) +# on Lock A20 gate on (Software/OS cannot disable A20) +# off_fake Lock A20 gate off but allow bit to toggle (hope your DOS game tests the HMA!) +# on_fake Lock A20 gate on but allow bit to toggle +# memory file: If set, guest memory is memory-mapped from a file on disk, rather than allocated from memory. +# This option can help keep DOSBox-X from consuming too much RAM for large values of memsize. +# This option is required to emulate 4GB or more of RAM. The file will be created if it does not exist +# and it does not require any special maintenance or formatting. +# memsize: Amount of memory DOSBox-X has in megabytes. +# This value is best left at its default to avoid problems with some games, +# although other games and applications may require a higher value. +# Programs that use 286 protected mode like Windows 3.0 in Standard Mode may crash with more than 15MB. +# A memory file is required to emulate a memory size of 4GB or more. +# The maximum value allowed is affected by the memalias setting which affects the maximum amount of memory CPU can access as a power of 2. +# The maximum value is also affected by the CPU type. See DOSBox-X console and log file for details. +# The maximum setting 1048576 represents 1TB and requires at least a Pentium II and PSE-40 emulation. +# nocachedir: If set, MOUNT commands will mount with -nocachedir (disable directory caching) by default. +# freesizecap: If set to "cap" (="true"), the value of MOUNT -freesize will apply only if the actual free size is greater than the specified value. +# If set to "relative", the value of MOUNT -freesize will change relative to the specified value. +# If set to "fixed" (="false"), the value of MOUNT -freesize will be a fixed one to be reported all the time. +# Possible values: true, false, fixed, relative, cap, 2, 1, 0. +# convertdrivefat: If set, DOSBox-X will auto-convert mounted non-FAT drives (such as local drives) to FAT format for use with guest systems. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> disable graphical splash; allow quit after warning; keyboard hook; weitek; bochs debug port e9; video debug at startup; compresssaveparts; show recorded filename; skip encoding unchanged frames; capture chroma format; capture format; shell environment size; private area size; turn off a20 gate on boot; cbus bus clock; isa bus clock; pci bus clock; call binary on reset; unhandled irq handler; call binary on boot; ibm rom basic; rom bios allocation max; rom bios minimum size; irq delay ns; iodelay; iodelay16; iodelay32; acpi; acpi rsd ptr location; acpi sci irq; acpi iobase; acpi reserved size; memsizekb; dos mem limit; isa memory hole at 512kb; isa memory hole at 15mb; reboot delay; memalias; convert fat free space; convert fat timeout; leading colon write protect image; locking disk image mount; unmask keyboard on int 16 read; int16 keyboard polling undocumented cf behavior; allow port 92 reset; enable port 92; enable 1st dma controller; enable 2nd dma controller; allow dma address decrement; enable 128k capable 16-bit dma; enable dma extra page registers; dma page registers write-only; cascade interrupt never in service; cascade interrupt ignore in service; enable slave pic; enable pc nmi mask; allow more than 640kb base memory; enable pci bus +# +language = +title = RetroDECK +logo text = RetroDECK is loading your Windows environment +logo = /app/retrodeck/graphics/splash.svg +fastbioslogo = true +startbanner = true +bannercolortheme = default +configuration tool theme = Windows Default +dpi aware = auto +quit warning = false +working directory option = default +working directory default = $storage_path/windows/dosbox-x +show advanced options = false +resolve config path = true +hostkey = mapper +mapper send key = ctrlaltdel +ime = auto +synchronize time = true +machine = svga_s3 +captures = capture +autosave = +saveslot = 1 +savefile = +saveremark = true +forceloadstate = false +a20 = mask +memory file = +memsize = 16 +nocachedir = false +freesizecap = cap +convertdrivefat = true + +[render] +# frameskip: How many frames DOSBox-X skips before drawing one. +# aspect: Aspect ratio correction mode. Can be set to the following values: +# 'false' (default): +# 'direct3d'/opengl outputs: image is simply scaled to full +# window/fullscreen size, possibly resulting in dis- +# proportional image +# 'surface' output: it does no aspect ratio correction, +# resulting in disproportional images if VGA mode pixel +# ratio is not 4:3 (default) +# 'true': +# 'direct3d'/opengl outputs: uses output driver functions to +# scale / pad image with black bars, correcting output +# to proportional 4:3 image +# In most cases image degradation should not be noticeable +# (it all depends on the video adapter and how much the image +# is upscaled). +# Should have none to negligible impact on performance, +# mostly being done in hardware. +# For the pixel-perfect scaling (output=openglpp), it is +# recommended to enable this whenever the emulated display +# has an aspect ratio of 4:3 +# 'surface' output: inherits old DOSBox aspect ratio correction +# method (adjusting rendered image line count to correct +# output to 4:3 ratio) +# Due to source image manipulation this mode does not mix +# well with scalers, i.e. multiline scalers like hq2x/hq3x +# will work poorly +# Slightly degrades visual image quality. Has a tiny impact +# on performance. +# When using xBRZ scaler with 'surface' output, aspect +# ratio correction is done by the scaler itself, so none of +# the above apply. +# Possible values: false, true, 0, 1, yes, no, nearest, bilinear. +# aspect_ratio: Set the aspect ratio (e.g. 16:9) in the aspect ratio correction mode. 0:0 means the default ratio of 4:3, and -1:-1 means the original image ratio. +# char9: Allow 9-pixel wide text mode fonts instead of 8-pixel wide fonts. +# euro: Display Euro symbol instead of the specified ASCII character (33-255). +# For example, setting it to 128 allows Euro symbol to be displayed instead of C-cedilla. +# doublescan: If set, doublescanned output emits two scanlines for each source line, in the same manner as the actual VGA output (320x200 is rendered as 640x400 for example). +# If clear, doublescanned output is rendered at the native source resolution (320x200 as 320x200). +# This affects the raster PRIOR to the software or hardware scalers. +# Setting this option may prevent some scalers to work as expected. +# Try turning this option off in such case. +# For pixel-perfect scaling (output=openglpp), it is recommended to turn this option off. +# scaler: Scaler used to enlarge/enhance low resolution modes. Add keyword 'forced', after the name of the scaler to always use the scaler even if the result might not be desired.(e.g. 'normal2x forced') +# Appending 'prompt' will cause a confirmation message for forcing the scaler. +# To fit a scaler in the resolution used at full screen may require a border or side bars. +# To fill the screen entirely, depending on your hardware, a different scaler/fullresolution might work. +# Scalers should work with most output options, but they are ignored for openglpp and TrueType font outputs. +# If you are using OpenGL/Direct3D output and a shader that requires it, set to hardware_none or hardware2x. +# Possible values: none, normal2x, normal3x, normal4x, normal5x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x, gray, gray2x, hardware_none, hardware2x, hardware3x, hardware4x, hardware5x, xbrz, xbrz_bilinear. +# glshader: Path to GLSL shader source to use with OpenGL output ("none" to disable, or "default" for default shader). +# Can be either an absolute path, a file in the "glshaders" subdirectory of the DOSBox-X configuration directory, or one of the built-in shaders (e.g. "sharp" for the pixel-perfect scaling mode): +# advinterp2x, advinterp3x, advmame2x, advmame3x, rgb2x, rgb3x, scan2x, scan3x, tv2x, tv3x, sharp. +# pixelshader: Set Direct3D pixel shader program (effect file must be in Shaders subdirectory). If 'forced' is appended, then the pixel shader will be used even if the result might not be desired. +# autofit: Best fits image to window +# Intended for output=direct3d, fullresolution=original, aspect=true +# monochrome_pal: Specify the color of monochrome display. +# Append 'bright' for a brighter look. +# Possible values: green, amber, gray, white. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> modeswitch; xbrz slice; xbrz fixed scale factor; xbrz max scale factor +# +frameskip = 0 +aspect = true +aspect_ratio = 0:0 +char9 = true +euro = -1 +doublescan = true +scaler = normal2x +glshader = none +pixelshader = none +autofit = true +monochrome_pal = green + +[pc98] +# pc-98 BIOS copyright string: If set, the PC-98 BIOS copyright string is placed at E800:0000. Enable this for software that detects PC-98 vs Epson. +# pc-98 fm board: In PC-98 mode, selects the FM music board to emulate. +# Possible values: auto, off, false, board14, board26k, board86, board86c. +# pc-98 enable 256-color: Allow 256-color graphics mode if set, disable if not set +# pc-98 enable 16-color: Allow 16-color graphics mode if set, disable if not set +# pc-98 enable grcg: Allow GRCG graphics functions if set, disable if not set +# pc-98 enable egc: Allow EGC graphics functions if set, disable if not set +# pc-98 bus mouse: Enable PC-98 bus mouse emulation. Disabling this option does not disable INT 33h emulation. +# pc-98 force ibm keyboard layout: Force to use a default keyboard layout like IBM US-English for PC-98 emulation. +# Will only work with apps and games using BIOS for keyboard. +# Possible values: true, false, 1, 0, auto. +# pc-98 force JIS keyboard layout: Force to use a default keyboard layout like JIS (JP106) for PC-98 emulation. +# Will only work with apps and games using BIOS for keyboard. +# pc-98 try font rom: If enabled, DOSBox-X will first try to load FONT.ROM as generated by T98Tools for PC-98 emulation. +# pc-98 anex86 font: Specify an Anex86 compatible font to load as supported by the Anex86 emulator for PC-98 emulation. +# By default DOSBox-X tries to load ANEX86.BMP followed by FREECG98.BMP after trying to load FONT.ROM. +# If you specify a font here then it will be tried first, perhaps before FONT.ROM (see previous option). +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> pc-98 int 1b fdc timer wait; pc-98 pic init to read isr; pc-98 fm board irq; pc-98 fm board io port; pc-98 time stamp; pc-98 sound bios; pc-98 load sound bios rom file; pc-98 buffer page flip; pc-98 enable 256-color planar; pc-98 enable 188 user cg; pc-98 start gdc at 5mhz; pc-98 allow scanline effect; pc-98 nec mouse function; pc-98 video mode; pc-98 timer always cycles; pc-98 timer master frequency; pc-98 allow 4 display partition graphics; pc-98 fontx sbcs; pc-98 fontx dbcs; pc-98 fontx internal symbol; pc-98 show graphics layer on initialize +# +pc-98 BIOS copyright string = false +pc-98 fm board = auto +pc-98 enable 256-color = true +pc-98 enable 16-color = true +pc-98 enable grcg = true +pc-98 enable egc = true +pc-98 bus mouse = true +pc-98 force ibm keyboard layout = auto +pc-98 force JIS keyboard layout = false +pc-98 try font rom = true +pc-98 anex86 font = + +[dosv] +# dosv: Enable DOS/V emulation and specify which version to emulate. This option is intended for use with games or software +# originating from East Asia (China, Japan, Korea) that use the double byte character set (DBCS) encodings and DOS/V extensions +# to display Japanese (jp), Chinese (chs/cht/cn/tw), or Korean (ko) text. Note that enabling DOS/V replaces 80x25 text mode with +# a EGA/VGA graphics mode that emulates text mode to display the characters and may be incompatible with non-Asian software that +# assumes direct access to the text mode via segment 0xB800. For a general DOS environment with CJK support please disable DOS/V +# emulation and use TrueType font (TTF) output with a CJK code page (932, 936, 949, 950) and TTF font with CJK characters instead. +# Possible values: off, jp, ko, chs, cht, cn, tw. +# getsysfont: If enabled, DOSBox-X will try to get and use the system fonts on Windows and Linux platforms for the DOS/V emulation. +# If this cannot be done, then DOSBox-X will try to use the internal Japanese DOS/V font, or you can specify a different font. +# fontxsbcs: FONTX2 file used to rendering SBCS characters (8x19) in DOS/V or JEGA mode. If not specified, the default one will be used. +# Loading the ASC16 and ASCFONT.15 font files (from the UCDOS and ETen Chinese DOS systems) is also supported for the DOS/V mode. +# fontxsbcs16: FONTX2 file used to rendering SBCS characters (8x16) in DOS/V or JEGA mode. If not specified, the default one will be used. +# Loading the ASC16 and ASCFONT.15 font files (from the UCDOS and ETen Chinese DOS systems) is also supported for the DOS/V mode. +# fontxsbcs24: FONTX2 file used to rendering SBCS characters (12x24) in DOS/V mode (with V-text). If not specified, the default one will be used. +# Loading the ASC24 and ASCFONT.24? font files (the latter from the ETen Chinese DOS system) is also supported for the DOS/V mode. +# fontxdbcs: FONTX2 file used to rendering DBCS characters (16x16) in DOS/V or VGA/JEGA mode. If not specified, the default one will be used. +# Alternatively, you can load a BDF or PCF font file (16x16 or 15x15), such as the free bitmap fonts from WenQuanYi (https://wenq.org/). +# For Simplified Chinese DOS/V, loading the HZK16 font file (https://github.com/aguegu/BitmapFont/tree/master/font) is also supported. +# For Traditional Chinese DOS/V, loading the STDFONT.15 font file from the ETen Chinese DOS system is also supported. +# fontxdbcs14: FONTX2 file used to rendering DBCS characters (14x14) for Configuration Tool or EGA mode. If not specified, the default one will be used. +# Alternatively, you can load a BDF or PCF font file (14x14 or 15x15), such as the free bitmap fonts from WenQuanYi (https://wenq.org/). +# For Simplified Chinese DOS/V, loading the HZK14 font file (https://github.com/aguegu/BitmapFont/tree/master/font) is also supported. +# For Traditional Chinese DOS/V, loading the STDFONT.15 font file from the ETen Chinese DOS system is also supported. +# fontxdbcs24: FONTX2 file used to rendering DBCS characters (24x24) in DOS/V mode (with V-text and 24-pixel fonts enabled). +# For Simplified Chinese DOS/V, loading the HZK24? font file (https://github.com/aguegu/BitmapFont/tree/master/font) is also supported. +# For Traditional Chinese DOS/V, loading the STDFONT.24 font file from the ETen Chinese DOS system is also supported. +# showdbcsnodosv: Enables rendering of Chinese/Japanese/Korean characters for DBCS code pages in standard VGA and EGA machine types in non-DOS/V and non-TTF mode. +# DOS/V fonts will be used in such cases, which can be adjusted by the above config options (such as fontxdbcs, fontxdbcs14, and fontxdbcs24). +# Setting to "auto" enables Chinese/Japanese/Korean character rendering if a language file is loaded (or with "autodbcs" option set) in such cases. +# Possible values: true, false, 1, 0, auto. +# yen: Enables the Japanese yen symbol at 5ch if it is found at 7fh in a custom SBCS font for the Japanese DOS/V or JEGA emulation. +# fepcontrol: FEP control API for the DOS/V emulation. +# Possible values: ias, mskanji, both. +# vtext1: V-text screen mode 1 for the DOS/V emulation. Enter command "VTEXT 1" for this mode. Note that XGA/SXGA mode is only supported by the svga_s3trio and svga_et4000 machine types. +# Possible values: xga, xga24, sxga, sxga24, svga. +# vtext2: V-text screen mode 2 for the DOS/V emulation. Enter command "VTEXT 2" for this mode. Note that XGA/SXGA mode is only supported by the svga_s3trio and svga_et4000 machine types. +# Possible values: xga, xga24, sxga, sxga24, svga. +# use20pixelfont: Enables the 20 pixel font to be used instead of the 24 pixel system font for the Japanese DOS/V emulation (with V-text enabled). +# j3100: With the setting dosv=jp and a non-off value of this option, the Toshiba J-3100 machine will be emulated with DCGA support. +# Setting to "on" or "auto" starts J-3100 automatically, and with the setting "manual" you can enter J-3100 mode with DCGA command. +# Possible values: off, on, auto, manual, 0, 1, 2. +# j3100type: Specifies the Toshiba J-3100 machine type if J-3100 mode is enabled. The color palette will be changed with different machine types. +# Possible values: default, gt, sgt, gx, gl, sl, sgx, ss, gs, sx, sxb, sxw, sxp, ez, zs, zx. +# j3100colorscroll: Specifies that the color display can be used for scrolling, which is currently incompatible with for example the J-3100 version of the SimCity game. +# The VGA version of the Toshiba Windows 3.1 works fine with the "false" value of this setting, whereas its CGA/EGA version requires a "true" value for this. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> del; j3100backcolor; j3100textcolor +# +dosv = off +getsysfont = true +fontxsbcs = +fontxsbcs16 = +fontxsbcs24 = +fontxdbcs = +fontxdbcs14 = +fontxdbcs24 = +showdbcsnodosv = auto +yen = false +fepcontrol = both +vtext1 = svga +vtext2 = xga +use20pixelfont = false +j3100 = off +j3100type = default +j3100colorscroll = false + +[video] +# vmemsize: Amount of video memory in megabytes. +# The maximum resolution and color depth the svga_s3 will be able to display +# is determined by this value. +# -1: auto (vmemsizekb is ignored) +# 0: 512k (800x600 at 256 colors) if vmemsizekb=0 +# 1: 1024x768 at 256 colors or 800x600 at 64k colors +# 2: 1600x1200 at 256 colors or 1024x768 at 64k colors or 640x480 at 16M colors +# 4: 1600x1200 at 64k colors or 1024x768 at 16M colors +# 8: up to 1600x1200 at 16M colors +# For build engine games, use more memory than in the list above so it can +# use triple buffering and thus won't flicker. +# +# vmemsizekb: Amount of video memory in kilobytes, in addition to vmemsize. +# high intensity blinking: Set to false if you want to see high-intensity background colors instead of blinking foreground text. +# This option has no effect in PC-98 and some other video modes. +# memory io optimization 1: Enable one class of EGA/VGA memory I/O optimizations. Default ON (true). +# If graphical artifacts or errors occur, try turning this off first. May provide a performance benefit. +# scanline render on demand: Render video output at vsync or when something is changed mid frame, instead of stopping to render every scanline. +# May provide a performance benefit to most DOS games. However this may also break timing-dependent game or Demoscene effects. +# Default auto, which will turn if off for VGA modes and turn it on for SVGA modes. +# Possible values: true, false, 1, 0, auto. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> int 10h use video parameter table; vmemdelay; lfb vmemdelay; prevent capture; vbe window granularity; vbe window size; enable 8-bit dac; svga lfb base; pci vga; vga attribute controller mapping; enable supermegazeux tweakmode; vga bios use rom image; vga bios rom image; vga bios size override; video bios dont duplicate cga first half rom font; video bios always offer 14-pixel high rom font; video bios always offer 16-pixel high rom font; video bios enable cga second half rom font; forcerate; sierra ramdac; sierra ramdac lock 565; vga fill active memory; page flip debug line; vertical retrace poll debug line; cgasnow; vga 3da undefined bits; rom bios 8x8 CGA font; rom bios video parameter table; int 10h points at vga bios; unmask timer on int 10 setmode; vesa bank switching window mirroring; vesa bank switching window range check; vesa zero buffer on get information; vesa set display vsync; vesa lfb base scanline adjust; vesa lfb pel scanline adjust; vesa map non-lfb modes to 128kb region; ega per scanline hpel; allow hpel effects; allow hretrace effects; hretrace effect weight; vesa modelist cap; vesa modelist width limit; vesa modelist height limit; vesa vbe put modelist in vesa information; vesa vbe 1.2 modes are 32bpp; allow low resolution vesa modes; allow explicit 24bpp vesa modes; allow high definition vesa modes; allow unusual vesa modes; allow 32bpp vesa modes; allow 24bpp vesa modes; allow 16bpp vesa modes; allow 15bpp vesa modes; allow 8bpp vesa modes; allow 4bpp vesa modes; allow 4bpp packed vesa modes; allow tty vesa modes; double-buffered line compare; ignore vblank wraparound; ignore extended memory bit; enable vga resize delay; resize only on vga active display width increase; vga palette update on full load; ignore odd-even mode in non-cga modes; ignore sequencer blanking +# +vmemsize = -1 +vmemsizekb = 0 +high intensity blinking = true +memory io optimization 1 = true +scanline render on demand = auto + +[vsync] +# vsyncmode: Synchronize vsync timing to the host display. Requires calibration within DOSBox-X. +# Possible values: off, on, force, host. +# vsyncrate: Vsync rate used if vsync is enabled. Ignored if vsyncmode is set to host (win32). +# Possible values:. +vsyncmode = off +vsyncrate = 75 + +[cpu] +# core: CPU Core used in emulation. auto will switch to dynamic if available and appropriate. +# For the dynamic core, both dynamic_x86 and dynamic_rec are supported (dynamic_x86 is preferred). +# Windows 95 or other preemptive multitasking OSes will not work with the dynamic_rec core. +# Possible values: auto, dynamic, dynamic_x86, dynamic_nodhfpu, dynamic_rec, normal, full, simple. +# fpu: Enable FPU emulation +# Possible values: true, false, 1, 0, auto, 8087, 287, 387. +# rdtsc rate: If nonzero, the Pentium RDTSC counter will tick at this rate per millisecond instead of by the cycle count +# segment limits: Enforce checks for segment limits on 80286 and higher CPU types. +# cputype: CPU Type used in emulation. "auto" emulates a 486 which tolerates Pentium instructions. +# "experimental" enables newer instructions not normally found in the CPU types emulated by DOSBox-X, such as FISTTP. +# Possible values: auto, 8086, 8086_prefetch, 80186, 80186_prefetch, 286, 286_prefetch, 386, 386_prefetch, 486old, 486old_prefetch, 486, 486_prefetch, pentium, pentium_mmx, ppro_slow, pentium_ii, pentium_iii, experimental. +# cycles: Number of instructions DOSBox-X tries to emulate each millisecond. +# Setting this value too high results in sound dropouts and lags. +# Cycles can be set in 3 ways: +# 'auto' tries to guess what a game needs. +# It usually works, but can fail for certain games. +# 'fixed #number' will set a fixed number of cycles. This is what you usually +# need if 'auto' fails (Example: fixed 4000). +# 'max' will allocate as much cycles as your computer is able to +# handle. Recommended if better performance is desired. +# Possible values: auto, fixed, max. +# cycleup: Amount of cycles to decrease/increase with the mapped keyboard shortcut. +# cycledown: Setting it lower than 100 will be a percentage. +# turbo: Enables Turbo (Fast Forward) mode to speed up operations. +# apmbios: Emulate Advanced Power Management (APM) BIOS calls. +# integration device: Enable DOSBox-X's integration I/O device, a way for additional software to talk to DOSBox-X. It is currently experimental. +# This can for example be used to return DOSBox-X's current status and by the guest OS to match the mouse pointer position. +# isapnpbios: Emulate ISA Plug & Play BIOS. Enable if using DOSBox-X to run a PnP aware DOS program or if booting Windows 9x. +# Do not disable if Windows 9x is configured around PnP devices, you will likely confuse it. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> cpuid string; processor serial number; double fault; clear trap flag on unhandled int 1; reset on triple fault; always report double fault; always report triple fault; mask stack pointer for enter leave instructions; allow lmsw to exit protected mode; report fdiv bug; enable msr; enable pse; enable cmpxchg8b; enable syscall; ignore undefined msr; interruptible rep string op; dynamic core cache block size; cycle emulation percentage adjust; stop turbo on key; stop turbo after second; use dynamic core with paging on; ignore opcode 63; apmbios pnp; apm power button event; apmbios version; apmbios allow realmode; apmbios allow 16-bit protected mode; apmbios allow 32-bit protected mode; integration device pnp; isapnpport; realbig16 +# +core = auto +fpu = true +rdtsc rate = 0 +segment limits = true +cputype = auto +cycles = auto +cycleup = 10 +cycledown = 20 +turbo = false +apmbios = true +integration device = false +isapnpbios = true + +[keyboard] +# aux: Enable emulation of the 8042 auxiliary port. PS/2 mouse emulation requires this to be enabled. +# You should enable this if you will be running Windows ME or any other OS that does not use the BIOS to receive mouse events. +# allow output port reset: If set (default), allow the application to reset the CPU through the keyboard controller. +# This option is required to allow Windows ME to reboot properly, whereas Windows 9x and earlier +# will reboot without this option using INT 19h +# controllertype: Type of keyboard controller (and keyboard) attached. +# auto Automatically pick according to machine type +# at AT (PS/2) type keyboard +# xt IBM PC/XT type keyboard +# pcjr IBM PCjr type keyboard (only if machine=pcjr) +# pc98 PC-98 keyboard emulation (only if machine=pc98) +# Possible values: auto, at, xt, pcjr, pc98. +# auxdevice: Type of PS/2 mouse attached to the AUX port +# Possible values: none, 2button, 3button, intellimouse, intellimouse45. +aux = true +allow output port reset = true +controllertype = auto +auxdevice = intellimouse + +[ttf] +# font: Specifies a TrueType font to use for the TTF output. If not specified, the built-in TrueType font will be used. +# Either a font name or full font path can be specified. If file ends with the .TTF extension then the extension can be omitted. +# For a font name or relative path, directories such as the working directory and default system font directory will be searched. +# For example, setting it to "consola" or "consola.ttf" will use Consola font (included in Windows); similar for other TTF fonts. +# Additionally, OTF fonts (e.g. OratorStd.otf), .FON fonts (e.g. vgasys.fon), and .TTC fonts (e.g. msgothic.ttc) are also supported. +# To display Chinese/Japanese/Korean text in these code pages, a font with CJK characters is needed (e.g. GNU Unifont or Sarasa Gothic). +# fontbold: You can optionally specify a bold TrueType font for use with the TTF output that will render the bold text style. +# It requires a word processor be set with the wp option, and this actual bold font will be used for the bold style. +# For example, setting it to "consolab" or "consolab.ttf" will use the Consolab font; similar for other TTF fonts. +# fontital: You can optionally specify an italic TrueType font for use with the TTF output that will render the italic text style. +# It requires a word processor be set with the wp option, and this actual italic font will be used for the italic style. +# For example, setting it to "consolai" or "consolai.ttf" will use the Consolai font; similar for other TTF fonts. +# fontboit: You can optionally specify a bold italic TrueType font for use with the TTF output that will render the bold italic text style. +# It requires a word processor be set with the wp option, and this actual bold-italic font will be used for the bold-italic style. +# For example, setting it to "consolaz" or "consolaz.ttf" will use the Consolaz font; similar for other TTF fonts. +# colors: Specifies a color scheme to use for the TTF output by supply all 16 color values in RGB: (r,g,b) or hexadecimal as in HTML: #RRGGBB +# The original DOS colors (0-15): #000000 #0000aa #00aa00 #00aaaa #aa0000 #aa00aa #aa5500 #aaaaaa #555555 #5555ff #55ff55 #55ffff #ff5555 #ff55ff #ffff55 #ffffff +# gray scaled color scheme: (0,0,0) #0e0e0e (75,75,75) (89,89,89) (38,38,38) (52,52,52) #717171 #c0c0c0 #808080 (28,28,28) (150,150,150) (178,178,178) (76,76,76) (104,104,104) (226,226,226) (255,255,255) +# An optional leading "+" sign allows the preset color scheme to be used when switching from another output. +# outputswitch: Specifies the output that DOSBox-X should switch to from the TTF output when a graphical mode is requested, or auto for automatic selection. +# Possible values: auto, surface, opengl, openglnb, openglhq, openglpp, direct3d. +# winperc: Specifies the window percentage for the TTF output (100 = full screen). Ignored if the ptsize setting is specified. +# ptsize: Specifies the font point size for the TTF output. If specified (minimum: 9), it will override the winperc setting. +# lins: Specifies the number of rows on the screen for the TTF output (0 = default). +# cols: Specifies the number of columns on the screen for the TTF output (0 = default). +# righttoleft: If set, DOSBox-X will display text from right to left instead of left to right on the screen for the TTF output. +# This is especially useful for languages which use right-to-left scripts (such as Arabic and Hebrew). +# wp: You can specify a word processor for the TTF output and optionally also a version number for the word processor. +# Supported word processors are WP=WordPerfect, WS=WordStar, XY=XyWrite, FE=FastEdit, and an optional version number. +# For example, WP6 will set the word processor as WordPerfect 6, and XY4 will set the word processor as XyWrite 4. +# Word processor-specific features like on-screen text styles and 512-character font will be enabled based on this. +# bold: If set, DOSBox-X will display bold text in visually (requires a word processor be set) for the TTF output. +# This is done either with the actual bold font specified by the fontbold option, or by making it bold automatically. +# italic: If set, DOSBox-X will display italicized text visually (requires a word processor be set) for the TTF output. +# This is done either with the actual italic font specified by the fontital option, or by slanting the characters automatically. +# underline: If set, DOSBox-X will display underlined text visually (requires a word processor be set) for the TTF output. +# strikeout: If set, DOSBox-X will display strikeout text visually (requires a word processor be set) for the TTF output. +# printfont: If set, DOSBox-X will force to use the current TrueType font (set via font option) for printing in addition to displaying. +# autodbcs: If set, DOSBox-X enables Chinese/Japanese/Korean DBCS (double-byte) characters when these code pages are active by default. +# Only applicable when using a DBCS code page (932: Japanese, 936: Simplified Chinese; 949: Korean; 950: Traditional Chinese) +# This applies to both the display and printing of these characters (see the [printer] section for details of the latter). +# blinkc: If set to true, the cursor blinks for the TTF output; setting it to false will turn the blinking off. +# You can also change the blinking rate by setting an integer between 1 (fastest) and 7 (slowest), or 0 for no cursor. +# gbk: Enables the GBK extension (in addition to the standard GB2312 charset) for the Simplified Chinese TTF output or DOS/V emulation. +# chinasea: Enables the ChinaSea and Big5-2003 extension (in addition to the standard Big5-1984 charset) for the Traditional Chinese TTF output. +# A TTF/OTF font containing such characters (such as the included SarasaGothicFixed TTF font) is needed to correctly render ChinaSea characters. +# dosvfunc: If set, enables FEP control to function for Japanese DOS/V applications, and changes the blinking of character attributes to high brightness. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> wpbg; wpfg; char512; autoboxdraw; halfwidthkana; uao +# +font = +fontbold = +fontital = +fontboit = +colors = +outputswitch = auto +winperc = 60 +ptsize = 0 +lins = 0 +cols = 0 +righttoleft = false +wp = +bold = true +italic = true +underline = true +strikeout = false +printfont = true +autodbcs = true +blinkc = true +gbk = false +chinasea = false +dosvfunc = false + +[voodoo] +# voodoo_card: Enable support for the 3dfx Voodoo card. +# Possible values: false, software, opengl, auto. +# voodoo_maxmem: Specify whether to enable maximum memory size for the Voodoo card. +# If set (on by default), the memory size will be 12MB (4MB front buffer + 2x4MB texture units) +# Otherwise, the memory size will be the standard 4MB (2MB front buffer + 1x2MB texture unit) +# glide: Enable Glide emulation (Glide API passthrough to the host). +# Requires a Glide wrapper - glide2x.dll (Windows), libglide2x.so (Linux), or libglide2x.dylib (macOS). +# lfb: Enable LFB access for Glide. OpenGlide does not support locking aux buffer, please use _noaux modes. +# Possible values: full, full_noaux, read, read_noaux, write, write_noaux, none. +# splash: Show 3dfx splash screen for Glide emulation (Windows; requires 3dfxSpl2.dll). +voodoo_card = auto +voodoo_maxmem = true +glide = false +lfb = full_noaux +splash = true + +[mixer] +# nosound: Enable silent mode, sound is still emulated though. +# sample accurate: Enable sample accurate mixing, at the expense of some emulation performance. Enable this option for DOS games and demos +# that require such accuracy for correct Tandy/OPL output including digitized speech. This option can also help eliminate +# minor errors in Gravis Ultrasound emulation that result in random echo/attenuation effects. +# swapstereo: Swaps the left and right stereo channels. +# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. +# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. +# Possible values: 1024, 2048, 4096, 8192, 512, 256. +# prebuffer: How many milliseconds of data to keep on top of the blocksize. +nosound = false +sample accurate = false +swapstereo = false +rate = 48000 +blocksize = 1024 +prebuffer = 25 + +[midi] +# mpu401: Type of MPU-401 to emulate. +# Possible values: intelligent, uart, none. +# mpubase: The IO address of the MPU-401. +# Set to 0 to use a default I/O address. +# 300h to 330h are for use with IBM PC mode. +# C0D0h to F8D0h (in steps of 800h) are for use with NEC PC-98 mode (MPU98). +# 80D2h through 80DEh are for use with NEC PC-98 Sound Blaster 16 MPU-401 emulation. +# If not assigned (0), 330h is the default for IBM PC and E0D0h is the default for PC-98. +# Possible values: 0, 300, 310, 320, 330, 332, 334, 336, 340, 360, c0d0, c8d0, d0d0, d8d0, e0d0, e8d0, f0d0, f8d0, 80d2, 80d4, 80d6, 80d8, 80da, 80dc, 80de. +# mididevice: Device that will receive the MIDI data from MPU-401. +# Possible values: default, win32, alsa, oss, coreaudio, coremidi, mt32, synth, fluidsynth, timidity, none. +# midiconfig: Special configuration options for the device driver. This is usually the id or part of the name of the device you want to use +# (find the id/name with mixer/listmidi). +# Or in the case of coreaudio or synth, you can specify a soundfont here. +# When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues. +# In that case, add 'delaysysex', for example: midiconfig=2 delaysysex +# See the README/Manual for more details. +# samplerate: Sample rate for MIDI synthesizer, if applicable. +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# mpuirq: MPU-401 IRQ. -1 to automatically choose. +# mt32.romdir: Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work. +# Accepted file names are as follows: +# MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file. +# MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file. +# mt32.model: Model of the MT-32 synthesizer to use. +# Possible values: cm32l, mt32, auto. +# fluid.driver: Driver to use with Fluidsynth, not needed under Windows. Available drivers depend on what Fluidsynth was compiled with. +# Possible values: pulseaudio, alsa, oss, coreaudio, dsound, portaudio, sndman, jack, file, default. +# fluid.soundfont: Soundfont (.SF2 or .SF3) to use with Fluidsynth. One must be specified (e.g. GeneralUser_GS.sf2). +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> roland gs sysex; mt32.reverse.stereo; mt32.verbose; mt32.thread; mt32.chunk; mt32.prebuffer; mt32.partials; mt32.dac; mt32.analog; mt32.output.gain; mt32.reverb.mode; mt32.reverb.output.gain; mt32.reverb.time; mt32.reverb.level; mt32.rate; mt32.src.quality; mt32.niceampramp; mt32.engage.channel1; fluid.samplerate; fluid.gain; fluid.polyphony; fluid.cores; fluid.periods; fluid.periodsize; fluid.reverb; fluid.chorus; fluid.reverb.roomsize; fluid.reverb.damping; fluid.reverb.width; fluid.reverb.level; fluid.chorus.number; fluid.chorus.level; fluid.chorus.speed; fluid.chorus.depth; fluid.chorus.type +# +mpu401 = intelligent +mpubase = 0 +mididevice = default +midiconfig = +samplerate = 48000 +mpuirq = -1 +mt32.romdir = +mt32.model = auto +fluid.driver = default +fluid.soundfont = + +[sblaster] +# sbtype: Type of Sound Blaster to emulate. 'gb' is Game Blaster. +# Possible values: sb1, sb1.0, sb1.5, sb2, sb2.0, sb2.01, sbpro1, sbpro2, sb16, sb16vibra, gb, ess688, ess1688, reveal_sc400, none. +# sbbase: The IO address of the Sound Blaster. +# 220h to 2E0h are for use with IBM PC Sound Blaster emulation. +# D2h to DEh are for use with NEC PC-98 Sound Blaster 16 emulation. +# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, d2, d4, d6, d8, da, dc, de. +# irq: The IRQ number of the Sound Blaster (usually 5 or 7, depending on the sound card type and the game). +# Set to 0 for the default setting of the sound card, or set to -1 to start DOSBox-X with the IRQ unassigned. +# Possible values: 7, 5, 3, 9, 10, 11, 12, 0, -1. +# listen to recording source: When the guest records audio from the Sound Blaster card, send the input source to the speakers as well so it can be heard. +# recording source: Audio source to use when guest is recording audio. At this time only generated audio sources are available. +# Possible values: silence, hiss, 1khz tone. +# dma: The DMA number of the Sound Blaster. Set to -1 to start DOSBox-X with the DMA unassigned. +# Possible values: 1, 5, 0, 3, 6, 7, -1. +# hdma: The High DMA number of the Sound Blaster. Set to -1 to start DOSBox-X with the High DMA unassigned. +# Possible values: 1, 5, 0, 3, 6, 7, -1. +# enable speaker: Start the DOS virtual machine with the Sound Blaster speaker enabled. +# Sound Blaster Pro and older cards have a speaker disable/enable command. +# Normally the card boots up with the speaker disabled. If a DOS game or demo +# attempts to play without enabling the speaker, set this option to true to +# compensate. This setting has no meaning if emulating a Sound Blaster 16 card. +# sbmixer: Allow the Sound Blaster mixer to modify the DOSBox-X mixer. +# oplmode: Type of OPL emulation. On 'auto' the mode is determined by the 'sbtype' setting. +# All OPL modes are AdLib-compatible. +# Possible values: auto, opl2, dualopl2, opl3, opl3gold, none, hardware, hardwaregb, esfm. +# oplemu: Provider for the OPL emulation. 'compat' might provide better quality. +# 'nuked' is the most accurate (but the most CPU-intensive). See oplrate as well. +# Possible values: default, compat, fast, nuked, mame, opl2board, opl3duoboard, retrowave_opl3, esfmu. +# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# oplport: Serial port of the OPL2 Audio Board when oplemu=opl2board, opl2mode will become 'opl2' automatically. +# retrowave_bus: Bus of the Retrowave series board (serial/spi). SPI is only supported on Linux. +# retrowave_port: Serial port of the Retrowave series board. +# hardwarebase: base address of the real hardware Sound Blaster: +# 210,220,230,240,250,260,280 +# goldplay: Enable goldplay emulation. +# blaster environment variable: Whether or not to set the BLASTER environment variable automatically at startup +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> mindma; irq hack; dsp command aliases; pic unmask irq; enable asp; disable filtering; dsp write buffer status must return 0x7f or 0xff; pre-set sbpro stereo; cms; adlib force timer overflow on detect; retrowave_spi_cs; force dsp auto-init; force goldplay; goldplay stereo; dsp require interrupt acknowledge; dsp write busy delay; sample rate limits; instant direct dac; stereo control with sbpro only; dsp busy cycle rate; dsp busy cycle always; dsp busy cycle duty; io port aliasing +# +sbtype = sb16 +sbbase = 220 +irq = 7 +listen to recording source = false +recording source = silence +dma = 1 +hdma = 5 +enable speaker = false +sbmixer = true +oplmode = auto +oplemu = default +oplrate = 48000 +oplport = +retrowave_bus = serial +retrowave_port = +hardwarebase = 220 +goldplay = true +blaster environment variable = true + +[gus] +# gus: Enable the Gravis Ultrasound emulation. +# global register read alias: If true, all GUS global registers have a read alias at N and N+0x80. +# If false, only the voice registers 0x0-0xF have a read alias at 0x80-0x8F as officially documented. +# If auto, automatically choose based on other settings such as GUS type. +# This setting may be needed for DOS demoscene entries that assume aliasing behavior such as Out of Control by Contract. +# Possible values: true, false, 1, 0, auto. +# gusrate: Sample rate of Ultrasound emulation. +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# gusmemsize: Amount of RAM on the Gravis Ultrasound in KB. Set to -1 for default. +# gus master volume: Master Gravis Ultrasound GF1 volume, in decibels. Reducing the master volume can help with games or demoscene productions where the music is too loud and clipping. +# gusbase: The IO base address of the Gravis Ultrasound. +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300, 210, 230, 250. +# gusirq: The IRQ number of the Gravis Ultrasound. +# Possible values: 5, 3, 7, 9, 10, 11, 12. +# gusdma: The DMA channel of the Gravis Ultrasound. +# Possible values: 3, 0, 1, 5, 6, 7. +# gustype: Type of Gravis Ultrasound to emulate. +# classic Original Gravis Ultrasound chipset +# classic37 Original Gravis Ultrasound with ICS Mixer (rev 3.7) +# max Gravis Ultrasound MAX emulation (with CS4231 codec) +# interwave Gravis Ultrasound Plug & Play (interwave) +# Possible values: classic, classic37, max, interwave. +# ultradir: Path to Ultrasound directory. In this directory +# there should be a MIDI directory that contains +# the patch files for GUS playback. Patch sets used +# with Timidity should work fine. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> warn on out of bounds dram access; autoamp; unmask dma; ignore channel count while active; pic unmask irq; startup initialized; dma enable on dma control polling; clear dma tc irq if excess polling; force master irq enable; gus panning table; gus fixed render rate; irq hack +# +gus = false +global register read alias = auto +gusrate = 48000 +gusmemsize = -1 +gus master volume = 0.00 +gusbase = 240 +gusirq = 5 +gusdma = 3 +gustype = classic +ultradir = C:\ULTRASND + +[innova] +# innova: Enable the Innovation SSI-2001 emulation. +# samplerate: Sample rate of Innovation SSI-2001 emulation +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# sidbase: SID base port (typically 280h). +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. +# quality: Set SID emulation quality level (0 to 3). +# Possible values: 0, 1, 2, 3. +innova = false +samplerate = 22050 +sidbase = 280 +quality = 0 + +[imfc] +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> imfc; imfc_base; imfc_irq; imfc_filter +# + +[speaker] +# pcspeaker: Enable PC-Speaker emulation. +# pcrate: Sample rate of the PC-Speaker sound generation. +# Possible values: 65536, 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. +# Possible values: auto, on, off. +# tandyrate: Sample rate of the Tandy 3-Voice generation. +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). +# ps1audio: Enable PS1 audio emulation. +# Possible values: on, off. +# ps1audiorate: Sample rate of the PS1 audio emulation. +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> pcspeaker clock gate enable at startup; initial frequency +# +pcspeaker = true +pcrate = 65536 +tandy = auto +tandyrate = 48000 +disney = false +ps1audio = off +ps1audiorate = 22050 + +[joystick] +# joysticktype: Type of joystick to emulate: auto (default), +# none (disables joystick emulation), +# 2axis (supports two joysticks), +# 4axis (supports one joystick, first joystick used), +# 4axis_2 (supports one joystick, second joystick used), +# fcs (Thrustmaster), ch (CH Flightstick). +# auto chooses emulation depending on real joystick(s). +# (Remember to reset DOSBox-X's mapperfile if you saved it earlier) +# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. +# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). +# autofire: continuously fires as long as you keep the button pressed. +# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. +# buttonwrap: enable button wrapping at the number of emulated buttons. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> joy1deadzone1; joy1deadzone2; joy2deadzone1; joy1response1; joy1response2; joy2response1; joy1axis0; joy1axis1; joy1axis2; joy1axis3; joy1axis4; joy1axis5; joy1axis6; joy1axis7; joy2axis0; joy2axis1; joy2axis2; joy2axis3; joy2axis4; joy2axis5; joy2axis6; joy2axis7 +# +joysticktype = auto +timed = true +autofire = false +swap34 = false +buttonwrap = false + +[mapper] +# joy1deadzone0-: deadzone for joystick 1 axis 0- +# joy1deadzone0+: deadzone for joystick 1 axis 0+ +# joy1deadzone1-: deadzone for joystick 1 axis 1- +# joy1deadzone1+: deadzone for joystick 1 axis 1+ +# joy1deadzone2-: deadzone for joystick 1 axis 2- +# joy1deadzone2+: deadzone for joystick 1 axis 2+ +# joy1deadzone3-: deadzone for joystick 1 axis 3- +# joy1deadzone3+: deadzone for joystick 1 axis 3+ +# joy1deadzone4-: deadzone for joystick 1 axis 4- +# joy1deadzone4+: deadzone for joystick 1 axis 4+ +# joy1deadzone5-: deadzone for joystick 1 axis 5- +# joy1deadzone5+: deadzone for joystick 1 axis 5+ +# joy1deadzone6-: deadzone for joystick 1 axis 6- +# joy1deadzone6+: deadzone for joystick 1 axis 6+ +# joy1deadzone7-: deadzone for joystick 1 axis 7- +# joy1deadzone7+: deadzone for joystick 1 axis 7+ +# joy2deadzone0-: deadzone for joystick 2 axis 0- +# joy2deadzone0+: deadzone for joystick 2 axis 0+ +# joy2deadzone1-: deadzone for joystick 2 axis 1- +# joy2deadzone1+: deadzone for joystick 2 axis 1+ +# joy2deadzone2-: deadzone for joystick 2 axis 2- +# joy2deadzone2+: deadzone for joystick 2 axis 2+ +# joy2deadzone3-: deadzone for joystick 2 axis 3- +# joy2deadzone3+: deadzone for joystick 2 axis 3+ +# joy2deadzone4-: deadzone for joystick 2 axis 4- +# joy2deadzone4+: deadzone for joystick 2 axis 4+ +# joy2deadzone5-: deadzone for joystick 2 axis 5- +# joy2deadzone5+: deadzone for joystick 2 axis 5+ +# joy2deadzone6-: deadzone for joystick 2 axis 6- +# joy2deadzone6+: deadzone for joystick 2 axis 6+ +# joy2deadzone7-: deadzone for joystick 2 axis 7- +# joy2deadzone7+: deadzone for joystick 2 axis 7+ +joy1deadzone0- = 0.60 +joy1deadzone0+ = 0.60 +joy1deadzone1- = 0.60 +joy1deadzone1+ = 0.60 +joy1deadzone2- = 0.60 +joy1deadzone2+ = 0.60 +joy1deadzone3- = 0.60 +joy1deadzone3+ = 0.60 +joy1deadzone4- = 0.60 +joy1deadzone4+ = 0.60 +joy1deadzone5- = 0.60 +joy1deadzone5+ = 0.60 +joy1deadzone6- = 0.60 +joy1deadzone6+ = 0.60 +joy1deadzone7- = 0.60 +joy1deadzone7+ = 0.60 +joy2deadzone0- = 0.60 +joy2deadzone0+ = 0.60 +joy2deadzone1- = 0.60 +joy2deadzone1+ = 0.60 +joy2deadzone2- = 0.60 +joy2deadzone2+ = 0.60 +joy2deadzone3- = 0.60 +joy2deadzone3+ = 0.60 +joy2deadzone4- = 0.60 +joy2deadzone4+ = 0.60 +joy2deadzone5- = 0.60 +joy2deadzone5+ = 0.60 +joy2deadzone6- = 0.60 +joy2deadzone6+ = 0.60 +joy2deadzone7- = 0.60 +joy2deadzone7+ = 0.60 + +[serial] +# serial1: serial1-9 -- set type of device connected to the serial (COM) port. +# Can be disabled, dummy, file, modem, nullmodem, directserial. +# Additional parameters must be in the same line in the form of +# parameter:value. Parameter for all types is irq (optional). +# for file: specify an output file +# Additional parameters: +# timeout: = how long to wait before closing the file on inactivity (default:0), +# squote to use single quotes instead of double quotes for quoted program commands. +# shellhide to hide the command window when opening programs on the Windows platform. +# openwith:: start a program to open the output file. +# openerror:: start a program to open the output file if an error had occurred. +# multiplier:: Actual baud rate is the programmed rate times X to allow rates higher than 115200. +# Example: serial1=file file:output1.txt timeout:1000 openwith:notepad +# for directserial: realport (required), rxdelay (optional). +# (realport:COM1 realport:ttyS0). +# for modem: listenport (optional). +# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, +# transparent, port, inhsocket, sock, nonlocal (all optional). +# connections are limited to localhost unless you specify nonlocal:1 +# "sock" parameter specifies the protocol to be used by both sides +# of the connection. 0 for TCP and 1 for ENet reliable UDP. +# Example: serial1=modem listenport:5000 sock:1 +# Note: COM1-4 are standard COM ports in DOS, whereas COM5-9 are extended COM ports. +# You can optionally specify base addresses and IRQs for them with base: and irq: options. +# Serial port settings can also be changed via the built-in SERIAL command. +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial2: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial3: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial4: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial5: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial6: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial7: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial8: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial9: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# phonebookfile: File used to map fake phone numbers to addresses. +serial1 = dummy +serial2 = dummy +serial3 = disabled +serial4 = disabled +serial5 = disabled +serial6 = disabled +serial7 = disabled +serial8 = disabled +serial9 = disabled +phonebookfile = phonebook-dosbox-x.txt + +[parallel] +# parallel1: parallel1-9 -- set type of device connected to the parallel (LPT) port. +# Can be: +# reallpt (direct parallel port passthrough), +# file (records data to a file or passes it to a device), +# printer (virtual dot-matrix printer, see [printer] section) +# disney (attach Disney Sound Source emulation to this port) +# Additional parameters must be in the same line in the form of +# parameter:value. +# for reallpt: +# Windows and DOS: +# realbase (the base address of your real parallel port). +# Default: 378 +# ecpbase (address of the ECP Extended Control register, optional). +# BSD: same as Windows (requires root access / setuid root). +# Linux: same as Windows (requires root access / setuid root) or: +# realport (the parallel port device e.g. /dev/parport0). +# for file: +# dev: (i.e. dev:lpt1) to forward data to a device, +# or append: appends data to the specified file. +# Without the above parameters data is written to files in the capture dir. +# Additional parameters: +# timeout: = how long to wait before closing the file on inactivity (default:0 or 500), +# squote to use single quotes instead of double quotes for quoted program commands. +# shellhide to hide the command window when opening programs on the Windows platform. +# addFF to add a formfeed when closing, addLF to add a linefeed if the app doesn't. +# cp: to perform codepage translation, i.e. cp:437 +# openps:: start a program to open the file if the print output is detected to be PostScript. +# openpcl:: start a program to open the file if the print output is detected to be PCL. +# openwith:: start a program to open the file in all other conditions. +# openerror:: start a program to open the file if an error had occurred. +# Example: parallel1=file file:output1.prn timeout:1000 openpcl:pcl6 openps:gswin32c openwith:notepad +# for printer: +# printer still has its own configuration section above. +# Note: LPT1-3 are standard LPT ports in DOS, whereas LPT4-9 are extended LPT ports. +# You can optionally specify base addresses and IRQs for them with base: and irq: options. +# Parallel port settings can also be changed via the built-in PARALLEL command. +# parallel2: see parallel1 +# parallel3: see parallel1 +# parallel4: see parallel1 +# parallel5: see parallel1 +# parallel6: see parallel1 +# parallel7: see parallel1 +# parallel8: see parallel1 +# parallel9: see parallel1 +# dongle: Enable dongle +parallel1 = printer +parallel2 = disabled +parallel3 = disabled +parallel4 = disabled +parallel5 = disabled +parallel6 = disabled +parallel7 = disabled +parallel8 = disabled +parallel9 = disabled +dongle = false + +[printer] +# printer: Enable printer emulation. +# dpi: Resolution of printer (default 360). +# width: Width of paper in 1/10 inch (default 85 = 8.5''). +# height: Height of paper in 1/10 inch (default 110 = 11.0''). +# printoutput: Output method for finished pages: +# png : Creates PNG images (default) +# ps : Creates PostScript +# bmp : Creates BMP images (very huge files, not recommended) +# printer : Send to an actual printer in Windows (specify a printer, or Print dialog will appear) +# multipage: Adds all pages to one PostScript file or printer job until CTRL-F2 is pressed. +# device: Specify the Windows printer device to use. You can see the list of devices from the Help +# menu ('List printer devices') or the Status Window. Then make your choice and put either +# the printer device number (e.g. 2) or your printer name (e.g. Microsoft Print to PDF). +# Leaving it empty will show the Windows Print dialog (or '-' for showing once). +# docpath: The path (directory) where the output files are stored. +# fontpath: The path (directory) where the printer fonts (courier.ttf, ocra.ttf, roman.ttf, sansserif.ttf, script.ttf) are located. +# openwith: Start the specified program to open the output file. +# openerror: Start the specified program to open the output file if an error had occurred. +# printdbcs: Allows DOSBox-X to print Chinese/Japanese/Korean DBCS (double-byte) characters when these code pages are active. +# If set to auto (default), this is enabled only for the TrueType font (TTF) output with the DBCS support enabled. +# Only applicable when using a DBCS code page (932: Japanese, 936: Simplified Chinese; 949: Korean; 950: Traditional Chinese) +# Possible values: true, false, 1, 0, auto. +# shellhide: If set, the command window will be hidden for openwith/openerror options on the Windows platform. +# timeout: (in milliseconds) if nonzero: the time the page will be ejected automatically after when no more data arrives at the printer. +printer = true +dpi = 360 +width = 85 +height = 110 +printoutput = png +multipage = false +device = - +docpath = . +fontpath = FONTS +openwith = +openerror = +printdbcs = auto +shellhide = false +timeout = 0 + +[dos] +# xms: Enable XMS support. +# xms handles: Number of XMS handles available for the DOS environment, or 0 to use a reasonable default +# shell configuration as commands: Allow entering dosbox-x.conf configuration parameters as shell commands to get and set settings. +# This is disabled by default to avoid conflicts between commands and executables. +# It is recommended to get and set dosbox-x.conf settings using the CONFIG command instead. +# Compatibility with DOSBox SVN can be improved by enabling this option. +# hma: Report through XMS that HMA exists (not necessarily available) +# hard drive data rate limit: Slow down (limit) hard disk throughput. This setting controls the limit in bytes/second. +# Set to 0 to disable the limit, or -1 (default) to use a reasonable limit. +# The disk I/O performance as in DOSBox SVN can be achieved by setting this to 0. +# floppy drive data rate limit: Slow down (limit) floppy disk throughput. This setting controls the limit in bytes/second. +# Set to 0 to disable the limit, or -1 (default) to use a reasonable limit. +# The disk I/O performance as in DOSBox SVN can be achieved by setting this to 0. +# ansi.sys: If set (by default), ANSI.SYS emulation is on. If clear, ANSI.SYS is not emulated and will not appear to be installed. +# NOTE: This option has no effect in PC-98 mode where MS-DOS systems integrate ANSI.SYS into the DOS kernel. +# log console: If set, log DOS CON output to the log file. Setting to "quiet" will log DOS CON output only (no debugging output). +# Possible values: true, false, 1, 0, quiet. +# share: Reports SHARE.EXE as resident and provides functions such as file-locking and record-locking, although not all SHARE functions are emulated. +# file access tries: If a positive integer is set, DOSBox-X will try to read/write/lock files directly on mounted local drives for the specified number of times without caching before failing on Windows systems. +# For networked database applications (e.g. dBase, FoxPro, etc), it is strongly recommended to set this to e.g. 3 for correct operations. +# network redirector: Report DOS network redirector as resident. This will allow the host name to be returned unless the secure mode is enabled. +# You can also directly access UNC network paths in the form \\MACHINE\SHARE even if they are not mounted as drives on Windows systems. +# Set either "ipx=true" in [ipx] section or "ne2000=true" in [ne2000] section for a full network redirector environment. +# minimum mcb free: Minimum free segment value to leave free. At startup, the DOS kernel will allocate memory +# up to this point. This can be used to deal with EXEPACK issues or DOS programs that cannot +# be loaded too low in memory. If you want more free conventional memory to be reported, +# you can for example set its value to 1. +# ems: Enable EMS support. The default (=true) provides the best +# compatibility but certain applications may run better with +# other choices, or require EMS support to be disabled (=false) +# to work at all. +# Possible values: true, emsboard, emm386, false, 1, 0. +# umb: Enable UMB support. +# quick reboot: If set, the DOS restart call will reboot the emulated DOS (integrated DOS or guest DOS) instead of the virtual machine. +# +# ver: Set DOS version. Specify as major.minor format. A single number is treated as the major version (compatible with LFN support). Common settings are: +# auto (or unset) Pick DOS kernel version 5.0 (DOSBox default) +# 3.3 MS-DOS 3.3 emulation (not tested!) +# 5.0 MS-DOS 5.0 emulation (recommended for DOS gaming) +# 6.22 MS-DOS 6.22 emulation +# 7.0 MS-DOS 7.0 (or Windows 95 pure DOS mode) emulation +# 7.1 MS-DOS 7.1 (or Windows 98 pure DOS mode) emulation +# Long filename (LFN) support will be enabled with a reported DOS version of 7.0 or higher with "lfn=auto" (default). +# Similarly, FAT32 disk images will be supported with a reported DOS version of 7.1 or higher. +# +# lfn: Enable long filename support. If set to auto (default), LFN support is enabled if the reported DOS version is at least 7.0. +# If set to autostart, the built-in VER command won't activate/deactivate LFN support according to the reported DOS version. +# Possible values: true, false, 1, 0, auto, autostart. +# fat32setversion: Whether DOSBox-X should automatically set the reported DOS version to 7.0/7.10 when it is less than 7.0/7.10 and mounting LBA/FAT32 disk images is requested. +# If set to "ask", a popup message will show up to ask whether DOSBox-X should automatically change the reported DOS version in order to mount the disk image. +# Possible values: ask, auto, manual. +# shellhigh: Load the DOSBox-X command shell into the upper memory when the UMB is available. +# If set to auto (default), it is enabled if the reported DOS version is at least 7.0. +# Possible values: true, false, 1, 0, auto. +# automount: Enable automatic drive mounting in Windows. +# automountall: Automatically mount all available Windows drives at start. +# Possible values: true, false, 1, 0, quiet. +# mountwarning: If set, a warning message will be displayed while trying to auto-mount your Windows host drives. +# autofixwarning: If set to true or both, DOSBox-X shows messages while trying to automatically fix the "Packed file is corrupt" error. +# If set to false or none, DOSBox-X will not show such messages on the screen when the error occurred. +# If set to "a20fix" or "loadfix", DOSBox-X will show the message for the a20fix or the loadfix only. +# Possible values: true, false, 1, 0, both, a20fix, loadfix, none. +# startcmd: Enable START command to start programs to run on the host system. On Windows host programs or commands may also be launched directly. +# starttranspath: Specify whether DOSBox-X should automatically translate all paths in the command-line to host system paths when starting programs to run on the host system. +# startwait: Specify whether DOSBox-X should wait for the host system applications after they are started. +# startquiet: If set, before launching host system applications to run on the host DOSBox-X will not show messages like "Now run it as a Windows application". +# startnopause: If set, DOSBox-X will not pause after host command execution is completed. +# vmware: Enable VMware interface emulation including guest mouse integration (when used along with e.g. VMware mouse driver for Windows 3.x). +# int33: Enable INT 33H for mouse support. +# mouse report rate: Mouse reporting rate, or 0 for auto. This affects how often mouse events are reported to the guest through the mouse interrupt. +# Some games including CyClone need a lower reporting rate to function correctly. Auto mode allows the guest to change the report rate through the PS/2 mouse emulation. +# This option does not affect any DOS game that uses polling through INT 33h to detect mouse movement. +# keyboardlayout: Language code of the keyboard layout (or none). +# customcodepage: Set a custom code page for CHCP command and specify a SBCS code page file, following the standard SBCS code page format. +# Examples of SBCS code pages are available from the Unicode Consortium website: https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/ +# dbcs: Enable DBCS table and Chinese, Japanese, Korean support for the TrueType font (TTF) output. +# CAUTION: Some software will crash without the DBCS table, including the Open Watcom installer. +# dos clipboard device enable: If enabled, a DOS device will be added for bidirectional communications with the shared clipboard. +# Setting to "read" will only allow read access, and setting to "write" will only allow write access. +# Setting to "full" or "true" enables both; setting to "false" or "disabled" disables the access or device. +# The default device name is CLIP$, but can be changed with the "dos clipboard device name" setting below. +# dos clipboard device name: Set DOS device name (up to 8 characters) for bidirectional communications with the shared clipboard. +# If unset or invalid, the default name CLIP$ will be used (e.g. "TYPE CLIP$" shows the clipboard contents). +# It has no effect if "dos clipboard device enable" is disabled, and it is deactivated if the secure mode is enabled. +# dos clipboard api: If set, DOS APIs for communications with the Windows clipboard will be enabled for shared clipboard communications. +# Caution: Enabling this API may cause some programs to think they are running under Windows +# dos idle api: If set, DOSBox-X can lower the host system's CPU load when a supported guest program is idle. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> turn off a20 gate on load if loadfix needed; xms memmove causes flat real mode; xms init causes flat real mode; resized free memory block becomes allocated; badcommandhandler; mscdex device name; hma allow reservation; command shell flush keyboard buffer; special operation file prefix; drive z is remote; drive z convert fat; drive z expand path; drive z hide files; automount drive directories; hidenonrepresentable; hma minimum allocation; dos sda size; hma free space; cpm compatibility mode; minimum dos initial private segment; minimum mcb segment; enable dummy device mcb; maximum environment block size on exec; additional environment block size on exec; enable a20 on windows init; zero memory on xms memory allocation; vcpi; unmask timer on disk io; zero int 67h if no ems; zero unused int 68h; emm386 startup active; zero memory on ems memory allocation; ems system handle memory size; ems system handle on even megabyte; ems frame; umb start; umb end; kernel allocation in umb; keep umb on boot; keep private area on boot; private area in umb; private area write protect; autoa20fix; autoloadfix; startincon; int33 max x; int33 max y; int33 xy adjust; int33 mickey threshold; int33 hide host cursor if interrupt subroutine; int33 hide host cursor when polling; int33 disable cell granularity; int 13 disk change detect; int 13 extensions; biosps2; int15 wait force unmask irq; int15 mouse callback does not preserve registers; filenamechar; collating and uppercase; con device use int 16h to detect keyboard input; zero memory on int 21h memory allocation; pipe temporary device +# +xms = true +xms handles = 0 +shell configuration as commands = false +hma = true +hard drive data rate limit = -1 +floppy drive data rate limit = -1 +ansi.sys = true +log console = false +share = true +file access tries = 0 +network redirector = true +minimum mcb free = 0 +ems = true +umb = true +quick reboot = false +ver = 7.1 +lfn = auto +fat32setversion = ask +shellhigh = auto +automount = true +automountall = false +mountwarning = true +autofixwarning = false +startcmd = false +starttranspath = true +startwait = true +startquiet = false +startnopause = false +vmware = true +int33 = true +mouse report rate = 0 +keyboardlayout = auto +customcodepage = +dbcs = true +dos clipboard device enable = false +dos clipboard device name = CLIP$ +dos clipboard api = false +dos idle api = true + +[ipx] +# ipx: Enable ipx over UDP/IP emulation. +ipx = false + +[ne2000] +# ne2000: Enable NE2000 Ethernet emulation. Either pcap or slirp backend can be used, switchable via "backend" option. +# Settings for the pcap and slirp backends can be found in the [ethernet, pcap] and [ethernet, slirp] sections. +# Once properly set, load the NE2000 packet driver inside DOSBox-X with base address and interrupt specified below. +# nicbase: The base address of the NE2000 board. +# nicirq: The interrupt it uses. Note serial2 uses IRQ3 as default. +# macaddr: The MAC address the emulator will use for its network adapter. +# If you have multiple DOSBox-Xes running on the same network, +# this has to be changed for each. AC:DE:48 is an address range reserved for +# private use, so modify the last three number blocks, e.g. AC:DE:48:88:99:AB. +# Default setting is 'random' which randomly chooses a MAC address. +# backend: The backend (either pcap or slirp is supported) used for the NE2000 Ethernet emulation. +# If set to "auto", then "slirp" is selected when available, otherwise "pcap" is selected when available. +# NE2000 Ethernet emulation will be disabled if no backend is available (or the specified backend if unavailable). +# Possible values: pcap, slirp, nothing, auto, none. +ne2000 = false +nicbase = 300 +nicirq = 3 +macaddr = random +backend = auto + +[ethernet, pcap] +# realnic: Specifies which of your host network interfaces is used for pcap. +# Write 'list' here to see the list of devices from the Help +# menu ('List network interfaces') or from the Status Window. +# Then make your choice and put either the interface number +# (e.g. 2) or a part of your adapters name (e.g. VIA here). +# timeout: Specifies the read timeout for the device in milliseconds for the pcap backend, or the default value will be used. +realnic = list +timeout = default + +[ethernet, slirp] +# ipv4_network: The IPv4 network the guest and host services are on. +# ipv4_netmask: The netmask for the IPv4 network. +# ipv4_host: The address of the guest on the IPv4 network. +# ipv4_nameserver: The address of the nameserver service provided by the host on the IPv4 network. +# ipv4_dhcp_start: The start address used for DHCP by the host services on the IPv4 network. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> restricted; disable_host_loopback; mtu; mru; tcp_port_forwards; udp_port_forwards +# +ipv4_network = 10.0.2.0 +ipv4_netmask = 255.255.255.0 +ipv4_host = 10.0.2.2 +ipv4_nameserver = 10.0.2.3 +ipv4_dhcp_start = 10.0.2.15 + +[ide, primary] +# enable: Enable IDE interface +# pnp: List IDE device in ISA PnP BIOS enumeration +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> irq; io; altio; int13fakeio; int13fakev86io; enable pio32; ignore pio32; cd-rom spinup time; cd-rom spindown timeout; cd-rom insertion delay +# +enable = true +pnp = true + +[ide, secondary] +enable = true +pnp = true + +[ide, tertiary] +enable = false +pnp = true + +[ide, quaternary] +enable = false +pnp = true + +[ide, quinternary] +enable = false +pnp = true + +[ide, sexternary] +enable = false +pnp = true + +[ide, septernary] +enable = false +pnp = true + +[ide, octernary] +enable = false +pnp = true + +[fdc, primary] +# enable: Enable floppy controller interface +# pnp: List floppy controller in ISA PnP BIOS enumeration +# mode: Floppy controller mode. What the controller acts like. +# ps2 PS/2 mode (most common) +# ps2_model30 PS/2 model 30 +# at AT mode +# xt PC/XT mode +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> irq; io; dma; int13fakev86io; instant mode; auto-attach to int 13h; chip +# +enable = false +pnp = true +mode = ps2 + +[4dos] +rem = This section is the 4DOS.INI file, if you use 4DOS as the command shell + +[config] +# rem: Records comments (remarks). +# break: Sets or clears extended CTRL+C checking. +# Possible values: on, off. +# numlock: Sets the initial state of the NumLock key. +# Possible values: on, off. +# shell: Specifies the command shell (COMMAND.COM or 4DOS.COM). +# dos: Reports whether DOS occupies HMA and allocates UMB memory (if available). +# fcbs: Number of FCB handles available to DOS programs (1-255). Set to 0 to automatically use a reasonable default. +# files: Number of file handles available to DOS programs (8-255). Set to 0 to automatically use a reasonable default. +# country: Country code for date/time/decimal formats and optionally code page for TTF output and language files. +# lastdrive: The maximum drive letter (A-Z) that can be accessed by programs. +# Possible values: a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z. +rem = This section is DOS's CONFIG.SYS file, not all CONFIG.SYS options supported +break = off +numlock = +shell = +dos = high, umb +fcbs = 0 +files = 0 +country = +lastdrive = a +set path = Z:\;Z:\SYSTEM;Z:\BIN;Z:\DOS;Z:\4DOS;Z:\DEBUG;Z:\TEXTUTIL +set prompt = $P$G +set temp = +install = +installhigh = +device = +devicehigh = + +[autoexec] +# Lines in this section will be run at startup. +# You can put your MOUNT lines here. diff --git a/dosbox-x/rd_assets/rd_config/mapper-dosbox-x.map b/dosbox-x/rd_assets/rd_config/mapper-dosbox-x.map new file mode 100644 index 00000000..eb2b3caa --- /dev/null +++ b/dosbox-x/rd_assets/rd_config/mapper-dosbox-x.map @@ -0,0 +1,225 @@ +[SDL2] +hand_reset "key 21 host" +hand_reboot "key 5 host" +hand_loadmap +hand_quickrun "key 20 host" +hand_shutdown "key 66 mod1" +hand_capmouse "key 67 mod1" +hand_fastedit +hand_copyall "key 62 mod1" +hand_paste "key 63 mod1" +hand_pasteend +hand_ejectpage "key 59 mod1" +hand_printtext +hand_pause "key 72 host" +hand_pauseints +hand_gui "key 6 host" +hand_mapper "key 16 host" +hand_fullscr "key 9 host" +hand_resetsize "key 42 host" +hand_dbcssbcs +hand_autoboxdraw +hand_incsize "key 82 host" +hand_decsize "key 81 host" +hand_resetcolor +hand_pwrbutton +hand_togmenu "key 41 host" +hand_speedlock "key 79 host" +hand_speedlock2 +hand_speednorm "key 80 host" +hand_speedup "key 48 host" +hand_slowdown "key 47 host" +hand_editcycles +hand_savestate "key 22 host" +hand_loadstate "key 15 host" +hand_showstate +hand_prevslot "key 54 host" +hand_nextslot "key 55 host" +hand_decfskip +hand_incfskip +hand_aspratio +hand_fscaler +hand_recwave "key 26 host" +hand_recmtwave +hand_caprawmidi +hand_caprawopl +hand_capnetrf +hand_video "key 12 host" +hand_scrshot "key 19 host" +hand_rawscrshot "key 19 mod1 host" +hand_cycauto +hand_cycledown "key 45 host" +hand_cycleup "key 46 host" +hand_normal +hand_dynamic +hand_simple +hand_full +hand_volup "key 87 host" +hand_voldown "key 86 host" +hand_recvolup +hand_recvoldown +hand_sendkey_mapper "key 76 host" +hand_swapimg "key 18 host" +hand_swapcd "key 7 host" +hand_rescanall +key_f13 +key_f14 +key_f15 +key_f16 +key_f17 +key_f18 +key_f19 +key_f20 +key_f21 +key_f22 +key_f23 +key_f24 +key_esc "key 41" +key_f1 "key 58" +key_f2 "key 59" +key_f3 "key 60" +key_f4 "key 61" +key_f5 "key 62" +key_f6 "key 63" +key_f7 "key 64" +key_f8 "key 65" +key_f9 "key 66" +key_f10 "key 67" +key_f11 "key 68" +key_f12 "key 69" +key_grave "key 53" +key_1 "key 30" +key_2 "key 31" +key_3 "key 32" +key_4 "key 33" +key_5 "key 34" +key_6 "key 35" +key_7 "key 36" +key_8 "key 37" +key_9 "key 38" +key_0 "key 39" +key_minus "key 45" +key_equals "key 46" +key_bspace "key 42" +key_tab "key 43" +key_q "key 20" +key_w "key 26" +key_e "key 8" +key_r "key 21" +key_t "key 23" +key_y "key 28" +key_u "key 24" +key_i "key 12" +key_o "key 18" +key_p "key 19" +key_lbracket "key 47" +key_rbracket "key 48" +key_enter "key 40" +key_capslock "key 57" +key_a "key 4" +key_s "key 22" +key_d "key 7" +key_f "key 9" +key_g "key 10" +key_h "key 11" +key_j "key 13" +key_k "key 14" +key_l "key 15" +key_semicolon "key 51" +key_quote "key 52" +key_backslash "key 49" +key_lshift "key 225" +key_lessthan "key 100" +key_z "key 29" +key_x "key 27" +key_c "key 6" +key_v "key 25" +key_b "key 5" +key_n "key 17" +key_m "key 16" +key_comma "key 54" +key_period "key 55" +key_slash "key 56" +key_rshift "key 229" +key_lctrl "key 224" +key_lwindows +key_lalt "key 226" +key_space "key 44" +key_ralt "key 230" +key_rwindows +key_rwinmenu +key_rctrl "key 228" +key_printscreen "key 70" +key_scrolllock "key 71" +key_pause "key 72" +key_insert "key 73" +key_home "key 74" +key_pageup "key 75" +key_delete "key 76" +key_end "key 77" +key_pagedown "key 78" +key_up "key 82" +key_left "key 80" +key_down "key 81" +key_right "key 79" +key_kp_equals "key 103" +key_kp_comma "key 133" +key_numlock "key 83" +key_kp_divide "key 84" +key_kp_multiply "key 85" +key_kp_minus "key 86" +key_kp_7 "key 95" +key_kp_8 "key 96" +key_kp_9 "key 97" +key_kp_plus "key 87" +key_kp_4 "key 92" +key_kp_5 "key 93" +key_kp_6 "key 94" +key_kp_1 "key 89" +key_kp_2 "key 90" +key_kp_3 "key 91" +key_kp_enter "key 88" +key_kp_0 "key 98" +key_kp_period "key 99" +mouse_left +mouse_middle +mouse_right +jbutton_0_0 +jbutton_0_1 +jaxis_0_0- +jaxis_0_0+ +jaxis_0_1- +jaxis_0_1+ +jbutton_0_2 +jbutton_0_3 +jbutton_1_0 +jbutton_1_1 +jaxis_0_2- +jaxis_0_2+ +jaxis_0_3- +jaxis_0_3+ +jaxis_1_0- +jaxis_1_1- +jaxis_1_0+ +jaxis_1_1+ +jbutton_0_4 +jbutton_0_5 +jhat_0_0_0 +jhat_0_0_3 +jhat_0_0_2 +jhat_0_0_1 +key_jp_hankaku +key_jp_muhenkan "key 139" +key_jp_henkan "key 138" +key_jp_hiragana "key 136" +key_jp_yen "key 137" +key_jp_bckslash "key 135" +key_colon +key_caret +key_atsign +key_kor_hancha +key_kor_hanyong +mod_1 "key 224" "key 228" +mod_2 "key 226" "key 230" +mod_3 "key 225" "key 229" +host "key 69" diff --git a/dosbox-x/rd_assets/rd_config/os_configs/win31.conf b/dosbox-x/rd_assets/rd_config/os_configs/win31.conf new file mode 100644 index 00000000..49651262 --- /dev/null +++ b/dosbox-x/rd_assets/rd_config/os_configs/win31.conf @@ -0,0 +1,44 @@ +[sdl] +autolock=true + +[dosbox] +title=Windows 3.1x +; Windows 3.1 works best with conservative memory settings to keep +; conventional/extended memory behavior compatible with 16/32-bit drivers. +; Use 16–32MB. Avoid very large memsize when running in "Standard" mode. +memsize=16 + +[dos] +; leave disk I/O unthrottled for snappy local image performance +hard drive data rate limit=0 +floppy drive data rate limit=0 +; enable standard memory features used by Windows 3.x +xms=true +hma=true +ems=true +umb=true + +[cpu] +cputype=386 +; dynamic core gives a good performance boost on modern hosts and remains +; compatible with Windows 3.1. dynamic_rec/dynamic_x86 sometimes break older +; 16-bit software — avoid them for maximum compatibility. +core=dynamic +; conservative cycles: auto usually handles well for GUI apps; you can set +; cycles=max on fast hosts for faster performance but it can affect timing +cycles=auto +turbo = true + +[pci] +; Windows 3.1 rarely needs 3dfx Voodoo — keep disabled by default +voodoo=false + +[ide, primary] +int13fakeio=true +int13fakev86io=false + +[render] +; keep scaler off for fidelity — use host/global config if you want upscaling +scaler=none + +[autoexec] diff --git a/dosbox-x/rd_assets/rd_config/os_configs/win98.conf b/dosbox-x/rd_assets/rd_config/os_configs/win98.conf new file mode 100644 index 00000000..f91b4284 --- /dev/null +++ b/dosbox-x/rd_assets/rd_config/os_configs/win98.conf @@ -0,0 +1,63 @@ +[sdl] +autolock=true + +# ------------------------------------------------------------------ +# Optimized Windows 95/98 profile for DOSBox-X +# Goal: maximize compatibility with Windows 9x guests while giving +# modern hosts good performance out-of-the-box. +# Notes: anyone running on weaker hardware should reduce `cycles` or +# switch `core` back to `normal` for stability. +# ------------------------------------------------------------------ + +[dosbox] +title=Windows 98 +memsize=512 + +[video] +; Video RAM for SVGA: 8 MB is a good baseline for Windows 98 (handles 1024x768/16M) +; If you want automatic selection, set to -1. Keep 8 to match most Win9x drivers. +vmemsize=8 +vesa modelist width limit=0 +vesa modelist height limit=0 + +[dos] +# Set 'ver=7.1' if using Win95 OSR2 (95B) or later +ver=7.1 +; remove artificial I/O throttles for best responsiveness when running from +; local images/mounts. Set to -1 to re-enable host-friendly defaults. +hard drive data rate limit=0 +floppy drive data rate limit=0 + +[cpu] +; CPU: Windows 9x works best with a Pentium-compatible CPU. Use pentium_ii +; for better compatibility with later Windows 9x-era drivers / apps. +; Use core=dynamic for significantly improved performance on modern hosts +; (dynamic_rec is unsafe for Windows 9x; avoid it). `cycles=max` gives max speed +; but can be adjusted (e.g. fixed 50000) if you see issues. +cputype=pentium_ii +core=dynamic +cycles=max +turbo = true +; Keep ISA PnP BIOS for Windows 9x detection of PnP devices +isapnpbios=true + +[fdc, primary] +int13fakev86io=true + +[ide, primary] +int13fakeio=true +int13fakev86io=true + +[ide, secondary] +int13fakeio=true +int13fakev86io=true +; reduce wait when inserting CDs (helpful for immersive testing/booting) +cd-rom insertion delay=0 + +[render] +; Scaler - leave as 'none' for faithful/natural rendering. +; If you prefer nicer upscaling on modern displays, try 'normal2x' or +; 'openglpp' (depending on host GPU/drivers). Example: scaler=normal2x +scaler=none + +[autoexec] diff --git a/dosbox-x/rd_assets/winplay/winplay.sh b/dosbox-x/rd_assets/winplay/winplay.sh new file mode 100755 index 00000000..7387f6a5 --- /dev/null +++ b/dosbox-x/rd_assets/winplay/winplay.sh @@ -0,0 +1,391 @@ +#!/bin/bash + +# WinPlay! is used to setup and run Windows 9x through DosBox-X. +# The ecosystem of scripts in WinPlay! is designed to set variables and prepare the environment to feed it to DosBox-X. +# The main entry point is winplay.sh, which parses the arguments and calls the appropriate functions for installation or running. +# Everything is called trough arguments and WinPlay! will prepare the config file and the actual agruments. Once prepared the actual DosBox-X executable is called with the generated config and arguments. +# Everything here is dynamic and generated on the fly, there are no hardcoded config files or arguments for DosBox-X. +# Everything is generated based on the provided arguments and the templates in the os_configs directory. + +# Call examples: +# Install Windows 98 with CD-ROM and Floppy images: +# winplay --os-install win98 --cdrom /path/to/windows98.iso --floppy /path/to/floppy.img +# Run the installed Windows 98: +# winplay --os-run win98 + +SYSTEM="UNKNOWN" # The system to install or run, e.g. win98 +GAME_NAME="UNKNOWN" # Serves as a game ID +GAME_PATH="UNKNOWN" # Path to the game VHD file +CALL_SOURCE="WINPLAY" # The scripts will know that they are called from winplay.sh and not directly, so they can check this variable to prevent direct execution. +DOSBOX_X_ARGS="" # This variable will be built up with the arguments to pass to DosBox-X, such as --cdrom and --floppy, based on the provided arguments. +MOUNT_MAP="" # Defines which CD-ROMs and Floppy disks are mounted. + +SCRIPT_DIR="$(cd "$(dirname -- "${BASH_SOURCE:-$0}")" &> /dev/null && pwd)" +DOSBOX_X_EXEC="$SCRIPT_DIR/../bin/dosbox-x" + +# TODO: only for local testing, remove me later +# log(){ +# if [ "$1" == "i" ]; then +# level="INFO" +# elif [ "$1" == "d" ]; then +# level="DEBUG" +# elif [ "$1" == "e" ]; then +# level="ERROR" +# elif [ "$1" == "w" ]; then +# level="WARNING" +# else +# level="LOG" +# fi +# echo "[$(date +'%Y-%m-%d %H:%M:%S')] [${level}]: $2" +# } + +log d "Starting WinPlay! with arguments: $*" + +reboot_windows() { + log i "Windows reboot was requested." + REBOOT_WINDOWS="true" +} + +imgmount_map() { + + # This function generates an IMGMOUNT command for the given media type and image, and keeps track of used drive letters to avoid conflicts. + # It returns the IMGMOUNT command string, which can be appended to the DosBox + + # Example usage: + # MOUNT_MAP+="$(imgmount_map "FLOPPY" "$FLOPPY_IMAGE")" + # MOUNT_MAP+="$(imgmount_map "CD-ROM" "$CDROM_IMAGE")" + # Example output: + # IMGMOUNT A "path/to/floppy.img" -t floppy + # IMGMOUNT E "path/to/cdrom.iso" -t cdrom + + declare -A IMGMOUNT_USED + + local type="${1^^}" + local image="$2" + local letter="" + local candidate + + log d "Generating IMGMOUNT command for type: $type, image: $image" + + case "$type" in + FLOPPY) + for candidate in A B; do + [[ -n "${IMGMOUNT_USED[$candidate]}" ]] && continue + letter="$candidate" + break + done + local mount_type="-t floppy" + ;; + + CDROM | CD-ROM) + for candidate in E F G H I J K L M N O P Q R S T U V W X Y Z; do + [[ -n "${IMGMOUNT_USED[$candidate]}" ]] && continue + letter="$candidate" + break + done + local mount_type="-t cdrom" + ;; + + *) + log e "Unknown media type: $type" + return 1 + ;; + esac + + if [[ -z "$letter" ]]; then + log e "No free drive letters available for $type" + return 1 + fi + + IMGMOUNT_USED["$letter"]=1 + + log d "Assigned drive letter $letter for $type image: $image" + + printf 'IMGMOUNT %s "%s" %s\n' "$letter" "$image" "$mount_type" +} + +show_help(){ + echo "Usage: winplay [OPTIONS]" + echo "" + echo "Drive Options:" + echo " --floppy Path to the floppy image to use for installation (optional)" + echo " --cdrom Path to the CD-ROM. CD-ROM disc image or directory can be used. Also --cd-rom" + echo "WinPlay! Supports two Floppy disks 22 CD-ROMs at the same time. If you need more than two Floppy disks, consider to group them into a CD-ROM." + echo "" + echo "Options:" + echo " --system Specify the system to install or run (win95, win98, win31)" + echo " --os-install Install Windows 9x on DosBox-X" + echo " --os-run Run the installed Windows 9x on DosBox-X" + echo " --game-install Install a game on an installed Windows 9x. Game name serves as game identifier." + echo " Game is installed in $roms_path/windows*/game_name directory." + echo " Game name should match the wished executable target,for example OMF to launch OMF.EXE." + echo " --game-run Run a game from a specified VHD file." + echo " the VHD base name (without extension) should match the wished executable target, for example OMF.vhd will search and launch OMF.EXE." + echo " -h, --help Show this help message and exit" + echo "" + echo "Supported systems:" + echo " win95 Install Windows 95 on DosBox-X (not implemented yet)" + echo " win98 Install Windows 98 on DosBox-X" + echo " win31 Install Windows 3.1 on DosBox-X (not implemented yet)" + echo "" + echo "Example usages:" + echo " winplay --os-install --system win98 --cdrom /path/to/windows98.iso --floppy /path/to/floppy.img" + echo " winplay --os-run --system win98" + echo " winplay --game-install --system win98 --game OMF --cdrom /path/to/OMF2097.iso" + echo " winplay --game-run --system win98 --game /home/deck/retrodeck/roms/windows9x/OMF.vhd" +} + +# TODO: not yet used +dos_name_sanitizer(){ + # Replace path separators with underscores and collapse any sequence of + # characters that are not a-zA-Z0-9, dot, underscore or hyphen into a single '_' + + # Usage: sanitized=$(sanitize_name "Some Name/With*Invalid|Chars") + # Output: Some_Name_With_Invalid_Chars + + local name="$1" + + [[ -z "$name" ]] && { + printf 'GAME' + return + } + + local safe + safe=$(printf '%s' "$name" \ + | sed -E 's|/|_|g' \ + | sed -E 's/[^A-Za-z0-9_-]+/_/g' \ + | sed -E 's/^_+|_+$//g') + + printf '%s' "${safe^^}" +} + +load_system_config(){ + + # Simple function to load the winXX.conf from the os_configs directory. + # NOTE: this clenas the Autoexec + + log d "Generating temporary config for $PRETTY_SYSTEM_NAME installation" + + if [ ! -f "$dosbox_x_os_configs_dir/${SYSTEM}.conf" ]; then + log e "Missing template config for $PRETTY_SYSTEM_NAME installation: $dosbox_x_os_configs_dir/${SYSTEM}.conf" + exit 1 + fi + + cp -fv "$dosbox_x_os_configs_dir/${SYSTEM}.conf" "$dosbox_x_generated_conf" + DOSBOX_X_CONF_ARGS="-conf $dosbox_x_generated_conf" + +} + +os_run() { + # Simple function to run DosBox-X with the set SYSTEM + log i "Running $PRETTY_SYSTEM_NAME in DosBox-X" + source "$SCRIPT_DIR/winplay_autoexec_gen.sh" + load_system_config # this cleans the autoexec + generate_autoexec_os_run +} + +game_run(){ + # Run the game on defined system and game name + log i "Running game $GAME_PATH on $PRETTY_SYSTEM_NAME in DosBox-X" + + if [[ -z "$GAME_PATH" ]]; then + log e "Game path is not specified for game_run" + exit 1 + fi + + source "$SCRIPT_DIR/winplay_autoexec_gen.sh" + load_system_config # this cleans the autoexec + generate_autoexec_game_run + + # TODO +} + +parse_arguments() { + + if [ $# -eq 0 ]; then + log w "No arguments provided for winplay" + show_help + exit 1 + fi + + while [[ $# -gt 0 ]]; do + + log d "Evaluating argument: $1" + + case "$1" in + + "--system") + if [ -n "$1" ]; then + + log d "Found \"$2\" as system name for installation or running" + + SYSTEM="$2" + + case "$SYSTEM" in + "win95") + log w "Windows 95 installation is not implemented yet" + exit 1 + ;; + + "win98") + log d "Selected system: Windows 98" + log d "Setting SYSTEM variable to \"win98\" for internal use" + log d "Setting PRETTY_SYSTEM_NAME variable to \"Windows 98\" for user-friendly display" + SYSTEM="win98" + PRETTY_SYSTEM_NAME="Windows 98" + ;; + "win31") + log w "Windows 3.1 installation is not implemented yet" + exit 1 + ;; + *) + log e "Unsupported system for os_install: $1" + os_install_help + exit 1 + ;; + esac + shift + else + log e "Missing value for --system option. Aborting." + show_help + exit 1 + fi + + ;; + "--floppy") + log d "Processing floppy argument" + if [ -n "$2" ]; then + if [ ! -f "$2" ]; then + log e "Floppy image file not found: $2" + exit 1 + fi + FLOPPY_IMAGE="$2" + # DOSBOX_X_ARGS+=" --floppy \"$FLOPPY_IMAGE\"" # Not needed, we just set it in the config + MOUNT_MAP+="$(imgmount_map "FLOPPY" "$FLOPPY_IMAGE")" + log i "Loaded floppy image: $FLOPPY_IMAGE" + shift + else + log e "Missing value for --floppy option. Aborting." + show_help + exit 1 + fi + ;; + "--cdrom" | "--cd-rom") + log d "Processing CD-ROM argument" + if [ -n "$2" ]; then + # For CD-ROM images, we allow both files and directories, so we check if the path exists. + if [ ! -f "$2" ] && [ ! -d "$2" ]; then + log e "CD-ROM image file not found: $2" + exit 1 + fi + CDROM_IMAGE="$2" + # DOSBOX_X_ARGS+=" --cdrom \"$CDROM_IMAGE\"" # Not needed, we just set it in the config + MOUNT_MAP+="$(imgmount_map "CD-ROM" "$CDROM_IMAGE")" + log i "Loaded CD-ROM image: $CDROM_IMAGE" + shift + else + log e "Missing value for --cdrom option" + exit 1 + fi + ;; + "--os-install") + log d "Selected action: OS install" + ACTION="os_install" + ;; + "--os-run") + log d "Selected action: OS run" + ACTION="os_run" + ;; + "--game-install") + log d "Selected action: Game install" + log d "Found \"$2\" as game name for installation" + if [[ -z "$2" || "$2" == --* ]]; then + log e "Missing game name after --game-install" + exit 1 + else + GAME_NAME="$2" + fi + source "$SCRIPT_DIR/winplay_install.sh" + ACTION="game_install" + ;; + "--game-run") + log d "Found \"$2\" as game path" + if [[ -z "$2" || "$2" == --* ]]; then + log e "Missing game path after --game-run" + exit 1 + else + GAME_PATH="$2" + GAME_NAME="$(basename "${GAME_PATH%.*}")" + fi + ACTION="game_run" + ;; + "--help" | "-h") + show_help + exit 0 + ;; + *) + log e "Invalid action for winplay: $1" + show_help + exit 1 + ;; + esac + shift +done +} + +if [ "$REBOOT_WINDOWS" == "true" ]; then + log d "Reboot flag is set, discarding arguments as environment is already build." +else + log d "Parsing arguments..." + parse_arguments "$@" +fi + +case "$ACTION" in + os_install) + source "$SCRIPT_DIR/winplay_install.sh" + os_install + ;; + os_run) + os_run + ;; + game_install) + source "$SCRIPT_DIR/winplay_install.sh" + game_install + ;; + game_run) + game_run + ;; + *) + log e "No action specified" + exit 1 + ;; +esac + +log d "Finished setting environment for DosBox-X execution." +log d "SYSTEM=$SYSTEM" +log d "PRETTY_SYSTEM_NAME=$PRETTY_SYSTEM_NAME" +log d "GAME_NAME=$GAME_NAME" +log d "GAME_PATH=$GAME_PATH" +log d "action=$ACTION" + +log d "Calling DosBox-X" +log d "Command: $DOSBOX_X_EXEC $DOSBOX_X_CONF_ARGS $DOSBOX_X_ARGS" + +log d "Config file content:" +log d "$(<$dosbox_x_generated_conf)" + +# At this point, all the arguments have been parsed, the config file is built and the environment is prepared. +# We can now call DosBox-X with the generated config and arguments. +# By default the dosbox-x.conf will be passed as the system .conf files are just overrides and don't include the full config stack. + +"$DOSBOX_X_EXEC" $DOSBOX_X_CONF_ARGS $DOSBOX_X_ARGS + +# Sometimes we need to reboot Windows during the installation process. +# Since we are running DosBox-X with exec, we can not just call exec again to reboot, so we set a flag and check it after DosBox-X exits. +# If the flag is set, we call exec again to restart DosBox-X, even with updated environment. + +if [ "$REBOOT_WINDOWS" == "true" ]; then + log i "Rebooting Windows as requested..." + REBOOT_WINDOWS="false" + "$DOSBOX_X_EXEC" $DOSBOX_X_CONF_ARGS $DOSBOX_X_ARGS +fi diff --git a/dosbox-x/rd_assets/winplay/winplay_autoexec_gen.sh b/dosbox-x/rd_assets/winplay/winplay_autoexec_gen.sh new file mode 100755 index 00000000..0c0ccdd9 --- /dev/null +++ b/dosbox-x/rd_assets/winplay/winplay_autoexec_gen.sh @@ -0,0 +1,164 @@ +#!/bin/bash + +# This script is used to generate autoexec sections for DosBox-X + +if [ "$CALL_SOURCE" != "WINPLAY" ]; then + log e "This script is not meant to be called directly. Please use winplay.sh to run this script." + exit 1 +fi + +generate_autoexec_headers() { +# Mount the OS image as a hard disk (VHD) for installation +log d "Generating autoexec headers" +cat <> "$dosbox_x_generated_conf" +IMGMOUNT C "$OS_IMAGE" -t hdd +EOF + +# Mount any additional media (floppy, CD-ROM) if specified, and build up the MOUNT_MAP for later inclusion in the config +log d "Appending generated MOUNT_MAP for autoexec:" +log d "$MOUNT_MAP" +cat <> "$dosbox_x_generated_conf" +${MOUNT_MAP} +EOF + +} + +generate_autoexec_install_os() { + +generate_autoexec_headers + +# Copy drivers from the CD to the Windows system directory to reduce prompts during installation. +cat <> "$dosbox_x_generated_conf" +REM Copy as many files as possible from the CD to C:\WINDOWS\SYSTEM +IF NOT EXIST C:\WINDOWS\SYSTEM MD C:\WINDOWS\SYSTEM +REM Copy full $SYSTEM and DRIVERS directories (recursive copy where available) +IF EXIST D:\${SYSTEM} XCOPY D:\${SYSTEM} C:\WINDOWS\SYSTEM /E /Y >NUL 2>NUL +IF EXIST D:\DRIVERS XCOPY D:\DRIVERS C:\WINDOWS\SYSTEM /E /Y >NUL 2>NUL +REM Also copy any root-level device files that might be directly requested +IF EXIST D:\*.VXD COPY /Y D:\*.VXD C:\WINDOWS\SYSTEM >NUL 2>NUL +IF EXIST D:\*.DRV COPY /Y D:\*.DRV C:\WINDOWS\SYSTEM >NUL 2>NUL +EOF + +# Add autoexec commands to run the Windows setup from the mounted CD-ROM +# In this phase we make sure that there is no run_game.bat in the startup folders +cat <> "$dosbox_x_generated_conf" +DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" +DIR "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" +DEL /F /Q "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" 2>NUL +DEL /F /Q "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" 2>NUL +DIR "C:\\WINDOWS\\STARTM~1\\PROGRAMS\\STARTUP\\run_game.bat" +DIR "C:\\WINDOWS\\Start Menu\\Programs\\Startup\\run_game.bat" +D: +SETUP.EXE +GOTO END_INSTALL +:WINDOWS_FOUND +ECHO Windows installation detected, booting it +BOOT C: +:END_INSTALL +C: +RUNDLL32.EXE USER.EXE,ExitWindows +EOF + +log i "Setup: first phase of installation complete. Rebooting to finish the installation." + +} + +generate_autoexec_os_run() { + generate_autoexec_headers +} + +generate_autoexec_game_install() { + generate_autoexec_headers +} + +generate_autoexec_game_run() { + +generate_autoexec_headers + +cat > "$dosbox_x_generated_conf" << EOF + +IMGMOUNT D "$GAME_PATH" -t hdd + +@ECHO OFF +CLS +COLOR 1F + +REM ----------------------------------------------------------------- +REM WINPLAY +REM ----------------------------------------------------------------- + +IF EXIST D:\\WINPLAY.CFG GOTO LOADCFG + +SET TARGET=${GAME_NAME}.EXE +GOTO FIND_DEFAULT + +:LOADCFG + +FOR /F "tokens=1,* delims==" %%A IN (D:\WINPLAY.CFG) DO SET EXEC_PATH=%%B + +IF EXIST "%EXEC_PATH%" ( + START /WAIT "" "%EXEC_PATH%" + GOTO END +) + +:FIND_DEFAULT + +SET FOUND= + +FOR /R D:\ %%F IN (%TARGET%) DO ( + SET FOUND=%%F +) + +IF NOT "%FOUND%"=="" ( + START /WAIT "" "%FOUND%" + GOTO END +) + +:NOT_FOUND + +CLS +COLOR 1F + +ECHO. +ECHO ============================================================ +ECHO WINPLAY +ECHO ============================================================ +ECHO. +ECHO Could not determine which executable to launch. +ECHO. +ECHO WinPlay searched for: +ECHO. +ECHO %TARGET% +ECHO. +ECHO To fix this, either: +ECHO. +ECHO 1. Rename the VHD file so that its name matches the EXE +ECHO. +ECHO Example: +ECHO OMF.VHD searches for OMF.EXE +ECHO. +ECHO 2. Create D:\WINPLAY.CFG containing: +ECHO. +ECHO EXEC=D:\PATH\TO\GAME.EXE +ECHO. +ECHO Press any key to exit. +ECHO. +ECHO ============================================================ + +PAUSE >NUL +GOTO END + +:END +RUNDLL32.EXE USER.EXE,ExitWindows +EOF +} + +clear_autoexec(){ + local conf_file="${1:-$dosbox_x_generated_conf}" + + # Clear the autoexec section of the generated config file + sed -i '/^\[autoexec\]$/,$d' "$dosbox_x_generated_conf" + + # Replace it with the system defult one + sed -n '/^\[autoexec\]$/,$p' "$dosbox_x_os_configs_dir/${SYSTEM}.conf" >> "$dosbox_x_generated_conf" +} \ No newline at end of file diff --git a/dosbox-x/rd_assets/winplay/winplay_install.sh b/dosbox-x/rd_assets/winplay/winplay_install.sh new file mode 100755 index 00000000..b4594d47 --- /dev/null +++ b/dosbox-x/rd_assets/winplay/winplay_install.sh @@ -0,0 +1,147 @@ +#!/bin/bash + +if [ "$CALL_SOURCE" != "WINPLAY" ]; then + log e "This script is not meant to be called directly. Please use winplay.sh to run this script." + exit 1 +fi + +os_install_help() { + echo "Usage: winplay --os-install --system --floppy --cdrom " + echo "" + echo "This will guide you through the installation of Windows 9x on DosBox-X using WinPlay!" + echo "You will need a legit Windows 98 CD Key and a Windows 98 ISO image to complete the installation." + echo "" + echo "Options:" + echo " --os-install --system Install the specified system on DosBox-X" + echo "" + echo "Example usage:" + echo " winplay --os-install --system win98 --cdrom /path/to/windows98.iso --floppy /path/to/floppy.img" +} + +os_install() { + + log d "Called os_install for system \"$PRETTY_SYSTEM_NAME\"" + + load_system_config # This already cleans the autoexec + + log d "Calling mkfs to create virtual hard disk for $PRETTY_SYSTEM_NAME installation" + OS_IMAGE="$storage_path/dosbox-x/${SYSTEM}.vhd" + mkfs + + log d "Calling AUTOEXEC generator for $PRETTY_SYSTEM_NAME installation" + source "$SCRIPT_DIR/winplay_autoexec_gen.sh" + generate_autoexec_install_os + + log d "Setting action variable to \"os_run\" before rebooting the system." + action="os_run" + reboot_windows + os_run + + clear_autoexec + +} + +create_vhd() { + + # Create a VHD (Virtual Hard Disk) file to be used as the virtual hard drive for the Windows installation or GAME HD. + # Usage: create_vhd + + local IMAGE_PATH="$1" + local size_mb="$2" + local fs_type="$3" + + log d "Creating VHD at \"$IMAGE_PATH\" with size ${size_mb}MB and filesystem $fs_type" + + + if [[ -f "$IMAGE_PATH" ]]; then + log e "VHD already exists: $IMAGE_PATH (skipping)" + log e "If you want to create a new VHD, please delete the existing one at \"$IMAGE_PATH\" and run the installation again." + exit 1 + fi + + mkdir -p "$(dirname "$IMAGE_PATH")" + + log i "Creating VHD: \"$IMAGE_PATH\" (${size_mb}MB, $fs_type)" + + # Use DOSBox-X imgmake to create a dynamic VHD + # This is native to DOSBox-X and fully compatible + if ! "$component_path/bin/dosbox-x" -c "imgmake -t hd -size $size_mb \"$IMAGE_PATH\"" -c "exit" > /dev/null 2>&1; then + log e "Failed to create VHD with imgmake" + rm -f "$IMAGE_PATH" + return 1 + fi + + local disk_blocks=$(stat -c%b "$OS_IMAGE" 2>/dev/null || echo 0) + local disk_usage_kb=$((disk_blocks * 512 / 1024)) + local size_str=$([[ $disk_usage_kb -lt 1024 ]] && echo "${disk_usage_kb}KB" || echo "$((disk_usage_kb / 1024))MB") + + log i "VHD created (sparse: ~${size_str} on disk)" +} + +mkfs() { + + case "$SYSTEM" in + "win98") + local fs_type="FAT32" + local size_mb=4096 + ;; + "win95") + local fs_type="FAT32" + local size_mb=4096 + ;; + "win31") + local fs_type="FAT16" + local size_mb=512 + ;; + *) + log e "Unsupported system for mkfs: $PRETTY_SYSTEM_NAME" + return 1 + ;; + esac + + create_vhd "$OS_IMAGE" "$size_mb" "$fs_type" +} + +mk_gamehd() { + log d "Called mk_gamehd for game name: \"$GAME_NAME\"" + log d "using system \"$PRETTY_SYSTEM_NAME\" to determine game HD parameters" + + case "$SYSTEM" in + "win98") + local fs_type="FAT32" + local size_mb=16384 # 16GB + local ESDE_SYSTEM_NAME="windows9x" + ;; + "win95") + local fs_type="FAT32" + local size_mb=8192 # 8GB + local ESDE_SYSTEM_NAME="windows9x" + ;; + "win31") + local fs_type="FAT16" + local size_mb=2048 # 2GB (FAT16 limitation) + local ESDE_SYSTEM_NAME="windows3x" + ;; + esac + + log d "Determined game HD parameters: size ${size_mb}MB, filesystem $fs_type, ESDE system name \"$ESDE_SYSTEM_NAME\"" + + GAME_IMAGE="$roms_path/$ESDE_SYSTEM_NAME/$(dos_name_sanitizer "$GAME_NAME.vhd")" + + create_vhd "$GAME_IMAGE" "$size_mb" "$fs_type" + +} + +game_install() { + log d "Called game_install for game name: \"$GAME_NAME\"" + + load_system_config # This already cleans the autoexec + + source "$SCRIPT_DIR/winplay_autoexec_gen.sh" + generate_autoexec_game_install + + mk_gamehd + + # At this point we got the game HD created and the autoexec ready to run the game installer. + # The flow with proceed calling DosBox-X with this environment set. +} \ No newline at end of file