https://github.com/akkartik/mu/blob/main/500fake-screen.mu
1
2
3
4
5
6
7
8
9
10
11
12
13
14 type screen {
15
16 width: int
17 height: int
18 data: (handle array screen-cell)
19 cursor-x: int
20 cursor-y: int
21
22 pixels: (handle array byte)
23 }
24
25 type screen-cell {
26 data: grapheme
27 color: int
28 background-color: int
29 }
30
31 fn initialize-screen _screen: (addr screen), width: int, height: int, pixel-graphics?: boolean {
32 var screen/esi: (addr screen) <- copy _screen
33 var tmp/eax: int <- copy 0
34 var dest/edi: (addr int) <- copy 0
35
36 dest <- get screen, width
37 tmp <- copy width
38 copy-to *dest, tmp
39
40 dest <- get screen, height
41 tmp <- copy height
42 copy-to *dest, tmp
43
44 {
45 var data-ah/edi: (addr handle array screen-cell) <- get screen, data
46 var capacity/eax: int <- copy width
47 capacity <- multiply height
48 populate data-ah, capacity
49 }
50
51 {
52 compare pixel-graphics?, 0/false
53 break-if-=
54 var pixels-ah/edi: (addr handle array byte) <- get screen, pixels
55 var capacity/eax: int <- copy width
56 capacity <- shift-left 3/log2-font-width
57 capacity <- multiply height
58 capacity <- shift-left 4/log2-font-height
59 populate pixels-ah, capacity
60 }
61
62 dest <- get screen, cursor-x
63 copy-to *dest, 0
64
65 dest <- get screen, cursor-y
66 copy-to *dest, 0
67 }
68
69
70 fn screen-size _screen: (addr screen) -> _/eax: int, _/ecx: int {
71 var screen/esi: (addr screen) <- copy _screen
72 var width/eax: int <- copy 0
73 var height/ecx: int <- copy 0
74 compare screen, 0
75 {
76 break-if-!=
77 return 0x80/128, 0x30/48
78 }
79
80 var tmp/edx: (addr int) <- get screen, width
81 width <- copy *tmp
82 tmp <- get screen, height
83 height <- copy *tmp
84 return width, height
85 }
86
87
88 fn draw-grapheme _screen: (addr screen), g: grapheme, x: int, y: int, color: int, background-color: int {
89 var screen/esi: (addr screen) <- copy _screen
90 {
91 compare screen, 0
92 break-if-!=
93 draw-grapheme-on-real-screen g, x, y, color, background-color
94 return
95 }
96
97 var idx/ecx: int <- screen-cell-index screen, x, y
98 var data-ah/eax: (addr handle array screen-cell) <- get screen, data
99 var data/eax: (addr array screen-cell) <- lookup *data-ah
100 var offset/ecx: (offset screen-cell) <- compute-offset data, idx
101 var dest-cell/ecx: (addr screen-cell) <- index data, offset
102 var dest-grapheme/eax: (addr grapheme) <- get dest-cell, data
103 var g2/edx: grapheme <- copy g
104 copy-to *dest-grapheme, g2
105 var dest-color/eax: (addr int) <- get dest-cell, color
106 var src-color/edx: int <- copy color
107 copy-to *dest-color, src-color
108 dest-color <- get dest-cell, background-color
109 src-color <- copy background-color
110 copy-to *dest-color, src-color
111 }
112
113
114 fn draw-code-point screen: (addr screen), c: code-point, x: int, y: int, color: int, background-color: int {
115 var g/eax: grapheme <- copy c
116 draw-grapheme screen, g, x, y, color, background-color
117 }
118
119
120 fn screen-cell-index _screen: (addr screen), x: int, y: int -> _/ecx: int {
121 var screen/esi: (addr screen) <- copy _screen
122 {
123 compare x, 0
124 break-if->=
125 abort "screen-cell-index: negative x"
126 }
127 {
128 var xmax/eax: (addr int) <- get screen, width
129 var xcurr/ecx: int <- copy x
130 compare xcurr, *xmax
131 break-if-<
132 abort "screen-cell-index: x too high"
133 }
134 {
135 compare y, 0
136 break-if->=
137 abort "screen-cell-index: negative y"
138 }
139 {
140 var ymax/eax: (addr int) <- get screen, height
141 var ycurr/ecx: int <- copy y
142 compare ycurr, *ymax
143 break-if-<
144 abort "screen-cell-index: y too high"
145 }
146 var width-addr/eax: (addr int) <- get screen, width
147 var result/ecx: int <- copy y
148 result <- multiply *width-addr
149 result <- add x
150 return result
151 }
152
153 fn cursor-position _screen: (addr screen) -> _/eax: int, _/ecx: int {
154 var screen/esi: (addr screen) <- copy _screen
155 {
156 compare screen, 0
157 break-if-!=
158 var x/eax: int <- copy 0
159 var y/ecx: int <- copy 0
160 x, y <- cursor-position-on-real-screen
161 return x, y
162 }
163
164 var cursor-x-addr/eax: (addr int) <- get screen, cursor-x
165 var cursor-y-addr/ecx: (addr int) <- get screen, cursor-y
166 return *cursor-x-addr, *cursor-y-addr
167 }
168
169 fn set-cursor-position _screen: (addr screen), x: int, y: int {
170 var screen/esi: (addr screen) <- copy _screen
171 {
172 compare screen, 0
173 break-if-!=
174 set-cursor-position-on-real-screen x, y
175 return
176 }
177
178
179 {
180 compare x, 0
181 break-if->=
182 return
183 }
184
185 {
186 var width-addr/eax: (addr int) <- get screen, width
187 var width/eax: int <- copy *width-addr
188 compare x, width
189 break-if-<=
190 return
191 }
192
193 {
194 compare y, 0
195 break-if->=
196 return
197 }
198
199 {
200 var height-addr/eax: (addr int) <- get screen, height
201 var height/eax: int <- copy *height-addr
202 compare y, height
203 break-if-<
204 return
205 }
206
207 var dest/edi: (addr int) <- get screen, cursor-x
208 var src/eax: int <- copy x
209 copy-to *dest, src
210
211 dest <- get screen, cursor-y
212 src <- copy y
213 copy-to *dest, src
214 }
215
216 fn draw-cursor screen: (addr screen), g: grapheme {
217 {
218 compare screen, 0
219 break-if-!=
220 draw-cursor-on-real-screen g
221 return
222 }
223
224 var cursor-x/eax: int <- copy 0
225 var cursor-y/ecx: int <- copy 0
226 cursor-x, cursor-y <- cursor-position screen
227 draw-grapheme screen, g, cursor-x, cursor-y, 0/fg, 7/bg
228 }
229
230 fn clear-screen _screen: (addr screen) {
231 var screen/esi: (addr screen) <- copy _screen
232 {
233 compare screen, 0
234 break-if-!=
235 clear-real-screen
236 return
237 }
238
239 set-cursor-position screen, 0, 0
240 var y/eax: int <- copy 0
241 var height/ecx: (addr int) <- get screen, height
242 {
243 compare y, *height
244 break-if->=
245 var x/edx: int <- copy 0
246 var width/ebx: (addr int) <- get screen, width
247 {
248 compare x, *width
249 break-if->=
250 draw-code-point screen, 0x20/space, x, y, 0/fg=black, 0/bg=black
251 x <- increment
252 loop
253 }
254 y <- increment
255 loop
256 }
257 set-cursor-position screen, 0, 0
258 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
259 var pixels/eax: (addr array byte) <- lookup *pixels-ah
260 var i/ecx: int <- copy 0
261 var max/edx: int <- length pixels
262 {
263 compare i, max
264 break-if->=
265 var curr/eax: (addr byte) <- index pixels, i
266 var zero/ebx: byte <- copy 0
267 copy-byte-to *curr, zero
268 i <- increment
269 loop
270 }
271 }
272
273 fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean {
274 var screen/esi: (addr screen) <- copy _screen
275 var y/eax: int <- copy 0
276 var height/ecx: (addr int) <- get screen, height
277 {
278 compare y, *height
279 break-if->=
280 var x/edx: int <- copy 0
281 var width/ebx: (addr int) <- get screen, width
282 {
283 compare x, *width
284 break-if->=
285 var g/eax: grapheme <- screen-grapheme-at screen, x, y
286 {
287 compare g, 0
288 break-if-=
289 compare g, 0x20/space
290 break-if-=
291 return 0/false
292 }
293 x <- increment
294 loop
295 }
296 y <- increment
297 loop
298 }
299 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
300 var pixels/eax: (addr array byte) <- lookup *pixels-ah
301 var y/ebx: int <- copy 0
302 var height-addr/edx: (addr int) <- get screen, height
303 var height/edx: int <- copy *height-addr
304 height <- shift-left 4/log2-font-height
305 {
306 compare y, height
307 break-if->=
308 var width-addr/edx: (addr int) <- get screen, width
309 var width/edx: int <- copy *width-addr
310 width <- shift-left 3/log2-font-width
311 var x/edi: int <- copy 0
312 {
313 compare x, width
314 break-if->=
315 var idx/ecx: int <- pixel-index screen, x, y
316 var color-addr/ecx: (addr byte) <- index pixels, idx
317 var color/ecx: byte <- copy-byte *color-addr
318 compare color, 0
319 {
320 break-if-=
321 return 0/false
322 }
323 x <- increment
324 loop
325 }
326 y <- increment
327 loop
328 }
329 return 1/true
330 }
331
332 fn clear-rect _screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
333 var screen/esi: (addr screen) <- copy _screen
334 {
335 compare screen, 0
336 break-if-!=
337 clear-rect-on-real-screen xmin, ymin, xmax, ymax, background-color
338 return
339 }
340
341 set-cursor-position screen, 0, 0
342 var y/eax: int <- copy ymin
343 var ymax/ecx: int <- copy ymax
344 {
345 compare y, ymax
346 break-if->=
347 var x/edx: int <- copy xmin
348 var xmax/ebx: int <- copy xmax
349 {
350 compare x, xmax
351 break-if->=
352 draw-code-point screen, 0x20/space, x, y, 0/fg, background-color
353 x <- increment
354 loop
355 }
356 y <- increment
357 loop
358 }
359 set-cursor-position screen, 0, 0
360 }
361
362
363
364 fn clear-real-screen {
365 var y/eax: int <- copy 0
366 {
367 compare y, 0x300/screen-height=768
368 break-if->=
369 var x/edx: int <- copy 0
370 {
371 compare x, 0x400/screen-width=1024
372 break-if->=
373 pixel-on-real-screen x, y, 0/color=black
374 x <- increment
375 loop
376 }
377 y <- increment
378 loop
379 }
380 }
381
382 fn clear-rect-on-real-screen xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
383 var y/eax: int <- copy ymin
384 y <- shift-left 4/log2-font-height
385 var ymax/ecx: int <- copy ymax
386 ymax <- shift-left 4/log2-font-height
387 {
388 compare y, ymax
389 break-if->=
390 var x/edx: int <- copy xmin
391 x <- shift-left 3/log2-font-width
392 var xmax/ebx: int <- copy xmax
393 xmax <- shift-left 3/log2-font-width
394 {
395 compare x, xmax
396 break-if->=
397 pixel-on-real-screen x, y, background-color
398 x <- increment
399 loop
400 }
401 y <- increment
402 loop
403 }
404 }
405
406 fn screen-grapheme-at _screen: (addr screen), x: int, y: int -> _/eax: grapheme {
407 var screen/esi: (addr screen) <- copy _screen
408 var idx/ecx: int <- screen-cell-index screen, x, y
409 var result/eax: grapheme <- screen-grapheme-at-idx screen, idx
410 return result
411 }
412
413 fn screen-grapheme-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: grapheme {
414 var screen/esi: (addr screen) <- copy _screen
415 var data-ah/eax: (addr handle array screen-cell) <- get screen, data
416 var data/eax: (addr array screen-cell) <- lookup *data-ah
417 var idx/ecx: int <- copy idx-on-stack
418 var offset/ecx: (offset screen-cell) <- compute-offset data, idx
419 var cell/eax: (addr screen-cell) <- index data, offset
420 var src/eax: (addr grapheme) <- get cell, data
421 return *src
422 }
423
424 fn screen-color-at _screen: (addr screen), x: int, y: int -> _/eax: int {
425 var screen/esi: (addr screen) <- copy _screen
426 var idx/ecx: int <- screen-cell-index screen, x, y
427 var result/eax: int <- screen-color-at-idx screen, idx
428 return result
429 }
430
431 fn screen-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int {
432 var screen/esi: (addr screen) <- copy _screen
433 var data-ah/eax: (addr handle array screen-cell) <- get screen, data
434 var data/eax: (addr array screen-cell) <- lookup *data-ah
435 var idx/ecx: int <- copy idx-on-stack
436 var offset/ecx: (offset screen-cell) <- compute-offset data, idx
437 var cell/eax: (addr screen-cell) <- index data, offset
438 var src/eax: (addr int) <- get cell, color
439 var result/eax: int <- copy *src
440 return result
441 }
442
443 fn screen-background-color-at _screen: (addr screen), x: int, y: int -> _/eax: int {
444 var screen/esi: (addr screen) <- copy _screen
445 var idx/ecx: int <- screen-cell-index screen, x, y
446 var result/eax: int <- screen-background-color-at-idx screen, idx
447 return result
448 }
449
450 fn screen-background-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int {
451 var screen/esi: (addr screen) <- copy _screen
452 var data-ah/eax: (addr handle array screen-cell) <- get screen, data
453 var data/eax: (addr array screen-cell) <- lookup *data-ah
454 var idx/ecx: int <- copy idx-on-stack
455 var offset/ecx: (offset screen-cell) <- compute-offset data, idx
456 var cell/eax: (addr screen-cell) <- index data, offset
457 var src/eax: (addr int) <- get cell, background-color
458 var result/eax: int <- copy *src
459 return result
460 }
461
462 fn pixel screen: (addr screen), x: int, y: int, color: int {
463 {
464 compare screen, 0
465 break-if-!=
466 pixel-on-real-screen x, y, color
467 return
468 }
469
470 var screen/esi: (addr screen) <- copy screen
471 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
472 var pixels/eax: (addr array byte) <- lookup *pixels-ah
473 {
474 compare pixels, 0
475 break-if-!=
476 abort "pixel graphics not enabled for this screen"
477 }
478 var idx/ecx: int <- pixel-index screen, x, y
479 var dest/ecx: (addr byte) <- index pixels, idx
480 var src/eax: byte <- copy-byte color
481 copy-byte-to *dest, src
482 }
483
484 fn pixel-index _screen: (addr screen), x: int, y: int -> _/ecx: int {
485 var screen/esi: (addr screen) <- copy _screen
486 {
487 compare x, 0
488 break-if->=
489 abort "screen-cell-index: negative x"
490 }
491 {
492 var xmax-a/eax: (addr int) <- get screen, width
493 var xmax/eax: int <- copy *xmax-a
494 xmax <- shift-left 3/log2-font-width
495 compare x, xmax
496 break-if-<
497 abort "screen-cell-index: x too high"
498 }
499 {
500 compare y, 0
501 break-if->=
502 abort "screen-cell-index: negative y"
503 }
504 {
505 var ymax-a/eax: (addr int) <- get screen, height
506 var ymax/eax: int <- copy *ymax-a
507 ymax <- shift-left 4/log2-font-height
508 compare y, ymax
509 break-if-<
510 abort "screen-cell-index: y too high"
511 }
512 var width-addr/eax: (addr int) <- get screen, width
513 var result/ecx: int <- copy y
514 result <- multiply *width-addr
515 result <- shift-left 3/log2-font-width
516 result <- add x
517 return result
518 }