tuxanci2-engine
Game engine for tuxanci2
Log | Files | Refs | README | LICENSE

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 }