about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--500fake-screen.mu (renamed from 500text-screen.mu)68
-rw-r--r--shell/global.mu86
-rw-r--r--shell/sandbox.mu66
3 files changed, 194 insertions, 26 deletions
diff --git a/500text-screen.mu b/500fake-screen.mu
index a266eb07..1731a63c 100644
--- a/500text-screen.mu
+++ b/500fake-screen.mu
@@ -1,17 +1,25 @@
-# Testable primitives for writing text to screen.
-# (Mu doesn't yet have testable primitives for graphics.)
+# Testable primitives for writing to screen.
 #
-# Unlike the top-level, this text mode has no scrolling.
+# Mu mostly uses the screen for text, but it builds it out of pixel graphics
+# and a bitmap font. There is no support for a blinking cursor, scrolling and
+# so on.
+#
+# Fake screens are primarily for testing text-mode prints. However, they do
+# support some rudimentary pixel operations as well. Caveats:
+#
+# - Drawing pixels atop text or vice versa is not supported. Results in a fake
+#   screen will not mimic real screens in these situations.
+# - Fake screens currently also assume a fixed-width 8x16 font.
 
-# coordinates here don't match top-level
-# Here we're consistent with graphics mode. Top-level is consistent with
-# terminal emulators.
 type screen {
+  # text mode
   width: int
   height: int
   data: (handle array screen-cell)
-  cursor-x: int
-  cursor-y: int
+  cursor-x: int  # [0..width)
+  cursor-y: int  # [0..height)
+  # pixel graphics
+  pixels: (handle stream pixel)  # sparse representation
 }
 
 type screen-cell {
@@ -20,6 +28,12 @@ type screen-cell {
   background-color: int
 }
 
+type pixel {
+  x: int  # [0..width*font-width)
+  y: int  # [0..height*font-height)
+  color: int  # [0..256)
+}
+
 fn initialize-screen _screen: (addr screen), width: int, height: int {
   var screen/esi: (addr screen) <- copy _screen
   var tmp/eax: int <- copy 0
@@ -38,6 +52,9 @@ fn initialize-screen _screen: (addr screen), width: int, height: int {
     tmp <- multiply width
     populate data-addr, tmp
   }
+  # pixels
+  var pixels-ah/ecx: (addr handle stream pixel) <- get screen, pixels
+  populate-stream pixels-ah, tmp
   # screen->cursor-x = 0
   dest <- get screen, cursor-x
   copy-to *dest, 0
@@ -64,6 +81,33 @@ fn screen-size _screen: (addr screen) -> _/eax: int, _/ecx: int {
   return width, height
 }
 
+fn pixel screen: (addr screen), x: int, y: int, color: int {
+  {
+    compare screen, 0
+    break-if-!=
+    pixel-on-real-screen x, y, color
+    return
+  }
+  # fake screen
+  # prepare a pixel
+  var pixel-storage: pixel
+  var src/ecx: int <- copy x
+  var dest/edx: (addr int) <- get pixel-storage, x
+  copy-to *dest, src
+  src <- copy y
+  dest <- get pixel-storage, y
+  copy-to *dest, src
+  src <- copy color
+  dest <- get pixel-storage, color
+  copy-to *dest, src
+  # save it
+  var src/ecx: (addr pixel) <- address pixel-storage
+  var screen/eax: (addr screen) <- copy screen
+  var dest-stream-ah/eax: (addr handle stream pixel) <- get screen, pixels
+  var dest-stream/eax: (addr stream pixel) <- lookup *dest-stream-ah
+  write-to-stream dest-stream, src
+}
+
 # testable screen primitive
 fn draw-grapheme _screen: (addr screen), g: grapheme, x: int, y: int, color: int, background-color: int {
   var screen/esi: (addr screen) <- copy _screen
@@ -219,6 +263,9 @@ fn clear-screen _screen: (addr screen) {
     loop
   }
   set-cursor-position screen, 0, 0
+  var dest-stream-ah/eax: (addr handle stream pixel) <- get screen, pixels
+  var dest-stream/eax: (addr stream pixel) <- lookup *dest-stream-ah
+  clear-stream dest-stream
 }
 
 fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean {
@@ -247,7 +294,10 @@ fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean {
     y <- increment
     loop
   }
-  return 1/true
+  var pixels-ah/eax: (addr handle stream pixel) <- get screen, pixels
+  var pixels/eax: (addr stream pixel) <- lookup *pixels-ah
+  var result/eax: boolean <- stream-empty? pixels
+  return result
 }
 
 fn clear-rect _screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
diff --git a/shell/global.mu b/shell/global.mu
index 325ace44..cb3eeb78 100644
--- a/shell/global.mu
+++ b/shell/global.mu
@@ -26,6 +26,7 @@ fn initialize-globals _self: (addr global-table) {
   append-primitive self, "cons"
   # for screens
   append-primitive self, "print"
+  append-primitive self, "pixel"
   # for keyboards
   append-primitive self, "key"
   # for streams
@@ -303,6 +304,13 @@ fn apply-primitive _f: (addr cell), args-ah: (addr handle cell), out: (addr hand
     return
   }
   {
+    var is-pixel?/eax: boolean <- string-equal? f-name, "pixel"
+    compare is-pixel?, 0/false
+    break-if-=
+    apply-pixel args-ah, out, trace
+    return
+  }
+  {
     var wait-for-key?/eax: boolean <- string-equal? f-name, "key"
     compare wait-for-key?, 0/false
     break-if-=
@@ -686,6 +694,84 @@ fn apply-print _args-ah: (addr handle cell), out: (addr handle cell), trace: (ad
   copy-object second-ah, out
 }
 
+fn apply-pixel _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) {
+  trace-text trace, "eval", "apply pixel"
+  var args-ah/eax: (addr handle cell) <- copy _args-ah
+  var _args/eax: (addr cell) <- lookup *args-ah
+  var args/esi: (addr cell) <- copy _args
+  # TODO: check that args is a pair
+  var empty-args?/eax: boolean <- nil? args
+  compare empty-args?, 0/false
+  {
+    break-if-=
+    error trace, "pixel needs 4 args but got 0"
+    return
+  }
+  # screen = args->left
+  var first-ah/eax: (addr handle cell) <- get args, left
+  var first/eax: (addr cell) <- lookup *first-ah
+  var first-type/ecx: (addr int) <- get first, type
+  compare *first-type, 5/screen
+  {
+    break-if-=
+    error trace, "first arg for 'pixel' is not a screen"
+    return
+  }
+  var screen-ah/eax: (addr handle screen) <- get first, screen-data
+  var _screen/eax: (addr screen) <- lookup *screen-ah
+  var screen/edi: (addr screen) <- copy _screen
+  # x = args->right->left->value
+  var rest-ah/eax: (addr handle cell) <- get args, right
+  var _rest/eax: (addr cell) <- lookup *rest-ah
+  var rest/esi: (addr cell) <- copy _rest
+  # TODO: check that rest is a pair
+  var second-ah/eax: (addr handle cell) <- get rest, left
+  var second/eax: (addr cell) <- lookup *second-ah
+  var second-type/ecx: (addr int) <- get second, type
+  compare *second-type, 1/number
+  {
+    break-if-=
+    error trace, "second arg for 'pixel' is not an int (x coordinate)"
+    return
+  }
+  var second-value/eax: (addr float) <- get second, number-data
+  var x/edx: int <- convert *second-value
+  # y = rest->right->left->value
+  var rest-ah/eax: (addr handle cell) <- get rest, right
+  var _rest/eax: (addr cell) <- lookup *rest-ah
+  rest <- copy _rest
+  # TODO: check that rest is a pair
+  var third-ah/eax: (addr handle cell) <- get rest, left
+  var third/eax: (addr cell) <- lookup *third-ah
+  var third-type/ecx: (addr int) <- get third, type
+  compare *third-type, 1/number
+  {
+    break-if-=
+    error trace, "third arg for 'pixel' is not an int (y coordinate)"
+    return
+  }
+  var third-value/eax: (addr float) <- get third, number-data
+  var y/ebx: int <- convert *third-value
+  # color = rest->right->left->value
+  var rest-ah/eax: (addr handle cell) <- get rest, right
+  var _rest/eax: (addr cell) <- lookup *rest-ah
+  rest <- copy _rest
+  # TODO: check that rest is a pair
+  var fourth-ah/eax: (addr handle cell) <- get rest, left
+  var fourth/eax: (addr cell) <- lookup *fourth-ah
+  var fourth-type/ecx: (addr int) <- get fourth, type
+  compare *fourth-type, 1/number
+  {
+    break-if-=
+    error trace, "fourth arg for 'pixel' is not an int (color; 0..0xff)"
+    return
+  }
+  var fourth-value/eax: (addr float) <- get fourth, number-data
+  var color/eax: int <- convert *fourth-value
+  pixel screen, x, y, color
+  # return nothing
+}
+
 fn apply-wait-for-key _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) {
   trace-text trace, "eval", "apply key"
   var args-ah/eax: (addr handle cell) <- copy _args-ah
diff --git a/shell/sandbox.mu b/shell/sandbox.mu
index ad51df8f..68b04344 100644
--- a/shell/sandbox.mu
+++ b/shell/sandbox.mu
@@ -250,29 +250,61 @@ fn render-screen screen: (addr screen), _target-screen: (addr screen), xmin: int
     }
     screen-y <- increment
   }
-  # screen
-  var height/edx: (addr int) <- get target-screen, height
-  var y/ecx: int <- copy 0
+  # text data
   {
-    compare y, *height
-    break-if->=
-    set-cursor-position screen, xmin, screen-y
-    draw-code-point-at-cursor screen, 0x7c/vertical-bar, 0x18/fg, 0/bg
-    move-cursor-right screen
-    var width/edx: (addr int) <- get target-screen, width
-    var x/ebx: int <- copy 0
+    var height/edx: (addr int) <- get target-screen, height
+    var y/ecx: int <- copy 0
     {
-      compare x, *width
+      compare y, *height
       break-if->=
-      print-screen-cell-of-fake-screen screen, target-screen, x, y
+      set-cursor-position screen, xmin, screen-y
+      draw-code-point-at-cursor screen, 0x7c/vertical-bar, 0x18/fg, 0/bg
       move-cursor-right screen
-      x <- increment
+      var width/edx: (addr int) <- get target-screen, width
+      var x/ebx: int <- copy 0
+      {
+        compare x, *width
+        break-if->=
+        print-screen-cell-of-fake-screen screen, target-screen, x, y
+        move-cursor-right screen
+        x <- increment
+        loop
+      }
+      draw-code-point-at-cursor screen, 0x7c/vertical-bar, 0x18/fg, 0/bg
+      y <- increment
+      screen-y <- increment
+      loop
+    }
+  }
+  # pixel data
+  {
+    var left/ebx: int <- copy xmin
+    left <- add 1/margin-left
+    left <- shift-left 3/log-font-width
+    var top/edx: int <- copy ymin
+    top <- add 1/margin-top
+    top <- shift-left 4/log-font-height
+    var pixels-ah/esi: (addr handle stream pixel) <- get target-screen, pixels
+    var _pixels/eax: (addr stream pixel) <- lookup *pixels-ah
+    var pixels/esi: (addr stream pixel) <- copy _pixels
+    rewind-stream pixels
+    {
+      var done?/eax: boolean <- stream-empty? pixels
+      compare done?, 0/false
+      break-if-!=
+      var curr-pixel: pixel
+      var curr-pixel-addr/eax: (addr pixel) <- address curr-pixel
+      read-from-stream pixels, curr-pixel-addr
+      var curr-x/eax: (addr int) <- get curr-pixel, x
+      var x/eax: int <- copy *curr-x
+      x <- add left
+      var curr-y/ecx: (addr int) <- get curr-pixel, y
+      var y/ecx: int <- copy *curr-y
+      y <- add top
+      var curr-color/edx: (addr int) <- get curr-pixel, color
+      pixel screen, x, y, *curr-color
       loop
     }
-    draw-code-point-at-cursor screen, 0x7c/vertical-bar, 0x18/fg, 0/bg
-    y <- increment
-    screen-y <- increment
-    loop
   }
   # bottom border
   {
0:31:55 +0000 Added python plugins code' href='/danisanti/profani-tty/commit/configure.ac?id=0fc0b3eeecccface462733f42b3acb636bcd3622'>0fc0b3ee ^
f1b9bb49 ^

0fc0b3ee ^










2c7a4e48 ^
7486e22b ^


0fc0b3ee ^



41fe8c22 ^
56c0c533 ^
41fe8c22 ^
41fe8c22 ^
56c0c533 ^



52e9be4a ^
b267b065 ^
52e9be4a ^
b267b065 ^







7486e22b ^


56c0c533 ^


41fe8c22 ^

1b0ce852 ^
c908f37a ^
1b0ce852 ^

559b1608 ^
1b0ce852 ^
2b88e2f1 ^
424918c5 ^
0a9200e2 ^
75bb0036 ^
0a9200e2 ^
75bb0036 ^
424918c5 ^
2519e450 ^
75bb0036 ^

42eb9ba6 ^


75bb0036 ^
42eb9ba6 ^

75bb0036 ^







52e9be4a ^
dcccfacb ^
52e9be4a ^
dcccfacb ^
52e9be4a ^
bc8a871a ^
1588106e ^
52e9be4a ^


2519e450 ^
2c361644 ^
2519e450 ^
52e9be4a ^
768df4d7 ^

52e9be4a ^
768df4d7 ^
f983438e ^
768df4d7 ^
f983438e ^
768df4d7 ^






2c976d35 ^
7fa9ecc7 ^

dcccfacb ^
b367c848 ^
7f5169c2 ^

b367c848 ^



6e5c9288 ^


8be49e9e ^
7d857fc3 ^

e361ea69 ^
401ebce8 ^
cf78fac5 ^
8bfb175d ^
900a0451 ^
05d19cb6 ^
94f0550c ^
900a0451 ^
05d19cb6 ^



dc0c3cc6 ^
8fd77ea1 ^
e361ea69 ^




8fd77ea1 ^









e361ea69 ^
524b1f23 ^
b5171cb0 ^
f0ffceef ^
b5171cb0 ^











f0ffceef ^
b5171cb0 ^





dcccfacb ^

d2035496 ^

78841f2e ^
dcccfacb ^

d2035496 ^


dcccfacb ^
78841f2e ^
bd1c1394 ^
78841f2e ^
2490c3ed ^
54df2101 ^
2490c3ed ^
f8187382 ^




24ebb512 ^
54df2101 ^


2490c3ed ^

fa89e2aa ^
7e4b1b1d ^
fa89e2aa ^
1dba341d ^
671849c7 ^










1dba341d ^


d2035496 ^

edbc15fa ^
4a5b672f ^
edbc15fa ^
97c66127 ^







f9b2fdc7 ^

bfbc8edc ^
c00ab035 ^
97c66127 ^


b2dfdc75 ^

97c66127 ^

4a5b672f ^

3ceb9b0d ^








718a708b ^


2519e450 ^

dcccfacb ^

28f5cdf7 ^
252c7c2e ^

c5a04de9 ^

8c9aee22 ^
c5a04de9 ^
2c5b4442 ^
2519e450 ^
d28930ea ^
8e0d8d2a ^
52e9be4a ^
11066f20 ^
2519e450 ^
e07da412 ^
dcccfacb ^

4ca6296f ^

7cf8f47f ^
8bfb175d ^
7486e22b ^
8bfb175d ^
3c062438 ^
41fe8c22 ^
3c062438 ^


2519e450 ^
8014e902 ^
2655d9e8 ^


dcccfacb ^

7486e22b ^










dcccfacb ^

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393