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