Skill: stanestane/dosbox (version 1.0.0)

--- name: dosbox description: Launch, configure, and troubleshoot DOSBox-X first, with fallback to classic DOSBox, for DOS games and software. Use when working with classic DOS programs, mounting folders or ISO/CD images, generating launch commands, auto-generating reusable .conf files, fixing sound/input/fullscreen issues, editing dosbox config files, or preparing a shareable setup for old games and abandonware. --- # DOSBox Use this skill to get a DOS program running with the least drama possible. Prefer **DOSBox-X** when available. Fall back to classic **DOSBox** only when DOSBox-X is missing or the user explicitly wants stock DOSBox behavior. ## Quick approach 1. Detect available emulators with `scripts/resolve_dosbox.py`. 2. Prefer **DOSBox-X** for: - ISO/CD-heavy installs - awkward installers - hardware and config edge cases - reusable setups that should be easier to tweak later 3. Identify what the user has: - a game/app folder - a floppy/ISO/CD image - an installer - an existing config file 4. Build a reproducible launch command or config instead of relying on vague manual steps. 5. If the program fails, troubleshoot in this order: - wrong mount / wrong drive letter - wrong startup executable - graphics/output mode - sound setup - CPU cycles / speed sensitivity - input or fullscreen settings ## Core workflows ### Launch a DOS app from a folder Prefer mounting the containing folder as `C:`. Typical command pattern: ```powershell <dosbox-binary> -c "mount c <path-to-folder>" -c "c:" -c "dir" -c "<program.exe>" ``` Rules: - Quote Windows paths carefully. - Mount the parent folder that contains the DOS files. - If the executable is unknown, inspect with `dir` first. - If there is a setup utility (`SETUP.EXE`, `INSTALL.EXE`), run that before the main game when sound/video must be configured. ### Launch from CD / ISO media Prefer DOSBox-X for image handling. Typical pattern: ```powershell <dosbox-binary> -c "imgmount d <image-file> -t iso" -c "d:" -c "dir" ``` If the game needs both a writable hard drive and CD: ```powershell <dosbox-binary> -c "mount c <game-or-install-folder>" -c "imgmount d <image-file> -t iso" -c "c:" ``` ### Install a DOS game Use a dedicated writable game folder. Recommended flow: 1. Create a clean install directory. 2. Mount it as `C:`. 3. Mount install media as `D:` if needed. 4. Run `INSTALL`, `SETUP`, or vendor-specific installer. 5. After install, create a reusable launch command or config file. ### Generate a reusable config file Prefer a config file when the user wants a stable, repeatable setup. Use `scripts/make_dosbox_conf.py` to generate a starter `.conf` file with: - detected emulator path - mount commands - optional ISO mounting - optional auto-run executable - sensible defaults for fullscreen, output, cycles, and Sound Blaster Examples: ```powershell python scripts/make_dosbox_conf.py --game-path "C:\Games\DOOM" --exe DOOM.EXE --conf "C:\Games\DOOM\doom.conf" python scripts/make_dosbox_conf.py --game-path "C:\Games\Install" --iso "C:\Images\GAME.iso" --exe INSTALL.EXE --conf "C:\Games\Install\install.conf" ``` Inspect the generated file before claiming it is final; some games need renderer, cycles, or audio tweaks. ### Use an existing config file If a config already exists, inspect it before changing anything. Typical launch forms: ```powershell <dosbox-binary> -conf <config-file> ``` or: ```powershell <dosbox-binary> -userconf ``` Only edit config values that solve the current problem. Avoid broad random tweaks. ## Troubleshooting checklist ### Program does not start Check: - mounted the correct folder - using the correct drive letter - executable name is correct - files are not nested one level deeper than expected - the program expects to be started from its own directory Useful in-emulator commands: ```text mount c: dir cd <subdir> ``` ### "This program requires MSCDEX/CD-ROM" Mount optical media properly: ```powershell imgmount d <image-file> -t iso ``` If using a host folder as a CD source, prefer DOSBox-X when possible and ensure the game really supports folder-based installation. ### Sound does not work Run the game's setup program first. Common working values for many DOS titles: - Sound Blaster 16 - Port `220` - IRQ `7` - DMA `1` If the game offers autodetect, still verify what it selected. ### Too fast or too slow Adjust cycles. Examples: ```text cycles auto cycles max cycles fixed 12000 ``` For old timing-sensitive games, prefer a fixed value and iterate. ### Fullscreen / black screen / renderer issues Try changing output mode in config: - `output=opengl` - `output=texture` - `output=ddraw` - `output=surface` Prefer changing one setting at a time. ### Keyboard / mouse problems Check: - whether mouse capture is active - whether the game expects keyboard-only input - whether key layout issues come from host locale differences ## Command generation rules When writing commands for the user or a script: - Prefer a single launch command with chained `-c` directives for quick tests. - Prefer a config file for repeatable setups. - Use absolute paths on Windows. - Do not assume DOSBox is on PATH; detect common executable names or ask for the install path. - If both DOSBox and DOSBox-X exist, prefer DOSBox-X for ISO/CD-heavy setups and advanced compatibility. - If the task is shareable or repeatable, generate a `.conf` file and keep commands in `[autoexec]`. ## ClawHub publishing notes This skill is meant to be portable. - Do not hardcode one machine's install path as a requirement. - Treat DOSBox-X as preferred, not mandatory. - Use helper scripts to detect executables and generate commands/configs. - Keep claims conservative: the generated config is a good starting point, not a guaranteed universal fix. ## Bundled resources ### scripts/resolve_dosbox.py Use this helper to detect likely DOSBox executables and emit example commands for folder or ISO launches. Example: ```powershell python scripts/resolve_dosbox.py --game-path "C:\Games\DOOM" python scripts/resolve_dosbox.py --game-path "C:\Games\Install" --iso "C:\Images\GAME.iso" ``` ### scripts/make_dosbox_conf.py Use this helper to generate a reusable `.conf` file for DOSBox-X or DOSBox. ### references/troubleshooting.md Read this when the task is mainly diagnosis rather than simple launching.

