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 {
124 compare x, 0
125 break-if->=
126 abort "screen-cell-index: negative x"
127 }
128 {
129 var xmax/eax: (addr int) <- get screen, width
130 var xcurr/ecx: int <- copy x
131 compare xcurr, *xmax
132 break-if-<
133 abort "screen-cell-index: x too high"
134 }
135 {
136 compare y, 0
137 break-if->=
138 abort "screen-cell-index: negative y"
139 }
140 {
141 var ymax/eax: (addr int) <- get screen, height
142 var ycurr/ecx: int <- copy y
143 compare ycurr, *ymax
144 break-if-<
145 abort "screen-cell-index: y too high"
146 }
147 var width-addr/eax: (addr int) <- get screen, width
148 var result/ecx: int <- copy y
149 result <- multiply *width-addr
150 result <- add x
151 return result
152 }
153
154 fn cursor-position _screen: (addr screen) -> _/eax: int, _/ecx: int {
155 var screen/esi: (addr screen) <- copy _screen
156 {
157 compare screen, 0
158 break-if-!=
159 var x/eax: int <- copy 0
160 var y/ecx: int <- copy 0
161 x, y <- cursor-position-on-real-screen
162 return x, y
163 }
164
165 var cursor-x-addr/eax: (addr int) <- get screen, cursor-x
166 var cursor-y-addr/ecx: (addr int) <- get screen, cursor-y
167 return *cursor-x-addr, *cursor-y-addr
168 }
169
170 fn set-cursor-position _screen: (addr screen), x: int, y: int {
171 var screen/esi: (addr screen) <- copy _screen
172 {
173 compare screen, 0
174 break-if-!=
175 set-cursor-position-on-real-screen x, y
176 return
177 }
178
179
180 {
181 compare x, 0
182 break-if->=
183 return
184 }
185
186 {
187 var width-addr/eax: (addr int) <- get screen, width
188 var width/eax: int <- copy *width-addr
189 compare x, width
190 break-if-<=
191 return
192 }
193
194 {
195 compare y, 0
196 break-if->=
197 return
198 }
199
200 {
201 var height-addr/eax: (addr int) <- get screen, height
202 var height/eax: int <- copy *height-addr
203 compare y, height
204 break-if-<
205 return
206 }
207
208 var dest/edi: (addr int) <- get screen, cursor-x
209 var src/eax: int <- copy x
210 copy-to *dest, src
211
212 dest <- get screen, cursor-y
213 src <- copy y
214 copy-to *dest, src
215 }
216
217 fn draw-cursor screen: (addr screen), g: grapheme {
218 {
219 compare screen, 0
220 break-if-!=
221 draw-cursor-on-real-screen g
222 return
223 }
224
225 var cursor-x/eax: int <- copy 0
226 var cursor-y/ecx: int <- copy 0
227 cursor-x, cursor-y <- cursor-position screen
228 draw-grapheme screen, g, cursor-x, cursor-y, 0/fg, 7/bg
229 }
230
231 fn clear-screen _screen: (addr screen) {
232 var screen/esi: (addr screen) <- copy _screen
233 {
234 compare screen, 0
235 break-if-!=
236 clear-real-screen
237 return
238 }
239
240 set-cursor-position screen, 0, 0
241 var y/eax: int <- copy 0
242 var height/ecx: (addr int) <- get screen, height
243 {
244 compare y, *height
245 break-if->=
246 var x/edx: int <- copy 0
247 var width/ebx: (addr int) <- get screen, width
248 {
249 compare x, *width
250 break-if->=
251 draw-code-point screen, 0x20/space, x, y, 0/fg=black, 0/bg=black
252 x <- increment
253 loop
254 }
255 y <- increment
256 loop
257 }
258 set-cursor-position screen, 0, 0
259 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
260 var pixels/eax: (addr array byte) <- lookup *pixels-ah
261 var i/ecx: int <- copy 0
262 var max/edx: int <- length pixels
263 {
264 compare i, max
265 break-if->=
266 var curr/eax: (addr byte) <- index pixels, i
267 var zero/ebx: byte <- copy 0
268 copy-byte-to *curr, zero
269 i <- increment
270 loop
271 }
272 }
273
274 fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean {
275 var screen/esi: (addr screen) <- copy _screen
276 var y/eax: int <- copy 0
277 var height/ecx: (addr int) <- get screen, height
278 {
279 compare y, *height
280 break-if->=
281 var x/edx: int <- copy 0
282 var width/ebx: (addr int) <- get screen, width
283 {
284 compare x, *width
285 break-if->=
286 var g/eax: grapheme <- screen-grapheme-at screen, x, y
287 {
288 compare g, 0
289 break-if-=
290 compare g, 0x20/space
291 break-if-=
292 return 0/false
293 }
294 x <- increment
295 loop
296 }
297 y <- increment
298 loop
299 }
300 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
301 var pixels/eax: (addr array byte) <- lookup *pixels-ah
302 var y/ebx: int <- copy 0
303 var height-addr/edx: (addr int) <- get screen, height
304 var height/edx: int <- copy *height-addr
305 height <- shift-left 4/log2-font-height
306 {
307 compare y, height
308 break-if->=
309 var width-addr/edx: (addr int) <- get screen, width
310 var width/edx: int <- copy *width-addr
311 width <- shift-left 3/log2-font-width
312 var x/edi: int <- copy 0
313 {
314 compare x, width
315 break-if->=
316 var idx/ecx: int <- pixel-index screen, x, y
317 var color-addr/ecx: (addr byte) <- index pixels, idx
318 var color/ecx: byte <- copy-byte *color-addr
319 compare color, 0
320 {
321 break-if-=
322 return 0/false
323 }
324 x <- increment
325 loop
326 }
327 y <- increment
328 loop
329 }
330 return 1/true
331 }
332
333 fn clear-rect _screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
334 var screen/esi: (addr screen) <- copy _screen
335 {
336 compare screen, 0
337 break-if-!=
338 clear-rect-on-real-screen xmin, ymin, xmax, ymax, background-color
339 return
340 }
341
342 set-cursor-position screen, 0, 0
343 var y/eax: int <- copy ymin
344 var ymax/ecx: int <- copy ymax
345 {
346 compare y, ymax
347 break-if->=
348 var x/edx: int <- copy xmin
349 var xmax/ebx: int <- copy xmax
350 {
351 compare x, xmax
352 break-if->=
353 draw-code-point screen, 0x20/space, x, y, 0/fg, background-color
354 x <- increment
355 loop
356 }
357 y <- increment
358 loop
359 }
360 set-cursor-position screen, 0, 0
361 }
362
363
364
365 fn clear-real-screen {
366 var y/eax: int <- copy 0
367 {
368 compare y, 0x300/screen-height=768
369 break-if->=
370 var x/edx: int <- copy 0
371 {
372 compare x, 0x400/screen-width=1024
373 break-if->=
374 pixel-on-real-screen x, y, 0/color=black
375 x <- increment
376 loop
377 }
378 y <- increment
379 loop
380 }
381 }
382
383 fn clear-rect-on-real-screen xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
384 var y/eax: int <- copy ymin
385 y <- shift-left 4/log2-font-height
386 var ymax/ecx: int <- copy ymax
387 ymax <- shift-left 4/log2-font-height
388 {
389 compare y, ymax
390 break-if->=
391 var x/edx: int <- copy xmin
392 x <- shift-left 3/log2-font-width
393 var xmax/ebx: int <- copy xmax
394 xmax <- shift-left 3/log2-font-width
395 {
396 compare x, xmax
397 break-if->=
398 pixel-on-real-screen x, y, background-color
399 x <- increment
400 loop
401 }
402 y <- increment
403 loop
404 }
405 }
406
407 fn screen-grapheme-at _screen: (addr screen), x: int, y: int -> _/eax: grapheme {
408 var screen/esi: (addr screen) <- copy _screen
409 var idx/ecx: int <- screen-cell-index screen, x, y
410 var result/eax: grapheme <- screen-grapheme-at-idx screen, idx
411 return result
412 }
413
414 fn screen-grapheme-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: grapheme {
415 var screen/esi: (addr screen) <- copy _screen
416 var data-ah/eax: (addr handle array screen-cell) <- get screen, data
417 var data/eax: (addr array screen-cell) <- lookup *data-ah
418 var idx/ecx: int <- copy idx-on-stack
419 var offset/ecx: (offset screen-cell) <- compute-offset data, idx
420 var cell/eax: (addr screen-cell) <- index data, offset
421 var src/eax: (addr grapheme) <- get cell, data
422 return *src
423 }
424
425 fn screen-color-at _screen: (addr screen), x: int, y: int -> _/eax: int {
426 var screen/esi: (addr screen) <- copy _screen
427 var idx/ecx: int <- screen-cell-index screen, x, y
428 var result/eax: int <- screen-color-at-idx screen, idx
429 return result
430 }
431
432 fn screen-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int {
433 var screen/esi: (addr screen) <- copy _screen
434 var data-ah/eax: (addr handle array screen-cell) <- get screen, data
435 var data/eax: (addr array screen-cell) <- lookup *data-ah
436 var idx/ecx: int <- copy idx-on-stack
437 var offset/ecx: (offset screen-cell) <- compute-offset data, idx
438 var cell/eax: (addr screen-cell) <- index data, offset
439 var src/eax: (addr int) <- get cell, color
440 var result/eax: int <- copy *src
441 return result
442 }
443
444 fn screen-background-color-at _screen: (addr screen), x: int, y: int -> _/eax: int {
445 var screen/esi: (addr screen) <- copy _screen
446 var idx/ecx: int <- screen-cell-index screen, x, y
447 var result/eax: int <- screen-background-color-at-idx screen, idx
448 return result
449 }
450
451 fn screen-background-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int {
452 var screen/esi: (addr screen) <- copy _screen
453 var data-ah/eax: (addr handle array screen-cell) <- get screen, data
454 var data/eax: (addr array screen-cell) <- lookup *data-ah
455 var idx/ecx: int <- copy idx-on-stack
456 var offset/ecx: (offset screen-cell) <- compute-offset data, idx
457 var cell/eax: (addr screen-cell) <- index data, offset
458 var src/eax: (addr int) <- get cell, background-color
459 var result/eax: int <- copy *src
460 return result
461 }
462
463 fn pixel screen: (addr screen), x: int, y: int, color: int {
464 {
465 compare screen, 0
466 break-if-!=
467 pixel-on-real-screen x, y, color
468 return
469 }
470
471 var screen/esi: (addr screen) <- copy screen
472 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
473 var pixels/eax: (addr array byte) <- lookup *pixels-ah
474 {
475 compare pixels, 0
476 break-if-!=
477 abort "pixel graphics not enabled for this screen"
478 }
479 var idx/ecx: int <- pixel-index screen, x, y
480 var dest/ecx: (addr byte) <- index pixels, idx
481 var src/eax: byte <- copy-byte color
482 copy-byte-to *dest, src
483 }
484
485 fn pixel-index _screen: (addr screen), x: int, y: int -> _/ecx: int {
486 var screen/esi: (addr screen) <- copy _screen
487 {
488 compare x, 0
489 break-if->=
490 abort "screen-cell-index: negative x"
491 }
492 {
493 var xmax-a/eax: (addr int) <- get screen, width
494 var xmax/eax: int <- copy *xmax-a
495 xmax <- shift-left 3/log2-font-width
496 compare x, xmax
497 break-if-<
498 abort "screen-cell-index: x too high"
499 }
500 {
501 compare y, 0
502 break-if->=
503 abort "screen-cell-index: negative y"
504 }
505 {
506 var ymax-a/eax: (addr int) <- get screen, height
507 var ymax/eax: int <- copy *ymax-a
508 ymax <- shift-left 4/log2-font-height
509 compare y, ymax
510 break-if-<
511 abort "screen-cell-index: y too high"
512 }
513 var width-addr/eax: (addr int) <- get screen, width
514 var result/ecx: int <- copy y
515 result <- multiply *width-addr
516 result <- shift-left 3/log2-font-width
517 result <- add x
518 return result
519 }
520
521
522
523
524 fn copy-pixels _screen: (addr screen), target-screen: (addr screen) {
525 var screen/esi: (addr screen) <- copy _screen
526 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
527 var _pixels/eax: (addr array byte) <- lookup *pixels-ah
528 var pixels/edi: (addr array byte) <- copy _pixels
529 var width-a/edx: (addr int) <- get screen, width
530 var width/edx: int <- copy *width-a
531 width <- shift-left 3/log2-font-width
532 var height-a/ebx: (addr int) <- get screen, height
533 var height/ebx: int <- copy *height-a
534 height <- shift-left 4/log2-font-height
535 var i/esi: int <- copy 0
536 var y/ecx: int <- copy 0
537 {
538
539 compare y, height
540 break-if->=
541 var x/eax: int <- copy 0
542 {
543 compare x, width
544 break-if->=
545 {
546 var color-addr/ebx: (addr byte) <- index pixels, i
547 var color/ebx: byte <- copy-byte *color-addr
548 var color2/ebx: int <- copy color
549 pixel target-screen, x, y, color2
550 }
551 x <- increment
552 i <- increment
553 loop
554 }
555 y <- increment
556 loop
557 }
558 }