gsasm 0.2.0__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.
- gsasm-0.2.0/.forgejo/workflows/tests.yml +27 -0
- gsasm-0.2.0/.github/workflows/publish.yml +44 -0
- gsasm-0.2.0/.gitignore +26 -0
- gsasm-0.2.0/LICENSE +21 -0
- gsasm-0.2.0/PKG-INFO +287 -0
- gsasm-0.2.0/README.md +243 -0
- gsasm-0.2.0/docs/GSOS_MILESTONES.md +153 -0
- gsasm-0.2.0/docs/RESULTS.md +92 -0
- gsasm-0.2.0/docs/REZ_REVIEW_2026-07-14.md +215 -0
- gsasm-0.2.0/docs/TODO.md +98 -0
- gsasm-0.2.0/docs/design/P3_DECOMPOSE.md +81 -0
- gsasm-0.2.0/docs/design/README.md +101 -0
- gsasm-0.2.0/docs/design/expressload.md +194 -0
- gsasm-0.2.0/docs/design/linkiigs.md +99 -0
- gsasm-0.2.0/docs/design/makebin.md +83 -0
- gsasm-0.2.0/docs/design/rez.md +342 -0
- gsasm-0.2.0/gsasm/__init__.py +0 -0
- gsasm-0.2.0/gsasm/__main__.py +307 -0
- gsasm-0.2.0/gsasm/asm.py +2683 -0
- gsasm-0.2.0/gsasm/expr.py +241 -0
- gsasm-0.2.0/gsasm/expressload.py +1240 -0
- gsasm-0.2.0/gsasm/link.py +243 -0
- gsasm-0.2.0/gsasm/linkiigs.py +782 -0
- gsasm-0.2.0/gsasm/m65816.py +425 -0
- gsasm-0.2.0/gsasm/makebin.py +197 -0
- gsasm-0.2.0/gsasm/omf.py +1108 -0
- gsasm-0.2.0/gsasm/rez/__init__.py +69 -0
- gsasm-0.2.0/gsasm/rez/convert.py +47 -0
- gsasm-0.2.0/gsasm/rez/emit.py +310 -0
- gsasm-0.2.0/gsasm/rez/gen.py +1271 -0
- gsasm-0.2.0/gsasm/rez/lexer.py +670 -0
- gsasm-0.2.0/gsasm/rez/parser.py +963 -0
- gsasm-0.2.0/pyproject.toml +38 -0
- gsasm-0.2.0/tests/README.md +64 -0
- gsasm-0.2.0/tests/fixtures/001-basic-code/expected.dump +7 -0
- gsasm-0.2.0/tests/fixtures/001-basic-code/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/001-basic-code/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/001-basic-code/input.asm +13 -0
- gsasm-0.2.0/tests/fixtures/002-dcw-string-padding/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/002-dcw-string-padding/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/002-dcw-string-padding/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/002-dcw-string-padding/input.asm +12 -0
- gsasm-0.2.0/tests/fixtures/003-dcb-string-fill/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/003-dcb-string-fill/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/003-dcb-string-fill/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/003-dcb-string-fill/input.asm +9 -0
- gsasm-0.2.0/tests/fixtures/004-dollar-in-identifier/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/004-dollar-in-identifier/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/004-dollar-in-identifier/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/004-dollar-in-identifier/input.asm +10 -0
- gsasm-0.2.0/tests/fixtures/005-if-and-or-bitwise/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/005-if-and-or-bitwise/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/005-if-and-or-bitwise/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/005-if-and-or-bitwise/input.asm +19 -0
- gsasm-0.2.0/tests/fixtures/006-backslash-continuation/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/006-backslash-continuation/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/006-backslash-continuation/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/006-backslash-continuation/input.asm +11 -0
- gsasm-0.2.0/tests/fixtures/007-expr-continues-whitespace/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/007-expr-continues-whitespace/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/007-expr-continues-whitespace/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/007-expr-continues-whitespace/input.asm +11 -0
- gsasm-0.2.0/tests/fixtures/008-doubled-quote-escape/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/008-doubled-quote-escape/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/008-doubled-quote-escape/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/008-doubled-quote-escape/input.asm +7 -0
- gsasm-0.2.0/tests/fixtures/009-case-on/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/009-case-on/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/009-case-on/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/009-case-on/input.asm +11 -0
- gsasm-0.2.0/tests/fixtures/010-case-off-default/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/010-case-off-default/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/010-case-off-default/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/010-case-off-default/input.asm +9 -0
- gsasm-0.2.0/tests/fixtures/011-record-typed-ds/expected.dump +10 -0
- gsasm-0.2.0/tests/fixtures/011-record-typed-ds/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/011-record-typed-ds/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/011-record-typed-ds/input.asm +16 -0
- gsasm-0.2.0/tests/fixtures/012-record-field-vs-import/expected.dump +6 -0
- gsasm-0.2.0/tests/fixtures/012-record-field-vs-import/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/012-record-field-vs-import/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/012-record-field-vs-import/input.asm +14 -0
- gsasm-0.2.0/tests/fixtures/013-import-comma-list/expected.dump +7 -0
- gsasm-0.2.0/tests/fixtures/013-import-comma-list/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/013-import-comma-list/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/013-import-comma-list/input.asm +9 -0
- gsasm-0.2.0/tests/fixtures/014-import-plus-const/expected.dump +6 -0
- gsasm-0.2.0/tests/fixtures/014-import-plus-const/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/014-import-plus-const/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/014-import-plus-const/input.asm +10 -0
- gsasm-0.2.0/tests/fixtures/015-extern-diff-immediate/expected.dump +6 -0
- gsasm-0.2.0/tests/fixtures/015-extern-diff-immediate/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/015-extern-diff-immediate/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/015-extern-diff-immediate/input.asm +9 -0
- gsasm-0.2.0/tests/fixtures/016-pcrel-same-seg-literal/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/016-pcrel-same-seg-literal/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/016-pcrel-same-seg-literal/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/016-pcrel-same-seg-literal/input.asm +12 -0
- gsasm-0.2.0/tests/fixtures/017-equ-alias-relocatable/expected.dump +8 -0
- gsasm-0.2.0/tests/fixtures/017-equ-alias-relocatable/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/017-equ-alias-relocatable/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/017-equ-alias-relocatable/input.asm +12 -0
- gsasm-0.2.0/tests/fixtures/018-proc-temporg/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/018-proc-temporg/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/018-proc-temporg/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/018-proc-temporg/input.asm +10 -0
- gsasm-0.2.0/tests/fixtures/019-seg-loadname-persists/expected.dump +13 -0
- gsasm-0.2.0/tests/fixtures/019-seg-loadname-persists/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/019-seg-loadname-persists/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/019-seg-loadname-persists/input.asm +16 -0
- gsasm-0.2.0/tests/fixtures/020-approx-ones-complement/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/020-approx-ones-complement/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/020-approx-ones-complement/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/020-approx-ones-complement/input.asm +10 -0
- gsasm-0.2.0/tests/fixtures/021-sysdate-injection/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/021-sysdate-injection/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/021-sysdate-injection/fixture.json +6 -0
- gsasm-0.2.0/tests/fixtures/021-sysdate-injection/input.asm +7 -0
- gsasm-0.2.0/tests/fixtures/022-high-bank-immediate-link/expected.dump +10 -0
- gsasm-0.2.0/tests/fixtures/022-high-bank-immediate-link/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/022-high-bank-immediate-link/expected.out +0 -0
- gsasm-0.2.0/tests/fixtures/022-high-bank-immediate-link/expected.out.dump +5 -0
- gsasm-0.2.0/tests/fixtures/022-high-bank-immediate-link/fixture.json +5 -0
- gsasm-0.2.0/tests/fixtures/022-high-bank-immediate-link/input.asm +11 -0
- gsasm-0.2.0/tests/fixtures/023-endproc-synonym/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/023-endproc-synonym/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/023-endproc-synonym/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/023-endproc-synonym/input.asm +6 -0
- gsasm-0.2.0/tests/fixtures/024-operand-const-atomic/expected.dump +7 -0
- gsasm-0.2.0/tests/fixtures/024-operand-const-atomic/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/024-operand-const-atomic/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/024-operand-const-atomic/input.asm +517 -0
- gsasm-0.2.0/tests/fixtures/025-mvn-operand-order/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/025-mvn-operand-order/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/025-mvn-operand-order/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/025-mvn-operand-order/input.asm +9 -0
- gsasm-0.2.0/tests/fixtures/026-tsa-tas-aliases/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/026-tsa-tas-aliases/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/026-tsa-tas-aliases/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/026-tsa-tas-aliases/input.asm +13 -0
- gsasm-0.2.0/tests/fixtures/027-endfunc-synonym/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/027-endfunc-synonym/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/027-endfunc-synonym/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/027-endfunc-synonym/input.asm +9 -0
- gsasm-0.2.0/tests/fixtures/028-len-literal-vs-substituted/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/028-len-literal-vs-substituted/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/028-len-literal-vs-substituted/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/028-len-literal-vs-substituted/input.asm +20 -0
- gsasm-0.2.0/tests/fixtures/029-nested-record-fields/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/029-nested-record-fields/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/029-nested-record-fields/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/029-nested-record-fields/input.asm +26 -0
- gsasm-0.2.0/tests/fixtures/030-name-macro-at-label-scope/expected.dump +5 -0
- gsasm-0.2.0/tests/fixtures/030-name-macro-at-label-scope/expected.obj +0 -0
- gsasm-0.2.0/tests/fixtures/030-name-macro-at-label-scope/fixture.json +4 -0
- gsasm-0.2.0/tests/fixtures/030-name-macro-at-label-scope/input.asm +52 -0
- gsasm-0.2.0/tests/omfdump.py +94 -0
- gsasm-0.2.0/tests/run_fixtures.py +157 -0
- gsasm-0.2.0/tests/test_branch_range.py +196 -0
- gsasm-0.2.0/tests/test_expressload_case_b.py +249 -0
- gsasm-0.2.0/tests/test_linkiigs_super_type26.py +148 -0
- gsasm-0.2.0/tests/test_rez_gen.py +776 -0
- gsasm-0.2.0/tests/test_rez_lexer.py +250 -0
- gsasm-0.2.0/tests/test_rez_parser.py +343 -0
- gsasm-0.2.0/tests/test_rez_pipeline.py +279 -0
- gsasm-0.2.0/work/buildrom.py +140 -0
- gsasm-0.2.0/work/bytecheck.py +114 -0
- gsasm-0.2.0/work/diskbuilders/__init__.py +32 -0
- gsasm-0.2.0/work/diskbuilders/expressload_files.py +458 -0
- gsasm-0.2.0/work/diskbuilders/kernel_os.py +298 -0
- gsasm-0.2.0/work/diskbuilders/kernel_setup.py +177 -0
- gsasm-0.2.0/work/diskbuilders/p8_driver.py +317 -0
- gsasm-0.2.0/work/diskbuilders/toolsets.py +380 -0
- gsasm-0.2.0/work/diskcheck.py +400 -0
- gsasm-0.2.0/work/drivercheck.py +345 -0
- gsasm-0.2.0/work/easymountcheck.py +306 -0
- gsasm-0.2.0/work/fstcheck.py +240 -0
- gsasm-0.2.0/work/gate.py +163 -0
- gsasm-0.2.0/work/gate_baseline.json +50 -0
- gsasm-0.2.0/work/generality_check.py +132 -0
- gsasm-0.2.0/work/hfs.py +127 -0
- gsasm-0.2.0/work/kernelcheck.py +984 -0
- gsasm-0.2.0/work/linkcheck.py +175 -0
- gsasm-0.2.0/work/linkrom.py +279 -0
- gsasm-0.2.0/work/loader_placed.py +87 -0
- gsasm-0.2.0/work/loader_residual.py +83 -0
- gsasm-0.2.0/work/mpwmake_probe.py +359 -0
- gsasm-0.2.0/work/objcheck.py +74 -0
- gsasm-0.2.0/work/p3_oracle.py +405 -0
- gsasm-0.2.0/work/probootcheck.py +147 -0
- gsasm-0.2.0/work/profst_diag.py +220 -0
- gsasm-0.2.0/work/recmap.py +98 -0
- gsasm-0.2.0/work/reloc_diag.py +141 -0
- gsasm-0.2.0/work/reloc_survey.py +220 -0
- gsasm-0.2.0/work/rezbuildcheck.py +201 -0
- gsasm-0.2.0/work/rezcheck.py +383 -0
- gsasm-0.2.0/work/rezemitcheck.py +121 -0
- gsasm-0.2.0/work/rezgencheck.py +159 -0
- gsasm-0.2.0/work/rezlexcheck.py +73 -0
- gsasm-0.2.0/work/rezloadcheck.py +291 -0
- gsasm-0.2.0/work/rezparsecheck.py +169 -0
- gsasm-0.2.0/work/romcov.py +64 -0
- gsasm-0.2.0/work/segdiff.py +73 -0
- gsasm-0.2.0/work/startgsos_diag.py +118 -0
- gsasm-0.2.0/work/toolcheck.py +331 -0
- gsasm-0.2.0/work/toolsetup_probe.py +84 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
fixtures:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.9", "3.12", "3.14"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: ${{ matrix.python-version }}
|
|
19
|
+
- name: Run fixture suite
|
|
20
|
+
run: python3 tests/run_fixtures.py
|
|
21
|
+
- name: Run corpus-free test suites
|
|
22
|
+
run: |
|
|
23
|
+
set -e
|
|
24
|
+
for t in tests/test_*.py; do
|
|
25
|
+
echo "== $t"
|
|
26
|
+
python3 "$t"
|
|
27
|
+
done
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Publish gsasm to PyPI via Trusted Publisher (OIDC) on version tags.
|
|
2
|
+
# Requires the repo to be registered as a Trusted Publisher on pypi.org
|
|
3
|
+
# (project: gsasm, owner: emdeejay, repo: gsasm, workflow: publish.yml).
|
|
4
|
+
name: publish
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
tags: ["v*"]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.12"
|
|
18
|
+
- name: Fixture suite
|
|
19
|
+
run: python3 tests/run_fixtures.py
|
|
20
|
+
- name: Corpus-free test suites
|
|
21
|
+
run: |
|
|
22
|
+
set -e
|
|
23
|
+
for t in tests/test_*.py; do
|
|
24
|
+
echo "== $t"
|
|
25
|
+
python3 "$t"
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
publish:
|
|
29
|
+
needs: test
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
environment: pypi
|
|
32
|
+
permissions:
|
|
33
|
+
id-token: write
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
- uses: actions/setup-python@v5
|
|
37
|
+
with:
|
|
38
|
+
python-version: "3.12"
|
|
39
|
+
- name: Build sdist and wheel
|
|
40
|
+
run: |
|
|
41
|
+
python3 -m pip install build
|
|
42
|
+
python3 -m build
|
|
43
|
+
- name: Publish to PyPI
|
|
44
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
gsasm-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# build / packaging
|
|
2
|
+
dist/
|
|
3
|
+
*.egg-info/
|
|
4
|
+
build/
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.pyc
|
|
7
|
+
*.pyo
|
|
8
|
+
.DS_Store
|
|
9
|
+
|
|
10
|
+
# extracted Apple ROM source and includes (must be supplied separately)
|
|
11
|
+
work/romsrc/
|
|
12
|
+
work/includes/
|
|
13
|
+
work/rincludes/
|
|
14
|
+
work/txt/
|
|
15
|
+
|
|
16
|
+
# linker working directory (generated artifacts)
|
|
17
|
+
work/link/
|
|
18
|
+
|
|
19
|
+
# built ROM images
|
|
20
|
+
work/*.built
|
|
21
|
+
work/*.bin
|
|
22
|
+
work/*.img
|
|
23
|
+
|
|
24
|
+
# reference materials (copyrighted Apple disk images, PDFs, ROM files)
|
|
25
|
+
ref/
|
|
26
|
+
.claude/
|
gsasm-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Matt Jenkins
|
|
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.
|
gsasm-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gsasm
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Clean-room MPW IIgs toolchain in Python: 65816 assembler, OMF linker, Rez resource compiler
|
|
5
|
+
Project-URL: Homepage, https://github.com/emdeejay/gsasm
|
|
6
|
+
Project-URL: Repository, https://github.com/emdeejay/gsasm
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2024 Matt Jenkins
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Keywords: 65816,apple2gs,assembler,omf,retro
|
|
30
|
+
Classifier: Development Status :: 4 - Beta
|
|
31
|
+
Classifier: Intended Audience :: Developers
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
40
|
+
Classifier: Topic :: Software Development :: Assemblers
|
|
41
|
+
Classifier: Topic :: System :: Emulators
|
|
42
|
+
Requires-Python: >=3.9
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
45
|
+
# gsasm
|
|
46
|
+
|
|
47
|
+
A clean-room Python reimplementation of the **MPW IIgs cross-development
|
|
48
|
+
toolchain** — the `AsmIIgs` assembler, `LinkIIgs` linker, the `RezIIgs`
|
|
49
|
+
resource compiler, the `MakeBinIIgs`/`OverlayIIgs`/`catenate` packagers, and
|
|
50
|
+
the `ExpressLoad` relinker — validated byte-for-byte against the Apple IIgs
|
|
51
|
+
ROM 03 and the GS/OS System 6.0.1 shipping binaries.
|
|
52
|
+
|
|
53
|
+
Apple built the IIgs ROM and GS/OS on a 68k Mac under MPW Shell. Running that
|
|
54
|
+
chain today means SheepShaver → a Mac OS 7 image → MPW → the GS cross-tools.
|
|
55
|
+
`gsasm` replaces it with pure Python — no emulator, no dependencies outside
|
|
56
|
+
the standard library.
|
|
57
|
+
|
|
58
|
+
## Results
|
|
59
|
+
|
|
60
|
+
Rebuilt from the original source and verified byte-identical to the shipping
|
|
61
|
+
binaries:
|
|
62
|
+
|
|
63
|
+
- **ROM 03** — all 262,144 bytes
|
|
64
|
+
- **All 7 buildable FSTs** (ProDOS, HFS, Char, High Sierra, DOS 3.3, Pascal,
|
|
65
|
+
MS-DOS) and **11 of 12 device drivers**
|
|
66
|
+
- **`prodos`, `Start.GS.OS`, `Error.Msg`, the GS/OS Loader**, `Tool014`
|
|
67
|
+
(Window Manager), and 19 of the 30 System 6.0.1 files the disk harness
|
|
68
|
+
rebuilds
|
|
69
|
+
- **Resource forks** (`gsrez`): `Sys.Resources` (24,337 bytes, 143 resources
|
|
70
|
+
including embedded code resources) and `EasyMount` — the latter byte-exact
|
|
71
|
+
across **both** forks, code and resources, from source to shipping file
|
|
72
|
+
- **Instruction encoding: 100%** — every instruction in the ~97,000-line
|
|
73
|
+
corpus encodes to the same bytes as the original listings
|
|
74
|
+
- **61/61 ROM objects link-identical** — for every module, linking `gsasm`'s
|
|
75
|
+
object or Apple's original produces the same load image
|
|
76
|
+
|
|
77
|
+
`GS.OS` itself reaches 38,711 of 38,805 bytes (99.76%); the residual 94 bytes
|
|
78
|
+
reference symbols that exist nowhere in the source archive, so a byte-exact
|
|
79
|
+
build is provably out of reach from these sources. The other shortfalls have
|
|
80
|
+
similarly settled causes (a source-revision skew, a converter whose output
|
|
81
|
+
isn't a function of its input, missing sources). The full accounting, with
|
|
82
|
+
evidence for each limit, is in [docs/RESULTS.md](docs/RESULTS.md).
|
|
83
|
+
|
|
84
|
+
## Install
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
pip install git+https://github.com/emdeejay/gsasm.git
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Or install from a local clone in editable mode:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
git clone https://github.com/emdeejay/gsasm.git
|
|
94
|
+
cd gsasm
|
|
95
|
+
pip install -e .
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Requires Python 3.9+. No dependencies outside the standard library.
|
|
99
|
+
|
|
100
|
+
## CLI
|
|
101
|
+
|
|
102
|
+
### gsasm — assembler
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
gsasm <source.asm> [-I <incdir>] [-d KEY=VAL] [-o <out.obj>]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Assembles an MPW IIgs-dialect 65816 source file and writes an OMF v2 object file.
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
# assemble a single file
|
|
112
|
+
gsasm MyTool.asm -I ./includes -o MyTool.obj
|
|
113
|
+
|
|
114
|
+
# pass command-line defines (equivalent to the -d flag in MPW IIgs)
|
|
115
|
+
gsasm ROMDataMgr.asm -I ./includes -d Big=1
|
|
116
|
+
|
|
117
|
+
# multiple include directories
|
|
118
|
+
gsasm monitor.aii -I ./includes -I ./romsrc/Monitor
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Include directories are searched in order for files referenced by `INCLUDE`
|
|
122
|
+
directives. The source file's own directory is not searched implicitly — add
|
|
123
|
+
`-I .` if you need it.
|
|
124
|
+
|
|
125
|
+
### gslink — linker
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
gslink <file.obj> [-o <out.load>]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Links a single multi-segment OMF object file. All `LEXPR`/`BEXPR`/`EXPR`
|
|
132
|
+
relocation records and `RELEXPR` (relative branch) records are fully evaluated
|
|
133
|
+
against the collected `GLOBAL` symbol table. The output is a single-segment OMF
|
|
134
|
+
load file with a flat body.
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
gslink MyTool.obj # writes MyTool.out
|
|
138
|
+
gslink MyTool.obj -o MyTool.load
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
For multi-object linking — libraries, segment naming/placement, the
|
|
142
|
+
`LinkIIgs -apw` recipe used by the GS/OS build scripts — use
|
|
143
|
+
`gsasm/linkiigs.py`; for ROM bank layout see `work/linkrom.py`.
|
|
144
|
+
|
|
145
|
+
### gsrez — resource compiler
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
gsrez <source.r> [-I <incdir>]... [-o <out>] [-t <filetype>] [-c <creator>]
|
|
149
|
+
[--read-dir <dir>]... [--meta KEY=VAL]...
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Compiles a Rez source file (the MPW IIgs `RezIIgs` dialect: `type` templates,
|
|
153
|
+
`resource` bodies, `read` statements, the C-style preprocessor) into an Apple
|
|
154
|
+
IIgs resource fork, written as a raw fork image. `TypesIIGS.r`-style include
|
|
155
|
+
files are searched through `-I` directories; `read` files (e.g. linked code
|
|
156
|
+
resources) through `--read-dir`. `--meta` sets fork-header fields (creation
|
|
157
|
+
timestamp etc.) for byte-exact reproduction work.
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
gsrez sys.resources.r -I ./rincludes --read-dir ./build -o SYS.RESOURCES -t "F9 "
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Python API
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from gsasm import asm, omf, link
|
|
167
|
+
|
|
168
|
+
# Assemble (include paths are positional; defines optional)
|
|
169
|
+
a = asm.assemble("MyTool.asm", ["./includes"], defines={"Big": 1})
|
|
170
|
+
if a.errors:
|
|
171
|
+
raise SystemExit("\n".join(a.errors))
|
|
172
|
+
|
|
173
|
+
# Emit an OMF object
|
|
174
|
+
obj_bytes = omf.emit(a)
|
|
175
|
+
with open("MyTool.obj", "wb") as f:
|
|
176
|
+
f.write(obj_bytes)
|
|
177
|
+
|
|
178
|
+
# Link to a load file
|
|
179
|
+
load_bytes = link.link(obj_bytes)
|
|
180
|
+
with open("MyTool.out", "wb") as f:
|
|
181
|
+
f.write(load_bytes)
|
|
182
|
+
|
|
183
|
+
# Parse an existing OMF file
|
|
184
|
+
header = omf.parse_header(obj_bytes)
|
|
185
|
+
records, _ = omf.parse_records(obj_bytes, header["DISPDATA"],
|
|
186
|
+
numlen=header["NUMLEN"])
|
|
187
|
+
for offset, record_type, data in records:
|
|
188
|
+
print(offset, record_type, data)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Source dialect
|
|
192
|
+
|
|
193
|
+
`gsasm` implements the **MPW IIgs** (`AsmIIgs`) source dialect as used in the
|
|
194
|
+
ROM 03 and System 6.0.1 source trees. Notable features:
|
|
195
|
+
|
|
196
|
+
- **65816 instruction set** — full addressing-mode selection (dp/abs/long,
|
|
197
|
+
cross-bank rules), `MVN`/`MVP`, `PEA`/`PEI`/`PER`
|
|
198
|
+
- **Macro engine** — `MACRO`/`ENDM`, positional parameters (`&1`…`&n`),
|
|
199
|
+
keyword parameters, `WHILE`/`ENDWHILE`, `IF`/`ELSE`/`ENDIF`,
|
|
200
|
+
`GOTO`/`AGO`/`AIF`, `MEXIT`, `ANOP`, builtins (`&sysdate`, `&systime`, …)
|
|
201
|
+
- **Directives** — `PROC` (with `TEMPORG`/`ENTRY`/`EXPORT` forms),
|
|
202
|
+
`ENTRY`/`EXPORT`/`IMPORT`, `RECORD`/`ENDR` (templates and typed `DS`
|
|
203
|
+
instances), `WITH`, `DC`/`DCB`/`DS`, `ORG`, `SEG`, `INCLUDE`,
|
|
204
|
+
`MSB`/`LONGA`/`LONGI`/`CASE ON|OFF`, `OBJEND`
|
|
205
|
+
- **Label scoping** — `@`-local labels scoped to the nearest enclosing
|
|
206
|
+
non-`@` label (per MPW Assembler Reference p. 17); per-`PROC` namespaces
|
|
207
|
+
- **Expression evaluator** — MPW operator precedence, byte extraction
|
|
208
|
+
(`#<x`, `#>x`, `#^x`), shifts, the `≈` one's-complement operator,
|
|
209
|
+
`MSB ON` character constants
|
|
210
|
+
- **OMF v2 emitter** — `CONST`/`LCONST`/`DS`, `LEXPR`/`BEXPR`/`EXPR`/`RELEXPR`,
|
|
211
|
+
`GLOBAL`/`GEQU`, `SUPER` relocation dictionaries, cross-segment and import
|
|
212
|
+
references, faithful record chunking
|
|
213
|
+
|
|
214
|
+
Sources are read as MacRoman with classic-Mac line endings, matching real MPW
|
|
215
|
+
files.
|
|
216
|
+
|
|
217
|
+
## Module layout
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
gsasm/
|
|
221
|
+
__init__.py
|
|
222
|
+
__main__.py CLI entry points (gsasm, gslink)
|
|
223
|
+
m65816.py 65816 opcode table and addressing-mode encoding
|
|
224
|
+
expr.py MPW expression evaluator
|
|
225
|
+
asm.py Multi-pass assembler: macro engine, symbols, segments
|
|
226
|
+
omf.py OMF v2 parser and emitter
|
|
227
|
+
link.py Single-object OMF linker
|
|
228
|
+
linkiigs.py General LinkIIgs: multi-object, libraries, -apw recipe,
|
|
229
|
+
segment naming and placement
|
|
230
|
+
makebin.py MakeBinIIgs / OverlayIIgs / catenate packaging
|
|
231
|
+
expressload.py ExpressLoad relinker (fast-load format + SUPER records)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Tests
|
|
235
|
+
|
|
236
|
+
```sh
|
|
237
|
+
python3 tests/run_fixtures.py
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The `tests/` fixture suite runs on a bare checkout — no reference material
|
|
241
|
+
needed. Each fixture is an original source pinning one discovered dialect or
|
|
242
|
+
OMF behavior, with expected bytes minted only while the full golden-corpus
|
|
243
|
+
validation passes. See [tests/README.md](tests/README.md) for how blessing
|
|
244
|
+
works and why the expected bytes are trustworthy.
|
|
245
|
+
|
|
246
|
+
## Validation harnesses (work/)
|
|
247
|
+
|
|
248
|
+
The `work/` scripts are the differential-validation harnesses used during
|
|
249
|
+
development. They compare rebuilt output against captured artifacts of the
|
|
250
|
+
original build — Apple's source, listings, objects, and shipping binaries —
|
|
251
|
+
which are copyrighted and **not included** (everything under `ref/` and
|
|
252
|
+
`work/romsrc/` is gitignored; supply your own).
|
|
253
|
+
|
|
254
|
+
| Script | What it validates |
|
|
255
|
+
|---|---|
|
|
256
|
+
| `gate.py` | Runs every harness below against a committed baseline; fails on any regression |
|
|
257
|
+
| `buildrom.py` | Reconstructs `rom.03` and verifies it byte-identical to the shipping ROM |
|
|
258
|
+
| `bytecheck.py` | Instruction encoding against the `.lst` Object Code column |
|
|
259
|
+
| `objcheck.py` | Emitted `.obj` files record-by-record against the originals |
|
|
260
|
+
| `linkcheck.py` | Differential link: original vs `gsasm` object through the same linker |
|
|
261
|
+
| `toolcheck.py` | `System/Tools/ToolNNN` toolsets vs the shipping files |
|
|
262
|
+
| `fstcheck.py` | `System/FSTs/*` vs the shipping files |
|
|
263
|
+
| `drivercheck.py` | `System/Drivers/*` vs the shipping files |
|
|
264
|
+
| `kernelcheck.py` | `prodos`, `GS.OS`, `Start.GS.OS`, `Error.Msg`, P8 |
|
|
265
|
+
| `diskcheck.py` | Whole System 6.0.1 disk-image files (needs the `a2til` sibling tools; set `A2TIL_PATH`) |
|
|
266
|
+
| `linkrom.py` | The `LinkIIgs`-equivalent ROM bank layout |
|
|
267
|
+
| `hfs.py` | Minimal HFS reader for extracting sources from `.hfv` images |
|
|
268
|
+
|
|
269
|
+
## Background
|
|
270
|
+
|
|
271
|
+
The ROM 03 and System 6.0.1 sources were assembled with **AsmIIgs** (circa
|
|
272
|
+
1989–1993), Apple's 65816 cross-assembler for MPW, distributed through APDA
|
|
273
|
+
with the rest of the MPW IIgs cross-development tools. The tools' own source
|
|
274
|
+
code was never published, so this project is a clean-room reimplementation:
|
|
275
|
+
behaviour was reverse-engineered from captured `.obj` and `.lst` files. Given
|
|
276
|
+
source, listings, and objects from a known-good build, every discrepancy
|
|
277
|
+
between `gsasm`'s output and the original is a measurable bug, and every
|
|
278
|
+
target that passes a differential comparison is proven correct rather than
|
|
279
|
+
assumed. The same method then extended, tool by tool, to the rest of the MPW
|
|
280
|
+
IIgs chain until whole shipping binaries reproduced.
|
|
281
|
+
|
|
282
|
+
The OMF (Object Module Format) specification is documented in the _Apple IIgs
|
|
283
|
+
Toolbox Reference_ and the _Apple IIgs GS/OS Reference_.
|
|
284
|
+
|
|
285
|
+
## License
|
|
286
|
+
|
|
287
|
+
MIT — see [LICENSE](LICENSE).
|
gsasm-0.2.0/README.md
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# gsasm
|
|
2
|
+
|
|
3
|
+
A clean-room Python reimplementation of the **MPW IIgs cross-development
|
|
4
|
+
toolchain** — the `AsmIIgs` assembler, `LinkIIgs` linker, the `RezIIgs`
|
|
5
|
+
resource compiler, the `MakeBinIIgs`/`OverlayIIgs`/`catenate` packagers, and
|
|
6
|
+
the `ExpressLoad` relinker — validated byte-for-byte against the Apple IIgs
|
|
7
|
+
ROM 03 and the GS/OS System 6.0.1 shipping binaries.
|
|
8
|
+
|
|
9
|
+
Apple built the IIgs ROM and GS/OS on a 68k Mac under MPW Shell. Running that
|
|
10
|
+
chain today means SheepShaver → a Mac OS 7 image → MPW → the GS cross-tools.
|
|
11
|
+
`gsasm` replaces it with pure Python — no emulator, no dependencies outside
|
|
12
|
+
the standard library.
|
|
13
|
+
|
|
14
|
+
## Results
|
|
15
|
+
|
|
16
|
+
Rebuilt from the original source and verified byte-identical to the shipping
|
|
17
|
+
binaries:
|
|
18
|
+
|
|
19
|
+
- **ROM 03** — all 262,144 bytes
|
|
20
|
+
- **All 7 buildable FSTs** (ProDOS, HFS, Char, High Sierra, DOS 3.3, Pascal,
|
|
21
|
+
MS-DOS) and **11 of 12 device drivers**
|
|
22
|
+
- **`prodos`, `Start.GS.OS`, `Error.Msg`, the GS/OS Loader**, `Tool014`
|
|
23
|
+
(Window Manager), and 19 of the 30 System 6.0.1 files the disk harness
|
|
24
|
+
rebuilds
|
|
25
|
+
- **Resource forks** (`gsrez`): `Sys.Resources` (24,337 bytes, 143 resources
|
|
26
|
+
including embedded code resources) and `EasyMount` — the latter byte-exact
|
|
27
|
+
across **both** forks, code and resources, from source to shipping file
|
|
28
|
+
- **Instruction encoding: 100%** — every instruction in the ~97,000-line
|
|
29
|
+
corpus encodes to the same bytes as the original listings
|
|
30
|
+
- **61/61 ROM objects link-identical** — for every module, linking `gsasm`'s
|
|
31
|
+
object or Apple's original produces the same load image
|
|
32
|
+
|
|
33
|
+
`GS.OS` itself reaches 38,711 of 38,805 bytes (99.76%); the residual 94 bytes
|
|
34
|
+
reference symbols that exist nowhere in the source archive, so a byte-exact
|
|
35
|
+
build is provably out of reach from these sources. The other shortfalls have
|
|
36
|
+
similarly settled causes (a source-revision skew, a converter whose output
|
|
37
|
+
isn't a function of its input, missing sources). The full accounting, with
|
|
38
|
+
evidence for each limit, is in [docs/RESULTS.md](docs/RESULTS.md).
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
pip install git+https://github.com/emdeejay/gsasm.git
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Or install from a local clone in editable mode:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
git clone https://github.com/emdeejay/gsasm.git
|
|
50
|
+
cd gsasm
|
|
51
|
+
pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Requires Python 3.9+. No dependencies outside the standard library.
|
|
55
|
+
|
|
56
|
+
## CLI
|
|
57
|
+
|
|
58
|
+
### gsasm — assembler
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
gsasm <source.asm> [-I <incdir>] [-d KEY=VAL] [-o <out.obj>]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Assembles an MPW IIgs-dialect 65816 source file and writes an OMF v2 object file.
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
# assemble a single file
|
|
68
|
+
gsasm MyTool.asm -I ./includes -o MyTool.obj
|
|
69
|
+
|
|
70
|
+
# pass command-line defines (equivalent to the -d flag in MPW IIgs)
|
|
71
|
+
gsasm ROMDataMgr.asm -I ./includes -d Big=1
|
|
72
|
+
|
|
73
|
+
# multiple include directories
|
|
74
|
+
gsasm monitor.aii -I ./includes -I ./romsrc/Monitor
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Include directories are searched in order for files referenced by `INCLUDE`
|
|
78
|
+
directives. The source file's own directory is not searched implicitly — add
|
|
79
|
+
`-I .` if you need it.
|
|
80
|
+
|
|
81
|
+
### gslink — linker
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
gslink <file.obj> [-o <out.load>]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Links a single multi-segment OMF object file. All `LEXPR`/`BEXPR`/`EXPR`
|
|
88
|
+
relocation records and `RELEXPR` (relative branch) records are fully evaluated
|
|
89
|
+
against the collected `GLOBAL` symbol table. The output is a single-segment OMF
|
|
90
|
+
load file with a flat body.
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
gslink MyTool.obj # writes MyTool.out
|
|
94
|
+
gslink MyTool.obj -o MyTool.load
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For multi-object linking — libraries, segment naming/placement, the
|
|
98
|
+
`LinkIIgs -apw` recipe used by the GS/OS build scripts — use
|
|
99
|
+
`gsasm/linkiigs.py`; for ROM bank layout see `work/linkrom.py`.
|
|
100
|
+
|
|
101
|
+
### gsrez — resource compiler
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
gsrez <source.r> [-I <incdir>]... [-o <out>] [-t <filetype>] [-c <creator>]
|
|
105
|
+
[--read-dir <dir>]... [--meta KEY=VAL]...
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Compiles a Rez source file (the MPW IIgs `RezIIgs` dialect: `type` templates,
|
|
109
|
+
`resource` bodies, `read` statements, the C-style preprocessor) into an Apple
|
|
110
|
+
IIgs resource fork, written as a raw fork image. `TypesIIGS.r`-style include
|
|
111
|
+
files are searched through `-I` directories; `read` files (e.g. linked code
|
|
112
|
+
resources) through `--read-dir`. `--meta` sets fork-header fields (creation
|
|
113
|
+
timestamp etc.) for byte-exact reproduction work.
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
gsrez sys.resources.r -I ./rincludes --read-dir ./build -o SYS.RESOURCES -t "F9 "
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Python API
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from gsasm import asm, omf, link
|
|
123
|
+
|
|
124
|
+
# Assemble (include paths are positional; defines optional)
|
|
125
|
+
a = asm.assemble("MyTool.asm", ["./includes"], defines={"Big": 1})
|
|
126
|
+
if a.errors:
|
|
127
|
+
raise SystemExit("\n".join(a.errors))
|
|
128
|
+
|
|
129
|
+
# Emit an OMF object
|
|
130
|
+
obj_bytes = omf.emit(a)
|
|
131
|
+
with open("MyTool.obj", "wb") as f:
|
|
132
|
+
f.write(obj_bytes)
|
|
133
|
+
|
|
134
|
+
# Link to a load file
|
|
135
|
+
load_bytes = link.link(obj_bytes)
|
|
136
|
+
with open("MyTool.out", "wb") as f:
|
|
137
|
+
f.write(load_bytes)
|
|
138
|
+
|
|
139
|
+
# Parse an existing OMF file
|
|
140
|
+
header = omf.parse_header(obj_bytes)
|
|
141
|
+
records, _ = omf.parse_records(obj_bytes, header["DISPDATA"],
|
|
142
|
+
numlen=header["NUMLEN"])
|
|
143
|
+
for offset, record_type, data in records:
|
|
144
|
+
print(offset, record_type, data)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Source dialect
|
|
148
|
+
|
|
149
|
+
`gsasm` implements the **MPW IIgs** (`AsmIIgs`) source dialect as used in the
|
|
150
|
+
ROM 03 and System 6.0.1 source trees. Notable features:
|
|
151
|
+
|
|
152
|
+
- **65816 instruction set** — full addressing-mode selection (dp/abs/long,
|
|
153
|
+
cross-bank rules), `MVN`/`MVP`, `PEA`/`PEI`/`PER`
|
|
154
|
+
- **Macro engine** — `MACRO`/`ENDM`, positional parameters (`&1`…`&n`),
|
|
155
|
+
keyword parameters, `WHILE`/`ENDWHILE`, `IF`/`ELSE`/`ENDIF`,
|
|
156
|
+
`GOTO`/`AGO`/`AIF`, `MEXIT`, `ANOP`, builtins (`&sysdate`, `&systime`, …)
|
|
157
|
+
- **Directives** — `PROC` (with `TEMPORG`/`ENTRY`/`EXPORT` forms),
|
|
158
|
+
`ENTRY`/`EXPORT`/`IMPORT`, `RECORD`/`ENDR` (templates and typed `DS`
|
|
159
|
+
instances), `WITH`, `DC`/`DCB`/`DS`, `ORG`, `SEG`, `INCLUDE`,
|
|
160
|
+
`MSB`/`LONGA`/`LONGI`/`CASE ON|OFF`, `OBJEND`
|
|
161
|
+
- **Label scoping** — `@`-local labels scoped to the nearest enclosing
|
|
162
|
+
non-`@` label (per MPW Assembler Reference p. 17); per-`PROC` namespaces
|
|
163
|
+
- **Expression evaluator** — MPW operator precedence, byte extraction
|
|
164
|
+
(`#<x`, `#>x`, `#^x`), shifts, the `≈` one's-complement operator,
|
|
165
|
+
`MSB ON` character constants
|
|
166
|
+
- **OMF v2 emitter** — `CONST`/`LCONST`/`DS`, `LEXPR`/`BEXPR`/`EXPR`/`RELEXPR`,
|
|
167
|
+
`GLOBAL`/`GEQU`, `SUPER` relocation dictionaries, cross-segment and import
|
|
168
|
+
references, faithful record chunking
|
|
169
|
+
|
|
170
|
+
Sources are read as MacRoman with classic-Mac line endings, matching real MPW
|
|
171
|
+
files.
|
|
172
|
+
|
|
173
|
+
## Module layout
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
gsasm/
|
|
177
|
+
__init__.py
|
|
178
|
+
__main__.py CLI entry points (gsasm, gslink)
|
|
179
|
+
m65816.py 65816 opcode table and addressing-mode encoding
|
|
180
|
+
expr.py MPW expression evaluator
|
|
181
|
+
asm.py Multi-pass assembler: macro engine, symbols, segments
|
|
182
|
+
omf.py OMF v2 parser and emitter
|
|
183
|
+
link.py Single-object OMF linker
|
|
184
|
+
linkiigs.py General LinkIIgs: multi-object, libraries, -apw recipe,
|
|
185
|
+
segment naming and placement
|
|
186
|
+
makebin.py MakeBinIIgs / OverlayIIgs / catenate packaging
|
|
187
|
+
expressload.py ExpressLoad relinker (fast-load format + SUPER records)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Tests
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
python3 tests/run_fixtures.py
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The `tests/` fixture suite runs on a bare checkout — no reference material
|
|
197
|
+
needed. Each fixture is an original source pinning one discovered dialect or
|
|
198
|
+
OMF behavior, with expected bytes minted only while the full golden-corpus
|
|
199
|
+
validation passes. See [tests/README.md](tests/README.md) for how blessing
|
|
200
|
+
works and why the expected bytes are trustworthy.
|
|
201
|
+
|
|
202
|
+
## Validation harnesses (work/)
|
|
203
|
+
|
|
204
|
+
The `work/` scripts are the differential-validation harnesses used during
|
|
205
|
+
development. They compare rebuilt output against captured artifacts of the
|
|
206
|
+
original build — Apple's source, listings, objects, and shipping binaries —
|
|
207
|
+
which are copyrighted and **not included** (everything under `ref/` and
|
|
208
|
+
`work/romsrc/` is gitignored; supply your own).
|
|
209
|
+
|
|
210
|
+
| Script | What it validates |
|
|
211
|
+
|---|---|
|
|
212
|
+
| `gate.py` | Runs every harness below against a committed baseline; fails on any regression |
|
|
213
|
+
| `buildrom.py` | Reconstructs `rom.03` and verifies it byte-identical to the shipping ROM |
|
|
214
|
+
| `bytecheck.py` | Instruction encoding against the `.lst` Object Code column |
|
|
215
|
+
| `objcheck.py` | Emitted `.obj` files record-by-record against the originals |
|
|
216
|
+
| `linkcheck.py` | Differential link: original vs `gsasm` object through the same linker |
|
|
217
|
+
| `toolcheck.py` | `System/Tools/ToolNNN` toolsets vs the shipping files |
|
|
218
|
+
| `fstcheck.py` | `System/FSTs/*` vs the shipping files |
|
|
219
|
+
| `drivercheck.py` | `System/Drivers/*` vs the shipping files |
|
|
220
|
+
| `kernelcheck.py` | `prodos`, `GS.OS`, `Start.GS.OS`, `Error.Msg`, P8 |
|
|
221
|
+
| `diskcheck.py` | Whole System 6.0.1 disk-image files (needs the `a2til` sibling tools; set `A2TIL_PATH`) |
|
|
222
|
+
| `linkrom.py` | The `LinkIIgs`-equivalent ROM bank layout |
|
|
223
|
+
| `hfs.py` | Minimal HFS reader for extracting sources from `.hfv` images |
|
|
224
|
+
|
|
225
|
+
## Background
|
|
226
|
+
|
|
227
|
+
The ROM 03 and System 6.0.1 sources were assembled with **AsmIIgs** (circa
|
|
228
|
+
1989–1993), Apple's 65816 cross-assembler for MPW, distributed through APDA
|
|
229
|
+
with the rest of the MPW IIgs cross-development tools. The tools' own source
|
|
230
|
+
code was never published, so this project is a clean-room reimplementation:
|
|
231
|
+
behaviour was reverse-engineered from captured `.obj` and `.lst` files. Given
|
|
232
|
+
source, listings, and objects from a known-good build, every discrepancy
|
|
233
|
+
between `gsasm`'s output and the original is a measurable bug, and every
|
|
234
|
+
target that passes a differential comparison is proven correct rather than
|
|
235
|
+
assumed. The same method then extended, tool by tool, to the rest of the MPW
|
|
236
|
+
IIgs chain until whole shipping binaries reproduced.
|
|
237
|
+
|
|
238
|
+
The OMF (Object Module Format) specification is documented in the _Apple IIgs
|
|
239
|
+
Toolbox Reference_ and the _Apple IIgs GS/OS Reference_.
|
|
240
|
+
|
|
241
|
+
## License
|
|
242
|
+
|
|
243
|
+
MIT — see [LICENSE](LICENSE).
|