path: references/troubleshooting.md
content: # DOSBox troubleshooting reference

## Choose the emulator

Prefer **DOSBox-X** when:
- working with ISO/CD images
- dealing with awkward installers
- needing stronger hardware/config flexibility

Plain **DOSBox** is usually enough when:
- launching a simple folder-based game
- the user already has a working config
- you only need a minimal command

## Common executable names to inspect

If startup is unclear, look for:
- `GAME.EXE`
- `START.EXE`
- `PLAY.EXE`
- `RUN.EXE`
- `GO.BAT`
- `SETUP.EXE`
- `INSTALL.EXE`
- `CONFIG.EXE`

Check manuals or included text files if the folder is ambiguous.

## Practical config knobs

### Performance

```ini
[cpu]
core=auto
cputype=auto
cycles=auto
cycleup=500
cycledown=500
```

For unstable timing, switch to a fixed cycle count.

### Display

```ini
[render]
aspect=true
scaler=normal2x

[sdl]
fullscreen=false
output=opengl
```

If `opengl` misbehaves, try `texture`, `ddraw`, or `surface`.

### Sound

```ini
[sblaster]
sbtype=sb16
sbbase=220
irq=7
dma=1
hdma=5
mixer=true
```

Not every game needs all values, but these defaults are often a good baseline.

## Installation pattern

Use a structure like:

```text
C:\DOS\GAME\
C:\DOS\MEDIA\GAME.iso
C:\DOS\CONFIG\game.conf
```

This keeps installed files, media, and configs separate.

## Good agent behavior

- Prefer reproducible commands over generic advice.
- Inspect before editing configs.
- Explain only the settings being changed.
- Avoid claiming a renderer/sound tweak will definitely fix the issue.
- If the emulator is not installed, say so plainly and stop short of inventing paths.


path: scripts/make_dosbox_conf.py
content: #!/usr/bin/env python3
"""Generate a starter DOSBox/DOSBox-X config file."""

from __future__ import annotations

import argparse
from pathlib import Path
import sys

from resolve_dosbox import find_binaries


def quote_autoexec_path(path: Path) -> str:
    return str(path.resolve()).replace('\\', '/')


def choose_binary() -> str | None:
    binaries = find_binaries()
    if not binaries:
        return None
    return next((b for b in binaries if 'dosbox-x' in b.lower()), binaries[0])


def build_conf(game_path: Path, iso_path: Path | None, exe: str | None, fullscreen: bool, output: str, cycles: str, binary: str | None) -> str:
    autoexec = [
        f"mount c \"{quote_autoexec_path(game_path)}\"",
    ]
    if iso_path:
        autoexec.append(f"imgmount d \"{quote_autoexec_path(iso_path)}\" -t iso")
    autoexec.append("c:")
    autoexec.append("dir")
    if exe:
        autoexec.append(exe)

    full = "true" if fullscreen else "false"
    binary_comment = binary or "NOT FOUND"

    return f"""# Generated by make_dosbox_conf.py
# Preferred emulator: {binary_comment}

[sdl]
fullscreen={full}
output={output}

[render]
aspect=true
scaler=normal2x

[cpu]
core=auto
cputype=auto
cycles={cycles}
cycleup=500
cycledown=500

[mixer]
rate=44100
blocksize=1024
prebuffer=20

[sblaster]
sbtype=sb16
sbbase=220
irq=7
dma=1
hdma=5
mixer=true
oplmode=auto
oplemu=default
oplrate=44100

[autoexec]
{"\n".join(autoexec)}
"""


