8 #include <drivers/fatfs/ff.h>
19 static level_thing
jumpnrun_level_parse_blob(unsigned char blob
[3]) {
22 result
.y
= blob
[0] >> 4;
23 result
.x
= ((blob
[0] & 0x0f) << 8) | blob
[1];
24 result
.type
= blob
[2];
29 static void jumpnrun_level_make_tile(jumpnrun_tile
*dest
, level_thing thing
) {
30 memset(dest
, 0, sizeof(*dest
));
32 dest
->type
= thing
.type
;
33 dest
->pos
.x
= thing
.x
;
34 dest
->pos
.y
= thing
.y
;
37 static void jumpnrun_level_make_item(jumpnrun_item
*dest
, level_thing thing
) {
38 memset(dest
, 0, sizeof(*dest
));
40 dest
->type
= &jumpnrun_item_type_data
[thing
.type
];
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
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);
49 static void jumpnrun_level_make_enemy(jumpnrun_enemy
*dest
, level_thing thing
) {
50 memset(dest
, 0, sizeof(*dest
));
52 dest
->type
= &jumpnrun_enemy_type_data
[thing
.type
];
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
);
60 int jumpnrun_load_level_header_from_file(jumpnrun_level
*dest
, FILE *fd
) {
62 int jumpnrun_load_level_header_from_file(jumpnrun_level
*dest
, FIL
*fd
) {
68 if(1 != fread(&head
, sizeof(head
), 1, fd
)) {
70 if(FR_OK
!= f_read(fd
, head
, sizeof(head
), &count
) || count
!= sizeof(head
)) {
72 return JUMPNRUN_LEVEL_LOAD_ERROR
;
75 dest
->header
. tile_count
= head
[0];
76 dest
->header
. item_count
= head
[1];
77 dest
->header
.enemy_count
= head
[2];
79 return JUMPNRUN_LEVEL_LOAD_OK
;
83 int jumpnrun_load_level_from_file(jumpnrun_level
*dest
, FILE *fd
) {
85 int jumpnrun_load_level_from_file(jumpnrun_level
*dest
, FIL
*fd
) {
93 if(1 != fread(spos
, sizeof(spos
), 1, fd
)) {
95 if(FR_OK
!= f_read(fd
, spos
, sizeof(spos
), &count
) || count
!= sizeof(spos
)) {
97 return JUMPNRUN_LEVEL_LOAD_ERROR
;
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
);
104 if(1 != fread(&dest
->start_lives
, 1, 1, fd
)) {
106 if(FR_OK
!= f_read(fd
, &dest
->start_lives
, sizeof(dest
->start_lives
), &count
) || count
!= sizeof(dest
->start_lives
)) {
108 return JUMPNRUN_LEVEL_LOAD_ERROR
;
111 for(i
= 0; i
< dest
->header
.tile_count
; ++i
) {
113 if(1 != fread(buf
, 3, 1, fd
)) {
115 if(FR_OK
!= f_read(fd
, buf
, sizeof(buf
), &count
) || count
!= sizeof(buf
)) {
117 return JUMPNRUN_LEVEL_LOAD_ERROR
;
120 jumpnrun_level_make_tile(&dest
->tiles
[i
], jumpnrun_level_parse_blob(buf
));
122 ((dest
->tiles
[i
- 1].pos
.x
> dest
->tiles
[i
].pos
.x
) ||
123 (dest
->tiles
[i
- 1].pos
.x
== dest
->tiles
[i
].pos
.x
&& dest
->tiles
[i
- 1].pos
.y
>= dest
->tiles
[i
].pos
.y
))) {
124 return JUMPNRUN_LEVEL_LOAD_ERROR
;
128 for(i
= 0; i
< dest
->header
.item_count
; ++i
) {
130 if(1 != fread(buf
, 3, 1, fd
)) {
132 if(FR_OK
!= f_read(fd
, buf
, sizeof(buf
), &count
) || count
!= sizeof(buf
)) {
134 return JUMPNRUN_LEVEL_LOAD_ERROR
;
137 jumpnrun_level_make_item(&dest
->items
[i
], jumpnrun_level_parse_blob(buf
));
139 (fixed_point_gt(dest
->items
[i
- 1].pos
.x
, dest
->items
[i
].pos
.x
) ||
140 (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
)))) {
141 return JUMPNRUN_LEVEL_LOAD_ERROR
;
145 for(i
= 0; i
< dest
->header
.enemy_count
; ++i
) {
147 if(1 != fread(buf
, 3, 1, fd
)) {
149 if(FR_OK
!= f_read(fd
, buf
, sizeof(buf
), &count
) || count
!= sizeof(buf
)) {
151 return JUMPNRUN_LEVEL_LOAD_ERROR
;
154 jumpnrun_level_make_enemy(&dest
->enemies
[i
], jumpnrun_level_parse_blob(buf
));
156 (fixed_point_gt(dest
->enemies
[i
- 1].spawn_pos
.x
, dest
->enemies
[i
].spawn_pos
.x
) ||
157 (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
)))) {
158 return JUMPNRUN_LEVEL_LOAD_ERROR
;
162 return JUMPNRUN_LEVEL_LOAD_OK
;