diff --git a/package-lock.json b/package-lock.json index c8655025..048eb65b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "license": "GPL-3.0", "dependencies": { "@sentry/electron": "^2.5.1", + "@wasmer/wasi": "^0.12.0", + "@wasmer/wasmfs": "^0.12.0", "binaryen": "^101.0.0", "chokidar": "^3.5.0", "jquery": "^3.5.1", @@ -64,11 +66,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.14.5", - "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.8.tgz", + "integrity": "sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg==", "dev": true, "dependencies": { - "@babel/types": "^7.14.5", + "@babel/types": "^7.14.8", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -131,8 +134,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.5", - "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz", + "integrity": "sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==", "dev": true, "engines": { "node": ">=6.9.0" @@ -187,8 +191,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.14.6", - "integrity": "sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.8.tgz", + "integrity": "sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -211,17 +216,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.14.5", - "integrity": "sha512-G3BiS15vevepdmFqmUc9X+64y0viZYygubAMO8SvBmKARuF6CPSZtH4Ng9vi/lrWlZFGe3FWdXNy835akH8Glg==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.8.tgz", + "integrity": "sha512-kexHhzCljJcFNn1KYAQ6A5wxMRzq9ebYpEDV4+WdNyr3i7O44tanbDOR/xjiG2F3sllan+LgwK+7OMk0EmydHg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.5", + "@babel/generator": "^7.14.8", "@babel/helper-function-name": "^7.14.5", "@babel/helper-hoist-variables": "^7.14.5", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5", + "@babel/parser": "^7.14.8", + "@babel/types": "^7.14.8", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -230,11 +236,12 @@ } }, "node_modules/@babel/types": { - "version": "7.14.5", - "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.8.tgz", + "integrity": "sha512-iob4soQa7dZw8nodR/KlOQkPh9S4I8RwCxwRIFuiMRYjOzH/KJzdUfDgz6cGi5dDaclXF4P2PAhCdrBJNIg68Q==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.8", "to-fast-properties": "^2.0.0" }, "engines": { @@ -765,6 +772,27 @@ "@types/node": "*" } }, + "node_modules/@wasmer/wasi": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@wasmer/wasi/-/wasi-0.12.0.tgz", + "integrity": "sha512-FJhLZKAfLWm/yjQI7eCRHNbA8ezmb7LSpUYFkHruZXs2mXk2+DaQtSElEtOoNrVQ4vApTyVaAd5/b7uEu8w6wQ==", + "dependencies": { + "browser-process-hrtime": "^1.0.0", + "buffer-es6": "^4.9.3", + "path-browserify": "^1.0.0", + "randomfill": "^1.0.4" + } + }, + "node_modules/@wasmer/wasmfs": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@wasmer/wasmfs/-/wasmfs-0.12.0.tgz", + "integrity": "sha512-m1ftchyQ1DfSenm5XbbdGIpb6KJHH5z0gODo3IZr6lATkj4WXfX/UeBTZ0aG9YVShBp+kHLdUHvOkqjy6p/GWw==", + "dependencies": { + "memfs": "3.0.4", + "pako": "^1.0.11", + "tar-stream": "^2.1.0" + } + }, "node_modules/7zip-bin": { "version": "5.1.1", "integrity": "sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==", @@ -1248,7 +1276,6 @@ "node_modules/base64-js": { "version": "1.5.1", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -1286,6 +1313,29 @@ "wasm-opt": "bin/wasm-opt" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/bluebird": { "version": "3.7.2", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", @@ -1495,8 +1545,7 @@ }, "node_modules/browser-process-hrtime": { "version": "1.0.0", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" }, "node_modules/browser-stdout": { "version": "1.3.1", @@ -1517,7 +1566,6 @@ "node_modules/buffer": { "version": "5.7.1", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -1532,7 +1580,6 @@ "url": "https://feross.org/support" } ], - "optional": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -1567,6 +1614,11 @@ "node": ">=0.4.0" } }, + "node_modules/buffer-es6": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/buffer-es6/-/buffer-es6-4.9.3.tgz", + "integrity": "sha1-8mNHuC33b9N+GLy1KIxJcM/VxAQ=" + }, "node_modules/buffer-fill": { "version": "1.0.0", "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", @@ -3537,6 +3589,11 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-extend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fast-extend/-/fast-extend-1.0.2.tgz", + "integrity": "sha512-XXA9RmlPatkFKUzqVZAFth18R4Wo+Xug/S+C7YlYA3xrXwfPlW3dqNwOb4hvQo7wZJ2cNDYhrYuPzVOfHy5/uQ==" + }, "node_modules/fast-glob": { "version": "3.2.5", "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", @@ -3801,6 +3858,11 @@ "node": ">= 0.12" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "node_modules/fs-extra": { "version": "8.1.0", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", @@ -3813,6 +3875,11 @@ "node": ">=6 <7 || >=8" } }, + "node_modules/fs-monkey": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-0.3.3.tgz", + "integrity": "sha512-FNUvuTAJ3CqCQb5ELn+qCbGR/Zllhf2HtwsdAtBi59s1WeCjKMT81fHcSu7dwIskqGVK+MmOrb7VOBlq3/SItw==" + }, "node_modules/fs.realpath": { "version": "1.0.0", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", @@ -4430,7 +4497,6 @@ "node_modules/ieee754": { "version": "1.2.1", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -4444,8 +4510,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "optional": true + ] }, "node_modules/ignore": { "version": "5.1.8", @@ -5585,6 +5650,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/memfs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.0.4.tgz", + "integrity": "sha512-OcZEzwX9E5AoY8SXjuAvw0DbIAYwUzV/I236I8Pqvrlv7sL/Y0E9aRCon05DhaV8pg1b32uxj76RgW0s5xjHBA==", + "dependencies": { + "fast-extend": "1.0.2", + "fs-monkey": "0.3.3" + } + }, "node_modules/merge-source-map": { "version": "1.1.0", "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", @@ -6775,8 +6849,7 @@ }, "node_modules/pako": { "version": "1.0.11", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "node_modules/parse-author": { "version": "2.0.0", @@ -6813,6 +6886,11 @@ "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", "dev": true }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, "node_modules/path-exists": { "version": "3.0.0", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", @@ -7097,6 +7175,23 @@ } ] }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "node_modules/raw-body": { "version": "2.4.1", "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", @@ -7994,6 +8089,34 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/tcp-port-used": { "version": "1.0.2", "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", @@ -9058,11 +9181,12 @@ } }, "@babel/generator": { - "version": "7.14.5", - "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.8.tgz", + "integrity": "sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg==", "dev": true, "requires": { - "@babel/types": "^7.14.5", + "@babel/types": "^7.14.8", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -9109,8 +9233,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.14.5", - "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz", + "integrity": "sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==", "dev": true }, "@babel/highlight": { @@ -9152,8 +9277,9 @@ } }, "@babel/parser": { - "version": "7.14.6", - "integrity": "sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.8.tgz", + "integrity": "sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA==", "dev": true }, "@babel/template": { @@ -9167,27 +9293,29 @@ } }, "@babel/traverse": { - "version": "7.14.5", - "integrity": "sha512-G3BiS15vevepdmFqmUc9X+64y0viZYygubAMO8SvBmKARuF6CPSZtH4Ng9vi/lrWlZFGe3FWdXNy835akH8Glg==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.8.tgz", + "integrity": "sha512-kexHhzCljJcFNn1KYAQ6A5wxMRzq9ebYpEDV4+WdNyr3i7O44tanbDOR/xjiG2F3sllan+LgwK+7OMk0EmydHg==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.5", + "@babel/generator": "^7.14.8", "@babel/helper-function-name": "^7.14.5", "@babel/helper-hoist-variables": "^7.14.5", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5", + "@babel/parser": "^7.14.8", + "@babel/types": "^7.14.8", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.14.5", - "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.8.tgz", + "integrity": "sha512-iob4soQa7dZw8nodR/KlOQkPh9S4I8RwCxwRIFuiMRYjOzH/KJzdUfDgz6cGi5dDaclXF4P2PAhCdrBJNIg68Q==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.8", "to-fast-properties": "^2.0.0" } }, @@ -9636,6 +9764,27 @@ "@types/node": "*" } }, + "@wasmer/wasi": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@wasmer/wasi/-/wasi-0.12.0.tgz", + "integrity": "sha512-FJhLZKAfLWm/yjQI7eCRHNbA8ezmb7LSpUYFkHruZXs2mXk2+DaQtSElEtOoNrVQ4vApTyVaAd5/b7uEu8w6wQ==", + "requires": { + "browser-process-hrtime": "^1.0.0", + "buffer-es6": "^4.9.3", + "path-browserify": "^1.0.0", + "randomfill": "^1.0.4" + } + }, + "@wasmer/wasmfs": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@wasmer/wasmfs/-/wasmfs-0.12.0.tgz", + "integrity": "sha512-m1ftchyQ1DfSenm5XbbdGIpb6KJHH5z0gODo3IZr6lATkj4WXfX/UeBTZ0aG9YVShBp+kHLdUHvOkqjy6p/GWw==", + "requires": { + "memfs": "3.0.4", + "pako": "^1.0.11", + "tar-stream": "^2.1.0" + } + }, "7zip-bin": { "version": "5.1.1", "integrity": "sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==", @@ -9999,8 +10148,7 @@ }, "base64-js": { "version": "1.5.1", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -10018,6 +10166,28 @@ "version": "101.0.0", "integrity": "sha512-FRmVxvrR8jtcf0qcukNAPZDM3dZ2sc9GmA/hKxBI7k3fFzREKh1cAs+ruQi+ITTKz7u/AuFMuVnbJwTh0ef/HQ==" }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "bluebird": { "version": "3.7.2", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", @@ -10172,8 +10342,7 @@ }, "browser-process-hrtime": { "version": "1.0.0", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" }, "browser-stdout": { "version": "1.3.1", @@ -10188,8 +10357,6 @@ "buffer": { "version": "5.7.1", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "optional": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -10218,6 +10385,11 @@ "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", "dev": true }, + "buffer-es6": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/buffer-es6/-/buffer-es6-4.9.3.tgz", + "integrity": "sha1-8mNHuC33b9N+GLy1KIxJcM/VxAQ=" + }, "buffer-fill": { "version": "1.0.0", "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", @@ -11719,6 +11891,11 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-extend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fast-extend/-/fast-extend-1.0.2.tgz", + "integrity": "sha512-XXA9RmlPatkFKUzqVZAFth18R4Wo+Xug/S+C7YlYA3xrXwfPlW3dqNwOb4hvQo7wZJ2cNDYhrYuPzVOfHy5/uQ==" + }, "fast-glob": { "version": "3.2.5", "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", @@ -11929,6 +12106,11 @@ "mime-types": "^2.1.12" } }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "fs-extra": { "version": "8.1.0", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", @@ -11938,6 +12120,11 @@ "universalify": "^0.1.0" } }, + "fs-monkey": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-0.3.3.tgz", + "integrity": "sha512-FNUvuTAJ3CqCQb5ELn+qCbGR/Zllhf2HtwsdAtBi59s1WeCjKMT81fHcSu7dwIskqGVK+MmOrb7VOBlq3/SItw==" + }, "fs.realpath": { "version": "1.0.0", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", @@ -12413,9 +12600,7 @@ }, "ieee754": { "version": "1.2.1", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "optional": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "5.1.8", @@ -13289,6 +13474,15 @@ } } }, + "memfs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.0.4.tgz", + "integrity": "sha512-OcZEzwX9E5AoY8SXjuAvw0DbIAYwUzV/I236I8Pqvrlv7sL/Y0E9aRCon05DhaV8pg1b32uxj76RgW0s5xjHBA==", + "requires": { + "fast-extend": "1.0.2", + "fs-monkey": "0.3.3" + } + }, "merge-source-map": { "version": "1.1.0", "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", @@ -14212,8 +14406,7 @@ }, "pako": { "version": "1.0.11", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "parse-author": { "version": "2.0.0", @@ -14241,6 +14434,11 @@ "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", "dev": true }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, "path-exists": { "version": "3.0.0", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", @@ -14438,6 +14636,23 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "raw-body": { "version": "2.4.1", "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", @@ -15120,6 +15335,30 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "tcp-port-used": { "version": "1.0.2", "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", diff --git a/package.json b/package.json index 1e32c668..d726d178 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ "license": "GPL-3.0", "dependencies": { "@sentry/electron": "^2.5.1", + "@wasmer/wasi": "^0.12.0", + "@wasmer/wasmfs": "^0.12.0", "binaryen": "^101.0.0", "chokidar": "^3.5.0", "jquery": "^3.5.1", diff --git a/res/atari8.wasm b/res/atari8.wasm new file mode 100755 index 00000000..6e9996ed Binary files /dev/null and b/res/atari8.wasm differ diff --git a/src/common/baseplatform.ts b/src/common/baseplatform.ts index 88ec7f23..1538ed7a 100644 --- a/src/common/baseplatform.ts +++ b/src/common/baseplatform.ts @@ -1,5 +1,5 @@ -import { RAM, RasterVideo, KeyFlags, dumpRAM, AnimationTimer, setKeyboardFromMap, padBytes, ControllerPoller } from "./emu"; +import { RAM, RasterVideo, KeyFlags, dumpRAM, AnimationTimer, setKeyboardFromMap, padBytes, ControllerPoller, EmuHalt } from "./emu"; import { hex, printFlags, invertMap, getBasePlatform, byteToASCII } from "./util"; import { CodeAnalyzer } from "./analysis"; import { Segment, FileData } from "./workertypes"; @@ -1036,7 +1036,7 @@ export function lookupSymbol(platform:Platform, addr:number, extra:boolean) { /// new Machine platform adapters -import { Bus, Resettable, FrameBased, VideoSource, SampledAudioSource, AcceptsROM, AcceptsBIOS, AcceptsKeyInput, SavesState, SavesInputState, HasCPU, TrapCondition, CPU, HasSerialIO, SerialIOInterface, SerialEvent } from "./devices"; +import { Bus, Resettable, FrameBased, VideoSource, SampledAudioSource, AcceptsROM, AcceptsBIOS, AcceptsKeyInput, SavesState, SavesInputState, HasCPU, TrapCondition, CPU, HasSerialIO, SerialIOInterface, SerialEvent, AcceptsJoyInput } from "./devices"; import { Probeable, RasterFrameBased, AcceptsPaddleInput, SampledAudioSink, ProbeAll, NullProbe } from "./devices"; import { SampledAudio } from "./audio"; import { ProbeRecorder } from "./recorder"; @@ -1053,6 +1053,9 @@ export function hasAudio(arg:any): arg is SampledAudioSource { export function hasKeyInput(arg:any): arg is AcceptsKeyInput { return typeof arg.setKeyInput === 'function'; } +export function hasJoyInput(arg:any): arg is AcceptsJoyInput { + return typeof arg.setJoyInput === 'function'; +} export function hasPaddleInput(arg:any): arg is AcceptsPaddleInput { return typeof arg.setPaddleInput === 'function'; } @@ -1323,8 +1326,11 @@ export abstract class BaseWASMMachine { audio : SampledAudioSink; audioarr : Float32Array; probe : ProbeAll; + maxROMSize : number = 0x40000; abstract getCPUState() : CpuState; + abstract saveState() : EmuState; + abstract loadState(state: EmuState); constructor(prefix: string) { this.prefix = prefix; @@ -1345,39 +1351,53 @@ export abstract class BaseWASMMachine { }, } } - async loadWASM() { - // fetch WASM + getImports(wmod: WebAssembly.Module) { + return {}; + } + async fetchWASM() { var wasmResponse = await fetch('res/'+this.prefix+'.wasm'); var wasmBinary = await wasmResponse.arrayBuffer(); var wasmCompiled = await WebAssembly.compile(wasmBinary); - var wasmResult = await WebAssembly.instantiate(wasmCompiled); + var wasmResult = await WebAssembly.instantiate(wasmCompiled, this.getImports(wasmCompiled)); this.instance = wasmResult; this.exports = wasmResult.exports; - this.exports.memory.grow(64); // TODO: need more when probing? - // fetch BIOS + } + async fetchBIOS() { var biosResponse = await fetch('res/'+this.prefix+'.bios'); var biosBinary = await biosResponse.arrayBuffer(); this.biosptr = this.exports.malloc(biosBinary.byteLength); this.biosarr = new Uint8Array(this.exports.memory.buffer, this.biosptr, biosBinary.byteLength); this.loadBIOS(new Uint8Array(biosBinary)); + } + async initWASM() { // init machine instance this.sys = this.exports.machine_init(this.biosptr); - console.log('machine_init', this.sys); - // create state buffers - var statesize = this.exports.machine_get_state_size(); + let statesize = this.exports.machine_get_state_size(); this.stateptr = this.exports.malloc(statesize); - this.statearr = new Uint8Array(this.exports.memory.buffer, this.stateptr, statesize); - var ctrlstatesize = this.exports.machine_get_controls_state_size(); + let ctrlstatesize = this.exports.machine_get_controls_state_size(); this.ctrlstateptr = this.exports.malloc(ctrlstatesize); - this.ctrlstatearr = new Uint8Array(this.exports.memory.buffer, this.ctrlstateptr, ctrlstatesize); - var cpustatesize = this.exports.machine_get_cpu_state_size(); + let cpustatesize = this.exports.machine_get_cpu_state_size(); this.cpustateptr = this.exports.malloc(cpustatesize); + this.romptr = this.exports.malloc(this.maxROMSize); + // create state buffers + // must do this after allocating memory (and everytime we grow memory?) + this.statearr = new Uint8Array(this.exports.memory.buffer, this.stateptr, statesize); + this.ctrlstatearr = new Uint8Array(this.exports.memory.buffer, this.ctrlstateptr, ctrlstatesize); this.cpustatearr = new Uint8Array(this.exports.memory.buffer, this.cpustateptr, cpustatesize); // create audio buffer - var sampbufsize = 4096*4; + let sampbufsize = 4096*4; this.audioarr = new Float32Array(this.exports.memory.buffer, this.exports.machine_get_sample_buffer(), sampbufsize); + // create ROM buffer + this.romarr = new Uint8Array(this.exports.memory.buffer, this.romptr, this.maxROMSize); // enable c64 joystick map to arrow keys (TODO) //this.exports.c64_set_joystick_type(this.sys, 1); + console.log('machine_init', this.sys, statesize, ctrlstatesize, cpustatesize, sampbufsize); + } + async loadWASM() { + await this.fetchWASM(); + this.exports.memory.grow(64); // TODO: need more when probing? + await this.fetchBIOS(); + await this.initWASM(); } getPC() : number { return this.exports.machine_cpu_get_pc(this.sys); @@ -1389,13 +1409,11 @@ export abstract class BaseWASMMachine { return this.exports.machine_cpu_is_stable(this.sys); } loadROM(rom: Uint8Array) { - if (!this.romptr) { - this.romptr = this.exports.malloc(0x10000); - this.romarr = new Uint8Array(this.exports.memory.buffer, this.romptr, 0x10000); - } + if (rom.length > this.maxROMSize) throw new EmuHalt(`Rom size too big: ${rom.length} bytes`); this.romarr.set(rom); this.romlen = rom.length; - this.reset(); + console.log('load rom', rom.length, 'bytes'); + this.reset(); // TODO? } // TODO: can't load after machine_init loadBIOS(srcArray: Uint8Array) { @@ -1423,12 +1441,14 @@ export abstract class BaseWASMMachine { } connectVideo(pixels:Uint32Array) : void { this.pixel_dest = pixels; - // save video pointer - var pixbuf = this.exports.machine_get_pixel_buffer(this.sys); + var pixbuf = this.exports.machine_get_pixel_buffer(this.sys); // save video pointer this.pixel_src = new Uint32Array(this.exports.memory.buffer, pixbuf, pixels.length); - console.log(pixbuf, pixels.length); + console.log('connectVideo', pixbuf, pixels.length); } syncVideo() { + if (this.exports.machine_update_video) { + this.exports.machine_update_video(this.sys); + } if (this.pixel_dest != null) { this.pixel_dest.set(this.pixel_src); } @@ -1486,8 +1506,71 @@ export abstract class BaseWASMMachine { connectProbe(probe: ProbeAll): void { this.probe = probe; } + getDebugTree() { + return this.saveState(); + } } +import { loadScript } from "../ide/ui"; +import { WasmFs } from "@wasmer/wasmfs"; + +let stub = function() { console.log(arguments); return 0 } + +export abstract class BaseWASIMachine extends BaseWASMMachine { + m_wasi; + wasiInstance; + wasmFs : WasmFs; + + constructor(prefix: string) { + super(prefix); + } + getImports(wmod: WebAssembly.Module) { + var imports = this.wasiInstance.getImports(wmod); + // TODO: eliminate these imports + imports.env = { + system: stub, + __sys_mkdir: stub, + __sys_chmod: stub, + __sys_stat64: stub, + __sys_unlink: stub, + __sys_rename: stub, + __sys_getdents64: stub, + __sys_getcwd: stub, + __sys_rmdir: stub, + emscripten_thread_sleep: stub, + } + return imports; + } + stdoutWrite(buffer) { + console.log('>>>', buffer.toString()); + return buffer.length; + } + async loadWASM() { + await loadScript('node_modules/@wasmer/wasi/lib/index.iife.js'); //TODO: require('@wasmer/wasi'); + await loadScript('node_modules/@wasmer/wasmfs/lib/index.iife.js'); //TODO: require('@wasmer/wasi'); + let WASI = window['WASI']; + let WasmFs = window['WasmFs']; + this.wasmFs = new WasmFs.WasmFs(); + let bindings = WASI.WASI.defaultBindings; + bindings.fs = this.wasmFs.fs; + bindings.fs.mkdirSync('/tmp'); + bindings.path = bindings.path.default; + this.wasiInstance = new WASI.WASI({ + preopenDirectories: {'/tmp':'/tmp'}, + env: {}, + args: [], + bindings: bindings + }); + this.wasmFs.volume.fds[1].write = this.stdoutWrite.bind(this); + this.wasmFs.volume.fds[2].write = this.stdoutWrite.bind(this); + await this.fetchWASM(); + this.wasiInstance.start(this.instance); + await this.initWASM(); + } +} + +///// + class SerialIOVisualizer { textarea : HTMLTextAreaElement; diff --git a/src/common/devices.ts b/src/common/devices.ts index ecdf2038..93bd4593 100644 --- a/src/common/devices.ts +++ b/src/common/devices.ts @@ -98,7 +98,6 @@ export interface SavesInputState { saveControlsState() : CS; } -// TODO: joystick export interface AcceptsKeyInput { setKeyInput(key:number, code:number, flags:number) : void; } @@ -107,6 +106,11 @@ export interface AcceptsPaddleInput { setPaddleInput(controller:number, value:number) : void; } +// TODO: interface not yet used (setKeyInput() handles joystick) +export interface AcceptsJoyInput { + setJoyInput(joy:number, bitmask:number) : void; +} + // SERIAL I/O export interface SerialEvent { diff --git a/src/machine/atari8.ts b/src/machine/atari8.ts new file mode 100644 index 00000000..69adb24b --- /dev/null +++ b/src/machine/atari8.ts @@ -0,0 +1,112 @@ +import { BaseWASIMachine, Machine } from "../common/baseplatform"; +import { AcceptsKeyInput, AcceptsPaddleInput, AcceptsROM, FrameBased, Probeable, RasterFrameBased, TrapCondition, VideoSource } from "../common/devices"; +import { KeyFlags } from "../common/emu"; +import { hex } from "../common/util"; + +export class Atari8_WASMMachine extends BaseWASIMachine + implements Machine, Probeable, VideoSource, AcceptsROM, FrameBased, AcceptsKeyInput, AcceptsPaddleInput { + + numTotalScanlines = 312; + cpuCyclesPerLine = 63; + + prgstart: number; + joymask0 = 0; + joymask1 = 0; + + loadROM(rom: Uint8Array) { + super.loadROM(rom); + this.reloadROM(); + } + reloadROM() { + if (this.sys) { + var result = this.exports.machine_load_rom(this.sys, this.romptr, this.romlen); + console.log('machine_load_rom', result); + //console.log(this.wasmFs.fs.existsSync('atari8.img'), result); + } + } + loadBIOS(srcArray: Uint8Array) { + super.loadBIOS(srcArray); + } + reset() { + super.reset(); + this.reloadROM(); + } + advanceFrame(trap: TrapCondition): number { + // TODO + this.exports.machine_start_frame(this.sys); + if (trap) { + this.advanceFrameClock(trap, 999999); // TODO? + } else { + this.exports.machine_advance_frame(this.sys); + } + this.syncVideo(); + this.syncAudio(); + return 1; + } + getCPUState() { + this.exports.machine_save_cpu_state(this.sys, this.stateptr); + var s = this.statearr; + var pc = s[6] + (s[7]<<8); + return { + PC:pc, + SP:s[2], + A:s[0], + X:s[3], + Y:s[4], + C:s[1] & 1, + Z:s[1] & 2, + I:s[1] & 4, + D:s[1] & 8, + V:s[1] & 64, + N:s[1] & 128, + o:this.readConst(pc), + } + } + saveState() { + var cpu = this.getCPUState(); + this.exports.machine_save_state(this.sys, this.stateptr); + return { + c: cpu, + state: this.statearr.slice(0), + //ram:this.statearr.slice(18640, 18640+0x200), // ZP and stack + }; + } + loadState(state): void { + this.statearr.set(state.state); + this.exports.machine_load_state(this.sys, this.stateptr); + } + getVideoParams() { + return { width: 384, height: 240, overscan: true, videoFrequency: 60 }; + } + pollControls() { + } + setKeyInput(key: number, code: number, flags: number): void { + // modifier flags + if (flags & KeyFlags.Shift) key |= 0x100; + if (flags & KeyFlags.Ctrl) key |= 0x200; + // keyboard -> joystick + var mask = 0; + if (key == 37) { key = 0x8; mask = 0x4; } // LEFT + if (key == 38) { key = 0xb; mask = 0x1; } // UP + if (key == 39) { key = 0x9; mask = 0x8; } // RIGHT + if (key == 40) { key = 0xa; mask = 0x2; } // DOWN + if (key == 32) { mask = 0x100; } // FIRE + // set machine inputs + if (flags & KeyFlags.KeyDown) { + this.exports.machine_key_down(this.sys, key); + this.joymask0 |= mask; + } else if (flags & KeyFlags.KeyUp) { + this.exports.machine_key_up(this.sys, key); + this.joymask0 &= ~mask; + } + this.setJoyInput(0, this.joymask0); + this.setJoyInput(1, this.joymask1); + } + setJoyInput(joy: number, mask: number) { + this.exports.machine_joy_set(this.sys, joy, mask); + } + setPaddleInput(controller: number, value: number): void { + this.exports.machine_paddle_set(this.sys, controller, value); + } + +} diff --git a/src/platform/atari8.ts b/src/platform/atari8.ts index 2257d423..1fc5180f 100644 --- a/src/platform/atari8.ts +++ b/src/platform/atari8.ts @@ -1,9 +1,8 @@ "use strict"; -import { Platform, Base6502Platform, BaseMAMEPlatform, getOpcodeMetadata_6502, getToolForFilename_6502 } from "../common/baseplatform"; -import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, dumpRAM, getMousePos } from "../common/emu"; -import { hex, lzgmini, stringToByteArray, lpad, rpad, rgb2bgr } from "../common/util"; -import { MasterAudio, POKEYDeviceChannel, newPOKEYAudio } from "../common/audio"; +import { Platform, BaseMAMEPlatform, getOpcodeMetadata_6502, getToolForFilename_6502, Base6502MachinePlatform } from "../common/baseplatform"; +import { PLATFORMS, Keys, makeKeycodeMap } from "../common/emu"; +import { Atari8_WASMMachine } from "../machine/atari8"; declare var jt; // for 6502 @@ -27,770 +26,42 @@ const ATARI8_KEYCODE_MAP = makeKeycodeMap([ [Keys.VK_ENTER, 0, 0], ]); -// ANTIC +const Atari800_MemoryMap = { main:[ + {name:'RAM',start:0x0,size:0x10000,type:'ram'}, + {name:'Left Cartridge ROM',start:0xa000,size:0x2000,type:'rom'}, + {name:'GTIA',start:0xd000,size:0x20,type:'io'}, + {name:'POKEY',start:0xd200,size:0x10,type:'io'}, + {name:'PIA',start:0xd300,size:0x04,type:'io'}, + {name:'ANTIC',start:0xd400,size:0x10,type:'io'}, + {name:'Cartridge Control Line',start:0xd600,size:0x100,type:'io'}, + {name:'ROM',start:0xd800,size:0x800,type:'rom'}, + {name:'ATARI Character Set',start:0xe000,size:0x400,type:'rom'}, + {name:'ROM',start:0xe400,size:0x1c00,type:'rom'}, +] } -// https://www.atarimax.com/jindroush.atari.org/atanttim.html -// http://www.virtualdub.org/blog/pivot/entry.php?id=243 -// http://www.beipmu.com/Antic_Timings.txt -// https://user.xmission.com/~trevin/atari/antic_regs.html -// https://user.xmission.com/~trevin/atari/antic_insns.html -// http://www.atarimuseum.com/videogames/consoles/5200/conv_to_5200.html - -const PF_LEFT = [999,64,48,32]; -const PF_RIGHT = [999,192,208,224]; - -const DMACTL = 0; -const CHACTL = 1; -const DLISTL = 2; -const DLISTH = 3; -const HSCROL = 4; -const VSCROL = 5; -const PMBASE = 7; -const CHBASE = 9; -const WSYNC = 10; -const VCOUNT = 11; -const PENH = 12; -const PENV = 13; -const NMIEN = 14; -const NMIRES = 15; -const NMIST = 15; - -const PFNONE = 0; -const PFNARROW = 1; -const PFNORMAL = 2; -const PFWIDE = 3; - -const NMIST_CYCLE = 12; -const NMI_CYCLE = 24; -const WSYNC_CYCLE = 212; - -const MODE_LINES = [ 0, 0, 7, 9, 7, 15, 7, 15, 7, 3, 3, 1, 0, 1, 0, 0 ]; -const MODE_PERIOD = [ 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 1, 0, 0, 0 ]; -const MODE_YPERIOD = [ 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 1, 0, 0, 0, 0 ]; - -class ANTIC { - regs = new Uint8Array(0x10); // registers - gtia : GTIA; // GTIA link - read : (address:number) => number; // bus read function - nmiPending : boolean = false; - - // derived by registers - pfwidth : number; // playfield width - left : number; - right : number; // left/right clocks for mode - - // a la minute - mode : number = 0; // current mode - period : number = 0; // current mode period bitmask - scanaddr : number = 0; // Scan Address (via LMS) - startaddr: number = 0; // Start of line Address - pfbyte : number = 0; // playfield byte fetched - ch : number = 0; // char read - linesleft : number = 0; // # of lines left in mode - yofs : number = 0; // yofs fine - v : number = 0; // vertical scanline # - h : number = 0; // horizontal color clock - - constructor(readfn) { - this.read = readfn; // bus read function - } - reset() { - this.regs[NMIEN] = 0x00; - this.regs[NMIST] = 0x1f; - this.setReg(DMACTL, 0x0); - } - saveState() { - return { - regs: this.regs.slice(0), - mode: this.mode, - period: this.period, - scanaddr: this.scanaddr, - startaddr: this.startaddr, - pfbyte: this.pfbyte, - ch: this.ch, - linesleft: this.linesleft, - yofs: this.yofs, - v: this.v, - h: this.h, - }; - } - loadState(s) { - for (let i=0; i<16; i++) - if (i != NMIRES) - this.setReg(i, s.regs[i]); - this.mode = s.mode; - this.period = s.period; - this.scanaddr = s.scanaddr; - this.startaddr = s.startaddr; - this.pfbyte = s.pfbyte; - this.ch = s.ch; - this.linesleft = s.linesleft; - this.yofs = s.yofs; - this.v = s.v; - this.h = s.h; - } - static stateToLongString(state) : string { - let s = ""; - s += "H: " + lpad(state.h,3) + " V: " + lpad(state.v,3) + " Linesleft: " + state.linesleft + "\n"; - s += "Mode: " + hex(state.mode,2) + " Period: " + (state.period+1) + "\n"; - s += "Addr: " + hex(state.scanaddr,4) + "\n"; - s += dumpRAM(state.regs, 0, 16).replace('$00', 'Regs'); - return s; - } - setReg(a:number, v:number) { - this.regs[a] = v; - switch (a) { - case DMACTL: - this.pfwidth = this.regs[DMACTL] & 3; - this.setLeftRight(); - break; - case NMIRES: - this.regs[NMIST] = 0x1f; - break; - } - } - setLeftRight() { - let offset = 4 << MODE_PERIOD[this.mode & 0xf]; - this.left = PF_LEFT[this.pfwidth]; - this.right = PF_RIGHT[this.pfwidth]; - } - readReg(a:number) { - switch (a) { - case NMIST: return this.regs[NMIST]; - default: return 0; - } - } - startline1() { - let stolen = 0; - if (this.linesleft) { - this.linesleft--; - if ((this.linesleft & MODE_YPERIOD[this.mode&0xf]) == 0) // use Y period - this.yofs++; - } - if (!this.linesleft) { - if (this.mode & 0x80) { - this.triggerInterrupt(0x80); // Display List Interrupt (DLI) - } - this.mode = this.nextInsn(); - this.setLeftRight(); - stolen++; - if ((this.mode & 0xf) == 0) { // N Blank Lines - this.linesleft = (this.mode >> 4) + 1; - } else { - this.linesleft = MODE_LINES[this.mode & 0xf]; - this.period = (1<> 8; - return b; - } - - nextScreen() : number { - let b = this.read(this.scanaddr); - this.scanaddr = ((this.scanaddr+1) & 0xfff) | (this.scanaddr & ~0xfff); - return b; - } - - clockPulse4() : number { - let nc = 4; // number of cycles not stolen by DMA - let h = this.h; - // in overscan region? - if (this.v >= 240) { - // interrupts on last scanline of frame - if (this.v == 240) { - if (h == NMIST_CYCLE) - this.regs[NMIST] = 0x5f; - else if (h == NMI_CYCLE) - this.triggerInterrupt(0x40); - } - } - // DMA enabled? - else if (this.regs[DMACTL] & 0x20) { - // read line data? - switch (h) { - case 0: nc -= this.startline1(); break; - case 4: nc -= this.startline2(); break; - case 8: nc -= this.startline3(); break; - case 12: nc -= this.startline4(); break; - default: - let mode = this.mode & 0xf; - if (h >= 48 && h < 120) nc--; // steal 1 clock for memory refresh - if (h >= this.left && h < this.right && mode >= 2) { // fetch screen byte? - if (((h>>2) & this.period) == 0) { // use period interval - if (mode < 8) { // character mode - let ch = this.ch = this.nextScreen(); - let addrofs = this.yofs; - let chbase = this.regs[CHBASE]; - // modes 6 & 7 - if ((mode & 0xe) == 6) { // or 7 - ch &= 0x3f; - chbase &= 0xfe; - } else { - ch &= 0x7f; - chbase &= 0xfc; - } - let addr = (ch<<3) + (chbase<<8); - // modes 2 & 3 - if ((mode & 0xe) == 2) { // or 3 - let chactl = this.regs[CHACTL]; - if (mode == 3 && ch >= 0x60) { - // TODO - } - if (chactl & 4) - this.pfbyte = this.read(addr + (addrofs ^ 7)); // mirror - else - this.pfbyte = this.read(addr + addrofs); - if (this.ch & 0x80) { - if (chactl & 1) - this.pfbyte = 0x0; // blank - if (chactl & 2) - this.pfbyte ^= 0xff; // invert - } - } else { - this.pfbyte = this.read(addr + addrofs); - } - nc -= 2; - } else { // map mode - this.pfbyte = this.nextScreen(); - nc -= 1; - } - } - } - break; - } - } - // next scanline? - this.h += 4; - if (this.h >= 228) { - this.h = 0; - this.v++; - if (this.v >= 262) { - this.v = 0; - } - } - return nc; - } +function getToolForFilename_Atari8(fn:string) { + if (fn.endsWith(".bas") || fn.endsWith(".fb") || fn.endsWith(".fbi")) return "fastbasic"; + else return getToolForFilename_6502(fn); } -// GTIA -// https://user.xmission.com/~trevin/atari/gtia_regs.html - -// write regs -const HPOSP0 = 0x0; -const HPOSM0 = 0x4; -const SIZEP0 = 0x8; -const SIZEM = 0x0c; -const GRAFP0 = 0x0d; -const GRAFM = 0x11; -const COLPM0 = 0x12; -const COLPF0 = 0x16; -const COLPF1 = 0x17; -const COLPF2 = 0x18; -const COLPF3 = 0x19; -const COLBK = 0x1a; -const PRIOR = 0x1b; -const VDELAY = 0x1c; -const GRACTL = 0x1d; -const HITCLR = 0x1e; -const CONSPK = 0x1f; -// read regs -const M0PF = 0x0; -const P0PF = 0x4; -const M0PL = 0x8; -const P0PL = 0xc; -const TRIG0 = 0x10; -const CONSOL = 0x1f; - -class GTIA { - regs = new Uint8Array(0x20); - count : number = 0; - antic : ANTIC; - - constructor(antic : ANTIC) { - this.antic = antic; - } - saveState() { - return { - regs: this.regs.slice(0), - count: this.count, - }; - } - loadState(s) { - for (let i=0; i<32; i++) - this.setReg(i, s.regs[i]); - this.count = s.count; - } - setReg(a:number, v:number) { - this.regs[a] = v; - switch (a) { - } - } - clockPulse() : number { - let pixel = (this.antic.pfbyte & 128) ? 1 : 0; - let col = 0; - switch (this.antic.mode & 0xf) { - // blank line - case 0: - case 1: - col = this.regs[COLBK]; - break; - // normal text mode - case 2: - case 3: - default: - if (pixel) - col = (this.regs[COLPF1] & 0xf) | (this.regs[COLPF2] & 0xf0); - else - col = this.regs[COLPF2]; - if ((this.count & this.antic.period) == 0) - this.antic.pfbyte <<= 1; - break; - // 4bpp mode - case 4: - case 5: - col = (this.antic.pfbyte>>6) & 3; - if ((this.antic.ch & 0x80) && col==3) - col = 4; // 5th color - col = col ? this.regs[COLPF0-1+col] : this.regs[COLBK]; - if ((this.count & 1) == 0) - this.antic.pfbyte <<= 2; - break; - // 4 colors per 64 chars mode - case 6: - case 7: - if (pixel) - col = this.regs[COLPF0 + (this.antic.ch>>6)]; - else - col = this.regs[COLBK]; - if ((this.count & this.antic.period) == 0) - this.antic.pfbyte <<= 1; - break; - } - this.count = (this.count + 1) & 0xff; - return COLORS_RGBA[col]; - } - static stateToLongString(state) : string { - let s = ""; - s += dumpRAM(state.regs, 0, 32); - return s; - } -} - -const _Atari8Platform = function(mainElement) { - // http://www.ataripreservation.org/websites/freddy.offenga/megazine/ISSUE5-PALNTSC.html - const cpuFrequency = 1789773; - const linesPerFrame = 262; - const colorClocksPerLine = 228; - // TODO: for 400/800/5200 - const romLength = 0x8000; - - var cpu; - var ram : RAM; - var rom : Uint8Array; - var bios : Uint8Array; - var bus; - var video, audio; - var timer; // TODO : AnimationTimer; - var antic : ANTIC; - var gtia : GTIA; - var inputs = new Uint8Array(4); - - class Atari8Platform extends Base6502Platform implements Platform { - - getPresets() { - return Atari8_PRESETS; - } - start() { - cpu = new jt.M6502(); - ram = new RAM(0x4000); // TODO - bios = new lzgmini().decode(stringToByteArray(atob(ALTIRRA_SUPERKERNEL_LZG))); - bus = { - // TODO: https://github.com/dmlloyd/atari800/blob/master/DOC/cart.txt - // TODO: http://atariage.com/forums/topic/169971-5200-memory-map/ - read: newAddressDecoder([ - [0x0000, 0x3fff, 0x3fff, function(a) { return ram.mem[a]; }], - [0x4000, 0xbfff, 0xffff, function(a) { return rom ? rom[a-0x4000] : 0; }], - [0xd400, 0xd4ff, 0xf, function(a) { return antic.readReg(a); }], - [0xf800, 0xffff, 0x7ff, function(a) { return bios[a]; }], - ]), - write: newAddressDecoder([ - [0x0000, 0x3fff, 0xffff, function(a,v) { ram.mem[a] = v; }], - [0xc000, 0xcfff, 0x1f, function(a,v) { gtia.regs[a] = v; }], - [0xd400, 0xd4ff, 0xf, function(a,v) { antic.setReg(a,v); }], - [0xe800, 0xefff, 0xf, function(a,v) { audio.pokey1.setRegister(a, v); }], - ]), - }; - cpu.connectBus(bus); - // create support chips - antic = new ANTIC(bus.read); - gtia = new GTIA(antic); - // create video/audio - video = new RasterVideo(mainElement, 352, 192); - audio = newPOKEYAudio(1); - video.create(); - setKeyboardFromMap(video, inputs, ATARI8_KEYCODE_MAP, (o,key,code,flags) => { - // TODO - }); - timer = new AnimationTimer(60, this.nextFrame.bind(this)); - // setup mouse events - var rasterPosBreakFn = (e) => { - if (e.ctrlKey) { - var clickpos = getMousePos(e.target, e); - this.runEval( (c) => { - var pos = {x:antic.h, y:this.getRasterScanline()}; - return (pos.x == (clickpos.x&~3)) && (pos.y == (clickpos.y|0)); - }); - } - }; - var jacanvas = $("#emulator").find("canvas"); - jacanvas.mousedown(rasterPosBreakFn); - } - - advance(novideo : boolean) : number { - var idata = video.getFrameData(); - var iofs = 0; - var debugCond = this.getDebugCallback(); - var rgb; - var freeClocks = 0; - var totalClocks = 0; - // load controls - // TODO - gtia.regs[0x10] = inputs[0] ^ 1; - // visible lines - for (var sl=0; sl 0) { - freeClocks--; - if (debugCond && debugCond()) { - debugCond = null; - i = 999; - sl = 999; - break; - } - cpu.clockPulse(); - totalClocks++; - } - // 4 ANTIC pulses = 8 pixels - if (antic.v >= 24 && antic.h >= 44 && antic.h < 44+176) { // TODO: const - for (var j=0; j<8; j++) { - rgb = gtia.clockPulse(); - idata[iofs++] = rgb; - } - } - } - } - // update video frame - if (!novideo) { - video.updateFrame(); - // set background/border color - let bkcol = gtia.regs[COLBK]; - $(video.canvas).css('background-color', COLORS_WEB[bkcol]); - } - return totalClocks; - } - - loadROM(title, data) { - rom = padBytes(data, romLength); - this.reset(); - } - - loadBIOS(title, data) { - bios = padBytes(data, 0x800); - this.reset(); - } - - isRunning() { - return timer.isRunning(); - } - pause() { - timer.stop(); - audio.stop(); - } - resume() { - timer.start(); - audio.start(); - } - reset() { - cpu.reset(); - // execute until out of BIOS - for (var i=0; i<20000; i++) { - cpu.clockPulse(); - if (this.getCPUState().PC < 0xf000) - break; - } - } - readAddress(addr : number) { - return ((addr & 0xf000) != 0xd000) ? bus.read(addr) : null; // ignore I/O space - } - - loadState(state) { - this.unfixPC(state.c); - cpu.loadState(state.c); - this.fixPC(state.c); - ram.mem.set(state.b); - antic.loadState(state.antic); - gtia.loadState(state.gtia); - this.loadControlsState(state); - } - saveState() { - return { - c:this.getCPUState(), - b:ram.mem.slice(0), - antic:antic.saveState(), - gtia:gtia.saveState(), - in:inputs.slice(0) - }; - } - loadControlsState(state) { - inputs.set(state.in); - } - saveControlsState() { - return { - in:inputs.slice(0) - }; - } - getCPUState() { - return this.fixPC(cpu.saveState()); - } - getRasterScanline() { - return antic.v; - } - getDebugCategories() { - return super.getDebugCategories().concat(['ANTIC','GTIA']); - } - getDebugInfo(category, state) { - switch (category) { - case 'ANTIC': return ANTIC.stateToLongString(state.antic); - case 'GTIA': return GTIA.stateToLongString(state.gtia); - default: return super.getDebugInfo(category, state); - } - } - } - - return new Atari8Platform(); // return inner class from constructor -}; - -// Atari 800 -const _Atari800Platform = function(mainElement) { - this.__proto__ = new (_Atari8Platform as any)(mainElement); -} - -// Atari 5200 -const _Atari5200Platform = function(mainElement) { - this.__proto__ = new (_Atari8Platform as any)(mainElement); -} - -/// - -const ATARI_NTSC_RGB = [ - 0x000000, // 00 - 0x404040, // 02 - 0x6c6c6c, // 04 - 0x909090, // 06 - 0xb0b0b0, // 08 - 0xc8c8c8, // 0A - 0xdcdcdc, // 0C - 0xf4f4f4, // 0E - 0x004444, // 10 - 0x106464, // 12 - 0x248484, // 14 - 0x34a0a0, // 16 - 0x40b8b8, // 18 - 0x50d0d0, // 1A - 0x5ce8e8, // 1C - 0x68fcfc, // 1E - 0x002870, // 20 - 0x144484, // 22 - 0x285c98, // 24 - 0x3c78ac, // 26 - 0x4c8cbc, // 28 - 0x5ca0cc, // 2A - 0x68b4dc, // 2C - 0x78c8ec, // 2E - 0x001884, // 30 - 0x183498, // 32 - 0x3050ac, // 34 - 0x4868c0, // 36 - 0x5c80d0, // 38 - 0x7094e0, // 3A - 0x80a8ec, // 3C - 0x94bcfc, // 3E - 0x000088, // 40 - 0x20209c, // 42 - 0x3c3cb0, // 44 - 0x5858c0, // 46 - 0x7070d0, // 48 - 0x8888e0, // 4A - 0xa0a0ec, // 4C - 0xb4b4fc, // 4E - 0x5c0078, // 50 - 0x74208c, // 52 - 0x883ca0, // 54 - 0x9c58b0, // 56 - 0xb070c0, // 58 - 0xc084d0, // 5A - 0xd09cdc, // 5C - 0xe0b0ec, // 5E - 0x780048, // 60 - 0x902060, // 62 - 0xa43c78, // 64 - 0xb8588c, // 66 - 0xcc70a0, // 68 - 0xdc84b4, // 6A - 0xec9cc4, // 6C - 0xfcb0d4, // 6E - 0x840014, // 70 - 0x982030, // 72 - 0xac3c4c, // 74 - 0xc05868, // 76 - 0xd0707c, // 78 - 0xe08894, // 7A - 0xeca0a8, // 7C - 0xfcb4bc, // 7E - 0x880000, // 80 - 0x9c201c, // 82 - 0xb04038, // 84 - 0xc05c50, // 86 - 0xd07468, // 88 - 0xe08c7c, // 8A - 0xeca490, // 8C - 0xfcb8a4, // 8E - 0x7c1800, // 90 - 0x90381c, // 92 - 0xa85438, // 94 - 0xbc7050, // 96 - 0xcc8868, // 98 - 0xdc9c7c, // 9A - 0xecb490, // 9C - 0xfcc8a4, // 9E - 0x5c2c00, // A0 - 0x784c1c, // A2 - 0x906838, // A4 - 0xac8450, // A6 - 0xc09c68, // A8 - 0xd4b47c, // AA - 0xe8cc90, // AC - 0xfce0a4, // AE - 0x2c3c00, // B0 - 0x485c1c, // B2 - 0x647c38, // B4 - 0x809c50, // B6 - 0x94b468, // B8 - 0xacd07c, // BA - 0xc0e490, // BC - 0xd4fca4, // BE - 0x003c00, // C0 - 0x205c20, // C2 - 0x407c40, // C4 - 0x5c9c5c, // C6 - 0x74b474, // C8 - 0x8cd08c, // CA - 0xa4e4a4, // CC - 0xb8fcb8, // CE - 0x003814, // D0 - 0x1c5c34, // D2 - 0x387c50, // D4 - 0x50986c, // D6 - 0x68b484, // D8 - 0x7ccc9c, // DA - 0x90e4b4, // DC - 0xa4fcc8, // DE - 0x00302c, // E0 - 0x1c504c, // E2 - 0x347068, // E4 - 0x4c8c84, // E6 - 0x64a89c, // E8 - 0x78c0b4, // EA - 0x88d4cc, // EC - 0x9cece0, // EE - 0x002844, // F0 - 0x184864, // F2 - 0x306884, // F4 - 0x4484a0, // F6 - 0x589cb8, // F8 - 0x6cb4d0, // FA - 0x7ccce8, // FC - 0x8ce0fc // FE -]; - -var COLORS_RGBA = new Uint32Array(256); -var COLORS_WEB = []; -for (var i=0; i<256; i++) { - COLORS_RGBA[i] = ATARI_NTSC_RGB[i>>1] | 0xff000000; - COLORS_WEB[i] = "#"+hex(rgb2bgr(ATARI_NTSC_RGB[i>>1]),6); -} - -/// - /// MAME support abstract class Atari8MAMEPlatform extends BaseMAMEPlatform { getPresets() { return Atari8_PRESETS; } - getToolForFilename = function(fn:string) { - if (fn.endsWith(".bas") || fn.endsWith(".fb") || fn.endsWith(".fbi")) return "fastbasic"; - else return getToolForFilename_6502(fn); + getToolForFilename = getToolForFilename_Atari8; + getOpcodeMetadata = getOpcodeMetadata_6502; + getDefaultExtension() { return ".asm"; }; + showHelp(tool:string, ident:string) { + if (tool == 'fastbasic') + window.open("https://github.com/dmsc/fastbasic/blob/master/manual.md", "_help"); + else + window.open("https://atariwiki.org/wiki/Wiki.jsp?page=Assembler", "_help"); // TODO } +} + +abstract class Atari8WASIMAMEPlatform extends BaseMAMEPlatform { + getPresets() { return Atari8_PRESETS; } + getToolForFilename = getToolForFilename_Atari8; getOpcodeMetadata = getOpcodeMetadata_6502; getDefaultExtension() { return ".asm"; }; showHelp(tool:string, ident:string) { @@ -825,18 +96,7 @@ class Atari800MAMEPlatform extends Atari8MAMEPlatform implements Platform { } start() { } - getMemoryMap = function() { return { main:[ - {name:'RAM',start:0x0,size:0x10000,type:'ram'}, - {name:'Left Cartridge ROM',start:0xa000,size:0x2000,type:'rom'}, - {name:'GTIA',start:0xd000,size:0x20,type:'io'}, - {name:'POKEY',start:0xd200,size:0x10,type:'io'}, - {name:'PIA',start:0xd300,size:0x04,type:'io'}, - {name:'ANTIC',start:0xd400,size:0x10,type:'io'}, - {name:'Cartridge Control Line',start:0xd600,size:0x100,type:'io'}, - {name:'ROM',start:0xd800,size:0x800,type:'rom'}, - {name:'ATARI Character Set',start:0xe000,size:0x400,type:'rom'}, - {name:'ROM',start:0xe400,size:0x1c00,type:'rom'}, - ] } }; + getMemoryMap = function() { return Atari800_MemoryMap }; } class Atari5200MAMEPlatform extends Atari8MAMEPlatform implements Platform { @@ -898,9 +158,32 @@ hQypD4UNqQCFDiVhDyVhEKkEjRvAogq9wh0nIB1cIoUHqcCNDtQdFQWpIIUGqQKND+ipwIUZIhapeMUC 0Pxs/r9wcHBCABCCB0HC/SFsdGlycmEAFRIQEAAyLy0AK2VybmVsGWpyJQMub3cAcGxheWluZxoZDxUZ a58lHiUcJQkD/Lj8svyh/gL9svxI5gzQBBkiJhkj9SUfJR8lHiUBI/0x/QD8`; + +/// WASM Atari8 platform +class Atari8WASMPlatform extends Base6502MachinePlatform implements Platform { + + newMachine() { return new Atari8_WASMMachine('atari8'); } + getPresets() { return Atari800_PRESETS; } + getDefaultExtension() { return ".c"; }; + getToolForFilename = getToolForFilename_Atari8; + readAddress(a) { return this.machine.readConst(a); } + getMemoryMap() { return Atari800_MemoryMap; } + showHelp() { + // TODO + } + getROMExtension(rom:Uint8Array) { + // TODO + if (rom && rom[0] == 0x01 && rom[1] == 0x08) return ".prg"; + else return ".bin"; + } +} + +class Atari800WASMPlatform extends Atari8WASMPlatform { + +} + /// -PLATFORMS['atari8-800xl'] = _Atari800Platform; -PLATFORMS['atari8-5200'] = _Atari5200Platform; -PLATFORMS['atari8-800xl.mame'] = Atari800MAMEPlatform; -PLATFORMS['atari8-5200.mame'] = Atari5200MAMEPlatform; +PLATFORMS['atari8-800xl.mame'] = Atari800MAMEPlatform +PLATFORMS['atari8-5200.mame'] = Atari5200MAMEPlatform +PLATFORMS['atari8-800xl'] = Atari800WASMPlatform diff --git a/src/platform/c64.ts b/src/platform/c64.ts index a1b16a4e..3113976e 100644 --- a/src/platform/c64.ts +++ b/src/platform/c64.ts @@ -47,7 +47,7 @@ class C64WASMPlatform extends Base6502MachinePlatform implement readAddress(a) { return this.machine.readConst(a); } getMemoryMap() { return C64_MEMORY_MAP; } showHelp() { - window.open("https://sta.c64.org/cbm64mem.html", "_help"); + window.open("https://8bitworkshop.com/docs/platforms/c64/", "_help"); } getROMExtension(rom:Uint8Array) { /* diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index d88d36cb..72e50f2c 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -258,16 +258,25 @@ var PLATFORM_PARAMS = { libargs: ['apple2.lib'], }, 'atari8-800xl': { + arch: '6502', + define: ['__ATARI__'], + cfgfile: 'atari.cfg', + libargs: ['atari.lib'], + fastbasic_cfgfile: 'fastbasic-cart.cfg', + }, + 'atari8-800xl.cart': { arch: '6502', define: ['__ATARI__'], cfgfile: 'atari-cart.cfg', libargs: ['atari.lib', '-D', '__CARTFLAGS__=4'], + fastbasic_cfgfile: 'fastbasic-cart.cfg', }, 'atari8-5200': { arch: '6502', define: ['__ATARI5200__'], cfgfile: 'atari5200.cfg', libargs: ['atari5200.lib', '-D', '__CARTFLAGS__=255'], + fastbasic_cfgfile: 'fastbasic-cart.cfg', }, 'verilog': { arch: 'verilog', @@ -2770,10 +2779,11 @@ function compileFastBasic(step:BuildStep) { }); var FS = fastbasic['FS']; populateFiles(step, FS); - params.libargs = ['fastbasic-int.lib']; - params.cfgfile = 'fastbasic-cart.cfg'; + var libfile = 'fastbasic-int.lib' + params.libargs = [libfile]; + params.cfgfile = params.fastbasic_cfgfile; //params.extra_compile_args = ["--asm-define", "NO_SMCODE"]; - params.extra_link_files = ['fastbasic-int.lib', 'fastbasic-cart.cfg']; + params.extra_link_files = [libfile, params.cfgfile]; //fixParamsWithDefines(step.path, params); var args = [step.path, destpath]; execMain(step, fastbasic, args);