1 #include <stdlib.h>
2 #include <string.h>
3 
4 #include "shadowdive/error.h"
5 #include "shadowdive/animation.h"
6 #include "shadowdive/move.h"
7 
sd_move_create(sd_move * move)8 int sd_move_create(sd_move *move) {
9     if(move == NULL) {
10         return SD_INVALID_INPUT;
11     }
12 
13     // Clear everything
14     memset(move, 0, sizeof(sd_move));
15     return SD_SUCCESS;
16 }
17 
sd_move_copy(sd_move * dst,const sd_move * src)18 int sd_move_copy(sd_move *dst, const sd_move *src) {
19     int ret;
20     if(dst == NULL || src == NULL) {
21         return SD_INVALID_INPUT;
22     }
23 
24     // Clear destination
25     memset(dst, 0, sizeof(sd_move));
26 
27     // Copy animation
28     if(src->animation != NULL) {
29         if((dst->animation = malloc(sizeof(sd_animation))) == NULL) {
30             return SD_OUT_OF_MEMORY;
31         }
32         if((ret = sd_animation_copy(dst->animation, src->animation)) != SD_SUCCESS) {
33             return ret;
34         }
35     }
36 
37     // Copy move and footer strings
38     strcpy(dst->move_string, src->move_string);
39     strcpy(dst->footer_string, src->footer_string);
40 
41     // Everything else
42     dst->unknown_0 = src->unknown_0;
43     dst->unknown_2 = src->unknown_2;
44     dst->unknown_4 = src->unknown_4;
45     dst->unknown_5 = src->unknown_5;
46     dst->unknown_6 = src->unknown_6;
47     dst->unknown_7 = src->unknown_7;
48     dst->unknown_8 = src->unknown_8;
49     dst->unknown_9 = src->unknown_9;
50     dst->unknown_10 = src->unknown_10;
51     dst->unknown_11 = src->unknown_11;
52     dst->next_anim_id = src->next_anim_id;
53     dst->category = src->category;
54     dst->unknown_14 = src->unknown_14;
55     dst->scrap_amount = src->scrap_amount;;
56     dst->successor_id = src->successor_id;
57     dst->damage_amount = src->damage_amount;;
58     dst->unknown_18 = src->unknown_18;
59     dst->unknown_19 = src->unknown_19;
60     dst->points = src->points;
61 
62     return SD_SUCCESS;
63 }
64 
sd_move_free(sd_move * move)65 void sd_move_free(sd_move *move) {
66     if(move == NULL) return;
67     if(move->animation != NULL) {
68         sd_animation_free(move->animation);
69         free(move->animation);
70     }
71 }
72 
sd_move_load(sd_reader * r,sd_move * move)73 int sd_move_load(sd_reader *r, sd_move *move) {
74     int ret;
75     uint16_t size;
76 
77     if(r == NULL || move == NULL) {
78         return SD_INVALID_INPUT;
79     }
80 
81     // Read animation
82     if((move->animation = malloc(sizeof(sd_animation))) == NULL) {
83         return SD_OUT_OF_MEMORY;
84     }
85     if((ret = sd_animation_create(move->animation)) != SD_SUCCESS) {
86         return ret;
87     }
88     if((ret = sd_animation_load(r, move->animation)) != SD_SUCCESS) {
89         return ret;
90     }
91 
92     // Header
93     move->unknown_0 = sd_read_uword(r);
94     move->unknown_2 = sd_read_uword(r);
95     move->unknown_4 = sd_read_ubyte(r);
96     move->unknown_5 = sd_read_ubyte(r);
97     move->unknown_6 = sd_read_ubyte(r);
98     move->unknown_7 = sd_read_ubyte(r);
99     move->unknown_8 = sd_read_ubyte(r);
100     move->unknown_9 = sd_read_ubyte(r);
101     move->unknown_10 = sd_read_ubyte(r);
102     move->unknown_11 = sd_read_ubyte(r);
103     move->next_anim_id = sd_read_ubyte(r);
104     move->category = sd_read_ubyte(r);
105     move->unknown_14 = sd_read_ubyte(r);
106     move->scrap_amount = sd_read_ubyte(r);
107     move->successor_id = sd_read_ubyte(r);
108     move->damage_amount = sd_read_ubyte(r);
109     move->unknown_18 = sd_read_ubyte(r);
110     move->unknown_19 = sd_read_ubyte(r);
111     move->points = sd_read_ubyte(r);
112 
113     // move string
114     sd_read_buf(r, move->move_string, 21);
115 
116     // Footer string
117     size = sd_read_uword(r);
118     if(size >= SD_MOVE_FOOTER_STRING_MAX) {
119         DEBUGLOG("Move footer too big! Expected max %d bytes, got %hu bytes.",
120             SD_MOVE_FOOTER_STRING_MAX, size);
121         return SD_FILE_PARSE_ERROR;
122     }
123     if(size > 0) {
124         sd_read_buf(r, move->footer_string, size);
125         if(move->footer_string[size-1] != 0) {
126             return SD_FILE_PARSE_ERROR;
127         }
128     }
129 
130     // Return success if reader is still ok
131     if(!sd_reader_ok(r)) {
132         return SD_FILE_PARSE_ERROR;
133     }
134     return SD_SUCCESS;
135 }
136 
sd_move_save(sd_writer * w,const sd_move * move)137 int sd_move_save(sd_writer *w, const sd_move *move) {
138     int ret;
139     uint16_t size;
140 
141     if(w == NULL || move == NULL) {
142         return SD_INVALID_INPUT;
143     }
144 
145     // Save animation
146     if((ret = sd_animation_save(w, move->animation)) != SD_SUCCESS) {
147         return ret;
148     }
149 
150     // Move header
151     sd_write_uword(w, move->unknown_0);
152     sd_write_uword(w, move->unknown_2);
153     sd_write_ubyte(w, move->unknown_4);
154     sd_write_ubyte(w, move->unknown_5);
155     sd_write_ubyte(w, move->unknown_6);
156     sd_write_ubyte(w, move->unknown_7);
157     sd_write_ubyte(w, move->unknown_8);
158     sd_write_ubyte(w, move->unknown_9);
159     sd_write_ubyte(w, move->unknown_10);
160     sd_write_ubyte(w, move->unknown_11);
161     sd_write_ubyte(w, move->next_anim_id);
162     sd_write_ubyte(w, move->category);
163     sd_write_ubyte(w, move->unknown_14);
164     sd_write_ubyte(w, move->scrap_amount);
165     sd_write_ubyte(w, move->successor_id);
166     sd_write_ubyte(w, move->damage_amount);
167     sd_write_ubyte(w, move->unknown_18);
168     sd_write_ubyte(w, move->unknown_19);
169     sd_write_ubyte(w, move->points);
170 
171     // move string
172     sd_write_buf(w, move->move_string, 21);
173 
174     // Save footer string
175     size = strlen(move->footer_string);
176     if(size > 0) {
177         sd_write_uword(w, size+1);
178         sd_write_buf(w, move->footer_string, size+1);
179     } else {
180         sd_write_uword(w, 0);
181     }
182 
183     return SD_SUCCESS;
184 }
185 
sd_move_set_animation(sd_move * move,const sd_animation * animation)186 int sd_move_set_animation(sd_move *move, const sd_animation *animation) {
187     int ret;
188     if(move == NULL) {
189         return SD_INVALID_INPUT;
190     }
191     if(move->animation != NULL) {
192         sd_animation_free(move->animation);
193         free(move->animation);
194         move->animation = NULL;
195     }
196     if(animation == NULL) {
197         return SD_SUCCESS;
198     }
199     if((move->animation = malloc(sizeof(sd_animation))) == NULL) {
200         return SD_OUT_OF_MEMORY;
201     }
202     if((ret = sd_animation_copy(move->animation, animation)) != SD_SUCCESS) {
203         return ret;
204     }
205     return SD_SUCCESS;
206 }
207 
sd_move_get_animation(const sd_move * move)208 sd_animation* sd_move_get_animation(const sd_move *move) {
209     return move->animation;
210 }
211 
sd_move_set_footer_string(sd_move * move,const char * str)212 int sd_move_set_footer_string(sd_move *move, const char* str) {
213     if(strlen(str) >= SD_MOVE_FOOTER_STRING_MAX-1) {
214         return SD_INVALID_INPUT;
215     }
216     strcpy(move->footer_string, str);
217     return SD_SUCCESS;
218 }
219 
sd_move_set_move_string(sd_move * move,const char * str)220 int sd_move_set_move_string(sd_move *move, const char *str) {
221     if(strlen(str) >= SD_MOVE_STRING_MAX-1) {
222         return SD_INVALID_INPUT;
223     }
224     strcpy(move->move_string, str);
225     return SD_SUCCESS;
226 }
227