https://github.com/akkartik/mu/blob/main/apps/life.mu
1
2
3
4
5
6
7
8 fn state _grid: (addr array boolean), x: int, y: int -> _/eax: boolean {
9
10 compare x, 0
11 {
12 break-if->=
13 return 0/false
14 }
15 compare y, 0
16 {
17 break-if->=
18 return 0/false
19 }
20 compare x, 0x80/width
21 {
22 break-if-<
23 return 0/false
24 }
25 compare y, 0x60/height
26 {
27 break-if-<
28 return 0/false
29 }
30 var idx/eax: int <- copy y
31 idx <- shift-left 7/log2width
32 idx <- add x
33 var grid/esi: (addr array boolean) <- copy _grid
34 var result/eax: (addr boolean) <- index grid, idx
35 return *result
36 }
37
38 fn set-state _grid: (addr array boolean), x: int, y: int, val: boolean {
39
40 var idx/eax: int <- copy y
41 idx <- shift-left 7/log2width
42 idx <- add x
43 var grid/esi: (addr array boolean) <- copy _grid
44 var result/eax: (addr boolean) <- index grid, idx
45 var src/ecx: boolean <- copy val
46 copy-to *result, src
47 }
48
49 fn num-live-neighbors grid: (addr array boolean), x: int, y: int -> _/eax: int {
50 var result/edi: int <- copy 0
51
52 decrement y
53 decrement x
54 var s/eax: boolean <- state grid, x, y
55 {
56 compare s, 0/false
57 break-if-=
58 result <- increment
59 }
60 increment x
61 s <- state grid, x, y
62 {
63 compare s, 0/false
64 break-if-=
65 result <- increment
66 }
67 increment x
68 s <- state grid, x, y
69 {
70 compare s, 0/false
71 break-if-=
72 result <- increment
73 }
74
75 increment y
76 s <- state grid, x, y
77 {
78 compare s, 0/false
79 break-if-=
80 result <- increment
81 }
82 subtract-from x, 2
83 s <- state grid, x, y
84 {
85 compare s, 0/false
86 break-if-=
87 result <- increment
88 }
89
90 increment y
91 s <- state grid, x, y
92 {
93 compare s, 0/false
94 break-if-=
95 result <- increment
96 }
97 increment x
98 s <- state grid, x, y
99 {
100 compare s, 0/false
101 break-if-=
102 result <- increment
103 }
104 increment x
105 s <- state grid, x, y
106 {
107 compare s, 0/false
108 break-if-=
109 result <- increment
110 }
111 return result
112 }
113
114 fn step old-grid: (addr array boolean), new-grid: (addr array boolean) {
115 var y/ecx: int <- copy 0
116 {
117 compare y, 0x60/height
118 break-if->=
119 var x/edx: int <- copy 0
120 {
121 compare x, 0x80/width
122 break-if->=
123 var n/eax: int <- num-live-neighbors old-grid, x, y
124
125 {
126 compare n, 2
127 break-if->=
128 set-state new-grid, x, y, 0/dead
129 }
130
131 {
132 compare n, 3
133 break-if-<=
134 set-state new-grid, x, y, 0/dead
135 }
136
137 {
138 compare n, 2
139 break-if-!=
140 var old-state/eax: boolean <- state old-grid, x, y
141 set-state new-grid, x, y, old-state
142 }
143
144 {
145 compare n, 3
146 break-if-!=
147 set-state new-grid, x, y, 1/live
148 }
149 x <- increment
150 loop
151 }
152 y <- increment
153 loop
154 }
155 }
156
157
158 fn render-square _x: int, _y: int, color: int {
159 var y/edx: int <- copy _y
160 y <- shift-left 3/log2side
161 var side/ebx: int <- copy 1
162 side <- shift-left 3/log2side
163 var ymax/ecx: int <- copy y
164 ymax <- add side
165 {
166 compare y, ymax
167 break-if->=
168 {
169 var x/eax: int <- copy _x
170 x <- shift-left 3/log2side
171 var xmax/ecx: int <- copy x
172 xmax <- add side
173 {
174 compare x, xmax
175 break-if->=
176 pixel-on-real-screen x, y, color
177 x <- increment
178 loop
179 }
180 }
181 y <- increment
182 loop
183 }
184 }
185
186 fn render grid: (addr array boolean) {
187 var y/ecx: int <- copy 0
188 {
189 compare y, 0xc0/height
190 break-if->=
191 var x/edx: int <- copy 0
192 {
193 compare x, 0x100/width
194 break-if->=
195 var state/eax: boolean <- state grid, x, y
196 compare state, 0/false
197 {
198 break-if-=
199 render-square x, y, 0/black
200 }
201 compare state, 0/false
202 {
203 break-if-!=
204 render-square x, y, 3/cyan
205 }
206 x <- increment
207 loop
208 }
209 y <- increment
210 loop
211 }
212 }
213
214 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
215
216
217
218
219
220
221 var grid1-storage: (handle array boolean)
222 var grid1-ah/eax: (addr handle array boolean) <- address grid1-storage
223 populate grid1-ah, 0x3000
224 var _grid1/eax: (addr array boolean) <- lookup *grid1-ah
225 var grid1/esi: (addr array boolean) <- copy _grid1
226 var grid2-storage: (handle array boolean)
227 var grid2-ah/eax: (addr handle array boolean) <- address grid2-storage
228 populate grid2-ah, 0x3000
229 var _grid2/eax: (addr array boolean) <- lookup *grid2-ah
230 var grid2/edi: (addr array boolean) <- copy _grid2
231
232 set-state grid1, 0x40, 0x2f, 1/live
233 set-state grid1, 0x41, 0x2f, 1/live
234 set-state grid1, 0x3f, 0x30, 1/live
235 set-state grid1, 0x40, 0x30, 1/live
236 set-state grid1, 0x40, 0x31, 1/live
237
238 render grid1
239 {
240 var key/eax: byte <- read-key keyboard
241 compare key, 0
242
243 break-if-!=
244
245 step grid1, grid2
246 render grid2
247
248
249 step grid2, grid1
250 render grid1
251
252 loop
253 }
254 }
255
256 fn linger {
257 var i/ecx: int <- copy 0
258 {
259 compare i, 0x10000000
260
261 break-if->=
262 i <- increment
263 loop
264 }
265 }