1 #include <stdlib.h>
2 #include <string.h>
3 
4 #include "shadowdive/animation.h"
5 #include "shadowdive/bkanim.h"
6 #include "shadowdive/error.h"
7 
sd_bk_anim_create(sd_bk_anim * bka)8 int sd_bk_anim_create(sd_bk_anim *bka) {
9     if(bka == NULL) {
10         return SD_INVALID_INPUT;
11     }
12     // clear everything
13     memset(bka, 0, sizeof(sd_bk_anim));
14     return SD_SUCCESS;
15 }
16 
sd_bk_anim_copy(sd_bk_anim * dst,const sd_bk_anim * src)17 int sd_bk_anim_copy(sd_bk_anim *dst, const sd_bk_anim *src) {
18     int ret;
19     if(dst == NULL || src == NULL) {
20         return SD_INVALID_INPUT;
21     }
22 
23     // Clear destination
24     memset(dst, 0, sizeof(sd_bk_anim));
25 
26     // Basic stuff
27     dst->null = src->null;
28     dst->chain_hit = src->chain_hit;
29     dst->chain_no_hit = src->chain_no_hit;
30     dst->load_on_start = src->load_on_start;
31     dst->probability = src->probability;
32     dst->hazard_damage = src->hazard_damage;
33 
34     // Footer string
35     strcpy(dst->footer_string, src->footer_string);
36 
37     // Copy animation (if exists)
38     if(src->animation != NULL) {
39         if((dst->animation = malloc(sizeof(sd_animation))) == NULL) {
40             return SD_OUT_OF_MEMORY;
41         }
42         if((ret = sd_animation_copy(dst->animation, src->animation)) != SD_SUCCESS) {
43             return ret;
44         }
45     }
46 
47     return SD_SUCCESS;
48 }
49 
sd_bk_anim_free(sd_bk_anim * bka)50 void sd_bk_anim_free(sd_bk_anim *bka) {
51     if(bka->animation != NULL) {
52         sd_animation_free(bka->animation);
53         free(bka->animation);
54         bka->animation = NULL;
55     }
56 }
57 
sd_bk_anim_load(sd_reader * r,sd_bk_anim * bka)58 int sd_bk_anim_load(sd_reader *r, sd_bk_anim *bka) {
59     int ret;
60     uint16_t size;
61 
62     // BK Specific animation header
63     bka->null = sd_read_ubyte(r);
64     bka->chain_hit = sd_read_ubyte(r);
65     bka->chain_no_hit = sd_read_ubyte(r);
66     bka->load_on_start = sd_read_ubyte(r);
67     bka->probability = sd_read_uword(r);
68     bka->hazard_damage = sd_read_ubyte(r);
69 
70     // Footer string
71     size = sd_read_uword(r);
72     if(size >= SD_BK_FOOTER_STRING_MAX) {
73         DEBUGLOG("BK specific animation footer too big! Expected max %d bytes, got %hu bytes.",
74             SD_BK_FOOTER_STRING_MAX, size);
75         return SD_FILE_PARSE_ERROR;
76     }
77     if(size > 0) {
78         sd_read_buf(r, bka->footer_string, size);
79         if(bka->footer_string[size-1] != 0) {
80             return SD_FILE_PARSE_ERROR;
81         }
82     }
83 
84     // Initialize animation
85     if((bka->animation = malloc(sizeof(sd_animation))) == NULL) {
86         return SD_OUT_OF_MEMORY;
87     }
88     if((ret = sd_animation_create(bka->animation)) != SD_SUCCESS) {
89         return ret;
90     }
91     if((ret = sd_animation_load(r, bka->animation)) != SD_SUCCESS) {
92         return ret;
93     }
94 
95     // Return success
96     return SD_SUCCESS;
97 }
98 
sd_bk_anim_save(sd_writer * w,const sd_bk_anim * bka)99 int sd_bk_anim_save(sd_writer *w, const sd_bk_anim *bka) {
100     int ret;
101     uint16_t size;
102 
103     if(w == NULL || bka == NULL) {
104         return SD_INVALID_INPUT;
105     }
106 
107     // Write BK specific header
108     sd_write_ubyte(w, bka->null);
109     sd_write_ubyte(w, bka->chain_hit);
110     sd_write_ubyte(w, bka->chain_no_hit);
111     sd_write_ubyte(w, bka->load_on_start);
112     sd_write_uword(w, bka->probability);
113     sd_write_ubyte(w, bka->hazard_damage);
114 
115     // Save footer string
116     size = strlen(bka->footer_string);
117     if(size > 0) {
118         sd_write_uword(w, size+1);
119         sd_write_buf(w, bka->footer_string, size+1);
120     } else {
121         sd_write_uword(w, 0);
122     }
123 
124     // Write animation
125     if((ret = sd_animation_save(w, bka->animation)) != SD_SUCCESS) {
126         return ret;
127     }
128 
129     return SD_SUCCESS;
130 }
131 
sd_bk_anim_set_animation(sd_bk_anim * bka,const sd_animation * animation)132 int sd_bk_anim_set_animation(sd_bk_anim *bka, const sd_animation *animation) {
133     int ret;
134     if(bka == NULL) {
135         return SD_INVALID_INPUT;
136     }
137     if(bka->animation != NULL) {
138         sd_animation_free(bka->animation);
139         free(bka->animation);
140         bka->animation = NULL;
141     }
142     if(animation == NULL) {
143         return SD_SUCCESS;
144     }
145     if((bka->animation = malloc(sizeof(sd_animation))) == NULL) {
146         return SD_OUT_OF_MEMORY;
147     }
148     if((ret = sd_animation_copy(bka->animation, animation)) != SD_SUCCESS) {
149         return ret;
150     }
151     return SD_SUCCESS;
152 }
153 
sd_bk_anim_get_animation(const sd_bk_anim * bka)154 sd_animation* sd_bk_anim_get_animation(const sd_bk_anim *bka) {
155     return bka->animation;
156 }
157 
sd_bk_set_anim_string(sd_bk_anim * bka,const char * data)158 int sd_bk_set_anim_string(sd_bk_anim *bka, const char *data) {
159     if(strlen(data) >= SD_BK_FOOTER_STRING_MAX-1) {
160         return SD_INVALID_INPUT;
161     }
162     strcpy(bka->footer_string, data);
163     return SD_SUCCESS;
164 }
165