Bugfix: Möglicher segfault beim Sterben.
[hackover2013-badge-firmware.git] / badge / jumpnrun / level_load.c
1 #include "levels.h"
2 #include "tiles.h"
3 #include "items.h"
4 #include "enemies.h"
5 #include "jumpnrun.h"
6
7 #ifndef __linux__
8 #include <drivers/fatfs/ff.h>
9 #endif
10
11 #include <stdio.h>
12
13 typedef struct {
14 uint16_t x;
15 uint8_t y;
16 uint8_t type;
17 } level_thing;
18
19 static level_thing jumpnrun_level_parse_blob(unsigned char blob[3]) {
20 level_thing result;
21
22 result.y = blob[0] >> 4;
23 result.x = ((blob[0] & 0x0f) << 8) | blob[1];
24 result.type = blob[2];
25
26 return result;
27 }
28
29 static void jumpnrun_level_make_tile(jumpnrun_tile *dest, level_thing thing) {
30 memset(dest, 0, sizeof(*dest));
31
32 dest->type = thing.type;
33 dest->pos.x = thing.x;
34 dest->pos.y = thing.y;
35 }
36
37 static void jumpnrun_level_make_item(jumpnrun_item *dest, level_thing thing) {
38 memset(dest, 0, sizeof(*dest));
39
40 dest->type = &jumpnrun_item_type_data[thing.type];
41
42 uint8_t xoff = (JUMPNRUN_TILE_PIXEL_WIDTH - (dest->type->sprite.width % JUMPNRUN_TILE_PIXEL_WIDTH)) / 2;
43 uint8_t yoff = thing.type != JUMPNRUN_ITEM_TYPE_CHECKPOINT ? 1 : 0; // HACK: spezielle Ausnahme
44
45 dest->pos.x = FIXED_POINT( thing.x * JUMPNRUN_TILE_PIXEL_WIDTH + xoff, 0);
46 dest->pos.y = FIXED_POINT((thing.y + 1) * JUMPNRUN_TILE_PIXEL_WIDTH - dest->type->sprite.height - yoff, 0);
47 }
48
49 static void jumpnrun_level_make_enemy(jumpnrun_enemy *dest, level_thing thing) {
50 memset(dest, 0, sizeof(*dest));
51
52 dest->type = &jumpnrun_enemy_type_data[thing.type];
53
54 dest->spawn_pos.x = FIXED_INT( thing.x * JUMPNRUN_TILE_PIXEL_WIDTH + fixed_point_cast_int(dest->type->hitbox.pos.x));
55 dest->spawn_pos.y = FIXED_INT((thing.y + 1) * JUMPNRUN_TILE_PIXEL_HEIGHT - fixed_point_cast_int(dest->type->hitbox.extent.y));
56 jumpnrun_enemy_despawn(dest);
57 }
58
59 #ifdef __linux__
60 int jumpnrun_load_level_header_from_file(jumpnrun_level *dest, FILE *fd) {
61 #else
62 int jumpnrun_load_level_header_from_file(jumpnrun_level *dest, FIL *fd) {
63 UINT count;
64 #endif
65 uint16_t head[3];
66
67 #ifdef __linux__
68 if(1 != fread(&head, sizeof(head), 1, fd)) {
69 #else
70 if(FR_OK != f_read(fd, head, sizeof(head), &count) || count != sizeof(head)) {
71 #endif
72 return JUMPNRUN_LEVEL_LOAD_ERROR;
73 }
74
75 dest->header. tile_count = head[0];
76 dest->header. item_count = head[1];
77 dest->header.enemy_count = head[2];
78
79 return JUMPNRUN_LEVEL_LOAD_OK;
80 }
81
82 #ifdef __linux__
83 int jumpnrun_load_level_from_file(jumpnrun_level *dest, FILE *fd) {
84 #else
85 int jumpnrun_load_level_from_file(jumpnrun_level *dest, FIL *fd) {
86 UINT count;
87 #endif
88 size_t i;
89 unsigned char buf[3];
90 uint16_t spos[2];
91
92 #ifdef __linux__
93 if(1 != fread(spos, sizeof(spos), 1, fd)) {
94 #else
95 if(FR_OK != f_read(fd, spos, sizeof(spos), &count) || count != sizeof(spos)) {
96 #endif
97 return JUMPNRUN_LEVEL_LOAD_ERROR;
98 } else {
99 dest->start_pos.x = fixed_point_sub(FIXED_INT((spos[0] + 1) * JUMPNRUN_TILE_PIXEL_WIDTH ), jumpnrun_player_extents().x);
100 dest->start_pos.y = FIXED_INT( spos[1] * JUMPNRUN_TILE_PIXEL_HEIGHT);
101 }
102
103 for(i = 0; i < dest->header.tile_count; ++i) {
104 #ifdef __linux__
105 if(1 != fread(buf, 3, 1, fd)) {
106 #else
107 if(FR_OK != f_read(fd, buf, sizeof(buf), &count) || count != sizeof(buf)) {
108 #endif
109 return JUMPNRUN_LEVEL_LOAD_ERROR;
110 }
111
112 jumpnrun_level_make_tile(&dest->tiles[i], jumpnrun_level_parse_blob(buf));
113 if(i != 0 &&
114 ((dest->tiles[i - 1].pos.x > dest->tiles[i].pos.x) ||
115 (dest->tiles[i - 1].pos.x == dest->tiles[i].pos.x && dest->tiles[i - 1].pos.y >= dest->tiles[i].pos.y))) {
116 return JUMPNRUN_LEVEL_LOAD_ERROR;
117 }
118 }
119
120 for(i = 0; i < dest->header.item_count; ++i) {
121 #ifdef __linux__
122 if(1 != fread(buf, 3, 1, fd)) {
123 #else
124 if(FR_OK != f_read(fd, buf, sizeof(buf), &count) || count != sizeof(buf)) {
125 #endif
126 return JUMPNRUN_LEVEL_LOAD_ERROR;
127 }
128
129 jumpnrun_level_make_item(&dest->items[i], jumpnrun_level_parse_blob(buf));
130 if(i != 0 &&
131 (fixed_point_gt(dest->items[i - 1].pos.x, dest->items[i].pos.x) ||
132 (fixed_point_eq(dest->items[i - 1].pos.x, dest->items[i].pos.x) && fixed_point_ge(dest->items[i - 1].pos.y, dest->items[i].pos.y)))) {
133 return JUMPNRUN_LEVEL_LOAD_ERROR;
134 }
135 }
136
137 for(i = 0; i < dest->header.enemy_count; ++i) {
138 #ifdef __linux__
139 if(1 != fread(buf, 3, 1, fd)) {
140 #else
141 if(FR_OK != f_read(fd, buf, sizeof(buf), &count) || count != sizeof(buf)) {
142 #endif
143 return JUMPNRUN_LEVEL_LOAD_ERROR;
144 }
145
146 jumpnrun_level_make_enemy(&dest->enemies[i], jumpnrun_level_parse_blob(buf));
147 if(i != 0 &&
148 (fixed_point_gt(dest->enemies[i - 1].spawn_pos.x, dest->enemies[i].spawn_pos.x) ||
149 (fixed_point_eq(dest->enemies[i - 1].spawn_pos.x, dest->enemies[i].spawn_pos.x) && fixed_point_ge(dest->enemies[i - 1].spawn_pos.y, dest->enemies[i].spawn_pos.y)))) {
150 return JUMPNRUN_LEVEL_LOAD_ERROR;
151 }
152 }
153
154 return JUMPNRUN_LEVEL_LOAD_OK;
155 }
This page took 0.055938 seconds and 5 git commands to generate.