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