diff --git a/CMakeLists.txt b/CMakeLists.txt index 11b524b..ef1a3a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,12 @@ cmake_minimum_required(VERSION 3.28) project(yeti3dpro LANGUAGES C) +find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3-shared) + +# base engine library + add_library(y3d STATIC) target_sources(y3d PRIVATE - ${PROJECT_SOURCE_DIR}/src/y3d/y3d_all.c ${PROJECT_SOURCE_DIR}/src/y3d/y3d_animation.c ${PROJECT_SOURCE_DIR}/src/y3d/y3d_ansic.c ${PROJECT_SOURCE_DIR}/src/y3d/y3d_cell.c @@ -25,5 +28,32 @@ target_sources(y3d PRIVATE ${PROJECT_SOURCE_DIR}/src/y3d/y3d_vertex.c ${PROJECT_SOURCE_DIR}/src/y3d/y3d_yeti.c ) -target_include_directories(y3d PRIVATE ${PROJECT_SOURCE_DIR}/src/y3d/) -target_compile_definitions(y3d PRIVATE __SDL__) +target_include_directories(y3d PUBLIC ${PROJECT_SOURCE_DIR}/src/y3d/) +target_compile_definitions(y3d PUBLIC __SDL__) + +# demo game library + +add_library(game STATIC) +target_sources(game PRIVATE + ${PROJECT_SOURCE_DIR}/src/game/data.c + ${PROJECT_SOURCE_DIR}/src/game/entities.c + ${PROJECT_SOURCE_DIR}/src/game/game.c + ${PROJECT_SOURCE_DIR}/src/game/maps.c + ${PROJECT_SOURCE_DIR}/src/game/models.c + ${PROJECT_SOURCE_DIR}/src/game/screens.c + ${PROJECT_SOURCE_DIR}/src/game/sprites.c +) +target_include_directories(game PUBLIC ${PROJECT_SOURCE_DIR}/src/game/) +target_link_libraries(game PRIVATE y3d) + +# sdl3 platform + +add_executable(game-sdl3) +target_sources(game-sdl3 PRIVATE + ${PROJECT_SOURCE_DIR}/platform/sdl3/main.c +) +target_link_libraries(game-sdl3 PRIVATE SDL3::SDL3 game y3d) +find_library(MATH m) +if(MATH) + target_link_libraries(game-sdl3 PUBLIC ${MATH}) +endif() diff --git a/platform/sdl3/main.c b/platform/sdl3/main.c new file mode 100644 index 0000000..f2682c1 --- /dev/null +++ b/platform/sdl3/main.c @@ -0,0 +1,128 @@ + +#include + +#define SDL_MAIN_USE_CALLBACKS +#include + +#include "game.h" + +static yeti_t yeti; +static u16 backbuffer[YETI_FRAMEBUFFER_WIDTH * YETI_FRAMEBUFFER_HEIGHT]; + +static SDL_Window *window = NULL; +static SDL_Renderer *renderer = NULL; +static SDL_Texture *texture = NULL; +static SDL_Surface *front = NULL; +static SDL_Surface *back = NULL; + +static void die(const char *fmt, ...) +{ + static char error[1024]; + va_list ap; + + va_start(ap, fmt); + SDL_vsnprintf(error, sizeof(error), fmt, ap); + va_end(ap); + + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, error); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", error, NULL); + + exit(1); +} + +SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) +{ + Uint32 format; + + if (!SDL_Init(SDL_INIT_VIDEO)) + die(SDL_GetError()); + + window = SDL_CreateWindow(YETI_STR_CAPTION, YETI_FRAMEBUFFER_WIDTH, YETI_FRAMEBUFFER_HEIGHT, SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED); + if (!window) + die(SDL_GetError()); + + SDL_SetWindowMinimumSize(window, YETI_FRAMEBUFFER_WIDTH, YETI_FRAMEBUFFER_HEIGHT); + + renderer = SDL_CreateRenderer(window, NULL); + if (!renderer) + die(SDL_GetError()); + + SDL_SetRenderVSync(renderer, 1); + SDL_SetRenderLogicalPresentation(renderer, YETI_FRAMEBUFFER_WIDTH, YETI_FRAMEBUFFER_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX); + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); + + back = SDL_CreateSurfaceFrom(YETI_FRAMEBUFFER_WIDTH, YETI_FRAMEBUFFER_HEIGHT, SDL_PIXELFORMAT_XBGR1555, backbuffer, YETI_FRAMEBUFFER_WIDTH * sizeof(u16)); + if (!back) + die(SDL_GetError()); + + format = SDL_GetWindowPixelFormat(window); + + front = SDL_CreateSurface(YETI_FRAMEBUFFER_WIDTH, YETI_FRAMEBUFFER_HEIGHT, format); + if (!front) + die(SDL_GetError()); + + texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STREAMING, YETI_FRAMEBUFFER_WIDTH, YETI_FRAMEBUFFER_HEIGHT); + if (!texture) + die(SDL_GetError()); + + SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST); + + yeti_init(&yeti, backbuffer, backbuffer, textures, palette); + yeti_init_lua(&yeti, YETI_GAMMA); + game_init(&yeti); + + return SDL_APP_CONTINUE; +} + +SDL_AppResult SDL_AppIterate(void *appstate) +{ + const bool *keys = SDL_GetKeyboardState(NULL); + + yeti.keyboard.state.up = keys[SDL_SCANCODE_UP]; + yeti.keyboard.state.down = keys[SDL_SCANCODE_DOWN]; + yeti.keyboard.state.left = keys[SDL_SCANCODE_LEFT]; + yeti.keyboard.state.right = keys[SDL_SCANCODE_RIGHT]; + yeti.keyboard.state.a = keys[SDL_SCANCODE_RCTRL]; + yeti.keyboard.state.b = keys[SDL_SCANCODE_SPACE]; + yeti.keyboard.state.l = keys[SDL_SCANCODE_A]; + yeti.keyboard.state.r = keys[SDL_SCANCODE_Z]; + yeti.keyboard.state.select = keys[SDL_SCANCODE_ESCAPE]; + + SDL_FillSurfaceRect(back, NULL, 0); + SDL_FillSurfaceRect(front, NULL, 0); + + game_loop(&yeti); + + SDL_BlitSurface(back, NULL, front, NULL); + SDL_UpdateTexture(texture, NULL, front->pixels, front->pitch); + SDL_RenderClear(renderer); + SDL_RenderTexture(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); + + return SDL_APP_CONTINUE; +} + +SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) +{ + switch (event->type) + { + case SDL_EVENT_QUIT: + return SDL_APP_SUCCESS; + } + + return SDL_APP_CONTINUE; +} + +void SDL_AppQuit(void *appstate, SDL_AppResult result) +{ + if (window) SDL_DestroyWindow(window); + if (renderer) SDL_DestroyRenderer(renderer); + if (back) SDL_DestroySurface(back); + if (front) SDL_DestroySurface(front); + if (texture) SDL_DestroyTexture(texture); + + SDL_Quit(); +} diff --git a/src/game/game.h b/src/game/game.h index 9152544..7b6eea9 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -17,7 +17,7 @@ /******************************************************************************/ -#include "y3d/y3d_yeti.h" +#include "y3d_yeti.h" /******************************************************************************/ diff --git a/src/game/maps.h b/src/game/maps.h index 2995473..3ab063b 100644 --- a/src/game/maps.h +++ b/src/game/maps.h @@ -15,7 +15,7 @@ #ifndef __MAPS_H__ #define __MAPS_H__ -#include "y3d/y3d_yeti.h" +#include "y3d_yeti.h" /******************************************************************************/ @@ -56,4 +56,4 @@ extern rom_map_t map_e3m9; #endif - \ No newline at end of file + diff --git a/src/y3d/y3d_viewport.h b/src/y3d/y3d_viewport.h index a5ae651..ebda4fa 100644 --- a/src/y3d/y3d_viewport.h +++ b/src/y3d/y3d_viewport.h @@ -283,7 +283,9 @@ extern int YetiFrameBufferHeight; #define YETI_VIEWPORT_Y1 0 #define YETI_VIEWPORT_X2 YETI_FRAMEBUFFER_WIDTH #define YETI_VIEWPORT_Y2 YETI_FRAMEBUFFER_HEIGHT -#define TEXT_SCALE 2 +#define TEXT_SCALE 1 + +#define YETI_GAMMA (2.1) #endif