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