@8bitscript/pet 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/input.8bs ADDED
@@ -0,0 +1,135 @@
1
+ // @8bitscript/pet/input — the PET behind @8bitscript/input.
2
+ //
3
+ // Named by "8bitscript".exports["./input"] in this package's package.json,
4
+ // and by "8bitscript".entry.pet in @8bitscript/input's, so a portable
5
+ // program writes
6
+ //
7
+ // import { input } from "@8bitscript/input";
8
+ //
9
+ // and gets this file on a PET. The matrix itself is ./keyboard.8bs with
10
+ // ./keys.8bs, which stay available to a program that wants a key this file
11
+ // does not map.
12
+ //
13
+ // ---- a keyboard and nothing else -----------------------------------------
14
+ //
15
+ // The PET is the machine with the least to offer this surface, and saying
16
+ // so plainly is the job. There are **no control ports** — no joystick, no
17
+ // paddles, no mouse, nothing to plug in — because the machine predates the
18
+ // idea. `pointer()` is a constant false, and so every `if
19
+ // (input.pointer())` in a component folds away to nothing here.
20
+ //
21
+ // What there is is a keyboard, and it has the two cursor keys the
22
+ // Commodore machines all have rather than four: `CURSOR_RIGHT` and
23
+ // `CURSOR_DOWN`, each reversed by SHIFT. So left is SHIFT plus the right
24
+ // key. That is what the machine has, and this file reports it rather than
25
+ // pretending otherwise.
26
+ //
27
+ // - **left / right / up / down** — the two cursor keys, with SHIFT.
28
+ // - **confirm** — RETURN.
29
+ // - **cancel** — RUN/STOP.
30
+ //
31
+ // ---- edges, not levels ---------------------------------------------------
32
+ //
33
+ // Every answer is **edge-triggered**: true on the one frame the press
34
+ // begins, false while it is held. `poll()` must be called exactly once a
35
+ // frame, right after waitFrame().
36
+ //
37
+ // One thing worth knowing about this keyboard specifically: the PET's
38
+ // matrix is read a row at a time and has the same ghosting every
39
+ // undiodedmatrix does — three keys down can read as four. Two keys are
40
+ // always safe, and SHIFT plus a cursor key is two.
41
+ import { keyboard } from "./keyboard.8bs";
42
+ import { Key } from "./keys.8bs";
43
+
44
+ namespace Edge {
45
+ const LEFT: utinyint = 1;
46
+ const RIGHT: utinyint = 2;
47
+ const UP: utinyint = 4;
48
+ const DOWN: utinyint = 8;
49
+ const CONFIRM: utinyint = 16;
50
+ const CANCEL: utinyint = 32;
51
+ }
52
+
53
+ let held: utinyint = 0;
54
+ let before: utinyint = 0;
55
+ let began: utinyint = 0;
56
+
57
+ export namespace input {
58
+
59
+ // Nothing to set up: there is no pointer to give a ceiling to and the
60
+ // matrix needs no configuration. Here so a program written for nine
61
+ // machines calls the same thing on all of them.
62
+ function begin(): void {
63
+ }
64
+
65
+ // Snapshot the matrix and work out what began this frame. Once a
66
+ // frame, right after waitFrame().
67
+ function poll(): void {
68
+ keyboard.scan();
69
+
70
+ before = held;
71
+ held = 0;
72
+
73
+ let shifted: bool = keyboard.pressed(Key.SHIFT_LEFT) || keyboard.pressed(Key.SHIFT_RIGHT);
74
+ if (keyboard.pressed(Key.CURSOR_RIGHT)) {
75
+ if (shifted) {
76
+ held = held | Edge.LEFT;
77
+ } else {
78
+ held = held | Edge.RIGHT;
79
+ }
80
+ }
81
+ if (keyboard.pressed(Key.CURSOR_DOWN)) {
82
+ if (shifted) {
83
+ held = held | Edge.UP;
84
+ } else {
85
+ held = held | Edge.DOWN;
86
+ }
87
+ }
88
+ if (keyboard.pressed(Key.RETURN)) {
89
+ held = held | Edge.CONFIRM;
90
+ }
91
+ if (keyboard.pressed(Key.STOP)) {
92
+ held = held | Edge.CANCEL;
93
+ }
94
+
95
+ began = held & (before ^ 0xFF);
96
+ }
97
+
98
+ function left(): bool {
99
+ return (began & Edge.LEFT) != 0;
100
+ }
101
+
102
+ function right(): bool {
103
+ return (began & Edge.RIGHT) != 0;
104
+ }
105
+
106
+ function up(): bool {
107
+ return (began & Edge.UP) != 0;
108
+ }
109
+
110
+ function down(): bool {
111
+ return (began & Edge.DOWN) != 0;
112
+ }
113
+
114
+ function confirm(): bool {
115
+ return (began & Edge.CONFIRM) != 0;
116
+ }
117
+
118
+ function cancel(): bool {
119
+ return (began & Edge.CANCEL) != 0;
120
+ }
121
+
122
+ // No control ports on this machine, so no pointer — a constant, not a
123
+ // measurement.
124
+ function pointer(): bool {
125
+ return false;
126
+ }
127
+
128
+ function pointerCell(): usmallint {
129
+ return 0;
130
+ }
131
+
132
+ function pointerButton(): bool {
133
+ return false;
134
+ }
135
+ }
@@ -0,0 +1,72 @@
1
+ // @8bitscript/pet/keyboard — the PET's keyboard matrix, one snapshot a frame.
2
+ //
3
+ // Named by "8bitscript".exports["./keyboard"] in this package's package.json:
4
+ //
5
+ // import { keyboard } from "@8bitscript/pet/keyboard";
6
+ // import { Key } from "@8bitscript/pet/keys";
7
+ //
8
+ // This is hardware-level, PET-only surface — the layer the portable input
9
+ // capability is built on: `@8bitscript/pet/input` reads this file and
10
+ // @8bitscript/input resolves to that, the way ./text.8bs is the layer
11
+ // under @8bitscript/text. Importing it makes a program PET-specific.
12
+ //
13
+ // ---- how the matrix works -----------------------------------------------
14
+ //
15
+ // Ten rows by eight columns, no diodes. Writing a row number 0-9 to PIA1
16
+ // port A ($E810) selects that row; PIA1 port B ($E812) then reads its eight
17
+ // keys, a 0 bit where a key is down. A program that calls waitFrame()
18
+ // anywhere — one scanning once a frame does — runs with interrupts off from
19
+ // start-up (FRAME_SYNC.pet's `sei`, in the frame prologue the backend
20
+ // emits for it), so the KERNAL's own scan is not running against this one.
21
+ // A program with no waitFrame() at all still has the KERNAL IRQ alive and
22
+ // selecting rows of its own sixty times a second; scan() there would read
23
+ // a row it did not select. This package keeps no key buffer and decodes no
24
+ // PETSCII; it answers "is this key down now", which is what a game loop asks.
25
+ //
26
+ // Reading $E812 has a side effect: it clears the retrace flag the frame
27
+ // runtime waits on (see `pia1PortB` in ./index.8bs). So the matrix is read
28
+ // exactly once a frame, all ten rows into `state`, by `keyboard.scan()`
29
+ // — called right after waitFrame() returns, when the edge was just
30
+ // consumed and the next is a whole frame away — and every question after
31
+ // that reads the snapshot, never the port. Ten writes and ten reads, about
32
+ // 200 cycles of a 20000-cycle frame.
33
+ //
34
+ // Ghosting: three keys down can read as four (any three corners of a
35
+ // rectangle in the matrix light the fourth). Two keys are always safe.
36
+ import { pia1PortA, pia1PortB } from "./index.8bs";
37
+
38
+ // The last scan, one byte per row, a 1 bit where a key is down (the port's
39
+ // active-low columns inverted once, here, so nothing else has to think
40
+ // about it). All zero until the first scan.
41
+ let state: array<utinyint, 10>;
42
+
43
+ // Column masks, indexed rather than shifted: `1 << n` with a variable n is
44
+ // a loop on the 6502, a table lookup is one indexed load.
45
+ const COLUMN_BIT: array<utinyint, 8> = [1, 2, 4, 8, 16, 32, 64, 128];
46
+
47
+ export namespace keyboard {
48
+ const ROWS: utinyint = 10;
49
+ const COLUMNS: utinyint = 8;
50
+
51
+ // Read all ten rows into the snapshot. Once a frame, right after
52
+ // waitFrame().
53
+ function scan(): void {
54
+ for (let row: utinyint = 0; row < 10; row++) {
55
+ pia1PortA = row;
56
+ state[row] = pia1PortB ^ 0xFF;
57
+ }
58
+ }
59
+
60
+ // Is this key down in the last scan? `key` is a `Key.*` value from
61
+ // @8bitscript/pet/keys — `row * 8 + column` in the profile's matrix.
62
+ function pressed(key: utinyint): bool {
63
+ return (state[key >> 3] & COLUMN_BIT[key & 7]) != 0;
64
+ }
65
+
66
+ // The last scan's eight columns of one row, a 1 bit per key down:
67
+ // for code that wants a whole row at once (a matrix ghosting check,
68
+ // an "any key" test over all ten).
69
+ function row(index: utinyint): utinyint {
70
+ return state[index];
71
+ }
72
+ }
package/src/keys.8bs ADDED
@@ -0,0 +1,120 @@
1
+ // @8bitscript/pet/keys — the keyboard matrix, key by key: graphics keyboard.
2
+ //
3
+ // Named by "8bitscript".exports["./keys"] in this package's package.json, for
4
+ //
5
+ // import { keyboard } from "@8bitscript/pet/keyboard";
6
+ // import { Key } from "@8bitscript/pet/keys";
7
+ //
8
+ // if (keyboard.pressed(Key.SPACE)) { ... }
9
+ //
10
+ // Each value is `row * 8 + column` in PIA1's matrix (see ./keyboard.8bs),
11
+ // so a build for a profile reads that profile's table: this file is the
12
+ // **graphics** keyboard of the 2001, 3xxx and 4xxx (calculator-style
13
+ // keypad digits, the symbol row `! " # $ % & ' ( ) ←` above the letters,
14
+ // every character unshifted), and `keys.pet.8032.8bs` beside it is the
15
+ // **business** keyboard the 8032 has (typewriter layout: digits on the
16
+ // top row, a numeric keypad, TAB, ESC, RPT). The two matrices wire the
17
+ // same letters to different rows, which is exactly why the table is the
18
+ // profile's and a program names keys, never numbers.
19
+ //
20
+ // A key that exists on both keyboards has the same name in both files —
21
+ // letters, `DIGIT_n`, SPACE, RETURN, STOP, HOME, DELETE, the cursor keys,
22
+ // both shifts, REVERSE, the arrows and the shared punctuation — so a
23
+ // program that sticks to those builds for every PET. Names that exist
24
+ // only here (the symbol row: EXCLAMATION, HASH, ... EQUALS) or only on
25
+ // the business keyboard (KEYPAD_n, TAB, ESCAPE, REPEAT) are that
26
+ // keyboard's alone, and an 8032 build of a program using one stops at
27
+ // the import with "no member" — which is the right time to find out.
28
+ //
29
+ // Source: the matrix every PET reference gives for the graphics keyboard,
30
+ // checked here key for key against VICE's own positional map for it,
31
+ // /opt/homebrew/share/vice/PET/gtk3_grus_pos.vkm (each line there is
32
+ // `keysym row column shiftflag`); packages/compiler/test/pet-keys.test.mjs
33
+ // repeats that check when the file is present. Row 0 is `$E810 = 0`,
34
+ // column 0 is PB0. A row's missing columns (1,5 and so on) have no key.
35
+
36
+ export namespace Key {
37
+ // row 0
38
+ const EXCLAMATION: utinyint = 0;
39
+ const HASH: utinyint = 1;
40
+ const PERCENT: utinyint = 2;
41
+ const AMPERSAND: utinyint = 3;
42
+ const PAREN_LEFT: utinyint = 4;
43
+ const LEFT_ARROW: utinyint = 5; // the back-arrow key, top row right
44
+ const HOME: utinyint = 6; // CLR/HOME
45
+ const CURSOR_RIGHT: utinyint = 7; // shifted: cursor left
46
+ // row 1
47
+ const QUOTE: utinyint = 8;
48
+ const DOLLAR: utinyint = 9;
49
+ const APOSTROPHE: utinyint = 10;
50
+ const PAREN_RIGHT: utinyint = 11;
51
+ const BACKSLASH: utinyint = 12;
52
+ const CURSOR_DOWN: utinyint = 14; // shifted: cursor up
53
+ const DELETE: utinyint = 15; // INST/DEL
54
+ // row 2
55
+ const Q: utinyint = 16;
56
+ const E: utinyint = 17;
57
+ const T: utinyint = 18;
58
+ const U: utinyint = 19;
59
+ const O: utinyint = 20;
60
+ const UP_ARROW: utinyint = 21;
61
+ const DIGIT_7: utinyint = 22; // keypad
62
+ const DIGIT_9: utinyint = 23;
63
+ // row 3
64
+ const W: utinyint = 24;
65
+ const R: utinyint = 25;
66
+ const Y: utinyint = 26;
67
+ const I: utinyint = 27;
68
+ const P: utinyint = 28;
69
+ const DIGIT_8: utinyint = 30;
70
+ const SLASH: utinyint = 31;
71
+ // row 4
72
+ const A: utinyint = 32;
73
+ const D: utinyint = 33;
74
+ const G: utinyint = 34;
75
+ const J: utinyint = 35;
76
+ const L: utinyint = 36;
77
+ const DIGIT_4: utinyint = 38;
78
+ const DIGIT_6: utinyint = 39;
79
+ // row 5
80
+ const S: utinyint = 40;
81
+ const F: utinyint = 41;
82
+ const H: utinyint = 42;
83
+ const K: utinyint = 43;
84
+ const COLON: utinyint = 44;
85
+ const DIGIT_5: utinyint = 46;
86
+ const ASTERISK: utinyint = 47;
87
+ // row 6
88
+ const Z: utinyint = 48;
89
+ const C: utinyint = 49;
90
+ const B: utinyint = 50;
91
+ const M: utinyint = 51;
92
+ const SEMICOLON: utinyint = 52;
93
+ const RETURN: utinyint = 53;
94
+ const DIGIT_1: utinyint = 54;
95
+ const DIGIT_3: utinyint = 55;
96
+ // row 7
97
+ const X: utinyint = 56;
98
+ const V: utinyint = 57;
99
+ const N: utinyint = 58;
100
+ const COMMA: utinyint = 59;
101
+ const QUESTION: utinyint = 60;
102
+ const DIGIT_2: utinyint = 62;
103
+ const PLUS: utinyint = 63;
104
+ // row 8
105
+ const SHIFT_LEFT: utinyint = 64;
106
+ const AT: utinyint = 65;
107
+ const BRACKET_RIGHT: utinyint = 66;
108
+ const GREATER: utinyint = 68;
109
+ const SHIFT_RIGHT: utinyint = 69;
110
+ const DIGIT_0: utinyint = 70;
111
+ const MINUS: utinyint = 71;
112
+ // row 9
113
+ const REVERSE: utinyint = 72; // RVS
114
+ const BRACKET_LEFT: utinyint = 73;
115
+ const SPACE: utinyint = 74;
116
+ const LESS: utinyint = 75;
117
+ const STOP: utinyint = 76; // RUN/STOP
118
+ const PERIOD: utinyint = 78;
119
+ const EQUALS: utinyint = 79;
120
+ }
@@ -0,0 +1,100 @@
1
+ // @8bitscript/pet/keys — the keyboard matrix, key by key: business keyboard.
2
+ //
3
+ // The 8032 profile's version of keys.8bs (see that file for how the two
4
+ // tables relate and which names both share). This is the **business**
5
+ // keyboard of the 8032 (and the 4032B/3032B, which are not profiles):
6
+ // typewriter layout with the digits on the top row, a numeric keypad of
7
+ // its own, TAB, ESC and RPT, and the symbols `! " # ...` reached with
8
+ // SHIFT rather than as keys of their own — so this table has KEYPAD_n
9
+ // and no EXCLAMATION. Same encoding, `row * 8 + column` in PIA1's matrix.
10
+ //
11
+ // Source: the business matrix the PET references give, checked key for
12
+ // key against VICE's positional map for the 8032, /opt/homebrew/share/
13
+ // vice/PET/gtk3_buuk_pos.vkm — the UK business layout, which is the one
14
+ // xpet's 8032 model loads. The US business keyboard is wired to the same
15
+ // matrix in every reference consulted, but has not been checked here.
16
+
17
+ export namespace Key {
18
+ // row 0
19
+ const DIGIT_2: utinyint = 0;
20
+ const DIGIT_5: utinyint = 1;
21
+ const DIGIT_8: utinyint = 2;
22
+ const MINUS: utinyint = 3; // shifted: =
23
+ const KEYPAD_8: utinyint = 4;
24
+ const CURSOR_RIGHT: utinyint = 5; // shifted: cursor left
25
+ // row 1
26
+ const DIGIT_1: utinyint = 8;
27
+ const DIGIT_4: utinyint = 9;
28
+ const DIGIT_7: utinyint = 10;
29
+ const DIGIT_0: utinyint = 11;
30
+ const KEYPAD_7: utinyint = 12;
31
+ const UP_ARROW: utinyint = 13;
32
+ const KEYPAD_9: utinyint = 15;
33
+ // row 2
34
+ const ESCAPE: utinyint = 16;
35
+ const S: utinyint = 17;
36
+ const F: utinyint = 18;
37
+ const H: utinyint = 19;
38
+ const BRACKET_RIGHT: utinyint = 20;
39
+ const K: utinyint = 21;
40
+ const SEMICOLON: utinyint = 22; // shifted: +
41
+ const KEYPAD_5: utinyint = 23;
42
+ // row 3
43
+ const A: utinyint = 24;
44
+ const D: utinyint = 25;
45
+ const G: utinyint = 26;
46
+ const J: utinyint = 27;
47
+ const RETURN: utinyint = 28;
48
+ const L: utinyint = 29;
49
+ const AT: utinyint = 30;
50
+ const KEYPAD_6: utinyint = 31;
51
+ // row 4
52
+ const TAB: utinyint = 32;
53
+ const W: utinyint = 33;
54
+ const R: utinyint = 34;
55
+ const Y: utinyint = 35;
56
+ const BACKSLASH: utinyint = 36;
57
+ const I: utinyint = 37;
58
+ const P: utinyint = 38;
59
+ const DELETE: utinyint = 39; // INST/DEL
60
+ // row 5
61
+ const Q: utinyint = 40;
62
+ const E: utinyint = 41;
63
+ const T: utinyint = 42;
64
+ const U: utinyint = 43;
65
+ const CURSOR_DOWN: utinyint = 44; // shifted: cursor up
66
+ const O: utinyint = 45;
67
+ const BRACKET_LEFT: utinyint = 46;
68
+ const KEYPAD_4: utinyint = 47;
69
+ // row 6
70
+ const SHIFT_LEFT: utinyint = 48;
71
+ const C: utinyint = 49;
72
+ const B: utinyint = 50;
73
+ const PERIOD: utinyint = 51;
74
+ const KEYPAD_PERIOD: utinyint = 52;
75
+ const SHIFT_RIGHT: utinyint = 54;
76
+ const KEYPAD_3: utinyint = 55;
77
+ // row 7
78
+ const Z: utinyint = 56;
79
+ const V: utinyint = 57;
80
+ const N: utinyint = 58;
81
+ const COMMA: utinyint = 59;
82
+ const KEYPAD_0: utinyint = 60;
83
+ const REPEAT: utinyint = 62; // RPT
84
+ const KEYPAD_2: utinyint = 63;
85
+ // row 8
86
+ const REVERSE: utinyint = 64; // RVS
87
+ const X: utinyint = 65;
88
+ const SPACE: utinyint = 66;
89
+ const M: utinyint = 67;
90
+ const HOME: utinyint = 68; // CLR/HOME
91
+ const SLASH: utinyint = 70; // shifted: ?
92
+ const KEYPAD_1: utinyint = 71;
93
+ // row 9
94
+ const LEFT_ARROW: utinyint = 72; // the back-arrow key, top row left
95
+ const DIGIT_3: utinyint = 73;
96
+ const DIGIT_6: utinyint = 74;
97
+ const DIGIT_9: utinyint = 75;
98
+ const STOP: utinyint = 76; // RUN/STOP
99
+ const COLON: utinyint = 77; // shifted: *
100
+ }
@@ -0,0 +1,39 @@
1
+ // @8bitscript/pet/pointer — the PET behind @8bitscript/pointer, and the
2
+ // one machine of the nine where "no cursor" is the final answer rather
3
+ // than a gap.
4
+ //
5
+ // Every call here does nothing and `DRAWS` is false, because **the PET has
6
+ // no control ports at all** — no mouse, no joystick, no paddles, nothing to
7
+ // point with — which is why @8bitscript/pet/input answers `pointer()`
8
+ // false too. There is nothing to draw an arrow for, and a machine with
9
+ // nothing to point cannot be given a pointer by writing more code.
10
+ //
11
+ // It still has to exist: Studio and every other portable program links
12
+ // @8bitscript/pointer, so a missing entry is not a program without a
13
+ // cursor, it is a program that does not build for the PET.
14
+ //
15
+ // It costs the PET nothing. `DRAWS` is a const and every function is
16
+ // empty, so a program's `if (pointer.DRAWS)` folds away and LLVM deletes
17
+ // the calls — the same zero the X16's input layer measures at (see
18
+ // packages/input/AGENTS.md).
19
+ //
20
+ // Were a pointer ever wanted here it would need hardware the machine does
21
+ // not have and this repository has no driver for: the light pen on the
22
+ // 8296's user port, or a KoalaPad. Both would be a new hardware option in
23
+ // packages/pet's catalog first, and neither would be a mouse.
24
+ export namespace pointer {
25
+
26
+ const DRAWS: bool = false;
27
+
28
+ function begin(): void {
29
+ }
30
+
31
+ function setColor(color: utinyint): void {
32
+ }
33
+
34
+ function update(): void {
35
+ }
36
+
37
+ function hide(): void {
38
+ }
39
+ }
package/src/screen.8bs ADDED
@@ -0,0 +1,94 @@
1
+ // @8bitscript/pet/screen — the PET's implementation of @8bitscript/screen.
2
+ //
3
+ // Named by "8bitscript".exports["./screen"] in this package's package.json,
4
+ // and what
5
+ //
6
+ // import { screen, BorderColor, BackgroundColor } from "@8bitscript/screen";
7
+ //
8
+ // resolves to when the build is for the PET: @8bitscript/screen's entry is
9
+ // keyed by machine and delegates here. Every machine's screen.8bs exports
10
+ // this same surface, which is what lets a program import it from
11
+ // @8bitscript/screen and never name the hardware.
12
+ //
13
+ // The PET is a monochrome machine — green or white phosphor, whatever the
14
+ // monitor is, with no colour hardware at all. `screen.setColors()` still
15
+ // exists and still links, because the point of the portable surface (see
16
+ // @8bitscript/vic20 and @8bitscript/c64's screen.8bs) is that a single
17
+ // portable program builds for every target without per-target branches in
18
+ // user code — but here it is deliberately inert: there is no register to
19
+ // write, so setColors() does nothing observable. A program that only ever
20
+ // sets colours through the portable surface still builds and runs correctly
21
+ // everywhere; it simply never shows a border or background tint on a PET,
22
+ // because a PET cannot show one.
23
+ //
24
+ // `blank()` is the one thing here that touches the screen, and how much
25
+ // screen there is depends on the model: 1000 cells on the 40-column PETs,
26
+ // 2000 on the 80-column 8032. That number comes from ./geometry.8bs, whose
27
+ // 8032 version is chosen by the build's profile — see that file.
28
+ import { Video } from "./geometry.8bs";
29
+
30
+ export namespace screen {
31
+ function setColors(border: u8, background: u8): void {
32
+ // Deliberately empty — see the file comment above.
33
+ }
34
+
35
+ // `blank(border, background)`: every cell blank and both colours set —
36
+ // black when left off, or `BorderColor.KEEP` / `BackgroundColor.KEEP`
37
+ // to leave one as it is. `setBorder` and `setBackground` are one
38
+ // colour each, `setColors` the pair; `text.setColor` owns what the
39
+ // next print looks like.
40
+ function blank(border: utinyint = BorderColor.BLACK, background: utinyint = BackgroundColor.BLACK): void {
41
+ if (border != BorderColor.KEEP) {
42
+ screen.setBorder(border);
43
+ }
44
+ if (background != BackgroundColor.KEEP) {
45
+ screen.setBackground(background);
46
+ }
47
+ for (let cell: usmallint = 0; cell < Video.CELL_COUNT; cell++) {
48
+ memory.write(0x8000 + cell, 32); // 32: the space screen code
49
+ }
50
+ }
51
+
52
+ function setBackground(background: u8): void {
53
+ // Deliberately empty — see the file comment above.
54
+ }
55
+
56
+ function setBorder(border: u8): void {
57
+ // Deliberately empty — see the file comment above.
58
+ }
59
+ }
60
+
61
+ // ---- colour names ----------------------------------------------------------
62
+ //
63
+ // The same eight names every machine's screen.8bs exports, so a program that
64
+ // says `screen.setColors(BorderColor.BLUE, BackgroundColor.BLACK)` through
65
+ // @8bitscript/screen still links here. The values are the C64's numbering,
66
+ // for want of any of the PET's own — nothing reads them.
67
+
68
+ export namespace BorderColor {
69
+ const BLACK: utinyint = 0;
70
+ const WHITE: utinyint = 1;
71
+ const RED: utinyint = 2;
72
+ const CYAN: utinyint = 3;
73
+ const PURPLE: utinyint = 4;
74
+ const GREEN: utinyint = 5;
75
+ const BLUE: utinyint = 6;
76
+ const YELLOW: utinyint = 7;
77
+ // Not a colour: `blank(KEEP, ...)` leaves this one as it is. 255 is
78
+ // a value no register here takes.
79
+ const KEEP: utinyint = 255;
80
+ }
81
+
82
+ export namespace BackgroundColor {
83
+ const BLACK: utinyint = 0;
84
+ const WHITE: utinyint = 1;
85
+ const RED: utinyint = 2;
86
+ const CYAN: utinyint = 3;
87
+ const PURPLE: utinyint = 4;
88
+ const GREEN: utinyint = 5;
89
+ const BLUE: utinyint = 6;
90
+ const YELLOW: utinyint = 7;
91
+ // Not a colour: `blank(KEEP, ...)` leaves this one as it is. 255 is
92
+ // a value no register here takes.
93
+ const KEEP: utinyint = 255;
94
+ }