diff --git a/CMakeLists.txt b/CMakeLists.txt index 326baeb..21c3314 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ project(epec-mcu-emulator LANGUAGES C) option(TESTS "Build unit tests" ON) option(WERROR "Treat warnings as errors" OFF) +option(SANITIZERS "Enable memory and undefined behaviour sanitizers" OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -14,6 +15,10 @@ macro(set_default_target_options target) if (${WERROR}) target_compile_options(${target} PRIVATE -Werror) endif() + if (${SANITIZERS}) + target_compile_options(${target} PRIVATE -fsanitize=memory,undefined) + target_link_options(${target} PRIVATE -fsanitize=memory,undefined) + endif() endmacro() add_custom_target(format @@ -29,6 +34,7 @@ add_custom_target(lint WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) +find_package(LibXml2 REQUIRED) find_package(SDL2 REQUIRED CONFIG REQUIRED COMPONENTS SDL2 SDL2main) add_subdirectory(engine) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index ab763cb..8577634 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -5,4 +5,4 @@ set_default_target_options(game) target_include_directories(game PUBLIC include) target_link_libraries(game - PRIVATE SDL2::SDL2 SDL2::SDL2main) + PRIVATE LibXml2::LibXml2 SDL2::SDL2 SDL2::SDL2main) diff --git a/app/main.c b/app/main.c index 1afc48b..7478890 100644 --- a/app/main.c +++ b/app/main.c @@ -5,16 +5,32 @@ #include #include +#include +#include #define TILESIZE 32 #define WINWIDTH 30 #define WINHEIGHT 20 -SDL_Window *window; -SDL_Renderer *renderer; +#define MAX_PATH_LEN 128 -int main(void) +#define MAP_ASSET "/map.tmx" +#define MAPWIDTH 112 +#define MAPHEIGHT 112 +#define MAPSHIFTX 48 +#define MAPSHIFTY 48 + +static SDL_Window *window; +static SDL_Renderer *renderer; +static unsigned map[MAPWIDTH][MAPHEIGHT]; + +int main(int argc, char *argv[]) { + if (2 != argc) { + fprintf(stderr, "Usage: %s ASSETS-DIR\n", argv[0]); + return 1; + } + int err = SDL_Init(SDL_INIT_VIDEO); assert(0 == err); window = SDL_CreateWindow( @@ -24,6 +40,75 @@ int main(void) renderer = SDL_CreateRenderer(window, -1, 0); assert(NULL != renderer); + xmlDocPtr doc; + xmlNodePtr node; + char mappath[MAX_PATH_LEN]; + strncpy(mappath, argv[1], MAX_PATH_LEN); + strncat(mappath, MAP_ASSET, MAX_PATH_LEN); + doc = xmlParseFile(mappath); + assert(NULL != doc); + node = xmlDocGetRootElement(doc); + assert(0 == xmlStrcmp(node->name, (const xmlChar *)"map")); + node = node->xmlChildrenNode; + while (NULL != node + && xmlStrcmp(node->name, (const xmlChar *)"layer") != 0) + node = node->next; + assert(NULL != node); + node = node->xmlChildrenNode; + while (NULL != node + && xmlStrcmp(node->name, (const xmlChar *)"data") != 0) + node = node->next; + assert(NULL != node); + + xmlNodePtr chunk_contents; + for (node = node->xmlChildrenNode; NULL != node; node = node->next) { + if (0 != xmlStrcmp(node->name, (const xmlChar *)"chunk")) + continue; + + xmlChar *x_attr, *y_attr; + x_attr = xmlGetProp(node, (const xmlChar *)"x"); + y_attr = xmlGetProp(node, (const xmlChar *)"y"); + const int chunk_x = atoi((const char *)x_attr); + const int chunk_y = atoi((const char *)y_attr); + + chunk_contents = node->xmlChildrenNode; + assert( + 0 == xmlStrcmp(chunk_contents->name, (const xmlChar *)"text")); + int x = chunk_x + MAPSHIFTX, y = chunk_y + MAPSHIFTY; + xmlChar buf[10]; + const xmlChar *p, *q; + q = chunk_contents->content; + while (isspace((const char)*q)) + ++q; + p = q; + while ('\0' != *q) { + switch (*q) { + case (xmlChar)',': + memset(buf, 0, sizeof(buf)); + memcpy(buf, p, sizeof(xmlChar) * (q - p)); + assert(x < MAPWIDTH && y < MAPHEIGHT); + map[x][y] = (unsigned)atoi((const char *)buf); + ++x; + p = ++q; + break; + case (xmlChar)'\n': + if (x < MAPWIDTH) { + memset(buf, 0, sizeof(buf)); + memcpy(buf, p, sizeof(xmlChar) * (q - p)); + assert(y < MAPHEIGHT); + map[x][y] = (unsigned)atoi((const char *)buf); + } + x = chunk_x + MAPSHIFTX; + ++y; + p = ++q; + break; + default: + ++q; + break; + } + } + } + SDL_Event event; SDL_RenderClear(renderer); while (1) {