diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
index 52c2d8c7..385b2fa8 100644
--- a/.github/workflows/node.js.yml
+++ b/.github/workflows/node.js.yml
@@ -33,3 +33,9 @@ jobs:
- run: npm test
env:
TEST8BIT_GITHUB_TOKEN: ${{ secrets.TEST8BIT_GITHUB_TOKEN }}
+ - run: make distro
+ - name: Deploy
+ uses: JamesIves/github-pages-deploy-action@v4.2.5
+ with:
+ branch: gh-pages
+ folder: tmp/dist
diff --git a/README.md b/README.md
index ef77a928..b2bf448f 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,12 @@
# 8bitworkshop
-![example workflow](https://github.com/sehugg/8bitworkshop/actions/workflows/node.js.yml/badge.svg)
+![Build Status](https://github.com/sehugg/8bitworkshop/actions/workflows/node.js.yml/badge.svg)
## Use Online
* Latest release: https://8bitworkshop.com/
-* Dev build: https://8bitworkshop.com/dev/
+* Latest Github build: https://sehugg.github.io/8bitworkshop/
## Install Locally
@@ -35,11 +35,11 @@ make tsweb
npm test
```
-Note: Github tests may fail due to lack of permissions.
+Note: Github tests may fail due to lack of API key.
## License
-Copyright © 2016-2021 [Steven Hugg](https://github.com/sehugg).
+Copyright © 2016-2022 [Steven Hugg](https://github.com/sehugg).
This project is [GPL-3.0](https://github.com/sehugg/8bitworkshop/blob/master/LICENSE) licensed.
diff --git a/index.html b/index.html
index ac0b20ae..d2ba288a 100644
--- a/index.html
+++ b/index.html
@@ -208,6 +208,8 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
Atari 2600 (MAME)
ColecoVision (MAME)
NES (MAME)
+
+ Williams (6809)
diff --git a/presets/williams/bitmap_rle.c b/presets/williams/bitmap_rle.c
new file mode 100644
index 00000000..50382669
--- /dev/null
+++ b/presets/williams/bitmap_rle.c
@@ -0,0 +1,137 @@
+
+#include "williams.h"
+
+word swapw(word a) {
+ return (a >> 8) | (a << 8);
+}
+
+const byte example_tga[] = {
+0x00,0x01,0x09,0x00,0x00,0x08,0x00,0x18,0x00,0x00,0x00,0x00,0xc0,0x00,0x8b,0x00,0x08,0x00,0x00,0x00,0x00,0x32,0x29,0x2e,0x66,0x3b,0x4d,0x9f,0x42,0x57,0xc5,0x54,0xbe,0xe6,0xe4,0xe3,0xbe,0xab,0xb4,0xc1,0x9c,0x67,0xff,0x00,0xbf,0x00,0xff,0x00,0xbf,0x00,0xfc,0x00,0x01,0x04,0x04,0xc0,0x00,0xfb,0x00,0x82,0x04,0xc0,0x00,0xfb,0x00,0x82,0x04,0xc0,0x00,0xfa,0x00,0x82,0x04,0xc1,0x00,0xfa,0x00,0x82,0x04,0xc1,0x00,0xf9,0x00,0x82,0x04,0xc2,0x00,0xf8,0x00,0x82,0x04,0xc3,0x00,0xf8,0x00,0x82,0x04,0xc3,0x00,0xcd,0x00,0x03,0x04,0x04,0x00,0x00,0x83,0x04,0xa2,0x00,0x01,0x04,0x04,0xc4,0x00,0xcc,0x00,0x89,0x04,0xa0,0x00,0x82,0x04,0xc4,0x00,0xcc,0x00,0x89,
+0x04,0xa0,0x00,0x01,0x04,0x04,0xc5,0x00,0xcb,0x00,0x84,0x04,0x82,0x01,0x83,0x04,0x9e,0x00,0x82,0x04,0xc5,0x00,0xca,0x00,0x84,0x04,0x83,0x01,0x02,0x06,0x04,0x04,0x9f,0x00,0x01,0x04,0x04,0xc6,0x00,0xca,0x00,0x83,0x04,0x84,0x02,0x02,0x06,0x04,0x04,0x9e,0x00,0x82,0x04,0xc6,0x00,0xc9,0x00,0x83,0x04,0x02,0x02,0x02,0x03,0x82,0x04,0x01,0x06,0x04,0x9f,0x00,0x01,0x04,0x04,0xc7,0x00,0xc9,0x00,0x82,0x04,0x01,0x02,0x01,0x82,0x02,0x00,0x03,0x82,0x04,0x9a,0x00,0x01,0x04,0x04,0x82,0x00,0x01,0x04,0x04,0xc7,0x00,0xc8,0x00,0x83,0x04,0x04,0x01,0x02,0x02,0x03,0x03,0x82,0x04,0x99,0x00,0x83,0x04,0x03,0x00,0x00,0x04,0x04,0xc8,0x00,0xc8,0x00,0x82,0x04,0x01,
+0x02,0x02,0x82,0x03,0x01,0x04,0x04,0x8d,0x00,0x00,0x04,0x8b,0x00,0x88,0x04,0xc8,0x00,0xc7,0x00,0x83,0x04,0x01,0x02,0x03,0x83,0x04,0x8d,0x00,0x82,0x04,0x8a,0x00,0x87,0x04,0xc9,0x00,0xc7,0x00,0x82,0x04,0x01,0x02,0x03,0x85,0x04,0x8b,0x00,0x83,0x04,0x89,0x00,0x83,0x04,0x00,0x03,0x83,0x04,0xc9,0x00,0xc6,0x00,0x82,0x04,0x01,0x03,0x02,0x8b,0x04,0x85,0x00,0x84,0x04,0x03,0x00,0x00,0x04,0x04,0x84,0x00,0x84,0x04,0x03,0x02,0x06,0x04,0x04,0x87,0x00,0x00,0x04,0xc1,0x00,0xa2,0x00,0x8d,0x05,0x82,0x04,0x8a,0x05,0x05,0x00,0x00,0x05,0x05,0x00,0x00,0x84,0x04,0x02,0x03,0x06,0x06,0x8b,0x04,0x02,0x05,0x05,0x06,0x8b,0x04,0x02,0x06,0x05,0x06,0x84,0x04,0x04,
+0x02,0x03,0x05,0x04,0x04,0x83,0x00,0x01,0x05,0x05,0x82,0x04,0xa2,0x05,0x9e,0x00,0xa1,0x00,0x01,0x05,0x06,0xa5,0x04,0x00,0x06,0x8e,0x04,0x01,0x06,0x06,0x84,0x04,0x01,0x02,0x06,0x85,0x04,0x00,0x06,0x85,0x04,0x03,0x02,0x04,0x06,0x04,0x85,0x00,0x04,0x05,0x04,0x04,0x03,0x07,0x9b,0x06,0x00,0x07,0x83,0x06,0x01,0x05,0x05,0x9d,0x00,0xa2,0x00,0x00,0x06,0x95,0x04,0x00,0x03,0x83,0x04,0x04,0x03,0x04,0x04,0x03,0x03,0x8a,0x04,0x04,0x03,0x02,0x01,0x01,0x02,0x84,0x04,0x00,0x03,0x85,0x04,0x02,0x02,0x02,0x06,0x84,0x04,0x00,0x03,0x85,0x04,0x01,0x02,0x03,0x82,0x04,0x86,0x00,0x02,0x04,0x03,0x02,0x98,0x03,0x02,0x07,0x07,0x03,0x85,0x07,0x00,0x06,0x9e,0x00,
+0xa3,0x00,0x02,0x04,0x04,0x03,0x83,0x02,0x03,0x03,0x02,0x03,0x04,0x82,0x02,0x83,0x04,0x00,0x03,0x8c,0x02,0x87,0x04,0x00,0x02,0x86,0x01,0x83,0x04,0x01,0x03,0x03,0x85,0x04,0x02,0x01,0x02,0x05,0x83,0x04,0x00,0x02,0x85,0x04,0x02,0x03,0x01,0x03,0x82,0x04,0x85,0x00,0x06,0x04,0x04,0x01,0x01,0x02,0x02,0x03,0x91,0x02,0x06,0x03,0x03,0x02,0x03,0x03,0x02,0x02,0x83,0x03,0x02,0x07,0x06,0x05,0x9e,0x00,0xa3,0x00,0x02,0x05,0x04,0x04,0x83,0x02,0x03,0x01,0x01,0x02,0x04,0x82,0x02,0x00,0x03,0x82,0x04,0x8c,0x02,0x00,0x03,0x85,0x04,0x00,0x03,0x85,0x01,0x03,0x02,0x02,0x03,0x05,0x82,0x04,0x00,0x02,0x85,0x04,0x01,0x02,0x01,0x85,0x04,0x00,0x02,0x85,0x04,0x01,
+0x01,0x02,0x82,0x04,0x86,0x00,0x02,0x04,0x02,0x01,0x8b,0x02,0x01,0x03,0x03,0x87,0x02,0x03,0x03,0x03,0x02,0x03,0x84,0x02,0x03,0x03,0x03,0x06,0x05,0x9f,0x00,0xa4,0x00,0x02,0x04,0x04,0x02,0x82,0x01,0x82,0x02,0x04,0x03,0x04,0x02,0x02,0x03,0x82,0x04,0x8c,0x02,0x85,0x04,0x84,0x01,0x83,0x02,0x02,0x03,0x05,0x06,0x82,0x04,0x00,0x02,0x84,0x04,0x02,0x03,0x01,0x02,0x84,0x04,0x00,0x02,0x85,0x04,0x02,0x03,0x01,0x03,0x82,0x04,0x85,0x00,0x02,0x04,0x03,0x01,0x8c,0x02,0x01,0x03,0x03,0x86,0x02,0x01,0x03,0x07,0x82,0x03,0x84,0x02,0x02,0x03,0x07,0x06,0xa0,0x00,0xa4,0x00,0x04,0x05,0x04,0x04,0x02,0x01,0x84,0x02,0x07,0x04,0x03,0x02,0x02,0x03,0x04,0x04,0x03,
+0x8b,0x02,0x83,0x04,0x00,0x02,0x83,0x01,0x85,0x02,0x84,0x04,0x01,0x01,0x02,0x84,0x04,0x01,0x02,0x01,0x85,0x04,0x00,0x03,0x85,0x04,0x01,0x02,0x02,0x83,0x04,0x85,0x00,0x02,0x04,0x01,0x01,0x84,0x02,0x00,0x03,0x88,0x02,0x00,0x03,0x85,0x02,0x00,0x03,0x87,0x02,0x03,0x03,0x03,0x06,0x05,0xa0,0x00,0xa5,0x00,0x02,0x04,0x04,0x03,0x84,0x02,0x05,0x01,0x03,0x04,0x02,0x02,0x03,0x82,0x04,0x8a,0x02,0x00,0x03,0x83,0x04,0x82,0x01,0x83,0x02,0x00,0x03,0x82,0x02,0x00,0x06,0x82,0x04,0x01,0x02,0x01,0x84,0x04,0x02,0x03,0x01,0x03,0x84,0x04,0x01,0x03,0x06,0x85,0x04,0x00,0x02,0x84,0x04,0x84,0x00,0x02,0x04,0x02,0x01,0x85,0x02,0x02,0x03,0x06,0x03,0x8d,0x02,0x03,
+0x03,0x02,0x02,0x03,0x83,0x02,0x03,0x03,0x03,0x07,0x06,0xa1,0x00,0xa6,0x00,0x01,0x04,0x04,0x86,0x02,0x03,0x04,0x03,0x02,0x02,0x82,0x04,0x00,0x03,0x89,0x02,0x83,0x04,0x02,0x02,0x01,0x01,0x87,0x02,0x83,0x04,0x02,0x03,0x01,0x01,0x84,0x04,0x02,0x02,0x02,0x06,0x87,0x04,0x00,0x03,0x88,0x04,0x84,0x00,0x03,0x04,0x04,0x01,0x01,0x85,0x02,0x03,0x07,0x05,0x06,0x03,0x8b,0x02,0x03,0x03,0x02,0x02,0x03,0x84,0x02,0x03,0x03,0x07,0x06,0x05,0xa1,0x00,0xa6,0x00,0x02,0x05,0x04,0x03,0x85,0x02,0x04,0x03,0x04,0x02,0x02,0x03,0x82,0x04,0x89,0x02,0x83,0x04,0x89,0x02,0x83,0x04,0x03,0x03,0x01,0x01,0x02,0x84,0x04,0x00,0x02,0x88,0x04,0x01,0x02,0x02,0x85,0x04,0x02,
+0x02,0x06,0x04,0x84,0x00,0x02,0x04,0x01,0x01,0x86,0x02,0x02,0x07,0x06,0x07,0x8c,0x02,0x03,0x03,0x02,0x02,0x07,0x84,0x02,0x02,0x03,0x06,0x05,0xa2,0x00,0xa7,0x00,0x04,0x04,0x04,0x03,0x06,0x03,0x83,0x02,0x00,0x04,0x82,0x02,0x82,0x04,0x00,0x03,0x87,0x02,0x00,0x03,0x82,0x04,0x01,0x03,0x01,0x87,0x02,0x84,0x04,0x03,0x01,0x01,0x02,0x02,0x87,0x04,0x00,0x02,0x84,0x04,0x03,0x03,0x01,0x01,0x03,0x82,0x04,0x04,0x03,0x02,0x01,0x06,0x04,0x83,0x00,0x02,0x04,0x02,0x01,0x87,0x02,0x82,0x03,0x8b,0x02,0x0b,0x03,0x02,0x02,0x03,0x02,0x02,0x01,0x02,0x02,0x03,0x07,0x06,0xa3,0x00,0xa7,0x00,0x03,0x05,0x04,0x04,0x03,0x84,0x02,0x07,0x03,0x04,0x02,0x02,0x03,0x04,
+0x04,0x03,0x87,0x02,0x83,0x04,0x88,0x02,0x84,0x04,0x01,0x01,0x01,0x82,0x02,0x86,0x04,0x01,0x02,0x01,0x84,0x04,0x83,0x01,0x82,0x02,0x0b,0x01,0x01,0x02,0x06,0x04,0x04,0x00,0x00,0x04,0x03,0x01,0x01,0x88,0x02,0x01,0x03,0x03,0x87,0x02,0x07,0x03,0x02,0x02,0x03,0x03,0x02,0x02,0x03,0x83,0x02,0x03,0x03,0x03,0x06,0x05,0xa3,0x00,0xa8,0x00,0x02,0x06,0x04,0x03,0x85,0x02,0x03,0x04,0x03,0x02,0x03,0x82,0x04,0x00,0x03,0x86,0x02,0x83,0x04,0x87,0x02,0x84,0x04,0x01,0x01,0x01,0x84,0x02,0x84,0x04,0x00,0x02,0x82,0x01,0x82,0x04,0x03,0x01,0x01,0x02,0x02,0x85,0x01,0x00,0x02,0x82,0x04,0x04,0x00,0x04,0x04,0x01,0x01,0x96,0x02,0x03,0x03,0x02,0x02,0x03,0x84,0x02,
+0x02,0x03,0x07,0x05,0xa4,0x00,0xa8,0x00,0x02,0x05,0x04,0x04,0x85,0x02,0x03,0x04,0x04,0x02,0x02,0x82,0x04,0x00,0x03,0x85,0x02,0x00,0x03,0x82,0x04,0x00,0x03,0x85,0x02,0x00,0x03,0x83,0x04,0x02,0x03,0x01,0x01,0x84,0x02,0x04,0x01,0x03,0x04,0x04,0x03,0x82,0x01,0x03,0x02,0x01,0x01,0x02,0x82,0x01,0x82,0x02,0x83,0x01,0x82,0x02,0x00,0x03,0x82,0x04,0x01,0x02,0x01,0x96,0x02,0x04,0x03,0x03,0x02,0x02,0x03,0x82,0x02,0x04,0x03,0x03,0x07,0x06,0x05,0xa4,0x00,0xa9,0x00,0x02,0x05,0x04,0x03,0x84,0x02,0x04,0x03,0x04,0x03,0x02,0x03,0x82,0x04,0x00,0x03,0x84,0x02,0x83,0x04,0x84,0x02,0x00,0x03,0x84,0x04,0x02,0x02,0x01,0x01,0x86,0x02,0x01,0x01,0x02,0x82,0x01,
+0x83,0x02,0x82,0x01,0x8a,0x02,0x86,0x01,0x96,0x02,0x04,0x03,0x03,0x02,0x03,0x03,0x82,0x02,0x03,0x03,0x03,0x06,0x05,0xa5,0x00,0xaa,0x00,0x03,0x06,0x04,0x03,0x03,0x83,0x02,0x03,0x04,0x04,0x02,0x03,0x82,0x04,0x00,0x03,0x83,0x02,0x00,0x03,0x83,0x04,0x82,0x02,0x01,0x03,0x03,0x84,0x04,0x02,0x02,0x01,0x01,0x87,0x02,0x84,0x01,0x84,0x02,0x01,0x01,0x01,0x8b,0x02,0x84,0x01,0x01,0x02,0x02,0x83,0x03,0x88,0x02,0x00,0x03,0x87,0x02,0x03,0x03,0x02,0x03,0x03,0x82,0x02,0x04,0x03,0x03,0x07,0x05,0x05,0xa5,0x00,0xaa,0x00,0x03,0x05,0x04,0x04,0x03,0x83,0x02,0x03,0x03,0x04,0x03,0x02,0x83,0x04,0x00,0x03,0x82,0x02,0x00,0x03,0x83,0x04,0x01,0x02,0x03,0x85,0x04,
+0x00,0x02,0x82,0x01,0x03,0x02,0x02,0x03,0x03,0x86,0x02,0x00,0x01,0x8f,0x02,0x01,0x03,0x03,0x84,0x02,0x00,0x01,0x82,0x02,0x03,0x03,0x06,0x03,0x03,0x91,0x02,0x0b,0x03,0x03,0x02,0x03,0x03,0x02,0x02,0x03,0x03,0x07,0x06,0x05,0xa6,0x00,0xab,0x00,0x02,0x05,0x04,0x03,0x83,0x02,0x00,0x03,0x86,0x04,0x03,0x03,0x03,0x02,0x03,0x8a,0x04,0x00,0x03,0x82,0x01,0x83,0x02,0x03,0x03,0x03,0x02,0x02,0x82,0x03,0x84,0x02,0x00,0x03,0x8c,0x02,0x00,0x03,0x82,0x02,0x07,0x03,0x03,0x07,0x03,0x02,0x02,0x03,0x02,0x82,0x03,0x90,0x02,0x06,0x03,0x03,0x02,0x02,0x03,0x02,0x02,0x82,0x03,0x01,0x07,0x05,0xa7,0x00,0xab,0x00,0x0a,0x05,0x04,0x04,0x03,0x02,0x03,0x03,0x02,0x03,
+0x04,0x06,0x84,0x04,0x02,0x03,0x02,0x03,0x88,0x04,0x01,0x03,0x02,0x82,0x01,0x01,0x02,0x02,0x8f,0x03,0x08,0x02,0x03,0x02,0x02,0x03,0x02,0x03,0x03,0x02,0x87,0x03,0x04,0x02,0x02,0x03,0x03,0x02,0x82,0x03,0x02,0x02,0x03,0x03,0x8b,0x02,0x02,0x03,0x02,0x02,0x83,0x03,0x03,0x02,0x03,0x03,0x02,0x82,0x03,0x02,0x07,0x06,0x05,0xa7,0x00,0xac,0x00,0x0a,0x05,0x04,0x04,0x02,0x02,0x03,0x02,0x03,0x04,0x04,0x03,0x84,0x04,0x00,0x03,0x83,0x04,0x84,0x02,0x83,0x01,0x01,0x02,0x02,0x8f,0x03,0x00,0x02,0x98,0x03,0x02,0x02,0x03,0x02,0x82,0x03,0x83,0x02,0x01,0x03,0x03,0x86,0x02,0x89,0x03,0x02,0x07,0x06,0x05,0xa8,0x00,0xad,0x00,0x01,0x06,0x04,0x83,0x03,0x04,0x02,
+0x03,0x04,0x03,0x03,0x83,0x04,0x00,0x03,0x83,0x04,0x00,0x02,0x85,0x01,0x01,0x02,0x02,0xa4,0x03,0x00,0x02,0x89,0x03,0x01,0x02,0x02,0x85,0x03,0x04,0x02,0x03,0x02,0x03,0x03,0x82,0x02,0x88,0x03,0x02,0x07,0x05,0x05,0xa8,0x00,0xad,0x00,0x02,0x05,0x04,0x04,0x84,0x03,0x02,0x04,0x04,0x03,0x88,0x04,0x86,0x02,0xc9,0x03,0x02,0x07,0x06,0x05,0xa9,0x00,0xad,0x00,0x03,0x05,0x05,0x04,0x04,0x83,0x03,0x02,0x04,0x04,0x03,0x87,0x04,0x01,0x02,0x02,0xc9,0x03,0x00,0x07,0x84,0x03,0x02,0x06,0x05,0x06,0xa9,0x00,0xae,0x00,0x00,0x05,0x84,0x04,0x00,0x03,0x87,0x04,0x09,0x03,0x04,0x03,0x02,0x03,0x04,0x04,0x03,0x03,0x04,0x9a,0x03,0x03,0x04,0x03,0x03,0x04,0x9f,0x03,
+0x02,0x04,0x03,0x03,0x83,0x04,0x83,0x03,0x03,0x07,0x05,0x05,0x06,0xa9,0x00,0xad,0x00,0x8e,0x05,0x00,0x06,0x82,0x02,0x00,0x06,0x85,0x05,0x00,0x06,0x82,0x04,0x93,0x03,0x00,0x06,0x8d,0x05,0x02,0x06,0x04,0x04,0x8e,0x03,0x03,0x07,0x04,0x06,0x06,0x91,0x05,0xa8,0x00,0x8a,0x00,0xb2,0x05,0x02,0x06,0x02,0x07,0x89,0x05,0x82,0x04,0x8f,0x03,0x01,0x07,0x07,0x90,0x05,0x01,0x04,0x04,0x8a,0x03,0x01,0x07,0x06,0xbf,0x05,0x87,0x00,0x82,0x05,0x01,0x06,0x06,0x98,0x05,0x01,0x06,0x06,0x83,0x05,0x00,0x06,0x90,0x05,0x82,0x06,0x84,0x05,0x00,0x06,0x85,0x05,0x82,0x04,0x8d,0x03,0x04,0x07,0x05,0x05,0x06,0x06,0x8d,0x05,0x01,0x04,0x04,0x88,0x03,0x01,0x07,0x06,0x85,
+0x05,0x83,0x06,0x02,0x05,0x06,0x06,0x8c,0x05,0x01,0x06,0x06,0x82,0x05,0x00,0x06,0x9e,0x05,0x02,0x06,0x06,0x05,0x85,0x00,0x82,0x05,0x00,0x06,0xa1,0x05,0x00,0x06,0x9c,0x05,0x00,0x06,0x82,0x05,0x82,0x04,0x8b,0x03,0x04,0x07,0x06,0x05,0x05,0x06,0x8e,0x05,0x01,0x04,0x04,0x86,0x03,0x01,0x07,0x07,0x83,0x05,0x01,0x06,0x06,0x96,0x05,0x00,0x06,0x82,0x05,0x00,0x06,0xa0,0x05,0x00,0x00,0x83,0x00,0x82,0x05,0x00,0x06,0x9d,0x05,0x00,0x06,0x84,0x05,0x00,0x06,0x9d,0x05,0x00,0x06,0x82,0x05,0x82,0x04,0x89,0x03,0x04,0x07,0x07,0x05,0x05,0x06,0x8f,0x05,0x01,0x04,0x04,0x85,0x03,0x01,0x07,0x07,0x82,0x05,0x01,0x06,0x06,0x97,0x05,0x00,0x06,0x83,0x05,0x00,0x06,
+0x8e,0x05,0x03,0x06,0x05,0x05,0x06,0x82,0x05,0x00,0x06,0x87,0x05,0x02,0x06,0x05,0x00,0x82,0x00,0x82,0x05,0x00,0x06,0x9d,0x05,0x00,0x06,0x82,0x05,0x03,0x06,0x05,0x05,0x06,0x9e,0x05,0x03,0x06,0x06,0x05,0x05,0x82,0x04,0x88,0x03,0x00,0x07,0x82,0x05,0x00,0x06,0x8f,0x05,0x01,0x04,0x04,0x84,0x03,0x01,0x07,0x06,0x82,0x05,0x00,0x06,0x99,0x05,0x00,0x06,0x83,0x05,0x00,0x06,0x8b,0x05,0x00,0x06,0x82,0x05,0x03,0x06,0x05,0x05,0x06,0x89,0x05,0x03,0x06,0x06,0x05,0x00,0x82,0x00,0x02,0x05,0x05,0x06,0x9e,0x05,0x07,0x06,0x05,0x05,0x04,0x06,0x05,0x05,0x06,0x9f,0x05,0x00,0x06,0x82,0x05,0x01,0x04,0x04,0x87,0x03,0x04,0x07,0x07,0x05,0x05,0x06,0x90,0x05,0x01,
+0x04,0x04,0x83,0x03,0x01,0x07,0x06,0x9d,0x05,0x00,0x06,0x84,0x05,0x00,0x06,0x8d,0x05,0x05,0x06,0x06,0x05,0x06,0x06,0x05,0x86,0x06,0x82,0x05,0x03,0x06,0x05,0x00,0x00,0x07,0x00,0x00,0x05,0x05,0x06,0x05,0x05,0x06,0x9b,0x05,0x08,0x06,0x05,0x05,0x04,0x04,0x06,0x05,0x05,0x06,0xa0,0x05,0x02,0x06,0x05,0x05,0x82,0x04,0x86,0x03,0x00,0x07,0x82,0x05,0x00,0x06,0x90,0x05,0x01,0x04,0x04,0x82,0x03,0x01,0x07,0x07,0x9d,0x05,0x01,0x06,0x06,0x84,0x05,0x00,0x06,0x89,0x05,0x02,0x06,0x05,0x05,0x8b,0x06,0x08,0x05,0x06,0x05,0x05,0x06,0x06,0x05,0x00,0x00,0x02,0x00,0x00,0x05,0x82,0x06,0x01,0x05,0x06,0x9b,0x05,0x04,0x06,0x05,0x05,0x04,0x04,0x82,0x05,0x00,0x06,
+0xa1,0x05,0x04,0x06,0x05,0x05,0x04,0x04,0x85,0x03,0x04,0x07,0x07,0x05,0x05,0x06,0x91,0x05,0x05,0x04,0x04,0x03,0x03,0x07,0x07,0x9e,0x05,0x00,0x06,0x85,0x05,0x00,0x06,0x8a,0x05,0x02,0x06,0x06,0x05,0x8a,0x06,0x01,0x05,0x05,0x82,0x06,0x00,0x05,0x82,0x00,0x02,0x00,0x05,0x05,0x85,0x06,0x99,0x05,0x09,0x06,0x05,0x05,0x06,0x04,0x04,0x06,0x05,0x05,0x06,0xa1,0x05,0x02,0x06,0x05,0x05,0x82,0x04,0x84,0x03,0x04,0x07,0x05,0x05,0x06,0x06,0x91,0x05,0x04,0x04,0x04,0x03,0x07,0x07,0x82,0x05,0x00,0x06,0x9b,0x05,0x07,0x06,0x05,0x05,0x06,0x06,0x05,0x05,0x06,0x87,0x05,0x01,0x06,0x05,0x90,0x06,0x03,0x05,0x06,0x06,0x05,0x82,0x00,0x02,0x00,0x05,0x05,0x85,0x06,
+0x01,0x05,0x06,0x97,0x05,0x02,0x06,0x05,0x05,0x82,0x04,0x03,0x07,0x05,0x05,0x06,0xa2,0x05,0x04,0x06,0x05,0x05,0x04,0x04,0x83,0x03,0x04,0x07,0x07,0x05,0x05,0x06,0x8f,0x05,0x0a,0x06,0x05,0x05,0x04,0x04,0x03,0x07,0x06,0x05,0x05,0x06,0x9b,0x05,0x08,0x06,0x05,0x05,0x06,0x04,0x07,0x05,0x05,0x06,0x8a,0x05,0x91,0x06,0x00,0x05,0x83,0x00,0x01,0x05,0x05,0x88,0x06,0x82,0x05,0x8e,0x06,0x00,0x05,0x85,0x06,0x01,0x05,0x05,0x82,0x04,0x03,0x07,0x05,0x05,0x06,0x89,0x05,0x8d,0x06,0x8a,0x05,0x04,0x06,0x05,0x05,0x04,0x04,0x83,0x03,0x04,0x07,0x05,0x05,0x06,0x06,0x8f,0x05,0x09,0x06,0x05,0x05,0x04,0x04,0x07,0x07,0x05,0x05,0x06,0x8d,0x05,0x8f,0x06,0x07,0x05,
+0x05,0x04,0x07,0x07,0x05,0x05,0x06,0x86,0x05,0x01,0x06,0x05,0x93,0x06,0x00,0x05,0x83,0x00,0x01,0x05,0x05,0x88,0x06,0x02,0x05,0x06,0x06,0x96,0x05,0x83,0x04,0x03,0x07,0x05,0x05,0x06,0x88,0x05,0x00,0x06,0x8c,0x05,0x82,0x06,0x88,0x05,0x04,0x06,0x06,0x05,0x04,0x04,0x82,0x03,0x06,0x07,0x07,0x05,0x05,0x06,0x05,0x06,0x8e,0x05,0x09,0x06,0x05,0x05,0x04,0x04,0x07,0x07,0x05,0x05,0x06,0x8a,0x05,0x82,0x06,0x90,0x05,0x06,0x06,0x04,0x07,0x07,0x05,0x05,0x06,0x87,0x05,0x01,0x06,0x06,0x92,0x05,0x84,0x00,0x01,0x05,0x05,0x8a,0x06,0x96,0x05,0x08,0x06,0x04,0x04,0x03,0x04,0x07,0x05,0x05,0x06,0x83,0x05,0x05,0x06,0x05,0x06,0x05,0x06,0x06,0x8e,0x05,0x00,0x06,
+0x88,0x05,0x02,0x06,0x06,0x05,0x82,0x04,0x0c,0x03,0x03,0x07,0x05,0x05,0x06,0x06,0x05,0x06,0x06,0x05,0x06,0x06,0x8a,0x05,0x08,0x06,0x05,0x05,0x04,0x07,0x07,0x05,0x05,0x06,0x8a,0x05,0x01,0x06,0x06,0x92,0x05,0x00,0x04,0x82,0x07,0x02,0x05,0x05,0x06,0x86,0x05,0x83,0x06,0x01,0x05,0x05,0x85,0x00,0x87,0x05,0x86,0x00,0x01,0x05,0x05,0x8a,0x06,0x03,0x05,0x05,0x06,0x06,0x84,0x07,0x00,0x06,0x8a,0x07,0x00,0x06,0x83,0x04,0x05,0x03,0x04,0x07,0x05,0x05,0x06,0x82,0x05,0x86,0x06,0x82,0x05,0x03,0x06,0x06,0x07,0x07,0x83,0x06,0x84,0x05,0x82,0x06,0x82,0x05,0x0f,0x06,0x05,0x05,0x06,0x06,0x05,0x05,0x04,0x04,0x03,0x07,0x06,0x05,0x05,0x06,0x05,0x8a,0x06,0x85,
+0x05,0x08,0x06,0x05,0x05,0x04,0x06,0x07,0x05,0x05,0x06,0x89,0x05,0x01,0x06,0x06,0x83,0x05,0x82,0x06,0x82,0x05,0x01,0x06,0x05,0x84,0x06,0x03,0x05,0x07,0x04,0x03,0x82,0x07,0x02,0x05,0x05,0x06,0x84,0x05,0x85,0x06,0x00,0x05,0x95,0x00,0x01,0x05,0x05,0x89,0x06,0x03,0x05,0x05,0x04,0x04,0x8b,0x03,0x00,0x04,0x82,0x03,0x00,0x04,0x83,0x03,0x09,0x04,0x04,0x03,0x03,0x07,0x05,0x05,0x06,0x06,0x05,0x87,0x06,0x82,0x05,0x03,0x04,0x04,0x03,0x03,0x83,0x04,0x01,0x06,0x06,0x82,0x05,0x8a,0x06,0x07,0x05,0x05,0x04,0x04,0x07,0x07,0x05,0x05,0x8f,0x06,0x83,0x05,0x08,0x06,0x05,0x05,0x04,0x06,0x06,0x05,0x06,0x06,0x88,0x05,0x01,0x06,0x06,0x82,0x05,0x0a,0x06,0x06,
+0x07,0x07,0x06,0x05,0x05,0x06,0x07,0x06,0x06,0x82,0x07,0x03,0x06,0x06,0x07,0x07,0x82,0x03,0x03,0x07,0x05,0x05,0x06,0x82,0x05,0x87,0x06,0x00,0x05,0x95,0x00,0x01,0x05,0x05,0x89,0x06,0x01,0x05,0x05,0x82,0x04,0x97,0x03,0x04,0x07,0x05,0x05,0x06,0x05,0x88,0x06,0x04,0x05,0x04,0x05,0x06,0x04,0x82,0x03,0x83,0x04,0x03,0x06,0x06,0x05,0x05,0x8a,0x06,0x07,0x05,0x06,0x04,0x04,0x07,0x06,0x05,0x05,0x94,0x06,0x0c,0x05,0x05,0x04,0x07,0x05,0x05,0x06,0x06,0x05,0x06,0x05,0x06,0x05,0x84,0x06,0x13,0x05,0x05,0x06,0x04,0x06,0x07,0x03,0x06,0x05,0x05,0x06,0x07,0x06,0x06,0x07,0x07,0x04,0x06,0x06,0x07,0x83,0x03,0x05,0x07,0x07,0x05,0x05,0x06,0x05,0x89,0x06,0x96,
+0x00,0x01,0x05,0x05,0x8a,0x06,0x01,0x05,0x05,0x91,0x04,0x87,0x03,0x02,0x07,0x05,0x05,0x8a,0x06,0x07,0x05,0x04,0x05,0x05,0x04,0x04,0x03,0x03,0x84,0x04,0x02,0x06,0x06,0x05,0x8a,0x06,0x06,0x05,0x05,0x04,0x04,0x07,0x05,0x05,0x95,0x06,0x05,0x05,0x05,0x04,0x07,0x05,0x05,0x8b,0x06,0x08,0x05,0x05,0x04,0x07,0x07,0x03,0x07,0x05,0x05,0x82,0x06,0x06,0x07,0x07,0x04,0x07,0x07,0x06,0x07,0x85,0x03,0x02,0x07,0x05,0x05,0x8b,0x06,0x00,0x05,0x95,0x00,0x01,0x05,0x05,0x8a,0x06,0x90,0x05,0x00,0x06,0x85,0x04,0x83,0x03,0x02,0x07,0x05,0x05,0x8a,0x06,0x05,0x05,0x04,0x04,0x05,0x06,0x04,0x82,0x03,0x83,0x04,0x02,0x06,0x05,0x05,0x8a,0x06,0x06,0x05,0x05,0x04,0x07,
+0x06,0x05,0x05,0x95,0x06,0x05,0x05,0x05,0x04,0x06,0x05,0x05,0x8a,0x06,0x01,0x05,0x05,0x82,0x04,0x0d,0x03,0x07,0x06,0x05,0x05,0x07,0x07,0x06,0x07,0x07,0x04,0x07,0x06,0x07,0x86,0x03,0x02,0x07,0x05,0x05,0x8b,0x06,0x00,0x05,0x95,0x00,0x01,0x05,0x05,0x8c,0x06,0x92,0x05,0x82,0x04,0x83,0x03,0x02,0x07,0x05,0x05,0x82,0x06,0x82,0x05,0x84,0x06,0x00,0x05,0x82,0x04,0x04,0x05,0x04,0x04,0x03,0x03,0x82,0x04,0x00,0x06,0x82,0x05,0x8a,0x06,0x05,0x05,0x05,0x04,0x06,0x05,0x05,0x96,0x06,0x04,0x05,0x05,0x04,0x06,0x05,0x8b,0x06,0x09,0x05,0x05,0x04,0x07,0x03,0x03,0x07,0x05,0x05,0x06,0x82,0x07,0x04,0x04,0x07,0x07,0x06,0x07,0x87,0x03,0x02,0x07,0x05,0x05,0x8a,
+0x06,0x8f,0x05,0x02,0x06,0x06,0x05,0x84,0x00,0x01,0x00,0x05,0x9d,0x06,0x83,0x05,0x82,0x04,0x04,0x03,0x03,0x07,0x05,0x05,0x83,0x06,0x01,0x05,0x05,0x84,0x06,0x05,0x05,0x06,0x04,0x06,0x05,0x06,0x84,0x04,0x00,0x06,0x82,0x05,0x8b,0x06,0x02,0x05,0x05,0x06,0x82,0x05,0x8a,0x06,0x00,0x05,0x8a,0x06,0x04,0x05,0x05,0x06,0x05,0x05,0x8b,0x06,0x08,0x05,0x06,0x04,0x07,0x03,0x07,0x06,0x05,0x05,0x82,0x07,0x00,0x04,0x84,0x07,0x87,0x03,0x02,0x07,0x05,0x05,0x8a,0x06,0x01,0x05,0x05,0x8f,0x06,0x00,0x05,0x84,0x00,0x02,0x00,0x05,0x05,0x91,0x06,0x00,0x05,0x82,0x06,0x04,0x05,0x05,0x06,0x05,0x05,0x84,0x06,0x82,0x05,0x05,0x04,0x04,0x03,0x07,0x05,0x05,0x84,0x06,
+0x00,0x05,0x84,0x06,0x8e,0x05,0x8b,0x06,0x04,0x05,0x06,0x06,0x05,0x05,0x8b,0x06,0x00,0x05,0x8a,0x06,0x04,0x05,0x05,0x06,0x05,0x05,0x8b,0x06,0x10,0x05,0x04,0x04,0x03,0x03,0x06,0x06,0x05,0x07,0x04,0x07,0x04,0x03,0x07,0x07,0x06,0x07,0x88,0x03,0x02,0x07,0x05,0x05,0x9c,0x06,0x00,0x05,0x84,0x00,0x02,0x00,0x05,0x05,0xa0,0x06,0x82,0x05,0x04,0x04,0x04,0x07,0x05,0x05,0x8a,0x06,0x00,0x05,0x87,0x06,0x83,0x05,0x8d,0x06,0x84,0x05,0x8a,0x06,0x01,0x05,0x05,0x8a,0x06,0x04,0x05,0x05,0x04,0x05,0x05,0x8a,0x06,0x02,0x05,0x05,0x04,0x82,0x03,0x05,0x06,0x05,0x06,0x07,0x04,0x04,0x82,0x03,0x01,0x06,0x07,0x89,0x03,0x02,0x07,0x07,0x05,0x89,0x06,0x00,0x05,0x91,
+0x06,0x00,0x05,0x84,0x00,0x02,0x00,0x05,0x05,0x82,0x06,0x00,0x05,0x9d,0x06,0x06,0x05,0x05,0x04,0x04,0x07,0x05,0x05,0x93,0x06,0x83,0x05,0x8c,0x06,0x84,0x05,0x8b,0x06,0x01,0x05,0x05,0x8a,0x06,0x04,0x05,0x05,0x04,0x05,0x05,0x8a,0x06,0x0f,0x05,0x05,0x04,0x03,0x03,0x07,0x06,0x05,0x07,0x07,0x04,0x07,0x03,0x03,0x07,0x07,0x8a,0x03,0x02,0x07,0x05,0x05,0x88,0x06,0x82,0x05,0x90,0x06,0x00,0x05,0x84,0x00,0x03,0x00,0x00,0x05,0x05,0xa1,0x06,0x05,0x05,0x05,0x04,0x07,0x05,0x05,0xa4,0x06,0x83,0x05,0x8b,0x06,0x82,0x05,0x8a,0x06,0x04,0x05,0x05,0x06,0x05,0x05,0x8a,0x06,0x0e,0x05,0x05,0x04,0x04,0x03,0x06,0x05,0x06,0x07,0x04,0x04,0x03,0x03,0x07,0x06,0x8b,
+0x03,0x02,0x07,0x05,0x05,0x88,0x06,0x82,0x05,0x90,0x06,0x00,0x05,0x84,0x00,0x03,0x00,0x00,0x05,0x05,0x82,0x06,0x82,0x07,0x01,0x02,0x02,0x93,0x07,0x0b,0x03,0x02,0x07,0x02,0x07,0x06,0x06,0x05,0x06,0x06,0x05,0x05,0x83,0x02,0x00,0x03,0x84,0x02,0x01,0x07,0x06,0x8a,0x02,0x00,0x03,0x8a,0x02,0x00,0x07,0x84,0x05,0x01,0x06,0x06,0x88,0x07,0x83,0x05,0x88,0x07,0x09,0x06,0x06,0x05,0x05,0x06,0x05,0x05,0x06,0x07,0x07,0x87,0x02,0x0d,0x06,0x05,0x04,0x04,0x07,0x05,0x06,0x07,0x04,0x07,0x03,0x03,0x07,0x06,0x8c,0x03,0x03,0x07,0x07,0x05,0x07,0x92,0x06,0x85,0x07,0x82,0x02,0x00,0x06,0x84,0x00,0x82,0x00,0x02,0x05,0x05,0x02,0x90,0x01,0x00,0x02,0x86,0x01,0x85,
+0x00,0x06,0x01,0x02,0x05,0x05,0x06,0x05,0x06,0x89,0x00,0x02,0x02,0x06,0x01,0x95,0x00,0x00,0x07,0x83,0x05,0x01,0x07,0x02,0x88,0x01,0x00,0x02,0x83,0x05,0x00,0x02,0x88,0x01,0x07,0x02,0x06,0x05,0x06,0x05,0x05,0x02,0x01,0x88,0x00,0x0d,0x07,0x05,0x04,0x04,0x06,0x05,0x07,0x03,0x04,0x07,0x03,0x03,0x07,0x07,0x8c,0x03,0x02,0x07,0x05,0x06,0x87,0x02,0x00,0x07,0x82,0x06,0x01,0x07,0x07,0x85,0x02,0x85,0x01,0x82,0x00,0x00,0x06,0x84,0x00,0x83,0x00,0x04,0x05,0x05,0x02,0x01,0x00,0x8e,0x01,0x82,0x02,0x83,0x01,0x86,0x00,0x01,0x01,0x06,0x82,0x05,0x00,0x06,0x89,0x00,0x02,0x02,0x05,0x06,0x94,0x00,0x00,0x02,0x83,0x05,0x01,0x06,0x02,0x89,0x01,0x00,0x06,0x82,
+0x05,0x00,0x06,0x89,0x01,0x06,0x02,0x06,0x05,0x06,0x05,0x05,0x02,0x89,0x00,0x0c,0x07,0x05,0x04,0x06,0x05,0x06,0x07,0x04,0x04,0x03,0x03,0x07,0x07,0x8d,0x03,0x03,0x07,0x05,0x06,0x01,0x87,0x02,0x02,0x03,0x07,0x07,0x87,0x02,0x84,0x01,0x83,0x00,0x00,0x06,0x84,0x00,0x84,0x00,0x02,0x05,0x05,0x07,0x8d,0x01,0x83,0x02,0x02,0x03,0x02,0x02,0x82,0x01,0x85,0x00,0x01,0x01,0x02,0x82,0x05,0x00,0x06,0x89,0x00,0x03,0x02,0x05,0x05,0x02,0x91,0x00,0x01,0x01,0x02,0x84,0x05,0x01,0x02,0x02,0x88,0x01,0x05,0x02,0x05,0x05,0x06,0x05,0x05,0x8a,0x01,0x05,0x06,0x05,0x06,0x05,0x05,0x02,0x89,0x00,0x04,0x02,0x05,0x06,0x05,0x05,0x84,0x07,0x01,0x04,0x06,0x8e,0x03,0x02,
+0x07,0x05,0x06,0x89,0x02,0x00,0x03,0x88,0x02,0x85,0x01,0x82,0x00,0x00,0x06,0x84,0x00,0x85,0x00,0x82,0x05,0x00,0x06,0x82,0x02,0x83,0x01,0x86,0x02,0x04,0x03,0x06,0x06,0x03,0x02,0x84,0x01,0x83,0x00,0x01,0x01,0x02,0x82,0x05,0x00,0x06,0x89,0x00,0x00,0x02,0x82,0x05,0x00,0x01,0x8f,0x00,0x01,0x01,0x07,0x84,0x05,0x01,0x06,0x02,0x89,0x01,0x05,0x06,0x05,0x06,0x06,0x05,0x06,0x8a,0x01,0x05,0x06,0x05,0x06,0x05,0x05,0x02,0x88,0x00,0x01,0x01,0x02,0x82,0x05,0x07,0x06,0x07,0x04,0x04,0x07,0x07,0x06,0x07,0x8e,0x03,0x02,0x07,0x05,0x06,0x95,0x02,0x86,0x01,0x00,0x06,0x84,0x00,0x87,0x00,0x84,0x05,0x8d,0x06,0x02,0x07,0x02,0x02,0x89,0x01,0x82,0x05,0x00,0x06,
+0x89,0x00,0x00,0x02,0x82,0x05,0x00,0x06,0x8b,0x00,0x82,0x01,0x01,0x02,0x06,0x82,0x05,0x04,0x06,0x05,0x05,0x02,0x02,0x88,0x01,0x07,0x02,0x05,0x05,0x04,0x07,0x05,0x05,0x02,0x89,0x01,0x05,0x06,0x05,0x04,0x06,0x05,0x02,0x85,0x01,0x0e,0x00,0x01,0x00,0x01,0x01,0x06,0x05,0x06,0x04,0x07,0x04,0x04,0x03,0x06,0x06,0x8f,0x03,0x02,0x07,0x05,0x06,0x8a,0x02,0x00,0x06,0x8e,0x05,0x02,0x06,0x06,0x05,0x84,0x00,0x91,0x00,0x89,0x05,0x01,0x07,0x02,0x89,0x01,0x82,0x05,0x0b,0x06,0x01,0x01,0x00,0x01,0x01,0x00,0x01,0x00,0x00,0x01,0x02,0x83,0x05,0x00,0x03,0x8c,0x02,0x00,0x06,0x82,0x05,0x04,0x06,0x07,0x05,0x05,0x06,0x82,0x02,0x00,0x01,0x86,0x02,0x06,0x06,0x05,
+0x04,0x04,0x07,0x05,0x05,0x83,0x02,0x86,0x01,0x05,0x06,0x05,0x04,0x06,0x05,0x07,0x8a,0x01,0x09,0x06,0x05,0x06,0x04,0x07,0x04,0x04,0x07,0x06,0x07,0x8f,0x03,0x02,0x07,0x05,0x06,0x8a,0x02,0x02,0x06,0x05,0x05,0x94,0x00,0x99,0x00,0x82,0x05,0x84,0x02,0x85,0x01,0x03,0x06,0x05,0x05,0x06,0x89,0x01,0x00,0x02,0x93,0x05,0x06,0x06,0x04,0x04,0x07,0x05,0x05,0x03,0x89,0x02,0x07,0x07,0x05,0x05,0x04,0x03,0x07,0x05,0x05,0x87,0x02,0x82,0x01,0x05,0x06,0x05,0x04,0x07,0x05,0x06,0x89,0x01,0x03,0x02,0x02,0x05,0x05,0x83,0x04,0x01,0x06,0x07,0x90,0x03,0x02,0x07,0x05,0x06,0x88,0x02,0x03,0x03,0x02,0x06,0x05,0x95,0x00,0x9a,0x00,0x02,0x05,0x05,0x06,0x87,0x02,0x05,
+0x01,0x01,0x06,0x05,0x05,0x06,0x89,0x01,0x02,0x02,0x05,0x06,0x89,0x00,0x01,0x05,0x05,0x82,0x06,0x09,0x05,0x06,0x06,0x04,0x04,0x07,0x06,0x05,0x06,0x07,0x89,0x02,0x07,0x05,0x05,0x04,0x04,0x03,0x07,0x05,0x05,0x8a,0x02,0x06,0x06,0x05,0x04,0x07,0x05,0x05,0x02,0x83,0x01,0x01,0x02,0x02,0x82,0x01,0x08,0x02,0x02,0x06,0x05,0x06,0x04,0x07,0x06,0x06,0x91,0x03,0x02,0x07,0x05,0x06,0x85,0x02,0x83,0x03,0x01,0x02,0x06,0x96,0x00,0x9a,0x00,0x02,0x05,0x05,0x06,0x89,0x02,0x03,0x06,0x05,0x05,0x06,0x8a,0x02,0x00,0x05,0x8b,0x00,0x03,0x05,0x06,0x04,0x03,0x83,0x04,0x05,0x06,0x06,0x05,0x05,0x07,0x07,0x88,0x02,0x08,0x06,0x05,0x05,0x04,0x04,0x03,0x07,0x05,0x05,
+0x8a,0x02,0x05,0x06,0x05,0x04,0x07,0x05,0x05,0x8b,0x02,0x06,0x07,0x05,0x05,0x06,0x04,0x06,0x04,0x91,0x03,0x02,0x07,0x05,0x06,0x83,0x02,0x02,0x07,0x03,0x03,0x82,0x07,0x01,0x02,0x06,0x96,0x00,0x9a,0x00,0x03,0x05,0x05,0x06,0x03,0x88,0x02,0x82,0x05,0x00,0x06,0x8a,0x02,0x00,0x05,0x8b,0x00,0x03,0x05,0x06,0x04,0x03,0x82,0x04,0x08,0x06,0x06,0x05,0x05,0x06,0x06,0x07,0x07,0x03,0x86,0x02,0x01,0x05,0x05,0x82,0x04,0x03,0x03,0x07,0x05,0x05,0x8a,0x02,0x06,0x06,0x05,0x04,0x07,0x06,0x05,0x06,0x8a,0x02,0x01,0x07,0x06,0x82,0x05,0x02,0x06,0x04,0x04,0x87,0x03,0x0c,0x04,0x04,0x03,0x04,0x07,0x04,0x03,0x03,0x07,0x07,0x05,0x06,0x02,0x88,0x07,0x02,0x03,0x06,
+0x05,0x95,0x00,0x99,0x00,0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x82,0x03,0x84,0x02,0x82,0x05,0x00,0x06,0x89,0x02,0x01,0x03,0x05,0x8c,0x00,0x00,0x05,0x84,0x04,0x00,0x06,0x82,0x05,0x82,0x06,0x83,0x07,0x04,0x03,0x07,0x03,0x03,0x06,0x82,0x05,0x82,0x06,0x82,0x05,0x00,0x02,0x84,0x03,0x84,0x02,0x06,0x06,0x05,0x04,0x07,0x07,0x05,0x05,0x8a,0x02,0x02,0x07,0x06,0x06,0x97,0x05,0x01,0x06,0x02,0x82,0x07,0x02,0x06,0x07,0x07,0x82,0x06,0x03,0x07,0x06,0x05,0x05,0x94,0x00,0x00,0x00,0x99,0x05,0x82,0x06,0x87,0x07,0x01,0x03,0x03,0x82,0x05,0x07,0x06,0x02,0x03,0x03,0x02,0x03,0x02,0x03,0x82,0x02,0x01,0x07,0x05,0x8d,0x00,0x00,0x05,0x82,0x04,0x01,0x06,0x06,0x82,
+0x05,0x86,0x06,0x03,0x07,0x06,0x07,0x06,0x89,0x05,0x00,0x06,0x88,0x07,0x08,0x03,0x06,0x05,0x04,0x03,0x07,0x05,0x05,0x06,0x82,0x02,0x07,0x03,0x03,0x07,0x03,0x07,0x03,0x07,0x03,0x97,0x06,0x82,0x05,0x00,0x02,0x9e,0x06,0x02,0x05,0x00,0x00,0x02,0x05,0x05,0x03,0x9f,0x06,0x82,0x07,0x01,0x03,0x06,0x83,0x05,0x00,0x02,0x87,0x07,0x02,0x03,0x07,0x05,0x8d,0x00,0x04,0x05,0x06,0x04,0x04,0x06,0x82,0x05,0x96,0x06,0x02,0x07,0x04,0x06,0x85,0x07,0x08,0x03,0x05,0x05,0x04,0x03,0x07,0x07,0x05,0x05,0x8b,0x07,0x95,0x06,0x04,0x07,0x06,0x05,0x05,0x07,0x9d,0x06,0x03,0x02,0x05,0x00,0x00,0x02,0x05,0x05,0x07,0xa1,0x06,0x02,0x04,0x07,0x06,0x83,0x05,0x05,0x07,0x07,
+0x06,0x07,0x07,0x06,0x83,0x07,0x01,0x06,0x05,0x8e,0x00,0x03,0x05,0x04,0x04,0x06,0x83,0x05,0x9d,0x06,0x0a,0x07,0x07,0x05,0x05,0x04,0x04,0x07,0x07,0x05,0x05,0x06,0x82,0x07,0x01,0x06,0x07,0x9d,0x06,0x02,0x05,0x05,0x07,0x9d,0x06,0x03,0x07,0x05,0x00,0x00,0x02,0x05,0x05,0x07,0xa2,0x06,0x00,0x07,0x84,0x05,0x00,0x07,0x89,0x06,0x00,0x05,0x8e,0x00,0x00,0x05,0x82,0x06,0x84,0x05,0x9d,0x06,0x09,0x07,0x05,0x05,0x04,0x03,0x03,0x07,0x07,0x05,0x05,0xa2,0x06,0x02,0x05,0x05,0x07,0x9d,0x06,0x03,0x07,0x05,0x00,0x00,0x01,0x05,0x05,0xa4,0x06,0x05,0x05,0x05,0x06,0x05,0x05,0x07,0x89,0x06,0x00,0x05,0x8f,0x00,0x01,0x05,0x06,0x84,0x05,0x88,0x06,0x00,0x05,0x95,
+0x06,0x02,0x05,0x05,0x04,0x82,0x03,0x03,0x07,0x06,0x05,0x05,0xa1,0x06,0x01,0x05,0x05,0x9f,0x06,0x02,0x05,0x00,0x00,0x01,0x05,0x05,0xa3,0x06,0x00,0x05,0x82,0x00,0x01,0x05,0x05,0x8a,0x06,0x00,0x05,0x90,0x00,0x85,0x05,0x87,0x06,0x82,0x05,0x94,0x06,0x07,0x05,0x05,0x04,0x04,0x03,0x03,0x07,0x07,0x82,0x05,0xa0,0x06,0x01,0x05,0x05,0x9f,0x06,0x02,0x05,0x00,0x00,0x01,0x05,0x05,0xa2,0x06,0x01,0x05,0x05,0x82,0x00,0x01,0x05,0x05,0x8a,0x06,0x00,0x05,0x90,0x00,0x83,0x05,0x89,0x06,0x82,0x05,0x94,0x06,0x02,0x05,0x05,0x04,0x82,0x03,0x82,0x07,0x82,0x05,0x9f,0x06,0x01,0x05,0x05,0x9f,0x06,0x02,0x05,0x00,0x00,0x01,0x05,0x05,0xa1,0x06,0x01,0x05,0x05,0x83,
+0x00,0x01,0x05,0x05,0x8a,0x06,0x00,0x05,0x8f,0x00,0x85,0x05,0x87,0x06,0x84,0x05,0x93,0x06,0x03,0x05,0x05,0x04,0x04,0x82,0x03,0x02,0x07,0x07,0x06,0x82,0x05,0x9e,0x06,0x01,0x05,0x05,0x9f,0x06,0x02,0x05,0x00,0x00,0x01,0x05,0x05,0xa0,0x06,0x01,0x05,0x05,0x84,0x00,0x01,0x05,0x05,0x8a,0x06,0x00,0x05,0x8f,0x00,0x84,0x05,0x87,0x06,0x82,0x05,0x02,0x06,0x05,0x05,0x93,0x06,0x02,0x05,0x05,0x04,0x83,0x03,0x01,0x07,0x06,0x85,0x05,0x9c,0x06,0x01,0x05,0x05,0x9f,0x06,0x02,0x05,0x00,0x00,0x01,0x05,0x05,0x9e,0x06,0x82,0x05,0x85,0x00,0x01,0x05,0x05,0x8a,0x06,0x00,0x05,0x8e,0x00,0x87,0x05,0x85,0x06,0x06,0x05,0x05,0x06,0x07,0x06,0x05,0x05,0x92,0x06,0x02,
+0x05,0x05,0x04,0x82,0x03,0x05,0x07,0x04,0x06,0x05,0x06,0x07,0x84,0x05,0x9a,0x06,0x01,0x05,0x05,0x9f,0x06,0x02,0x05,0x00,0x00,0x01,0x05,0x05,0x9b,0x06,0x83,0x05,0x87,0x00,0x01,0x05,0x05,0x89,0x06,0x01,0x05,0x05,0x8e,0x00,0x8b,0x05,0x00,0x06,0x82,0x05,0x02,0x04,0x07,0x07,0x82,0x05,0x91,0x06,0x09,0x05,0x05,0x04,0x03,0x03,0x07,0x03,0x06,0x05,0x05,0x82,0x07,0x88,0x05,0x94,0x06,0x82,0x05,0x9f,0x06,0x02,0x05,0x00,0x00,0x00,0x00,0x9e,0x05,0x89,0x00,0x8c,0x05,0x8f,0x00,0x8e,0x05,0x03,0x04,0x03,0x03,0x07,0x96,0x05,0x00,0x04,0x82,0x03,0x06,0x04,0x06,0x05,0x04,0x03,0x04,0x06,0x83,0x00,0xbd,0x05,0x01,0x00,0x00,0xcb,0x00,0x88,0x05,0x01,0x06,0x04,
+0x82,0x03,0x00,0x07,0x94,0x05,0x0a,0x06,0x04,0x03,0x07,0x03,0x04,0x05,0x06,0x04,0x04,0x07,0xc4,0x00,0xcc,0x00,0x02,0x05,0x06,0x07,0x83,0x06,0x88,0x03,0x91,0x07,0x84,0x03,0x05,0x07,0x05,0x06,0x07,0x07,0x04,0xc5,0x00,0xcd,0x00,0x00,0x05,0x85,0x04,0x9e,0x03,0x05,0x06,0x05,0x06,0x03,0x04,0x04,0xc5,0x00,0xce,0x00,0x00,0x06,0x84,0x04,0x9d,0x03,0x02,0x07,0x05,0x06,0x82,0x04,0xc6,0x00,0xce,0x00,0x00,0x05,0x84,0x04,0x9c,0x03,0x05,0x04,0x06,0x05,0x04,0x03,0x04,0xc7,0x00,0xcf,0x00,0x00,0x06,0x84,0x04,0x9b,0x03,0x05,0x06,0x05,0x06,0x07,0x04,0x07,0xc7,0x00,0xcf,0x00,0x01,0x05,0x06,0x83,0x04,0x8d,0x03,0x00,0x02,0x8b,0x03,0x05,0x04,0x06,0x05,0x07,
+0x03,0x04,0xc8,0x00,0xd0,0x00,0x00,0x06,0x84,0x04,0x99,0x03,0x04,0x06,0x05,0x04,0x03,0x04,0xc9,0x00,0xd1,0x00,0x00,0x06,0x82,0x04,0x99,0x03,0x05,0x07,0x05,0x05,0x04,0x04,0x07,0xc9,0x00,0xd1,0x00,0x00,0x05,0x84,0x04,0x96,0x03,0x05,0x04,0x06,0x05,0x04,0x03,0x07,0xca,0x00,0xd0,0x00,0x08,0x06,0x05,0x05,0x06,0x04,0x04,0x03,0x03,0x04,0x87,0x07,0x87,0x03,0x01,0x07,0x07,0x85,0x06,0x02,0x07,0x04,0x06,0xca,0x00,0xcc,0x00,0x86,0x05,0x00,0x06,0x82,0x04,0x01,0x07,0x06,0x87,0x05,0x01,0x06,0x07,0x83,0x03,0x02,0x07,0x06,0x06,0x85,0x05,0x01,0x06,0x07,0x82,0x06,0x83,0x05,0x8b,0x00,0x83,0x05,0xb5,0x00,0xbb,0x00,0x88,0x05,0x86,0x00,0x88,0x05,0x03,0x06,
+0x04,0x06,0x06,0x89,0x05,0x00,0x06,0x83,0x03,0x00,0x06,0x88,0x05,0x03,0x06,0x06,0x07,0x06,0x88,0x05,0x84,0x00,0x87,0x05,0xb3,0x00,0xbb,0x00,0x89,0x05,0x84,0x00,0x89,0x05,0x03,0x06,0x06,0x04,0x06,0x89,0x05,0x04,0x06,0x07,0x03,0x07,0x07,0x89,0x05,0x02,0x06,0x06,0x07,0x89,0x05,0x83,0x00,0x88,0x05,0xb3,0x00,0xba,0x00,0x8a,0x05,0x84,0x00,0x8a,0x05,0x82,0x06,0x8a,0x05,0x03,0x07,0x03,0x07,0x06,0x8a,0x05,0x01,0x00,0x00,0x89,0x05,0x83,0x00,0x89,0x05,0xb2,0x00,0xba,0x00,0x84,0x05,0x00,0x00,0x84,0x05,0x83,0x00,0x84,0x05,0x00,0x00,0x85,0x05,0x01,0x06,0x06,0x84,0x05,0x00,0x00,0x84,0x05,0x03,0x06,0x07,0x03,0x07,0x84,0x05,0x01,0x00,0x00,0x84,0x05,
+0x83,0x00,0x86,0x05,0x83,0x00,0x83,0x05,0x01,0x00,0x00,0x84,0x05,0xb2,0x00,0xba,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x02,0x06,0x05,0x06,0x84,0x05,0x01,0x00,0x00,0x83,0x05,0x03,0x06,0x04,0x03,0x07,0x83,0x05,0x82,0x00,0x84,0x05,0x84,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0xb3,0x00,0xba,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x02,0x06,0x05,0x06,0x83,0x05,0x82,0x00,0x83,0x05,0x00,0x06,0x82,0x07,0x83,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0xb3,0x00,0xba,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x83,
+0x00,0x83,0x05,0x01,0x00,0x00,0x84,0x05,0x02,0x07,0x06,0x06,0x83,0x05,0x82,0x00,0x83,0x05,0x03,0x06,0x07,0x03,0x07,0x83,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0xb3,0x00,0xba,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x83,0x00,0x84,0x05,0x01,0x00,0x00,0x84,0x05,0x02,0x07,0x07,0x06,0x83,0x05,0x82,0x00,0x83,0x05,0x03,0x07,0x07,0x04,0x06,0x83,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0xb9,0x00,0xba,0x00,0x82,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x82,0x00,0x84,0x05,0x02,0x00,0x07,0x06,0x83,0x05,0x82,0x00,0x83,0x05,0x03,0x07,0x03,0x04,0x06,0x83,0x05,0x82,0x00,
+0x83,0x05,0x85,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0xb9,0x00,0xba,0x00,0x82,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x82,0x00,0x00,0x06,0x83,0x05,0x01,0x00,0x00,0x84,0x05,0x02,0x07,0x03,0x07,0x84,0x05,0x82,0x00,0x83,0x05,0x84,0x00,0x84,0x05,0x85,0x00,0x83,0x05,0xb9,0x00,0xba,0x00,0x82,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x82,0x00,0x84,0x05,0x01,0x00,0x00,0x83,0x05,0x03,0x06,0x04,0x03,0x07,0x84,0x05,0x01,0x00,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x86,0x00,0x84,0x05,0xb8,0x00,0xb9,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x89,0x05,0x03,0x06,
+0x03,0x03,0x07,0x84,0x05,0x01,0x00,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x86,0x00,0x84,0x05,0xb8,0x00,0xb9,0x00,0x8a,0x05,0x83,0x00,0x83,0x05,0x01,0x00,0x00,0x84,0x05,0x83,0x00,0x88,0x05,0x04,0x06,0x07,0x03,0x03,0x06,0x83,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x87,0x00,0x84,0x05,0xb7,0x00,0xb9,0x00,0x89,0x05,0x84,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x83,0x00,0x89,0x05,0x04,0x07,0x04,0x03,0x07,0x06,0x83,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x88,0x00,0x84,0x05,0xb6,0x00,0xb9,0x00,0x88,0x05,0x85,0x00,0x82,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x8a,0x05,0x03,0x07,0x03,0x07,0x06,0x83,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,
+0x05,0x89,0x00,0x84,0x05,0xb5,0x00,0xb9,0x00,0x88,0x05,0x85,0x00,0x82,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x01,0x00,0x00,0x84,0x05,0x03,0x07,0x03,0x07,0x06,0x83,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x8a,0x00,0x83,0x05,0xb5,0x00,0xb9,0x00,0x88,0x05,0x84,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x01,0x00,0x00,0x84,0x05,0x02,0x07,0x03,0x07,0x84,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x82,0x05,0x8b,0x00,0x83,0x05,0xb5,0x00,0xb9,0x00,0x82,0x05,0x01,0x00,0x00,0x83,0x05,0x84,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x01,0x00,0x00,0x84,0x05,0x02,0x07,0x04,0x06,0x84,0x05,0x01,0x00,0x00,0x83,0x05,0x85,
+0x00,0x83,0x05,0x8b,0x00,0x83,0x05,0xb5,0x00,0xb8,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x84,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x02,0x06,0x07,0x07,0x84,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x8c,0x00,0x82,0x05,0xb5,0x00,0xb8,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x84,0x00,0x83,0x05,0x82,0x00,0x83,0x05,0x83,0x00,0x82,0x05,0x82,0x00,0x83,0x05,0x82,0x06,0x84,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x86,0x00,0x01,0x05,0x05,0x82,0x00,0x83,0x05,0xb5,0x00,0xb8,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x84,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x84,0x00,0x82,0x05,0x82,0x00,0x83,
+0x05,0x01,0x06,0x06,0x85,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0xb5,0x00,0xb8,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x84,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x82,0x00,0x85,0x05,0x00,0x06,0x84,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x85,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0xb5,0x00,0xb8,0x00,0x83,0x05,0x01,0x00,0x00,0x83,0x05,0x83,0x00,0x84,0x05,0x01,0x00,0x00,0x83,0x05,0x83,0x00,0x83,0x05,0x01,0x00,0x00,0x86,0x05,0x00,0x06,0x84,0x05,0x82,0x00,0x83,0x05,0x85,0x00,0x82,0x05,0x85,0x00,0x84,0x05,0x01,0x00,0x00,0x83,0x05,0xb5,0x00,0xb8,0x00,0x82,0x05,
+0x82,0x00,0x84,0x05,0x82,0x00,0x84,0x05,0x00,0x00,0x84,0x05,0x83,0x00,0x8b,0x05,0x01,0x00,0x00,0x84,0x05,0x01,0x00,0x00,0x83,0x05,0x86,0x00,0x82,0x05,0x85,0x00,0x84,0x05,0x00,0x06,0x84,0x05,0xb5,0x00,0xb7,0x00,0x83,0x05,0x82,0x00,0x84,0x05,0x82,0x00,0x8a,0x05,0x83,0x00,0x8a,0x05,0x83,0x00,0x89,0x05,0x85,0x00,0x83,0x05,0x85,0x00,0x89,0x05,0xb6,0x00,0xb7,0x00,0x83,0x05,0x82,0x00,0x84,0x05,0x83,0x00,0x88,0x05,0x84,0x00,0x89,0x05,0x84,0x00,0x89,0x05,0x85,0x00,0x83,0x05,0x86,0x00,0x88,0x05,0xb6,0x00,0xb8,0x00,0x82,0x05,0x83,0x00,0x83,0x05,0x84,0x00,0x86,0x05,0x85,0x00,0x87,0x05,0x87,0x00,0x86,0x05,0x87,0x00,0x83,0x05,0x87,0x00,0x85,0x05,
+0xb8,0x00,0xca,0x00,0x82,0x05,0x99,0x00,0x82,0x05,0x97,0x00,0x82,0x05,0xb9,0x00,0xff,0x00,0xbf,0x00,0xff,0x00,0xbf,0x00,0xff,0x00,0xbf,0x00
+};
+
+// http://paulbourke.net/dataformats/tga/
+typedef struct {
+ char idlength;
+ char colourmaptype;
+ char datatypecode;
+ short colourmaporigin;
+ short colourmaplength;
+ char colourmapdepth;
+ short x_origin;
+ short y_origin;
+ short width;
+ short height;
+ char bitsperpixel;
+ char imagedescriptor;
+ struct { byte r,g,b; } palette[8];
+ byte data[0];
+} TGAHeader;
+
+void draw_tga(const byte* tgadata, byte cenx, byte ceny) {
+ const TGAHeader* hdr = (TGAHeader*) tgadata;
+ const byte* src = hdr->data;
+ const width = swapw(hdr->width);
+ const height = swapw(hdr->height);
+ byte* dest = &vidmem[cenx-width/4][ceny-height/2];
+ byte i,j,lastbyte;
+ // set palette from TGA
+ for (i=0; i<8; i++) {
+ byte pal = 0;
+ pal |= (hdr->palette[i].r >> 5);
+ pal |= (hdr->palette[i].g >> 2) & 0x38;
+ pal |= (hdr->palette[i].b) & 0xc0;
+ palette[i] = pal;
+ }
+ // iterate over height of image
+ for (j=0; j HICHAR) return 1;
+ shape = FONT_TABLE[ch - LOCHAR];
+ draw_copy_solid((byte)x, y - (shape[1]>>4),
+ shape[0] & 0xf, shape[1] & 0xf,
+ shape+2, color);
+ return shape[0] >> 4;
+}
+
+void draw_string(const char* str, word x, byte y, byte color) {
+ while (*str) {
+ x += draw_char(*str++, x, y, color);
+ }
+}
diff --git a/presets/williams/font.h b/presets/williams/font.h
new file mode 100644
index 00000000..52adcbde
--- /dev/null
+++ b/presets/williams/font.h
@@ -0,0 +1,4 @@
+
+byte draw_char(char ch, word x, byte y, byte color);
+
+void draw_string(const char* str, word x, byte y, byte color);
diff --git a/presets/williams/fonttest.c b/presets/williams/fonttest.c
new file mode 100644
index 00000000..b5bc8101
--- /dev/null
+++ b/presets/williams/fonttest.c
@@ -0,0 +1,30 @@
+
+#include "williams.h"
+//#link "williams.c"
+
+#include "font.h"
+//#link "font.c"
+
+// 256x304x4bpp video memory
+
+int main(void) {
+ byte i;
+ rom_select = 1;
+ blit_solid(0, 0, 152, 255, 0x00);
+ for (i=0; i<16; i++)
+ palette[i] = (byte)(i*7);
+ for (i=0; i<152; i++) {
+ vidmem[0][i] = 16;
+ vidmem[i][2] = 32;
+ draw_pixel(i, i, 0x77);
+ draw_pixel(i+1, i, 0x33);
+ }
+ while (1) {
+ for (i=0; i<16; i++) {
+ watchdog0x39 = 0x39;
+ draw_string("Hello World, this proportional font is the jam!!",
+ 20, i*17+8, i+i*16);
+ }
+ }
+ return 0;
+}
diff --git a/presets/williams/game1.c b/presets/williams/game1.c
new file mode 100644
index 00000000..75cfef54
--- /dev/null
+++ b/presets/williams/game1.c
@@ -0,0 +1,653 @@
+
+
+#include "williams.h"
+//#link "williams.c"
+
+#include "stdlib.h"
+
+//#link "font.c"
+#include "font.h"
+
+// for CMOC (??)
+void stkcheck() { }
+
+// GRAPHIC DATA
+
+const byte palette_data[16] = {/*{pal:332,n:16}*/
+ 0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1f, 0x37, 0xe0, 0xa4, 0xfd, 0xff, 0x38, 0x70, 0x7f, 0xf8, };
+
+const byte laser_vert[2+1*8] = {
+ 1,8,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+};
+
+const byte laser_horiz[2+4*2] = {
+ 4,2,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+};
+
+
+const byte playersprite1[] = {
+7,16,/*{w:14,h:16,bpp:4,brev:1}*/
+0x00,0x00,0xEF,0xEF,0xE0,0x00,0x00,
+0x00,0xEE,0xEE,0xFE,0xEE,0xE0,0x00,
+0x0E,0xED,0xEF,0xEF,0xED,0xEE,0x00,
+0x0E,0xEE,0xDD,0xDD,0xDE,0xEE,0x00,
+0x0E,0xEE,0xEC,0xDC,0xEE,0xEE,0x00,
+0x00,0xEE,0xEE,0xDE,0xEE,0xE0,0x00,
+0x00,0xEE,0xEE,0xDE,0xEE,0xE0,0x00,
+0x00,0x00,0xED,0xDD,0xE0,0x00,0x00,
+0xDD,0xDD,0xEE,0xEE,0xED,0xDD,0xD0,
+0x0C,0xEE,0xEE,0xEE,0xEE,0xEC,0x00,
+0x0E,0xE0,0xEE,0xEE,0xE0,0xEE,0x00,
+0x0E,0xE0,0xEE,0xEE,0xE0,0xEE,0x00,
+0x0E,0xE0,0xDD,0xDD,0xD0,0xDE,0x00,
+0x0D,0x00,0xEE,0x0E,0xE0,0x0D,0x00,
+0x00,0x00,0xEC,0x0C,0xE0,0x00,0x00,
+0x00,0x0D,0xDD,0x0D,0xDD,0x00,0x00,
+};
+
+const byte sprite1[2+16*16/2] = {
+8,16,/*{w:16,h:16,bpp:4,brev:1}*/
+0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
+0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00,
+0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90,
+0x94,0x99,0x94,0x90,0x09,0x49,0x99,0x49,
+0x99,0x99,0x49,0x93,0x39,0x94,0x99,0x99,
+0x04,0x49,0x99,0x94,0x49,0x99,0x94,0x90,
+0x00,0x94,0x94,0x43,0x34,0x49,0x49,0x00,
+0x00,0x09,0x43,0x94,0x49,0x34,0x90,0x00,
+0x00,0x90,0x00,0x39,0x93,0x00,0x09,0x00,
+0x00,0x09,0x83,0x33,0x33,0x33,0x90,0x00,
+0x00,0x09,0x32,0x23,0x32,0x23,0x90,0x00,
+0x00,0x03,0x03,0x23,0x82,0x30,0x30,0x00,
+0x03,0x30,0x00,0x33,0x33,0x00,0x03,0x30,
+0x00,0x30,0x03,0x00,0x00,0x30,0x03,0x00,
+0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00,
+0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
+};
+
+const byte sprite2[2+16*16/2] = {
+8,16,/*{w:16,h:16,bpp:4,brev:1}*/
+0x00,0x08,0x80,0x40,0x00,0x00,0x8D,0x00,
+0x80,0x94,0x88,0x90,0x09,0x48,0x89,0x00,
+0x08,0x49,0x48,0x66,0x66,0x98,0x94,0x98,
+0x94,0x89,0x66,0x66,0x66,0x66,0x98,0x89,
+0x99,0x66,0x67,0x76,0x67,0x76,0x69,0x98,
+0x88,0x67,0x77,0x66,0x66,0x77,0x74,0x90,
+0x09,0x97,0x74,0x46,0x64,0x47,0x78,0x88,
+0x09,0x89,0x43,0x96,0x69,0x34,0x99,0x90,
+0x08,0x89,0xBB,0x39,0x93,0xBB,0x98,0x90,
+0x80,0x99,0x3B,0x33,0x33,0xB0,0x99,0x88,
+0x00,0x09,0x9C,0xC3,0x3C,0xC8,0x99,0x08,
+0x00,0x00,0x03,0xC3,0x8C,0x30,0x00,0x00,
+0x00,0x00,0x0D,0xD3,0x3D,0x00,0x00,0x00,
+0x00,0x00,0x0D,0x00,0x0D,0xD0,0x00,0x00,
+0x00,0x00,0xDD,0x30,0x03,0xD0,0x00,0x00,
+0x00,0x00,0xD0,0x40,0x00,0xD0,0x00,0x00,
+};
+
+const byte sprite3[2+16*16/2] = {
+8,16,/*{w:16,h:16,bpp:4,brev:1}*/
+0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
+0x00,0x00,0x00,0x11,0x11,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
+0x00,0x11,0x10,0x01,0x10,0x01,0x11,0x00,
+0x11,0x00,0x10,0x11,0x11,0x01,0x00,0x11,
+0x10,0x00,0x11,0x11,0x11,0x11,0x00,0x01,
+0x10,0x00,0x00,0x11,0x11,0x00,0x00,0x01,
+0x00,0x01,0x10,0x11,0x41,0x01,0x10,0x00,
+0x00,0x10,0x11,0x11,0x11,0x11,0x01,0x00,
+0x01,0x00,0x00,0x51,0x15,0x00,0x00,0x10,
+0x01,0x00,0x01,0x10,0x01,0x10,0x00,0x10,
+0x01,0x00,0x10,0x00,0x00,0x01,0x00,0x10,
+0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00,
+0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,
+0x00,0x01,0x10,0x00,0x00,0x01,0x10,0x00,
+};
+
+const byte sprite4[2+16*16/2] = {
+8,16,/*{w:16,h:16,bpp:4,brev:1}*/
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00,
+0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00,
+0x00,0x00,0xbb,0xbb,0xbb,0xbb,0x00,0x00,
+0x00,0x0b,0x4b,0xbb,0xbb,0xb4,0xb0,0x00,
+0x00,0x0b,0x44,0xbb,0xbb,0x49,0xb0,0x00,
+0x00,0xbb,0x99,0x4b,0xb4,0x99,0xbb,0x00,
+0x00,0x4b,0xb9,0x9b,0xb4,0x4b,0xb4,0x00,
+0x00,0x04,0xbb,0x4b,0xb9,0xbb,0x40,0x00,
+0x00,0x00,0x4b,0xbb,0xbb,0xb4,0x00,0x00,
+0x11,0x00,0x0b,0xbb,0xbb,0xb0,0x00,0x11,
+0x10,0x10,0x0b,0x41,0x14,0xb0,0x01,0x01,
+0x10,0x00,0x05,0x11,0x11,0x50,0x00,0x01,
+0x01,0x00,0x01,0x51,0x15,0x10,0x00,0x10,
+0x00,0x10,0x01,0x10,0x01,0x10,0x01,0x00,
+0x01,0x01,0x10,0x10,0x01,0x01,0x10,0x10,
+};
+
+const byte sprite5[2+16*16/2] = {
+8,16,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x22,0x00,0x00,0x22,0x00,0x00,
+0x00,0x20,0x20,0x00,0x00,0x02,0x02,0x00,
+0x02,0x22,0x12,0x00,0x00,0x21,0x22,0x20,
+0x00,0x02,0x11,0x00,0x00,0x11,0x20,0x00,
+0x00,0x00,0x02,0x11,0x11,0x20,0x00,0x00,
+0x00,0x00,0x02,0x22,0x22,0x20,0x00,0x00,
+0x00,0x00,0x21,0x22,0x22,0x12,0x00,0x00,
+0x00,0x00,0x22,0x12,0x21,0x22,0x00,0x00,
+0x02,0x00,0x22,0x12,0x21,0x22,0x00,0x20,
+0x20,0x02,0x21,0x11,0x11,0x12,0x20,0x02,
+0x02,0x22,0x15,0x12,0x21,0x51,0x22,0x20,
+0x02,0x11,0x15,0x52,0x25,0x51,0x11,0x20,
+0x20,0x00,0x22,0x12,0x21,0x22,0x00,0x02,
+0x20,0x02,0x20,0x20,0x02,0x02,0x20,0x02,
+0x02,0x02,0x00,0x20,0x02,0x00,0x20,0x20,
+};
+
+const byte sprite6[2+10*16/2] = {
+8,10,/*{w:16,h:10,bpp:4,brev:1}*/
+0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00,
+0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x40,
+0x00,0x00,0x04,0x04,0x49,0x49,0x99,0x44,
+0x00,0x00,0x44,0x44,0x99,0x94,0x44,0x40,
+0x00,0x04,0x49,0x99,0x94,0x49,0x99,0x40,
+0x00,0x44,0x99,0x94,0x49,0x99,0x44,0x00,
+0x04,0x49,0x44,0x99,0x99,0x44,0x00,0x00,
+0x04,0x44,0x00,0x49,0x44,0x40,0x00,0x00,
+0x04,0x40,0x00,0x04,0x00,0x00,0x00,0x00,
+0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+const byte sprite7[2+14*16/2] = {
+8,14,/*{w:16,h:14,bpp:4,brev:1}*/
+0x00,0x60,0x00,0x00,0x00,0x00,0x06,0x00,
+0x60,0x60,0x00,0x00,0x00,0x00,0x06,0x06,
+0x60,0x60,0x50,0x00,0x00,0x05,0x06,0x06,
+0x60,0x60,0x06,0x00,0x00,0x60,0x06,0x06,
+0x66,0x60,0x06,0x06,0x60,0x60,0x06,0x66,
+0x66,0x60,0x66,0x66,0x66,0x66,0x06,0x66,
+0x66,0x60,0x6b,0x6b,0xb6,0xb6,0x06,0x66,
+0x06,0x66,0x66,0xb6,0x6b,0x66,0x66,0x60,
+0x00,0x67,0x66,0x66,0x66,0x66,0x66,0x00,
+0x00,0x11,0x11,0x66,0x66,0x11,0x11,0x00,
+0x01,0x11,0x21,0x11,0x11,0x12,0x11,0x10,
+0x00,0x10,0x01,0x01,0x10,0x10,0x01,0x00,
+0x00,0x10,0x11,0x00,0x00,0x11,0x01,0x00,
+0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
+};
+
+const byte sprite8[2+15*16/2] = {
+8,15,/*{w:16,h:15,bpp:4,brev:1}*/
+0x00,0x00,0x11,0x11,0x11,0x11,0x00,0x00,
+0x00,0x01,0x61,0x11,0x21,0x12,0x10,0x00,
+0x00,0x11,0x12,0x11,0x61,0x11,0x11,0x00,
+0x00,0x11,0x71,0x21,0x61,0x17,0x11,0x00,
+0x00,0x11,0x77,0x11,0x12,0x77,0x11,0x00,
+0x00,0x11,0x17,0x17,0x71,0x72,0x11,0x00,
+0x00,0x16,0x21,0x78,0x87,0x11,0x11,0x00,
+0x00,0x01,0x81,0x88,0x88,0x18,0x10,0x00,
+0x00,0x08,0x18,0x58,0x85,0x81,0x80,0x00,
+0x00,0x88,0x01,0x88,0x88,0x10,0x88,0x00,
+0x00,0x08,0x07,0x78,0x87,0x70,0x80,0x00,
+0x08,0x80,0x07,0x80,0x08,0x70,0x08,0x80,
+0x88,0x00,0x88,0x00,0x00,0x88,0x00,0x88,
+0x80,0x00,0x08,0x80,0x08,0x80,0x00,0x08,
+0x00,0x00,0x00,0x80,0x08,0x00,0x00,0x00,
+};
+
+const byte sprite9[2+13*16/2] = {
+8,13,/*{w:16,h:13,bpp:4,brev:1}*/
+0x00,0x00,0xaa,0x00,0x00,0xaa,0x00,0x00,
+0x00,0x00,0xa0,0x0a,0xa0,0x0a,0x00,0x00,
+0x0a,0xaa,0xa4,0xaa,0xaa,0x3a,0xaa,0xa0,
+0x00,0x0a,0x3a,0x9a,0xa9,0xa3,0xa0,0x00,
+0x00,0x0a,0xaa,0x99,0xa4,0xaa,0xa0,0x00,
+0x00,0x0a,0xaa,0x99,0x94,0xaa,0xa0,0x00,
+0x00,0xaa,0x33,0xaa,0xaa,0x43,0xaa,0x00,
+0x0a,0x3a,0xaa,0x3a,0xa3,0xaa,0xa3,0xa0,
+0x00,0xaa,0xaa,0x30,0x03,0xaa,0xaa,0x00,
+0x00,0x0a,0xa0,0x30,0x03,0x0a,0xa0,0x00,
+0x00,0xa3,0xa0,0x00,0x00,0x0a,0x4a,0x00,
+0x00,0xaa,0xa0,0x00,0x00,0x0a,0xaa,0x00,
+0x00,0x0a,0xa0,0x00,0x00,0x0a,0xa0,0x00,
+};
+
+const byte* const all_sprites[9] = {
+ sprite1,
+ sprite2,
+ sprite3,
+ sprite4,
+ sprite5,
+ sprite6,
+ sprite7,
+ sprite8,
+ sprite9,
+};
+
+// GAME CODE
+
+typedef struct Actor {
+ struct Actor* next;
+ struct Actor** prevptr;
+ byte x,y;
+ const byte* shape;
+ void (*update)(struct Actor* a);
+ void (*draw)(struct Actor* a);
+ union u {
+ struct { sbyte dx,dy; } laser;
+ struct { byte exploding; } enemy;
+ } u;
+} Actor;
+
+#define MAX_ACTORS 128
+
+static Actor actors[MAX_ACTORS];
+static Actor* player_list;
+static Actor* fast_list;
+static Actor* slow_lists[4];
+static Actor* obstacle_list;
+static Actor* free_list;
+static Actor* effects_list;
+static byte frame;
+
+static word score; // bcd score
+
+#define PLAYER 1
+#define LASER 2
+
+void add_actor(Actor** list, Actor* a) {
+ if (*list) (*list)->prevptr = &a->next;
+ a->next = *list;
+ a->prevptr = list;
+ *list = a;
+}
+
+void remove_actor(Actor* a) {
+ if (a->next) a->next->prevptr = a->prevptr;
+ *a->prevptr = a->next;
+}
+
+void draw_actor_normal(Actor* a) {
+ blit_sprite(a->shape, a->x, a->y);
+}
+
+void draw_actor_exploding(Actor* a) {
+ unblit_sprite_strided(a->shape, a->x, a->y, a->u.enemy.exploding);
+ if (a->u.enemy.exploding > 10) {
+ a->draw = NULL;
+ } else {
+ blit_sprite_strided(a->shape, a->x, a->y, ++a->u.enemy.exploding);
+ }
+}
+
+void update_actor(Actor* a) {
+ // if NULL shape, we don't have anything
+ if (a->shape) {
+ // erase the sprite
+ blit_sprite_solid(a->shape, a->x, a->y, 0);
+ // call update callback
+ if (a->update) {
+ a->update(a);
+ }
+ // did we delete it?
+ if (a->shape) {
+ // draw the sprite
+ if (a->draw) {
+ a->draw(a);
+ }
+ } else {
+ // shape became null, remove from list
+ remove_actor(a);
+ }
+ }
+}
+
+//
+
+word lfsr = 1;
+
+word xrand() {
+ byte lsb = (byte)lfsr & 1;
+ lfsr >>= 1;
+ if (lsb) lfsr ^= 0xd400;
+ return lfsr;
+}
+
+signed char random_dir() {
+ byte x = (byte)xrand();
+ if (x < 85) return 0;
+ else if (x < 85*2) return -1;
+ else return 1;
+}
+
+void update_actor_list(Actor* a) {
+ while (a) {
+ update_actor(a);
+ a = a->next;
+ }
+}
+
+static byte g_section;
+
+void update_actors_partial(Actor* a) {
+ while (a) {
+ if (g_section ^ (a->y < 0x80)) {
+ update_actor(a);
+ }
+ a = a->next;
+ }
+}
+
+void update_screen_section(byte section) {
+ g_section = section;
+ update_actors_partial(player_list);
+ update_actors_partial(fast_list);
+ update_actors_partial(slow_lists[frame & 3]);
+}
+
+static Actor* test_actor;
+static byte test_x, test_y;
+
+byte minbyte(byte a, byte b) { return ab?a:b; }
+
+bool test_actor_pixels(Actor* a) {
+ if (a->shape) {
+ byte x,y;
+ const byte *p1, *p2;
+ byte x1 = maxbyte(test_actor->x, a->x);
+ byte y1 = maxbyte(test_actor->y, a->y);
+ byte x2 = minbyte(test_actor->x + test_actor->shape[0]*2,
+ a->x + a->shape[0]*2);
+ byte y2 = minbyte(test_actor->y + test_actor->shape[1],
+ a->y + a->shape[1]);
+ if (x2 < x1) x2 = 255; // clip to 8-bit coord.
+ if (y2 < y1) y2 = 255; // clip to 8-bit coord.
+ if (x2 <= x1 || y2 <= y1) return false;
+ //draw_box(x1,y1,x2,y2,0xff);
+ p1 = &test_actor->shape[2+(y1-test_actor->y)*test_actor->shape[0]];
+ p2 = &a->shape[2+(y1-a->y)*a->shape[0]];
+ p1 += (x1 - test_actor->x) >> 1;
+ p2 += (x1 - a->x) >> 1;
+ for (y=y1; yshape[0];
+ p2 += a->shape[0];
+ }
+ }
+ return false;
+}
+
+bool test_collision_actor(Actor* a) {
+ return ((byte)(test_y - a->y + 16) < 32 &&
+ (byte)(test_x - a->x + 16) < 32 &&
+ test_actor_pixels(a));
+}
+
+Actor* test_collisions(Actor* a) {
+ while (a) {
+ if (test_collision_actor(a)) {
+ return a;
+ }
+ a = a->next;
+ }
+ return NULL;
+}
+
+void setup_collision(Actor* a) {
+ test_actor = a;
+ test_x = a->x;
+ test_y = a->y;
+}
+
+void destroy_player() {
+ Actor* a = &actors[PLAYER];
+ byte i;
+ sound_pia = 1; // play sound
+ for (i=0; i<60; i++) {
+ WATCHDOG;
+ while (video_counter != 0xfc) ;
+ blit_sprite_solid(a->shape, a->x, a->y, i);
+ while (video_counter == 0xfc) ;
+ }
+ for (i=1; i<60; i++) {
+ WATCHDOG;
+ while (video_counter != 0xfc) ;
+ blit_sprite_strided(a->shape, a->x+i, a->y, i);
+ blit_sprite_strided(a->shape, a->x-i, a->y, i);
+ while (video_counter == 0xfc) ;
+ }
+}
+
+void random_walk(Actor* a) {
+ a->x += random_dir();
+ a->y += random_dir();
+ setup_collision(a);
+ if (actors[PLAYER].shape && test_collision_actor(&actors[PLAYER])) {
+ destroy_player();
+ actors[PLAYER].shape = NULL;
+ }
+}
+
+void laser_move(Actor* a) {
+ // did we hit something?
+ Actor* collided;
+ setup_collision(a);
+ collided = test_collisions(fast_list);
+ if (!collided) collided = test_collisions(slow_lists[0]);
+ if (!collided) collided = test_collisions(slow_lists[1]);
+ if (!collided) collided = test_collisions(slow_lists[2]);
+ if (!collided) collided = test_collisions(slow_lists[3]);
+ if (collided) {
+ // get rid of laser (we can do this in our 'update' fn)
+ a->shape = NULL;
+ // set exploding counter for enemy, change fn pointers
+ collided->draw = draw_actor_exploding;
+ collided->update = NULL;
+ collided->u.enemy.exploding = 1;
+ // move enemy to effects list
+ remove_actor(collided);
+ add_actor(&effects_list, collided);
+ // play sound
+ sound_pia = 2;
+ // add score
+ score = bcd_add(score, 5);
+ return;
+ }
+ // move laser
+ // check for wall collisions
+ a->x += a->u.laser.dx;
+ if (a->u.laser.dx > 0 && a->x < 8) a->shape = NULL;
+ if (a->u.laser.dx < 0 && a->x > 255-8) a->shape = NULL;
+ a->y += a->u.laser.dy;
+ if (a->y > 255-8) a->shape = NULL;
+}
+
+void shoot_laser(sbyte dx, sbyte dy, const byte* shape) {
+ Actor* a = &actors[LASER];
+ a->shape = (byte*) shape;
+ a->x = actors[PLAYER].x + 6;
+ a->y = actors[PLAYER].y + 8;
+ a->u.laser.dx = dx;
+ a->u.laser.dy = dy;
+ add_actor(&player_list, a);
+}
+
+void player_laser() {
+ // is the laser being used?
+ if (actors[LASER].shape == NULL) { // no, check controls
+ if (UP2) shoot_laser(0,-8,laser_vert);
+ else if (DOWN2) shoot_laser(0,8,laser_vert);
+ else if (LEFT2) shoot_laser(-8,0,laser_horiz);
+ else if (RIGHT2) shoot_laser(8,0,laser_horiz);
+ }
+}
+
+void player_move(Actor* a) {
+ byte x = a->x;
+ byte y = a->y;
+ if (UP1) y-=1;
+ if (DOWN1) y+=1;
+ if (LEFT1) x-=1;
+ if (RIGHT1) x+=1;
+ a->x = x;
+ a->y = y;
+ player_laser();
+}
+
+static Actor* current_effect;
+
+void effects_new_frame() {
+ current_effect = effects_list;
+}
+
+void effects_next() {
+ if (current_effect) {
+ if (current_effect->draw) {
+ current_effect->draw(current_effect);
+ } else {
+ remove_actor(current_effect);
+ }
+ current_effect = current_effect->next;
+ }
+}
+
+Actor* new_actor() {
+ Actor* a = free_list;
+ remove_actor(a);
+ a->draw = draw_actor_normal;
+ return a;
+}
+
+Actor* new_effect(void (*draw)(struct Actor *)) {
+ Actor* a = new_actor();
+ a->draw = draw;
+ add_actor(&effects_list, a);
+ return a;
+}
+
+void init() {
+ byte i;
+ blit_solid(0, 0, 255, 255, 0);
+ memset(actors, 0, sizeof(actors));
+ memcpy(palette, palette_data, 16);
+ player_list = fast_list = obstacle_list = free_list = NULL;
+ memset(slow_lists, 0, sizeof(slow_lists));
+ // add all actors to free list
+ for (i=MAX_ACTORS-1; i>0; i--) {
+ add_actor(&free_list, &actors[i]);
+ }
+ score = 0;
+}
+
+void make_player_actors() {
+ // make player
+ Actor* a = new_actor();
+ a->x = 128;
+ a->y = 120;
+ a->shape = (byte*) playersprite1;
+ a->update = player_move;
+ add_actor(&player_list, a);
+ // make laser
+ a = new_actor();
+ a->update = laser_move;
+ a->shape = NULL;
+}
+
+void make_enemy_actors() {
+ byte i;
+ const byte num_actors = 32;
+ for (i=3; ix = (byte)xrand();
+ a->y = (byte)xrand() + 24;
+ } while ((byte)(a->x - 96) < 64 && (byte)(a->y - 96) < 64);
+ a->shape = (byte*) all_sprites[i%9];
+ a->update = random_walk;
+ a->draw = draw_actor_normal;
+ if (i < 5) add_actor(&fast_list, a);
+ else add_actor(&slow_lists[i&3], a);
+ WATCHDOG;
+ }
+}
+
+void draw_bcd_word(word bcd, word x, byte y, byte color) {
+ byte j;
+ x += 4*4;
+ for (j=0; j<4; j++) {
+ x -= 4;
+ draw_char('0'+((byte)bcd & 0xf), x, y, color);
+ bcd >>= 4;
+ }
+}
+
+void draw_score(Actor* a) {
+ a;
+ draw_string("Plyr 1", 278, 8, 0xee);
+ // draw digits in color 0 so the background is erased
+ draw_bcd_word(score, 278, 20, 0);
+ // last two digits of score are "00"
+ draw_char('0', 278+16, 20, 0);
+ draw_char('0', 278+20, 20, 0);
+}
+
+void draw_playfield(Actor* a) {
+// draw_box(0,0,275,255,0x11);
+}
+
+int main() {
+ init();
+ make_player_actors();
+ make_enemy_actors();
+ // add low-priority effects here, because new effects
+ // are added to the head of the list
+ new_effect(draw_score);
+ new_effect(draw_playfield);
+ // main loop
+ while (actors[PLAYER].shape) {
+ WATCHDOG;
+ effects_new_frame();
+ while (video_counter >= 0x90) effects_next();
+ update_screen_section(1);
+ while (video_counter < 0x90) effects_next();
+ update_screen_section(0);
+ switch (frame & 7) {
+ case 0:
+ break;
+ }
+ score = bcd_add(score, 1);
+ frame++;
+ }
+ return 0;
+}
+
+// SOUND ROM
+/*
+const byte __at(0x9000) SOUND_ROM[] = {
+0xdb,0x00,0xb7,0x20,0x01,0x76,0x31,0x00,0x80,0xf3,0x11,0x00,0x40,0xdb,0x00,0x4f,0x0d,0x06,0x00,0x69,0x60,0x29,0x09,0x29,0x29,0x01,0x2b,0x01,0x09,0x01,0x0c,0x00,0xed,0xb0,0xcd,0xb5,0x01,0x3e,0x00,0xd3,0x00,0x76,0xc9,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0x00,0x03,0x06,0x09,0x0c,0x10,0x13,0x16,0x19,0x1c,0x1f,0x22,0x25,0x28,0x2b,0x2e,0x31,0x33,0x36,0x39,0x3c,
+0x3f,0x41,0x44,0x47,0x49,0x4c,0x4e,0x51,0x53,0x55,0x58,0x5a,0x5c,0x5e,0x60,0x62,0x64,0x66,0x68,0x6a,0x6b,0x6d,0x6f,0x70,0x71,0x73,0x74,0x75,0x76,0x78,0x79,0x7a,0x7a,0x7b,0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7e,0x7e,0x7e,0x7d,0x7d,0x7c,0x7b,0x7a,0x7a,0x79,0x78,0x76,0x75,0x74,0x73,0x71,0x70,0x6f,0x6d,0x6b,0x6a,0x68,0x66,0x64,0x62,0x60,0x5e,0x5c,0x5a,0x58,0x55,0x53,0x51,0x4e,0x4c,0x49,0x47,0x44,0x41,0x3f,0x3c,0x39,0x36,0x33,0x31,0x2e,0x2b,0x28,0x25,0x22,0x1f,0x1c,0x19,0x16,0x13,0x10,0x0c,0x09,0x06,0x03,0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8,0x00,0x08,0x10,0x18,0x20,
+0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x60,0x37,0x3f,0x5c,0x16,0xca,0xc2,0xa5,0xfe,0xba,0x77,0x89,0xaa,0x77,0x13,0xd8,0xae,0x82,0xfd,0x22,0x9c,0x46,0xde,0x14,0x50,0xb4,0x97,0x46,0x54,0x9d,0x60,0x2b,0xb0,0x04,0x00,0x00,0x00,0x00,0x01,0x00,0x0b,0x01,0xff,0x00,0xfa,0x00,0x00,0x00,0xe8,0x03,0xfc,0xff,0x6b,0x00,0x7f,0x00,0xf4,0x01,0x00,0x00,0xe8,0x03,0x02,0x00,0xeb,0x00,0x1f,0x00,0x58,0x02,0x00,0x00,0xb8,0x0b,0xff,0xff,0x2b,0x00,0x1f,0x00,0x58,0x02,0x00,0x00,0xb8,0x0b,0xff,0xff,0x4b,0x00,0x1f,0x00,0x58,0x02,0x00,0x00,0xb8,0x0b,0x01,0x00,0x2b,0x00,0x3f,0x00,0xb0,0x04,0x00,0x00,0x00,0x00,0x01,0x00,0x6b,0x00,0x7f,0x01,0xdd,
+0xe5,0xdd,0x21,0x00,0x00,0xdd,0x39,0x3b,0xed,0x5b,0x08,0x40,0xed,0x4b,0x02,0x40,0xdd,0x70,0xff,0x3a,0x0a,0x40,0xdd,0xa6,0xff,0x6f,0x26,0x00,0x19,0x5e,0x3a,0x0c,0x40,0x93,0x38,0x03,0x7b,0xd3,0x00,0x2a,0x04,0x40,0x09,0x4d,0x44,0xed,0x43,0x02,0x40,0x33,0xdd,0xe1,0xc9,0x21,0x0c,0x40,0x36,0xff,0xed,0x4b,0x00,0x40,0x59,0x50,0x1b,0xed,0x53,0x00,0x40,0x78,0xb1,0xc8,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xed,0x4b,0x04,0x40,0x2a,0x06,0x40,0x09,0x4d,0x44,0xed,0x43,0x04,0x40,0xed,0x4b,0x06,0x40,0x3a,0x0b,0x40,0x6f,0x17,0x9f,0x67,0x09,0x4d,0x44,0xed,0x43,0x06,0x40,
+0x2a,0x00,0x40,0x3e,0xff,0xbd,0x3e,0x00,0x9c,0x38,0xaf,0xfd,0x21,0x0c,0x40,0xfd,0x75,0x00,0x18,0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+*/
diff --git a/presets/williams/gfxtest.c b/presets/williams/gfxtest.c
new file mode 100644
index 00000000..ea9b4a6e
--- /dev/null
+++ b/presets/williams/gfxtest.c
@@ -0,0 +1,83 @@
+
+#include "williams.h"
+//#link "williams.c"
+
+// 256x304x4bpp video memory
+
+#define LOCHAR 0x21
+#define HICHAR 0x5e
+
+const byte font8x8[HICHAR-LOCHAR+1][8] = {
+{ 0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x00 }, { 0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00 }, { 0x66,0x66,0xff,0x66,0xff,0x66,0x66,0x00 }, { 0x18,0x3e,0x60,0x3c,0x06,0x7c,0x18,0x00 }, { 0x62,0x66,0x0c,0x18,0x30,0x66,0x46,0x00 }, { 0x3c,0x66,0x3c,0x38,0x67,0x66,0x3f,0x00 }, { 0x06,0x0c,0x18,0x00,0x00,0x00,0x00,0x00 }, { 0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00 }, { 0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00 }, { 0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00 }, { 0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30 }, { 0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 }, { 0x00,0x03,0x06,0x0c,0x18,0x30,0x60,0x00 }, { 0x3c,0x66,0x6e,0x76,0x66,0x66,0x3c,0x00 }, { 0x18,0x18,0x38,0x18,0x18,0x18,0x7e,0x00 }, { 0x3c,0x66,0x06,0x0c,0x30,0x60,0x7e,0x00 }, { 0x3c,0x66,0x06,0x1c,0x06,0x66,0x3c,0x00 }, { 0x06,0x0e,0x1e,0x66,0x7f,0x06,0x06,0x00 }, { 0x7e,0x60,0x7c,0x06,0x06,0x66,0x3c,0x00 }, { 0x3c,0x66,0x60,0x7c,0x66,0x66,0x3c,0x00 }, { 0x7e,0x66,0x0c,0x18,0x18,0x18,0x18,0x00 }, { 0x3c,0x66,0x66,0x3c,0x66,0x66,0x3c,0x00 }, { 0x3c,0x66,0x66,0x3e,0x06,0x66,0x3c,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x18,0x30 }, { 0x0e,0x18,0x30,0x60,0x30,0x18,0x0e,0x00 }, { 0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00 }, { 0x70,0x18,0x0c,0x06,0x0c,0x18,0x70,0x00 }, { 0x3c,0x66,0x06,0x0c,0x18,0x00,0x18,0x00 }, { 0x3c,0x66,0x6e,0x6e,0x60,0x62,0x3c,0x00 }, { 0x18,0x3c,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x7c,0x66,0x66,0x7c,0x66,0x66,0x7c,0x00 }, { 0x3c,0x66,0x60,0x60,0x60,0x66,0x3c,0x00 }, { 0x78,0x6c,0x66,0x66,0x66,0x6c,0x78,0x00 }, { 0x7e,0x60,0x60,0x78,0x60,0x60,0x7e,0x00 }, { 0x7e,0x60,0x60,0x78,0x60,0x60,0x60,0x00 }, { 0x3c,0x66,0x60,0x6e,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x3c,0x18,0x18,0x18,0x18,0x18,0x3c,0x00 }, { 0x1e,0x0c,0x0c,0x0c,0x0c,0x6c,0x38,0x00 }, { 0x66,0x6c,0x78,0x70,0x78,0x6c,0x66,0x00 }, { 0x60,0x60,0x60,0x60,0x60,0x60,0x7e,0x00 }, { 0x63,0x77,0x7f,0x6b,0x63,0x63,0x63,0x00 }, { 0x66,0x76,0x7e,0x7e,0x6e,0x66,0x66,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x7c,0x66,0x66,0x7c,0x60,0x60,0x60,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x3c,0x0e,0x00 }, { 0x7c,0x66,0x66,0x7c,0x78,0x6c,0x66,0x00 }, { 0x3c,0x66,0x60,0x3c,0x06,0x66,0x3c,0x00 }, { 0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x3c,0x18,0x00 }, { 0x63,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00 }, { 0x66,0x66,0x3c,0x18,0x3c,0x66,0x66,0x00 }, { 0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x00 }, { 0x7e,0x06,0x0c,0x18,0x30,0x60,0x7e,0x00 }, { 0x3c,0x30,0x30,0x30,0x30,0x30,0x3c,0x00 }, { 0x00,0x60,0x30,0x18,0x0c,0x06,0x03,0x00 }, { 0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00 }, { 0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18 }
+};
+
+const byte sprite1[] = {
+8,16,
+0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
+0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00,
+0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90,
+0x94,0x99,0x94,0x90,0x09,0x49,0x99,0x49,
+0x99,0x99,0x49,0x93,0x39,0x94,0x99,0x99,
+0x04,0x49,0x99,0x94,0x49,0x99,0x94,0x90,
+0x00,0x94,0x94,0x43,0x34,0x49,0x49,0x00,
+0x00,0x09,0x43,0x94,0x49,0x34,0x90,0x00,
+0x00,0x90,0x00,0x39,0x93,0x00,0x09,0x00,
+0x00,0x09,0x83,0x33,0x33,0x33,0x90,0x00,
+0x00,0x09,0x32,0x23,0x32,0x23,0x90,0x00,
+0x00,0x03,0x03,0x23,0x82,0x30,0x30,0x00,
+0x03,0x30,0x00,0x33,0x33,0x00,0x03,0x30,
+0x00,0x30,0x03,0x00,0x00,0x30,0x03,0x00,
+0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00,
+0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,
+};
+
+void draw_char(char ch, byte x, byte y, byte color) {
+ byte data[8][4];
+ const byte* src = &font8x8[ch-LOCHAR][0];
+ int i,j,pixels;
+ if (ch < LOCHAR || ch > HICHAR) return;
+ for (i=0; i<8; i++) {
+ byte b = *src++;
+ for (j=0; j<4; j++) {
+ pixels = 0;
+ if (b & 0x80) pixels |= color & 0xf0;
+ if (b & 0x40) pixels |= color & 0x0f;
+ data[i][j] = (byte)pixels;
+ b <<= 2;
+ }
+ }
+ blit_copy(x, y, 4, 8, (byte*)data);
+}
+
+void draw_string(const char* str, byte x, byte y, byte color) {
+ char ch;
+ do {
+ ch = *str++;
+ draw_char(ch, x, y, color);
+ x += 4;
+ } while (ch);
+}
+
+int main(void) {
+ byte i;
+ rom_select = 1;
+ blit_solid(0, 0, 152, 255, 0x00);
+ for (i=0; i<16; i++)
+ palette[i] = (byte)(i*7);
+ for (i=0; i<152; i++) {
+ vidmem[0][i] = 16;
+ vidmem[i][2] = 32;
+ draw_pixel(i, i, 0x77);
+ draw_pixel(i+1, i, 0x33);
+ }
+ while (1) {
+ watchdog0x39 = 0x39;
+ blit_sprite(sprite1, 35, 20);
+ blit_sprite_solid(sprite1, 55, 20, 0x24);
+ blit_solid(75, 20, 40, 20, 0x35);
+ draw_string("HELLO WORLD", 20, 5, 0x88);
+ }
+ return 0;
+}
+
+
diff --git a/presets/williams/sprites.c b/presets/williams/sprites.c
new file mode 100644
index 00000000..5c5bcddf
--- /dev/null
+++ b/presets/williams/sprites.c
@@ -0,0 +1,334 @@
+
+#include "williams.h"
+//#link "williams.c"
+
+#include "stdlib.h"
+
+const byte palette_data[16] = {
+ 0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1f, 0x37, 0xe0, 0xa4, 0xfd, 0xff, 0x00, 0x00, 0x00, 0xf8, };
+
+const byte sprite1[2+16*16/2] = {
+8,16,
+0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
+0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00,
+0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90,
+0x94,0x99,0x94,0x90,0x09,0x49,0x99,0x49,
+0x99,0x99,0x49,0x93,0x39,0x94,0x99,0x99,
+0x04,0x49,0x99,0x94,0x49,0x99,0x94,0x90,
+0x00,0x94,0x94,0x43,0x34,0x49,0x49,0x00,
+0x00,0x09,0x43,0x94,0x49,0x34,0x90,0x00,
+0x00,0x90,0x00,0x39,0x93,0x00,0x09,0x00,
+0x00,0x09,0x83,0x33,0x33,0x33,0x90,0x00,
+0x00,0x09,0x32,0x23,0x32,0x23,0x90,0x00,
+0x00,0x03,0x03,0x23,0x82,0x30,0x30,0x00,
+0x03,0x30,0x00,0x33,0x33,0x00,0x03,0x30,
+0x00,0x30,0x03,0x00,0x00,0x30,0x03,0x00,
+0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00,
+0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
+};
+
+const byte sprite2[2+16*15/2] = {
+8,16,
+0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00,
+0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90,
+0x94,0x99,0x94,0x90,0x09,0x49,0x99,0x49,
+0x99,0x99,0x49,0x93,0x39,0x94,0x99,0x99,
+0x04,0x49,0x99,0x94,0x49,0x99,0x94,0x90,
+0x00,0x94,0x94,0x43,0x34,0x49,0x49,0x00,
+0x00,0x09,0x43,0x94,0x49,0x34,0x90,0x00,
+0x00,0x90,0x00,0x39,0x93,0x00,0x09,0x00,
+0x00,0x09,0x83,0x33,0x33,0x33,0x90,0x00,
+0x00,0x09,0x32,0x23,0x32,0x23,0x90,0x00,
+0x00,0x03,0x03,0x23,0x82,0x30,0x30,0x00,
+0x03,0x30,0x00,0x33,0x33,0x00,0x03,0x30,
+0x00,0x30,0x03,0x00,0x00,0x30,0x03,0x00,
+0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00,
+0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,
+};
+
+const byte sprite3[2+16*16/2] = {
+8,16,
+0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
+0x00,0x00,0x00,0x11,0x11,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
+0x00,0x11,0x10,0x01,0x10,0x01,0x11,0x00,
+0x11,0x00,0x10,0x11,0x11,0x01,0x00,0x11,
+0x10,0x00,0x11,0x11,0x11,0x11,0x00,0x01,
+0x10,0x00,0x00,0x11,0x11,0x00,0x00,0x01,
+0x00,0x01,0x10,0x11,0x41,0x01,0x10,0x00,
+0x00,0x10,0x11,0x11,0x11,0x11,0x01,0x00,
+0x01,0x00,0x00,0x51,0x15,0x00,0x00,0x10,
+0x01,0x00,0x01,0x10,0x01,0x10,0x00,0x10,
+0x01,0x00,0x10,0x00,0x00,0x01,0x00,0x10,
+0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00,
+0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,
+0x00,0x01,0x10,0x00,0x00,0x01,0x10,0x00,
+};
+
+const byte sprite4[2+16*16/2] = {
+8,16,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00,
+0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00,
+0x00,0x00,0xbb,0xbb,0xbb,0xbb,0x00,0x00,
+0x00,0x0b,0x4b,0xbb,0xbb,0xb4,0xb0,0x00,
+0x00,0x0b,0x44,0xbb,0xbb,0x49,0xb0,0x00,
+0x00,0xbb,0x99,0x4b,0xb4,0x99,0xbb,0x00,
+0x00,0x4b,0xb9,0x9b,0xb4,0x4b,0xb4,0x00,
+0x00,0x04,0xbb,0x4b,0xb9,0xbb,0x40,0x00,
+0x00,0x00,0x4b,0xbb,0xbb,0xb4,0x00,0x00,
+0x11,0x00,0x0b,0xbb,0xbb,0xb0,0x00,0x11,
+0x10,0x10,0x0b,0x41,0x14,0xb0,0x01,0x01,
+0x10,0x00,0x05,0x11,0x11,0x50,0x00,0x01,
+0x01,0x00,0x01,0x51,0x15,0x10,0x00,0x10,
+0x00,0x10,0x01,0x10,0x01,0x10,0x01,0x00,
+0x01,0x01,0x10,0x10,0x01,0x01,0x10,0x10,
+};
+
+const byte sprite5[2+16*16/2] = {
+8,16,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x22,0x00,0x00,0x22,0x00,0x00,
+0x00,0x20,0x20,0x00,0x00,0x02,0x02,0x00,
+0x02,0x22,0x12,0x00,0x00,0x21,0x22,0x20,
+0x00,0x02,0x11,0x00,0x00,0x11,0x20,0x00,
+0x00,0x00,0x02,0x11,0x11,0x20,0x00,0x00,
+0x00,0x00,0x02,0x22,0x22,0x20,0x00,0x00,
+0x00,0x00,0x21,0x22,0x22,0x12,0x00,0x00,
+0x00,0x00,0x22,0x12,0x21,0x22,0x00,0x00,
+0x02,0x00,0x22,0x12,0x21,0x22,0x00,0x20,
+0x20,0x02,0x21,0x11,0x11,0x12,0x20,0x02,
+0x02,0x22,0x15,0x12,0x21,0x51,0x22,0x20,
+0x02,0x11,0x15,0x52,0x25,0x51,0x11,0x20,
+0x20,0x00,0x22,0x12,0x21,0x22,0x00,0x02,
+0x20,0x02,0x20,0x20,0x02,0x02,0x20,0x02,
+0x02,0x02,0x00,0x20,0x02,0x00,0x20,0x20,
+};
+
+const byte sprite6[2+16*10/2] = {
+8,10,
+0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00,
+0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x40,
+0x00,0x00,0x04,0x04,0x49,0x49,0x99,0x44,
+0x00,0x00,0x44,0x44,0x99,0x94,0x44,0x40,
+0x00,0x04,0x49,0x99,0x94,0x49,0x99,0x40,
+0x00,0x44,0x99,0x94,0x49,0x99,0x44,0x00,
+0x04,0x49,0x44,0x99,0x99,0x44,0x00,0x00,
+0x04,0x44,0x00,0x49,0x44,0x40,0x00,0x00,
+0x04,0x40,0x00,0x04,0x00,0x00,0x00,0x00,
+0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+const byte sprite7[2+16*14/2] = {
+8,14,
+0x00,0x60,0x00,0x00,0x00,0x00,0x06,0x00,
+0x60,0x60,0x00,0x00,0x00,0x00,0x06,0x06,
+0x60,0x60,0x50,0x00,0x00,0x05,0x06,0x06,
+0x60,0x60,0x06,0x00,0x00,0x60,0x06,0x06,
+0x66,0x60,0x06,0x06,0x60,0x60,0x06,0x66,
+0x66,0x60,0x66,0x66,0x66,0x66,0x06,0x66,
+0x66,0x60,0x6b,0x6b,0xb6,0xb6,0x06,0x66,
+0x06,0x66,0x66,0xb6,0x6b,0x66,0x66,0x60,
+0x00,0x67,0x66,0x66,0x66,0x66,0x66,0x00,
+0x00,0x11,0x11,0x66,0x66,0x11,0x11,0x00,
+0x01,0x11,0x21,0x11,0x11,0x12,0x11,0x10,
+0x00,0x10,0x01,0x01,0x10,0x10,0x01,0x00,
+0x00,0x10,0x11,0x00,0x00,0x11,0x01,0x00,
+0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
+};
+
+const byte sprite8[2+16*15/2] = {
+8,15,
+0x00,0x00,0x11,0x11,0x11,0x11,0x00,0x00,
+0x00,0x01,0x61,0x11,0x21,0x12,0x10,0x00,
+0x00,0x11,0x12,0x11,0x61,0x11,0x11,0x00,
+0x00,0x11,0x71,0x21,0x61,0x17,0x11,0x00,
+0x00,0x11,0x77,0x11,0x12,0x77,0x11,0x00,
+0x00,0x11,0x17,0x17,0x71,0x72,0x11,0x00,
+0x00,0x16,0x21,0x78,0x87,0x11,0x11,0x00,
+0x00,0x01,0x81,0x88,0x88,0x18,0x10,0x00,
+0x00,0x08,0x18,0x58,0x85,0x81,0x80,0x00,
+0x00,0x88,0x01,0x88,0x88,0x10,0x88,0x00,
+0x00,0x08,0x07,0x78,0x87,0x70,0x80,0x00,
+0x08,0x80,0x07,0x80,0x08,0x70,0x08,0x80,
+0x88,0x00,0x88,0x00,0x00,0x88,0x00,0x88,
+0x80,0x00,0x08,0x80,0x08,0x80,0x00,0x08,
+0x00,0x00,0x00,0x80,0x08,0x00,0x00,0x00,
+};
+
+const byte sprite9[2+13*16/2] = {
+8,13,
+0x00,0x00,0xaa,0x00,0x00,0xaa,0x00,0x00,
+0x00,0x00,0xa0,0x0a,0xa0,0x0a,0x00,0x00,
+0x0a,0xaa,0xa4,0xaa,0xaa,0x3a,0xaa,0xa0,
+0x00,0x0a,0x3a,0x9a,0xa9,0xa3,0xa0,0x00,
+0x00,0x0a,0xaa,0x99,0xa4,0xaa,0xa0,0x00,
+0x00,0x0a,0xaa,0x99,0x94,0xaa,0xa0,0x00,
+0x00,0xaa,0x33,0xaa,0xaa,0x43,0xaa,0x00,
+0x0a,0x3a,0xaa,0x3a,0xa3,0xaa,0xa3,0xa0,
+0x00,0xaa,0xaa,0x30,0x03,0xaa,0xaa,0x00,
+0x00,0x0a,0xa0,0x30,0x03,0x0a,0xa0,0x00,
+0x00,0xa3,0xa0,0x00,0x00,0x0a,0x4a,0x00,
+0x00,0xaa,0xa0,0x00,0x00,0x0a,0xaa,0x00,
+0x00,0x0a,0xa0,0x00,0x00,0x0a,0xa0,0x00,
+};
+
+const byte* const all_sprites[9] = {
+ sprite1,
+ sprite2,
+ sprite3,
+ sprite4,
+ sprite5,
+ sprite6,
+ sprite7,
+ sprite8,
+ sprite9,
+};
+
+//typedef void ActorUpdateFn(struct Actor* a);
+//typedef void ActorDrawFn(struct Actor* a);
+//typedef void ActorEnumerateFn(struct Actor* a);
+
+typedef struct Actor {
+ byte grid_index;
+ byte next_actor;
+ byte x,y;
+ byte* shape;
+ void (*update)(struct Actor* a);
+ void (*draw)(struct Actor* a);
+} Actor;
+
+#define GBITS 3
+#define GDIM (1<> (8-GBITS)) | (y & ((GDIM-1) << GBITS));
+}
+
+void insert_into_grid(byte gi, byte actor_index) {
+ struct Actor* a = &actors[actor_index];
+ a->grid_index = gi;
+ a->next_actor = grid[gi];
+ grid[gi] = actor_index;
+}
+
+void delete_from_grid(byte gi, byte actor_index) {
+ byte i = grid[gi];
+ byte next = actors[actor_index].next_actor;
+ // is actor to delete at head of list?
+ if (i == actor_index) {
+ grid[gi] = next;
+ } else {
+ // iterate through the list
+ do {
+ byte j = actors[i].next_actor;
+ if (j == actor_index) {
+ actors[i].next_actor = next;
+ break;
+ }
+ i = j;
+ } while (1); // watchdog reset if actor not found to delete
+ }
+ actors[actor_index].next_actor = 0;
+ actors[actor_index].grid_index = 0;
+}
+
+void draw_actor(struct Actor* a) {
+ blit_sprite(a->shape, a->x, a->y);
+}
+
+void draw_actor_debug(struct Actor* a) {
+ blit_sprite_solid(a->shape, a->x, a->y, a->next_actor?0xff:0x33);
+}
+
+byte update_actor(byte actor_index) {
+ struct Actor* a = &actors[actor_index];
+ byte next_actor;
+ byte gi0,gi1;
+ if (!a->shape) return 0;
+ next_actor = a->next_actor;
+ gi0 = a->grid_index;
+ blit_sprite_solid(a->shape, a->x, a->y, 0);
+ if (a->update) a->update(a);
+ if (a->draw) a->draw(a);
+ //draw_sprite_strided(a->shape, a->x, a->y, 2);
+ gi1 = xy2grid(a->x, a->y);
+ if (gi0 != gi1) {
+ delete_from_grid(gi0, actor_index);
+ insert_into_grid(gi1, actor_index);
+ }
+ return next_actor;
+}
+
+//
+
+word lfsr = 1;
+
+word xrand() {
+ byte lsb = (byte)(lfsr & 1);
+ lfsr >>= 1;
+ if (lsb) lfsr ^= 0xd400;
+ return lfsr;
+}
+
+signed char random_dir() {
+ byte x = (byte)xrand();
+ if (x < 85) return 0;
+ else if (x < 85*2) return -1;
+ else return 1;
+}
+
+void random_walk(Actor* a) {
+ a->x += random_dir();
+ a->y += random_dir();
+}
+
+void update_grid_cell(byte grid_index) {
+ byte actor_index = grid[grid_index];
+ while (actor_index) {
+ actor_index = update_actor(actor_index);
+ }
+}
+
+void update_grid_rows(byte row_start, byte row_end) {
+ byte i0 = row_start * GDIM;
+ byte i1 = row_end * GDIM;
+ byte i;
+ for (i=i0; i!=i1; i++) {
+ update_grid_cell(i);
+ }
+}
+
+int main() {
+ byte i;
+ byte num_actors = 32;
+ blit_solid(0, 0, 255, 255, 0);
+ memset(grid, 0, sizeof(grid));
+ memset(actors, 0, sizeof(actors));
+ memcpy(palette, palette_data, 16);
+ for (i=1; ix = (i & 3) * 16 + 32;
+ a->y = (i / 4) * 16 + 64;
+ a->shape = (byte*) all_sprites[i%9];
+ a->update = random_walk;
+ a->draw = draw_actor; // draw_actor_debug;
+ insert_into_grid(xy2grid(a->x, a->y), i);
+ watchdog0x39 = 0x39;
+ }
+ while (1) {
+ // update top half while drawing bottom half
+ while (video_counter < 0x80) ;
+ update_grid_rows(0,GDIM/2);
+ // update bottom half while drawing top half
+ while (video_counter >= 0x80) ;
+ update_grid_rows(GDIM/2,GDIM);
+ watchdog0x39 = 0x39;
+ }
+ return 0;
+}
diff --git a/presets/williams/williams.c b/presets/williams/williams.c
new file mode 100644
index 00000000..df7d8261
--- /dev/null
+++ b/presets/williams/williams.c
@@ -0,0 +1,145 @@
+
+#include "williams.h"
+
+// bias sprites by +4 pixels
+#define XBIAS 2
+
+// x1: 0-151
+// y1: 0-255
+
+void blit_solid(byte x1, byte y1, byte w, byte h, byte color) {
+ blitter.width = w^4;
+ blitter.height = h^4;
+ blitter.dstart = ((word)x1<<8)+y1; // swapped
+ blitter.solid = color;
+ blitter.flags = DSTSCREEN|SOLID;
+}
+
+void blit_copy(byte x1, byte y1, byte w, byte h, const byte* data) {
+ blitter.width = w^4;
+ blitter.height = h^4;
+ blitter.sstart = (word)data;
+ blitter.dstart = ((word)x1<<8)+y1; // swapped
+ blitter.solid = 0;
+ blitter.flags = DSTSCREEN|FGONLY;
+}
+
+void blit_copy_solid(byte x1, byte y1, byte w, byte h, const byte* data, byte solid) {
+ blitter.width = w^4;
+ blitter.height = h^4;
+ blitter.sstart = (word)data;
+ blitter.dstart = ((word)x1<<8)+y1; // swapped
+ blitter.solid = solid;
+ if (solid)
+ blitter.flags = DSTSCREEN|FGONLY|SOLID;
+ else
+ blitter.flags = DSTSCREEN;
+}
+
+void blit_sprite(const byte* data, byte x, byte y) {
+ blitter.width = data[0]^4;
+ blitter.height = data[1]^4;
+ blitter.sstart = (word)(data+2);
+ blitter.dstart = ((word)(x+XBIAS)<<8)+y; // swapped
+ blitter.solid = 0;
+ blitter.flags = DSTSCREEN|FGONLY;
+}
+
+void blit_sprite_solid(const byte* data, byte x, byte y, byte color) {
+ blitter.width = data[0]^4;
+ blitter.height = data[1]^4;
+ blitter.sstart = (word)(data+2);
+ blitter.dstart = ((word)(x+XBIAS)<<8)+y; // swapped
+ blitter.solid = color;
+ blitter.flags = DSTSCREEN|FGONLY|SOLID;
+}
+
+void unblit_sprite_rect(const byte* data, byte x, byte y) {
+ blitter.width = data[0]^4;
+ blitter.height = data[1]^4;
+ blitter.dstart = ((word)(x+XBIAS)<<8)+y; // swapped
+ blitter.solid = 0;
+ blitter.flags = DSTSCREEN|SOLID;
+}
+
+void blit_sprite_strided(const byte* data, byte x, byte y, byte stride) {
+ const byte* src = data+2;
+ byte height = data[1]^4;
+ byte width = data[0]^4;
+ while (height--) {
+ blit_copy(x, y, width, 1, src);
+ y += stride;
+ src += width;
+ }
+}
+
+void unblit_sprite_strided(const byte* data, byte x, byte y, byte stride) {
+ byte height = data[1]^4;
+ byte width = data[0]^4;
+ while (height--) {
+ blit_solid(x, y, width, 1, 0);
+ y += stride;
+ }
+}
+
+void blit_vline(word x1, byte y1, byte h, byte color) {
+ blitter.width = 1^4;
+ blitter.height = h^4;
+ blitter.dstart = ((word)x1<<8)+y1; // swapped
+ blitter.solid = color;
+ blitter.flags = (x1&1) ? DSTSCREEN|SOLID|ODDONLY : DSTSCREEN|SOLID|EVENONLY;
+}
+
+// x: 0-303
+
+void draw_solid(word xx, byte y, byte w, byte h, byte color) {
+ blitter.width = w^4;
+ blitter.height = h^4;
+ blitter.dstart = ((xx<<7)&0xff00)+y; // swapped
+ blitter.solid = color;
+ blitter.flags = (xx&1) ? DSTSCREEN|SOLID|RSHIFT : DSTSCREEN|SOLID;
+}
+
+void draw_vline(word xx, byte y, byte h, byte color) {
+ blitter.width = 1^4;
+ blitter.height = h^4;
+ blitter.dstart = ((xx<<7)&0xff00)+y; // swapped
+ blitter.solid = color;
+ blitter.flags = (xx&1) ? DSTSCREEN|SOLID|ODDONLY : DSTSCREEN|SOLID|EVENONLY;
+}
+
+void draw_copy_solid(word xx, byte y, byte w, byte h, const byte* data, byte solid) {
+ blitter.width = w^4;
+ blitter.height = h^4;
+ blitter.solid = solid;
+ blitter.sstart = data;
+ blitter.dstart = ((xx<<7)&0xff00)+y; // swapped
+ if (solid)
+ blitter.flags = (xx&1) ? DSTSCREEN|FGONLY|SOLID|RSHIFT : DSTSCREEN|FGONLY|SOLID;
+ else
+ blitter.flags = (xx&1) ? DSTSCREEN|RSHIFT : DSTSCREEN;
+}
+
+void draw_pixel(word xx, byte y, byte color) {
+ blitter.width = 1^4;
+ blitter.height = 1^4;
+ blitter.dstart = (((xx>>1)&0xff)<<8)+y; // swapped
+ blitter.solid = color;
+ blitter.flags = (xx&1) ? SOLID|ODDONLY : SOLID|EVENONLY;
+}
+
+
+// BCD
+
+asm word bcd_add(word a, word b) {
+ asm {
+ lda 3,s
+ adda 5,s
+ daa
+ exg b,a
+ lda 2,s
+ adca 4,s
+ daa
+ }
+}
+
diff --git a/presets/williams/williams.h b/presets/williams/williams.h
new file mode 100644
index 00000000..1e82a0df
--- /dev/null
+++ b/presets/williams/williams.h
@@ -0,0 +1,117 @@
+
+#ifndef _WILLIAMS_H
+#define _WILLIAMS_H
+
+typedef unsigned char byte;
+typedef unsigned char bool;
+typedef signed char sbyte;
+typedef unsigned short word;
+
+enum { false=0, true=1 };
+
+byte* palette = 0xc000;
+byte* nvram = 0xcc00;
+
+#define input0 (*(byte*)0xc804)
+#define input1 (*(byte*)0xc806)
+#define input2 (*(byte*)0xc80c)
+#define sound_pia (*(byte*)0xc80c)
+#define rom_select *((byte*)0xc900)
+#define video_counter *((byte*)0xcb00)
+#define watchdog0x39 *((byte*)0xcbff)
+
+#define WATCHDOG (watchdog0x39 = 0x39)
+
+// switch flags
+
+#define UP1 (input0 & 0x1)
+#define DOWN1 (input0 & 0x2)
+#define LEFT1 (input0 & 0x4)
+#define RIGHT1 (input0 & 0x8)
+#define START1 (input0 & 0x10)
+#define START2 (input0 & 0x20)
+#define UP2 (input0 & 0x40)
+#define DOWN2 (input0 & 0x80)
+#define LEFT2 (input1 & 0x1)
+#define RIGHT2 (input1 & 0x2)
+#define AUTOUP (input2 & 0x1)
+#define ADVANCE (input2 & 0x2)
+#define COIN2 (input2 & 0x4)
+#define HIGHSCORERESET (input2 & 0x8)
+#define COIN1 (input2 & 0x10)
+#define COIN3 (input2 & 0x20)
+#define TILTSWITCH (input2 & 0x40)
+#define SOUNDACK (input2 & 0x80)
+
+// blitter flags
+#define SRCSCREEN 0x1
+#define DSTSCREEN 0x2
+#define ESYNC 0x4
+#define FGONLY 0x8
+#define SOLID 0x10
+#define RSHIFT 0x20
+#define EVENONLY 0x40
+#define ODDONLY 0x80
+
+struct {
+ byte flags;
+ byte solid;
+ word sstart;
+ word dstart;
+ byte width;
+ byte height;
+} *_blitter = 0xca00;
+
+#define blitter (*_blitter)
+
+struct {
+ byte mem[152][256];
+} *_vid = 0x0;
+
+#define vidmem (_vid->mem)
+
+#define BLIT_OP(_x,_y,_w,_h,_src,_color,_flags) do {\
+ blitter.width = (_w)^4; \
+ blitter.height = (_h)^4; \
+ blitter.sstart = (word)(_src); \
+ blitter.dstart = ((word)(_x)<<8)+(_y); \
+ blitter.solid = (_color); \
+ blitter.flags = (_flags); \
+ } while (0)
+
+#define BLIT_SOLID(x, y, w, h, color) \
+ BLIT_OP(x, y, w, h, 0, color, DSTSCREEN|SOLID)
+
+
+// x1: 0-151
+// y1: 0-255
+void blit_solid(byte x1, byte y1, byte w, byte h, byte color);
+
+void blit_copy(byte x1, byte y1, byte w, byte h, const byte* data);
+
+void blit_copy_solid(byte x1, byte y1, byte w, byte h, const byte* data, byte solid);
+
+void blit_sprite(const byte* data, byte x, byte y);
+
+void blit_sprite_solid(const byte* data, byte x, byte y, byte color);
+
+void unblit_sprite_rect(const byte* data, byte x, byte y);
+
+void blit_sprite_strided(const byte* data, byte x, byte y, byte stride);
+
+void unblit_sprite_strided(const byte* data, byte x, byte y, byte stride);
+
+// x1: 0-303
+// y1: 0-255
+void draw_pixel(word xx, byte y, byte color);
+
+void draw_solid(word x, byte y, byte w, byte h, byte color);
+
+void draw_vline(word x, byte y, byte h, byte color);
+
+void draw_copy_solid(word x, byte y, byte w, byte h, const byte* data, byte solid);
+
+// BCD
+asm word bcd_add(word a, word b);
+
+#endif
diff --git a/src/common/baseplatform.ts b/src/common/baseplatform.ts
index c3a6754d..7e0aad13 100644
--- a/src/common/baseplatform.ts
+++ b/src/common/baseplatform.ts
@@ -13,6 +13,7 @@ import { SampledAudio } from "./audio";
import { ProbeRecorder } from "./recorder";
import { BaseWASMMachine } from "./wasmplatform";
import { CPU6809 } from "./cpu/6809";
+import { _MOS6502 } from "./cpu/MOS6502";
///
@@ -449,7 +450,7 @@ export abstract class Base6502Platform extends BaseDebugPlatform {
abstract readAddress(addr:number) : number;
newCPU(membus : MemoryBus) {
- var cpu = new jt.M6502();
+ var cpu = new _MOS6502();
cpu.connectBus(membus);
return cpu;
}
diff --git a/src/common/cpu/MOS6502.ts b/src/common/cpu/MOS6502.ts
index 33362d8e..2f516999 100644
--- a/src/common/cpu/MOS6502.ts
+++ b/src/common/cpu/MOS6502.ts
@@ -3,7 +3,7 @@ import { CPU, Bus, ClockBased, SavesState, Interruptable } from "../devices";
// Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file.
-var _MOS6502 = function() {
+export var _MOS6502 = function() {
var self = this;
this.powerOn = function() {
diff --git a/src/common/workertypes.ts b/src/common/workertypes.ts
index fe53426c..198a2292 100644
--- a/src/common/workertypes.ts
+++ b/src/common/workertypes.ts
@@ -7,6 +7,8 @@ export interface SourceLocation {
path?: string; // TODO: make mandatory?
start?: number;
end?: number;
+ segment?:string;
+ func?:string;
}
// actually it's a kind of SourceSnippet .. can have multiple per line
diff --git a/src/ide/ui.ts b/src/ide/ui.ts
index 727b0e13..d2a78d59 100644
--- a/src/ide/ui.ts
+++ b/src/ide/ui.ts
@@ -30,6 +30,7 @@ declare var $ : JQueryStatic; // use browser jquery
interface UIQueryString {
platform? : string;
+ options?: string;
repo? : string;
file? : string;
electron? : string;
@@ -643,7 +644,7 @@ async function getGithubService() {
// load firebase
await loadScript('https://www.gstatic.com/firebasejs/8.8.1/firebase-app.js');
await loadScript('https://www.gstatic.com/firebasejs/8.8.1/firebase-auth.js');
- await loadScript('./config.js');
+ await loadScript('https://8bitworkshop.com/config.js');
// get github API key from cookie
// TODO: move to service?
var ghkey = getCookie('__github_key');
@@ -2216,7 +2217,9 @@ function installGAHooks() {
async function startPlatform() {
if (!PLATFORMS[platform_id]) throw Error("Invalid platform '" + platform_id + "'.");
- platform = new PLATFORMS[platform_id]($("#emuscreen")[0]);
+ let emudiv = $("#emuscreen")[0];
+ let options = decodeQueryString(qs.options || '');
+ platform = new PLATFORMS[platform_id](emudiv, options);
setPlatformUI();
stateRecorder = new StateRecorderImpl(platform);
PRESETS = platform.getPresets ? platform.getPresets() : [];
diff --git a/src/ide/views/editors.ts b/src/ide/views/editors.ts
index 513702c1..eff2e84f 100644
--- a/src/ide/views/editors.ts
+++ b/src/ide/views/editors.ts
@@ -77,6 +77,12 @@ export class SourceEditor implements ProjectView {
return div;
}
+ setVisible(showing: boolean): void {
+ if (showing) {
+ this.editor.focus(); // so that keyboard works when moving between files
+ }
+ }
+
newEditor(parent:HTMLElement, isAsmOverride?:boolean) {
var modedef = MODEDEFS[this.mode] || MODEDEFS.default;
var isAsm = isAsmOverride || modedef.isAsm;
@@ -602,5 +608,5 @@ export class ListingView extends DisassemblerView implements ProjectView {
}
}
}
-}
+}
diff --git a/src/platform/vector.ts b/src/platform/vector.ts
index ba2c5ed0..2df13cc2 100644
--- a/src/platform/vector.ts
+++ b/src/platform/vector.ts
@@ -270,7 +270,7 @@ var AtariColorVectorPlatform = function(mainElement) {
clock++;
if (--nmicount == 0) {
//console.log("NMI", cpu.saveState());
- var n = cpu.setIRQAndWait(); // TODO: only if I flag set
+ var n = cpu.setIRQ(); // TODO: only if I flag set
clock += n;
nmicount = cpuCyclesPerNMI - n;
//console.log(n, clock, nmicount);
diff --git a/src/platform/williams.ts b/src/platform/williams.ts
index f678bc72..54de92ab 100644
--- a/src/platform/williams.ts
+++ b/src/platform/williams.ts
@@ -11,10 +11,11 @@ var WILLIAMS_PRESETS = [
{ id: 'bitmap_rle.c', name: 'RLE Bitmap' },
];
-var WilliamsPlatform = function(mainElement, proto, isDefender) {
+var WilliamsPlatform = function(mainElement, proto, options) {
var self = this;
this.__proto__ = new (proto ? proto : Base6809Platform)();
+ var isDefender = options.isDefender;
var SCREEN_HEIGHT = 304;
var SCREEN_WIDTH = 256;
@@ -98,7 +99,7 @@ var WilliamsPlatform = function(mainElement, proto, isDefender) {
var iowrite_defender = newAddressDecoder([
[0x0, 0xf, 0xf, setPalette],
- [0x3fc, 0x3ff, 0, function(a, v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; }],
+ [0x3fc, 0x3ff, 0, function(a, v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; watchdog_enabled=true; }],
[0x400, 0x5ff, 0x1ff, function(a, v) { nvram.mem[a] = v; }],
[0xc02, 0xc02, 0x1, function(a, v) { if (worker) worker.postMessage({ command: v & 0x3f }); }],
[0xc00, 0xc07, 0x7, function(a, v) { pia6821[a] = v; }],
@@ -145,7 +146,7 @@ var WilliamsPlatform = function(mainElement, proto, isDefender) {
//[0x80c, 0x80f, 0x3, function(a,v) { console.log('iowrite',a+4); }], // TODO: sound
[0x900, 0x9ff, 0, function(a, v) { banksel = v & 0x1; }],
[0xa00, 0xa07, 0x7, setBlitter],
- [0xbff, 0xbff, 0, function(a, v) { if (v == 0x39) watchdog_counter = INITIAL_WATCHDOG; }],
+ [0xbff, 0xbff, 0, function(a, v) { if (v == 0x39) { watchdog_counter = INITIAL_WATCHDOG; watchdog_enabled=true; } }],
[0xc00, 0xfff, 0x3ff, function(a, v) { nvram.mem[a] = v; }],
//[0x0, 0xfff, 0, function(a,v) { console.log('iowrite',hex(a),hex(v)); }],
]);
@@ -302,7 +303,8 @@ var WilliamsPlatform = function(mainElement, proto, isDefender) {
workerchannel = new WorkerSoundChannel(worker);
audio.master.addChannel(workerchannel);
- video = new RasterVideo(mainElement, SCREEN_WIDTH, SCREEN_HEIGHT, { rotate: -90 });
+ let rotate = options.rotate == null ? -90 : parseFloat(options.rotate);
+ video = new RasterVideo(mainElement, SCREEN_WIDTH, SCREEN_HEIGHT, { rotate });
video.create();
$(video.canvas).click(function(e) {
var x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width());
@@ -418,6 +420,7 @@ var WilliamsPlatform = function(mainElement, proto, isDefender) {
this.reset = function() {
cpu.reset();
watchdog_counter = INITIAL_WATCHDOG;
+ watchdog_enabled = false;
banksel = 1;
}
this.scaleCPUFrequency = function(scale) {
@@ -431,8 +434,12 @@ var WilliamsPlatform = function(mainElement, proto, isDefender) {
] } };
}
-var WilliamsZ80Platform = function(mainElement) {
- this.__proto__ = new WilliamsPlatform(mainElement, BaseZ80Platform, false);
+var Williams6809Platform = function(mainElement, options) {
+ this.__proto__ = new WilliamsPlatform(mainElement, null, options);
+}
+
+var WilliamsZ80Platform = function(mainElement, options) {
+ this.__proto__ = new WilliamsPlatform(mainElement, BaseZ80Platform, options);
// Z80 @ 4 MHz
// also scale bitblt clocks
@@ -451,8 +458,8 @@ var WilliamsZ80Platform = function(mainElement) {
}
}
-var WilliamsDefenderPlatform = function(mainElement) {
- this.__proto__ = new WilliamsPlatform(mainElement, null, true);
+var WilliamsDefenderPlatform = function(mainElement, options) {
+ this.__proto__ = new WilliamsPlatform(mainElement, null, {isDefender:true});
this.getMemoryMap = function() { return { main:[
{name:'NVRAM',start:0x400,size:0x200,type:'ram'},
{name:'Video RAM',start:0x0000,size:0xc000,type:'ram'},
@@ -461,7 +468,7 @@ var WilliamsDefenderPlatform = function(mainElement) {
] } };
}
-PLATFORMS['williams'] = WilliamsPlatform;
+PLATFORMS['williams'] = Williams6809Platform;
PLATFORMS['williams-defender'] = WilliamsDefenderPlatform;
PLATFORMS['williams-z80'] = WilliamsZ80Platform;
diff --git a/src/worker/lib/vector-ataricolor/crt0.o b/src/worker/lib/vector-ataricolor/crt0.o
index 26a68713..a904d800 100644
Binary files a/src/worker/lib/vector-ataricolor/crt0.o and b/src/worker/lib/vector-ataricolor/crt0.o differ
diff --git a/src/worker/lib/vector-ataricolor/crt0.s b/src/worker/lib/vector-ataricolor/crt0.s
index 9dc585df..6ebaa318 100644
--- a/src/worker/lib/vector-ataricolor/crt0.s
+++ b/src/worker/lib/vector-ataricolor/crt0.s
@@ -8,7 +8,6 @@
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import zerobss, callmain
.import initlib, donelib, copydata
- .import exit
.import __PRGRAM_START__, __PRGRAM_SIZE__ ; Linker generated
; .import __STACKSIZE__ ; Linker generated
@@ -30,7 +29,7 @@ start:
_exit: pha
jsr donelib
pla
- jmp exit
+ jmp start
nmi:
inc $0
diff --git a/src/worker/lib/williams/assert.h b/src/worker/lib/williams/assert.h
new file mode 100644
index 00000000..45d9fba0
--- /dev/null
+++ b/src/worker/lib/williams/assert.h
@@ -0,0 +1,20 @@
+/* assert.h - Assert macro for CMOC
+
+ By Pierre Sarrazin .
+ This file is in the public domain.
+*/
+
+#ifndef _ASSERT_H
+#define _ASSERT_H
+
+#include "cmoc.h"
+
+#ifdef NDEBUG
+#define assert(cond)
+#else
+#define assert(cond) do { if (!(cond)) { \
+ printf("***ASSERT FAILED: %s:%u: %s\n", __FILE__, __LINE__, #cond); \
+ for (;;); } } while (0)
+#endif
+
+#endif /* _ASSERT_H */
diff --git a/src/worker/lib/williams/cmoc.h b/src/worker/lib/williams/cmoc.h
new file mode 100644
index 00000000..090f69ef
--- /dev/null
+++ b/src/worker/lib/williams/cmoc.h
@@ -0,0 +1,345 @@
+// cmoc.h - CMOC's standard library functions.
+//
+// By Pierre Sarrazin .
+// This file is in the public domain.
+//
+// Functions not documented here should be assumed to behave as in C.
+
+#ifndef _H_CMOC
+#define _H_CMOC
+
+#ifndef __GNUC__
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+
+#ifndef _CMOC_CONST_
+#define _CMOC_CONST_ const
+#endif
+
+
+// Gives the offset in bytes of the specified 'member' in the struct
+// or union named 'Type'.
+//
+#define offsetof(Type, member) ((unsigned) &((Type *) 0)->member)
+
+typedef unsigned size_t;
+
+
+#ifndef VECTREX
+// Supports %u, %d, %x, %X, %p, %s, %c and %%. Specifying a field width is
+// allowed, but a left justification is only supported for strings, i.e.,
+// %-15s will work, but %-6u will not. Zero padding for a number is supported
+// (e.g., %04x).
+//
+int printf(_CMOC_CONST_ char *format, ...);
+#endif
+
+
+// Writes to 'dest'. Not thread-safe. Does not check for buffer overflow.
+int sprintf(char *dest, _CMOC_CONST_ char *format, ...);
+
+
+#ifndef VECTREX
+// Writes the first 'n' characters designated by 's', regardless of any
+// null characters encountered among them.
+//
+void putstr(_CMOC_CONST_ char *s, size_t n);
+
+void putchar(int c);
+#endif
+
+int strcmp(_CMOC_CONST_ char *s1, _CMOC_CONST_ char *s2);
+int stricmp(_CMOC_CONST_ char *s1, _CMOC_CONST_ char *s2);
+int memcmp(_CMOC_CONST_ void *s1, _CMOC_CONST_ void *s2, size_t n);
+int memicmp(_CMOC_CONST_ void *s1, _CMOC_CONST_ void *s2, size_t n);
+void *memcpy(void *dest, _CMOC_CONST_ void *src, size_t n);
+void *memset(void *s, int c, size_t n);
+size_t strlen(_CMOC_CONST_ char *s);
+char *strcpy(char *dest, _CMOC_CONST_ char *src);
+char *strcat(char *dest, _CMOC_CONST_ char *src);
+char *strncpy(char *dest, _CMOC_CONST_ char *src, size_t n);
+char *strchr(_CMOC_CONST_ char *s, int c);
+char *strstr(const char *haystack, const char *needle);
+char *strlwr(char *s);
+char *strupr(char *s);
+
+
+// Converts an ASCII unsigned decimal string into an unsigned word.
+//
+unsigned atoui(_CMOC_CONST_ char *s);
+
+
+// Converts an ASCII signed decimal string into a signed word.
+//
+int atoi(_CMOC_CONST_ char *s);
+
+
+// Converts an integer to a NUL-terminated ASCII signed decimal string.
+// Returns 'str'.
+// The caller must be careful to pass an array of sufficient size,
+// including room for the terminating '\0'.
+//
+char *itoa10(int value, char *str);
+
+
+// Converts an integer to a NUL-terminated ASCII signed decimal string.
+// N.B.: 'base' must be 10. No other base is supported by this implementation.
+// Returns 'str'.
+// The caller must be careful to pass an array of sufficient size,
+// including room for the terminating '\0'.
+//
+#define itoa(value, str, base) (itoa10((value), (str)))
+
+
+// Like itoa10(), but 'value' can be in the range 32768..65535.
+//
+char *utoa10(unsigned value, char *str);
+
+
+// Like itoa(), but 'value' can be in the range 32768..65535.
+// N.B.: 'base' must be 10. No other base is supported by this implementation.
+//
+#define utoa(value, str, base) (utoa10((value), (str)))
+
+
+// Like itoa10(), but 'value' can be 32 bits.
+//
+char *ltoa10(long value, char *str);
+
+
+// Like itoa(), but 'value' can be 32 bits.
+// N.B.: 'base' must be 10. No other base is supported by this implementation.
+//
+#define ltoa(value, str, base) (ltoa10((value), (str)))
+
+
+// Like utoa10(), but 'value' can be 32 bits.
+//
+char *ultoa10(unsigned long value, char *str);
+
+
+// Like utoa(), but 'value' can be 32 bits.
+// N.B.: 'base' must be 10. No other base is supported by this implementation.
+//
+#define ultoa(value, str, base) (ultoa10((value), (str)))
+
+
+// Double-word to ASCII.
+// Converts the unsigned 32-bit integer formed by hi * 65536 + lo into
+// an ASCII decimal representation that gets written to 'out'.
+// 'out' must point to at least 11 bytes. The string written there will
+// be terminated by a null character.
+// Returns the address of the first non-'0' character in the 11-byte
+// buffer, or to "0" if hi and lo are both zero.
+// Example: char s[11]; char *p = dwtoa(s, 1, 2);
+// s will get the string "
+// NOTE: This operation can also be done with the 'long' type and by
+// calling sprintf() with the "%lu" or "%ld" placeholders.
+//
+char *dwtoa(char *out, unsigned hi, unsigned lo);
+
+
+// Returns the integer part of the square root of n.
+//
+unsigned char sqrt16(unsigned n);
+
+
+// Returns the quotient and remainder of a 16-bit unsigned division
+// in a single operation.
+//
+void divmod16(unsigned dividend, unsigned divisor,
+ unsigned *quotient, unsigned *remainder);
+
+
+// Returns the quotient and remainder of an 8-bit unsigned division
+// in a single operation.
+//
+void divmod8(unsigned char dividend, unsigned char divisor,
+ unsigned char *quotient, unsigned char *remainder);
+
+
+// Divides an unsigned 32-bit integer by an unsigned 8-bit integer.
+// The two words designated by 'dividendInQuotientOut' are the input dividend.
+// The 32-bit quotient is left in those two words.
+//
+void divdwb(unsigned dividendInQuotientOut[2], unsigned char divisor);
+
+
+// Previous name of divdwb().
+//
+#define div328 divdwb
+
+
+// Divides an unsigned 32-bit integer by an unsigned 16-bit integer.
+// The two words designated by 'dividendInQuotientOut' are the input dividend.
+// The 32-bit quotient is left in those two words.
+//
+void divdww(unsigned dividendInQuotientOut[2], unsigned divisor);
+
+
+// Multiply a word by a byte.
+// Stores the high word of the product in *hi and returns the low word.
+//
+unsigned mulwb(unsigned char *hi, unsigned wordFactor, unsigned char byteFactor);
+
+
+// Similar to mulwb().
+unsigned mulww(unsigned *hi, unsigned factor0, unsigned factor1);
+
+
+// Stores 0 in twoWords[0], twoWords[1].
+//
+void zerodw(unsigned *twoWords);
+
+
+// Adds the 16-bit integer 'term' to the 32-bit integer designated by
+// twoWords[0] and twoWords[1].
+//
+void adddww(unsigned *twoWords, unsigned term);
+
+
+// Subtracts the 16-bit integer 'term' from the 32-bit integer designated by
+// twoWords[0] and twoWords[1].
+//
+void subdww(unsigned *twoWords, unsigned term);
+
+
+// Returns 0 if the 32-bit unsigned word composed of left[0] and left[1]
+// (where left[0] is the high word) is equal to 'right';
+// returns +1 if left > right; -1 if left < right.
+//
+char cmpdww(unsigned left[2], unsigned right);
+
+
+#ifdef _COCO_BASIC_
+
+// Converts an ASCII decimal floating point number to a float.
+// The string is allowed to contain a suffix (e.g., "1.2E6XYZ");
+// endptr: Receives the address where the parsing stopped.
+// Caution: Passing a string whose value does not fit in a float
+// may have undefined behavior.
+// An 'E' used in exponential notation must be in upper-case.
+//
+float strtof(_CMOC_CONST_ char *nptr, char **endptr);
+
+
+// Like strtof(), but does not return the end pointer.
+//
+float atoff(_CMOC_CONST_ char *nptr);
+
+
+// Writes an ASCII decimal representation of 'f' in the buffer
+// at 'out' which must contain at least 38 bytes.
+// Returns 'out' upon success, or null upon failure.
+//
+char *ftoa(char out[38], float f);
+
+#endif /* _COCO_BASIC_ */
+
+
+// CAUTION: base is ignored, only base 10 is supported.
+//
+unsigned long strtoul(_CMOC_CONST_ char *nptr, char **endptr, int base);
+
+unsigned long atoul(_CMOC_CONST_ char *nptr);
+
+// CAUTION: base is ignored, only base 10 is supported.
+//
+long strtol(_CMOC_CONST_ char *nptr, char **endptr, int base);
+
+long atol(_CMOC_CONST_ char *nptr);
+
+int tolower(int c);
+int toupper(int c);
+void exit(int status);
+
+#define RAND_MAX 0x7FFF
+void srand(unsigned seed);
+int rand();
+
+// See the CMOC manual.
+void *sbrk(size_t increment);
+size_t sbrkmax();
+void set_null_ptr_handler(void (*newHandler)(void *));
+void set_stack_overflow_handler(void (*newHandler)(void *, void *));
+
+
+// Function pointer type used by setConsoleOutHook().
+//
+typedef void (*ConsoleOutHook)();
+
+
+// Redirect printf() et al. to the function at 'routine', which will
+// receive each character to be printed in register A.
+//
+// That routine MUST preserve registers B, X, Y and U.
+//
+// If this function is never called, printf() et al. write to the
+// system's standard character output routine.
+//
+// Returns the original output routine address.
+// To uninstall the new routine, call this function again with
+// the original routine address.
+//
+ConsoleOutHook setConsoleOutHook(ConsoleOutHook routine);
+
+
+#ifndef VECTREX
+
+// Blocks the execution for the specified time in 60ths of a second.
+//
+void delay(size_t sixtiethsOfASecond);
+
+
+// Reads a line from standard input, converts an expected 16-bit decimal
+// number and returns it. Not thread-safe.
+//
+unsigned readword();
+
+
+// Reads a line from standard input and returns it.
+// Not thread-safe.
+// Returns a null pointer if the operation failed (e.g., end of file
+// encountered).
+//
+char *readline();
+
+#endif /* ndef VECTREX */
+
+
+// Sorts an array that starts at 'base', that has 'nmemb' elements, whose
+// elements are 'size' bytes each.
+// compar: Pointer to a function that receives pointers to two array elements
+// and that returns -1, 0 or +1 depending on whether the first element
+// comes before, is equal to, or comes after the second element.
+// This function is recursive and will thus use stack space.
+//
+void qsort(void *base, size_t nmemb, size_t size, int (*compar)(_CMOC_CONST_ void *, _CMOC_CONST_ void *));
+
+
+// Searches for the value pointed to by 'key' in the array starting at 'base',
+// that has 'nmemb' elements, whose elements are 'size' bytes each.
+// compar: Pointer to a function that receives pointers to the targeted key and
+// to an array element. It must return -1, 0 or +1 depending on whether
+// the targeted key comes before, is equal to, or comes after the second element.
+// Returns a pointer to the element of the array that matches the targeted key,
+// or NULL if none is found.
+// The time taken by this function is proportional to the logarithm of the array size.
+// This function is recursive and will thus use stack space.
+//
+void *bsearch(const void *key, const void *base, size_t nmemb, size_t size,
+ int (*compar)(_CMOC_CONST_ void *key, _CMOC_CONST_ void *element));
+
+
+#else
+
+#include
+#include
+#include
+
+#endif /* __GNUC__ */
+
+#endif /* _H_CMOC */
diff --git a/src/worker/lib/williams/stdarg.h b/src/worker/lib/williams/stdarg.h
new file mode 100644
index 00000000..e3d0b345
--- /dev/null
+++ b/src/worker/lib/williams/stdarg.h
@@ -0,0 +1,22 @@
+/* stdarg.h - Support for variable argument functions
+
+ By Pierre Sarrazin .
+ This file is in the public domain.
+*/
+
+#ifndef _stdarg_h_
+#define _stdarg_h_
+
+
+typedef char *va_list;
+
+
+char *__va_arg(va_list *app, unsigned int sizeInBytes);
+
+
+#define va_start(ap, lastFixed) do { (ap) = (char *) &(lastFixed) + sizeof(lastFixed); } while (0)
+#define va_arg(ap, type) (* (type *) __va_arg(&(ap), sizeof(type)))
+#define va_end(ap) do {} while (0)
+
+
+#endif /* _stdarg_h_ */
diff --git a/src/worker/lib/williams/stdlib.h b/src/worker/lib/williams/stdlib.h
new file mode 100644
index 00000000..3da92a0e
--- /dev/null
+++ b/src/worker/lib/williams/stdlib.h
@@ -0,0 +1,13 @@
+#ifndef __vectrex_stdlib_h__
+#define __vectrex_stdlib_h__
+
+/**
+ * Most stdlib functions are supported on the Vectrex, except those that imply having a keyboard and console:
+ * printf, putsr, putchar, readword, readline.
+ * Also delay is not implemented as it does not seem to make much sense to have a delay function on the Vectrex.
+ */
+
+//#include "vectrex.h"
+#include "cmoc.h"
+
+#endif // __vectrex_stdlib_h__
diff --git a/src/worker/tools/m6809.ts b/src/worker/tools/m6809.ts
index 538fa8c4..760872eb 100644
--- a/src/worker/tools/m6809.ts
+++ b/src/worker/tools/m6809.ts
@@ -41,7 +41,6 @@ export function assembleXASM6809(step: BuildStep): BuildStepResult {
return { errors: errors };
var aout = FS.readFile(binpath, { encoding: 'binary' });
if (aout.length == 0) {
- console.log(alst);
errors.push({ line: 0, msg: "Empty output file" });
return { errors: errors };
}
@@ -116,6 +115,8 @@ export function compileCMOC(step: BuildStep): BuildStepResult {
if (errors.length)
return { errors: errors };
var asmout = FS.readFile(destpath, { encoding: 'utf8' });
+ if (step.params.set_stack_end)
+ asmout = asmout.replace('stack space in bytes', `\n lds #${step.params.set_stack_end}\n`)
putWorkFile(destpath, asmout);
}
return {
@@ -219,7 +220,11 @@ export function linkLWLINK(step: BuildStep): BuildStepResult {
if (toks[0] == 'Symbol:') {
let ident = toks[1];
let ofs = parseInt(toks[4], 16);
- if (ident && ofs >= 0 && !ident.startsWith("l_") && !/^L\d+$/.test(ident)) {
+ if (ident && ofs >= 0
+ && !ident.startsWith("l_")
+ //&& !/^L\d+$/.test(ident)
+ && !ident.startsWith('funcsize_')
+ && !ident.startsWith('funcend_')) {
symbolmap[ident] = ofs;
}
}
@@ -231,15 +236,25 @@ export function linkLWLINK(step: BuildStep): BuildStepResult {
}
}
// build listings
+ const re_segment = /\s*SECTION\s+(\w+)/i;
+ const re_function = /\s*([0-9a-f]+).+?(\w+)\s+EQU\s+[*]/i;
var listings: CodeListingMap = {};
for (var fn of step.files) {
if (fn.endsWith('.lst')) {
// TODO
var lstout = FS.readFile(fn, { encoding: 'utf8' });
- var asmlines = parseListing(lstout, /^([0-9A-F]+)\s+([0-9A-F]+)\s+[(]\s*(.+?)[)]:(\d+) (.*)/i, 4, 1, 2, 3);
+ var asmlines = parseListing(lstout, /^([0-9A-F]+)\s+([0-9A-F]+)\s+[(]\s*(.+?)[)]:(\d+) (.*)/i, 4, 1, 2, 3, re_function, re_segment);
+ for (let l of asmlines) {
+ l.offset += symbolmap[l.func] || 0;
+ }
// * Line //threed.c:117: init of variable e
- var srclines = parseSourceLines(lstout, /Line .+?:(\d+)/i, /^([0-9A-F]{4})/i);
+ var srclines = parseSourceLines(lstout, /Line .+?:(\d+)/i, /^([0-9A-F]{4})/i, re_function, re_segment);
+ for (let l of srclines) {
+ l.offset += symbolmap[l.func] || 0;
+ }
putWorkFile(fn, lstout);
+ // strip out left margin
+ lstout = lstout.split('\n').map(l => l.substring(0,15) + l.substring(56)).join('\n')
// TODO: you have to get rid of all source lines to get asm listing
listings[fn] = {
asmlines: srclines.length ? asmlines : null,
diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts
index 45a6a4fb..04ee1955 100644
--- a/src/worker/workermain.ts
+++ b/src/worker/workermain.ts
@@ -127,9 +127,11 @@ var PLATFORM_PARAMS = {
data_start: 0x9800,
data_size: 0x2800,
stack_end: 0xc000,
+ set_stack_end: 0xc000,
extra_link_files: ['williams.scr', 'libcmoc-crt-vec.a', 'libcmoc-std-vec.a'],
extra_link_args: ['-swilliams.scr', '-lcmoc-crt-vec', '-lcmoc-std-vec'],
- extra_compile_files: ['assert.h','cmoc.h','stdarg.h','vectrex.h','stdlib.h','bios.h'],
+ extra_compile_files: ['assert.h','cmoc.h','stdarg.h','stdlib.h'],
+ //extra_compile_args: ['--vectrex'],
},
'williams-defender': {
arch: '6809',
@@ -884,10 +886,20 @@ export const re_crlf = /\r?\n/;
// 1 %line 16+1 hello.asm
export const re_lineoffset = /\s*(\d+)\s+[%]line\s+(\d+)\+(\d+)\s+(.+)/;
-export function parseListing(code:string, lineMatch, iline:number, ioffset:number, iinsns:number, icycles?:number) : SourceLine[] {
+export function parseListing(code:string,
+ lineMatch, iline:number, ioffset:number, iinsns:number, icycles?:number,
+ funcMatch?, segMatch?) : SourceLine[] {
var lines : SourceLine[] = [];
var lineofs = 0;
+ var segment = '';
+ var func = '';
+ var funcbase = 0;
code.split(re_crlf).forEach((line, lineindex) => {
+ let segm = segMatch && segMatch.exec(line);
+ if (segm) { segment = segm[1]; }
+ let funcm = funcMatch && funcMatch.exec(line);
+ if (funcm) { funcbase = parseInt(funcm[1],16); func = funcm[2]; }
+
var linem = lineMatch.exec(line);
if (linem && linem[1]) {
var linenum = iline < 0 ? lineindex : parseInt(linem[iline]);
@@ -897,11 +909,13 @@ export function parseListing(code:string, lineMatch, iline:number, ioffset:numbe
var iscode = cycles > 0;
if (insns) {
lines.push({
- line:linenum + lineofs,
- offset:offset,
- insns:insns,
- cycles:cycles,
- iscode:iscode
+ line: linenum + lineofs,
+ offset: offset - funcbase,
+ insns,
+ cycles,
+ iscode,
+ segment,
+ func
});
}
} else {
@@ -915,10 +929,18 @@ export function parseListing(code:string, lineMatch, iline:number, ioffset:numbe
return lines;
}
-export function parseSourceLines(code:string, lineMatch, offsetMatch) {
+export function parseSourceLines(code:string, lineMatch, offsetMatch, funcMatch?, segMatch?) {
var lines = [];
var lastlinenum = 0;
+ var segment = '';
+ var func = '';
+ var funcbase = 0;
for (var line of code.split(re_crlf)) {
+ let segm = segMatch && segMatch.exec(line);
+ if (segm) { segment = segm[1]; }
+ let funcm = funcMatch && funcMatch.exec(line);
+ if (funcm) { funcbase = parseInt(funcm[1],16); func = funcm[2]; }
+
var linem = lineMatch.exec(line);
if (linem && linem[1]) {
lastlinenum = parseInt(linem[1]);
@@ -927,8 +949,10 @@ export function parseSourceLines(code:string, lineMatch, offsetMatch) {
if (linem && linem[1]) {
var offset = parseInt(linem[1], 16);
lines.push({
- line:lastlinenum,
- offset:offset,
+ line: lastlinenum,
+ offset: offset - funcbase,
+ segment,
+ func
});
lastlinenum = 0;
}
diff --git a/test/cli/testworker.js b/test/cli/testworker.js
index 493183fa..43fd983c 100644
--- a/test/cli/testworker.js
+++ b/test/cli/testworker.js
@@ -262,5 +262,10 @@ describe('Worker', function() {
it('should compile CC65 flags', function(done) {
compile('cc65', '#define CC65_FLAGS -Or,-g,-j\nint main() {\nint x=1;\nreturn x+2;\n}', 'apple2', done, 416, 3);
});
+ /*
+ it('should compile CMOC', function(done) {
+ compile('cmoc', 'int foo=0; // comment\n#if defined(__8BITWORKSHOP__) && defined(__MAIN__)\nint main(int argc) {\nint x=1;\nint y=2+argc;\nreturn x+y+argc;\n}\n#endif\n', 'williams', done, 8192, 3, 0, {filename:'test.c'});
+ });
+ */
});