def main() -> int:
    parser = argparse.ArgumentParser(description="Generate a starter DOSBox config file.")
    parser.add_argument("--game-path", required=True, help="Folder to mount as C:")
    parser.add_argument("--iso", help="Optional ISO to mount as D:")
    parser.add_argument("--exe", help="Optional executable or batch file to auto-run")
    parser.add_argument("--conf", required=True, help="Output config path")
    parser.add_argument("--fullscreen", action="store_true", help="Start in fullscreen mode")
    parser.add_argument("--output", default="opengl", help="Output mode: opengl, texture, ddraw, surface")
    parser.add_argument("--cycles", default="auto", help="CPU cycles value")
    args = parser.parse_args()

    game_path = Path(args.game_path)
    if not game_path.exists() or not game_path.is_dir():
        print(f"Game path not found or not a directory: {game_path}", file=sys.stderr)
        return 1

    iso_path = Path(args.iso) if args.iso else None
    if iso_path and not iso_path.exists():
        print(f"ISO path not found: {iso_path}", file=sys.stderr)
        return 1

    conf_path = Path(args.conf)
    conf_path.parent.mkdir(parents=True, exist_ok=True)

    binary = choose_binary()
    conf_text = build_conf(
        game_path=game_path,
        iso_path=iso_path,
        exe=args.exe,
        fullscreen=args.fullscreen,
        output=args.output,
        cycles=args.cycles,
        binary=binary,
    )
    conf_path.write_text(conf_text, encoding="utf-8")
    print(f"Wrote config: {conf_path.resolve()}")
    if binary:
        print(f"Preferred emulator: {binary}")
        print(f'Launch example: "{binary}" -conf "{conf_path.resolve()}"')
    else:
        print("Preferred emulator: not found")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())


path: scripts/resolve_dosbox.py
content: #!/usr/bin/env python3
"""Detect DOSBox/DOSBox-X and print example launch commands."""

from __future__ import annotations

import argparse
import os
import shutil
from pathlib import Path

COMMON_WINDOWS_PATHS = [
    r"C:\Program Files\DOSBox-X\dosbox-x.exe",
    r"C:\Program Files (x86)\DOSBox-X\dosbox-x.exe",
    r"C:\Program Files\DOSBox-0.74-3\DOSBox.exe",
    r"C:\Program Files (x86)\DOSBox-0.74-3\DOSBox.exe",
    r"C:\Program Files\DOSBox Staging\dosbox.exe",
    r"C:\Program Files (x86)\DOSBox Staging\dosbox.exe",
]


def find_binaries() -> list[str]:
    found: list[str] = []
    for name in ("dosbox-x", "dosbox"):
        path = shutil.which(name)
        if path and path not in found:
            found.append(path)
    for path in COMMON_WINDOWS_PATHS:
        if os.path.exists(path) and path not in found:
            found.append(path)
    return found


def quote(value: str) -> str:
    return '"' + value.replace('"', '\\"') + '"'


def build_folder_command(binary: str, game_path: Path) -> str:
    return (
        f"{quote(binary)} "
        f"-c \"mount c {game_path}\" "
        f"-c \"c:\" "
        f"-c \"dir\""
    )


def build_iso_command(binary: str, game_path: Path | None, iso_path: Path) -> str:
    parts = [quote(binary)]
    if game_path:
        parts.append(f'-c "mount c {game_path}"')
    parts.append(f'-c "imgmount d {iso_path} -t iso"')
    if game_path:
        parts.append('-c "c:"')
    else:
        parts.append('-c "d:"')
    parts.append('-c "dir"')
    return " ".join(parts)


def main() -> int:
    parser = argparse.ArgumentParser(description="Detect DOSBox executables and suggest commands.")
    parser.add_argument("--game-path", help="Folder to mount as C:")
    parser.add_argument("--iso", help="ISO image to mount as D:")
    args = parser.parse_args()

    binaries = find_binaries()
    if not binaries:
        print("No DOSBox executable found on PATH or in common Windows install locations.")
        return 1

    preferred = next((b for b in binaries if "dosbox-x" in b.lower()), binaries[0])
    print(f"Preferred binary: {preferred}")
    print("Detected binaries:")
    for binary in binaries:
        print(f"- {binary}")

    game_path = Path(args.game_path).resolve() if args.game_path else None
    iso_path = Path(args.iso).resolve() if args.iso else None

    if game_path:
        print("\nFolder launch example:")
        print(build_folder_command(preferred, game_path))

    if iso_path:
        print("\nISO launch example:")
        print(build_iso_command(preferred, game_path, iso_path))

    if not game_path and not iso_path:
        print("\nTip: pass --game-path and/or --iso to generate example commands.")

    return 0


if __name__ == "__main__":
    raise SystemExit(main())


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)