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