1 #include "sectSprites.h"
2
3 #include "../common/bufio.h"
4 #include "../Utils/Logger.h"
5
6 #include <cstdlib>
7 #include <cstring>
8
GetSpriteCount(const uint8_t * data,int datalen)9 int SIFSpritesSect::GetSpriteCount(const uint8_t *data, int datalen)
10 {
11 const uint8_t *data_end = data + (datalen - 1);
12 return read_U16(&data, data_end);
13 }
14
Decode(const uint8_t * data,int datalen,SIFSprite * sprites,int * nsprites_out,int maxsprites)15 bool SIFSpritesSect::Decode(const uint8_t *data, int datalen, SIFSprite *sprites, int *nsprites_out, int maxsprites)
16 {
17 const uint8_t *data_end = data + (datalen - 1);
18 int i, f, nsprites;
19
20 nsprites = read_U16(&data, data_end);
21 if (nsprites_out)
22 *nsprites_out = nsprites;
23
24 if (nsprites >= maxsprites)
25 {
26 LOG_ERROR("SIFSpritesSect::Decode: too many sprites in file (nsprites={}, maxsprites={})", nsprites, maxsprites);
27 return 1;
28 }
29
30 LOG_DEBUG("SIFSpritesSect: loading {} sprites", nsprites);
31 for (i = 0; i < nsprites; i++)
32 {
33 if (data > data_end)
34 {
35 LOG_ERROR("SIFSpritesSect::Decode: section corrupt: overran end of data");
36 return 1;
37 }
38
39 // read sprite-level fields
40 sprites[i].w = read_U8(&data, data_end);
41 sprites[i].h = read_U8(&data, data_end);
42 sprites[i].spritesheet = read_U8(&data, data_end);
43
44 sprites[i].nframes = read_U8(&data, data_end);
45 sprites[i].ndirs = read_U8(&data, data_end);
46
47 if (sprites[i].ndirs > SIF_MAX_DIRS)
48 {
49 LOG_ERROR("SIFSpritesSect::Decode: SIF_MAX_DIRS exceeded on sprite {} (ndirs={})", i, sprites[i].ndirs);
50 return 1;
51 }
52
53
54 for (f = 0; f < sprites[i].ndirs; f++)
55 LoadRect(&sprites[i].bbox[f], &data, data_end);
56 LoadRect(&sprites[i].solidbox, &data, data_end);
57
58 LoadPoint(&sprites[i].spawn_point, &data, data_end);
59
60 LoadPointList(&sprites[i].block_l, &data, data_end);
61 LoadPointList(&sprites[i].block_r, &data, data_end);
62 LoadPointList(&sprites[i].block_u, &data, data_end);
63 LoadPointList(&sprites[i].block_d, &data, data_end);
64
65 // malloc enough space to hold the specified number
66 // of apple fritters, i mean, frames.
67 sprites[i].frame = (SIFFrame *)malloc(sizeof(SIFFrame) * sprites[i].nframes);
68
69 // then load all frames
70 for (f = 0; f < sprites[i].nframes; f++)
71 {
72 if (LoadFrame(&sprites[i].frame[f], sprites[i].ndirs, &data, data_end))
73 return 1;
74 }
75 }
76
77 return 0;
78 }
79
LoadFrame(SIFFrame * frame,int ndirs,const uint8_t ** data,const uint8_t * data_end)80 bool SIFSpritesSect::LoadFrame(SIFFrame *frame, int ndirs, const uint8_t **data, const uint8_t *data_end)
81 {
82 // sets defaults for un-specified/default fields
83 memset(frame, 0, sizeof(SIFFrame));
84
85 for (int d = 0; d < ndirs; d++)
86 {
87 SIFDir *dir = &frame->dir[d];
88 LoadPoint(&dir->sheet_offset, data, data_end);
89
90 int t;
91 for (;;)
92 {
93 t = read_U8(data, data_end);
94 if (t == S_DIR_END)
95 break;
96
97 switch (t)
98 {
99 case S_DIR_DRAW_POINT:
100 LoadPoint(&dir->drawpoint, data, data_end);
101 break;
102 case S_DIR_ACTION_POINT:
103 LoadPoint(&dir->actionpoint, data, data_end);
104 break;
105 case S_DIR_ACTION_POINT_2:
106 LoadPoint(&dir->actionpoint2, data, data_end);
107 break;
108
109 case S_DIR_PF_BBOX:
110 LoadRect(&dir->pf_bbox, data, data_end);
111 break;
112
113 default:
114 LOG_WARN("SIFSpriteSect::LoadFrame: encountered unknown optional field type {}", t);
115 return 1;
116 }
117 }
118 }
119
120 return 0;
121 }
122
123 /*
124 void c------------------------------() {}
125 */
126
LoadRect(SIFRect * rect,const uint8_t ** data,const uint8_t * data_end)127 void SIFSpritesSect::LoadRect(SIFRect *rect, const uint8_t **data, const uint8_t *data_end)
128 {
129 rect->x1 = (int16_t)read_U16(data, data_end);
130 rect->y1 = (int16_t)read_U16(data, data_end);
131 rect->x2 = (int16_t)read_U16(data, data_end);
132 rect->y2 = (int16_t)read_U16(data, data_end);
133 }
134
LoadPoint(SIFPoint * pt,const uint8_t ** data,const uint8_t * data_end)135 void SIFSpritesSect::LoadPoint(SIFPoint *pt, const uint8_t **data, const uint8_t *data_end)
136 {
137 pt->x = (int16_t)read_U16(data, data_end);
138 pt->y = (int16_t)read_U16(data, data_end);
139 }
140
LoadPointList(SIFPointList * lst,const uint8_t ** data,const uint8_t * data_end)141 void SIFSpritesSect::LoadPointList(SIFPointList *lst, const uint8_t **data, const uint8_t *data_end)
142 {
143 lst->count = read_U8(data, data_end);
144 if (lst->count > SIF_MAX_BLOCK_POINTS)
145 {
146 LOG_ERROR("SIFSpritesSect::LoadPointList: too many block points ({}, max={})", lst->count, SIF_MAX_BLOCK_POINTS);
147 return;
148 }
149
150 for (int i = 0; i < lst->count; i++)
151 {
152 lst->point[i].x = (int16_t)read_U16(data, data_end);
153 lst->point[i].y = (int16_t)read_U16(data, data_end);
154 }
155 }
156