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

screen.c (2575B)


      1 #include <stdint.h>
      2 #include <stdlib.h>
      3 #include <stdbool.h>
      4 #include <stddef.h>
      5 #include "vm.h"
      6 #include "scene.h"
      7 #include "image.h"
      8 
      9 #define TA_SCREEN_NONE (-1)
     10 
     11 typedef struct {
     12 	uint32_t init;
     13 	uint32_t update;
     14 	uint32_t destroy;
     15 	bool registered;
     16 } ta_screen_entry;
     17 
     18 static ta_screen_entry *screens;
     19 static uint32_t screen_count;
     20 static int32_t current_screen;
     21 static int32_t pending_screen;
     22 
     23 static void screens_clear(void) {
     24 	if (screens != NULL) {
     25 		free(screens);
     26 	}
     27 
     28 	screens = NULL;
     29 	screen_count = 0;
     30 }
     31 
     32 static bool screens_grow(uint32_t new_count) {
     33 	ta_screen_entry *grown = (ta_screen_entry *)malloc((size_t)new_count * sizeof(ta_screen_entry));
     34 
     35 	if (grown == NULL) {
     36 		return false;
     37 	}
     38 
     39 	for (uint32_t i = 0; i < screen_count; i++) {
     40 		grown[i] = screens[i];
     41 	}
     42 
     43 	for (uint32_t i = screen_count; i < new_count; i++) {
     44 		grown[i].init = 0;
     45 		grown[i].update = 0;
     46 		grown[i].destroy = 0;
     47 		grown[i].registered = false;
     48 	}
     49 
     50 	if (screens != NULL) {
     51 		free(screens);
     52 	}
     53 
     54 	screens = grown;
     55 	screen_count = new_count;
     56 
     57 	return true;
     58 }
     59 
     60 void ta_screen_init(void) {
     61 	screens_clear();
     62 
     63 	current_screen = TA_SCREEN_NONE;
     64 	pending_screen = TA_SCREEN_NONE;
     65 }
     66 
     67 bool ta_screen_register(uint32_t id, uint32_t init, uint32_t update, uint32_t destroy) {
     68 	if (id == 0xFFFFFFFFu) {
     69 		return false;
     70 	}
     71 
     72 	if (id >= screen_count && !screens_grow(id + 1)) {
     73 		return false;
     74 	}
     75 
     76 	screens[id].init = init;
     77 	screens[id].update = update;
     78 	screens[id].destroy = destroy;
     79 	screens[id].registered = true;
     80 
     81 	return true;
     82 }
     83 
     84 bool ta_screen_switch(uint32_t id) {
     85 	if (id >= screen_count || !screens[id].registered) {
     86 		return false;
     87 	}
     88 
     89 	pending_screen = (int32_t)id;
     90 
     91 	return true;
     92 }
     93 
     94 bool ta_screen_update(void) {
     95 	while (pending_screen != TA_SCREEN_NONE) {
     96 		int32_t next_screen = pending_screen;
     97 
     98 		pending_screen = TA_SCREEN_NONE;
     99 
    100 		if (current_screen != TA_SCREEN_NONE && screens[current_screen].destroy != 0) {
    101 			if (!ta_vm_call(screens[current_screen].destroy, 0, 0, 0, NULL)) {
    102 				return false;
    103 			}
    104 		}
    105 
    106 		current_screen = next_screen;
    107 
    108 		if (screens[current_screen].init != 0) {
    109 			if (!ta_vm_call(screens[current_screen].init, 0, 0, 0, NULL)) {
    110 				return false;
    111 			}
    112 		}
    113 	}
    114 
    115 	if (current_screen == TA_SCREEN_NONE || screens[current_screen].update == 0) {
    116 		return false;
    117 	}
    118 
    119 	ta_scene_begin();
    120 
    121 	if (!ta_vm_call(screens[current_screen].update, 0, 0, 0, NULL)) {
    122 		return false;
    123 	}
    124 
    125 	return ta_scene_end();
    126 }
    127 
    128 void ta_screen_destroy(void) {
    129 	current_screen = TA_SCREEN_NONE;
    130 	pending_screen = TA_SCREEN_NONE;
    131 	ta_scene_invalidate();
    132 
    133 	screens_clear();
    134 
    135 	ta_image_release();
    136 }