Skip to content

Commit 08c7562

Browse files
committed
feat: a DSP-2 model with its commands proved rather than sampled
The chip shipped in one cartridge, so there is no published per-instruction suite and there never will be. The usual answer is to replay a recording of the real hardware, which works and has a ceiling: it only covers what that one game asked for, and the bytes it returns are the game's artwork, so the recording cannot be distributed. So the commands are split from the protocol that feeds them and proved directly. The tile conversion is a permutation of the 256 bits it is given, which 256 single bit inputs settle completely. The merge is a per-nibble rule checked over every input it accepts. The multiply is checked against arithmetic. The recording still has a job. This model agrees byte for byte with the implementation that reproduced 71,970,987 bytes of recorded traffic with zero errors, over 1,139,246 reads of randomised streams reaching lengths the game never used. The parameter RAM no longer starts at zero. The chip never clears it and the rescale reads past its own data straight into it, so a zeroed start hides every one of those reads. An earlier version padded with zeroes and agreed with the recordings anyway, because there those reads happened to land on bytes that were still zero.
0 parents  commit 08c7562

23 files changed

Lines changed: 4491 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
concurrency:
13+
group: ci-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
env:
17+
PYTHON_VERSION: "3.12"
18+
19+
jobs:
20+
lint:
21+
name: Format and lint
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v5
25+
26+
- uses: actions/setup-python@v6
27+
with:
28+
python-version: ${{ env.PYTHON_VERSION }}
29+
30+
- name: Install ruff
31+
run: pipx install ruff==0.16.3
32+
33+
- name: Check formatting
34+
run: ruff format --check .
35+
36+
- name: Lint
37+
run: ruff check --output-format=github .
38+
39+
test:
40+
name: Tests on Python ${{ matrix.python }}
41+
runs-on: ubuntu-latest
42+
strategy:
43+
fail-fast: false
44+
matrix:
45+
python: ["3.12", "3.13", "3.14"]
46+
steps:
47+
- uses: actions/checkout@v5
48+
49+
- uses: actions/setup-python@v6
50+
with:
51+
python-version: ${{ matrix.python }}
52+
53+
- name: Install coverage
54+
run: python -m pip install --disable-pip-version-check coverage==7.6.10
55+
56+
- name: Run every test file, under coverage
57+
run: |
58+
python -m coverage erase
59+
status=0
60+
while IFS= read -r file; do
61+
echo "::group::${file}"
62+
python -m coverage run -a "${file}" || status=1
63+
echo "::endgroup::"
64+
done < <(find dsp2 conformance -name '*.test.py' | sort)
65+
exit "${status}"
66+
shell: bash
67+
68+
- name: Coverage must be total
69+
run: python -m coverage report

.github/workflows/release.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Release
2+
3+
on:
4+
workflow_run:
5+
workflows: [CI]
6+
branches: [main]
7+
types: [completed]
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: write
12+
issues: write
13+
pull-requests: write
14+
id-token: write
15+
16+
concurrency:
17+
group: release
18+
cancel-in-progress: false
19+
20+
jobs:
21+
release:
22+
name: Semantic release
23+
if: >-
24+
github.event_name == 'workflow_dispatch' ||
25+
github.event.workflow_run.conclusion == 'success'
26+
runs-on: ubuntu-latest
27+
steps:
28+
- uses: actions/checkout@v5
29+
with:
30+
fetch-depth: 0
31+
persist-credentials: false
32+
33+
- uses: pnpm/action-setup@v6
34+
35+
- uses: actions/setup-node@v6
36+
with:
37+
node-version: "22"
38+
cache: pnpm
39+
40+
- uses: actions/setup-python@v6
41+
with:
42+
python-version: "3.12"
43+
44+
- name: Install release tooling
45+
run: pnpm install --frozen-lockfile --ignore-scripts
46+
47+
- name: Release
48+
env:
49+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50+
run: pnpm exec semantic-release

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
__pycache__/
2+
.ruff_cache/
3+
.coverage
4+
coverage.json
5+
node_modules/
6+
dist/
7+
build/
8+
*.egg-info/
9+
.DS_Store

.releaserc.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"branches": ["main"],
3+
"plugins": [
4+
"@semantic-release/commit-analyzer",
5+
"@semantic-release/release-notes-generator",
6+
[
7+
"@semantic-release/exec",
8+
{
9+
"prepareCmd": "bash scripts/set-version.sh ${nextRelease.version}"
10+
}
11+
],
12+
[
13+
"@semantic-release/git",
14+
{
15+
"assets": ["dsp2/version.py"],
16+
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
17+
}
18+
],
19+
"@semantic-release/github"
20+
]
21+
}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Gustavo Franco
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)