dbxdebug 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dbxdebug-0.2.1/.github/workflows/lint.yml +29 -0
- dbxdebug-0.2.1/.github/workflows/publish.yml +65 -0
- dbxdebug-0.2.1/.github/workflows/test.yml +73 -0
- dbxdebug-0.2.1/.gitignore +41 -0
- dbxdebug-0.2.1/.pre-commit-config.yaml +82 -0
- dbxdebug-0.2.1/PKG-INFO +164 -0
- dbxdebug-0.2.1/README.md +143 -0
- dbxdebug-0.2.1/pyproject.toml +89 -0
- dbxdebug-0.2.1/src/dbxdebug/__init__.py +134 -0
- dbxdebug-0.2.1/src/dbxdebug/capture_io.py +210 -0
- dbxdebug-0.2.1/src/dbxdebug/cli.py +618 -0
- dbxdebug-0.2.1/src/dbxdebug/dbx_kbd.py +392 -0
- dbxdebug-0.2.1/src/dbxdebug/gdb.py +297 -0
- dbxdebug-0.2.1/src/dbxdebug/html.py +559 -0
- dbxdebug-0.2.1/src/dbxdebug/keyboard.py +205 -0
- dbxdebug-0.2.1/src/dbxdebug/qmp.py +239 -0
- dbxdebug-0.2.1/src/dbxdebug/utils.py +92 -0
- dbxdebug-0.2.1/src/dbxdebug/video.py +239 -0
- dbxdebug-0.2.1/tests/__init__.py +0 -0
- dbxdebug-0.2.1/tests/test_basic.py +170 -0
- dbxdebug-0.2.1/uv.lock +818 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Lint workflow - runs on every push
|
|
2
|
+
# Checks: ruff, pyright, pre-commit hooks
|
|
3
|
+
|
|
4
|
+
name: Lint
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
workflow_call: # Allow other workflows to call this
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
name: Lint
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v5
|
|
19
|
+
|
|
20
|
+
- name: Install uv and set up Python
|
|
21
|
+
uses: astral-sh/setup-uv@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.11"
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: uv sync --locked
|
|
27
|
+
|
|
28
|
+
- name: Run pre-commit hooks
|
|
29
|
+
run: uv run pre-commit run --all-files
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Publish workflow - runs on v* tags
|
|
2
|
+
# Uses artifacts from test workflow, publishes to PyPI
|
|
3
|
+
#
|
|
4
|
+
# SETUP REQUIRED:
|
|
5
|
+
# 1. Create "pypi" environment in GitHub repo settings
|
|
6
|
+
# 2. Configure PyPI Trusted Publisher at pypi.org
|
|
7
|
+
|
|
8
|
+
name: Publish
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
tags:
|
|
13
|
+
- v[0-9]+.[0-9]+.[0-9]+
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
id-token: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
test:
|
|
21
|
+
name: Test & Build
|
|
22
|
+
uses: ./.github/workflows/test.yml
|
|
23
|
+
|
|
24
|
+
release:
|
|
25
|
+
name: Create GitHub Release
|
|
26
|
+
needs: test
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v5
|
|
30
|
+
|
|
31
|
+
- name: Download distributions
|
|
32
|
+
uses: actions/download-artifact@v4
|
|
33
|
+
with:
|
|
34
|
+
name: python-package-distributions
|
|
35
|
+
path: dist/
|
|
36
|
+
|
|
37
|
+
- name: Generate changelog
|
|
38
|
+
id: changelog
|
|
39
|
+
uses: requarks/changelog-action@v1
|
|
40
|
+
with:
|
|
41
|
+
token: ${{ github.token }}
|
|
42
|
+
tag: ${{ github.ref_name }}
|
|
43
|
+
|
|
44
|
+
- name: Create release
|
|
45
|
+
uses: softprops/action-gh-release@v2
|
|
46
|
+
with:
|
|
47
|
+
files: dist/*
|
|
48
|
+
body: ${{ steps.changelog.outputs.changes }}
|
|
49
|
+
|
|
50
|
+
publish:
|
|
51
|
+
name: Publish to PyPI
|
|
52
|
+
needs: test
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
environment:
|
|
55
|
+
name: pypi
|
|
56
|
+
url: https://pypi.org/p/dbxdebug
|
|
57
|
+
steps:
|
|
58
|
+
- name: Download distributions
|
|
59
|
+
uses: actions/download-artifact@v4
|
|
60
|
+
with:
|
|
61
|
+
name: python-package-distributions
|
|
62
|
+
path: dist/
|
|
63
|
+
|
|
64
|
+
- name: Publish to PyPI
|
|
65
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Test workflow - runs on push/PR to main
|
|
2
|
+
# Builds and uploads artifacts for reuse by publish workflow
|
|
3
|
+
|
|
4
|
+
name: Test
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main, master]
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main, master]
|
|
11
|
+
workflow_call:
|
|
12
|
+
outputs:
|
|
13
|
+
artifact-name:
|
|
14
|
+
description: "Name of uploaded artifact"
|
|
15
|
+
value: ${{ jobs.build.outputs.artifact-name }}
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
lint:
|
|
22
|
+
name: Lint
|
|
23
|
+
uses: ./.github/workflows/lint.yml
|
|
24
|
+
|
|
25
|
+
test:
|
|
26
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
27
|
+
needs: lint
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
strategy:
|
|
30
|
+
matrix:
|
|
31
|
+
python-version: ["3.11", "3.12"]
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v5
|
|
34
|
+
|
|
35
|
+
- name: Install uv and set up Python ${{ matrix.python-version }}
|
|
36
|
+
uses: astral-sh/setup-uv@v6
|
|
37
|
+
with:
|
|
38
|
+
python-version: ${{ matrix.python-version }}
|
|
39
|
+
|
|
40
|
+
- name: Install dependencies
|
|
41
|
+
run: uv sync --locked
|
|
42
|
+
|
|
43
|
+
- name: Run tests
|
|
44
|
+
run: uv run pytest tests -v
|
|
45
|
+
|
|
46
|
+
build:
|
|
47
|
+
name: Build
|
|
48
|
+
needs: test
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
outputs:
|
|
51
|
+
artifact-name: python-package-distributions
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v5
|
|
54
|
+
with:
|
|
55
|
+
fetch-depth: 0 # Need full history for hatch-vcs
|
|
56
|
+
|
|
57
|
+
- name: Install uv
|
|
58
|
+
uses: astral-sh/setup-uv@v6
|
|
59
|
+
|
|
60
|
+
- name: Set up Python
|
|
61
|
+
uses: actions/setup-python@v6
|
|
62
|
+
with:
|
|
63
|
+
python-version-file: "pyproject.toml"
|
|
64
|
+
|
|
65
|
+
- name: Build package
|
|
66
|
+
run: uv build
|
|
67
|
+
|
|
68
|
+
- name: Upload distributions
|
|
69
|
+
uses: actions/upload-artifact@v5
|
|
70
|
+
with:
|
|
71
|
+
name: python-package-distributions
|
|
72
|
+
path: dist/
|
|
73
|
+
retention-days: 1
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
|
|
28
|
+
# IDE
|
|
29
|
+
.idea/
|
|
30
|
+
.vscode/
|
|
31
|
+
*.swp
|
|
32
|
+
*.swo
|
|
33
|
+
|
|
34
|
+
# Testing
|
|
35
|
+
.pytest_cache/
|
|
36
|
+
.coverage
|
|
37
|
+
htmlcov/
|
|
38
|
+
|
|
39
|
+
# Type checking
|
|
40
|
+
.mypy_cache/
|
|
41
|
+
.pyright/
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Pre-commit hooks configuration
|
|
2
|
+
# Install: uv run pre-commit install --install-hooks
|
|
3
|
+
# Install commit-msg hook: uv run pre-commit install --hook-type commit-msg
|
|
4
|
+
# Run manually: uv run pre-commit run --all-files
|
|
5
|
+
|
|
6
|
+
repos:
|
|
7
|
+
# Standard pre-commit hooks
|
|
8
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
9
|
+
rev: v4.5.0
|
|
10
|
+
hooks:
|
|
11
|
+
- id: check-ast
|
|
12
|
+
- id: check-merge-conflict
|
|
13
|
+
- id: check-case-conflict
|
|
14
|
+
- id: check-docstring-first
|
|
15
|
+
- id: check-toml
|
|
16
|
+
- id: check-yaml
|
|
17
|
+
- id: end-of-file-fixer
|
|
18
|
+
- id: trailing-whitespace
|
|
19
|
+
- id: check-added-large-files
|
|
20
|
+
- id: debug-statements
|
|
21
|
+
- id: name-tests-test
|
|
22
|
+
args: ["--pytest-test-first"]
|
|
23
|
+
|
|
24
|
+
# Gitleaks for secret scanning
|
|
25
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
26
|
+
rev: v8.18.4
|
|
27
|
+
hooks:
|
|
28
|
+
- id: gitleaks
|
|
29
|
+
|
|
30
|
+
# Ruff for linting and formatting
|
|
31
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
32
|
+
rev: v0.8.4
|
|
33
|
+
hooks:
|
|
34
|
+
- id: ruff
|
|
35
|
+
types_or: [python, pyi]
|
|
36
|
+
args: [--fix]
|
|
37
|
+
- id: ruff-format
|
|
38
|
+
types_or: [python, pyi]
|
|
39
|
+
|
|
40
|
+
# Pyright for type checking
|
|
41
|
+
- repo: https://github.com/RobertCraigie/pyright-python
|
|
42
|
+
rev: v1.1.390
|
|
43
|
+
hooks:
|
|
44
|
+
- id: pyright
|
|
45
|
+
additional_dependencies:
|
|
46
|
+
- click>=8.0
|
|
47
|
+
- loguru>=0.7
|
|
48
|
+
- pytest>=7.4.0
|
|
49
|
+
|
|
50
|
+
# Pydoclint for docstring linting (Google style)
|
|
51
|
+
# Disabled for now - too many false positives with internal methods
|
|
52
|
+
# - repo: https://github.com/jsh9/pydoclint
|
|
53
|
+
# rev: 0.5.9
|
|
54
|
+
# hooks:
|
|
55
|
+
# - id: pydoclint
|
|
56
|
+
# args:
|
|
57
|
+
# - --style=google
|
|
58
|
+
# - --check-return-types=False
|
|
59
|
+
# - --arg-type-hints-in-docstring=False
|
|
60
|
+
# - --check-class-attributes=False
|
|
61
|
+
# - --skip-checking-short-docstrings=False
|
|
62
|
+
# - --allow-init-docstring=True
|
|
63
|
+
# exclude: ^(tests/|src/dbxdebug/cli\.py)
|
|
64
|
+
|
|
65
|
+
# Commitizen for commit message linting (Conventional Commits)
|
|
66
|
+
- repo: https://github.com/commitizen-tools/commitizen
|
|
67
|
+
rev: v3.29.1
|
|
68
|
+
hooks:
|
|
69
|
+
- id: commitizen
|
|
70
|
+
stages: [commit-msg]
|
|
71
|
+
|
|
72
|
+
# Actionlint for GitHub Actions workflow linting
|
|
73
|
+
- repo: https://github.com/rhysd/actionlint
|
|
74
|
+
rev: v1.7.4
|
|
75
|
+
hooks:
|
|
76
|
+
- id: actionlint
|
|
77
|
+
|
|
78
|
+
# UV for dependency management - ensures uv.lock is synced
|
|
79
|
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
80
|
+
rev: 0.7.13
|
|
81
|
+
hooks:
|
|
82
|
+
- id: uv-lock
|
dbxdebug-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dbxdebug
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Client library and CLI for DOSBox-X remote debug protocols (GDB and QMP)
|
|
5
|
+
Author: lokkju
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: debugging,dosbox,dosbox-x,emulator,gdb,qmp
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: POSIX
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Software Development :: Debuggers
|
|
16
|
+
Classifier: Topic :: System :: Emulators
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Requires-Dist: click>=8.0
|
|
19
|
+
Requires-Dist: loguru>=0.7
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# dbxdebug
|
|
23
|
+
|
|
24
|
+
Client library and CLI for DOSBox-X remote debug protocols.
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- **GDB Client**: Remote debugging via GDB Remote Serial Protocol
|
|
29
|
+
- Memory read/write
|
|
30
|
+
- Register inspection
|
|
31
|
+
- Breakpoint management
|
|
32
|
+
- Execution control (step, continue, halt)
|
|
33
|
+
|
|
34
|
+
- **QMP Client**: Keyboard input via QEMU Monitor Protocol
|
|
35
|
+
- Key press/release with timing control
|
|
36
|
+
- Text typing with shift handling
|
|
37
|
+
- Key combinations (Ctrl+C, Alt+F4, etc.)
|
|
38
|
+
|
|
39
|
+
- **Video Tools**: DOS text mode screen capture
|
|
40
|
+
- Screen capture (text, raw, HTML)
|
|
41
|
+
- Timed multi-frame recording
|
|
42
|
+
- Color analysis
|
|
43
|
+
- BIOS timer correlation
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uv sync
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## CLI Usage
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
dbxdebug
|
|
55
|
+
├── mem # Memory operations (alias: gdb)
|
|
56
|
+
│ ├── read # Read memory
|
|
57
|
+
│ └── write # Write hex bytes
|
|
58
|
+
│
|
|
59
|
+
├── cpu # CPU and execution control
|
|
60
|
+
│ ├── regs # Display registers
|
|
61
|
+
│ ├── break # Set breakpoint
|
|
62
|
+
│ ├── delete # Remove breakpoint
|
|
63
|
+
│ ├── step # Single step
|
|
64
|
+
│ ├── cont # Continue execution
|
|
65
|
+
│ └── halt # Stop execution
|
|
66
|
+
│
|
|
67
|
+
├── key # Keyboard input (alias: qmp)
|
|
68
|
+
│ ├── send # Key chord (e.g., ctrl c)
|
|
69
|
+
│ ├── type # Type text string
|
|
70
|
+
│ ├── down # Press and hold key
|
|
71
|
+
│ ├── up # Release key
|
|
72
|
+
│ └── list # List QMP commands
|
|
73
|
+
│
|
|
74
|
+
└── screen # Screen capture
|
|
75
|
+
├── show # Display text to stdout
|
|
76
|
+
├── capture # Save frame to file (-f raw|html|text)
|
|
77
|
+
├── record # Multi-frame timed capture
|
|
78
|
+
├── watch # Real-time display
|
|
79
|
+
├── info # Video mode, BIOS ticks
|
|
80
|
+
└── colors # Analyze color palette
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Examples
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Memory
|
|
87
|
+
dbxdebug mem read b800:0000 4000 --hex
|
|
88
|
+
dbxdebug mem write 0x1000 90909090
|
|
89
|
+
|
|
90
|
+
# CPU / Debugging
|
|
91
|
+
dbxdebug cpu regs
|
|
92
|
+
dbxdebug cpu break 0x1000
|
|
93
|
+
dbxdebug cpu step
|
|
94
|
+
dbxdebug cpu cont
|
|
95
|
+
|
|
96
|
+
# Keyboard
|
|
97
|
+
dbxdebug key send a
|
|
98
|
+
dbxdebug key send ctrl c
|
|
99
|
+
dbxdebug key send ctrl alt delete
|
|
100
|
+
dbxdebug key type "Hello World!"
|
|
101
|
+
|
|
102
|
+
# Screen
|
|
103
|
+
dbxdebug screen show
|
|
104
|
+
dbxdebug screen capture -f html -o snapshot
|
|
105
|
+
dbxdebug screen record -d 60 -r 30 -o session.capture.gz
|
|
106
|
+
dbxdebug screen watch
|
|
107
|
+
dbxdebug screen colors
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Library Usage
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from dbxdebug import (
|
|
114
|
+
GDBClient, QMPClient, DOSVideoTools,
|
|
115
|
+
ScreenRecorder, load_capture,
|
|
116
|
+
ctrl_key, CTRL_C, DBX_KEY,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Memory and debugging
|
|
120
|
+
with GDBClient() as gdb:
|
|
121
|
+
regs = gdb.read_registers()
|
|
122
|
+
mem = gdb.read_memory("b800:0000", 4000)
|
|
123
|
+
gdb.write_memory(0x1000, b"\x90\x90")
|
|
124
|
+
gdb.set_breakpoint(0x1000)
|
|
125
|
+
gdb.step()
|
|
126
|
+
gdb.continue_execution()
|
|
127
|
+
|
|
128
|
+
# Keyboard input
|
|
129
|
+
with QMPClient() as qmp:
|
|
130
|
+
qmp.send_key(["ctrl", "c"]) # Key chord
|
|
131
|
+
qmp.send_key(CTRL_C) # Using constant
|
|
132
|
+
qmp.type_text("Hello World!") # Type string
|
|
133
|
+
qmp.key_down("shift") # Hold key
|
|
134
|
+
qmp.key_up("shift") # Release key
|
|
135
|
+
|
|
136
|
+
# Screen capture
|
|
137
|
+
with DOSVideoTools() as video:
|
|
138
|
+
lines = video.screen_dump() # Text lines
|
|
139
|
+
raw = video.screen_raw() # Raw bytes with attrs
|
|
140
|
+
lines, ticks = video.screen_dump_with_ticks()
|
|
141
|
+
|
|
142
|
+
# Timed recording
|
|
143
|
+
with DOSVideoTools() as video:
|
|
144
|
+
recorder = ScreenRecorder()
|
|
145
|
+
recorder.record(video, duration=10.0, sample_rate=50)
|
|
146
|
+
recorder.save("session.capture.gz")
|
|
147
|
+
|
|
148
|
+
# Load and analyze capture
|
|
149
|
+
data = load_capture("session.capture.gz")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Ports
|
|
153
|
+
|
|
154
|
+
| Protocol | Default Port | Purpose |
|
|
155
|
+
|----------|--------------|---------|
|
|
156
|
+
| GDB | 2159 | Debugging, memory access |
|
|
157
|
+
| QMP | 4444 | Keyboard input |
|
|
158
|
+
|
|
159
|
+
Enable in DOSBox-X config:
|
|
160
|
+
```ini
|
|
161
|
+
[dosbox]
|
|
162
|
+
gdbserver=true
|
|
163
|
+
qmpserver=true
|
|
164
|
+
```
|
dbxdebug-0.2.1/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# dbxdebug
|
|
2
|
+
|
|
3
|
+
Client library and CLI for DOSBox-X remote debug protocols.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **GDB Client**: Remote debugging via GDB Remote Serial Protocol
|
|
8
|
+
- Memory read/write
|
|
9
|
+
- Register inspection
|
|
10
|
+
- Breakpoint management
|
|
11
|
+
- Execution control (step, continue, halt)
|
|
12
|
+
|
|
13
|
+
- **QMP Client**: Keyboard input via QEMU Monitor Protocol
|
|
14
|
+
- Key press/release with timing control
|
|
15
|
+
- Text typing with shift handling
|
|
16
|
+
- Key combinations (Ctrl+C, Alt+F4, etc.)
|
|
17
|
+
|
|
18
|
+
- **Video Tools**: DOS text mode screen capture
|
|
19
|
+
- Screen capture (text, raw, HTML)
|
|
20
|
+
- Timed multi-frame recording
|
|
21
|
+
- Color analysis
|
|
22
|
+
- BIOS timer correlation
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv sync
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## CLI Usage
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
dbxdebug
|
|
34
|
+
├── mem # Memory operations (alias: gdb)
|
|
35
|
+
│ ├── read # Read memory
|
|
36
|
+
│ └── write # Write hex bytes
|
|
37
|
+
│
|
|
38
|
+
├── cpu # CPU and execution control
|
|
39
|
+
│ ├── regs # Display registers
|
|
40
|
+
│ ├── break # Set breakpoint
|
|
41
|
+
│ ├── delete # Remove breakpoint
|
|
42
|
+
│ ├── step # Single step
|
|
43
|
+
│ ├── cont # Continue execution
|
|
44
|
+
│ └── halt # Stop execution
|
|
45
|
+
│
|
|
46
|
+
├── key # Keyboard input (alias: qmp)
|
|
47
|
+
│ ├── send # Key chord (e.g., ctrl c)
|
|
48
|
+
│ ├── type # Type text string
|
|
49
|
+
│ ├── down # Press and hold key
|
|
50
|
+
│ ├── up # Release key
|
|
51
|
+
│ └── list # List QMP commands
|
|
52
|
+
│
|
|
53
|
+
└── screen # Screen capture
|
|
54
|
+
├── show # Display text to stdout
|
|
55
|
+
├── capture # Save frame to file (-f raw|html|text)
|
|
56
|
+
├── record # Multi-frame timed capture
|
|
57
|
+
├── watch # Real-time display
|
|
58
|
+
├── info # Video mode, BIOS ticks
|
|
59
|
+
└── colors # Analyze color palette
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Examples
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Memory
|
|
66
|
+
dbxdebug mem read b800:0000 4000 --hex
|
|
67
|
+
dbxdebug mem write 0x1000 90909090
|
|
68
|
+
|
|
69
|
+
# CPU / Debugging
|
|
70
|
+
dbxdebug cpu regs
|
|
71
|
+
dbxdebug cpu break 0x1000
|
|
72
|
+
dbxdebug cpu step
|
|
73
|
+
dbxdebug cpu cont
|
|
74
|
+
|
|
75
|
+
# Keyboard
|
|
76
|
+
dbxdebug key send a
|
|
77
|
+
dbxdebug key send ctrl c
|
|
78
|
+
dbxdebug key send ctrl alt delete
|
|
79
|
+
dbxdebug key type "Hello World!"
|
|
80
|
+
|
|
81
|
+
# Screen
|
|
82
|
+
dbxdebug screen show
|
|
83
|
+
dbxdebug screen capture -f html -o snapshot
|
|
84
|
+
dbxdebug screen record -d 60 -r 30 -o session.capture.gz
|
|
85
|
+
dbxdebug screen watch
|
|
86
|
+
dbxdebug screen colors
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Library Usage
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from dbxdebug import (
|
|
93
|
+
GDBClient, QMPClient, DOSVideoTools,
|
|
94
|
+
ScreenRecorder, load_capture,
|
|
95
|
+
ctrl_key, CTRL_C, DBX_KEY,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# Memory and debugging
|
|
99
|
+
with GDBClient() as gdb:
|
|
100
|
+
regs = gdb.read_registers()
|
|
101
|
+
mem = gdb.read_memory("b800:0000", 4000)
|
|
102
|
+
gdb.write_memory(0x1000, b"\x90\x90")
|
|
103
|
+
gdb.set_breakpoint(0x1000)
|
|
104
|
+
gdb.step()
|
|
105
|
+
gdb.continue_execution()
|
|
106
|
+
|
|
107
|
+
# Keyboard input
|
|
108
|
+
with QMPClient() as qmp:
|
|
109
|
+
qmp.send_key(["ctrl", "c"]) # Key chord
|
|
110
|
+
qmp.send_key(CTRL_C) # Using constant
|
|
111
|
+
qmp.type_text("Hello World!") # Type string
|
|
112
|
+
qmp.key_down("shift") # Hold key
|
|
113
|
+
qmp.key_up("shift") # Release key
|
|
114
|
+
|
|
115
|
+
# Screen capture
|
|
116
|
+
with DOSVideoTools() as video:
|
|
117
|
+
lines = video.screen_dump() # Text lines
|
|
118
|
+
raw = video.screen_raw() # Raw bytes with attrs
|
|
119
|
+
lines, ticks = video.screen_dump_with_ticks()
|
|
120
|
+
|
|
121
|
+
# Timed recording
|
|
122
|
+
with DOSVideoTools() as video:
|
|
123
|
+
recorder = ScreenRecorder()
|
|
124
|
+
recorder.record(video, duration=10.0, sample_rate=50)
|
|
125
|
+
recorder.save("session.capture.gz")
|
|
126
|
+
|
|
127
|
+
# Load and analyze capture
|
|
128
|
+
data = load_capture("session.capture.gz")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Ports
|
|
132
|
+
|
|
133
|
+
| Protocol | Default Port | Purpose |
|
|
134
|
+
|----------|--------------|---------|
|
|
135
|
+
| GDB | 2159 | Debugging, memory access |
|
|
136
|
+
| QMP | 4444 | Keyboard input |
|
|
137
|
+
|
|
138
|
+
Enable in DOSBox-X config:
|
|
139
|
+
```ini
|
|
140
|
+
[dosbox]
|
|
141
|
+
gdbserver=true
|
|
142
|
+
qmpserver=true
|
|
143
|
+
```
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dbxdebug"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "Client library and CLI for DOSBox-X remote debug protocols (GDB and QMP)"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "lokkju" }
|
|
10
|
+
]
|
|
11
|
+
keywords = ["dosbox", "dosbox-x", "debugging", "gdb", "qmp", "emulator"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Environment :: Console",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: POSIX",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Topic :: Software Development :: Debuggers",
|
|
21
|
+
"Topic :: System :: Emulators",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"click>=8.0",
|
|
25
|
+
"loguru>=0.7",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
dbxdebug = "dbxdebug.cli:main"
|
|
30
|
+
|
|
31
|
+
[dependency-groups]
|
|
32
|
+
dev = [
|
|
33
|
+
"pytest>=7.4.0",
|
|
34
|
+
"pytest-cov>=4.1.0",
|
|
35
|
+
"ruff>=0.8.0",
|
|
36
|
+
"pyright>=1.1.0",
|
|
37
|
+
"pre-commit>=3.5.0",
|
|
38
|
+
"commitizen>=3.29.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[build-system]
|
|
42
|
+
requires = ["hatchling", "hatch-vcs"]
|
|
43
|
+
build-backend = "hatchling.build"
|
|
44
|
+
|
|
45
|
+
[tool.hatch.version]
|
|
46
|
+
source = "vcs"
|
|
47
|
+
|
|
48
|
+
[tool.hatch.build.targets.wheel]
|
|
49
|
+
packages = ["src/dbxdebug"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
|
|
54
|
+
[tool.ruff]
|
|
55
|
+
line-length = 100
|
|
56
|
+
target-version = "py311"
|
|
57
|
+
|
|
58
|
+
[tool.ruff.lint]
|
|
59
|
+
select = [
|
|
60
|
+
"E", # pycodestyle errors
|
|
61
|
+
"W", # pycodestyle warnings
|
|
62
|
+
"F", # pyflakes
|
|
63
|
+
"I", # isort
|
|
64
|
+
"UP", # pyupgrade
|
|
65
|
+
"B", # flake8-bugbear
|
|
66
|
+
"C4", # flake8-comprehensions
|
|
67
|
+
"ARG", # flake8-unused-arguments
|
|
68
|
+
"SIM", # flake8-simplify
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
[tool.ruff.format]
|
|
72
|
+
quote-style = "double"
|
|
73
|
+
indent-style = "space"
|
|
74
|
+
|
|
75
|
+
[tool.pyright]
|
|
76
|
+
include = ["src/dbxdebug", "tests"]
|
|
77
|
+
exclude = [".venv", "**/__pycache__"]
|
|
78
|
+
pythonVersion = "3.11"
|
|
79
|
+
typeCheckingMode = "basic"
|
|
80
|
+
reportMissingTypeStubs = false
|
|
81
|
+
|
|
82
|
+
[tool.commitizen]
|
|
83
|
+
name = "cz_conventional_commits"
|
|
84
|
+
tag_format = "v$version"
|
|
85
|
+
version_scheme = "pep440"
|
|
86
|
+
version_provider = "scm" # Read current version from git tags
|
|
87
|
+
major_version_zero = true # Allow breaking changes in 0.x without major bump
|
|
88
|
+
# Use `cz bump --dry-run` to calculate next version from commits
|
|
89
|
+
# Then `git tag v<version>` - hatch-vcs uses the tag for package version
|