Compare commits
6 Commits
0333e1e27e
...
e1a5d74fe6
Author | SHA1 | Date |
---|---|---|
Xavier Del Campo Romero | e1a5d74fe6 | |
Xavier Del Campo Romero | 7ed6a22eed | |
Xavier Del Campo Romero | e95e42a34c | |
Xavier Del Campo Romero | 5afd26c634 | |
Xavier Del Campo Romero | 8ee22f719e | |
Xavier Del Campo Romero | b2629e023f |
|
@ -1,5 +1,4 @@
|
|||
build/
|
||||
build-*/
|
||||
.vscode/
|
||||
*.code-workspace
|
||||
cdimg/
|
||||
|
|
|
@ -1 +1,70 @@
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/functions.cmake)
|
||||
|
||||
sprite(NAME sidewalk
|
||||
X 384
|
||||
Y 0
|
||||
BPP 4
|
||||
CX 384
|
||||
CY 48
|
||||
TRANSPARENT FALSE)
|
||||
|
||||
sprite(NAME roof1
|
||||
X 384
|
||||
Y 0
|
||||
BPP 4
|
||||
CX 384
|
||||
CY 48
|
||||
TRANSPARENT FALSE)
|
||||
|
||||
sprite(NAME roof2
|
||||
X 384
|
||||
Y 0
|
||||
BPP 4
|
||||
CX 384
|
||||
CY 48
|
||||
TRANSPARENT FALSE)
|
||||
|
||||
sprite(NAME cursor
|
||||
X 384
|
||||
Y 0
|
||||
BPP 4
|
||||
CX 384
|
||||
CY 48
|
||||
TRANSPARENT TRUE)
|
||||
|
||||
sprite(NAME btn_left
|
||||
X 384
|
||||
Y 0
|
||||
BPP 4
|
||||
CX 384
|
||||
CY 48
|
||||
TRANSPARENT TRUE)
|
||||
|
||||
sprite(NAME btn_mid
|
||||
X 384
|
||||
Y 0
|
||||
BPP 4
|
||||
CX 384
|
||||
CY 48
|
||||
TRANSPARENT FALSE)
|
||||
|
||||
sprite(NAME btn_right
|
||||
X 384
|
||||
Y 0
|
||||
BPP 4
|
||||
CX 384
|
||||
CY 48
|
||||
TRANSPARENT TRUE)
|
||||
|
||||
level(NAME city1)
|
||||
|
||||
container(NAME jancity
|
||||
SPRITES
|
||||
sidewalk
|
||||
roof1
|
||||
roof2
|
||||
cursor
|
||||
btn_left
|
||||
btn_mid
|
||||
btn_right
|
||||
)
|
||||
|
|
After Width: | Height: | Size: 586 B |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 586 B |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 21 KiB |
|
@ -0,0 +1,21 @@
|
|||
24 16
|
||||
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
After Width: | Height: | Size: 550 B |
After Width: | Height: | Size: 2.1 KiB |
|
@ -77,6 +77,18 @@ function(sound)
|
|||
endif()
|
||||
endfunction()
|
||||
|
||||
function(level)
|
||||
set(options "")
|
||||
set(multiValueArgs "")
|
||||
set(oneValueArgs NAME)
|
||||
cmake_parse_arguments(LEVEL "${options}" "${oneValueArgs}"
|
||||
"${multiValueArgs}" ${ARGN})
|
||||
|
||||
file(COPY ${LEVEL_NAME}.txt DESTINATION ${cdroot})
|
||||
add_custom_target(${LEVEL_NAME}_lvl
|
||||
DEPENDS ${cdroot}/${LEVEL_NAME})
|
||||
endfunction()
|
||||
|
||||
function(container)
|
||||
set(options "")
|
||||
set(multiValueArgs SPRITES SOUNDS)
|
||||
|
|
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 192 KiB |
After Width: | Height: | Size: 192 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 18 KiB |
|
@ -13,8 +13,8 @@ extern "C"
|
|||
|
||||
enum
|
||||
{
|
||||
CAMERA_CURSOR_WIDTH = 20,
|
||||
CAMERA_CURSOR_HEIGHT = 20
|
||||
CAMERA_CURSOR_WIDTH = 16,
|
||||
CAMERA_CURSOR_HEIGHT = 16
|
||||
};
|
||||
|
||||
void camera_update_pos(struct camera *cam);
|
||||
|
|
|
@ -26,11 +26,6 @@ struct container
|
|||
struct sprite *sprite;
|
||||
struct sound *sound;
|
||||
} data;
|
||||
|
||||
struct container_rt
|
||||
{
|
||||
struct container *c;
|
||||
} *rt;
|
||||
};
|
||||
|
||||
int container_load_ex(const char *path, const struct container *list, size_t n);
|
||||
|
|
|
@ -41,13 +41,19 @@ static int get_file_size(size_t *const sz, FILE *const f)
|
|||
return -1;
|
||||
|
||||
errno = 0;
|
||||
const unsigned long val = strtoul(szstr, NULL, 10);
|
||||
char *end;
|
||||
const unsigned long val = strtoul(szstr, &end, 10);
|
||||
|
||||
if (errno)
|
||||
{
|
||||
fprintf(stderr, "%s: strtoul(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (*end)
|
||||
{
|
||||
fprintf(stderr, "%s: invalid number %s\n", __func__, szstr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*sz = val;
|
||||
return 0;
|
||||
|
@ -123,29 +129,24 @@ static const struct container *find_element(const struct container *const list,
|
|||
static int read_element(const struct container *const list, const size_t n,
|
||||
FILE *const f, bool *const done)
|
||||
{
|
||||
int ret = -1;
|
||||
long init_off;
|
||||
const struct container *el = NULL;
|
||||
size_t sz;
|
||||
|
||||
if (!(el = find_element(list, n, f)))
|
||||
goto end;
|
||||
else if (get_file_size(&sz, f))
|
||||
goto end;
|
||||
if (!(el = find_element(list, n, f))
|
||||
|| get_file_size(&sz, f))
|
||||
return -1;
|
||||
else if ((init_off = ftell(f)) < 0)
|
||||
{
|
||||
fprintf(stderr, "%s:%d: fseek failed: %s\n",
|
||||
__func__, __LINE__, strerror(errno));
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
else if (read_file_contents(el, f, init_off, sz))
|
||||
goto end;
|
||||
return -1;
|
||||
|
||||
done[el - list] = true;
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_all_elements(const struct container *const list, const size_t n,
|
||||
|
|
|
@ -30,6 +30,7 @@ struct game_cfg
|
|||
|
||||
size_t n;
|
||||
union peripheral *p;
|
||||
const char *map;
|
||||
};
|
||||
|
||||
int game_resinit(void);
|
||||
|
|
|
@ -14,8 +14,7 @@ int game(const struct game_cfg *const cfg)
|
|||
struct human_player human;
|
||||
struct terrain_map map;
|
||||
|
||||
terrain_init(&map);
|
||||
building_set_alive_cb(terrain_block_update, &map);
|
||||
terrain_init(cfg->map, &map);
|
||||
|
||||
const struct human_player_cfg hcfg =
|
||||
{
|
||||
|
|
|
@ -12,7 +12,45 @@
|
|||
#include <unit.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static const struct container c[1];
|
||||
static const struct container c[] =
|
||||
{
|
||||
{
|
||||
.path = "sidewalk",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &terrain_sprites[SIDEWALK]
|
||||
},
|
||||
{
|
||||
.path = "roof1",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &terrain_sprites[ROOF1]
|
||||
},
|
||||
{
|
||||
.path = "roof2",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &terrain_sprites[ROOF2]
|
||||
},
|
||||
{
|
||||
.path = "cursor",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &cursor_sprite
|
||||
},
|
||||
{
|
||||
.path = "btn_left",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &gui_button_sprites[GUI_BUTTON_LEFT]
|
||||
},
|
||||
{
|
||||
.path = "btn_mid",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &gui_button_sprites[GUI_BUTTON_MID]
|
||||
},
|
||||
{
|
||||
.path = "btn_right",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &gui_button_sprites[GUI_BUTTON_RIGHT]
|
||||
},
|
||||
};
|
||||
|
||||
static bool init;
|
||||
|
||||
void game_free(void)
|
||||
|
|
|
@ -50,9 +50,6 @@ int menu_update(struct menu_common *const c,
|
|||
|
||||
case PERIPHERAL_TYPE_TOUCH:
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gfx_draw())
|
||||
|
|
|
@ -10,6 +10,7 @@ elseif(SDL1_2_BUILD)
|
|||
set(inc ${inc} "sdl-1.2/inc")
|
||||
set(privinc ${privinc} "sdl-1.2/privinc")
|
||||
set(privdeps ${privdeps} SDL::SDL)
|
||||
set(privdefs ${privdefs} "PROJECT_NAME=\"${PROJECT_NAME}\"")
|
||||
|
||||
if(WIN9X_BUILD)
|
||||
set(src ${src} "win9x/src/system.c")
|
||||
|
@ -21,3 +22,4 @@ endif()
|
|||
add_library(system ${src})
|
||||
target_include_directories(system PUBLIC ${inc} PRIVATE ${privinc})
|
||||
target_link_libraries(system PRIVATE ${privdeps})
|
||||
target_compile_definitions(system PRIVATE ${privdefs})
|
||||
|
|
|
@ -37,7 +37,7 @@ int system_init(void)
|
|||
else if (gfx_init() || sfx_init() || net_init())
|
||||
goto failure;
|
||||
|
||||
SDL_WM_SetCaption("rts", NULL);
|
||||
SDL_WM_SetCaption(PROJECT_NAME, NULL);
|
||||
SDL_ShowCursor(0);
|
||||
/* SDL_WM_GrabInput(SDL_GRAB_ON); */
|
||||
SDL_EnableUNICODE(1);
|
||||
|
|
|
@ -21,26 +21,64 @@ enum
|
|||
|
||||
enum terrain_type
|
||||
{
|
||||
TERRAIN_TYPE_GRASS
|
||||
ROOF1_1_NW,
|
||||
ROOF1_1_N,
|
||||
ROOF1_1_NE,
|
||||
ROOF1_2_NW,
|
||||
ROOF1_2_NE,
|
||||
ROOF1_3_NW,
|
||||
ROOF1_3_N,
|
||||
ROOF1_3_NE,
|
||||
ROOF1_4_N,
|
||||
|
||||
ROOF1_1_W,
|
||||
ROOF1_1_C,
|
||||
ROOF1_1_E,
|
||||
ROOF1_2_SW,
|
||||
ROOF1_2_SE,
|
||||
ROOF1_3_SW,
|
||||
ROOF1_3_S,
|
||||
ROOF1_3_SE,
|
||||
ROOF1_4_C,
|
||||
|
||||
ROOF1_1_SW,
|
||||
ROOF1_1_S,
|
||||
ROOF1_1_SE,
|
||||
ROOF1_5_W,
|
||||
ROOF1_5_C,
|
||||
ROOF1_5_E,
|
||||
ROOF1_6,
|
||||
ROOF1_4_S,
|
||||
|
||||
ROOF1_START = ROOF1_1_NW,
|
||||
ROOF1_END = ROOF1_4_S
|
||||
};
|
||||
|
||||
struct terrain_map
|
||||
{
|
||||
struct terrain_tile
|
||||
{
|
||||
enum terrain_type t;
|
||||
unsigned char bl;
|
||||
unsigned char t, obj;
|
||||
} m[MAP_TILES][MAP_TILES];
|
||||
|
||||
int nx, ny, last_w, last_h;
|
||||
};
|
||||
|
||||
void terrain_init(struct terrain_map *map);
|
||||
int terrain_init(const char *path, struct terrain_map *map);
|
||||
void terrain_update(struct terrain_map *map);
|
||||
int terrain_render(const struct terrain_map *map, const struct camera *cam);
|
||||
void terrain_block_update(const struct util_rect *dim, bool alive, void *p);
|
||||
|
||||
extern struct sprite grass_sprite;
|
||||
enum
|
||||
{
|
||||
SIDEWALK,
|
||||
ROOF1,
|
||||
ROOF2,
|
||||
BUILDING1,
|
||||
|
||||
MAX_TERRAIN_SPRITES
|
||||
};
|
||||
|
||||
extern struct sprite terrain_sprites[MAX_TERRAIN_SPRITES];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -2,11 +2,16 @@
|
|||
#include <camera.h>
|
||||
#include <gfx.h>
|
||||
#include <util.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct sprite grass_sprite;
|
||||
struct sprite terrain_sprites[MAX_TERRAIN_SPRITES];
|
||||
|
||||
void terrain_update(struct terrain_map *const map)
|
||||
{
|
||||
|
@ -27,56 +32,6 @@ void terrain_update(struct terrain_map *const map)
|
|||
}
|
||||
}
|
||||
|
||||
struct block
|
||||
{
|
||||
size_t x0, x1, y0, y1;
|
||||
};
|
||||
|
||||
void terrain_block_update(const struct util_rect *const dim, const bool alive,
|
||||
void *const p)
|
||||
{
|
||||
const struct block b =
|
||||
{
|
||||
.x0 = dim->x / TERRAIN_SZ,
|
||||
.x1 = (dim->x + dim->w) / TERRAIN_SZ,
|
||||
.y0 = dim->y / TERRAIN_SZ,
|
||||
.y1 = (dim->y + dim->h) / TERRAIN_SZ
|
||||
};
|
||||
|
||||
for (size_t x = b.x0; x <= b.x1; x++)
|
||||
for (size_t y = b.y0; y <= b.y1; y++)
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
for (size_t j = 0; j < 2; j++)
|
||||
{
|
||||
const struct util_rect sub =
|
||||
{
|
||||
.x = x * TERRAIN_SZ + i * (TERRAIN_SZ / 2),
|
||||
.y = y * TERRAIN_SZ + j * (TERRAIN_SZ / 2),
|
||||
.w = TERRAIN_SZ / 2,
|
||||
.h = TERRAIN_SZ / 2
|
||||
};
|
||||
|
||||
if (util_collision(dim, &sub))
|
||||
{
|
||||
const enum
|
||||
{
|
||||
NO_SUB = 0,
|
||||
UPPER_LEFT = 1 << 0,
|
||||
UPPER_RIGHT = 1 << 1,
|
||||
LOWER_LEFT = 1 << 2,
|
||||
LOWER_RIGHT = 1 << 3,
|
||||
ALL_BLOCKS = UPPER_LEFT | UPPER_RIGHT
|
||||
| LOWER_LEFT | LOWER_RIGHT
|
||||
} sub = 1 << (i + j * 2);
|
||||
|
||||
struct terrain_map *const map = p;
|
||||
unsigned char *const bl = &map->m[y][x].bl;
|
||||
|
||||
*bl = alive ? *bl | sub : *bl & ~sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int terrain_render(const struct terrain_map *const map,
|
||||
const struct camera *const cam)
|
||||
{
|
||||
|
@ -105,28 +60,172 @@ int terrain_render(const struct terrain_map *const map,
|
|||
for (struct m y = {.i = start_y, .p = remy};
|
||||
y.i < ny + start_y; y.i++, y.p += TERRAIN_SZ)
|
||||
{
|
||||
static const struct tile
|
||||
{
|
||||
const struct sprite *s;
|
||||
int start, end;
|
||||
} tiles[] =
|
||||
{
|
||||
{
|
||||
.s = &terrain_sprites[ROOF1],
|
||||
.start = ROOF1_START,
|
||||
.end = ROOF1_END
|
||||
}
|
||||
};
|
||||
|
||||
const struct terrain_tile *const t = &map->m[y.i][x.i];
|
||||
|
||||
sprite_get_or_ret(s, -1);
|
||||
|
||||
switch (t->t)
|
||||
for (size_t i = 0; i < sizeof tiles / sizeof *tiles; i++)
|
||||
{
|
||||
case TERRAIN_TYPE_GRASS:
|
||||
if (sprite_clone(&grass_sprite, s))
|
||||
const struct tile *const rt = &tiles[i];
|
||||
|
||||
if (t->t >= rt->start && t->t <= rt->end)
|
||||
{
|
||||
sprite_get_or_ret(s, -1);
|
||||
|
||||
if (sprite_clone(rt->s, s))
|
||||
return -1;
|
||||
|
||||
break;
|
||||
s->x = x.p;
|
||||
s->y = y.p;
|
||||
sprite_sort(s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s->x = x.p;
|
||||
s->y = y.p;
|
||||
sprite_sort(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int read_token(FILE *const f, char *const s, const size_t n)
|
||||
{
|
||||
uint8_t c;
|
||||
size_t i = 0;
|
||||
|
||||
while (fread(&c, sizeof c, 1, f))
|
||||
{
|
||||
if (isspace(c) && i)
|
||||
break;
|
||||
else if (!isalnum(c))
|
||||
{
|
||||
fprintf(stderr, "%s: invalid character %" PRIx8 " at offset %ld\n",
|
||||
__func__, c, ftell(f));
|
||||
return -1;
|
||||
}
|
||||
else if (i + 1 >= n)
|
||||
{
|
||||
fprintf(stderr, "%s: exceeded maximum token size %zu\n",
|
||||
__func__, n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s[i++] = c;
|
||||
}
|
||||
|
||||
if (!i)
|
||||
{
|
||||
fprintf(stderr, "%s: feof=%d, ferror=%d\n", __func__, feof(f),
|
||||
ferror(f));
|
||||
return -1;
|
||||
}
|
||||
|
||||
s[i] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_num(FILE *const f, char *const s, const size_t n,
|
||||
unsigned *const out, const int base, const int limit)
|
||||
{
|
||||
if (read_token(f, s, n))
|
||||
return -1;
|
||||
|
||||
errno = 0;
|
||||
|
||||
char *end;
|
||||
const unsigned long value = strtoul(s, &end, 10);
|
||||
|
||||
if (errno)
|
||||
{
|
||||
fprintf(stderr, "%s: strtoul(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (*end)
|
||||
{
|
||||
fprintf(stderr, "%s: invalid number %s\n", __func__, s);
|
||||
return -1;
|
||||
}
|
||||
else if (value > limit)
|
||||
{
|
||||
fprintf(stderr, "%s: %lu exceeds maximum range %d\n", __func__, value,
|
||||
limit);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_dec(FILE *const f, unsigned *const out)
|
||||
{
|
||||
char s[sizeof "65535"];
|
||||
|
||||
return read_num(f, s, sizeof s, out, 10, UINT16_MAX);
|
||||
}
|
||||
|
||||
static int read_hex(FILE *const f, unsigned *const out)
|
||||
{
|
||||
char s[sizeof "0000"];
|
||||
|
||||
return read_num(f, s, sizeof s, out, 16, UINT16_MAX);
|
||||
}
|
||||
|
||||
static int read_dimensions(FILE *const f, unsigned *const w, unsigned *const h)
|
||||
{
|
||||
if (read_dec(f, w) || read_dec(f, h))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_map(FILE *const f, const unsigned w, const unsigned h,
|
||||
struct terrain_map *const map)
|
||||
{
|
||||
for (unsigned j = 0; j < h; j++)
|
||||
for (unsigned i = 0; i < w; i++)
|
||||
{
|
||||
unsigned tile;
|
||||
|
||||
if (read_hex(f, &tile))
|
||||
return -1;
|
||||
|
||||
map->m[j][i].t = tile;
|
||||
map->m[j][i].obj = tile >> 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void terrain_init(struct terrain_map *const map)
|
||||
int terrain_init(const char *const path, struct terrain_map *const map)
|
||||
{
|
||||
*map = (const struct terrain_map){0};
|
||||
int ret = -1;
|
||||
FILE *const f = fopen(path, "rb");
|
||||
unsigned w, h;
|
||||
|
||||
if (!f)
|
||||
{
|
||||
fprintf(stderr, "%s: fopen(3): %s\n", __func__, strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
else if (read_dimensions(f, &w, &h) || read_map(f, w, h, map))
|
||||
goto end;
|
||||
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
if (f && fclose(f))
|
||||
{
|
||||
fprintf(stderr, "%s: fclose(3): %s\n", __func__, strerror(errno));
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|