-
Notifications
You must be signed in to change notification settings - Fork 2
/
menu.asm
287 lines (261 loc) · 8.45 KB
/
menu.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
; menu routines
const MENU_SELECTED_BACKGROUND_COLOR: 0xFFFFFFFF
const MENU_SELECTED_TEXT_COLOR: 0xFF000000
const MENU_UNSELECTED_BACKGROUND_COLOR: 0xFF3F3F3F
const MENU_UNSELECTED_TEXT_COLOR: 0xFFFFFFFF
; draw menu items
; inputs:
; r0: pointer to menu bar root struct
; r1: selected root menu item
; r2: hovering menu item (or 0xFFFFFFFF for none)
; outputs:
; none
draw_menu_items:
push r0
push r1
push r2
push r3
push r4
push r5
push r6
push r7
push r8
push r29
push r30
push r31
; calculate the X position of the menu
mov r31, r1 ; load number of the selected item into r31 for looping
mov r30, 16 ; X counter
cmp r31, 0 ; we don't need to loop if this is menu 0
ifz jmp draw_menu_items_calculate_x_skip
mov r4, r0
add r4, 5 ; point to start of root menu items text pointer
draw_menu_items_calculate_x_loop:
mov r3, [r4] ; get pointer to text
movz.8 r3, [r3] ; get text length byte
add r3, 2 ; add 2 for the spaces on each side of the text
mul r3, 8 ; characters are 8 pixels wide
add r30, r3 ; add length to X counter
add r4, 8 ; point to next text pointer
loop draw_menu_items_calculate_x_loop
draw_menu_items_calculate_x_skip:
sub r30, 8 ; move the menu to the left by 8 pixels
mov.16 [MENU_POSITION_X], r30
mov r31, r0
inc r31 ; point to menu list pointer
mul r1, 8 ; point to the selected menu
add r31, r1
mov r0, [r31] ; load menu list pointer
movz.8 r31, [r0] ; load number of menu items
mov r30, r2 ; r30: number of the hovered item
mov r29, 0 ; counter of how many menu items drawn so far
; calculate the required height for the menu overlay
; multiply the number of menu items by 16 (the font is 16 pixels tall)
mov r1, r31
mul r1, 16
mov.16 [MENU_HEIGHT], r1
; calculate the required width for the menu overlay
; multiply the width by 8 (the font is 8 pixels wide)
mov r1, r0
inc r1
movz.8 r1, [r1] ; load width of menu
mov r8, r1 ; save the width in characters in r8 for later
mul r1, 8
mov.16 [MENU_WIDTH], r1
push r0
; set properties of overlay 29
mov.16 [MENU_POSITION_Y], 16
mov [MENU_FRAMEBUFFER_PTR], MENU_FRAMEBUFFER
mov r0, 0x8000001D ; overlay 29: position
mov.16 r1, [MENU_POSITION_Y]
sla r1, 16
mov.16 r1, [MENU_POSITION_X]
out r0, r1
mov r0, 0x8000011D ; overlay 29: size
mov.16 r1, [MENU_HEIGHT]
sla r1, 16
mov.16 r1, [MENU_WIDTH]
out r0, r1
mov r0, 0x8000021D ; overlay 29: framebuffer pointer
mov r1, [MENU_FRAMEBUFFER_PTR]
out r0, r1
mov r0, 0x8000031D
out r0, 1
; draw empty menu
mov r6, r31 ; outer loop counter
movz.8 r0, ' '
mov r1, 0
mov r2, 0
mov r5, 29
draw_empty_menu_loop:
mov r7, r8 ; inner loop counter
cmp r30, r29
;ifz mov r3, MENU_UNSELECTED_BACKGROUND_COLOR
ifz mov r4, MENU_SELECTED_BACKGROUND_COLOR
;ifnz mov r3, MENU_SELECTED_BACKGROUND_COLOR
ifnz mov r4, MENU_UNSELECTED_BACKGROUND_COLOR
draw_empty_menu_line_loop:
call draw_font_tile_to_overlay
add r1, 8
dec r7
ifnz jmp draw_empty_menu_line_loop
mov r1, 0
add r2, 16
inc r29
dec r6
ifnz jmp draw_empty_menu_loop
mov r29, 0 ; counter of how many menu items drawn so far
pop r0
; draw menu text
add r0, 3 ; point to start of menu items text
mov r2, 0 ; Y = 0
draw_menu_text_loop:
cmp r30, r29
ifz mov r3, MENU_SELECTED_TEXT_COLOR
ifz mov r4, MENU_SELECTED_BACKGROUND_COLOR
ifnz mov r3, MENU_UNSELECTED_TEXT_COLOR
ifnz mov r4, MENU_UNSELECTED_BACKGROUND_COLOR
mov r1, 0 ; X = 0
call draw_str_to_overlay ; draw menu item text
mov r1, r0
dec r1 ; point to length byte of this menu item
movz.8 r1, [r1] ; load length byte
inc r1 ; add one to count the null-terminator
add r0, r1 ; add length to menu item text pointer
inc r0 ; increment past length byte
add r2, 16 ; add 16 to Y
inc r29
loop draw_menu_text_loop
pop r31
pop r30
pop r29
pop r8
pop r7
pop r6
pop r5
pop r4
pop r3
pop r2
pop r1
pop r0
ret
; hide the menu
; inputs:
; r0: pointer to menu bar root struct
; outputs:
; none
close_menu:
push r1
; disable overlay 29
mov r1, 0x8000031D
out r1, 0
mov r1, 0xFFFFFFFF
call draw_menu_bar_root_items
pop r1
ret
; update the currently open menu
; detects mouse movements over the menu and handles clicks
; this should only be called if a event_type_menu_update event is received
; inputs:
; *** these inputs should already be in the required registers from the event parameters ***
; r1: pointer to menu bar root struct
; r2: selected root menu item
; r3: hovering menu item (or 0xFFFFFFFF for none)
; outputs:
; none
; the event is added back into the event queue if the menu is still open
menu_update_event:
push r0
push r1
push r2
push r3
push r4
push r5
push r6
push r7
push r8
push r9
mov r8, r1 ; r8: pointer to menu bar root struct
mov r9, r2 ; r9: selected root menu item
mov r10, r3 ; r10: hovering menu item (or 0xFFFFFFFF for none)
; check if the menu overlay is enabled
; if the menu was closed then exit without readding the update event to the event queue
in r0, 0x8000031D
cmp r0, 0
ifz jmp menu_update_event_end_no_add
; get the current mouse position and check if the menu overlay covers that position
; if the mouse is not in the menu, then there is nothing to do
call get_mouse_position
mov r2, 29
call check_if_enabled_overlay_covers_position
ifnz jmp menu_update_event_end_add
; make the mouse position relative to the menu overlay
mov r2, 29
call make_coordinates_relative_to_overlay
; if the currently hovered item is different than the hovered item in the event parameters,
; then redraw the menu with correct hovered item
div r1, 16 ; mouse Y / 16
cmp r1, r10 ; compare the currently hovered item to the hovered item in event parameter 2
ifz jmp menu_update_event_no_redraw
mov r10, r1 ; set the hovering item to the currently hovering item
mov r2, r1
mov r1, r9
mov r0, r8
call draw_menu_items
menu_update_event_no_redraw:
; check the mouse held bit
; this is kinda hacky but it works
call get_mouse_button
bts r0, 2
ifnz jmp menu_update_event_clicked
jmp menu_update_event_end_add
menu_update_event_clicked:
; wait until the mouse button is released
; this is extremely hacky
call get_mouse_button
bts r0, 2
ifnz jmp menu_update_event_clicked
; add an EVENT_TYPE_MENU_CLICK event
mov r1, r8 ; event parameter 0: pointer to menu bar root struct
mov r2, r9 ; event parameter 1: selected root menu item
mov r3, r10 ; event parameter 2: selected menu item
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r0, EVENT_TYPE_MENU_CLICK
call new_event
; add an EVENT_TYPE_MENU_ACK event
mov r1, 0
mov r2, 0
mov r3, 0
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r0, EVENT_TYPE_MENU_ACK
call new_event
jmp menu_update_event_end_no_add
menu_update_event_end_add:
; readd the event_type_menu_update event to the event queue
mov r1, r8 ; event parameter 0: pointer to menu bar root struct
mov r2, r9 ; event parameter 1: selected root menu item
mov r3, r10 ; event parameter 2: hovering menu item (or 0xFFFFFFFF for none)
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r0, EVENT_TYPE_MENU_UPDATE
call new_event
menu_update_event_end_no_add:
pop r9
pop r8
pop r7
pop r6
pop r5
pop r4
pop r3
pop r2
pop r1
pop r0
ret