├── orig
├── COLOR.COM
├── README.md
├── discf.py
├── asmcf.py
├── discfcolor.py
├── GEN.ASM
├── BOOT.ASM
├── forth.txt
└── COLOR.ASM
├── color.html
├── README.md
├── storage.js
├── keyb.js
├── edit.js
├── icons.js
├── gfx.js
├── init.js
└── main.js
/orig/COLOR.COM:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiju/jsColorForth/HEAD/orig/COLOR.COM
--------------------------------------------------------------------------------
/color.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | jsColorForth
2 | =============
3 |
4 | This is a port of Chuck Moore's [colorForth](https://colorforth.github.io/cf.htm) to Javascript.
5 | I derived it from the original assembly and Forth code, trying to stay fairly to the original.
6 |
7 | Notable changes made:
8 |
9 | - Since I can't compile to machine code, I compile to a bytecode ("wordcode") that gets JIT compiled to Javascript (Webassembly would be interesting to try as an alternative)
10 | - Naturally, all the PC hardware specific code is gone.
11 | - Currently the 'VM' is Harvard architecture and the wordcode is compiled to an append-only array.
12 |
--------------------------------------------------------------------------------
/orig/README.md:
--------------------------------------------------------------------------------
1 | This is the source code of the original colorForth, for reference.
2 | There are three parts:
3 | - Assembly language code in `*.ASM` files
4 | - Icons
5 | - colorForth code
6 |
7 | The latter two are only distributed as part of the `COLOR.COM` image.
8 | `forth.txt` contains the decompiled colorForth code in text form, using idiosyncratic syntax instead of colours.
9 | `forth.html` is the same, but in Technicolor.
10 |
11 | My script `discf.py` decompiles the colorForth code.
12 | It uses a ASCII representation for the colorForth.
13 | `discfcolor.py` decompiles into colors (terminal or HTML).
14 |
15 | `asmcf.py` assembles the ASCII form back into binary format.
16 |
--------------------------------------------------------------------------------
/orig/discf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | def dechuck(w):
3 | s = ""
4 | while True:
5 | if w >> 31 == 0:
6 | c = w >> 28
7 | w = w << 4 & 0xffffffff
8 | if c == 0:
9 | return s
10 | s += " rtoeani"[c]
11 | elif w >> 30 == 2:
12 | c = w >> 27 & 7
13 | w = w << 5 & 0xffffffff
14 | s += "smcylgfw"[c]
15 | else:
16 | c = w >> 25 & 31
17 | w = w << 7 & 0xffffffff
18 | s += "dvpbhxuq0123456789j-k.z/;:!+@*,?"[c]
19 | def sx(n):
20 | return (n & (1<<26) - 1) - (n & 1<<26) & 0xffffffff
21 |
22 | f = open('COLOR.COM', 'rb')
23 | for i in range(63):
24 | block = f.read(1024)
25 | if i < 18: continue
26 | print('#{}'.format(i))
27 | words = [block[4*j] | block[4*j+1] << 8 | block[4*j+2] << 16 | block[4*j+3] << 24 for j in range(256)]
28 | j = 0
29 | line = 0
30 | comment = False
31 | execute = False
32 | cyan = False
33 | while j < len(words):
34 | w = words[j]
35 | j += 1
36 | if w == 0:
37 | break
38 | m = w & 15
39 | s = dechuck(w & -16)
40 | if m in [1,3,4,7,9,10,11]:
41 | while j < len(words) and words[j] != 0 and (words[j] & 15) == 0:
42 | s += dechuck(words[j] & -16)
43 | j += 1
44 | if m == 8 or m == 6:
45 | if w & 0x10:
46 | dec = '${:x}'.format(sx(w>>5))
47 | else:
48 | dec = str(sx(w>>5))
49 | elif m == 2 or m == 5:
50 | if j == len(words):
51 | raise ValueError
52 | else:
53 | if w & 0x10:
54 | dec = '${:x}'.format(words[j])
55 | else:
56 | dec = str(words[j])
57 | j += 1
58 | elif m == 10:
59 | dec = s.capitalize()
60 | elif m == 11:
61 | dec = s.upper()
62 | else:
63 | dec = s
64 | pre = ''
65 | if not m in [2,5,6,8,9,10,11] and dec.isdigit():
66 | dec = '$$' + dec
67 | if m in [9,10,11]:
68 | if not comment:
69 | pre += '( '
70 | comment = True
71 | else:
72 | if comment:
73 | pre += ') '
74 | comment = False
75 | if m in [1,2,8]:
76 | if not execute:
77 | pre += '[ '
78 | execute = True
79 | else:
80 | if execute:
81 | pre += '] '
82 | execute = False
83 | if m == 7:
84 | if not cyan:
85 | pre += '[[ '
86 | cyan = True
87 | else:
88 | if cyan:
89 | pre += ']] '
90 | cyan = False
91 | if m == 12:
92 | pre += '& '
93 | assert j < len(words)
94 | dec += ' ' + str(words[j])
95 | j += 1
96 | elif m == 3:
97 | pre += '\n: '
98 | elif m in [4,6,5]:
99 | pass
100 | else:
101 | print(m)
102 | raise ValueError
103 | dec = pre + dec
104 | print(dec + ' ', end='')
105 | line += len(dec) + 1
106 | if comment:
107 | print(') ', end='')
108 | line += 2
109 | if execute:
110 | print('] ', end='')
111 | line += 2
112 | if line > 0:
113 | print()
114 |
--------------------------------------------------------------------------------
/orig/asmcf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | import re
3 |
4 | lower = re.compile('^[a-z0-9\-./;:!+@*,?]+$')
5 | upper = re.compile('^[A-Z0-9\-./;:!+@*,?]+$')
6 | capit = re.compile('^[A-Z0-9\-./;:!+@*,?][a-z0-9\-./;:!+@*,?]+$')
7 |
8 | def enchuck(s):
9 | w = 0
10 | n = 0
11 | r = []
12 | #print(s)
13 | for ch in s.lower():
14 | c = 1 + 'rtoeanismcylgfwdvpbhxuq0123456789j-k.z/;:!+@*,?'.find(ch)
15 | assert c > 0
16 | if c < 8:
17 | nc = 4
18 | b = c
19 | elif c < 16:
20 | nc = 5
21 | b = 0x10 | c - 8
22 | else:
23 | nc = 7
24 | b = 0x60 | c - 16
25 | tz = len(bin(b)) - len(bin(b).rstrip('0'))
26 | # print(ch, bin(b), nc, tz)
27 | if n + nc - tz > 28:
28 | r += [w << 32 - n]
29 | w = 0
30 | n = 0
31 | elif n + nc > 28:
32 | b >>= n + nc - 28
33 | nc = 28 - n
34 | w = w << nc | b
35 | n += nc
36 | if n != 0:
37 | r += [w << 32 - n]
38 | #print([hex(x) for x in r])
39 | return r
40 | def do_comment(w):
41 | r = enchuck(w)
42 | if lower.match(w):
43 | r[0] |= 9
44 | elif upper.match(w):
45 | r[0] |= 11
46 | elif capit.match(w):
47 | r[0] |= 10
48 | else:
49 | assert False
50 | return r
51 | def do_number(w, hex, execute, magenta):
52 | if magenta:
53 | return [w]
54 | if w>>26 in [0,63]:
55 | return [w<<5 & 0xffffffff | int(hex)<<4 | (8 if execute else 6)]
56 | else:
57 | return [int(hex)<<4 | (2 if execute else 5), w]
58 | def do_word(w, execute, cyan, next):
59 | r = enchuck(w)
60 | if next == 'red':
61 | r[0] |= 3
62 | elif next == 'magenta':
63 | r[0] |= 12
64 | elif execute:
65 | r[0] |= 1
66 | elif cyan:
67 | r[0] |= 7
68 | else:
69 | r[0] |= 4
70 | return r
71 |
72 | f = open('cf.f', 'r')
73 | blocks = {}
74 | comment = False
75 | execute = False
76 | cyan = False
77 | next = ''
78 | for l in f:
79 | words = l.split()
80 | for w in words:
81 | if w[0] == '#':
82 | cur = int(w[1:])
83 | if cur not in blocks.keys():
84 | blocks[cur] = []
85 | elif w == '(':
86 | comment = True
87 | elif comment:
88 | if w == ')':
89 | comment = False
90 | else:
91 | blocks[cur] += do_comment(w)
92 | elif w == '[':
93 | assert not execute and next == ''
94 | execute = True
95 | elif w == ']':
96 | assert execute and next == ''
97 | execute = False
98 | elif w == '[[':
99 | assert not cyan and next == ''
100 | cyan = True
101 | elif w == ']]':
102 | assert cyan and next == ''
103 | cyan = False
104 | elif w == ':':
105 | assert not execute and not cyan and next == ''
106 | next = 'red'
107 | elif w.isdigit():
108 | assert not cyan and (next == '' or next == 'magenta-num')
109 | blocks[cur] += do_number(int(w), False, execute, next == 'magenta-num')
110 | next = ''
111 | elif w[0:2] == '$$':
112 | assert next != 'magenta-num'
113 | blocks[cur] += do_word(w[2:], execute, cyan, next)
114 | next = ''
115 | elif w[0] == '$':
116 | assert not cyan and (next == '' or next == 'magenta-num')
117 | blocks[cur] += do_number(int(w[1:], 16), True, execute, next == 'magenta-num')
118 | next = ''
119 | elif w == '&':
120 | assert not execute and not cyan and next == ''
121 | next = 'magenta'
122 | else:
123 | assert next != 'magenta-num'
124 | blocks[cur] += do_word(w, execute, cyan, next)
125 | if next == 'magenta':
126 | next = 'magenta-num'
127 | else:
128 | next = ''
129 |
130 | g = open('new.bin', 'wb')
131 | for i in range(63):
132 | if i not in blocks:
133 | g.write(bytes([0] * 1024))
134 | continue
135 | b = blocks[i]
136 | for j in b:
137 | g.write(bytes([j & 0xff, j >> 8 & 0xff, j >> 16 & 0xff, j >> 24 & 0xff]))
138 | g.write(bytes([0] * (4 * (256 - len(b)))))
139 |
--------------------------------------------------------------------------------
/orig/discfcolor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | import sys
3 |
4 | def dechuck(w):
5 | s = ""
6 | while True:
7 | if w >> 31 == 0:
8 | c = w >> 28
9 | w = w << 4 & 0xffffffff
10 | if c == 0:
11 | return s
12 | s += " rtoeani"[c]
13 | elif w >> 30 == 2:
14 | c = w >> 27 & 7
15 | w = w << 5 & 0xffffffff
16 | s += "smcylgfw"[c]
17 | else:
18 | c = w >> 25 & 31
19 | w = w << 7 & 0xffffffff
20 | s += "dvpbhxuq0123456789j-k.z/;:!+@*,?"[c]
21 | def sx(n):
22 | return (n & (1<<26) - 1) - (n & 1<<26) & 0xffffffff
23 |
24 | def error(x,h):
25 | raise ValueError
26 | def t_green(x,h):
27 | return '\u001b[32{}m{}\u001b[0m'.format('' if h else ';1', x)
28 | def t_red(x,h):
29 | return '\u001b[31;1m{}\u001b[0m'.format(x)
30 | def t_cyan(x,h):
31 | return '\u001b[36;1m{}\u001b[0m'.format(x)
32 | def t_yellow(x,h):
33 | return '\u001b[33{}m{}\u001b[0m'.format('' if h else ';1', x)
34 | def t_white(x,h):
35 | return '\u001b[37;1m{}\u001b[0m'.format(x)
36 | def t_magenta(x,h):
37 | return '\u001b[35;1m{}\u001b[0m'.format(x)
38 |
39 | t_coltab = [error, t_yellow, t_green, t_red, t_green, t_green, t_green, t_cyan, t_yellow, t_white, t_white, t_white, t_magenta, error, error, error]
40 |
41 | def hc(x,c):
42 | return '{}'.format(c,x)
43 | def h_yellow(x,h):
44 | return hc(x, 'darkyellow' if h else 'yellow')
45 | def h_green(x,h):
46 | return hc(x, 'darkgreen' if h else 'green')
47 | def h_red(x,h):
48 | return hc(x, 'red')
49 | def h_cyan(x,h):
50 | return hc(x, 'cyan')
51 | def h_white(x,h):
52 | return hc(x, 'white')
53 | def h_magenta(x,h):
54 | return hc(x, 'magenta')
55 |
56 | h_coltab = [error, h_yellow, h_green, h_red, h_green, h_green, h_green, h_cyan, h_yellow, h_white, h_white, h_white, h_magenta, error, error, error]
57 |
58 | html = len(sys.argv) > 1
59 | coltab = h_coltab if html else t_coltab
60 |
61 | if html:
62 | header = """
63 |
64 |
65 |
66 |
67 | title
68 |
82 |
83 |
84 |
85 | """
86 | trailer = '
'
87 | nl = '
'
88 | def paropen(i):
89 | print('| {} | '.format(i),end='')
90 | def parclose():
91 | print(' |
')
92 | else:
93 | header = ""
94 | trailer = ""
95 | nl = '\n'
96 | def paropen(i):
97 | print('#{}'.format(i))
98 | def parclose():
99 | pass
100 |
101 | f = open('COLOR.COM', 'rb')
102 | print(header, end='')
103 | for i in range(63):
104 | block = f.read(1024)
105 | if i < 18: continue
106 | words = [block[4*j] | block[4*j+1] << 8 | block[4*j+2] << 16 | block[4*j+3] << 24 for j in range(256)]
107 | if words[0] == 0: continue
108 | paropen(i)
109 | j = 0
110 | line = 0
111 | while j < len(words):
112 | w = words[j]
113 | j += 1
114 | if w == 0:
115 | break
116 | m = w & 15
117 | s = dechuck(w & -16)
118 | if m in [1,3,4,7,9,10,11]:
119 | while j < len(words) and words[j] != 0 and (words[j] & 15) == 0:
120 | s += dechuck(words[j] & -16)
121 | j += 1
122 | if m == 8 or m == 6:
123 | if w & 0x10:
124 | dec = '{:x}'.format(sx(w>>5))
125 | else:
126 | dec = str(sx(w>>5))
127 | elif m == 2 or m == 5:
128 | if j == len(words):
129 | raise ValueError
130 | else:
131 | if w & 0x10:
132 | dec = '{:x}'.format(words[j])
133 | else:
134 | dec = str(words[j])
135 | j += 1
136 | elif m == 10:
137 | dec = s.capitalize()
138 | elif m == 11:
139 | dec = s.upper()
140 | else:
141 | dec = s
142 | if m == 3 and line > 0:
143 | print(nl,end='')
144 | line = 0
145 | dec = coltab[m](dec, (w & 0x10) != 0)
146 | print(dec + ' ', end='')
147 | line += len(dec) + 1
148 | if m == 12:
149 | dec = coltab[2](words[j], False)
150 | j += 1
151 | print(dec + ' ', end='')
152 | line += len(dec) + 1
153 | if line > 0:
154 | print(nl,end='')
155 | parclose()
156 | print(trailer, end='')
157 |
--------------------------------------------------------------------------------
/orig/GEN.ASM:
--------------------------------------------------------------------------------
1 | ;Generic graphics
2 |
3 | ALIGN 4
4 | frame dd 2000000h-hp*vp*2 ; 32 M
5 | displ dd 0f0000000h ; fujitsu
6 | fore dd 0f7deh
7 | xc dd 0
8 | yc dd 0
9 |
10 | rgb: ror EAX, 8
11 | shr AX, 2
12 | ror EAX, 6
13 | shr AL, 3
14 | rol EAX, 6+5
15 | and EAX, 0f7deh
16 | ret
17 |
18 | white: DUP_
19 | mov EAX, 0ffffffh
20 | color: call rgb
21 | mov fore, EAX
22 | DROP
23 | ret
24 |
25 | north: mov EDX, 0cf8h
26 | out DX, EAX
27 | add EDX, 4
28 | in EAX, DX
29 | ret
30 |
31 | dev: mov EAX, 80001008h ; Find display, start at device 2
32 | mov ECX, 31-1 ; end with AGP: 10008, bus 1, dev 0
33 | @@: DUP_
34 | call north
35 | and EAX, 0ff000000h
36 | cmp EAX, 3000000h
37 | DROP
38 | jz @f
39 | add EAX, 800h
40 | next @b
41 | @@: ret
42 |
43 | ati0: call dev
44 | or dword ptr [EAX-4], 2 ; Enable memory
45 | add AL, 24h-8 ; look for prefetch
46 | mov CL, 5
47 | @@: DUP_
48 | call north
49 | xor AL, 8
50 | jz @f
51 | DROP
52 | sub EAX, 4
53 | next @b
54 | DUP_
55 | call north
56 | and EAX, 0fffffff0h
57 | @@: mov displ, EAX
58 | DROP
59 | ret
60 |
61 | fifof: DROP
62 | graphic: ret
63 |
64 | switch:
65 | ; DUP_
66 | push ESI
67 | mov ESI, frame
68 | push EDI
69 | mov EDI, displ ; 0f2000000h eMonster Nvidia
70 | ; xor EAX, EAX
71 | mov ECX, hp*vp/2
72 | ;@@: lodsd
73 | ; add EAX, [EDI]
74 | ; rcr EAX, 1
75 | ; and EAX, 0f7def7deh
76 | ; stosd
77 | ; next @b
78 | rep movsd
79 | pop EDI
80 | pop ESI
81 | ; DROP
82 | jmp PAUSE
83 |
84 | clip: mov EDI, xy
85 | mov ECX, EDI
86 | test CX, CX
87 | jns @f
88 | xor ECX, ECX
89 | @@: and ECX, 0ffffh
90 | mov yc, ECX
91 | imul ECX, hp*2
92 | ; shl ECX, 10+1
93 | sar EDI, 16
94 | jns @f
95 | xor EDI, EDI
96 | @@: mov xc, EDI
97 | lea EDI, [EDI*2+ECX]
98 | add EDI, frame
99 | ret
100 |
101 | bit16: lodsw
102 | xchg AL, AH
103 | mov ECX, 16
104 | b16: shl AX, 1
105 | jnc @f
106 | mov [EDI], DX
107 | @@: add EDI, 2
108 | next b16
109 | ret
110 |
111 | bit32: lodsw
112 | xchg AL, AH
113 | mov ECX, 16
114 | b32: shl EAX, 1
115 | jnc @f
116 | mov [EDI], DX
117 | mov [EDI+2], DX
118 | mov [EDI+hp*2], DX
119 | mov [EDI+hp*2+2], DX
120 | @@: add EDI, 4
121 | next b32
122 | ret
123 |
124 | emit: call qcr
125 | push ESI
126 | push EDI
127 | push EDX
128 | imul EAX, 16*24/8
129 | lea ESI, icons[EAX]
130 | call clip
131 | mov EDX, fore
132 | mov ECX, 24
133 | @@: push ECX
134 | call bit16
135 | add EDI, (hp-16)*2
136 | pop ECX
137 | next @b
138 | pop EDX
139 | pop EDI
140 | pop ESI
141 | BL_: DROP
142 | SPACE: add xy, iw*10000h
143 | ret
144 |
145 | emit2: push ESI
146 | push EDI
147 | push EDX
148 | imul EAX, 16*24/8
149 | lea ESI, icons[EAX]
150 | call clip
151 | mov EDX, fore
152 | mov ECX, 24
153 | @@: push ECX
154 | call bit32
155 | add EDI, (2*hp-16*2)*2
156 | pop ECX
157 | next @b
158 | pop EDX
159 | pop EDI
160 | pop ESI
161 | add xy, iw*10000h*2
162 | DROP
163 | ret
164 |
165 | text1: call WHITE
166 | mov lm, 3
167 | mov rm, hc*iw
168 | jmp TOP
169 |
170 | line: call clip
171 | mov ECX, [ESI]
172 | shl ECX, 1
173 | sub EDI, ECX
174 | mov ECX, EAX
175 | mov EAX, fore
176 | rep stosw
177 | inc xy
178 | DROP
179 | DROP
180 | ret
181 |
182 | box: call clip
183 | cmp EAX, vp+1
184 | js @f
185 | mov EAX, vp
186 | @@: mov ECX, EAX
187 | sub ECX, yc
188 | jng no
189 | cmp dword ptr [ESI], hp+1
190 | js @f
191 | mov dword ptr [ESI], hp
192 | @@: mov EAX, xc
193 | sub [ESI], EAX
194 | jng no
195 | mov EDX, hp
196 | sub EDX, [ESI]
197 | shl EDX, 1
198 | mov EAX, fore
199 | @@: push ECX
200 | mov ECX, [ESI]
201 | rep stosw
202 | add EDI, EDX
203 | pop ECX
204 | next @b
205 | no: DROP
206 | DROP
207 | ret
208 |
--------------------------------------------------------------------------------
/storage.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | function uint32array_eq(a,b) {
4 | if(a.length !== b.length) return false;
5 | for(let j = 0; j < a.length; j++)
6 | if((a[j]|0) !== (b[j]|0))
7 | return false;
8 | return true;
9 | }
10 |
11 | function disassemble(words) {
12 | function raw(n) {
13 | if(n < 0) n += 2**32;
14 | return '%' + n.toString(16);
15 | }
16 | var n;
17 | for(var n = words.length - 1; n >= 0; n--)
18 | if(words[n] != 0)
19 | break;
20 | n++;
21 | var output = [];
22 | let num;
23 | for(var i = 0; i < n; ){
24 | let i0 = i;
25 | let w = words[i++];
26 | if(w == 0){
27 | output.push(raw(0));
28 | continue;
29 | }
30 | let m = w & 15;
31 | switch(m){
32 | case 1: case 3: case 4: case 7: case 9: case 10: case 11: case 12:
33 | let s = dechuck(w & -16);
34 | if(m != 12)
35 | while(i < n && words[i] != 0 && (words[i] & 15) == 0)
36 | s += dechuck(words[i++] & -16);
37 | let t = enchuck(s);
38 | t[0] |= m;
39 | if(s == '' || !uint32array_eq(words.subarray(i0, i), t) || m == 10 && !s.match(/^[a-z]/) || m == 11 && !s.match(/[a-z]/)){
40 | for(let j = i0; j < i; j++)
41 | output.push(raw(words[j]));
42 | continue;
43 | }
44 | if(s.match(/^[0-9]+$/) || s == ':') s = '\\' + s;
45 | switch(m){
46 | case 1:
47 | output.push('['); output.push(s); output.push(']');
48 | break;
49 | case 3:
50 | output.push(':'); output.push(s);
51 | break;
52 | case 4:
53 | output.push(s);
54 | break;
55 | case 7:
56 | output.push('[['); output.push(s); output.push(']]');
57 | break;
58 | case 9:
59 | output.push('('); output.push(s); output.push(')');
60 | break;
61 | case 10:
62 | output.push('(');
63 | output.push(s[0].toUpperCase() + s.substr(1));
64 | output.push(')');
65 | break;
66 | case 11:
67 | output.push('(');
68 | output.push(s.toUpperCase());
69 | output.push(')');
70 | break;
71 | case 12:
72 | if(i == words.length)
73 | output.push(raw(w));
74 | else{
75 | output.push('&');
76 | output.push(s);
77 | num = words[i++];
78 | if(num < 0) num += 2**32;
79 | output.push(num);
80 | }
81 | break;
82 | }
83 | break;
84 | case 8: case 6:
85 | if(m == 8)
86 | output.push('[');
87 | num = w>>5<<5>>5;
88 | if(num < 0) num += 2**32;
89 | if((w & 0x10) != 0)
90 | output.push('$' + num.toString(16));
91 | else
92 | output.push(num.toString());
93 | if(m == 8)
94 | output.push(']');
95 | break;
96 | case 2: case 5:
97 | if(i == words.length){
98 | output.push(raw(w));
99 | continue;
100 | }
101 | if(w>>5 != 0 || (words[i+1]>>26) + 1 <= 1){
102 | output.push(raw(w));
103 | output.push(raw(words[i++]));
104 | continue;
105 | }
106 | if(m == 2)
107 | output.push('[');
108 | num = words[i++];
109 | if(num < 0) num += 2**32;
110 | if((w & 0x10) != 0)
111 | output.push('$' + num.toString(16));
112 | else
113 | output.push(num.toString());
114 | if(m == 2)
115 | output.push(']');
116 | break;
117 | default:
118 | output.push(raw(w));
119 | continue;
120 | }
121 | }
122 | let w = 0;
123 | for(let i = 0; i < output.length; i++){
124 | switch(output[i]){
125 | case ':': if(i > 0){ output[w++] = '\n:'; continue; } break;
126 | case ')': if(output[i+1] === '('){ i++; continue; } break;
127 | case ']': if(output[i+1] === '['){ i++; continue; } break;
128 | case ']]': if(output[i+1] === '[['){ i++; continue; } break;
129 | }
130 | output[w++] = output[i];
131 | }
132 | output.length = w;
133 | return output.join(' ');
134 | }
135 |
136 | function storage_write() {
137 | var n = tos++;;
138 | if(n >= 0 && n < mem.length/256){
139 | let d = mem.subarray(n*256, n*256+256);
140 | let s = disassemble(d);
141 | let t = assemble(s, true);
142 | if(!uint32array_eq(d, t)){
143 | console.log('trial reassembly failed!');
144 | console.log(d);
145 | console.log(s);
146 | console.log(t);
147 | s = Array.prototype.slice.call(d).map(x => '=' + (x < 0 ? x + 2**32 : x).toString(16)).join(' ');
148 | }
149 | localStorage.setItem('jsColorForth #' + n, s);
150 | }else
151 | console.log("invalid write arg " + n);
152 | }
153 | builtin("write", storage_write);
154 |
155 | function storage_read() {
156 | var n = tos++;
157 | if(n >= 0 && n < mem.length/256){
158 | let d = localStorage.getItem('jsColorForth #' + n.toString());
159 | if(d === null) return;
160 | try{
161 | let data = assemble(d, true);
162 | mem.set(data, n * 256);
163 | }catch(e){
164 | console.log("invalid data in localStorage "+n);
165 | }
166 | }else
167 | console.log("invalid read arg " + n);
168 | }
169 | builtin("read", storage_read);
170 |
171 | function nc() {
172 | DUP_();
173 | tos = mem.length/256;
174 | }
175 | builtin("nc", nc);
176 |
--------------------------------------------------------------------------------
/orig/BOOT.ASM:
--------------------------------------------------------------------------------
1 | ; Floppy boot segment
2 |
3 | org 0 ; actually 7c00
4 | start: jmp start0
5 | nop
6 |
7 | db 'cmcf 1.0'
8 | dw 512 ; bytes/sector
9 | db 1 ; sector/cluster
10 | dw 1 ; sector reserved
11 | db 2 ; FATs
12 | dw 16*14 ; root directory entries
13 | dw 80*2*18 ; sectors
14 | db 0F0h ; media
15 | dw 9 ; sectors/FAT
16 | dw 18 ; sectors/track
17 | dw 2 ; heads
18 | dd 0 ; hidden sectors
19 | dd 80*2*18 ; sectors again
20 | db 0 ; drive
21 | ; db 0
22 | ; db 29h ; signature
23 | ; dd 44444444h ; serial
24 | ; db 'COLOR FORTH' ; label
25 | ; db ' '
26 |
27 | command db 0
28 | db 0 ; head, drive
29 | cylinder db 0
30 | db 0 ; head
31 | db 1 ; sector
32 | db 2 ; 512 bytes/sector
33 | db 18 ; sectors/track
34 | db 1bh ; gap
35 | db 0ffh
36 | ALIGN 4
37 | nc dd 9 ; Forth+Icons+blocks 24-161
38 | gdt dw 17h
39 | dd offset gdt0
40 | ALIGN 8
41 | gdt0 dw 0, 0, 0, 0
42 | dw 0FFFFh, 0, 9A00h, 0CFh ; code
43 | dw 0FFFFh, 0, 9200h, 0CFh ; data
44 |
45 | ; Code is compiled in Protected 32-bit mode.
46 | ; Hence org $-2 to fix 16-bit words
47 | ; and 4 hand-assembled instructions.
48 | ; and EAX and AX exchanged
49 | ; This code is in Real 16-bit mode
50 |
51 | start0: mov EAX, 4F02h ; Video mode
52 | org $-2
53 | mov EBX, vesa ; hp*vp rgb: 565
54 | org $-2
55 | int 10h
56 | cli
57 | xor AX, AX ; Move code to 0
58 | mov BX, AX
59 | mov EBX, CS
60 | mov DS, EBX
61 | mov ES, EAX
62 | mov DI, AX
63 | mov SI, AX
64 | call $+5 ; Where are we? IP+4*CS
65 | org $-2
66 | loc: pop ESI
67 | sub ESI, offset loc-offset start
68 | org $-2
69 | mov ECX, 512/4
70 | org $-2
71 | rep movsw
72 | ; jmp 0:relocate
73 | db 0eah
74 | dw offset relocate-offset start, 0
75 |
76 | relocate: ; This code is executed from 0
77 | mov DS, EAX
78 | ; lgdt fword ptr gdt
79 | db 0fh, 1, 16h
80 | dw offset gdt-offset start
81 | mov AL, 1
82 | mov CR0, EAX
83 | ; jmp 8:protected
84 | db 0eah
85 | dw offset protected-offset start, 8
86 |
87 | protected: ; Now in Protected 32-bit mode
88 | mov AL, 10h
89 | mov DS, EAX
90 | mov ES, EAX
91 | mov SS, EAX
92 | mov ESP, Gods
93 | xor ECX, ECX
94 |
95 | A20: mov AL, 0d1h
96 | out 64h, AL
97 | @@: in AL, 64h
98 | and AL, 2
99 | jnz @b
100 | mov AL, 4bh
101 | out 60h, AL
102 |
103 | call dma
104 | shl EBX, 4
105 | add ESI, EBX
106 | cmp dword ptr [ESI], 44444444h ; Boot?
107 | jnz cold
108 | mov CX, 63*100h-80h ; Nope
109 | rep movsd
110 | mov ESI, Godd
111 | jmp start2
112 |
113 | cold: call sense_
114 | jns cold
115 | mov ESI, Godd
116 | xor EDI, EDI ; Cylinder 0 on top of Address 0
117 | mov CL, byte ptr nc
118 | @@: push ECX
119 | call READ
120 | inc cylinder
121 | pop ECX
122 | loop @b
123 | start2: call stop
124 | jmp start1
125 |
126 | us equ 1000/6
127 | ms equ 1000*us
128 | SPIN: mov CL, 1ch
129 | call onoff
130 | ; mov DX, 3f2h
131 | ; out DX, AL
132 | @@: call sense_
133 | jns @b
134 | mov cylinder, 0 ; calibrate
135 | mov AL, 7
136 | mov CL, 2
137 | call cmd
138 | mov ECX, 500*ms
139 | @@: loop @b
140 | cmdi: call sense_
141 | js cmdi
142 | ret
143 |
144 | ready: ;call delay
145 | mov DX, 3f4h
146 | @@: in AL, DX
147 | out 0e1h, AL
148 | shl AL, 1
149 | jnc @b
150 | lea EDX, [EDX+1]
151 | ret
152 |
153 | transfer: mov CL, 9
154 | cmd: lea EDX, command
155 | mov [EDX], AL
156 | cmd0: push ESI
157 | mov ESI, EDX
158 | cmd1: call ready
159 | jns @f
160 | in AL, DX
161 | jmp cmd1
162 | @@: lodsb
163 | out DX, AL
164 | out 0e1h, AL
165 | loop cmd1
166 | pop ESI
167 | ;delay: mov EAX, us
168 | ;@@: dec EAX
169 | ; jnz @b
170 | ret
171 |
172 | sense_: mov AL, 8
173 | mov ECX, 1
174 | call cmd
175 | @@: call ready
176 | jns @b
177 | in AL, DX
178 | out 0e1h, AL
179 | and AL, AL
180 | ; cmp AL, 80h
181 | ret
182 |
183 | seek: call sense_
184 | jns seek
185 | ret
186 |
187 | stop: mov CL, 0ch ; Motor off
188 | onoff: DUP_
189 | mov AL, CL
190 | mov DX, 3f2h
191 | out DX, AL
192 | out 0e1h, AL
193 | DROP
194 | ret
195 |
196 | dma: mov word ptr command+1, 3a2h ; l2 s6 u32 ms (e 2)
197 | mov AL, 3 ; timing
198 | mov CL, 3
199 | call cmd
200 | mov word ptr command+1, 7000h ; +seek -fifo -poll
201 | mov AL, 13h ; configure
202 | mov CL, 4
203 | call cmd
204 | mov dword ptr command, ECX ; 0
205 | ret
206 |
207 | READ: call SEEK
208 | mov AL, 0e6h ; Read normal data
209 | call TRANSFER
210 | mov CX, 18*2*512
211 | @@: call ready
212 | in AL, DX
213 | out 0e1h, AL
214 | stosb
215 | next @b
216 | ret
217 |
218 | WRITE: call SEEK
219 | mov AL, 0c5h ; Write data
220 | call TRANSFER
221 | mov CX, 18*2*512
222 | @@: call ready
223 | lodsb
224 | out DX, AL
225 | out 0e1h, AL
226 | next @b
227 | ret
228 |
229 | org 1feh ; Mark boot sector
230 | dw 0aa55h
231 | dd 44444444h ; Mark COLOR.COM
232 |
233 | flop: mov cylinder, AL ; c-cx
234 | DUP_
235 | mov DX, 3f2h
236 | in AL, DX
237 | out 0e1h, AL
238 | test AL, 10h
239 | jnz @f
240 | jmp spin
241 | @@: ret
242 |
243 | readf: call flop ; ac-ac
244 | push EDI
245 | mov EDI, [ESI+4]
246 | shl EDI, 2
247 | call READ
248 | pop EDI
249 | readf1: DROP
250 | inc EAX
251 | add dword ptr [ESI], 1200h
252 | ret
253 |
254 | writef: call flop ; ac-ac
255 | push ESI
256 | mov ESI, [ESI+4]
257 | shl ESI, 2
258 | call WRITE
259 | pop ESI
260 | jmp readf1
261 |
262 | seekf: call flop ; c-c
263 | ; call delay
264 | call seek
265 | mov AL, 0fh
266 | mov CL, 3
267 | call cmd
268 | call cmdi
269 | DROP
270 | ret
271 |
272 | cmdf: mov ECX, EAX ; an
273 | DROP
274 | lea EDX, [EAX*4]
275 | call cmd0
276 | DROP
277 | ret
278 |
279 | readyf: DUP_
280 | call ready
281 | DROP
282 | ret
283 |
--------------------------------------------------------------------------------
/keyb.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | function $ACCEPT() {
3 | shift = alpha0;
4 | board = alpha;
5 | ret.push($ACCEPT1);
6 | }
7 | builtin("accept", $ACCEPT);
8 |
9 | function $ACCEPT1() {
10 | ret.push(() => {
11 | if(tos >= 4){
12 | shift = shift[8];
13 | ret.push($ACCEPT);
14 | ret.push(aword);
15 | ret.push($WORD_);
16 | }else
17 | ret.push(shift[tos]);
18 | });
19 | ret.push($KEY);
20 | }
21 |
22 | function $nul0() {
23 | DROP();
24 | ret.push($ACCEPT1);
25 | }
26 |
27 | function $WORD_() {
28 | RIGHT();
29 | words = 1;
30 | chars = 1;
31 | DUP_();
32 | data[data.length - 1] = 0;
33 | bits = 28;
34 | ret.push($WORD1);
35 | }
36 |
37 | function $WORD0() {
38 | DROP();
39 | ret.push($WORD1);
40 | ret.push($KEY);
41 | }
42 |
43 | function $WORD1() {
44 | if(!LETTER())
45 | ret.push(shift[tos]);
46 | else{
47 | if(tos != 0){
48 | DUP_();
49 | ECHO_();
50 | PACK();
51 | chars++;
52 | }
53 | DROP();
54 | ret.push($WORD1);
55 | ret.push($KEY);
56 | }
57 | }
58 |
59 | function ECHO_() {
60 | history_.copyWithin(0, 1);
61 | history_[10] = tos;
62 | DROP();
63 | }
64 |
65 | function PACK() {
66 | var cl, ch, t;
67 |
68 | if(tos >= 0o20){
69 | tos += 0o120;
70 | cl = 7;
71 | }else{
72 | cl = 4;
73 | if((tos & 0o10) != 0){
74 | cl++;
75 | tos ^= 0o30;
76 | }
77 | }
78 | t = tos;
79 | ch = cl;
80 | while(bits < cl){
81 | if((tos & 1) != 0){
82 | tos >>= 1;
83 | data[data.length - 1] <<= bits + 4;
84 | words++;
85 | bits = 28 - ch;
86 | tos = t;
87 | DUP_();
88 | return;
89 | }else{
90 | tos >>= 1;
91 | cl--;
92 | }
93 | }
94 | data[data.length - 1] <<= cl;
95 | data[data.length - 1] ^= tos;
96 | bits -= cl;
97 | }
98 |
99 | function LJ() {
100 | data[data.length - 1] <<= bits + 4;
101 | DROP();
102 | }
103 |
104 | function $X() {
105 | RIGHT();
106 | tos = words;
107 | data.length -= words;
108 | DROP();
109 | ret.push($ACCEPT);
110 | }
111 |
112 | function RIGHT() {
113 | history_.fill(0);
114 | }
115 |
116 | function LETTER() {
117 | if(tos >= 4){
118 | tos = board[tos - 4];
119 | return true;
120 | }else
121 | return false;
122 | }
123 |
124 | function $ALPHn() { DROP(); ret.push($ALPH0); }
125 | function $ALPH0() {
126 | shift = alpha0;
127 | board = alpha;
128 | DROP();
129 | ret.push($ACCEPT1);
130 | }
131 |
132 | function $STAR0() {
133 | shift = graph0;
134 | board = graphics;
135 | DROP();
136 | ret.push($ACCEPT1);
137 | }
138 |
139 | function $ALPH() {
140 | shift = alpha1;
141 | board = alpha;
142 | ret.push($WORD0);
143 | }
144 |
145 | function $GRAPH() {
146 | shift = graph1;
147 | board = graphics;
148 | ret.push($WORD0);
149 | }
150 |
151 | function decimal() {
152 | base = 10;
153 | shift = numb0;
154 | board = numbers;
155 | }
156 |
157 | function hex() {
158 | base = 16;
159 | shift = numb0;
160 | board = octals;
161 | }
162 |
163 | function $OCTAL() {
164 | if(current == decimal)
165 | current = hex;
166 | else
167 | current = decimal;
168 | numb0[6] ^= 0o41 ^ 0o16;
169 | current();
170 | ret.push($NUMBER0);
171 | }
172 |
173 | function $Xn() {
174 | DROP();
175 | DROP();
176 | ret.push($ACCEPT);
177 | }
178 |
179 | function $MINUS() {
180 | sign = tos;
181 | ret.push($NUMBER2);
182 | }
183 |
184 | var digit = [
185 | 14, 10, 0, 0,
186 | 0, 0, 12, 0, 0, 0, 15, 0,
187 | 13, 0, 0, 11, 0, 0, 0, 0,
188 | 0, 1, 2, 3, 4, 5, 6, 7,
189 | 8, 9
190 | ];
191 | var sign = 0;
192 |
193 | function $NUMBER0() { DROP(); ret.push($NUMBER3); }
194 | function $NUMBER() { current(); sign = 0; tos = 0; ret.push($NUMBER3); }
195 | function $NUMBER3() {
196 | ret.push(() => {
197 | if(!LETTER())
198 | ret.push(shift[tos]);
199 | else if(tos == 0)
200 | ret.push($NUMBER0);
201 | else{
202 | tos = digit[tos-4];
203 | if((sign & 0o37) != 0)
204 | tos = -tos;
205 | data[data.length - 1] = data[data.length - 1] * base + tos;
206 | ret.push($NUMBER2);
207 | }
208 | });
209 | ret.push($KEY);
210 | }
211 | function $NUMBER2() {
212 | DROP();
213 | shift = numb1;
214 | ret.push($NUMBER3);
215 | }
216 |
217 | function $ENDN() {
218 | DROP();
219 | ret.push($ACCEPT);
220 | ret.push(anumber);
221 | }
222 |
223 | function $EX1() {
224 | var r;
225 |
226 | while(--words > 0)
227 | DROP();
228 | r = forth0.lastIndexOf(tos);
229 | if(r < 0)
230 | ret.push($ABORT1);
231 | else{
232 | DROP();
233 | ret.push(dict_fn[forth2[r]]);
234 | }
235 | }
236 |
237 | var graph1 = [$WORD0, $X, LJ, $ALPH, 0o25, 0o45, 5, 0];
238 | var graph0 = [$nul0, $nul0, $nul0, $ALPH0, 0, 0, 5, 0, graph1];
239 | var alpha1 = [$WORD0, $X, LJ, $GRAPH, 0o25, 0o45, 0o55, 0];
240 | var alpha0 = [$nul0, $nul0, $NUMBER, $STAR0, 0, 0o41, 0o55, 0, alpha1];
241 | var numb1 = [$NUMBER0, $Xn, $ENDN, $NUMBER0, 0o25, 0o45, 0, 0];
242 | var numb0 = [$nul0, $MINUS, $ALPHn, $OCTAL, 0o43, 5, 0o16, 0, numb1];
243 | var alpha = [
244 | 0o15, 0o12, 0o01, 0o14,
245 | 0o24, 0o02, 0o06, 0o10,
246 | 0o23, 0o11, 0o17, 0o21,
247 | 0o22, 0o13, 0o16, 0o07,
248 | 0o05, 0o03, 0o04, 0o26,
249 | 0o27, 0o44, 0o25, 0o20
250 | ];
251 | var graphics = [
252 | 0o31, 0o32, 0o33, 0,
253 | 0o34, 0o35, 0o36, 0o30,
254 | 0o37, 0o40, 0o41, 0o57,
255 | 0o51, 0o50, 0o52, 0o54, //g : ; ! @
256 | 0o46, 0o42, 0o45, 0o56, //g Z J . ,
257 | 0o55, 0o47, 0o53, 0o43 //g * / + -
258 | ];
259 | var numbers = [
260 | 0o31, 0o32, 0o33, 0,
261 | 0o34, 0o35, 0o36, 0o30,
262 | 0o37, 0o40, 0o41, 0,
263 | 0, 0 , 0 , 0,
264 | 0, 0 , 0 , 0,
265 | 0, 0 , 0 , 0
266 | ];
267 | var octals = [
268 | 0o31, 0o32, 0o33, 0,
269 | 0o34, 0o35, 0o36, 0o30,
270 | 0o37, 0o40, 0o41, 0,
271 | 0 , 5 , 0o23, 0o12,
272 | 0 , 0o20, 4 , 0o16,
273 | 0 , 0 , 0 , 0
274 | ];
275 | var board = alpha;
276 | var shift = alpha0;
277 | var base = 10;
278 | var current = decimal;
279 | var chars = 1;
280 | var aword = $EX1;
281 | var anumber = nul;
282 | var words = 1;
283 | var bits = 28;
284 | var history_ = new Array(11).fill(0);
285 |
286 | var keys = {
287 | KeyQ: 16,
288 | KeyW: 17,
289 | KeyE: 18,
290 | KeyR: 19,
291 | KeyT: 0,
292 | KeyY: 0,
293 | KeyU: 4,
294 | KeyI: 5,
295 | KeyO: 6,
296 | KeyP: 7,
297 | BracketLeft: 0,
298 | BracketRight: 0,
299 | Enter: 0,
300 | ControlLeft: 0,
301 | KeyA: 20,
302 | KeyS: 21,
303 | KeyD: 22,
304 | KeyF: 23,
305 | KeyG: 0,
306 | KeyH: 0,
307 | KeyJ: 8,
308 | KeyK: 9,
309 | KeyL: 10,
310 | Semicolon: 11,
311 | Quote: 0,
312 | Backquote: 0,
313 | // ShiftLeft: 0,
314 | KeyZ: 24,
315 | KeyX: 25,
316 | KeyC: 26,
317 | KeyV: 27,
318 | KeyN: 1,
319 | KeyM: 12,
320 | Comma: 13,
321 | Period: 14,
322 | Slash: 15,
323 | // ShiftRight: 0,
324 | AltLeft: 3,
325 | AltRight: 3,
326 | ShiftLeft: 3,
327 | ShiftRight: 3,
328 | Space: 2
329 | };
330 | var keyqueue = [];
331 |
332 | function keypressed(e) {
333 | keyqueue.push(e.code);
334 | wakeup();
335 | }
336 |
337 | function $KEY() {
338 | DUP_();
339 | tos = 0;
340 | function loop() {
341 | let k = keyqueue.shift();
342 | if(!(k in keys)){
343 | ret.push(loop);
344 | ret.push(() => $SLEEP(() => keyqueue.length != 0));
345 | }else{
346 | tos = keys[k];
347 | }
348 | }
349 | ret.push(loop);
350 | ret.push($PAUSE);
351 | }
352 | builtin("key", $KEY);
353 |
--------------------------------------------------------------------------------
/edit.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var bas = dot10;
3 | var blk = 18;
4 | var curs = 0;
5 | var cad = 0;
6 | var pcad = 0;
7 | var lcad = 0;
8 | var trash = [];
9 | var ekbd = [
10 | 0o17, 0o01, 0o15, 0o55,
11 | 0o14, 0o26, 0o20, 0o01,
12 | 0o43, 0o11, 0o12, 0o53,
13 | 0o00, 0o70, 0o72, 0o02,
14 | 0o00, 0o00, 0o00, 0o00,
15 | 0o00, 0o00, 0o00, 0o00,
16 | ];
17 | var ekbd0 = [nul, nul, nul, nul, 0o25, 0o45, 7, 0];
18 | var actc = [
19 | yellow, 0, 0xff0000, 0xc000,
20 | 0, 0, 0xffff,
21 | 0, 0xffffff, 0xffffff, 0xffffff, 0x8080ff
22 | ];
23 | var action = 1;
24 |
25 | function $EDIT() {
26 | blk = tos;
27 | DROP();
28 | ret.push($E);
29 | }
30 | builtin("edit", $EDIT);
31 | function $E() {
32 | DUP_();
33 | tos = blk;
34 | anumber = $FORMAT;
35 | alpha0[4] = 0o45;
36 | alpha0[1] = $E0;
37 | ret.push($E0_);
38 | ret.push($REFRESH);
39 | }
40 | builtin("e", $E);
41 | function $E0() {
42 | DROP();
43 | ret.push($E0_);
44 | }
45 | function $E0_() {
46 | shift = ekbd0;
47 | board = ekbd;
48 | keyc = yellow;
49 | function loop() {
50 | ret.push(() => {
51 | ret.push(() => { DROP(); ret.push(loop); });
52 | if(tos < ekeys.length)
53 | ret.push(ekeys[tos]);
54 | });
55 | ret.push($KEY);
56 | }
57 | ret.push(loop);
58 | }
59 |
60 | function $FORMAT() {
61 | if((action & 0o12) != 0){
62 | DROP();
63 | return;
64 | }
65 | if((tos & 0xFC000000) != 0 && (tos & 0xFC000000) != 0xFC000000){
66 | DUP_();
67 | tos = 1;
68 | if(action != 4)
69 | tos = 3;
70 | if(base != 10)
71 | tos ^= 0o20;
72 | let t = data[data.length - 1];
73 | data[data.length - 1] = tos;
74 | tos = t;
75 | words = 2;
76 | }else{
77 | tos = tos << 5 ^ 2;
78 | if(action != 4)
79 | tos ^= 0o13;
80 | if(base != 10)
81 | tos ^= 0o20;
82 | words = 1;
83 | }
84 | ret.push($INSERT);
85 | }
86 |
87 | function unPACK() {
88 | DUP_();
89 | if(tos >= 0) {
90 | data[data.length - 1] <<= 4;
91 | tos = tos << 4 | tos >>> 28;
92 | tos &= 7;
93 | return tos;
94 | }
95 | tos <<= 1;
96 | if(tos >= 0){
97 | data[data.length - 1] <<= 5;
98 | tos = tos << 4 | tos >>> 28;
99 | tos = tos & 7 ^ 0o10;
100 | return tos;
101 | }
102 | data[data.length - 1] <<= 7;
103 | tos = tos << 6 | tos >>> 26;
104 | tos = (tos & 0o77) - 0o20;
105 | return tos;
106 | }
107 | builtin("unpack", unPACK);
108 |
109 | function $INSERT() {
110 | var t = insert0();
111 | if(t !== undefined)
112 | write(t, read(t) ^ action);
113 | else
114 | console.log("BUG");
115 | ret.push($ACCEPT);
116 | }
117 |
118 | function insert0() {
119 | if(((lcad + words ^ lcad) & -0x100) != 0){
120 | for(var i = words; i > 0; i--)
121 | DROP();
122 | return;
123 | }
124 | if(lcad > cad)
125 | memmove(cad + words, cad, lcad - cad);
126 | curs = cad + words;
127 | var t = curs;
128 | for(var i = words; i > 0; i--){
129 | write(--t, tos);
130 | DROP();
131 | }
132 | next = t;
133 | return t;
134 | }
135 |
136 | function blank() {
137 | xy = [0, 0];
138 | DUP_();
139 | tos = 0;
140 | color();
141 | DUP_();
142 | tos = hp;
143 | DUP_();
144 | tos = vp;
145 | box();
146 | }
147 |
148 | function qRING() {
149 | DUP_();
150 | data[data.length - 1]++;
151 | if(curs == next)
152 | curs = tos;
153 | if(tos != curs){
154 | if(tos < curs)
155 | pcad = next;
156 | DROP();
157 | return;
158 | }
159 | cad = next;
160 | xy[1] -= iw;
161 | DUP_();
162 | tos = 0xe04000;
163 | color();
164 | tos = 0o60;
165 | let c = xy[1] - rm;
166 | emit();
167 | if(c >= 0) xy[1] -= iw;
168 | }
169 |
170 | function $REFRESH() {
171 | function ref1() {
172 | if((read(next) & 0xf) != 0)
173 | qRING();
174 | var t = read(next++);
175 | if((t & 0o20) != 0)
176 | bas = dot;
177 | else
178 | bas = dot10;
179 | ret.push(ref1);
180 | ret.push(display[t & 0o17]);
181 | }
182 | ret.push(() => {
183 | blank();
184 | text1();
185 | DUP_();
186 | cad = lcad;
187 | tos = 0;
188 | pcad = blk << 8;
189 | next = pcad;
190 | ret.push(ref1);
191 | });
192 | ret.push($SHOW);
193 | }
194 | var display = (function() {
195 | function rW() {
196 | if(xy[1] != lm)
197 | cr();
198 | RED();
199 | type1();
200 | }
201 | function gW() { GREEN(); type1(); }
202 | function mW() { CYAN(); type1(); }
203 | function wW() { DUP_(); tos = yellow; color(); type1(); }
204 | function $type0() {
205 | xy[1] -= iw;
206 | if((read(next - 1) & -0o20) != 0)
207 | type1();
208 | else{
209 | lcad = --next;
210 | space();
211 | qRING();
212 | ret.pop();
213 | DROP();
214 | ret.push(keyboard);
215 | }
216 | }
217 | function Cap() {
218 | WHITE();
219 | DUP_();
220 | tos = read(next - 1) & -0o20;
221 | unPACK();
222 | tos += 48;
223 | emit();
224 | type2();
225 | }
226 | function CAPS() {
227 | WHITE();
228 | DUP_();
229 | tos = read(next - 1) & -0o20;
230 | while(unPACK()){
231 | tos += 48;
232 | emit();
233 | }
234 | space();
235 | DROP();
236 | DROP();
237 | }
238 | function text() { WHITE(); type1(); }
239 | function type1() {
240 | DUP_();
241 | tos = read(next - 1) & -0o20;
242 | type2();
243 | }
244 | function type2() {
245 | while(unPACK())
246 | emit();
247 | space();
248 | DROP();
249 | DROP();
250 | }
251 | function gsW() {
252 | gnW1(read(next - 1) >> 5);
253 | }
254 | function var_() {
255 | MAGENTA();
256 | type1();
257 | gnW();
258 | }
259 | function gnW() {
260 | gnW1(read(next++));
261 | }
262 | function gnW1(t) {
263 | DUP_();
264 | tos = bas == dot10 ? 0xf800 : 0xc000;
265 | color();
266 | DUP_();
267 | tos = t;
268 | bas();
269 | }
270 | function sW() {
271 | nW1(read(next - 1) >> 5);
272 | }
273 | function nW() {
274 | nW1(read(next++));
275 | }
276 | function nW1(t) {
277 | DUP_();
278 | tos = bas == dot10 ? yellow : 0xc0c000;
279 | color();
280 | DUP_();
281 | tos = t;
282 | bas();
283 | }
284 | return [
285 | $type0, wW, nW, rW,
286 | gW, gnW, gsW, mW,
287 | sW, text, Cap, CAPS,
288 | var_, nul, nul, nul
289 | ];
290 |
291 | })();
292 |
293 | var ekeys = (function() {
294 | function $actn() {
295 | keyc = tos;
296 | ret.pop();
297 | DROP();
298 | ret.push($ACCEPT);
299 | }
300 | function $act(n) {
301 | return () => {
302 | action = n;
303 | tos = actc[action - 1];
304 | aword = $INSERT;
305 | ret.push($actn);
306 | };
307 | }
308 | function $actv() {
309 | action = 12;
310 | tos = 0xff00ff;
311 | aword = () => {
312 | DUP_();
313 | tos = 0;
314 | words++;
315 | ret.push($INSERT);
316 | };
317 | ret.push($actn);
318 | }
319 | function mcur() {
320 | if(curs > 0)
321 | curs--;
322 | }
323 | function pcur() {
324 | curs++;
325 | }
326 | function mmcur() {
327 | if(curs >= 8)
328 | curs -= 8;
329 | else
330 | curs = 0;
331 | }
332 | function ppcur() {
333 | curs += 8;
334 | }
335 | function pblk() {
336 | blk += 2;
337 | data[data.length - 1] += 2;
338 | }
339 | function mblk(){
340 | if(blk >= 20){
341 | blk -= 2;
342 | data[data.length - 1] -= 2;
343 | }
344 | }
345 | function shadow() {
346 | blk ^= 1;
347 | data[data.length - 1] ^= 1;
348 | }
349 | function $eout() {
350 | ret.pop();
351 | ret.pop();
352 | DROP();
353 | DROP();
354 | aword = $EX1;
355 | anumber = nul;
356 | alpha0[4] = 0;
357 | alpha0[1] = $nul0;
358 | keyc = yellow;
359 | ret.push($ACCEPT);
360 | }
361 | function enstack() {
362 | for(var t = cad - 1; t >= pcad; t--)
363 | trash.push(read(t));
364 | trash.push(cad - pcad);
365 | }
366 | function DEL() {
367 | enstack();
368 | memmove(pcad, cad, lcad - pcad);
369 | mcur();
370 | }
371 | function destack() {
372 | if(trash.length == 0)
373 | return;
374 | words = trash.pop();
375 | for(var i = words; i > 0; i--){
376 | DUP_();
377 | tos = trash.pop();
378 | }
379 | insert0();
380 | }
381 | return [
382 | nul, DEL, $eout, destack,
383 | $act(1), $act(3), $act(4), shadow,
384 | mcur, mmcur, ppcur, pcur,
385 | mblk, $actv, $act(7), pblk,
386 | nul, $act(11), $act(10), $act(9),
387 | nul, nul, nul, nul
388 | ];
389 | })();
390 |
--------------------------------------------------------------------------------
/icons.js:
--------------------------------------------------------------------------------
1 | var iconstr = atob(
2 | `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
3 | AAAA4/j3/v///Af4AfAA8ADwAPAA8ADwAPAA8ADwAAAAAAAAAAAAA8ADwAPAA8A//D/8P/wDwAPA
4 | A8ADwAPAA8ADwAPAA8ADwAPAA8ADwAAAAAAAAAAAAAAAAAAAAAAAAAAAH/h//n/++B/wD/AP8A/w
5 | D/AP8A/4H3/+f/4f+AAAAAAAAAAAAAAAAAAAAAAAAAAAH/h//n/+8A/wD/Af//7//PAA8AD4AH/+
6 | f/4f+AAAAAAAAAAAAAAAAAAAAAAAAAAAH/h//n/+AB8ADwAPP/9///gP8A/wH3//f/8f9wAAAAAA
7 | AAAAAAAAAAAAAAAAAAAA4/j3/v/+/B/4D/AP8A/wD/AP8A/wD/AP8A/wDwAAAAAAAAAAA8ADwAPA
8 | A8AAAAAAAAADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAAAAAAAAAAAAAAAAAAAAAAAAAAAH/h/
9 | /n/++ALwAPAAf/w//gAPAA9AH3/+f/4f+AAAAAAAAAAAAAAAAAAAAAAAAAAA3Dz+fv/////zz+GH
10 | 4AfgB+AH4AfgB+AH4AfgBwAAAAAAAAAAAAAAAAAAAAAAAAAAH/h//n/++A/wAfAA8ADwAPAA8AH4
11 | D3/+f/4f+AAAAAAAAAAAAAAAAAAAAAAAAAAA4AfwD/gffD4+fB/4D/AH4AfAD4AfAD4AfAD4APAA
12 | 4ADAAIAABwAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHwAfAA+AB4AAAAAAAAAAAAAAA
13 | AAAAAAAAAAAAH+d/93//+B/wD/AP8A/wD/gff/9//x//AA8AD2Aff/5//h/4AfAD+AeIB4A/4D/w
14 | P/AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAAAAAAAAAAAAAAAAAAAAAAAAAAAwAPgB+AH4Afx
15 | j3GOcY573jvcP/weeB54DDAMMAAAAAAAAAAAAA8ADwAPAA8ADwAPH+9//3//+B/wD/AP8A/wD/AP
16 | 8A/4H3//f/8f7wAAAAAAAAAAAAAAAAAAAAAAAAAA4AfgB/APcA54HjgcPDwcOB54DnAP8AfgA8AB
17 | gAAAAAAAAAAAAAAAAAAAAAAAAAAA4/j3/v/+/h/8D/gP8A/wD/gf//7//vf48ADwAPAA8ADwAPAA
18 | 8ADwAPAA8ADwAPAA9/j//v/++B/wD/AP8A/wD/AP8A/4H//+7/7n+AAAAAAAAAAA8ADwAPAA8ADw
19 | APAA8/j3/v/+/B/4D/AP8A/wD/AP8A/wD/AP8A/wDwAAAAAAAAAAAAAAAAAAAAAAAAAA8A/4H3w+
20 | Pnwf+A/wB+AH4A/wH/g+fHw++B/wDwAAAAAAAAAAAAAAAAAAAAAAAAAA8A/wD/AP8A/wD/AP8A/w
21 | D/AP8A/4H3/+f/4f+AAAAAAAAAAAAAAAAAAAAAAAAAAAH8d/73//+D/wH/AP8A/wD/gff/9//x/v
22 | AA8ADwAPAA8ADwAOH/h//n/++B/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/4H3/+f/4f+AAAAAAA
23 | AAAAAeAD4APgB+AH4AXgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AAAAAAAAAAAH/h//n/+
24 | 8B8ADwAPAA8ADwAfH/5//n/4+ADwAPAA8ADwAP///////wAAAAAAAAAAH/h//n/+8B8ADwAPAA8A
25 | DwAfB/4H/Af+AB8ADwAPAA/wH3/+f/4f+AAAAAAAAAAA8PDw8PDw8PDw8PDw8PDw8PDw////////
26 | APAA8ADwAPAA8ADwAPAA8AAAAAAAAAAA////////8ADwAPAA8ADwAPAA//j//v/+AB8ADwAPAA/w
27 | H3/+f/4f+AAAAAAAAAAAH/h//n/++A/wAPAA8ADwAPgA//j//v/++B/wD/AP8A/4H3/+f/4f+AAA
28 | AAAAAAAA////////AAcADwAfAD4AfAD4AfAD4AfAD4AfAD4AfAD4APAA4ADAAAAAAAAAAAAAH/h/
29 | /n/++B/wD/AP8A/wD/gff/4//H/++B/wD/AP8A/4H3/+f/4f+AAAAAAAAAAAH/h//n/++B/wD/AP
30 | 8A/wD/gff/9//x/vAA8ADwAPAA/wH3/+f/4f+AAAAAAAAAAAAHgAeAB4AHgAAAAAAAAAeAB4AHgA
31 | eAB4AHgAeAB4AHgAeAB4AHgAeBz4H/AP8AfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//f////v/+
32 | AAAAAAAAAAAAAAAAAAAAAAAA8ADwAPAA8ADwAPAA8Dzw/PP8/+D/gP8A/wD/wP/w8/zw//A/8A/w
33 | AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYADwAfgB+ADwAGAAAAAAAAAAAA
34 | AAAAAAAAAAAAAAAA////////AB8APwD+A/gP4D+A/gD4AP///////wAAAAAAAAAAAA8AHwAfAD4A
35 | fAB8APgB8AHwA+AHwAfAD4AfAB8APgB8AHwA+AD4AAAAAAAAAAAAAAAAAAAABwAPgB/AH8AfwA+A
36 | BwAAAAAAAAAHAA+AH8AfwB/AD4AHgAOABwAOABwAAAAAAAAABwAPgB/AH8AfwA+ABwAAAAAAAAAH
37 | AA+AH8AfwB/AD4AHAAAAAAAAAAAAAYADwAPAB+AH4AfgB+AH4APAA8ABgAGAAYAAAAAAAAADwAPA
38 | A8ADwAAAAAAAAAAAAAAAAAAAAAAAAAAAA8ADwAPAA8ADwH/+f/5//n/+A8ADwAPAA8ADwAAAAAAA
39 | AAAAH/h//n/+8A/gB+AH4cfj5+Pn4+fj/+P+4/7h+OAA4ADwD3/+f/4f+AAAAAAAAAAAAAAAAAAA
40 | AAAAAAAAAAAIMBx4HvAP4AfAA+AH8A94HjgMEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
41 | AAAAAAAAAAAAAAAHAA+AH8AfwB/AD8AHwAOABwAOABwAH/h//n/+8A8ABwAHAA8AfgH+AfgD4APA
42 | A8AAAAAAAAADwAPAA8ADwAAAAAAAAAAA//D//P/+f/4//x//D/8H/wP/Af8A/wD/AP8A/wH/A/8H
43 | /w//H/8//3/+//7//P/w//j//v/+///wH/AP8A/wD/Af/////v/+//j/wPfg8/Dx+PD88H7wP/Af
44 | 8A8AAAAA//////////8DwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8AAAAAAH/h/
45 | /n/+///4H/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/gf//9//n/+H/gAAAAA///////////wAPAA
46 | 8ADwAPAA/+D/4P/g/+DwAPAA8ADwAPAA//////////8AAAAAAYABgAPAA8AH4AfgB+AP8A5wDnAe
47 | eB/4H/g//D/8OBx4HnAO8A/wD+AH4AcAAAAA+A/8D/wP/g/+D/8P9w/3D/eP84/zz/PP8c/x7/Dv
48 | 8O/w//B/8H/wP/A/8B8AAAAAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8AD
49 | wAPAA8AAAAAAH/h//n/+///4A/AA8ADwAPgA//h//n/+H/8AHwAPAA8AD8Af//9//n/+H/gAAAAA
50 | 4AfgB/AP+B/4H/w//n/ud+fn5+fjx+GH4AfgB+AH4AfgB+AH4AfgB+AH4AcAAAAAH/h//n/+///4
51 | H/AP8ADwAPAA8ADwAPAA8ADwAPAA8ADwD/gf//9//n/+H/gAAAAA4AfwD/APeB54Hjw8PDweeA/w
52 | D/AH4APAA8ADwAPAA8ADwAPAA8ADwAPAA8AAAAAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADw
53 | APAA8ADwAPAA//////////8AAAAAH/h//n/+///4H/AP8ADwAPAA8ADwAPA/8D/wP/AP8A/wD/gf
54 | //9//n/+H/gAAAAA///////////wAPAA8ADwAPAA/+D/4P/g/+DwAPAA8ADwAPAA8ADwAPAA8AAA
55 | AAAAwAPgB+AH4AfgB3AOcA5wDnAOcA5xjnGOOZw73D/8P/wf+B54HDgcOBgYGBgAAAAA/+D/+P/8
56 | //7wPvAf8A/wD/AP8A/wD/AP8A/wD/AP8A/wH/A+//7//P/4/+AAAAAA4AfgB/AP8A/wD/gf+B94
57 | Hnw+fD48PDw8HngeeA/wD/AH4AfgA8ADwAGAAYAAAAAA//j//v/+///wH/AP8A/wD/Af/////v/+
58 | //jwAPAA8ADwAPAA8ADwAPAA8AAAAAAA/+D/+P/8//7wPvAf8A/wD/Af//7//P/8//7wH/AP8A/w
59 | H/A+//7//P/4/+AAAAAA8A/wD/AP8A/wD/AP8A/wD/AP///////////wD/AP8A/wD/AP8A/wD/AP
60 | 8A8AAAAA4AfwD/gfeB58Pj58Hngf+A/wB+AH4AfgB+AP8B/4Hng+fHw+eB74H/AP4AcAAAAA8A/w
61 | D/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/gf//9//n/+H/gAAAAAH/h//n/+///4H/AP
62 | 8A/wD/AP8A/wD/AP8A/wD/DP8O/wf/g///9//n//H/sAAAAAH/h//n/+f/7gB+AH4AfgB+AH4Afg
63 | B+AH4AfgB+AH4AfgB+AH4AfgB3/+f/5//h/4AYABgAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGA
64 | AYABgAGAAYABgAGAAYABgAGAH/h//n/+f/7gB+AHAAcABwAHAAcf/n/+f/5/+OAA4ADgAOAA4ADg
65 | AP//////////H/h//n/+f/7gB+AHAAcABwAHAAcH/gf+B/4H/gAHAAcABwAH4AfgB3/+f/5//h/4
66 | 4ODg4ODg4ODg4ODg4ODg4ODg4OD//////////wDgAOAA4ADgAOAA4ADgAOAA4ADg///////////g
67 | AOAA4ADgAOAA4AD/+P/+//7//gAHAAcABwAH4AfgB3/+f/5//h/4H/h//n/+f/7gB+AH4ADgAOAA
68 | 4AD/+P/+//7//uAH4AfgB+AH4AfgB3/+f/5//h/4//////////8ADwAeAB4APAB4AHgA8AHgAeAD
69 | wAeAB4APAB4AHgA8AHgAeADwAOAAH/h//n/+f/7gB+AH4AfgB+AH4Ad//n/+f/5//uAH4AfgB+AH
70 | 4AfgB3/+f/5//h/4H/h//n/+f/7gB+AH4AfgB+AH4Ad//3//f/8f/wAHAAcABwAH4AfgB3/+f/5/
71 | /h/4AA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8AD/Af//9//n/+H/gAAAAAAAAAAAAA
72 | AAAAAAAAAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAA8A/wH/A/8H7x+PPw9+D/
73 | gP8A/gD8APwA/gD/AP+A9+Dz8PH48H7wP/Af8A8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
74 | AYADwAPAB+AH4APAA8ABgAAAAAAAAAAA//////////8ADwAfAD8AfgD8AfgD8AfgD8AfgD8AfgD8
75 | APgA//////////8AAAAAAAMABwAHAA4AHgAcADgAeABwAOAB4AHAA4AHgAcADgAeABwAOAB4AHAA
76 | 4ADgAMAAAAAAAAAAAAAAAAAAAYADgAOAA4ABgAAAAAAAAAAAAYADgAOAA4ABgAGABwAGAAAAAAAA
77 | AAAAAAAAAAAAAYADgAOAA4ABgAAAAAAAAAAAAYADgAOAA4ABgAAAAAAAAAAAA8ADwAPAA8ADwAPA
78 | A8ADwAPAA8ADwAPAAYABgAGAAYAAAAAAAAAAAAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAYD/
79 | /////////wGAAYABgAGAAYABgAGAAYABgAGAH/h//n/+f/7gB+AH4Afn5+fn5+fmZ+Zn5mfmZ+f+
80 | 5/7n/OAA4ADgB3/+f/5//h/4AYABgAGAAYABgAGAA8ADwP////9//h/4D/AH4AfgD/AP8B54Hngc
81 | OBgYEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYADgAOAA4ABgAGABwAGAAAA
82 | ////////////////////////////////////////////////////////////////AAAAAAAAAAAA
83 | AAAAAAAAAA8AAPAPAAPwDwAP8A8AP/APAP/ADwP/AA8P/AAPP/AAD//AAA//AAAP/AAAD/AAAA/w
84 | AAAP/AAAD/8AAA//wAAPP/AADw/8AA8D/wAPAP/ADwA/8A8AD/APAAPwDwAA8AAAAAAAAAAAAAAA
85 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
86 | AAAAAAAAAAAAAAAAAAGAAAAH4AAAB+AAAA/wAAAP8AAAB+AAAAfgAAABgAAAAAAAAAAAAAAAAAAA
87 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wD///8A////AP///wAAAH4AAA
88 | D8AAAB+AAAA/AAAAfgAAAPwAAAH4AAAD8AAAB+AAAA/AAAAfgAAAPwAAAH4AAAD8AAAB+AAAA/AA
89 | AAf///AP///wD///8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAADw
90 | AAAB8AAAA+AAAAfAAAAPgAAAHwAAAD4AAAB8AAAA+AAAAfAAAAPgAAAHwAAAD4AAAB8AAAA+AAAA
91 | fAAAAPgAAAHwAAAD4AAAB8AAAA+AAAAPAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
92 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAHwAAAB8AAAAfAAAADgAAAAAAAAAAA
93 | AAAAAAAAAAAAAAOAAAAHwAAAB8AAAAfAAAADgAAAA4AAAA8AAAAOAAAAAAAAAAAAAAAAAAAAAAAA
94 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAfAAAAHwAAA
95 | B8AAAAOAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAfAAAAHwAAAB8AAAAOAAAAAAAAAAAAAAAAAAAAA
96 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfg
97 | AAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAADwAAAA8AAAAPAAAADwAAAAAAAAAAAAAAAAAAAAAAA
98 | AAPAAAADwAAAA8AAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAADwAAA
99 | A8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAA////AP///wD///8A////AAA8AAAAPAAAAD
100 | wAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
101 | AAAAAAAA//8AA///wAf//+AH///gD4AB8A8AAPAPAADwDw/w8A8f+PAPH/jwDxw48A8cOPAPHDjw
102 | Dxw58A8f/+APH//gDw//gA8AAAAPAAAAD4AB8Af//+AH///gA///wAD//wAAAAAAAAAAAAAAAAAA
103 | AAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAAAAGAAAADwAAAA8AAAAPAAAAH4AAAB+AAD///8A//
104 | //AD///AAP//AAA//AAAH/gAAB/4AAA//AAAP/wAAH5+AAB8PgAAeB4AAOAHAADAAwAAAAAAAAAA
105 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
106 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAHwAAAB8AAAAfAAAADgAAA
107 | A4AAAA8AAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//8Af///4PAAAPHAAAA7/////////////
108 | ////////////////////////////////////////////////////////////////////////////
109 | //////////////////////////////////////9wAAAOPAAACAgICAgICAgI`
110 | );
111 |
--------------------------------------------------------------------------------
/gfx.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var hp = 1024;
3 | var vp = 768;
4 | var canvas, ctx;
5 | var fore, forestr;
6 | var xc = 0;
7 | var yc = 0;
8 | var xy = [3, 3];
9 |
10 | function LRU(N, mask) {
11 | this.N = N;
12 | this.next = new Array(N+1);
13 | this.prev = new Array(N+1);
14 | for(var i = N; i >= 0; i--){
15 | if(i == N || (i & ~mask) == 0){
16 | this.next[i] = i;
17 | this.prev[i] = i;
18 | this.used(i);
19 | }
20 | }
21 | }
22 | LRU.prototype.used = function(i) {
23 | this.next[this.prev[i]] = this.next[i];
24 | this.prev[this.next[i]] = this.prev[i];
25 | this.next[i] = this.next[this.N];
26 | this.prev[i] = this.N;
27 | this.next[this.N] = i;
28 | this.prev[this.next[i]] = i;
29 | }
30 | LRU.prototype.get = function() {
31 | return this.prev[this.N];
32 | }
33 |
34 | var fontcache = (function(){
35 | var canvas, ctx, data, buf;
36 | var state = [];
37 | var r = {};
38 | var chars = {};
39 | var N = 256;
40 | var by = 16;
41 | var bmask = N - 1 & ~(by | 1);
42 | var slots = new Array(N);
43 | var lru = new LRU(N, -1);
44 | var lrub = new LRU(N, bmask);
45 |
46 | function sx(i) { return (i & by - 1) * 16; }
47 | function sy(i) { return (i >> 4) * 24; }
48 | r.init = function() {
49 | canvas = document.createElement('canvas');
50 | canvas.width = by*16;
51 | canvas.height = (N/by|0)*24;
52 | ctx = canvas.getContext('2d');
53 | data = ctx.createImageData(16*2, 24*2);
54 | buf = new Uint32Array(data.data.buffer);
55 | for(var i = 0; i < 64; i++)
56 | slots[i] = '';
57 | };
58 | function used(i, big) {
59 | lru.used(i);
60 | lrub.used(i & bmask);
61 | if(big){
62 | lru.used(i ^ 1);
63 | lru.used(i ^ by);
64 | lru.used(i ^ by ^ 1);
65 | }
66 | }
67 | function set1(i, ch, col, big) {
68 | delete chars[slots[i]];
69 | slots[i] = [ch, col, big].toString();
70 | }
71 | function set(i, ch, col, big) {
72 | set1(i, ch, col, big);
73 | if(big){
74 | set1(i^1, ch, col, big);
75 | set1(i^by, ch, col, big);
76 | set1(i^by^1, ch, col, big);
77 | }
78 | }
79 | function populate(i, ch, col, big) {
80 | var l = 12*256 + 16*24/(8*4)*tos;
81 | var p = 0;
82 | var w;
83 | for(var y = 24; --y >= 0; ){
84 | if((y & 1) != 0){
85 | w = read(l++);
86 | w = w << 16 | w >>> 16;
87 | w = w << 8 & 0xff00ff00 | w >> 8 & 0x00ff00ff;
88 | }
89 | for(var x = 16; --x >= 0; ){
90 | if(big){
91 | buf[p] = w >> 31 ? col : 0;
92 | buf[p+1] = w >> 31 ? col : 0;
93 | buf[p+32] = w >> 31 ? col : 0;
94 | buf[p+33] = w >> 31 ? col : 0;
95 | p += 2;
96 | }else{
97 | buf[p++] = w >> 31 ? col : 0;
98 | }
99 | w <<= 1;
100 | }
101 | if(big)
102 | p += 32;
103 | else
104 | p += 16;
105 | }
106 | if(big)
107 | ctx.putImageData(data, sx(i), sy(i));
108 | else
109 | ctx.putImageData(data, sx(i), sy(i), 0, 0, 16, 24);
110 | };
111 | function get(ch, col, big) {
112 | var s = [ch, col, big].toString();
113 | var i = chars[s];
114 | if(i === undefined){
115 | i = big ? lrub.get() : lru.get();
116 | chars[s] = i;
117 | set(i, ch, col, big);
118 | populate(i, ch, col, big);
119 | }
120 | used(i, big);
121 | return i;
122 | }
123 | r.draw = function(targctx, x, y, ch, col, big) {
124 | var i = get(ch, col, big);
125 | if(big)
126 | targctx.drawImage(canvas, sx(i), sy(i), 32, 48, x, y, 32, 48);
127 | else
128 | targctx.drawImage(canvas, sx(i), sy(i), 16, 24, x, y, 16, 24);
129 | };
130 | return r;
131 | })();
132 |
133 | function color() {
134 | fore = tos << 16 & 0xff0000 | tos & 0xff00 | tos >> 16 & 0xff | 0xff << 24;
135 | var s = (tos & 0xffffff).toString(16);
136 | s = "#" + "0".repeat(6 - s.length) + s;
137 | forestr = s;
138 | DROP();
139 | }
140 | builtin("color", color);
141 |
142 | function gfxinit() {
143 | canvas = document.getElementById('canvas');
144 | canvas.addEventListener('keydown', keypressed);
145 | ctx = canvas.getContext('2d');
146 | ctx.imageSmoothingEnabled = false;
147 | fontcache.init();
148 | }
149 |
150 | function $SWITCH() {
151 | ret.push($PAUSE);
152 | }
153 |
154 | function AT() {
155 | xy[0] = tos & 0xffff;
156 | DROP();
157 | xy[1] = tos & 0xffff;
158 | DROP();
159 | }
160 | builtin("at", AT);
161 |
162 | function pAT() {
163 | xy[0] = xy[0] + tos & 0xffff;
164 | DROP();
165 | xy[1] = xy[1] + tos & 0xffff;
166 | DROP();
167 | }
168 | builtin("+at", pAT);
169 |
170 | function xy_() {
171 | DUP_();
172 | tos = xy[0] & 0xffff | xy[1] << 16;
173 | }
174 | builtin("xy", xy_);
175 |
176 | function clip() {
177 | yc = xy[0];
178 | if((yc & 0x8000) != 0) yc = 0;
179 | yc &= 0xffff;
180 | xc = xy[1];
181 | if((xc & 0x8000) != 0) xc = 0;
182 | xc &= 0xffff;
183 | return [yc, xc];
184 | }
185 |
186 | function box() {
187 | var d, x, y;
188 |
189 | d = clip();
190 | y = tos;
191 | DROP();
192 | x = tos;
193 | DROP();
194 | if(y > vp) y = vp;
195 | y -= yc;
196 | if(y < 0) return;
197 | if(x > hp) x = hp;
198 | x -= xc;
199 | if(x < 0) return;
200 | ctx.fillStyle = forestr;
201 | ctx.fillRect(d[1], d[0], x, y);
202 | }
203 | builtin("box", box);
204 |
205 | function line() {
206 | var d, n;
207 |
208 | d = clip();
209 | n = tos;
210 | DROP();
211 | d -= tos;
212 | DROP();
213 | ctx.fillStyle = forestr;
214 | ctx.fillRect(d[1], d[0], x, 1);
215 | xy[0]++;
216 | }
217 | builtin("line", line);
218 |
219 | var iw = 16 + 6;
220 | var ih = 24 + 6;
221 | var hc = hp / iw | 0;
222 | var vc = vp / ih | 0;
223 | var lm = 3;
224 | var rm = hc * iw;
225 | var xycr = 0;
226 |
227 | function emit() {
228 | qcr();
229 | var d = clip();
230 | fontcache.draw(ctx, d[1], d[0], tos, fore, false);
231 | DROP();
232 | xy[1] += iw;
233 | }
234 | builtin("emit", emit);
235 |
236 | function emit2() {
237 | var d = clip();
238 | fontcache.draw(ctx, d[1], d[0], tos, fore, true);
239 | DROP();
240 | xy[1] += iw*2;
241 | }
242 | builtin("2emit", emit2);
243 |
244 | function text1() {
245 | WHITE();
246 | lm = 3;
247 | rm = hc * iw;
248 | xy = [3, lm];
249 | xycr = [3, lm];
250 | }
251 | builtin("text", text1);
252 |
253 | function qcr() {
254 | if(xy[1] >= rm) cr();
255 | }
256 | function cr() {
257 | xy[0] += ih;
258 | xy[1] = lm;
259 | }
260 | builtin("cr", cr);
261 |
262 | function space() {
263 | xy[1] += iw;
264 | }
265 | builtin("space", space);
266 |
267 | function qdot() { if(base != 10) dot(); else dot10(); }
268 | var tens = [ 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 ];
269 | function dot10() {
270 | var d, i;
271 |
272 | d = tos;
273 | if(d < 0){
274 | d = -d;
275 | DUP_();
276 | tos = 0o43;
277 | emit();
278 | }
279 | for(i = 8; i >= 0; i--){
280 | tos = d / tens[i] | 0;
281 | d %= tens[i];
282 | if(tos != 0)
283 | break;
284 | }
285 | if(i >= 0){
286 | eDIG1();
287 | while(--i >= 0){
288 | tos = d / tens[i] | 0;
289 | d %= tens[i];
290 | eDIG1();
291 | }
292 | }
293 | tos = d;
294 | eDIG1();
295 | space();
296 | DROP();
297 | }
298 | builtin(".", dot10);
299 |
300 | var hicon = [
301 | 0o30, 0o31, 0o32, 0o33, 0o34, 0o35, 0o36, 0o37,
302 | 0o40, 0o41, 0o05, 0o23, 0o12, 0o20, 0o04, 0o16
303 | ];
304 |
305 | function eDIG1() { DUP_(); eDIG(); }
306 | function eDIG() {
307 | tos = hicon[tos];
308 | emit();
309 | }
310 | builtin("digit", eDIG);
311 | function oDIG() {
312 | tos = tos << 4 | tos >>> 28;
313 | DUP_();
314 | tos &= 0xf;
315 | return tos;
316 | }
317 | function dot() {
318 | var i;
319 |
320 | for(i = 7; i > 0; i--){
321 | if(oDIG())
322 | break;
323 | DROP();
324 | }
325 | if(i <= 0)
326 | oDIG();
327 | i++;
328 | for(;;){
329 | eDIG();
330 | if(--i <= 0) break;
331 | oDIG();
332 | }
333 | space();
334 | DROP();
335 | return;
336 | }
337 | function hdotn() {
338 | var n = tos;
339 | DROP();
340 | tos = tos << 32 - n * 4 | tos >>> n * 4;
341 | for(; n > 0; n--){
342 | oDIG();
343 | eDIG();
344 | }
345 | DROP();
346 | }
347 | builtin("h.n", hdotn);
348 | function hdot() {
349 | for(var i = 8; i > 0; i--){
350 | oDIG();
351 | eDIG();
352 | }
353 | DROP();
354 | }
355 | builtin("h.", hdot);
356 |
357 | function keyboard() {
358 | text1();
359 | DUP_();
360 | tos = keyc;
361 | color();
362 | rm = hc * iw;
363 | lm = hp - 9 * iw + 3;
364 | xy = [vp-4*ih+3, hp-9*iw+3];
365 | var k = 0;
366 | for(var i = 0; i < 3; i++){
367 | k += 12;
368 | for(var j = 0; j < 4; j++){
369 | DUP_();
370 | tos = board[k++];
371 | emit();
372 | }
373 | space();
374 | k -= 16;
375 | for(var j = 0; j < 4; j++){
376 | DUP_();
377 | tos = board[k++];
378 | emit();
379 | }
380 | }
381 | cr();
382 | xy[1] += 4 * iw;
383 | var k = 4;
384 | for(var j = 0; j < 3; j++){
385 | DUP_();
386 | tos = shift[k++];
387 | emit();
388 | }
389 | lm = 3;
390 | xy[1] = 3;
391 | for(var i = 0; i < god_data.length - 1; i++){
392 | DUP_();
393 | tos = god_data[i];
394 | qdot();
395 | }
396 | xy[1] = hp - (11 + 9) * iw + 3;
397 | for(var j = 0; j < 11; j++){
398 | DUP_();
399 | tos = history_[j];
400 | emit();
401 | }
402 | }
403 | builtin("keyboard", keyboard);
404 |
405 | function $pad() {
406 | board = [];
407 | var t = tos + 28 * 2;
408 | var v = dict[t];
409 | shift = [nul, nul, nul, nul, v&0xff, v>>8&0xff, v>>16&0xff, v>>24&0xff];
410 | t++;
411 | for(var i = 0; i < 28; i++)
412 | board.push(dict[t + (i>>2)] >> ((i & 3) << 3) & 0xff);
413 | t = tos + 1;
414 | DROP();
415 | function loop(){
416 | ret.push(() => {
417 | let n = dict[t + 2*tos];
418 | DROP();
419 | ret.push(loop);
420 | ret.push(forth2[n]);
421 | });
422 | ret.push($KEY);
423 | }
424 | ret.push(loop);
425 | }
426 | var pad_fn = forth2.length;
427 | builtin(".pad", $pad);
428 |
429 | function mpad() {
430 | dict[here] = INS_DUP;
431 | dict[here+1] = INS_SETTOS;
432 | dict[here+2] = here + 6;
433 | dict[here+3] = INS_FORTH;
434 | dict[here+4] = pad_fn;
435 | dict[here+5] = INS_SEMI;
436 | here += 6;
437 | }
438 | builtin_macro("pad", mpad);
439 |
440 | var yellow = 0xffff00;
441 | function WHITE() { DUP_(); tos = 0xffffff; color(); }
442 | function CYAN() { DUP_(); tos = 0xffff; color(); }
443 | function MAGENTA() { DUP_(); tos = 0xff00ff; color(); }
444 | function SILVER() { DUP_(); tos = 0xc0c0c0; color(); }
445 | function BLUE() { DUP_(); tos = 0x4040ff; color(); }
446 | function RED() { DUP_(); tos = 0xff0000; color(); }
447 | function GREEN() { DUP_(); tos = 0x8000ff00; color(); }
448 | var keyc = yellow;
449 |
--------------------------------------------------------------------------------
/init.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | ( white words )
4 | [ yellow words ]
5 | [[ cyan words ]]
6 | : redword
7 | & magentaword 12345
8 |
9 | #16 switch block
10 | $2A hex constant
11 | \0 number as text word (not number)
12 | \: colon as word (not define)
13 | =expr replaced with eval("expr")
14 | */
15 |
16 | var forth = `
17 | #18
18 | ( jscolorforth )
19 | [ 24 load 26 load 28 load 30 load ]
20 | : dump 32 load ;
21 | : icons 34 load ;
22 | : pi 40 load ;
23 | : colors 56 load ;
24 | [ mark empty ]
25 | #24
26 | ( Wordcode ) [ macro ]
27 | : t! =INS_TBANG , , [[ drop ]] ;
28 | : t@ [[ ?dup ]] =INS_TAT , , ;
29 | : swap 0 [[ t! ]] 1 [[ t! ]] 0 [[ t@ ]] 1 [[ t@ ]] ;
30 | : if =INS_JNO , $0 , here ;
31 | : 2* =INS_LSH , ;
32 | : 2/ =INS_ASR , ;
33 | : @ =INS_AT , ;
34 | : ! =INS_BANG , [[ drop drop ]] ;
35 | : nip =INS_NIP , ;
36 | : + =INS_ADD , ;
37 | : or =INS_OR , ;
38 | : and =INS_AND , ;
39 | : u+ =INS_UPLUS , [[ drop ]] ;
40 | : ? =INS_TEST , [[ drop ]] ;
41 | : less =INS_LESS , ;
42 | : over [[ ?dup ]] =INS_OVER , ;
43 | : push =INS_PUSH , [[ drop ]] ;
44 | : pop [[ ?dup ]] =INS_POP , ;
45 | : - =INS_NOT , ;
46 | #25
47 | ( Wordcode macros: , compiles 1 word )
48 | : t! ( set temporary )
49 | : t@ ( read temporary )
50 | : if ( uses global flag )
51 | : then ( fix address - in kernel )
52 | : u+ ( add to 2nd number )
53 | #26
54 | ( macros )
55 | : for [[ push begin ]] ;
56 | : next =INS_NEXT , , ;
57 | : -next =INS_0NEXT , , ;
58 | : i [[ ?dup ]] =INS_POP , =INS_PUSH , ;
59 | : +! =INS_TBANG , 0 , [[ @ + ]] 0 [[ t@ ! ]] ;
60 | : or! =INS_TBANG , 0 , [[ @ or ]] 0 [[ t@ ! ]] ;
61 | : nop =INS_NOP , ;
62 | : * =INS_MUL , ;
63 | : */ =INS_MULDIV , [[ nip nip ]] ;
64 | : / =INS_DIV , ;
65 | : mod =INS_MOD , ;
66 | : /mod [[ over over mod ]] 0 [[ t! / ]] 0 [[ t@ ]] ;
67 | #27
68 | #28
69 | ( Compiled macros )
70 | [ forth ]
71 | : @ @ ;
72 | : ! ! ;
73 | : + + ;
74 | : */ */ ;
75 | : * * ;
76 | : / / ;
77 | : 2* 2* ;
78 | : 2/ 2/ ;
79 | : dup dup ; ( Arithmetic )
80 | : negate - 1 + ;
81 | : min less if drop ; then swap drop ;
82 | : abs dup negate
83 | : max less if swap then drop ;
84 | : v+ ( vv-v ) push u+ pop + ;
85 | : writes ( acn ) for write next drop drop ;
86 | : reads ( acn ) for read next drop drop ;
87 | : rest 0 dup nc reads ;
88 | : oadf ( qwerty )
89 | : save 0 dup nc writes ;
90 | #29
91 | ( These macros may be white, others may not )
92 | : @ etc ( Arithmetic )
93 | : negate n-n ( when you just cant use ) -
94 | : min nn-n ( minimum )
95 | : abs n-u ( absolute value )
96 | : max nn-n ( maximum )
97 | : v+ vv-v ( add 2-vectors )
98 | : nc -a ( number of cylinders booted )
99 | : save ( write colorforth to bootable floppy )
100 | : oadf ( save as spelled by qwerty. For typing with blank screen )
101 | #30
102 | ( Colors etc )
103 | : block $100 * ;
104 | : white $ffffff color ;
105 | : red $ff0000 color ;
106 | : green $ff00 color ;
107 | : blue $ff color ;
108 | : silver $bfbfbf color ;
109 | : black 0 color ;
110 | : screen 0 dup at 1024 768 box ;
111 | : 5* 5 for 2emit next ;
112 | : cf 25 dup at red $1 $3 $c $3 $a 5* green $14 $2 $1 $3 $3e 5* ;
113 | : logo show black screen 800 710 blue box 600 50 at 1024 620 red box 200 100 at 700 500 green box text cf keyboard ;
114 | : empty empt logo ;
115 | #31
116 |
117 | : block n-a ( block number to word address )
118 | : colors ( specified as rgb: 888 )
119 | : screen ( fills screen with current color )
120 | : at xy ( set current screen position )
121 | : box xy ( lower-right of colored rectangle )
122 | : dump ( compiles memory display )
123 | : print ( compiles screen print )
124 | : icon ( compiles icon editor )
125 | : logo ( displays colorforth logo )
126 | : show ( background task executes following code repeatedly )
127 | : keyboard ( displays keypad and stack )
128 | #32
129 | ( Dump ) & x 2097152 & y 2101760
130 | : one dup @ h. space dup h. cr ;
131 | : lines for one 4294967295 + next drop ;
132 | : dump x !
133 | : r show black screen x @ 15 + 16 text lines keyboard ;
134 | : it @ + @ dup h. space ;
135 | : lines for white i [ x ] it i [ y ] it or drop if red then i . cr -next ;
136 | : cmp show blue screen text 19 lines red [ x ] @ h. space [ y ] @ h. keyboard ;
137 | : u 16
138 | : +xy dup [ x ] +! [ y ] +! ;
139 | : d 4294967280 +xy ;
140 | : byte 4 / dump ;
141 | : fix for 0 over ! 1 + next ; [ dump ]
142 | #33
143 | ( Does not say empty, compiles on top of application )
144 | : x -a ( current address )
145 | : one a-a ( line of display )
146 | : lines an
147 | : dump a ( background task continually displays memory )
148 | : u ( increment address )
149 | : d ( decrement )
150 | : byte a ( byte address dump )
151 | : fix an-a ( test word )
152 | #34
153 | ( Icons ) [ empty macro ]
154 | ( @w !w *byte )
155 | [ forth ] & ic 0 & cu 351
156 | : sq xy $10000 /mod 16 + swap 16 + box 17 0 +at ;
157 | : loc [ ic ] @ [ 16 24 8 */ ] * [ 12 block 4 * ] + ;
158 | : 0/1 $8000 ? if green sq ; then blue sq ;
159 | : row dup @w *byte 16 for 0/1 2* next drop [ 4294967279 16 * ] 17 +at ;
160 | : ikon loc 24 for row 2 + next drop ;
161 | : adj 17 * swap ;
162 | : cursor [ cu ] @ 16 /mod adj adj over over at red 52 u+ 52 + box ;
163 | : ok show black screen cursor 18 dup at ikon text [ ic ] @ . keyboard ; [ 36 load ok h ]
164 | #35
165 | ( Draw big-bits icon )
166 | : @w a-n ( fetch 16-bit word from byte address )
167 | : !w na ( store same )
168 | : *byte n-n ( swap bytes )
169 | : ic -a ( current icon )
170 | : cu -a ( cursor )
171 | : sq ( draw small square )
172 | : xy -a ( current screen position, set by ) at
173 | : loc -a ( location of current icons bit-map )
174 | : 0/1 n-n ( color square depending on bit 15 )
175 | : row a-a ( draw row of icon )
176 | : +at nn ( relative change to screen position )
177 | : ikon ( draw big-bits icon )
178 | : adj nn-nn ( magnify cursor position )
179 | : cursor ( draw red box for cursor )
180 | : ok ( background task to continually draw icon, icon number at top )
181 | #36
182 | ( Edit )
183 | : +ic 1 [ ic ] +! ;
184 | : -ic [ ic ] @ 4294967295 + 0 max [ ic ] ! ;
185 | : bit [ cu ] @ 2/ 2/ 2/ 2/ 2* loc + $10000 [ cu ] @ $f and 1 + for 2/ next *byte ;
186 | : toggle bit over @w or swap !w ;
187 | : td toggle
188 | : d 16
189 | : wrap [ cu ] @ + [ 16 24 * ] dup u+ /mod drop [ cu ] ! ;
190 | : tu toggle
191 | : u 4294967280 wrap ;
192 | : tr toggle
193 | : r 1 wrap ;
194 | : tl toggle
195 | : l 4294967295 wrap ;
196 | : nul ;
197 | : h pad nul nul accept nul tl tu td tr l u d r -ic nul nul +ic nul nul nul nul nul nul nul nul nul nul nul nul [ $2500 , $110160c dup , , $2b000023 , 0 , 0 , 0 , ]
198 | #37
199 | ( Edit icon )
200 | #38
201 | #40
202 | ( Calculate Pi )
203 | & c 0
204 | & b 0
205 | : a 64 256 * ;
206 | : init c @ 4294967295 + for 2000 a i + ! -next ;
207 | : g b @ 2* 4294967295 + ;
208 | : d1 b @ * b @ a + @ 10000 * + ;
209 | : si b @ for i b ! d1 g /mod b @ a + ! next ;
210 | : o1 c @ 4294967282 + dup c ! 4294967295 + b ! 10000 mod dup ;
211 | : o2 10000 /mod push + . drop pop ;
212 | : loop c @ 15 less drop drop if ; then o1 si o2 loop ;
213 | : show0 show nop ;
214 | : ok show0 black screen text init 0 loop key empty ;
215 | [ 200 14 * c ! ok ]
216 | #42
217 | #44
218 | #45
219 | #46
220 | #48
221 | ( ASCII ) [ macro ]
222 | ( 1@ ) [ forth ]
223 | : string pop ;
224 | : cf-ii string [ $6f747200 , $696e6165 , $79636d73 , $7766676c , $62707664 , $71757868 , $336a7a6b , $37363534 , $2d313938 , $2f322e30 , $2b213a3b , $3f2c2a40 , ]
225 | : ch $fffffff0 and unpack [ cf-ii ] + 1@ $ff and ;
226 | : ii-cf string [ $2a00 , 0 , $2b2d0000 , $2725232e , $1b262224 , $1f1e1d1c , $28292120 , $2f000000 , $3a43355c , $3d3e3440 , $484a3744 , $3336393c , $38314742 , $3f414632 , $493b45 , 0 , $a13052c , $d0e0410 , $181a0714 , $306090c , $8011712 , $f111602 , $190b15 , ]
227 | : chc $ffffffe0 + [ ii-cf ] + 1@ $ff and ;
228 | #50
229 | ( Clock ) [ macro ]
230 | ( p@ )
231 | ( p! ) [ forth ]
232 | : ca $70 a! p! $71 a! ;
233 | : c@ ca 0 p@ ;
234 | : c! ca p! ;
235 | : hi 10 c@ $80 and drop if ; then hi ;
236 | : lo 0 p@ $80 and drop if lo ; then ;
237 | : bcd c@ 16 /mod 10 * + ;
238 | : hms0 4 bcd 100 * 2 bcd + 100 * 0 bcd + ;
239 | : hms hms0 2 ms dup hms0 or drop if drop hms ; then ;
240 | : ymd 9 bcd 100 * 8 bcd + 100 * 7 bcd + ;
241 | : day 6 c@ 4294967295 + ;
242 | : cal hi lo time - hi lo time + ( 748 ) ;
243 | #52
244 | #54
245 | #55
246 | #56
247 | ( Hexagon ) [ empty ] & col 0 & del 2105376
248 | : lin dup 2/ 2/ dup 2* line ;
249 | : hex xy 7 and over 2/ for lin 7 + next over for lin next swap 2/ for 4294967289 + lin next drop ;
250 | : +del [ del ] @ nop
251 | : petal and [ col ] @ + $f8f8f8 and color 100 hex ;
252 | : -del [ del ] @ $f8f8f8 or $80808 + ;
253 | : rose 0 +del 4294967120 4294967096 +at $f80000 -del petal 352 4294967096 +at $f80000 +del 4294967032 4294966947 +at $f800 -del petal 176 4294967096 +at $f8 +del 4294967120 98 +at $f8 -del petal 176 4294967096 +at $f800 +del ;
254 | : ok show black screen 512 282 at rose text [ col ] @ h. space [ del ] @ $ff and . keyboard ; [ 58 load ok h ]
255 | #57
256 | ( Draws 7 hexagons. Colors differ along red, green and blue axes. )
257 | : col ( color of center hexagon )
258 | : del ( color difference )
259 | : lin n ( draws 1 horizontal line of a hexagon )
260 | : hex n ( draws top, center and bottom. Slope 7 x to 4 y is 1.750 compared to 1.732 )
261 | : +del n ( increment color )
262 | : -del n
263 | : petal n ( draw colored hexagon )
264 | : rose ( draw 7 hexagons )
265 | : ok ( describe screen. Center color at top )
266 | #58
267 | ( Pan )
268 | : in [ del ] @ 2* $404040 min [ del ] ! ;
269 | : out [ del ] @ 2/ $80808 max [ del ] ! ;
270 | : r $f80000
271 | : +del [ del ] @
272 | : +col and [ col ] @ + $f8f8f8 and [ col ] ! ;
273 | : g $f800 +del ;
274 | : b $f8 +del ;
275 | : -r $f80000 -del +col ;
276 | : -g $f800 -del +col ;
277 | : -b $f8 -del +col ;
278 | : nul ;
279 | : h pad nul nul accept nul -r -g -b nul r g b nul out nul nul in nul nul nul nul nul nul nul nul nul nul nul nul [ $250000 , $130d01 dup , , $2b000023 , 0 , 0 , 0 , ]
280 | #59
281 | : in ( increment color difference )
282 | : out ( decrement it )
283 | : r
284 | : g
285 | : b ( increment center color )
286 | : -r
287 | : -g
288 | : -b ( decrement it )
289 | : +del ( redefine with ; )
290 | : +col ( change center color )
291 | : nul ( ignore )
292 | : h ( describe keypad )
293 | #62
294 | ( Timing ) [ empty macro ]
295 | ( out ) [ forth ]
296 | : tare time - 1000 for next time + ;
297 | : tare+ time - push 1000 for dup next c pop time + ;
298 | : test tare time + - 1000 for out next time + ; ( next 3 loop 5.7 /next 2 /swap 25 swap 7.2 ) [ macro ]
299 | : c! $c88b 2, [[ drop ]] here ;
300 | : loop $49 1, $75 1, ( e2 ) here - + 1, ; [ forth ]
301 | : try time - 1000 c! loop time + ;
302 | `;
303 |
304 | function ctz(n) {
305 | var k;
306 | for(k = 0; (n & 1) == 0; k++)
307 | n >>= 1;
308 | return k;
309 | }
310 |
311 | function dechuck(w){
312 | var s, c;
313 |
314 | s = '';
315 | for(;;){
316 | if(w>>31 == 0){
317 | c = w >> 28 & 7;
318 | w <<= 4;
319 | if(c == 0)
320 | return s;
321 | s += ' rtoeani'[c];
322 | }else if((w >> 30 & 3) == 2){
323 | c = w >> 27 & 7;
324 | w <<= 5;
325 | s += 'smcylgfw'[c];
326 | }else{
327 | c = w >> 25 & 31;
328 | w <<= 7;
329 | s += 'dvpbhxuq0123456789j-k.z/;:!+@*,?'[c];
330 | }
331 | }
332 | }
333 |
334 | function do_comment(w) {
335 | if(w[0] == '\\') w = w.substr(1);
336 | var r = enchuck(w.toLowerCase());
337 | if(w.match(/^[a-z0-9\-./;:!+@*,?]+$/))
338 | r[0] |= 9;
339 | else if(w.match(/^[A-Z0-9\-./;:!+@*,?]+$/))
340 | r[0] |= 11;
341 | else if(w.match(/^[A-Z0-9\-./;:!+@*,?][a-z0-9\-./;:!+@*,?]+$/))
342 | r[0] |= 10;
343 | else
344 | throw 'invalid comment word ' + w;
345 | return r;
346 | }
347 |
348 | function do_number(w, hex, execute, magenta) {
349 | if(magenta)
350 | return [w];
351 | if(w >> 26 == 0 || w >> 26 == -1)
352 | return [w << 5 | hex << 4 | (execute ? 8 : 6)];
353 | else
354 | return [hex << 4 | (execute ? 2 : 5), w];
355 | }
356 |
357 | function do_word(w, execute, cyan, next) {
358 | var r = enchuck(w);
359 | if(next == 'red')
360 | r[0] |= 3;
361 | else if(next == 'magenta')
362 | r[0] |= 12;
363 | else if(execute)
364 | r[0] |= 1;
365 | else if(cyan)
366 | r[0] |= 7;
367 | else
368 | r[0] |= 4;
369 | return r;
370 | }
371 |
372 | function assemble(src, single) {
373 | var words = src.split(/[ \t\n]+/);
374 | var blocks = {};
375 | var cur = 0;
376 | var comment = false;
377 | var execute = false;
378 | var cyan = false;
379 | var next = '';
380 | if(single) blocks[cur] = [];
381 | for(var i = 0; i < words.length; i++){
382 | var w = words[i];
383 | var r = [];
384 | if(w == '') continue;
385 | if(w[0] == '=' && !single)
386 | w = eval(w.substring(1)).toString();
387 | if(w[0] == '%')
388 | r = [Number.parseInt(w.substring(1), 16)];
389 | else if(w[0] == '#' && !single){
390 | cur = parseInt(w.substring(1));
391 | if(!(cur in blocks))
392 | blocks[cur] = [];
393 | }else if(w == '(')
394 | comment = true;
395 | else if(comment){
396 | if(w == ')')
397 | comment = false;
398 | else
399 | r = do_comment(w);
400 | }else if(w == '['){
401 | if(execute || next != '') throw "syntax error";
402 | execute = true;
403 | }else if(w == ']'){
404 | if(!execute || next != '') throw "syntax error";
405 | execute = false;
406 | }else if(w == '[['){
407 | if(cyan || next != '') throw "syntax error";
408 | cyan = true;
409 | }else if(w == ']]'){
410 | if(!cyan || next != '') throw "syntax error";
411 | cyan = false;
412 | }else if(w == ':'){
413 | if(execute || cyan || next != '') throw "syntax error";
414 | next = 'red';
415 | }else if(w == '&'){
416 | if(execute || cyan || next != '') throw "syntax error";
417 | next = 'magenta';
418 | }else if(w[0] == '\\'){
419 | if(next == 'magenta-num') throw "syntax error";
420 | r = do_word(w.substring(1), execute, cyan, next);
421 | if(next == 'magenta')
422 | next = 'magenta-num';
423 | else
424 | next = '';
425 | }else if(w.match(/^\$[0-9a-fA-F]+$/)){
426 | if(cyan || (next != '' && next != 'magenta-num')) throw "syntax error";
427 | r = do_number(parseInt(w.substring(1), 16), true, execute, next == 'magenta-num');
428 | next = '';
429 | }else if(w.match(/^[0-9]+$/)){
430 | if(cyan || (next != '' && next != 'magenta-num')) throw "syntax error";
431 | r = do_number(parseInt(w), false, execute, next == 'magenta-num');
432 | next = '';
433 | }else{
434 | if(next == 'magenta-num') throw "syntax error";
435 | r = do_word(w, execute, cyan, next);
436 | if(next == 'magenta')
437 | next = 'magenta-num';
438 | else
439 | next = '';
440 | }
441 | blocks[cur].push.apply(blocks[cur], r);
442 | }
443 | if(single){
444 | var r = new Uint32Array(256);
445 | if(0 in blocks)
446 | r.set(blocks[0]);
447 | return r;
448 | }
449 | var r = new Uint32Array(256 * 128);
450 | for(var i = 0; i < 128; i++){
451 | var b = blocks[i];
452 | if(b !== undefined)
453 | r.set(b, i * 256);
454 | }
455 | return r;
456 | }
457 |
458 | function output(file, b){
459 | const fs = require('fs');
460 | var f = fs.createWriteStream('out.bin', {options: 'wb'});
461 | for(var i = 0; i < 63; i++){
462 | f.write(Buffer.from(b[i].buffer));
463 | }
464 | f.end();
465 | }
466 |
--------------------------------------------------------------------------------
/orig/forth.txt:
--------------------------------------------------------------------------------
1 | #18
2 | ( colorforth Jul31 Chuck Moore Public Domain ) [ 24 load 26 load 28 load 30 load ]
3 | : dump 32 load ;
4 | : icons 34 load ;
5 | : print 38 load ;
6 | : file 44 load ;
7 | : north 46 load ;
8 | : colors 56 load ; [ mark empty ]
9 | #19
10 | #20
11 | #21
12 | #22
13 | #23
14 | #24
15 | [ macro ]
16 | : swap $168b 2, $c28b0689 , ;
17 | : $$0 [[ ?dup ]] $c031 2, ;
18 | : if $74 2, here ;
19 | : -if $79 2, here ;
20 | : a [[ ?dup ]] $c28b 2, ;
21 | : a! ?lit if $ba 1, , ; then $d08b 2, [[ drop ]] ;
22 | : 2* $e0d1 2, ;
23 | : a, 2* 2* , ;
24 | : @ ?lit if [[ ?dup ]] $58b 2, [[ a, ]] ; then $85048b 3, $$0 , ;
25 | : ! ?lit if ?lit if $5c7 2, swap [[ a, ]] , ; then $589 2, [[ a, drop ]] ; then [[ a! ]] $950489 3, $$0 , [[ drop ]] ;
26 | : nip $4768d 3, ;
27 | : + ?lit if $5 1, , ; then $603 2, [[ nip ]] ;
28 | : or $633
29 | : binary ?lit if swap 2 + 1, , ; then 2, [[ nip ]] ;
30 | : and $623 [[ binary ]] ;
31 | : u+ ?lit if $681 2, , ; then $44601 3, [[ drop ]] ;
32 | : ? ?lit $a9 1, , ;
33 | #25
34 | ( Pentium macros: 1, 2, 3, , compile 1-4 bytes )
35 | : drop ( lodsd, flags unchanged, why sp is in ESI )
36 | : over ( sp 4 + @ )
37 | : swap ( sp xchg )
38 | : $$0 ( 0 0 xor, macro 0 identical to number 0 )
39 | : a ( 2 0 mov, never used? )
40 | : a! ( 0 2 mov, unoptimized )
41 | : @ ( EAX 4 *, unoptimized )
42 | : ! ( EDX 4 * )
43 | : nop ( used to thwart look-back optimization )
44 | : - ( ones-complement )
45 | : 2*
46 | : 2/
47 | : if ( jz, flags set, max 127 bytes, leave address )
48 | : -if ( jns, same )
49 | : then ( fix address - in kernel )
50 | : push ( EAX push )
51 | : pop ( EAX pop )
52 | : u+ ( add to 2nd number, literal or value )
53 | : ? ( test bits, set flags, literal only! )
54 | #26
55 | ( macros )
56 | : over [[ ?dup ]] $4468b 3, ;
57 | : push $50 1, [[ drop ]] ;
58 | : pop [[ ?dup ]] $58 1, ;
59 | : - $d0f7 2, ;
60 | : for [[ push begin ]] ;
61 | : *next swap
62 | : next $75240cff
63 | : 0next , here - + 1, $4c483 3, ;
64 | : -next $79240cff [[ 0next ]] ;
65 | : i [[ ?dup ]] $24048b 3, ;
66 | : *end swap
67 | : end $eb 1, here - + 1, ;
68 | : +! ?lit if ?lit if $581 2, swap [[ a, ]] , ; then $501 2, [[ a, drop ]] ; then [[ a! ]] $950401 3, $$0 , [[ drop ]] ;
69 | : nop $90 1, ;
70 | : align here - 3 and drop if [[ nop align ]] ; then ;
71 | : or! [[ a! ]] $950409 3, $$0 , [[ drop ]] ;
72 | : * $6af0f 3, [[ nip ]] ;
73 | : */ $c88b 2, [[ drop ]] $f9f72ef7 , [[ nip ]] ;
74 | : /mod [[ swap ]] $99 1, $16893ef7 , ;
75 | : / [[ /mod nip ]] ;
76 | : mod [[ /mod drop ]] ;
77 | #27
78 |
79 | : for n ( push count onto return stack, falls into ) begin
80 | : begin -a ( current code address - byte )
81 | : *next aa-aa ( swap ) for ( and ) if ( addresses )
82 | : next a ( decrement count, jnz to ) for, ( pop return stack when done )
83 | : -next a ( same, jns - loop includes 0 )
84 | : i -n ( copy loop index to data stack )
85 | : end a ( jmp to ) begin
86 | : +! na ( add to memory, 2 literals optimized )
87 | : align ( next call to end on word boundary )
88 | : or! na ( inclusive-or to memory, unoptimized )
89 | : * mm-p ( 32-bit product )
90 | : */ mnd-q ( 64-bit product, then quotient )
91 | : /mod nd-rq ( remainder and quotient )
92 | : / nd-q ( quotient )
93 | : mod nd-r ( remainder )
94 | : time -n ( Pentium cycle counter, calibrate to get actual clock rate )
95 | #28
96 | ( Compiled macros )
97 | : 2/ $f8d1 2, ;
98 | : time [[ ?dup ]] $310f 2, ; [ forth ]
99 | : @ @ ;
100 | : ! ! ;
101 | : + + ;
102 | : */ */ ;
103 | : * * ;
104 | : / / ;
105 | : 2/ 2/ ;
106 | : dup dup ; ( Arithmetic )
107 | : negate - 1 + ;
108 | : min less if drop ; then swap drop ;
109 | : abs dup negate
110 | : max less if swap then drop ;
111 | : v+ ( vv-v ) push u+ pop + ;
112 | : writes ( acn ) for write next drop drop ;
113 | : reads ( acn ) for read next drop drop ;
114 | : oadf ( qwerty )
115 | : save 0 dup [ nc ] @ writes stop ;
116 | #29
117 | ( These macros may be white, others may not )
118 | : @ etc ( Arithmetic )
119 | : negate n-n ( when you just cant use ) -
120 | : min nn-n ( minimum )
121 | : abs n-u ( absolute value )
122 | : max nn-n ( maximum )
123 | : v+ vv-v ( add 2-vectors )
124 | : nc -a ( number of cylinders booted )
125 | : save ( write colorforth to bootable floppy )
126 | : oadf ( save as spelled by qwerty. For typing with blank screen )
127 | #30
128 | ( Colors etc )
129 | : block $100 * ;
130 | : white $ffffff color ;
131 | : red $ff0000 color ;
132 | : green $ff00 color ;
133 | : blue $ff color ;
134 | : silver $bfbfbf color ;
135 | : black 0 color ;
136 | : screen 0 dup at 1024 768 box ;
137 | : 5* 5 for 2emit next ;
138 | : cf 25 dup at red $1 $3 $c $3 $a 5* green $14 $2 $1 $3 $3e 5* ;
139 | : logo show black screen 800 710 blue box 600 50 at 1024 620 red box 200 100 at 700 500 green box text cf keyboard ;
140 | : empty empt logo ;
141 | #31
142 |
143 | : block n-a ( block number to word address )
144 | : colors ( specified as rgb: 888 )
145 | : screen ( fills screen with current color )
146 | : at xy ( set current screen position )
147 | : box xy ( lower-right of colored rectangle )
148 | : dump ( compiles memory display )
149 | : print ( compiles screen print )
150 | : icon ( compiles icon editor )
151 | : logo ( displays colorforth logo )
152 | : show ( background task executes following code repeatedly )
153 | : keyboard ( displays keypad and stack )
154 | #32
155 | ( Dump ) & x 2097152 & y 2101760
156 | : one dup @ h. space dup h. cr ;
157 | : lines for one 4294967295 + next drop ;
158 | : dump x !
159 | : r show black screen x @ 15 + 16 text lines keyboard ;
160 | : it @ + @ dup h. space ;
161 | : lines for white i [ x ] it i [ y ] it or drop if red then i . cr -next ;
162 | : cmp show blue screen text 19 lines red [ x ] @ h. space [ y ] @ h. keyboard ;
163 | : u 16
164 | : +xy dup [ x ] +! [ y ] +! ;
165 | : d 4294967280 +xy ;
166 | : ati $f4100000 ( ff7fc000 ) or
167 | : byte 4 / dump ;
168 | : fix for 0 over ! 1 + next ; [ dump ]
169 | #33
170 | ( Does not say empty, compiles on top of application )
171 | : x -a ( current address )
172 | : one a-a ( line of display )
173 | : lines an
174 | : dump a ( background task continually displays memory )
175 | : u ( increment address )
176 | : d ( decrement )
177 | : ati ( address of AGP graphic registers )
178 | : byte a ( byte address dump )
179 | : fix an-a ( test word )
180 | #34
181 | ( Icons ) [ empty macro ]
182 | : @w $8b66 3, ;
183 | : !w [[ a! ]] $28966 3, [[ drop ]] ;
184 | : *byte $c486 2, ; [ forth ] & ic 0 & cu 351
185 | : sq [ xy ] @ $10000 /mod 16 + swap 16 + box 17 0 +at ;
186 | : loc [ ic ] @ [ 16 24 8 */ ] * [ 12 block 4 * ] + ;
187 | : 0/1 $8000 ? if green sq ; then blue sq ;
188 | : row dup @w *byte 16 for 0/1 2* next drop [ 4294967279 16 * ] 17 +at ;
189 | : ikon loc 24 for row 2 + next drop ;
190 | : adj 17 * swap ;
191 | : cursor [ cu ] @ 16 /mod adj adj over over at red 52 u+ 52 + box ;
192 | : ok show black screen cursor 18 dup at ikon text [ ic ] @ . keyboard ; [ 36 load ok h ]
193 | #35
194 | ( Draw big-bits icon )
195 | : @w a-n ( fetch 16-bit word from byte address )
196 | : !w na ( store same )
197 | : *byte n-n ( swap bytes )
198 | : ic -a ( current icon )
199 | : cu -a ( cursor )
200 | : sq ( draw small square )
201 | : xy -a ( current screen position, set by ) at
202 | : loc -a ( location of current icons bit-map )
203 | : 0/1 n-n ( color square depending on bit 15 )
204 | : row a-a ( draw row of icon )
205 | : +at nn ( relative change to screen position )
206 | : ikon ( draw big-bits icon )
207 | : adj nn-nn ( magnify cursor position )
208 | : cursor ( draw red box for cursor )
209 | : ok ( background task to continually draw icon, icon number at top )
210 | #36
211 | ( Edit )
212 | : +ic 1 [ ic ] +! ;
213 | : -ic [ ic ] @ 4294967295 + 0 max [ ic ] ! ;
214 | : bit [ cu ] @ 2/ 2/ 2/ 2/ 2* loc + $10000 [ cu ] @ $f and 1 + for 2/ next *byte ;
215 | : toggle bit over @w or swap !w ;
216 | : td toggle
217 | : d 16
218 | : wrap [ cu ] @ + [ 16 24 * ] dup u+ /mod drop [ cu ] ! ;
219 | : tu toggle
220 | : u 4294967280 wrap ;
221 | : tr toggle
222 | : r 1 wrap ;
223 | : tl toggle
224 | : l 4294967295 wrap ;
225 | : nul ;
226 | : h pad nul nul accept nul tl tu td tr l u d r -ic nul nul +ic nul nul nul nul nul nul nul nul nul nul nul nul [ $2500 , $110160c dup , , $2b000023 , 0 , 0 , 0 , ]
227 | #37
228 | ( Edit icon )
229 | #38
230 | ( PNG ) [ empty ] & w 54 & h 32 & d 4
231 | : frame $1e80000 ; [ file 42 load 40 load ]
232 | : -crc ( a ) here over negate + crc . ;
233 | : crc -crc ;
234 | : wd ( -a ) here 3 and drop if 0 1, wd ; then here 2 2/s ;
235 | : bys ( n-a ) . here swap , ;
236 | : plte $45544c50 48 bys $0 3, $ff0000 3, $ff00 3, $ffff00 3, $ff 3, $ff00ff 3, $ffff 3, $ffffff 3, $0 3, $c00000 3, $c000 3, $c0c000 3, $c0 3, $c000c0 3, $c0c0 3, $c0c0c0 3, crc ;
237 | : png ( awh ) [ d ] @ / [ h ] ! [ d ] @ / [ w ] ! wd swap $474e5089 , $a1a0a0d , ( ihdr ) $52444849 13 bys [ w ] @ . [ h ] @ . $304 , $0 1, crc plte ( idat ) $54414449 0 bys swap deflate crc ( iend ) $444e4549 0 bys crc wd over negate + ;
238 | : at 1024 * + 2* [ frame ] + ;
239 | : full 4 [ d ] ! 0 dup at 1024 768 png ;
240 | : pad 1 [ d ] ! [ 46 4294967287 + 22 * ] nop [ 25 4294967292 + 30 * ] at [ 9 22 * ] nop [ 4 30 * ] png ;
241 | #39
242 | #40
243 | ( lz77 ) [ macro ]
244 | : @w $8b66 3, ;
245 | : *byte $c486 2, ;
246 | : !b [[ a! ]] $289 2, [[ drop ]] ; [ forth ]
247 | : *bys dup 16 2/s *byte swap $ffff and *byte $10000 * + ;
248 | : . *bys , ;
249 | : +or over - and or ;
250 | : 0/1 $10 ? if $1e and $1e or drop if 7 ; then $f ; then 0 and ;
251 | : 4b dup 0/1 9 and over 6 2/s 0/1 $a and +or swap 11 2/s 0/1 $c and +or $8 or ;
252 | : pix dup @w [ d ] @ 2* u+ 4b ;
253 | : row 1, dup [ w ] @ 2/ dup 1 + dup 2, - 2, 0 dup 1, +adl for pix 16 * push pix pop or dup 1, +adl next drop +mod [ d ] @ [ 1024 2 * ] * + ;
254 | : deflate $178 2, 1 0 adl! [ h ] @ 4294967295 + for 0 row next 1 row drop [ ad2 ] @ *byte 2, [ ad1 ] @ *byte 2, here over 4 + negate + *bys over 4294967292 + !b ;
255 | #41
256 | #42
257 | ( Crc ) [ macro ]
258 | : 2/s ?lit $e8c1 2, 1, ;
259 | : 1@ $8a 2, ; [ forth ] & ad1 48546 & ad2 48600
260 | : array ( -a ) pop 2 2/s ;
261 | : bit ( n-n ) 1 ? if 1 2/s $edb88320 or ; then 1 2/s ;
262 | : fill ( nn ) for dup 8 for bit next , 1 + next drop ;
263 | : table ( -a ) align array [ 0 256 fill ]
264 | : crc ( an-n ) 4294967295 swap for over 1@ over or $ff and [ table ] + @ swap 8 2/s or 1 u+ next - nip ;
265 | : +adl ( n ) $ff and [ ad1 ] @ + dup [ ad2 ] @ +
266 | : adl! [ ad2 ] ! [ ad1 ] ! ;
267 | : +mod [ ad1 ] @ 65521 mod [ ad2 ] @ 65521 mod adl! ;
268 | #43
269 | #44
270 | ( DOS file )
271 | : blks 256 * ;
272 | : w/c [ 18 blks ] ;
273 | : buffer [ 604 block ] ;
274 | : size ( -a ) [ buffer ] 0 1 reads [ buffer $98f + ] ;
275 | : set ( n ) ! [ buffer ] 0 1 writes ;
276 | : cyls ( n-nn ) 1 swap [ w/c 4294967295 + ] + [ w/c ] / ;
277 | : put ( an ) dup 2* 2* size set cyls writes stop ;
278 | : get ( a ) size @ 3 + 2/ 2/ cyls reads stop ;
279 | : .com 0 63 blocks put ;
280 | #45
281 |
282 | : blks n-n ( size in blocks to words )
283 | : w/c -n ( words per cylinder )
284 | : buffer -a ( 1 cylinder required for floppy dma )
285 | : size -a ( locate size of 2nd file. Floppy has first FILLER then FILE allocated. FILLER is 2048 bytes, to fill out cylinder 0. Names at most 8 letters, all caps. Directory starts at ) [ buffer $980 + ]
286 | : set n ( size. FILE must be larger than your file. )
287 | : cyls n-nn ( starting cylinder 1 and number of cylinders )
288 | : put an ( write file from address )
289 | : get a ( read file to address )
290 | #46
291 | ( North Bridge ) [ empty macro ]
292 | : 4@ [[ dup ]] $ed 1, ;
293 | : 4! $ef 1, [[ drop ]] ; [ forth ] & dev 15104
294 | : nb $0 [ dev ] ! ;
295 | : sb $3800 [ dev ] ! ;
296 | : agp $800 [ dev ] ! ;
297 | : ess $6800 [ dev ] ! ;
298 | : ric $7800 [ dev ] ! ;
299 | : win $8000 [ dev ] ! ;
300 | : ati $10000 [ dev ] ! ;
301 | : add $cf8 a! 4! $cfc a! ;
302 | : q $80000000 + add 4@ ;
303 | : en $8004 q 4294967292 and or 4! ;
304 | : dv dup $800 * q swap 1 + ;
305 | : regs [ dev ] @ [ 19 4 * ] + 20 for dup q h. space dup h. cr 4294967292 + next drop ;
306 | : devs 0 33 for dup q dup 1 + drop if dup h. space drop dup 8 + q dup h. space over h. cr then drop $800 + next drop ;
307 | : ok show black screen text regs keyboard ;
308 | : u $40 [ dev ] +! ;
309 | : d 4294967232 [ dev ] +! ;
310 | : test $ff00 + a! 4@ ; [ ok ]
311 | #47
312 | #48
313 | ( ASCII ) [ macro ]
314 | : 1@ $8a 2, ; [ forth ]
315 | : string pop ;
316 | : cf-ii string [ $6f747200 , $696e6165 , $79636d73 , $7766676c , $62707664 , $71757868 , $336a7a6b , $37363534 , $2d313938 , $2f322e30 , $2b213a3b , $3f2c2a40 , ]
317 | : ch $fffffff0 and unpack [ cf-ii ] + 1@ $ff and ;
318 | : ii-cf string [ $2a00 , 0 , $2b2d0000 , $2725232e , $1b262224 , $1f1e1d1c , $28292120 , $2f000000 , $3a43355c , $3d3e3440 , $484a3744 , $3336393c , $38314742 , $3f414632 , $493b45 , 0 , $a13052c , $d0e0410 , $181a0714 , $306090c , $8011712 , $f111602 , $190b15 , ]
319 | : chc $ffffffe0 + [ ii-cf ] + 1@ $ff and ;
320 | #49
321 | #50
322 | ( Clock ) [ macro ]
323 | : p@ $ec 1, ;
324 | : p! $ee 1, [[ drop ]] ; [ forth ]
325 | : ca $70 a! p! $71 a! ;
326 | : c@ ca 0 p@ ;
327 | : c! ca p! ;
328 | : hi 10 c@ $80 and drop if ; then hi ;
329 | : lo 0 p@ $80 and drop if lo ; then ;
330 | : bcd c@ 16 /mod 10 * + ;
331 | : hms0 4 bcd 100 * 2 bcd + 100 * 0 bcd + ;
332 | : hms hms0 2 ms dup hms0 or drop if drop hms ; then ;
333 | : ymd 9 bcd 100 * 8 bcd + 100 * 7 bcd + ;
334 | : day 6 c@ 4294967295 + ;
335 | : cal hi lo time - hi lo time + ( 748 ) ;
336 | #51
337 | #52
338 | ( LAN ) [ empty $3f8 54 load init ]
339 | : no block 4 * 1024 ;
340 | : send no for dup 1@ xmit 1 + next drop ;
341 | : receive no for rcv over 1! 1 + next drop ;
342 | : no 18 [ 7 18 * ] ;
343 | : backup no for dup send 1 + next drop ;
344 | : accept no for dup receive 1 + next drop ;
345 | #53
346 | #54
347 | ( Serial 3f8 2e8 1050 ) [ macro ]
348 | : p@ [[ a! dup ]] $ec 1, ;
349 | : p! [[ a! ]] $ee 1, [[ drop ]] ;
350 | : 1@ $8a 2, ;
351 | : 1! [[ a! ]] $288 2, [[ drop ]] ; [ forth ]
352 | : r [ 0 + ] + ;
353 | : $$9600 12 ;
354 | : $$115200 1 ;
355 | : b/s $83 [ 3 r ] p! $$9600 [ 0 r ] p! 0 [ 1 r ] p! 3 [ 3 r ] p! ;
356 | : init b/s ( 16550 ) 1 [ 2 r ] p! 0 [ 4 r ] p! ;
357 | : xmit ( n ) [ 5 r ] p@ $20 and drop if [ 0 r ] p! ; then pause xmit ;
358 | : cts [ 6 r ] p@ $30 and $30 or drop if cts ; then xmit ;
359 | : st [ 6 r ] p@
360 | : xbits $30 and $10 / dup 1 and 2* 2* + 2/ ;
361 | : st! [ 4 r ] p! ;
362 | : ?rcv [ 5 r ] p@ 1 and drop if [ 0 r ] p@ then ;
363 | : rcv ?rcv if ; then pause rcv ;
364 | #55
365 |
366 | : p@ p-n ( fetch byte from port )
367 | : p! np ( store byte to port )
368 | : 1@ a-n ( fetch byte from byte address )
369 | : 1! na ( store byte to byte address )
370 | : r n-p ( convert relative to absolute port address. Base port on stack at compile time. Compiled as literal at yellow-green transition )
371 | : $$9600
372 | : $$115200 ( baud-rate divisors. These are names, not numbers )
373 | : b/s ( set baud rate. Edit to change )
374 | : init ( initialize uart )
375 | : xmit n ( wait for ready and transmit byte )
376 | : cts n ( wait for clear-to-send then xmit )
377 | : st -n ( fetch status byte )
378 | : xbits n-n ( exchange status bits )
379 | : st! n ( store control byte )
380 | : ?rcv ( fetch byte if ready. Set flag to be tested by ) if
381 | : rcv -n ( wait for ready and fetch byte )
382 | #56
383 | ( Hexagon ) [ empty ] & col 0 & del 2105376
384 | : lin dup 2/ 2/ dup 2* line ;
385 | : hex [ xy ] @ 7 and over 2/ for lin 7 + next over for lin next swap 2/ for 4294967289 + lin next drop ;
386 | : +del [ del ] @ nop
387 | : petal and [ col ] @ + $f8f8f8 and color 100 hex ;
388 | : -del [ del ] @ $f8f8f8 or $80808 + ;
389 | : rose 0 +del 4294967120 4294967096 +at $f80000 -del petal 352 4294967096 +at $f80000 +del 4294967032 4294966947 +at $f800 -del petal 176 4294967096 +at $f8 +del 4294967120 98 +at $f8 -del petal 176 4294967096 +at $f800 +del ;
390 | : ok show black screen 512 282 at rose text [ col ] @ h. space [ del ] @ $ff and . keyboard ; [ 58 load ok h ]
391 | #57
392 | ( Draws 7 hexagons. Colors differ along red, green and blue axes. )
393 | : col ( color of center hexagon )
394 | : del ( color difference )
395 | : lin n ( draws 1 horizontal line of a hexagon )
396 | : hex n ( draws top, center and bottom. Slope 7 x to 4 y is 1.750 compared to 1.732 )
397 | : +del n ( increment color )
398 | : -del n
399 | : petal n ( draw colored hexagon )
400 | : rose ( draw 7 hexagons )
401 | : ok ( describe screen. Center color at top )
402 | #58
403 | ( Pan )
404 | : in [ del ] @ 2* $404040 min [ del ] ! ;
405 | : out [ del ] @ 2/ $80808 max [ del ] ! ;
406 | : r $f80000
407 | : +del [ del ] @
408 | : +col and [ col ] @ + $f8f8f8 and [ col ] ! ;
409 | : g $f800 +del ;
410 | : b $f8 +del ;
411 | : -r $f80000 -del +col ;
412 | : -g $f800 -del +col ;
413 | : -b $f8 -del +col ;
414 | : nul ;
415 | : h pad nul nul accept nul -r -g -b nul r g b nul out nul nul in nul nul nul nul nul nul nul nul nul nul nul nul [ $250000 , $130d01 dup , , $2b000023 , 0 , 0 , 0 , ]
416 | #59
417 |
418 | : in ( increment color difference )
419 | : out ( decrement it )
420 | : r
421 | : g
422 | : b ( increment center color )
423 | : -r
424 | : -g
425 | : -b ( decrement it )
426 | : +del ( redefine with ; )
427 | : +col ( change center color )
428 | : nul ( ignore )
429 | : h ( describe keypad )
430 | #60
431 | #61
432 | #62
433 | ( Timing ) [ empty macro ]
434 | : out $e1e6 2, ; [ forth ]
435 | : tare time - 1000 for next time + ;
436 | : tare+ time - push 1000 for dup next c pop time + ;
437 | : test tare time + - 1000 for out next time + ; ( next 3 loop 5.7 /next 2 /swap 25 swap 7.2 ) [ macro ]
438 | : c! $c88b 2, [[ drop ]] here ;
439 | : loop $49 1, $75 1, ( e2 ) here - + 1, ; [ forth ]
440 | : try time - 1000 c! loop time + ;
441 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | to implement stack manipulation, 'trampolining' is used.
4 | functions that manipulate the stack are called dollar functions
5 | and their names prefixed with a dollar sign, like $ACCEPT. dollar
6 | functions must not be called directly, but instead are pushed
7 | on the return stack ret. the master loop for(;;) ret.pop()()
8 | will then pick them up and execute them. it's generally legal to
9 | push a sequence of functions on the return stack to execute them
10 | (in reverse of the order pushed). non-dollar functions are also
11 | legal to push on the return stack.
12 |
13 | dollar functions can have arguments which are passed using
14 |
15 | ret.push(() => $fn(a,b,c));
16 |
17 | dollar functions can't currently have return values.
18 |
19 | summary:
20 | function x() {
21 | OK: y();
22 | NEIN NEIN NEIN: ret.push(...)
23 | NEIN NEIN NEIN: ret.pop(...)
24 | NEIN NEIN NEIN: $z();
25 | }
26 | function $x() {
27 | OK: y();
28 | OK: ret.push(x);
29 | OK: ret.push($z);
30 | OK: ret.pop();
31 | NEIN NEIN NEIN: $z();
32 | }
33 | */
34 |
35 | var tos = 0;
36 | var flag = false;
37 | var next = 0;
38 | var screen = undefined;
39 | var main_ret = [];
40 | var main_data = [];
41 | var god_ret = [];
42 | var god_data = [];
43 |
44 | var data = god_data;
45 | var ret = god_ret;
46 | var me = 'god';
47 | var mem;
48 |
49 | function alit() { lit = adup; literal(); }
50 | function adup() { DUP_(); }
51 | var lit = adup;
52 |
53 | var dict = [];
54 | var dict_fn = [];
55 | var dict_name = []; /* for debugging */
56 | var nojit = [];
57 | var here = 0;
58 | var list = [0, 0];
59 | var mk = [0, 0, 0];
60 |
61 | var forth0 = [];
62 | var forth2 = [];
63 | var macro0 = [];
64 | var macro2 = [];
65 |
66 | function enchuck(s) {
67 | var w = 0;
68 | var n = 0;
69 | var r = [];
70 | var nc, b;
71 | for(var i = 0; i < s.length; i++){
72 | var c = 1 + 'rtoeanismcylgfwdvpbhxuq0123456789j-k.z/;:!+@*,?'.indexOf(s[i]);
73 | if(c == 0) throw new Error("unchuckable: " + s);
74 | if(c < 8) { nc = 4; b = c; }
75 | else if(c < 16) { nc = 5; b = 0x10 | c - 8; }
76 | else { nc = 7; b = 0x30; b = 0x60 | c - 16; }
77 | if(n + nc - ctz(b) > 28){
78 | r.push(w << 32 - n);
79 | w = 0;
80 | n = 0;
81 | }else if(n + nc > 28){
82 | b >>= n + nc - 28;
83 | nc = 28 - n;
84 | }
85 | w = w << nc | b;
86 | n += nc;
87 | }
88 | if(n != 0)
89 | r.push(w << 32 - n);
90 | return r;
91 | }
92 |
93 | function builtin(name, fn) {
94 | if(fn.name == '' || fn.name == 'anonymous')
95 | throw new Error("don't call builtin_macro with anonymous functions");
96 | var w = enchuck(name)[0];
97 | forth0.push(w);
98 | forth2.push(dict.length);
99 | dict[here++] = 0;
100 | dict_fn.push(fn);
101 | dict_name.push(name);
102 | fn.$ = fn.name[0] == '$';
103 | nojit.push(true);
104 | }
105 | function builtin_macro(name, fn) {
106 | if(fn.name == '' || fn.name == 'anonymous')
107 | throw new Error("don't call builtin_macro with anonymous functions");
108 | var w = enchuck(name)[0];
109 | macro0.push(w);
110 | macro2.push(dict.length);
111 | dict[here++] = 0;
112 | dict_fn.push(fn);
113 | dict_name.push(name);
114 | fn.$ = fn.name[0] == '$';
115 | nojit.push(true);
116 | }
117 |
118 | var INS_NOP = 0;
119 | var INS_DUP = 1;
120 | var INS_DROP = 2;
121 | var INS_SETTOS = 3;
122 | var INS_FORTH = 4;
123 | var INS_MACRO = 5;
124 | var INS_SEMI = 6;
125 | var INS_JYES = 7;
126 | var INS_JNO = 8;
127 | var INS_NOT = 9;
128 | var INS_PUSH = 0xb;
129 | var INS_POP = 0xc;
130 | var INS_ADD = 0xd;
131 | var INS_UPLUS = 0xe;
132 | var INS_NEXT = 0xf;
133 | var INS_MUL = 0x10;
134 | var INS_BANG = 0x11;
135 | var INS_AT = 0x12;
136 | var INS_LSH = 0x13;
137 | var INS_ASR = 0x14;
138 | var INS_NIP = 0x15;
139 | var INS_OR = 0x16;
140 | var INS_AND = 0x17;
141 | var INS_TEST = 0x18;
142 | var INS_OVER = 0x19;
143 | var INS_0NEXT = 0x1a;
144 | var INS_TBANG = 0x1b;
145 | var INS_TAT = 0x1c;
146 | var INS_MULDIV = 0x1d;
147 | var INS_DIV = 0x1e;
148 | var INS_MOD = 0x1f;
149 | var INS_LESS = 0x20;
150 |
151 | function read(n) {
152 | return mem[n]|0;
153 | }
154 |
155 | function write(n, v) {
156 | mem[n] = v;
157 | }
158 |
159 | function memmove(dst, src, n) {
160 | mem.copyWithin(dst, src, src + n);
161 | }
162 |
163 | function DUP_() {
164 | data.push(tos);
165 | }
166 |
167 | function DROP() {
168 | tos = data.pop() | 0;
169 | }
170 |
171 | function $start() {
172 | ret.push($ACCEPT);
173 | ret.push($LOAD);
174 | ret.push(() => {DUP_(); tos = 18;});
175 | ret.push($show0);
176 | }
177 | builtin("warm", $start);
178 |
179 | function $show0() {
180 | ret.push(function(){});
181 | ret.push($SHOW);
182 | }
183 |
184 | function $SHOW() {
185 | screen = ret.pop();
186 | DUP_();
187 | tos = 0;
188 | function $loop(){
189 | ret.push($loop);
190 | ret.push(() => {tos++;});
191 | ret.push(screen);
192 | ret.push($SWITCH);
193 | }
194 | ret.push($loop);
195 | ret.push($ACT);
196 | }
197 | builtin("show", $SHOW);
198 |
199 | function $ACT() {
200 | main_data.length = 0;
201 | main_data.push(tos);
202 | main_ret.length = 0;
203 | main_ret.push(ret.pop());
204 | DROP();
205 | }
206 | builtin("act", $ACT);
207 |
208 | function c_() {
209 | god_data = [0, 0];
210 | }
211 | builtin("c", c_);
212 |
213 | function $PAUSE() {
214 | DUP_();
215 | if(me == 'god'){
216 | me = 'main';
217 | data = main_data;
218 | ret = main_ret;
219 | }else{
220 | me = 'god';
221 | data = god_data;
222 | ret = god_ret;
223 | }
224 | DROP();
225 | }
226 | builtin("pause", $PAUSE);
227 |
228 | var sleeping = true;
229 | var sleepmagic = new Object;
230 |
231 | function $SLEEP(fn) {
232 | if(me != 'god') throw new Error('$SLEEP from main thread');
233 | function loop() {
234 | if(!fn()){
235 | ret.push(loop);
236 | sleeping = true;
237 | throw sleepmagic;
238 | }
239 | }
240 | ret.push(loop);
241 | ret.push($PAUSE);
242 | }
243 |
244 | function wakeup() {
245 | if(sleeping){
246 | sleeping = false;
247 | setTimeout(master, 0);
248 | }
249 | }
250 |
251 | function $delay() {
252 | let expired = false;
253 | setTimeout(() => {expired = true; wakeup();}, 250);
254 | DROP();
255 | ret.push(() => $SLEEP(() => expired));
256 | }
257 | builtin("delay", $delay);
258 |
259 | function $ABORT() {
260 | curs = next;
261 | blk = next >> 8;
262 | ret.push($ABORT1);
263 | }
264 |
265 | function $ABORT1() {
266 | ret = god_ret;
267 | spaces[3] = forthd;
268 | spaces[4] = $qCOMPILE;
269 | spaces[5] = cNUM;
270 | spaces[6] = cSHORT;
271 | tos = 0o57;
272 | ECHO_();
273 | ret.push($ACCEPT);
274 | }
275 |
276 | function $LOAD() {
277 | ret.push(next);
278 | next = tos * 256;
279 | DROP();
280 | ret.push($INTER);
281 | }
282 | builtin("load", $LOAD);
283 |
284 | function $INTER() {
285 | var word, f;
286 |
287 | word = read(next);
288 | next++;
289 | f = spaces[word & 0o17];
290 | ret.push($INTER);
291 | ret.push(() => f(word));
292 | }
293 |
294 | function $qIGNORE(word) {
295 | if(word == 0){
296 | ret.pop();
297 | next = ret.pop();
298 | }
299 | }
300 |
301 | function nul() {
302 | }
303 |
304 | function $execute(word) {
305 | var r;
306 |
307 | lit = alit;
308 | DUP_();
309 | tos = word & -16;
310 | r = forth0.lastIndexOf(tos);
311 | if(r < 0){
312 | console.log("not found " + dechuck(word & -16));
313 | ret.push($ABORT);
314 | }else{
315 | DROP();
316 | ret.push(dict_fn[forth2[r]]);
317 | }
318 | }
319 |
320 | function NUM(word) {
321 | lit = alit;
322 | DUP_();
323 | tos = read(next);
324 | next++;
325 | }
326 |
327 | function SHORT_(word) {
328 | lit = alit;
329 | DUP_();
330 | tos = word >> 5;
331 | }
332 |
333 | function MACRO(word) {
334 | spaces[3] = macrod;
335 | }
336 | builtin("macro", MACRO);
337 |
338 | function FORTH(word) {
339 | spaces[3] = forthd;
340 | }
341 | builtin("forth", FORTH);
342 |
343 | function macrod(word) {
344 | macro0.push(word & -16);
345 | var h = here;
346 | macro2.push(h);
347 | dict_fn[h] = () => jit(h)();
348 | dict_name[h] = dechuck(word & -16);
349 | list[0] = undefined;
350 | lit = adup;
351 | }
352 |
353 | function forthd(word) {
354 | forth0.push(word & -16);
355 | var h = here;
356 | forth2.push(h);
357 | dict_fn[h] = () => jit(h)();
358 | dict_name[h] = dechuck(word & -16);
359 | list[0] = undefined;
360 | lit = adup;
361 | }
362 |
363 | function $qCOMPILE(word) {
364 | var r;
365 |
366 | lit();
367 | tos = word & -16;
368 | r = macro0.lastIndexOf(tos);
369 | if(r >= 0){
370 | DROP();
371 | ret.push(dict_fn[macro2[r]]);
372 | }else{
373 | r = forth0.lastIndexOf(tos);
374 | if(r < 0){
375 | console.log("not found " + dechuck(word & -16));
376 | ret.push($ABORT);
377 | }else{
378 | list[0] = here;
379 | dict[here++] = INS_FORTH;
380 | dict[here++] = r;
381 | DROP();
382 | }
383 | }
384 | }
385 |
386 | function $COMPILE(word) {
387 | var r;
388 |
389 | lit();
390 | tos = word & -16;
391 | r = macro0.lastIndexOf(tos);
392 | if(r < 0){
393 | console.log("not found " + dechuck(word & -16));
394 | ret.push($ABORT);
395 | }else{
396 | list[0] = here;
397 | dict[here++] = INS_MACRO;
398 | dict[here++] = r;
399 | DROP();
400 | }
401 | }
402 |
403 | function cNUM(word) {
404 | lit();
405 | tos = read(next);
406 | next++;
407 | literal();
408 | DROP();
409 | }
410 |
411 | function cSHORT(word) {
412 | lit();
413 | tos = word >> 5;
414 | literal();
415 | DROP();
416 | }
417 |
418 | function variable(word) {
419 | forth0.push(word & -16);
420 | forth2.push(here);
421 | dict_fn[here] = () => {DUP_(); tos = a;};
422 | dict_fn[here].$ = false;
423 | dict_name[here] = dechuck(word & -16);
424 | nojit[here] = true;
425 | dict[here++] = 0;
426 | let a = next;
427 | macro0.push(word & -16);
428 | macro2.push(here);
429 | dict.push(0);
430 | dict_fn[here] = () => {lit(); tos = a; literal(); DROP();};
431 | dict_fn[here].$ = false;
432 | dict_name[here] = dechuck(word & -16);
433 | nojit[here] = true;
434 | dict[here++] = 0;
435 | list[0] = undefined;
436 | lit = adup;
437 | next++;
438 | }
439 |
440 | var spaces = [
441 | $qIGNORE,
442 | $execute,
443 | NUM,
444 | macrod,
445 | $qCOMPILE,
446 | cNUM,
447 | cSHORT,
448 | $COMPILE,
449 | SHORT_,
450 | nul,
451 | nul,
452 | nul,
453 | variable,
454 | nul,
455 | nul,
456 | nul
457 | ];
458 |
459 |
460 | function cdrop() {
461 | list[0] = here;
462 | dict[here++] = INS_DROP;
463 | }
464 | builtin_macro("drop", cdrop);
465 |
466 | function cdup() {
467 | dict[here++] = INS_DUP;
468 | }
469 | builtin_macro("dup", cdup);
470 |
471 | function qdup() {
472 | if(list[0] != here-1 || dict[here-1] != INS_DROP)
473 | cdup();
474 | else
475 | here--;
476 | }
477 | builtin_macro("?dup", qdup);
478 |
479 | function qlit() {
480 | if(list[0] != here-2 || dict[here-2] != INS_SETTOS)
481 | flag = false;
482 | else{
483 | flag = true;
484 | DUP_();
485 | list[0] = list[1];
486 | if(dict[here-3] == INS_DUP){
487 | here -= 3;
488 | }else{
489 | here -= 2;
490 | cdrop();
491 | }
492 | }
493 | }
494 | builtin("?lit", qlit);
495 |
496 | function literal() {
497 | qdup();
498 | list[1] = list[0];
499 | list[0] = here;
500 | dict[here++] = INS_SETTOS;
501 | dict[here++] = tos;
502 | }
503 |
504 | function semi() {
505 | dict[here++] = INS_SEMI;
506 | }
507 | builtin_macro(";", semi);
508 |
509 | function then() {
510 | list[0] = undefined;
511 | dict[tos-1] = here;
512 | DROP();
513 | }
514 | builtin_macro("then", then);
515 |
516 | function begin() {
517 | list[0] = undefined;
518 | DUP_();
519 | tos = here;
520 | }
521 | builtin_macro("begin", begin);
522 |
523 | function comma() {
524 | dict[here++] = tos;
525 | DROP();
526 | }
527 | builtin(",", comma);
528 |
529 | function HERE() {
530 | DUP_();
531 | tos = here;
532 | }
533 | builtin("here", HERE);
534 |
535 | function mark() {
536 | mk = [macro0.length, forth0.length, here];
537 | }
538 | builtin("mark", mark);
539 |
540 | function empty() {
541 | macro2.length = macro0.length = mk[0];
542 | forth2.length = forth0.length = mk[1];
543 | here = mk[2];
544 | }
545 | builtin("empt", empty);
546 |
547 | function log() {
548 | console.log(data, tos);
549 | }
550 | builtin("log", log);
551 |
552 | function debug() {
553 | debugger;
554 | }
555 | builtin("debug", debug);
556 |
557 | function erase() {
558 | var n = tos << 8; DROP();
559 | var a = tos << 8; DROP();
560 | mem.fill(0, a, a + n);
561 | }
562 | builtin("erase", erase);
563 |
564 | function $copy() {
565 | if(tos < 12) ret.push($ABORT1);
566 | var a = tos; DROP();
567 | memmove(a << 8, blk << 8, 256);
568 | blk = a;
569 | }
570 | builtin("copy", $copy);
571 |
572 | function master() {
573 | try {
574 | for(var i = 0; i < 1000; i++)
575 | ret.pop()();
576 | setTimeout(master, 0);
577 | }catch(e){
578 | if(e !== sleepmagic){
579 | console.log(e.stack);
580 | throw e;
581 | }
582 | }
583 | }
584 |
585 | function dict_$(n) {
586 | var f = dict_fn[n];
587 | if(f !== undefined && f.$ !== undefined)
588 | return f.$;
589 | return jit_instrs[n].$;
590 | }
591 |
592 | function common(t) { }
593 | function Basic(id, s, n, $) { this.id = id; this.stat = s; this.next = [n]; common(this); this.is$ = () => !!$; }
594 | function Semi(id) { this.id = id; this.next = []; common(this); }
595 | function JSCall(id, f, n) { this.id = id; this.fun = f; this.next = [n]; if(!nojit[f]) this.next.push(f); common(this); }
596 | function Cond(id, c, t, e) { this.id = id; this.cond = c; this.next = [t,e]; common(this); }
597 | function Next(id, c, t, e) { this.id = id; this.cond = c; this.next = [t,e]; common(this); }
598 |
599 | Basic.prototype.mktext = function(n) { return this.stat + "\n" + n[0]; };
600 | Semi.prototype.mktext = function(n) { return ""; };
601 | JSCall.prototype.mktext = function(n) {
602 | if(dict_$(this.fun) === false){
603 | return "dict_fn[" + this.fun + "](); /* " + dict_name[this.fun] + " */\n" + n[0];
604 | }else{
605 | var s = "";
606 | if(n[0] != "")
607 | s += "ret.push(() => {" + n[0] + "});\n"
608 | s += "ret.push(dict_fn[" + this.fun + "]); /* " + dict_name[this.fun] + " */ "
609 | return s;
610 | }
611 | };
612 | Cond.prototype.mktext = function(n) { return "if(" + this.cond + ") {\n" + n[0] + "} else {\n" + n[1] + "}"; };
613 | Next.prototype.mktext = function(n) { return "if(--ret[ret.length - 1] " + this.cond + ") {\n" + n[0] + "} else {\nret.pop();\n" + n[1] + "}"; };
614 |
615 | Semi.prototype.is$ = () => false;
616 | JSCall.prototype.is$ = function() { return dict_$(this.fun); };
617 | Cond.prototype.is$ = () => false;
618 | Next.prototype.is$ = () => true;
619 |
620 | var jit_instrs = [];
621 |
622 | function jit_instr(h) {
623 | switch(dict[h]){
624 | case INS_NOP: return new Basic(h, ';', h + 1); /* intentionally breaks tail call optimisation */
625 | case INS_SEMI: return new Semi(h, );
626 | case INS_DUP: return new Basic(h, "data.push(tos);", h + 1);
627 | case INS_DROP: return new Basic(h, "tos = data.pop() | 0;", h + 1);
628 | case INS_SETTOS: return new Basic(h, "tos = " + dict[h+1] + ";", h + 2);
629 | case INS_NOT: return new Basic(h, "tos = ~tos;", h + 1);
630 | case INS_PUSH: return new Basic(h, "ret.push(tos);", h + 1, true);
631 | case INS_POP: return new Basic(h, "tos = ret.pop();", h + 1, true);
632 | case INS_ADD: return new Basic(h, "tos = 0 | tos + data.pop();", h + 1);
633 | case INS_MUL: return new Basic(h, "tos = 0 | tos * data.pop();", h + 1);
634 | case INS_UPLUS: return new Basic(h, "data[data.length - 2] += tos;", h + 1);
635 | case INS_AT: return new Basic(h, "tos = read(tos);", h + 1);
636 | case INS_BANG: return new Basic(h, "write(tos, data[data.length - 1]);", h + 1);
637 | case INS_LSH: return new Basic(h, "tos <<= 1;", h + 1);
638 | case INS_ASR: return new Basic(h, "tos >>>= 1;", h + 1);
639 | case INS_NIP: return new Basic(h, "data.length--;", h + 1);
640 | case INS_OR: return new Basic(h, "tos |= data.pop();", h + 1);
641 | case INS_AND: return new Basic(h, "tos &= data.pop();", h + 1);
642 | case INS_TEST: return new Basic(h, "flag = (data[data.length - 1] & tos) != 0;}", h + 1);
643 | case INS_OVER: return new Basic(h, "tos = data[data.length - 2];", h + 1);
644 | case INS_TBANG: return new Basic(h, "var t" + dict[h+1] + " = tos;", h + 2);
645 | case INS_TAT: return new Basic(h, "tos = t" + dict[h+1] + ";", h + 2);
646 | case INS_MULDIV: return new Basic(h, "tos = data[data.length - 2] * data[data.length - 1] / tos | 0;", h + 1);
647 | case INS_DIV: return new Basic(h, "tos = data.pop() / tos | 0;", h + 1);
648 | case INS_MOD: return new Basic(h, "tos = data.pop() % tos;", h + 1);
649 | case INS_LESS: return new Basic(h, "flag = data[data.length - 1] < tos;", h + 1);
650 |
651 | case INS_FORTH: return new JSCall(h, forth2[dict[h+1]], h+2);
652 | case INS_MACRO: return new JSCall(h, macro2[dict[h+1]], h+2);
653 | case INS_JYES: return new Cond(h, "flag", dict[h+1], h+2);
654 | case INS_JNO: return new Cond(h, "!flag", dict[h+1], h+2);
655 | case INS_NEXT: return new Next(h, "> 0", dict[h+1], h+2);
656 | case INS_0NEXT: return new Next(h, ">= 0", dict[h+1], h+2);
657 | default: throw new Error("invalid opcode " + dict[h]);
658 | }
659 | }
660 |
661 | function jit_loop(start) {
662 | if(start in jit_instrs) return jit_instrs[start];
663 |
664 | var namectr = 0
665 | var named = {};
666 |
667 | function handle(p) {
668 | var n = [];
669 | var $ = false;
670 | for(var i = 0; i < p.next.length; i++){
671 | p.next[i] = jit_instrs[p.next[i]];
672 | if(p.next[i].text === undefined){
673 | named[p.next[i].id] = '_' + namectr++;
674 | n.push("ret.push(" + named[p.next[i].id] + ");");
675 | $ = true;
676 | }else{
677 | n.push(p.next[i].text);
678 | if(p.next[i].$ !== false)
679 | $ = true;
680 | }
681 | }
682 | let t = p.mktext(n);
683 | if(named[p.id]){
684 | p.text = "function " + named[p.id] + "() {\n" + t + "}\nret.push(" + named[p.id] + ");";
685 | p.$ = true;
686 | }else{
687 | p.text = t;
688 | p.$ = $ || p.is$();
689 | }
690 | }
691 |
692 | var qu = [start];
693 | while(qu.length != 0){
694 | let h = qu.pop();
695 | if(h instanceof Function) {h(); continue;}
696 | if(h in jit_instrs) continue;
697 | let p = jit_instr(h);
698 | jit_instrs[h] = p;
699 | qu.push(() => handle(p));
700 | p.next.forEach(x => {
701 | if(!(x in jit_instrs))
702 | qu.push(x);
703 | });
704 | }
705 | return jit_instrs[start];
706 | }
707 |
708 | function jit(h) {
709 | var p = jit_loop(h);
710 | var f = new Function(p.text);
711 | f.$ = p.$;
712 | return dict_fn[h] = f;
713 | }
714 |
715 | function init() {
716 | mem = assemble(forth);
717 | for(var i = 0; i < iconstr.length / 4; i++)
718 | mem[12*256 + i] =
719 | iconstr.charCodeAt(4 * i) |
720 | iconstr.charCodeAt(4 * i + 1) << 8 |
721 | iconstr.charCodeAt(4 * i + 2) << 16 |
722 | iconstr.charCodeAt(4 * i + 3) << 24;
723 | ret.push($start);
724 | setTimeout(master, 0);
725 | gfxinit();
726 | }
727 |
728 | window.onload = init;
729 |
--------------------------------------------------------------------------------
/orig/COLOR.ASM:
--------------------------------------------------------------------------------
1 | ;colorForth, 2001 Jul 22, Chuck Moore, Public Domain
2 |
3 | .MODEL tiny
4 | .486p
5 | only SEGMENT USE32
6 | ASSUME DS:only
7 |
8 | next MACRO adr
9 | dec ECX
10 | jnz adr
11 | ENDM
12 |
13 | DUP_ MACRO
14 | lea ESI, [ESI-4]
15 | mov [ESI], EAX
16 | ENDM
17 |
18 | DROP MACRO
19 | lodsd
20 | ENDM
21 |
22 | ;hp equ 800
23 | ;vp equ 600
24 | ;vesa equ 114h
25 | hp equ 1024
26 | vp equ 768
27 | vesa equ 117h
28 | buffer equ 604*256
29 | include boot.asm ; boot boot0 hard
30 |
31 | ; 100000 dictionary
32 | ; a0000 top of return stack
33 | ; 9f800 top of data stack
34 | ; 9d800 free
35 | ; 97000 floppy buffer
36 | ; 4800 source
37 | icons equ 12*256*4 ; 3000
38 | ; 7c00 BIOS boot sector
39 | ; 0 Forth
40 |
41 | warm: DUP_
42 | start1: call ATI0
43 | ; mov screen, offset nul
44 | ; xor EAX, EAX
45 | call show0
46 | mov forths, (forth1-forth0)/4
47 | mov macros, (macro1-macro0)/4
48 | mov EAX, 18
49 | call LOAD
50 | jmp ACCEPT
51 |
52 | Gods equ 28000h*4 ; 0A0000h
53 | Godd equ Gods-750*4
54 | mains equ Godd-1500*4
55 | maind equ mains-750*4
56 | ALIGN 4
57 | me dd offset God
58 | screen dd 0 ; logo
59 |
60 | ROUND: call unPAUSE
61 | God dd 0 ; Gods-2*4
62 | call unPAUSE
63 | main dd 0 ; mains-2*4
64 | jmp ROUND
65 |
66 | PAUSE: DUP_
67 | push ESI
68 | mov EAX, me
69 | mov [EAX], ESP
70 | add EAX, 4
71 | jmp EAX
72 |
73 | unPAUSE: pop EAX
74 | mov ESP, [EAX]
75 | mov me, EAX
76 | pop ESI
77 | DROP
78 | ret
79 |
80 | ACT: mov EDX, maind-4
81 | mov [EDX], EAX
82 | mov EAX, mains-4
83 | pop [EAX]
84 | sub EAX, 4
85 | mov [EAX], EDX
86 | mov main, EAX
87 | DROP
88 | ret
89 |
90 | show0: call show
91 | ret
92 | show: pop screen
93 | DUP_
94 | xor EAX, EAX
95 | call ACT
96 | @@: call graphic
97 | call [screen]
98 | call SWITCH
99 | inc EAX
100 | jmp @b
101 |
102 | c_: mov ESI, Godd+4
103 | ret
104 |
105 | mark: mov ECX, macros
106 | mov mk, ECX
107 | mov ECX, forths
108 | mov mk+4, ECX
109 | mov ECX, H
110 | mov mk+2*4, ECX
111 | ret
112 |
113 | empty: mov ECX, mk+2*4
114 | mov H, ECX
115 | mov ECX, mk+4
116 | mov forths, ECX
117 | mov ECX, mk
118 | mov macros, ECX
119 | mov class, 0
120 | ret
121 |
122 | mFIND: mov ECX, macros
123 | push EDI
124 | lea EDI, [macro0-4+ECX*4]
125 | jmp @f
126 |
127 | FIND: mov ECX, forths
128 | push EDI
129 | lea EDI, [forth0-4+ECX*4]
130 | @@: std
131 | repne scasd
132 | cld
133 | pop EDI
134 | ret
135 |
136 | EX1: dec words ; from keyboard
137 | jz @f
138 | DROP
139 | jmp EX1
140 | @@: call FIND
141 | jnz ABORT1
142 | DROP
143 | jmp [forth2+ECX*4]
144 |
145 | execute: mov lit, offset alit
146 | DUP_
147 | mov EAX, [-4+EDI*4]
148 | ex2: and EAX, -20o
149 | call FIND
150 | jnz ABORT
151 | DROP
152 | jmp [forth2+ECX*4]
153 |
154 | ABORT: mov curs, EDI
155 | shr EDI, 10-2
156 | mov blk, EDI
157 | ABORT1: mov ESP, Gods
158 | mov spaces+3*4, offset forthd
159 | mov spaces+4*4, offset qcompile
160 | mov spaces+5*4, offset cnum
161 | mov spaces+6*4, offset cshort
162 | mov EAX, 57o ; ?
163 | call ECHO_
164 | jmp ACCEPT
165 |
166 | sDEFINE: pop aDEFINE
167 | ret
168 | MACRO_: call sDEFINE
169 | macrod: mov ECX, macros
170 | inc macros
171 | lea ECX, [macro0+ECX*4]
172 | jmp @f
173 |
174 | FORTH: call sDEFINE
175 | forthd: mov ECX, forths
176 | inc forths
177 | lea ECX, [forth0+ECX*4]
178 | @@: mov EDX, [-4+EDI*4]
179 | and EDX, -20o
180 | mov [ECX], EDX
181 | mov EDX, h
182 | mov [forth2-forth0+ECX], EDX
183 | lea EDX, [forth2-forth0+ECX]
184 | shr EDX, 2
185 | mov last, EDX
186 | mov list, ESP
187 | mov lit, offset adup
188 | test class, -1
189 | jz @f
190 | jmp [class]
191 | @@: ret
192 |
193 | cdrop: mov EDX, h
194 | mov list, EDX
195 | mov byte ptr [EDX], 0adh ; lodsd
196 | inc h
197 | ret
198 |
199 | qdup: mov EDX, h
200 | dec EDX
201 | cmp list, EDX
202 | jnz cdup
203 | cmp byte ptr [EDX], 0adh
204 | jnz cdup
205 | mov h, EDX
206 | ret
207 | cdup: mov EDX, h
208 | mov dword ptr [EDX], 89fc768dh
209 | mov byte ptr [4+EDX], 06
210 | add h, 5
211 | ret
212 |
213 | adup: DUP_
214 | ret
215 |
216 | var1: DUP_
217 | mov EAX, [4+forth0+ECX*4]
218 | ret
219 | variable: call forthd
220 | mov [forth2-forth0+ECX], offset var1
221 | inc forths ; dummy entry for source address
222 | mov [4+ECX], EDI
223 | call macrod
224 | mov [forth2-forth0+ECX], offset @f
225 | inc macros
226 | mov [4+ECX], EDI
227 | inc EDI
228 | ret
229 | @@: call [lit]
230 | mov EAX, [4+macro0+ECX*4]
231 | jmp @f
232 |
233 | cNUM: call [lit]
234 | mov EAX, [EDI*4]
235 | inc EDI
236 | jmp @f
237 |
238 | cSHORT: call [lit]
239 | mov EAX, [-4+EDI*4]
240 | sar EAX, 5
241 | @@: call literal
242 | DROP
243 | ret
244 |
245 | alit: mov lit, offset adup
246 | literal: call qDUP
247 | mov EDX, list
248 | mov list+4, EDX
249 | mov EDX, h
250 | mov list, EDX
251 | mov byte ptr [EDX], 0b8h
252 | mov [1+EDX], EAX
253 | add h, 5
254 | ret
255 |
256 | qCOMPILE: call [lit]
257 | mov EAX, [-4+EDI*4]
258 | and EAX, -20o
259 | call mFIND
260 | jnz @f
261 | DROP
262 | jmp [macro2+ECX*4]
263 | @@: call FIND
264 | mov EAX, [forth2+ECX*4]
265 | @@: jnz ABORT
266 | call_: mov EDX, h
267 | mov list, EDX
268 | mov byte ptr [EDX], 0e8h
269 | add EDX, 5
270 | sub EAX, EDX
271 | mov [-4+EDX], EAX
272 | mov h, EDX
273 | DROP
274 | ret
275 |
276 | COMPILE: call [lit]
277 | mov EAX, [-4+EDI*4]
278 | and EAX, -20o
279 | call mFIND
280 | mov EAX, [macro2+ECX*4]
281 | jmp @b
282 |
283 | SHORT_: mov lit, offset alit
284 | DUP_
285 | mov EAX, [-4+EDI*4]
286 | sar EAX, 5
287 | ret
288 |
289 | NUM: mov lit, offset alit
290 | DUP_
291 | mov EAX, [EDI*4]
292 | inc EDI
293 | ret
294 |
295 | comma: mov ECX, 4
296 | @@: mov EDX, h
297 | mov [EDX], EAX
298 | mov EAX, [ESI] ; drop
299 | lea EDX, [EDX+ECX]
300 | lea ESI, [ESI+4]
301 | mov h, EDX
302 | ; DROP
303 | ret
304 |
305 | comma1: mov ECX, 1
306 | jmp @b
307 |
308 | comma2: mov ECX, 2
309 | jmp @b
310 |
311 | comma3: mov ECX, 3
312 | jmp @b
313 |
314 | semi: mov EDX, h
315 | sub EDX, 5
316 | cmp list, EDX
317 | jnz @f
318 | cmp byte ptr [EDX], 0e8h
319 | jnz @f
320 | inc byte ptr [EDX] ; jmp
321 | ret
322 | @@: mov byte ptr [5+EDX], 0c3h ; ret
323 | inc h
324 | ret
325 |
326 | then: mov list, ESP
327 | mov EDX, h
328 | sub EDX, EAX
329 | mov [-1+EAX], DL
330 | DROP
331 | ret
332 |
333 | begin: mov list, ESP
334 | here: DUP_
335 | mov EAX, h
336 | ret
337 |
338 | qlit: mov EDX, h
339 | lea EDX, [EDX-5]
340 | cmp list, EDX
341 | jnz @f
342 | cmp byte ptr [EDX], 0b8h
343 | jnz @f
344 | DUP_
345 | mov EAX, list+4
346 | mov list, EAX
347 | mov EAX, [1+EDX]
348 | cmp dword ptr [EDX-5], 89fc768dh ; dup
349 | jz q1
350 | mov h, EDX
351 | jmp cdrop
352 | q1: add h, -10 ; flag nz
353 | ret
354 | @@: xor EDX, EDX ; flag z
355 | ret
356 |
357 | less: cmp [ESI], EAX
358 | js @f ; flag nz
359 | xor ECX, ECX ; flag z
360 | @@: ret
361 |
362 | qIGNORE: test dword ptr [-4+EDI*4], -20o
363 | jnz nul
364 | pop EDI
365 | pop EDI
366 | nul: ret
367 |
368 | jump: pop EDX
369 | add EDX, EAX
370 | lea EDX, [5+EAX*4+EDX]
371 | add EDX, [-4+EDX]
372 | DROP
373 | jmp EDX
374 |
375 | LOAD: shl EAX, 10-2
376 | push EDI
377 | mov EDI, EAX
378 | DROP
379 | INTER: mov EDX, [EDI*4]
380 | inc EDI
381 | and EDX, 17o
382 | call spaces[EDX*4]
383 | jmp INTER
384 |
385 | ALIGN 4
386 | spaces dd offset qIGNORE, offset execute, offset NUM
387 | aDEFINE dd 5+offset MACRO_ ; offset macrod ?
388 | dd offset qCOMPILE, offset cNUM, offset cSHORT, offset COMPILE
389 | dd offset SHORT_, offset nul, offset nul, offset nul
390 | dd offset variable, offset nul, offset nul, offset nul
391 |
392 | lit dd offset adup
393 | mk dd 0, 0, 0
394 | H dd 40000h*4
395 | last dd 0
396 | class dd 0
397 | list dd 0, 0
398 | macros dd 0
399 | forths dd 0
400 | ;macro0 dd (3 shl 4+1)shl 24 ; or
401 | ; dd ((5 shl 4+6)shl 7+140o)shl 17 ; and
402 | ; dd 173o shl 25 ; +
403 | macro0 dd 170o shl 25 ; ;
404 | dd ((140o shl 7+146o)shl 7+142o)shl 11 ; dup
405 | dd (((177o shl 7+140o)shl 7+146o)shl 7+142o)shl 4 ; ?dup
406 | dd (((140o shl 4+1)shl 4+3)shl 7+142o)shl 10 ; drop
407 | ; dd ((6 shl 4+7)shl 7+142o)shl 17 ; nip
408 | dd (((2 shl 7+144o)shl 4+4)shl 4+6)shl 13 ; then
409 | dd ((((143o shl 4+4)shl 5+25o)shl 4+7)shl 4+6)shl 8 ; begin
410 | macro1 dd 128 dup (0)
411 | forth0 dd (((143o shl 4+3)shl 4+3)shl 4+2)shl 13 ; boot
412 | dd (((27o shl 4+5)shl 4+1)shl 5+21o)shl 14 ; warm
413 | dd ((((142o shl 4+5)shl 7+146o)shl 5+20o)shl 4+4)shl 5 ; pause
414 | dd ((((21o shl 4+5)shl 5+22o)shl 4+1)shl 4+3)shl 10 ; MACRO
415 | dd ((((26o shl 4+3)shl 4+1)shl 4+2)shl 7+144o)shl 8 ; FORTH
416 | dd 22o shl 27 ; c
417 | dd (((20o shl 4+2)shl 4+3)shl 7+142o)shl 12 ; stop
418 | dd (((1 shl 4+4)shl 4+5)shl 7+140o)shl 13 ; read
419 | dd ((((27o shl 4+1)shl 4+7)shl 4+2)shl 4+4)shl 11 ; write
420 | dd (6 shl 5+22o)shl 23 ; nc
421 | dd (((((22o shl 4+3)shl 5+21o)shl 5+21o)shl 4+5)shl 4+6)shl 5; comman d
422 | dd (((20o shl 4+4)shl 4+4)shl 7+164o)shl 12 ; seek
423 | dd ((((1 shl 4+4)shl 4+5)shl 7+140o)shl 5+23o)shl 8 ; ready
424 | ; dd (((22o shl 5+24o)shl 4+1)shl 4+7)shl 14 ; clri
425 | dd ((5 shl 5+22o)shl 4+2)shl 19 ; ACT
426 | dd (((20o shl 7+144o)shl 4+3) shl 5+27o)shl 11 ; SHOW
427 | dd (((24o shl 4+3)shl 4+5)shl 7+140o)shl 12 ; LOAD
428 | dd (((144o shl 4+4)shl 4+1)shl 4+4)shl 13 ; here
429 | dd (((177o shl 5+24o)shl 4+7)shl 4+2)shl 12 ; ?lit
430 | dd (153o shl 7+176o) shl 18 ; 3,
431 | dd (152o shl 7+176o) shl 18 ; 2,
432 | dd (151o shl 7+176o) shl 18 ; 1,
433 | dd 176o shl 25 ; ,
434 | dd (((24o shl 4+4)shl 5+20o)shl 5+20o)shl 13 ; less
435 | dd (((162o shl 7+146o)shl 5+21o)shl 7+142o)shl 6 ; jump
436 | dd (((((5 shl 5+22o)shl 5+22o)shl 4+4)shl 7+142o)shl 4+2)shl 3 ; accept
437 | dd ((142o shl 4+5)shl 7+140o)shl 14 ; pad
438 | dd ((((4 shl 4+1)shl 4+5)shl 5+20o)shl 4+4)shl 11 ; erase
439 | dd (((22o shl 4+3)shl 7+142o)shl 5+23o)shl 11 ; copy
440 | dd (((21o shl 4+5)shl 4+1)shl 7+164o)shl 12 ; mark
441 | dd (((4 shl 5+21o)shl 7+142o)shl 4+2)shl 12 ; empt
442 | dd (((4 shl 5+21o)shl 4+7)shl 4+2)shl 15 ; emit
443 | dd ((((140o shl 4+7)shl 5+25o)shl 4+7)shl 4+2)shl 8 ; digit
444 | dd ((((152o shl 4+4)shl 5+21o)shl 4+7)shl 4+2)shl 8 ; 2emit
445 | dd 165o shl 25 ; .
446 | dd (144o shl 7+165o)shl 18 ; h.
447 | dd ((144o shl 7+165o)shl 4+6)shl 14 ; h.n
448 | dd (22o shl 4+1)shl 23 ; CR
449 | dd ((((20o shl 7+142o)shl 4+5)shl 5+22o)shl 4+4)shl 7 ; space
450 | dd (((140o shl 4+3)shl 5+27o)shl 4+6)shl 12 ; DOWN
451 | dd (((4 shl 7+140o)shl 4+7)shl 4+2)shl 13 ; edit
452 | dd 4 shl 28 ; E
453 | ; dd (((26o shl 4+3)shl 4+6)shl 4+2)shl 15 ; font
454 | dd (24o shl 5+21o)shl 22 ; lm
455 | dd (1 shl 5+21o)shl 23 ; rm
456 | dd ((((25o shl 4+1)shl 4+5)shl 7+142o)shl 7+144o)shl 5 ; graph ic
457 | dd (((2 shl 4+4)shl 7+145o)shl 4+2)shl 13 ; text
458 | ; dd (153o shl 7+140o)shl 18 ; 3d
459 | ; dd (((((1 shl 4+4)shl 4+6)shl 7+140o)shl 4+4)shl 4+1)shl 5 ; render
460 | ; dd ((((141o shl 4+4)shl 4+1)shl 4+2)shl 4+4)shl 9 ; verte x
461 | ; dd ((((26o shl 4+1)shl 4+3)shl 4+6)shl 4+2)shl 11 ; front
462 | ; dd ((2 shl 4+3)shl 7+142o)shl 17 ; top
463 | ; dd (((20o shl 4+7)shl 7+140o)shl 4+4)shl 12 ; side
464 | dd ((((164o shl 4+4)shl 5+23o)shl 7+143o)shl 4+3)shl 5 ; keybo ard
465 | dd (((140o shl 4+4)shl 7+143o)shl 7+146o)shl 7 ; debu g
466 | dd (5 shl 4+2)shl 24 ; at
467 | dd ((173o shl 4+5)shl 4+2)shl 17 ; +at
468 | dd (145o shl 5+23o)shl 20 ; xy
469 | dd ((26o shl 4+3)shl 7+141o)shl 16 ; fov
470 | dd (((26o shl 4+7)shl 5+26o)shl 4+3)shl 14 ; fifo
471 | dd ((143o shl 4+3)shl 7+145o)shl 14 ; box
472 | dd (((24o shl 4+7)shl 4+6)shl 4+4)shl 15 ; line
473 | dd ((((22o shl 4+3)shl 5+24o)shl 4+3)shl 4+1)shl 10 ; color
474 | ; dd (((22o shl 5+24o)shl 4+7)shl 7+142o)shl 11 ; clip
475 | dd (((((3 shl 5+22o)shl 4+2)shl 4+5)shl 4+6)shl 4+2)shl 7 ; octant
476 | dd (20o shl 7+142o)shl 20 ; sp
477 | dd (((24o shl 4+5)shl 5+20o)shl 4+2)shl 14 ; last
478 | dd (((((146o shl 4+6)shl 7+142o)shl 4+5)shl 5+22o))shl 5 ; unpac k
479 | ; dd (((142o shl 4+5)shl 5+22o)shl 7+164o)shl 9 ; pack
480 | forth1 dd 512 dup (0)
481 | ;macro2 dd offset cOR
482 | ; dd offset cAND
483 | ; dd offset PLUS
484 | macro2 dd offset semi
485 | dd offset cdup
486 | dd offset qdup
487 | dd offset cdrop
488 | ; dd offset nip
489 | dd offset then
490 | dd offset begin
491 | dd 128 dup (0)
492 | forth2 dd offset boot
493 | dd offset warm
494 | dd offset PAUSE
495 | dd offset MACRO_
496 | dd offset FORTH
497 | dd offset c_
498 | dd offset stop
499 | dd offset readf
500 | dd offset writef
501 | dd offset nc_
502 | dd offset cmdf
503 | dd offset seekf
504 | dd offset readyf
505 | dd offset ACT
506 | dd offset SHOW
507 | dd offset LOAD
508 | dd offset here
509 | dd offset qlit
510 | dd offset COMMA3
511 | dd offset COMMA2
512 | dd offset COMMA1
513 | dd offset COMMA
514 | dd offset less
515 | dd offset jump
516 | dd offset ACCEPT
517 | dd offset pad
518 | dd offset erase
519 | dd offset copy
520 | dd offset mark
521 | dd offset empty
522 | dd offset emit
523 | dd offset eDIG
524 | dd offset emit2
525 | dd offset dot10
526 | dd offset hdot
527 | dd offset hdotn
528 | dd offset CR
529 | dd offset space
530 | dd offset DOWN
531 | dd offset edit
532 | dd offset E
533 | ; dd offset font
534 | dd offset LMs
535 | dd offset RMs
536 | dd offset graphic
537 | dd offset text1
538 | ; dd offset set3d
539 | ; dd offset render
540 | ; dd offset vertex
541 | ; dd offset front
542 | ; dd offset top_
543 | ; dd offset side
544 | dd offset keyboard
545 | dd offset debug
546 | dd offset at
547 | dd offset pat
548 | dd offset xy_
549 | dd offset fov_
550 | dd offset fifof
551 | dd offset box
552 | dd offset line
553 | dd offset color
554 | ; dd offset clip
555 | dd offset octant
556 | dd offset sps
557 | dd offset last_
558 | dd offset unpack
559 | ; dd offset pack
560 | dd 512 dup (0)
561 |
562 | boot: mov AL, 0FEh ; Reset
563 | out 64h, AL
564 | jmp $
565 |
566 | erase: mov ECX, EAX
567 | shl ECX, 8
568 | DROP
569 | push EDI
570 | mov EDI, EAX
571 | shl EDI, 2+8
572 | xor EAX, EAX
573 | rep stosd
574 | pop EDI
575 | DROP
576 | ret
577 |
578 | ;move: mov ECX, EAX
579 | ; DROP
580 | ; mov EDI, EAX
581 | ; shl EDI, 2
582 | ; DROP
583 | ; push ESI
584 | ; mov ESI, EAX
585 | ; shl ESI, 2
586 | ; rep movsd
587 | ; pop ESI
588 | ; DROP
589 | ; ret
590 |
591 | copy: cmp EAX, 12
592 | jc ABORT1
593 | mov EDI, EAX
594 | shl EDI, 2+8
595 | push ESI
596 | mov ESI, blk
597 | shl ESI, 2+8
598 | mov ECX, 256
599 | rep movsd
600 | pop ESI
601 | mov blk, EAX
602 | DROP
603 | ret
604 |
605 | debug: mov xy, 3*10000h+(vc-2)*ih+3
606 | DUP_
607 | mov EAX, God
608 | push [EAX]
609 | call dot
610 | DUP_
611 | pop EAX
612 | call dot
613 | DUP_
614 | mov EAX, main
615 | call dot
616 | DUP_
617 | mov EAX, ESI
618 | jmp dot
619 |
620 | iw equ 16+6
621 | ih equ 24+6
622 | hc equ hp/iw ; 46
623 | vc equ vp/ih ; 25
624 | ALIGN 4
625 | xy dd 3*10000h+3
626 | lm dd 3
627 | rm dd hc*iw ; 1012
628 | xycr dd 0
629 | fov dd 10*(2*vp+vp/2)
630 |
631 | nc_: DUP_
632 | mov EAX, (offset nc-offset start)/4
633 | ret
634 |
635 | xy_: DUP_
636 | mov EAX, (offset xy-offset start)/4
637 | ret
638 |
639 | fov_: DUP_
640 | mov EAX, (offset fov-offset start)/4
641 | ret
642 |
643 | sps: DUP_
644 | mov EAX, (offset spaces-offset start)/4
645 | ret
646 |
647 | last_: DUP_
648 | mov EAX, (offset last-offset start)/4
649 | ret
650 |
651 | include gen.asm ; cce.asm pio.asm ATI128.asm ATI64.asm gen.asm
652 |
653 | yellow equ 0ffff00h
654 | CYAN: DUP_
655 | mov EAX, 0ffffh
656 | jmp color
657 | MAGENTA: DUP_
658 | mov EAX, 0ff00ffh
659 | jmp color
660 | SILVER: DUP_
661 | mov EAX, 0c0c0c0h
662 | jmp color
663 | BLUE: DUP_
664 | mov EAX, 4040ffh
665 | jmp color
666 | RED: DUP_
667 | mov EAX, 0ff0000h
668 | jmp color
669 | GREEN: DUP_
670 | mov EAX, 8000ff00h
671 | jmp color
672 |
673 | history db 11 dup (0)
674 | ECHO_: push ESI
675 | mov ECX, 11-1
676 | lea EDI, history
677 | lea ESI, [1+EDI]
678 | rep movsb
679 | pop ESI
680 | mov history+11-1, AL
681 | DROP
682 | ret
683 |
684 | RIGHT: DUP_
685 | mov ECX, 11
686 | lea EDI, history
687 | xor EAX, EAX
688 | rep stosb
689 | DROP
690 | ret
691 |
692 | DOWN: DUP_
693 | xor EDX, EDX
694 | mov ECX, ih
695 | div ECX
696 | mov EAX, EDX
697 | add EDX, 3*10000h+8000h-ih+3
698 | mov xy, EDX
699 | ZERO: test EAX, EAX
700 | mov EAX, 0
701 | jnz @f
702 | inc EAX
703 | @@: ret
704 |
705 | blank: DUP_
706 | xor EAX, EAX
707 | mov xy, EAX
708 | call color
709 | DUP_
710 | mov EAX, hp
711 | DUP_
712 | mov EAX, vp
713 | jmp box
714 |
715 | TOP: mov ECX, lm
716 | shl ECX, 16
717 | add ECX, 3
718 | mov xy, ECX
719 | mov xycr, ECX
720 | ret
721 |
722 | qcr: mov CX, word ptr xy+2
723 | cmp CX, word ptr rm
724 | js @f
725 | cr: mov ECX, lm
726 | shl ECX, 16
727 | mov CX, word ptr xy
728 | add ECX, ih
729 | mov xy, ECX
730 | @@: ret
731 |
732 | LMs: mov lm, EAX
733 | DROP
734 | ret
735 |
736 | RMs: mov rm, EAX
737 | DROP
738 | ret
739 |
740 | at: mov word ptr xy, AX
741 | DROP
742 | mov word ptr xy+2, AX
743 | DROP
744 | ret
745 |
746 | pAT: add word ptr xy, AX
747 | DROP
748 | add word ptr xy+2, AX
749 | DROP
750 | ret
751 |
752 | ;cl1: xor EAX, EAX
753 | ; mov [ESI], EAX
754 | ; ret
755 | ;clip: movsx EDX, word ptr xy
756 | ; cmp EDX, vp
757 | ; jns cl1
758 | ; add EAX, EDX
759 | ; js cl1
760 | ; test EDX, EDX
761 | ; jns @f
762 | ; xor EDX, EDX
763 | ;@@: cmp EAX, vp
764 | ; js @f
765 | ; mov EAX, vp
766 | ;@@: sub EAX, EDX
767 | ; mov word ptr xy, DX
768 | ; movsx EDX, word ptr xy+2
769 | ; cmp EDX, hp
770 | ; jns cl1
771 | ; add [ESI], EDX
772 | ; js cl1
773 | ; test EDX, EDX
774 | ; jns @f
775 | ; xor EDX, EDX
776 | ;@@: cmp dword ptr [ESI], hp
777 | ; js @f
778 | ; mov dword ptr [ESI], hp
779 | ;@@: sub [ESI], EDX
780 | ; mov word ptr xy+2, DX
781 | ; ret
782 |
783 | octant: DUP_
784 | mov EAX, 43h ; poly -last y+ x+ ;23h ; last y+ x+
785 | mov EDX, [4+ESI]
786 | test EDX, EDX
787 | jns @f
788 | neg EDX
789 | mov [4+ESI], EDX
790 | xor AL, 1
791 | @@: cmp EDX, [ESI]
792 | jns @f
793 | xor AL, 4
794 | @@: ret
795 |
796 | ; Keyboard
797 | EIGHT: add EDI, 12
798 | call FOUR
799 | call SPACE
800 | sub EDI, 16
801 | FOUR: mov ECX, 4
802 | FOUR1: push ECX
803 | DUP_
804 | xor EAX, EAX
805 | mov AL, [4+EDI]
806 | inc EDI
807 | call EMIT
808 | pop ECX
809 | next FOUR1
810 | ret
811 |
812 | stack: mov EDI, Godd-4
813 | @@: mov EDX, God
814 | cmp [EDX], EDI
815 | jnc @f
816 | DUP_
817 | mov EAX, [EDI]
818 | sub EDI, 4
819 | call qDOT
820 | jmp @b
821 | @@: ret
822 |
823 | KEYBOARD: call text1
824 | mov EDI, board
825 | DUP_
826 | mov EAX, keyc
827 | call color
828 | mov rm, hc*iw
829 | mov lm, hp-9*iw+3
830 | mov xy, (hp-9*iw+3)*10000h+vp-4*ih+3
831 | call EIGHT
832 | call EIGHT
833 | call EIGHT
834 | call CR
835 | add xy, 4*iw*10000h
836 | mov EDI, shift
837 | add EDI, 4*4-4
838 | mov ECX, 3
839 | call FOUR1
840 | mov lm, 3
841 | mov word ptr xy+2, 3
842 | call stack
843 | mov word ptr xy+2, hp-(11+9)*iw+3
844 | lea EDI, history-4
845 | mov ECX, 11
846 | jmp FOUR1
847 |
848 | alpha db 15o, 12o, 1 , 14o
849 | db 24o, 2 , 6 , 10o
850 | db 23o, 11o, 17o, 21o
851 | db 22o, 13o, 16o, 7
852 | db 5 , 3 , 4 , 26o
853 | db 27o, 44o, 25o, 20o
854 | graphics db 31o, 32o, 33o, 0
855 | db 34o, 35o, 36o, 30o
856 | db 37o, 40o, 41o, 57o
857 | db 51o, 50o, 52o, 54o ; : ; ! @
858 | db 46o, 42o, 45o, 56o ; Z J . ,
859 | db 55o, 47o, 53o, 43o ; * / + -
860 | numbers db 31o, 32o, 33o, 0
861 | db 34o, 35o, 36o, 30o
862 | db 37o, 40o, 41o, 0
863 | db 0, 0 , 0 , 0
864 | db 0, 0 , 0 , 0
865 | db 0, 0 , 0 , 0
866 | octals db 31o, 32o, 33o, 0
867 | db 34o, 35o, 36o, 30o
868 | db 37o, 40o, 41o, 0
869 | db 0 , 5 , 23o, 12o
870 | db 0 , 20o, 4 , 16o
871 | db 0 , 0 , 0 , 0
872 | LETTER: cmp AL, 4
873 | js @f
874 | mov EDX, board
875 | mov AL, [EDX][EAX]
876 | @@: ret
877 |
878 | keys db 16, 17, 18, 19, 0, 0, 4, 5 ; 20
879 | db 6, 7, 0, 0, 0, 0, 20, 21
880 | db 22, 23, 0, 0, 8, 9, 10, 11 ; 40
881 | db 0, 0, 0, 0, 24, 25, 26, 27
882 | db 0, 1, 12, 13, 14, 15, 0, 0 ; 60 N
883 | db 3, 2 ; alt space
884 | KEY: DUP_
885 | xor EAX, EAX
886 | @@: call PAUSE
887 | in AL, 144o
888 | test AL, 1
889 | jz @b
890 | in AL, 140o
891 | test AL, 360o
892 | jz @b
893 | cmp AL, 72o
894 | jnc @b
895 | mov AL, [keys-20o+EAX]
896 | ret
897 |
898 | ALIGN 4
899 | graph0 dd offset nul0, offset nul0, offset nul0, offset ALPH0
900 | db 0 , 0 , 5 , 0 ; a
901 | graph1 dd offset WORD0, offset X, offset LJ, offset ALPH
902 | db 25o, 45o, 5 , 0 ; x . a
903 | alpha0 dd offset nul0, offset nul0, offset NUMBER, offset STAR0
904 | db 0 , 41o, 55o, 0 ; 9 *
905 | alpha1 dd offset WORD0, offset X, offset LJ, offset GRAPH
906 | db 25o, 45o, 55o, 0 ; x . *
907 | numb0 dd offset nul0, offset MINUS, offset ALPHn, offset OCTAL
908 | db 43o, 5 , 16o, 0 ; - a f
909 | numb1 dd offset NUMBER0, offset Xn, offset ENDN, offset NUMBER0
910 | db 25o, 45o, 0 , 0 ; x .
911 |
912 | board dd offset alpha-4
913 | shift dd offset alpha0
914 | base dd 10
915 | current dd offset decimal
916 | keyc dd yellow
917 | chars dd 1
918 | aword dd offset EX1
919 | anumber dd offset nul
920 | words dd 1
921 |
922 | nul0: DROP
923 | jmp @f
924 | ACCEPT:
925 | acceptn: mov shift, offset alpha0
926 | lea EDI, alpha-4
927 | ACCEPT1: mov board, EDI
928 | @@: call KEY
929 | cmp AL, 4
930 | jns first
931 | mov EDX, shift
932 | jmp dword ptr [EDX+EAX*4]
933 |
934 | bits db 28
935 | @@: add EAX, 120o
936 | mov CL, 7
937 | jmp @f
938 | PACK: cmp AL, 20o
939 | jnc @b
940 | mov CL, 4
941 | test AL, 10o
942 | jz @f
943 | inc ECX
944 | xor AL, 30o
945 | @@: mov EDX, EAX
946 | mov CH, CL
947 | @@: cmp bits, CL
948 | jnc @f
949 | shr AL, 1
950 | jc FULL
951 | dec CL
952 | jmp @b
953 | @@: shl dword ptr [ESI], CL
954 | xor [ESI], EAX
955 | sub bits, CL
956 | ret
957 |
958 | LJ0: mov CL, bits
959 | add CL, 4
960 | shl dword ptr [ESI], CL
961 | ret
962 |
963 | LJ: call LJ0
964 | DROP
965 | ret
966 |
967 | FULL: call LJ0
968 | inc words
969 | mov bits, 28
970 | sub bits, CH
971 | mov EAX, EDX
972 | DUP_
973 | ret
974 |
975 | X: call RIGHT
976 | mov EAX, words
977 | lea ESI, [EAX*4+ESI]
978 | DROP
979 | jmp ACCEPT
980 |
981 | WORD_: call RIGHT
982 | mov words, 1
983 | mov chars, 1
984 | DUP_
985 | mov dword ptr [ESI], 0
986 | mov bits, 28
987 | WORD1: call LETTER
988 | jns @f
989 | mov EDX, shift
990 | jmp dword ptr [EDX+EAX*4]
991 | @@: test AL, AL
992 | jz WORD0
993 | DUP_
994 | call ECHO_
995 | call PACK
996 | inc chars
997 | WORD0: DROP
998 | call KEY
999 | jmp WORD1
1000 |
1001 | decimal: mov base, 10
1002 | mov shift, offset numb0
1003 | mov board, offset numbers-4
1004 | ret
1005 |
1006 | hex: mov base, 16
1007 | mov shift, offset numb0 ; oct0
1008 | mov board, offset octals-4
1009 | ret
1010 |
1011 | octal: xor current, (offset decimal-offset start) xor (offset hex-offset start)
1012 | xor byte ptr numb0+18, 41o xor 16o ; f vs 9
1013 | call current
1014 | jmp NUMBER0
1015 |
1016 | Xn: DROP
1017 | DROP
1018 | jmp ACCEPTn
1019 |
1020 | ; db 0, 0, 0, 0
1021 | digit db 14, 10, 0, 0
1022 | db 0, 0, 12, 0, 0, 0, 15, 0
1023 | db 13, 0, 0, 11, 0, 0, 0, 0
1024 | db 0, 1, 2, 3, 4, 5, 6, 7
1025 | db 8, 9
1026 | sign db 0
1027 | MINUS: ; mov AL, 43o ; -
1028 | mov sign, AL
1029 | jmp NUMBER2
1030 |
1031 | NUMBER0: DROP
1032 | jmp NUMBER3
1033 | NUMBER: call current
1034 | mov sign, 0
1035 | xor EAX, EAX
1036 | NUMBER3: call KEY
1037 | call LETTER
1038 | jns @f
1039 | mov EDX, shift
1040 | jmp dword ptr [EDX+EAX*4]
1041 | @@: test AL, AL
1042 | jz NUMBER0
1043 | mov AL, [digit-4+EAX]
1044 | test sign, 37o
1045 | jz @f
1046 | neg EAX
1047 | @@: mov EDX, [ESI]
1048 | imul EDX, base
1049 | add EDX, EAX
1050 | @@: mov [ESI], EDX
1051 | NUMBER2: DROP
1052 | mov shift, offset numb1
1053 | jmp NUMBER3
1054 |
1055 | ENDN: DROP
1056 | call [anumber]
1057 | jmp ACCEPTn
1058 |
1059 | ALPHn: DROP
1060 | ALPH0: mov shift, offset alpha0
1061 | lea EDI, alpha-4
1062 | jmp @f
1063 | STAR0: mov shift, offset graph0
1064 | lea EDI, graphics-4
1065 | @@: DROP
1066 | jmp ACCEPT1
1067 |
1068 | ALPH: mov shift, offset alpha1
1069 | lea EDI, alpha-4
1070 | jmp @f
1071 | GRAPH: mov shift, offset graph1
1072 | lea EDI, graphics-4
1073 | @@: mov board, EDI
1074 | jmp WORD0
1075 |
1076 | first: add shift, 4*4+4
1077 | call WORD_
1078 | call [aword]
1079 | jmp ACCEPT
1080 |
1081 | hicon db 30o, 31o, 32o, 33o, 34o, 35o, 36o, 37o
1082 | db 40o, 41o, 5 , 23o, 12o, 20o, 4 , 16o
1083 | eDIG1: DUP_
1084 | eDIG: push ECX
1085 | mov AL, hicon[EAX]
1086 | call EMIT
1087 | pop ECX
1088 | ret
1089 |
1090 | oDIG: rol EAX, 4
1091 | DUP_
1092 | and EAX, 0Fh
1093 | ret
1094 |
1095 | hdotn: mov EDX, EAX
1096 | neg EAX
1097 | lea ECX, [32+EAX*4]
1098 | DROP
1099 | rol EAX, CL
1100 | mov ECX, EDX
1101 | jmp @f
1102 | hdot: mov ECX, 8
1103 | @@: call oDIG
1104 | call eDIG
1105 | next @b
1106 | DROP
1107 | ret
1108 |
1109 | dot: mov ECX, 7
1110 | @@: call oDIG
1111 | jnz @h
1112 | DROP
1113 | next @b
1114 | inc ECX
1115 | @@: call oDIG
1116 | @h1: call eDIG
1117 | next @b
1118 | call space
1119 | DROP
1120 | ret
1121 | @h: inc ECX
1122 | jmp @h1
1123 |
1124 | qdot: cmp base, 10
1125 | jnz dot
1126 | dot10: mov EDX, EAX
1127 | test EDX, EDX
1128 | jns @f
1129 | neg EDX
1130 | DUP_
1131 | mov EAX, 43o
1132 | call EMIT
1133 | @@: mov ECX, 8
1134 | @@: mov EAX, EDX
1135 | xor EDX, EDX
1136 | div tens[ECX*4]
1137 | test EAX, EAX
1138 | jnz D_1
1139 | dec ECX
1140 | jns @b
1141 | jmp D_2
1142 | @@: mov EAX, EDX
1143 | xor EDX, EDX
1144 | div tens[ECX*4]
1145 | D_1: call eDIG1
1146 | dec ECX
1147 | jns @b
1148 | D_2: mov EAX, EDX
1149 | call eDIG1
1150 | call space ; spcr
1151 | DROP
1152 | ret
1153 |
1154 | unPACK: DUP_
1155 | test EAX, EAX
1156 | js @f
1157 | shl dword ptr [ESI], 4
1158 | rol EAX, 4
1159 | and EAX, 7
1160 | ret
1161 | @@: shl EAX, 1
1162 | js @f
1163 | shl dword ptr [ESI], 5
1164 | rol EAX, 4
1165 | and EAX, 7
1166 | xor AL, 10o
1167 | ret
1168 | @@: shl dword ptr [ESI], 7
1169 | rol EAX, 6
1170 | and EAX, 77o
1171 | sub AL, 20o
1172 | ret
1173 |
1174 | qRING: DUP_
1175 | inc dword ptr [ESI]
1176 | cmp curs, EDI ; from abort, insert
1177 | jnz @f
1178 | mov curs, EAX
1179 | @@: cmp EAX, curs
1180 | jz RING
1181 | jns @f
1182 | mov pcad, EDI
1183 | @@: DROP
1184 | ret
1185 |
1186 | RING: mov cad, EDI
1187 | sub xy, iw*10000h ; bksp
1188 | DUP_
1189 | mov EAX, 0e04000h
1190 | call color
1191 | mov EAX, 60o
1192 | mov CX, word ptr xy+2
1193 | cmp CX, word ptr rm
1194 | js @f
1195 | call EMIT
1196 | sub xy, iw*10000h ; bksp
1197 | ret
1198 | @@: jmp EMIT
1199 |
1200 | rW: mov CX, word ptr xy+2
1201 | cmp CX, word ptr lm
1202 | jz @f
1203 | call cr
1204 | @@: call RED
1205 | jmp TYPE_
1206 |
1207 | gW: call GREEN
1208 | jmp TYPE_
1209 | mW: call CYAN
1210 | jmp TYPE_
1211 | wW: DUP_
1212 | mov EAX, yellow
1213 | call color
1214 | jmp TYPE_
1215 |
1216 | type0: sub xy, iw*10000h ; call bspcr
1217 | test dword ptr [-4+EDI*4], -20o
1218 | jnz type1
1219 | dec EDI
1220 | mov lcad, EDI
1221 | call space
1222 | call qRING
1223 | pop EDX ; End of block
1224 | DROP
1225 | jmp KEYBOARD
1226 |
1227 | Cap: call white
1228 | DUP_
1229 | mov EAX, [-4+EDI*4]
1230 | and EAX, -20o
1231 | call unPACK
1232 | add AL, 48
1233 | call EMIT
1234 | jmp type2
1235 |
1236 | CAPS: call white
1237 | DUP_
1238 | mov EAX, [-4+EDI*4]
1239 | and EAX, -20o
1240 | @@: call unPACK
1241 | jz @f
1242 | add AL, 48
1243 | call EMIT
1244 | jmp @b
1245 |
1246 | text: call WHITE
1247 | TYPE_:
1248 | type1: DUP_
1249 | mov EAX, [-4+EDI*4]
1250 | and EAX, -20o
1251 | type2: call unPACK
1252 | jz @f
1253 | call EMIT
1254 | jmp type2
1255 | @@: call space
1256 | DROP
1257 | DROP
1258 | ret
1259 |
1260 | gsW: mov EDX, [-4+EDI*4]
1261 | sar EDX, 5
1262 | jmp gnW1
1263 |
1264 | var: call MAGENTA
1265 | call TYPE_
1266 | gnW: mov EDX, [EDI*4]
1267 | inc EDI
1268 | gnW1: DUP_
1269 | mov EAX, 0f800h ; Green
1270 | cmp bas, offset dot10
1271 | jz @f
1272 | mov EAX, 0c000h ; dark green
1273 | jmp @f
1274 |
1275 | sW: mov EDX, [-4+EDI*4]
1276 | sar EDX, 5
1277 | jmp nW1
1278 |
1279 | nW: mov EDX, [EDI*4]
1280 | inc EDI
1281 | nW1: DUP_
1282 | mov EAX, yellow
1283 | cmp bas, offset dot10
1284 | jz @f
1285 | mov EAX, 0c0c000h ; dark yellow
1286 | @@: call color
1287 | DUP_
1288 | mov EAX, EDX
1289 | jmp [bas]
1290 |
1291 | REFRESH: call SHOW
1292 | call blank
1293 | call text1
1294 | DUP_ ; Counter
1295 | mov EAX, lcad
1296 | mov cad, EAX ; for curs beyond end
1297 | xor EAX, EAX
1298 | mov EDI, blk
1299 | shl EDI, 10-2
1300 | mov pcad, EDI ; for curs=0
1301 | ref1: test dword ptr [EDI*4], 0fh
1302 | jz @f
1303 | call qRING
1304 | @@: mov EDX, [EDI*4]
1305 | inc EDI
1306 | mov bas, offset dot10
1307 | test DL, 20o
1308 | jz @f
1309 | mov bas, offset dot
1310 | @@: and EDX, 17o
1311 | call display[EDX*4]
1312 | jmp ref1
1313 |
1314 | ALIGN 4
1315 | display dd offset TYPE0, offset wW, offset nW, offset rW
1316 | dd offset gW, offset gnW, offset gsW, offset mW
1317 | dd offset sW, offset text, offset Cap, offset CAPS
1318 | dd offset var, offset nul, offset nul, offset nul
1319 | tens dd 10, 100, 1000, 10000, 100000, 1000000
1320 | dd 10000000, 100000000, 1000000000
1321 | bas dd offset dot10
1322 | blk dd 18
1323 | curs dd 0
1324 | cad dd 0
1325 | pcad dd 0
1326 | lcad dd 0
1327 | trash dd buffer*4
1328 | ekeys dd offset nul, offset DEL, offset Eout, offset destack
1329 | dd offset act1, offset act3, offset act4, offset shadow
1330 | dd offset mcur, offset mmcur, offset ppcur, offset pcur
1331 | dd offset mblk, offset actv, offset act7, offset pblk
1332 | dd offset nul, offset act11, offset act10, offset act9
1333 | dd offset nul, offset nul, offset nul, offset nul
1334 | ekbd0 dd offset nul, offset nul, offset nul, offset nul
1335 | db 25o, 45o, 7 , 0 ; x . i
1336 | ekbd db 17o, 1 , 15o, 55o ; w r g *
1337 | db 14o, 26o, 20o, 1 ; l u d r
1338 | db 43o, 11o, 12o, 53o ; - m c +
1339 | db 0 , 70o, 72o, 2 ; S C t
1340 | db 0 , 0 , 0 , 0
1341 | db 0 , 0 , 0 , 0
1342 | actc dd yellow, 0, 0ff0000h, 0c000h, 0, 0, 0ffffh
1343 | dd 0, 0ffffffh, 0ffffffh, 0ffffffh, 8080ffh
1344 | vector dd 0
1345 | action db 1
1346 |
1347 | act1: mov AL, 1
1348 | jmp @f
1349 | act3: mov AL, 3
1350 | jmp @f
1351 | act4: mov AL, 4
1352 | jmp @f
1353 | act9: mov AL, 9
1354 | jmp @f
1355 | act10: mov AL, 10
1356 | jmp @f
1357 | act11: mov AL, 11
1358 | jmp @f
1359 | act7: mov AL, 7
1360 | @@: mov action, AL
1361 | mov EAX, [actc-4+EAX*4]
1362 | mov aword, offset insert
1363 | actn: mov keyc, EAX
1364 | pop EAX
1365 | DROP
1366 | jmp ACCEPT
1367 |
1368 | actv: mov action, 12
1369 | mov EAX, 0ff00ffh ; Magenta
1370 | mov aword, offset @f
1371 | jmp actn
1372 |
1373 | @@: DUP_
1374 | xor EAX, EAX
1375 | inc words
1376 | jmp insert
1377 |
1378 | mcur: dec curs
1379 | jns @f
1380 | pcur: inc curs
1381 | @@: ret
1382 |
1383 | mmcur: sub curs, 8
1384 | jns @f
1385 | mov curs, 0
1386 | @@: ret
1387 | ppcur: add curs, 8
1388 | ret
1389 |
1390 | pblk: add blk, 2
1391 | add dword ptr [ESI], 2
1392 | ret
1393 | mblk: cmp blk, 20
1394 | js @f
1395 | sub blk, 2
1396 | sub dword ptr [ESI], 2
1397 | @@: ret
1398 |
1399 | shadow: xor blk, 1
1400 | xor dword ptr [ESI], 1
1401 | ret
1402 |
1403 | E0: DROP
1404 | jmp @f
1405 |
1406 | edit: mov blk, EAX
1407 | DROP
1408 | E: DUP_
1409 | mov EAX, blk
1410 | mov anumber, offset FORMAT
1411 | mov byte ptr alpha0+4*4, 45o ; .
1412 | mov alpha0+4, offset E0
1413 | call REFRESH
1414 | @@: mov shift, offset ekbd0
1415 | mov board, offset ekbd-4
1416 | mov keyc, yellow
1417 | @@: call KEY
1418 | call ekeys[EAX*4]
1419 | DROP
1420 | jmp @b
1421 |
1422 | eout: pop EAX
1423 | DROP
1424 | DROP
1425 | mov aword, offset EX1
1426 | mov anumber, offset nul
1427 | mov byte ptr alpha0+4*4, 0
1428 | mov alpha0+4, offset nul0
1429 | mov keyc, yellow
1430 | jmp ACCEPT
1431 |
1432 | destack: mov EDX, trash
1433 | cmp EDX, buffer*4
1434 | jnz @f
1435 | ret
1436 | @@: sub EDX, 2*4
1437 | mov ECX, [EDX+1*4]
1438 | mov words, ECX
1439 | @@: DUP_
1440 | mov EAX, [EDX]
1441 | sub EDX, 1*4
1442 | next @b
1443 | add EDX, 1*4
1444 | mov trash, EDX
1445 |
1446 | insert0: mov ECX, lcad ; room available?
1447 | add ECX, words
1448 | xor ECX, lcad
1449 | and ECX, -100h
1450 | jz insert1
1451 | mov ECX, words ; no
1452 | @@: DROP
1453 | next @b
1454 | ret
1455 | insert1: push ESI
1456 | mov ESI, lcad
1457 | mov ECX, ESI
1458 | dec ESI
1459 | mov EDI, ESI
1460 | add EDI, words
1461 | shl EDI, 2
1462 | sub ECX, cad
1463 | js @f
1464 | shl ESI, 2
1465 | std
1466 | rep movsd
1467 | cld
1468 | @@: pop ESI
1469 | shr EDI, 2
1470 | inc EDI
1471 | mov curs, EDI ; like abort
1472 | mov ECX, words
1473 | @@: dec EDI
1474 | mov [EDI*4], EAX
1475 | DROP ; requires cld
1476 | next @b
1477 | ret
1478 |
1479 | insert: call insert0
1480 | mov CL, action
1481 | xor [EDI*4], CL
1482 | jmp ACCEPT
1483 |
1484 | FORMAT: test action, 12o ; ignore 3 and 9
1485 | jz @f
1486 | DROP
1487 | ret
1488 | @@: mov EDX, EAX
1489 | and EDX, 0FC000000h
1490 | jz @f
1491 | cmp EDX, 0FC000000h
1492 | jnz FORMAT2
1493 | @@: shl EAX, 5
1494 | xor AL, 2 ; 6
1495 | cmp action, 4
1496 | jz @f
1497 | xor AL, 13o ; 8
1498 | @@: cmp base, 10
1499 | jz @f
1500 | xor AL, 20o
1501 | @@: mov words, 1
1502 | jmp insert
1503 |
1504 | FORMAT2: DUP_
1505 | mov EAX, 1 ; 5
1506 | cmp action, 4
1507 | jz @f
1508 | mov AL, 3 ; 2
1509 | @@: cmp base, 10
1510 | jz @f
1511 | xor AL, 20o
1512 | @@: xchg EAX, [ESI]
1513 | mov words, 2
1514 | jmp insert
1515 |
1516 | DEL: call enstack
1517 | mov EDI, pcad
1518 | mov ECX, lcad
1519 | sub ECX, EDI
1520 | shl EDI, 2
1521 | push ESI
1522 | mov ESI, cad
1523 | shl ESI, 2
1524 | rep movsd
1525 | pop ESI
1526 | jmp mcur
1527 |
1528 | enstack: DUP_
1529 | mov EAX, cad
1530 | sub EAX, pcad
1531 | jz ens
1532 | mov ECX, EAX
1533 | xchg EAX, EDX
1534 | push ESI
1535 | mov ESI, cad
1536 | lea ESI, [ESI*4-4]
1537 | mov EDI, trash
1538 | @@: std
1539 | lodsd
1540 | cld
1541 | stosd
1542 | next @b
1543 | xchg EAX, EDX
1544 | stosd
1545 | mov trash, EDI
1546 | pop ESI
1547 | ens: DROP
1548 | ret
1549 |
1550 | pad: pop EDX
1551 | mov vector, EDX
1552 | add EDX, 28*5
1553 | mov board, EDX
1554 | sub EDX, 4*4
1555 | mov shift, EDX
1556 | @@: call KEY
1557 | mov EDX, vector
1558 | add EDX, EAX
1559 | lea EDX, [5+EAX*4+EDX]
1560 | add EDX, [-4+EDX]
1561 | DROP
1562 | call EDX
1563 | jmp @b
1564 |
1565 | org (1200h-1)*4
1566 | dd 0
1567 | end start
1568 |
--------------------------------------------------------------------------------