syscall.c (7370B)
1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
4 #include <stddef.h>
5 #include "vm.h"
6 #include "text.h"
7 #include "abi.h"
8 #include "scene.h"
9 #include "screen.h"
10 #include "shapes.h"
11 #include "keyboard.h"
12 #include "image.h"
13 #include "ft2.h"
14 #include "api.h"
15 #include "tab.h"
16
17 static bool get_file(uint32_t file, const uint8_t **data, uint32_t *length) {
18 if (file > TA_TAB_MAX_FILES) {
19 return false;
20 }
21
22 return ta_tab_find((uint8_t)file, data, length);
23 }
24
25 static ta_text **texts;
26 static uint32_t text_count;
27
28 static ta_text *text_get(uint32_t handle) {
29 if (handle == 0 || handle > text_count) {
30 return NULL;
31 }
32
33 return texts[handle - 1];
34 }
35
36 static bool text_slot_find(uint32_t *slot) {
37 for (uint32_t i = 0; i < text_count; i++) {
38 if (texts[i] == NULL) {
39 *slot = i;
40
41 return true;
42 }
43 }
44
45 ta_text **grown = (ta_text **)malloc((size_t)(text_count + 1) * sizeof(ta_text *));
46
47 if (grown == NULL) {
48 return false;
49 }
50
51 for (uint32_t i = 0; i < text_count; i++) {
52 grown[i] = texts[i];
53 }
54
55 grown[text_count] = NULL;
56
57 if (texts != NULL) {
58 free(texts);
59 }
60
61 texts = grown;
62 *slot = text_count;
63 text_count++;
64
65 return true;
66 }
67
68 static uint32_t text_create(const char *string, uint32_t size, uint32_t color, uint32_t border_width, uint32_t border_color) {
69 if (size == 0) {
70 return 0;
71 }
72
73 ta_text *text = (ta_text *)malloc(sizeof(ta_text));
74
75 if (text == NULL) {
76 return 0;
77 }
78
79 text->text = string;
80 text->x = 0;
81 text->y = 0;
82 text->size = (uint8_t)size;
83 text->red = (uint8_t)((color >> 16) & 255);
84 text->green = (uint8_t)((color >> 8) & 255);
85 text->blue = (uint8_t)(color & 255);
86 text->border_width = (uint8_t)border_width;
87 text->border_red = (uint8_t)((border_color >> 16) & 255);
88 text->border_green = (uint8_t)((border_color >> 8) & 255);
89 text->border_blue = (uint8_t)(border_color & 255);
90 text->width = 0;
91 text->height = 0;
92 text->sprite = NULL;
93
94 ta_text_rasterize(text);
95
96 text->text = NULL;
97
98 if (!text->sprite) {
99 free(text);
100 return 0;
101 }
102
103 uint32_t slot;
104
105 if (!text_slot_find(&slot)) {
106 ta_text_destroy(text);
107 free(text);
108
109 return 0;
110 }
111
112 texts[slot] = text;
113
114 return slot + 1;
115 }
116
117 static void text_destroy(uint32_t handle) {
118 ta_text *text = text_get(handle);
119
120 if (!text) {
121 return;
122 }
123
124 ta_text_destroy(text);
125 free(text);
126 texts[handle - 1] = NULL;
127 }
128
129 ta_vm_status ta_syscall_handler(ta_vm *vm) {
130 uint32_t *registers = vm->regs;
131 uint32_t number = registers[TA_VM_REG_A7];
132 uint32_t args[6] = {
133 registers[TA_VM_REG_A0],
134 registers[TA_VM_REG_A1],
135 registers[TA_VM_REG_A2],
136 registers[TA_VM_REG_A3],
137 registers[TA_VM_REG_A4],
138 registers[TA_VM_REG_A5]
139 };
140 uint32_t result = 0;
141
142 switch (number) {
143 case TA_SYS_DISPLAY_WIDTH: {
144 result = ta_display->width;
145
146 break;
147 }
148 case TA_SYS_DISPLAY_HEIGHT: {
149 result = ta_display->height;
150
151 break;
152 }
153 case TA_SYS_DISPLAY_SPRITE_MODE: {
154 result = ta_display->sprite_mode ? 1 : 0;
155
156 break;
157 }
158 case TA_SYS_KEYBOARD_IS_DOWN: {
159 result = ta_keyboard_is_down((ta_keyboard_keys)args[0]) ? 1 : 0;
160
161 break;
162 }
163 case TA_SYS_IMAGE_DRAW: {
164 const uint8_t *data;
165 uint32_t length;
166
167 if (!get_file(args[0], &data, &length)) {
168 break;
169 }
170
171 result = ta_scene_image(data, length, (ta_fixed)args[1], (ta_fixed)args[2], (ta_fixed)args[3], (ta_fixed)args[4], (uint16_t)args[5]) ? 1 : 0;
172
173 break;
174 }
175 case TA_SYS_IMAGE_INIT: {
176 const uint8_t *data;
177 uint32_t length;
178
179 if (!get_file(args[0], &data, &length)) {
180 break;
181 }
182
183 result = ta_image_init(data, length) ? 1 : 0;
184
185 break;
186 }
187 case TA_SYS_IMAGE_GET_SIZE: {
188 const uint8_t *data;
189 uint32_t length;
190 uint32_t *width;
191 uint32_t *height;
192
193 if (!get_file(args[0], &data, &length)) {
194 break;
195 }
196
197 width = (uint32_t *)ta_vm_translate_pointer(vm, args[1], sizeof(uint32_t));
198 height = (uint32_t *)ta_vm_translate_pointer(vm, args[2], sizeof(uint32_t));
199
200 if (!width || !height) {
201 return TA_VM_FAULT_MEMORY;
202 }
203
204 result = ta_image_get_size(data, width, height) ? 1 : 0;
205
206 break;
207 }
208 case TA_SYS_TEXT_CREATE: {
209 const char *string = ta_vm_cstr(vm, args[0]);
210
211 if (!string) {
212 return TA_VM_FAULT_MEMORY;
213 }
214
215 result = text_create(string, args[1], args[2], args[3], args[4]);
216
217 break;
218 }
219 case TA_SYS_TEXT_WIDTH: {
220 ta_text *text = text_get(args[0]);
221
222 result = text ? text->width : 0;
223
224 break;
225 }
226 case TA_SYS_TEXT_HEIGHT: {
227 ta_text *text = text_get(args[0]);
228
229 result = text ? text->height : 0;
230
231 break;
232 }
233 case TA_SYS_TEXT_DRAW: {
234 ta_text *text = text_get(args[0]);
235
236 if (text) {
237 ta_scene_text(text, args[1], args[2]);
238 }
239
240 break;
241 }
242 case TA_SYS_TEXT_DESTROY: {
243 text_destroy(args[0]);
244
245 break;
246 }
247 case TA_SYS_TEXT_CHANGE_COLOR: {
248 result = ta_text_change_color(text_get(args[0]), args[1]) ? 1 : 0;
249
250 break;
251 }
252 case TA_SYS_SCREEN_REGISTER: {
253 result = ta_screen_register(args[0], args[1], args[2], args[3]) ? 1 : 0;
254
255 break;
256 }
257 case TA_SYS_SCREEN_SWITCH: {
258 result = ta_screen_switch(args[0]) ? 1 : 0;
259
260 break;
261 }
262 case TA_SYS_SHAPES_PIXEL: {
263 uint32_t shape_args[6] = {args[0], args[1], 0, 0, 0, 0};
264 result = ta_scene_shape(1, shape_args, args[2]) ? 1 : 0;
265 break;
266 }
267 case TA_SYS_SHAPES_RECTANGLE:
268 case TA_SYS_SHAPES_OVAL: {
269 uint32_t shape_args[6] = {args[0], args[1], args[2], args[3], 0, 0};
270 result = ta_scene_shape(registers[TA_VM_REG_A7] == TA_SYS_SHAPES_RECTANGLE ? 2 : 4, shape_args, args[4]) ? 1 : 0;
271 break;
272 }
273 case TA_SYS_SHAPES_TRIANGLE: {
274 const uint32_t *coordinates = (const uint32_t *)ta_vm_translate_pointer(vm, args[0], 6 * sizeof(uint32_t));
275 if (coordinates == NULL) return TA_VM_FAULT_MEMORY;
276 result = ta_scene_shape(3, coordinates, args[1]) ? 1 : 0;
277 break;
278 }
279 case TA_SYS_FT2_LOAD: {
280 const uint8_t *data;
281 uint32_t length;
282
283 if (!get_file(args[0], &data, &length)) {
284 break;
285 }
286
287 result = ta_ft2_init(data, length) ? 1 : 0;
288
289 break;
290 }
291 case TA_SYS_FT2_PLAY: {
292 result = ta_ft2_play() ? 1 : 0;
293
294 break;
295 }
296 case TA_SYS_FT2_STOP: {
297 ta_ft2_stop();
298
299 break;
300 }
301 case TA_SYS_FT2_IS_PLAYING: {
302 result = ta_ft2_is_playing() ? 1 : 0;
303
304 break;
305 }
306 case TA_SYS_FILE_SIZE: {
307 const uint8_t *data;
308 uint32_t length;
309
310 result = get_file(args[0], &data, &length) ? length : 0xFFFFFFFFu;
311
312 break;
313 }
314 case TA_SYS_FILE_READ: {
315 const uint8_t *data;
316 uint32_t length;
317
318 if (!get_file(args[0], &data, &length)) {
319 break;
320 }
321
322 if (length == 0) {
323 result = 1;
324
325 break;
326 }
327
328 uint8_t *destination = (uint8_t *)ta_vm_translate_pointer(vm, args[1], length);
329
330 if (destination == NULL) {
331 return TA_VM_FAULT_MEMORY;
332 }
333
334 for (uint32_t i = 0; i < length; i++) {
335 destination[i] = data[i];
336 }
337
338 result = 1;
339
340 break;
341 }
342 case TA_SYS_FILE_EXEC: {
343 const uint8_t *data;
344 uint32_t length;
345
346 if (!get_file(args[0], &data, &length) || length == 0) {
347 break;
348 }
349
350 ta_vm_request_exec((uint8_t)args[0]);
351
352 return TA_VM_YIELDED;
353 }
354 default: {
355 return TA_VM_FAULT_ILLEGAL;
356 }
357 }
358
359 registers[TA_VM_REG_A0] = result;
360
361 return TA_VM_RUNNING;
362 }
363
364 void ta_syscall_reset(void) {
365 ta_ft2_destroy();
366 ta_scene_invalidate();
367 ta_image_release();
368
369 for (uint32_t i = 0; i < text_count; i++) {
370 if (texts[i] != NULL) {
371 ta_text_destroy(texts[i]);
372 free(texts[i]);
373 }
374 }
375
376 if (texts != NULL) {
377 free(texts);
378 }
379
380 texts = NULL;
381 text_count = 0;
382 }