diff --git a/CMakeLists.txt b/CMakeLists.txt index c6711b3..0564579 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,6 @@ set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) if(NOT DEFINED DUSK_TARGET_SYSTEM) - # set(DUSK_TARGET_SYSTEM "psp") set(DUSK_TARGET_SYSTEM "linux") endif() @@ -23,8 +22,6 @@ set(DUSK_BUILD_DIR "${CMAKE_BINARY_DIR}") set(DUSK_SOURCES_DIR "${DUSK_ROOT_DIR}/src") set(DUSK_TEMP_DIR "${DUSK_BUILD_DIR}/temp") set(DUSK_TOOLS_DIR "${DUSK_ROOT_DIR}/tools") -# set(DUSK_ASSETS_DIR "${DUSK_ROOT_DIR}/assets") -# set(DUSK_ASSETS_BUILD_DIR "${DUSK_BUILD_DIR}/assets") set(DUSK_DATA_DIR "${DUSK_ROOT_DIR}/data") set(DUSK_GENERATED_HEADERS_DIR "${DUSK_BUILD_DIR}/generated") set(DUSK_TARGET_NAME "Dusk" CACHE INTERNAL ${DUSK_CACHE_TARGET}) diff --git a/src/dusk/CMakeLists.txt b/archive/dusk/CMakeLists.txt similarity index 100% rename from src/dusk/CMakeLists.txt rename to archive/dusk/CMakeLists.txt diff --git a/src/dusk/assert/CMakeLists.txt b/archive/dusk/assert/CMakeLists.txt similarity index 100% rename from src/dusk/assert/CMakeLists.txt rename to archive/dusk/assert/CMakeLists.txt diff --git a/src/dusk/assert/assert.c b/archive/dusk/assert/assert.c similarity index 100% rename from src/dusk/assert/assert.c rename to archive/dusk/assert/assert.c diff --git a/src/dusk/assert/assert.h b/archive/dusk/assert/assert.h similarity index 100% rename from src/dusk/assert/assert.h rename to archive/dusk/assert/assert.h diff --git a/src/dusk/console/CMakeLists.txt b/archive/dusk/console/CMakeLists.txt similarity index 100% rename from src/dusk/console/CMakeLists.txt rename to archive/dusk/console/CMakeLists.txt diff --git a/src/dusk/console/cmd/CMakeLists.txt b/archive/dusk/console/cmd/CMakeLists.txt similarity index 100% rename from src/dusk/console/cmd/CMakeLists.txt rename to archive/dusk/console/cmd/CMakeLists.txt diff --git a/src/dusk/console/cmd/cmdecho.h b/archive/dusk/console/cmd/cmdecho.h similarity index 100% rename from src/dusk/console/cmd/cmdecho.h rename to archive/dusk/console/cmd/cmdecho.h diff --git a/src/dusk/console/cmd/cmdget.h b/archive/dusk/console/cmd/cmdget.h similarity index 100% rename from src/dusk/console/cmd/cmdget.h rename to archive/dusk/console/cmd/cmdget.h diff --git a/src/dusk/console/cmd/cmdquit.h b/archive/dusk/console/cmd/cmdquit.h similarity index 100% rename from src/dusk/console/cmd/cmdquit.h rename to archive/dusk/console/cmd/cmdquit.h diff --git a/src/dusk/console/cmd/cmdset.h b/archive/dusk/console/cmd/cmdset.h similarity index 100% rename from src/dusk/console/cmd/cmdset.h rename to archive/dusk/console/cmd/cmdset.h diff --git a/src/dusk/console/console.c b/archive/dusk/console/console.c similarity index 100% rename from src/dusk/console/console.c rename to archive/dusk/console/console.c diff --git a/src/dusk/console/console.h b/archive/dusk/console/console.h similarity index 100% rename from src/dusk/console/console.h rename to archive/dusk/console/console.h diff --git a/src/dusk/console/consolecmd.c b/archive/dusk/console/consolecmd.c similarity index 100% rename from src/dusk/console/consolecmd.c rename to archive/dusk/console/consolecmd.c diff --git a/src/dusk/console/consolecmd.h b/archive/dusk/console/consolecmd.h similarity index 100% rename from src/dusk/console/consolecmd.h rename to archive/dusk/console/consolecmd.h diff --git a/src/dusk/console/consoledefs.h b/archive/dusk/console/consoledefs.h similarity index 100% rename from src/dusk/console/consoledefs.h rename to archive/dusk/console/consoledefs.h diff --git a/src/dusk/console/consolevar.c b/archive/dusk/console/consolevar.c similarity index 100% rename from src/dusk/console/consolevar.c rename to archive/dusk/console/consolevar.c diff --git a/src/dusk/console/consolevar.h b/archive/dusk/console/consolevar.h similarity index 100% rename from src/dusk/console/consolevar.h rename to archive/dusk/console/consolevar.h diff --git a/src/dusk/display/CMakeLists.txt b/archive/dusk/display/CMakeLists.txt similarity index 100% rename from src/dusk/display/CMakeLists.txt rename to archive/dusk/display/CMakeLists.txt diff --git a/src/dusk/display/renderbase.c b/archive/dusk/display/renderbase.c similarity index 100% rename from src/dusk/display/renderbase.c rename to archive/dusk/display/renderbase.c diff --git a/src/dusk/display/renderbase.h b/archive/dusk/display/renderbase.h similarity index 100% rename from src/dusk/display/renderbase.h rename to archive/dusk/display/renderbase.h diff --git a/src/dusk/display/scene.c b/archive/dusk/display/scene.c similarity index 100% rename from src/dusk/display/scene.c rename to archive/dusk/display/scene.c diff --git a/src/dusk/display/scene.h b/archive/dusk/display/scene.h similarity index 100% rename from src/dusk/display/scene.h rename to archive/dusk/display/scene.h diff --git a/src/dusk/dusk.h b/archive/dusk/dusk.h similarity index 100% rename from src/dusk/dusk.h rename to archive/dusk/dusk.h diff --git a/src/dusk/entity/CMakeLists.txt b/archive/dusk/entity/CMakeLists.txt similarity index 100% rename from src/dusk/entity/CMakeLists.txt rename to archive/dusk/entity/CMakeLists.txt diff --git a/src/dusk/entity/direction.c b/archive/dusk/entity/direction.c similarity index 100% rename from src/dusk/entity/direction.c rename to archive/dusk/entity/direction.c diff --git a/src/dusk/entity/direction.h b/archive/dusk/entity/direction.h similarity index 100% rename from src/dusk/entity/direction.h rename to archive/dusk/entity/direction.h diff --git a/src/dusk/entity/entity.c b/archive/dusk/entity/entity.c similarity index 100% rename from src/dusk/entity/entity.c rename to archive/dusk/entity/entity.c diff --git a/src/dusk/entity/entity.h b/archive/dusk/entity/entity.h similarity index 100% rename from src/dusk/entity/entity.h rename to archive/dusk/entity/entity.h diff --git a/src/dusk/entity/npc.c b/archive/dusk/entity/npc.c similarity index 100% rename from src/dusk/entity/npc.c rename to archive/dusk/entity/npc.c diff --git a/src/dusk/entity/npc.h b/archive/dusk/entity/npc.h similarity index 100% rename from src/dusk/entity/npc.h rename to archive/dusk/entity/npc.h diff --git a/src/dusk/entity/player.c b/archive/dusk/entity/player.c similarity index 100% rename from src/dusk/entity/player.c rename to archive/dusk/entity/player.c diff --git a/src/dusk/entity/player.h b/archive/dusk/entity/player.h similarity index 100% rename from src/dusk/entity/player.h rename to archive/dusk/entity/player.h diff --git a/src/dusk/error/CMakeLists.txt b/archive/dusk/error/CMakeLists.txt similarity index 100% rename from src/dusk/error/CMakeLists.txt rename to archive/dusk/error/CMakeLists.txt diff --git a/src/dusk/error/error.c b/archive/dusk/error/error.c similarity index 100% rename from src/dusk/error/error.c rename to archive/dusk/error/error.c diff --git a/src/dusk/error/error.h b/archive/dusk/error/error.h similarity index 100% rename from src/dusk/error/error.h rename to archive/dusk/error/error.h diff --git a/src/dusk/event/CMakeLists.txt b/archive/dusk/event/CMakeLists.txt similarity index 100% rename from src/dusk/event/CMakeLists.txt rename to archive/dusk/event/CMakeLists.txt diff --git a/src/dusk/event/event.c b/archive/dusk/event/event.c similarity index 100% rename from src/dusk/event/event.c rename to archive/dusk/event/event.c diff --git a/src/dusk/event/event.h b/archive/dusk/event/event.h similarity index 100% rename from src/dusk/event/event.h rename to archive/dusk/event/event.h diff --git a/src/dusk/event/eventdata.h b/archive/dusk/event/eventdata.h similarity index 100% rename from src/dusk/event/eventdata.h rename to archive/dusk/event/eventdata.h diff --git a/src/dusk/event/eventitem.h b/archive/dusk/event/eventitem.h similarity index 100% rename from src/dusk/event/eventitem.h rename to archive/dusk/event/eventitem.h diff --git a/src/dusk/event/eventtext.c b/archive/dusk/event/eventtext.c similarity index 100% rename from src/dusk/event/eventtext.c rename to archive/dusk/event/eventtext.c diff --git a/src/dusk/event/eventtext.h b/archive/dusk/event/eventtext.h similarity index 100% rename from src/dusk/event/eventtext.h rename to archive/dusk/event/eventtext.h diff --git a/src/dusk/game.c b/archive/dusk/game.c similarity index 100% rename from src/dusk/game.c rename to archive/dusk/game.c diff --git a/src/dusk/game.h b/archive/dusk/game.h similarity index 100% rename from src/dusk/game.h rename to archive/dusk/game.h diff --git a/src/dusk/input.c b/archive/dusk/input.c similarity index 100% rename from src/dusk/input.c rename to archive/dusk/input.c diff --git a/src/dusk/input.h b/archive/dusk/input.h similarity index 100% rename from src/dusk/input.h rename to archive/dusk/input.h diff --git a/src/dusk/item/CMakeLists.txt b/archive/dusk/item/CMakeLists.txt similarity index 100% rename from src/dusk/item/CMakeLists.txt rename to archive/dusk/item/CMakeLists.txt diff --git a/src/dusk/item/inventory.c b/archive/dusk/item/inventory.c similarity index 100% rename from src/dusk/item/inventory.c rename to archive/dusk/item/inventory.c diff --git a/src/dusk/item/inventory.h b/archive/dusk/item/inventory.h similarity index 100% rename from src/dusk/item/inventory.h rename to archive/dusk/item/inventory.h diff --git a/src/dusk/item/itemstack.h b/archive/dusk/item/itemstack.h similarity index 100% rename from src/dusk/item/itemstack.h rename to archive/dusk/item/itemstack.h diff --git a/src/dusk/item/itemtype.h b/archive/dusk/item/itemtype.h similarity index 100% rename from src/dusk/item/itemtype.h rename to archive/dusk/item/itemtype.h diff --git a/src/dusk/locale/CMakeLists.txt b/archive/dusk/locale/CMakeLists.txt similarity index 100% rename from src/dusk/locale/CMakeLists.txt rename to archive/dusk/locale/CMakeLists.txt diff --git a/src/dusk/locale/language.c b/archive/dusk/locale/language.c similarity index 100% rename from src/dusk/locale/language.c rename to archive/dusk/locale/language.c diff --git a/src/dusk/locale/language.h b/archive/dusk/locale/language.h similarity index 100% rename from src/dusk/locale/language.h rename to archive/dusk/locale/language.h diff --git a/src/dusk/time.c b/archive/dusk/time.c similarity index 100% rename from src/dusk/time.c rename to archive/dusk/time.c diff --git a/src/dusk/time.h b/archive/dusk/time.h similarity index 100% rename from src/dusk/time.h rename to archive/dusk/time.h diff --git a/src/dusk/ui/CMakeLists.txt b/archive/dusk/ui/CMakeLists.txt similarity index 100% rename from src/dusk/ui/CMakeLists.txt rename to archive/dusk/ui/CMakeLists.txt diff --git a/src/dusk/ui/font.h b/archive/dusk/ui/font.h similarity index 100% rename from src/dusk/ui/font.h rename to archive/dusk/ui/font.h diff --git a/src/dusk/ui/uitextbox.c b/archive/dusk/ui/uitextbox.c similarity index 100% rename from src/dusk/ui/uitextbox.c rename to archive/dusk/ui/uitextbox.c diff --git a/src/dusk/ui/uitextbox.h b/archive/dusk/ui/uitextbox.h similarity index 100% rename from src/dusk/ui/uitextbox.h rename to archive/dusk/ui/uitextbox.h diff --git a/src/dusk/util/CMakeLists.txt b/archive/dusk/util/CMakeLists.txt similarity index 100% rename from src/dusk/util/CMakeLists.txt rename to archive/dusk/util/CMakeLists.txt diff --git a/src/dusk/util/math.c b/archive/dusk/util/math.c similarity index 100% rename from src/dusk/util/math.c rename to archive/dusk/util/math.c diff --git a/src/dusk/util/math.h b/archive/dusk/util/math.h similarity index 100% rename from src/dusk/util/math.h rename to archive/dusk/util/math.h diff --git a/src/dusk/util/memory.c b/archive/dusk/util/memory.c similarity index 100% rename from src/dusk/util/memory.c rename to archive/dusk/util/memory.c diff --git a/src/dusk/util/memory.h b/archive/dusk/util/memory.h similarity index 100% rename from src/dusk/util/memory.h rename to archive/dusk/util/memory.h diff --git a/src/dusk/util/string.c b/archive/dusk/util/string.c similarity index 100% rename from src/dusk/util/string.c rename to archive/dusk/util/string.c diff --git a/src/dusk/util/string.h b/archive/dusk/util/string.h similarity index 100% rename from src/dusk/util/string.h rename to archive/dusk/util/string.h diff --git a/src/dusk/world/CMakeLists.txt b/archive/dusk/world/CMakeLists.txt similarity index 100% rename from src/dusk/world/CMakeLists.txt rename to archive/dusk/world/CMakeLists.txt diff --git a/src/dusk/world/chunk.c b/archive/dusk/world/chunk.c similarity index 100% rename from src/dusk/world/chunk.c rename to archive/dusk/world/chunk.c diff --git a/src/dusk/world/chunk.h b/archive/dusk/world/chunk.h similarity index 100% rename from src/dusk/world/chunk.h rename to archive/dusk/world/chunk.h diff --git a/src/dusk/world/chunkdata.h b/archive/dusk/world/chunkdata.h similarity index 100% rename from src/dusk/world/chunkdata.h rename to archive/dusk/world/chunkdata.h diff --git a/src/dusk/world/overworld.c b/archive/dusk/world/overworld.c similarity index 100% rename from src/dusk/world/overworld.c rename to archive/dusk/world/overworld.c diff --git a/src/dusk/world/overworld.h b/archive/dusk/world/overworld.h similarity index 100% rename from src/dusk/world/overworld.h rename to archive/dusk/world/overworld.h diff --git a/src/dusk/world/tile.h b/archive/dusk/world/tile.h similarity index 100% rename from src/dusk/world/tile.h rename to archive/dusk/world/tile.h diff --git a/src/duskpsp/CMakeLists.txt b/archive/duskpsp/CMakeLists.txt similarity index 100% rename from src/duskpsp/CMakeLists.txt rename to archive/duskpsp/CMakeLists.txt diff --git a/src/duskpsp/duskpsp.c b/archive/duskpsp/duskpsp.c similarity index 100% rename from src/duskpsp/duskpsp.c rename to archive/duskpsp/duskpsp.c diff --git a/src/duskpsp/duskpsp.h b/archive/duskpsp/duskpsp.h similarity index 100% rename from src/duskpsp/duskpsp.h rename to archive/duskpsp/duskpsp.h diff --git a/src/dusksdl2/CMakeLists.txt b/archive/dusksdl2/CMakeLists.txt similarity index 100% rename from src/dusksdl2/CMakeLists.txt rename to archive/dusksdl2/CMakeLists.txt diff --git a/src/dusksdl2/display/CMakeLists.txt b/archive/dusksdl2/display/CMakeLists.txt similarity index 100% rename from src/dusksdl2/display/CMakeLists.txt rename to archive/dusksdl2/display/CMakeLists.txt diff --git a/src/dusksdl2/display/camera/CMakeLists.txt b/archive/dusksdl2/display/camera/CMakeLists.txt similarity index 100% rename from src/dusksdl2/display/camera/CMakeLists.txt rename to archive/dusksdl2/display/camera/CMakeLists.txt diff --git a/src/dusksdl2/display/camera/camera.c b/archive/dusksdl2/display/camera/camera.c similarity index 100% rename from src/dusksdl2/display/camera/camera.c rename to archive/dusksdl2/display/camera/camera.c diff --git a/src/dusksdl2/display/camera/camera.h b/archive/dusksdl2/display/camera/camera.h similarity index 100% rename from src/dusksdl2/display/camera/camera.h rename to archive/dusksdl2/display/camera/camera.h diff --git a/src/dusksdl2/display/framebuffer/CMakeLists.txt b/archive/dusksdl2/display/framebuffer/CMakeLists.txt similarity index 100% rename from src/dusksdl2/display/framebuffer/CMakeLists.txt rename to archive/dusksdl2/display/framebuffer/CMakeLists.txt diff --git a/src/dusksdl2/display/framebuffer/framebuffer.c b/archive/dusksdl2/display/framebuffer/framebuffer.c similarity index 100% rename from src/dusksdl2/display/framebuffer/framebuffer.c rename to archive/dusksdl2/display/framebuffer/framebuffer.c diff --git a/src/dusksdl2/display/framebuffer/framebuffer.h b/archive/dusksdl2/display/framebuffer/framebuffer.h similarity index 100% rename from src/dusksdl2/display/framebuffer/framebuffer.h rename to archive/dusksdl2/display/framebuffer/framebuffer.h diff --git a/src/dusksdl2/display/mesh/CMakeLists.txt b/archive/dusksdl2/display/mesh/CMakeLists.txt similarity index 100% rename from src/dusksdl2/display/mesh/CMakeLists.txt rename to archive/dusksdl2/display/mesh/CMakeLists.txt diff --git a/src/dusksdl2/display/mesh/mesh.c b/archive/dusksdl2/display/mesh/mesh.c similarity index 100% rename from src/dusksdl2/display/mesh/mesh.c rename to archive/dusksdl2/display/mesh/mesh.c diff --git a/src/dusksdl2/display/mesh/mesh.h b/archive/dusksdl2/display/mesh/mesh.h similarity index 100% rename from src/dusksdl2/display/mesh/mesh.h rename to archive/dusksdl2/display/mesh/mesh.h diff --git a/src/dusksdl2/display/mesh/quad.c b/archive/dusksdl2/display/mesh/quad.c similarity index 100% rename from src/dusksdl2/display/mesh/quad.c rename to archive/dusksdl2/display/mesh/quad.c diff --git a/src/dusksdl2/display/mesh/quad.h b/archive/dusksdl2/display/mesh/quad.h similarity index 100% rename from src/dusksdl2/display/mesh/quad.h rename to archive/dusksdl2/display/mesh/quad.h diff --git a/src/dusksdl2/display/overworld/CMakeLists.txt b/archive/dusksdl2/display/overworld/CMakeLists.txt similarity index 100% rename from src/dusksdl2/display/overworld/CMakeLists.txt rename to archive/dusksdl2/display/overworld/CMakeLists.txt diff --git a/src/dusksdl2/display/overworld/renderoverworld.c b/archive/dusksdl2/display/overworld/renderoverworld.c similarity index 100% rename from src/dusksdl2/display/overworld/renderoverworld.c rename to archive/dusksdl2/display/overworld/renderoverworld.c diff --git a/src/dusksdl2/display/overworld/renderoverworld.h b/archive/dusksdl2/display/overworld/renderoverworld.h similarity index 100% rename from src/dusksdl2/display/overworld/renderoverworld.h rename to archive/dusksdl2/display/overworld/renderoverworld.h diff --git a/src/dusksdl2/display/render.c b/archive/dusksdl2/display/render.c similarity index 100% rename from src/dusksdl2/display/render.c rename to archive/dusksdl2/display/render.c diff --git a/src/dusksdl2/display/render.h b/archive/dusksdl2/display/render.h similarity index 100% rename from src/dusksdl2/display/render.h rename to archive/dusksdl2/display/render.h diff --git a/src/dusksdl2/display/renderbackbuffer.c b/archive/dusksdl2/display/renderbackbuffer.c similarity index 100% rename from src/dusksdl2/display/renderbackbuffer.c rename to archive/dusksdl2/display/renderbackbuffer.c diff --git a/src/dusksdl2/display/renderbackbuffer.h b/archive/dusksdl2/display/renderbackbuffer.h similarity index 100% rename from src/dusksdl2/display/renderbackbuffer.h rename to archive/dusksdl2/display/renderbackbuffer.h diff --git a/src/dusksdl2/display/scene/CMakeLists.txt b/archive/dusksdl2/display/scene/CMakeLists.txt similarity index 100% rename from src/dusksdl2/display/scene/CMakeLists.txt rename to archive/dusksdl2/display/scene/CMakeLists.txt diff --git a/src/dusksdl2/display/scene/renderscene.c b/archive/dusksdl2/display/scene/renderscene.c similarity index 100% rename from src/dusksdl2/display/scene/renderscene.c rename to archive/dusksdl2/display/scene/renderscene.c diff --git a/src/dusksdl2/display/scene/renderscene.h b/archive/dusksdl2/display/scene/renderscene.h similarity index 100% rename from src/dusksdl2/display/scene/renderscene.h rename to archive/dusksdl2/display/scene/renderscene.h diff --git a/src/dusksdl2/display/spritebatch/CMakeLists.txt b/archive/dusksdl2/display/spritebatch/CMakeLists.txt similarity index 100% rename from src/dusksdl2/display/spritebatch/CMakeLists.txt rename to archive/dusksdl2/display/spritebatch/CMakeLists.txt diff --git a/src/dusksdl2/display/spritebatch/spritebatch.c b/archive/dusksdl2/display/spritebatch/spritebatch.c similarity index 100% rename from src/dusksdl2/display/spritebatch/spritebatch.c rename to archive/dusksdl2/display/spritebatch/spritebatch.c diff --git a/src/dusksdl2/display/spritebatch/spritebatch.h b/archive/dusksdl2/display/spritebatch/spritebatch.h similarity index 100% rename from src/dusksdl2/display/spritebatch/spritebatch.h rename to archive/dusksdl2/display/spritebatch/spritebatch.h diff --git a/src/dusksdl2/display/texture/CMakeLists.txt b/archive/dusksdl2/display/texture/CMakeLists.txt similarity index 100% rename from src/dusksdl2/display/texture/CMakeLists.txt rename to archive/dusksdl2/display/texture/CMakeLists.txt diff --git a/src/dusksdl2/display/texture/texture.c b/archive/dusksdl2/display/texture/texture.c similarity index 100% rename from src/dusksdl2/display/texture/texture.c rename to archive/dusksdl2/display/texture/texture.c diff --git a/src/dusksdl2/display/texture/texture.h b/archive/dusksdl2/display/texture/texture.h similarity index 100% rename from src/dusksdl2/display/texture/texture.h rename to archive/dusksdl2/display/texture/texture.h diff --git a/src/dusksdl2/display/ui/CMakeLists.txt b/archive/dusksdl2/display/ui/CMakeLists.txt similarity index 100% rename from src/dusksdl2/display/ui/CMakeLists.txt rename to archive/dusksdl2/display/ui/CMakeLists.txt diff --git a/src/dusksdl2/display/ui/renderconsole.c b/archive/dusksdl2/display/ui/renderconsole.c similarity index 100% rename from src/dusksdl2/display/ui/renderconsole.c rename to archive/dusksdl2/display/ui/renderconsole.c diff --git a/src/dusksdl2/display/ui/renderconsole.h b/archive/dusksdl2/display/ui/renderconsole.h similarity index 100% rename from src/dusksdl2/display/ui/renderconsole.h rename to archive/dusksdl2/display/ui/renderconsole.h diff --git a/src/dusksdl2/display/ui/renderfps.c b/archive/dusksdl2/display/ui/renderfps.c similarity index 100% rename from src/dusksdl2/display/ui/renderfps.c rename to archive/dusksdl2/display/ui/renderfps.c diff --git a/src/dusksdl2/display/ui/renderfps.h b/archive/dusksdl2/display/ui/renderfps.h similarity index 100% rename from src/dusksdl2/display/ui/renderfps.h rename to archive/dusksdl2/display/ui/renderfps.h diff --git a/src/dusksdl2/display/ui/rendertext.c b/archive/dusksdl2/display/ui/rendertext.c similarity index 100% rename from src/dusksdl2/display/ui/rendertext.c rename to archive/dusksdl2/display/ui/rendertext.c diff --git a/src/dusksdl2/display/ui/rendertext.h b/archive/dusksdl2/display/ui/rendertext.h similarity index 100% rename from src/dusksdl2/display/ui/rendertext.h rename to archive/dusksdl2/display/ui/rendertext.h diff --git a/src/dusksdl2/display/ui/rendertextbox.c b/archive/dusksdl2/display/ui/rendertextbox.c similarity index 100% rename from src/dusksdl2/display/ui/rendertextbox.c rename to archive/dusksdl2/display/ui/rendertextbox.c diff --git a/src/dusksdl2/display/ui/rendertextbox.h b/archive/dusksdl2/display/ui/rendertextbox.h similarity index 100% rename from src/dusksdl2/display/ui/rendertextbox.h rename to archive/dusksdl2/display/ui/rendertextbox.h diff --git a/src/dusksdl2/display/ui/renderui.c b/archive/dusksdl2/display/ui/renderui.c similarity index 100% rename from src/dusksdl2/display/ui/renderui.c rename to archive/dusksdl2/display/ui/renderui.c diff --git a/src/dusksdl2/display/ui/renderui.h b/archive/dusksdl2/display/ui/renderui.h similarity index 100% rename from src/dusksdl2/display/ui/renderui.h rename to archive/dusksdl2/display/ui/renderui.h diff --git a/src/dusksdl2/dusksdl2.h b/archive/dusksdl2/dusksdl2.h similarity index 100% rename from src/dusksdl2/dusksdl2.h rename to archive/dusksdl2/dusksdl2.h diff --git a/src/dusksdl2/dusksdl2input.c b/archive/dusksdl2/dusksdl2input.c similarity index 100% rename from src/dusksdl2/dusksdl2input.c rename to archive/dusksdl2/dusksdl2input.c diff --git a/src/dusksdl2/dusksdl2input.h b/archive/dusksdl2/dusksdl2input.h similarity index 100% rename from src/dusksdl2/dusksdl2input.h rename to archive/dusksdl2/dusksdl2input.h diff --git a/src/dusksdl2/main.c b/archive/dusksdl2/main.c similarity index 100% rename from src/dusksdl2/main.c rename to archive/dusksdl2/main.c diff --git a/src/dusksdl2/time.c b/archive/dusksdl2/time.c similarity index 100% rename from src/dusksdl2/time.c rename to archive/dusksdl2/time.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9513952..7b557db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,15 +1,34 @@ # Copyright (c) 2025 Dominic Masters -# +# # This software is released under the MIT License. # https://opensource.org/licenses/MIT -add_subdirectory(dusk) +# Libs +target_link_libraries(${DUSK_TARGET_NAME} + PUBLIC + m +) -if(DUSK_TARGET_SYSTEM STREQUAL "linux") - add_subdirectory(dusksdl2) -elseif(DUSK_TARGET_SYSTEM STREQUAL "psp") - add_subdirectory(duskpsp) - add_subdirectory(dusksdl2) -else() - message(FATAL_ERROR "Unsupported target system: ${DUSK_TARGET_SYSTEM}") -endif() \ No newline at end of file +# Includes +target_include_directories(${DUSK_TARGET_NAME} + PRIVATE + ${CMAKE_CURRENT_LIST_DIR} +) + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + main.c +) + +# Subdirs +add_subdirectory(assert) +add_subdirectory(console) +add_subdirectory(display) +add_subdirectory(engine) +add_subdirectory(error) +add_subdirectory(input) +add_subdirectory(locale) +add_subdirectory(thread) +add_subdirectory(time) +add_subdirectory(util) \ No newline at end of file diff --git a/src/assert/CMakeLists.txt b/src/assert/CMakeLists.txt new file mode 100644 index 0000000..ca33cd5 --- /dev/null +++ b/src/assert/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + assert.c +) \ No newline at end of file diff --git a/src/assert/assert.c b/src/assert/assert.c new file mode 100644 index 0000000..2f02a16 --- /dev/null +++ b/src/assert/assert.c @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2023 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assert.h" + +#ifndef ASSERTIONS_FAKED + void assertTrueImpl( + const char *file, + const int32_t line, + const bool x, + const char *message + ) { + if(x != true) { + fprintf( + stderr, + "Assertion Failed in %s:%i\n\n%s\n", + file, + line, + message + ); + abort(); + } + } + + void assertFalseImpl( + const char *file, + const int32_t line, + bool x, + const char *message + ) { + assertTrueImpl(file, line, !x, message); + } + + void assertUnreachableImpl( + const char *file, + const int32_t line, + const char *message + ) { + assertTrueImpl(file, line, false, message); + } + + void assertNotNullImpl( + const char *file, + const int32_t line, + const void *pointer, + const char *message + ) { + assertTrueImpl( + file, + line, + pointer != NULL, + message + ); + + // Ensure we can touch it + volatile char temp; + temp = *((char*)pointer); + } + + void assertNullImpl( + const char *file, + const int32_t line, + const void *pointer, + const char *message + ) { + assertTrueImpl( + file, + line, + pointer == NULL, + message + ); + } + + void assertDeprecatedImpl( + const char *file, + const int32_t line, + const char *message + ) { + assertUnreachableImpl(file, line, message); + } +#endif \ No newline at end of file diff --git a/src/assert/assert.h b/src/assert/assert.h new file mode 100644 index 0000000..03e401e --- /dev/null +++ b/src/assert/assert.h @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2023 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +#ifndef ASSERTIONS_FAKED + /** + * Assert a given value to be true. + * + * @param file File that the assertion is being made from. + * @param line Line that the assertion is being made from. + * @param x Value to assert as true. + * @param message Message to throw against assertion failure. + */ + void assertTrueImpl( + const char *file, + const int32_t line, + const bool_t x, + const char *message + ); + + /** + * Asserts a given statement to be false. + * + * @param file File that the assertion is being made from. + * @param line Line that the assertion is being made from. + * @param x Value to assert as false. + * @param message Message to throw against assertion failure. + */ + void assertFalseImpl( + const char *file, + const int32_t line, + const bool_t x, + const char *message + ); + + /** + * Asserts that a given line of code is unreachable. Essentially a forced + * assertion failure, good for "edge cases" + * + * @param file File that the assertion is being made from. + * @param line Line that the assertion is being made from. + * @param message Message to throw against assertion failure. + */ + void assertUnreachableImpl( + const char *file, + const int32_t line, + const char *message + ); + + /** + * Assert a given pointer to not point to a null pointer. + * + * @param file File that the assertion is being made from. + * @param line Line that the assertion is being made from. + * @param pointer Pointer to assert is not a null pointer. + * @param message Message to throw against assertion failure. + */ + void assertNotNullImpl( + const char *file, + const int32_t line, + const void *pointer, + const char *message + ); + + /** + * Asserts a given pointer to be a nullptr. + * + * @param file File that the assertion is being made from. + * @param line Line that the assertion is being made from. + * @param pointer Pointer to assert is nullptr. + * @param message Message to throw against assertion failure. + */ + void assertNullImpl( + const char *file, + const int32_t line, + const void *pointer, + const char *message + ); + + /** + * Asserts a function as being deprecated. + * + * @param file File that the assertion is being made from. + * @param line Line that the assertion is being made from. + * @param message Message to throw against assertion failure. + */ + void assertDeprecatedImpl( + const char *file, + const int32_t line, + const char *message + ); + + void assertMemoryRangeMatchesImpl( + const char *file, + const int32_t line, + const void *start, + const void *end, + const size_t size, + const char *message + ); + + #define assertTrue(x, message) \ + assertTrueImpl(__FILE__, __LINE__, x, message) + + #define assertFalse(x, message) \ + assertFalseImpl(__FILE__, __LINE__, x, message) + + #define assertUnreachable(message) \ + assertUnreachableImpl(__FILE__, __LINE__, message) + + #define assertNotNull(pointer, message) \ + assertNotNullImpl(__FILE__, __LINE__, pointer, message) + + #define assertNull(pointer, message) \ + assertNullImpl(__FILE__, __LINE__, pointer, message) + + #define assertDeprecated(message) \ + assertDeprecatedImpl(__FILE__, __LINE__, message) + + #define assertStrLenMax(str, len, message) \ + assertTrue(strlen(str) < len, message) + + #define assertStrLenMin(str, len, message) \ + assertTrue(strlen(str) >= len, message) + +#else + // If assertions are faked, we define the macros to do nothing. + #define assertTrue(x, message) ((void)0) + #define assertFalse(x, message) ((void)0) + #define assertUnreachable(message) ((void)0) + #define assertNotNull(pointer, message) ((void)0) + #define assertNull(pointer, message) ((void)0) + #define assertDeprecated(message) ((void)0) + #define assertStrLenMax(str, len, message) ((void)0) + #define assertStrLenMin(str, len, message) ((void)0) + +#endif \ No newline at end of file diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt new file mode 100644 index 0000000..ba39dd6 --- /dev/null +++ b/src/console/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + console.c + consolecmd.c + consolevar.c +) + +# Subdirectories +add_subdirectory(cmd) + +# Compiler flags. +if(DUSK_TARGET_SYSTEM STREQUAL "linux") + target_compile_definitions(${DUSK_TARGET_NAME} + PRIVATE + DUSK_CONSOLE_TERMIOS=1 + ) +endif() \ No newline at end of file diff --git a/src/console/cmd/CMakeLists.txt b/src/console/cmd/CMakeLists.txt new file mode 100644 index 0000000..fb0e252 --- /dev/null +++ b/src/console/cmd/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE +) \ No newline at end of file diff --git a/src/console/cmd/cmdecho.h b/src/console/cmd/cmdecho.h new file mode 100644 index 0000000..d9cc4a0 --- /dev/null +++ b/src/console/cmd/cmdecho.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "console/console.h" + +void cmdEcho(const consolecmdexec_t *exec) { + assertTrue( + exec->argc >= 1, + "echo command requires 1 argument." + ); + + consolePrint("%s", exec->argv[0]); +} \ No newline at end of file diff --git a/src/console/cmd/cmdget.h b/src/console/cmd/cmdget.h new file mode 100644 index 0000000..6b6cb13 --- /dev/null +++ b/src/console/cmd/cmdget.h @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "console/console.h" + +void cmdGet(const consolecmdexec_t *exec) { + assertTrue( + exec->argc >= 1, + "Get command requires 1 argument." + ); + + for(uint32_t i = 0; i < CONSOLE.variableCount; i++) { + consolevar_t *var = &CONSOLE.variables[i]; + if(stringCompare(var->name, exec->argv[0]) != 0) continue; + consolePrint("%s", var->value); + return; + } + + consolePrint("Error: Variable '%s' not found.", exec->argv[0]); +} \ No newline at end of file diff --git a/src/console/cmd/cmdquit.h b/src/console/cmd/cmdquit.h new file mode 100644 index 0000000..e897def --- /dev/null +++ b/src/console/cmd/cmdquit.h @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "console/console.h" +#include "engine/engine.h" + +void cmdQuit(const consolecmdexec_t *exec) { + consolePrint("Quitting..."); + ENGINE.running = false; +} \ No newline at end of file diff --git a/src/console/cmd/cmdset.h b/src/console/cmd/cmdset.h new file mode 100644 index 0000000..e468ea2 --- /dev/null +++ b/src/console/cmd/cmdset.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "console/console.h" + +void cmdSet(const consolecmdexec_t *exec) { + assertTrue(exec->argc >= 2, "set command requires 2 arguments."); + + for(uint32_t i = 0; i < CONSOLE.variableCount; i++) { + consolevar_t *var = &CONSOLE.variables[i]; + if(stringCompare(var->name, exec->argv[0]) != 0) continue; + consoleVarSetValue(var, exec->argv[1]); + consolePrint("%s %s", var->name, var->value); + for(i = 0; i < var->eventCount; i++) { + assertNotNull(var->events[i], "Event is NULL"); + var->events[i](var); + } + return; + } + + consolePrint("Error: Variable '%s' not found.", exec->argv[0]); +} \ No newline at end of file diff --git a/src/console/console.c b/src/console/console.c new file mode 100644 index 0000000..9d1088f --- /dev/null +++ b/src/console/console.c @@ -0,0 +1,344 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "console.h" +#include "assert/assert.h" +#include "util/memory.h" +#include "util/string.h" +#include "console/cmd/cmdquit.h" +#include "console/cmd/cmdecho.h" +#include "console/cmd/cmdset.h" +#include "console/cmd/cmdget.h" + +console_t CONSOLE; + +void consoleInit() { + memoryZero(&CONSOLE, sizeof(console_t)); + + // Register the get and set command. + CONSOLE.cmdGet = consoleRegCmd("get", cmdGet); + CONSOLE.cmdSet = consoleRegCmd("set", cmdSet); + consoleRegCmd("quit", cmdQuit); + consoleRegCmd("echo", cmdEcho); + + consolePrint(" = Dawn Console = "); + + #if DUSK_CONSOLE_TERMIOS + // Create termios session. + struct termios newTermios; + tcgetattr(STDIN_FILENO, &CONSOLE.originalTermios); + + // Disable canonical mode & echo + newTermios.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newTermios); + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);// Set stdin to non-blocking + #endif +} + +consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function) { + consolecmd_t *cmd = &CONSOLE.commands[CONSOLE.commandCount++]; + consoleCmdInit(cmd, name, function); + return cmd; +} + +consolevar_t * consoleRegVar( + const char_t *name, + const char_t *value, + consolevarchanged_t event +) { + consolevar_t *var = &CONSOLE.variables[CONSOLE.variableCount++]; + consoleVarInitListener(var, name, value, event); + return var; +} + +void consolePrint(const char_t *message, ...) { + char_t buffer[CONSOLE_LINE_MAX]; + + va_list args; + va_start(args, message); + int32_t len = stringFormatVA(buffer, CONSOLE_LINE_MAX, message, args); + va_end(args); + + // Move all lines back + memoryMove( + CONSOLE.line[0], + CONSOLE.line[1], + (CONSOLE_HISTORY_MAX - 1) * CONSOLE_LINE_MAX + ); + + // Copy the new line + memoryCopy( + CONSOLE.line[CONSOLE_HISTORY_MAX - 1], + buffer, + len + 1 + ); + printf("%s\n", buffer); +} + +void consoleExec(const char_t *line) { + assertNotNull(line, "line must not be NULL"); + assertTrue( + CONSOLE.execBufferCount < CONSOLE_EXEC_BUFFER_MAX, + "Too many commands in the buffer." + ); + + char_t buffer[CONSOLE_LINE_MAX]; + size_t i = 0, j = 0; + char_t c; + consoleexecstate_t state = CONSOLE_EXEC_STATE_INITIAL; + consolecmdexec_t *exec = NULL; + + while(state != CONSOLE_EXEC_STATE_FULLY_PARSED) { + c = line[i]; + + switch(state) { + case CONSOLE_EXEC_STATE_INITIAL: + assertTrue(j == 0, "Buffer not empty?"); + + if(c == '\0') { + state = CONSOLE_EXEC_STATE_FULLY_PARSED; + break; + } + + if(stringIsWhitespace(c) || c == ';') { + i++; + continue; + } + + state = CONSOLE_EXEC_STATE_PARSE_CMD; + break; + + case CONSOLE_EXEC_STATE_PARSE_CMD: + if(stringIsWhitespace(c) || c == '\0' || c == ';') { + state = CONSOLE_EXEC_STATE_CMD_PARSED; + continue; + } + + if(c == '"') { + // Can't handle quotes within the command. + consolePrint("Invalid command"); + while(c != '\0' && c != ';') c = line[++i]; + continue; + } + + buffer[j++] = c; + i++; + + if(j >= CONSOLE_LINE_MAX) { + consolePrint("Command too long"); + state = CONSOLE_EXEC_STATE_FULLY_PARSED; + continue; + } + break; + + case CONSOLE_EXEC_STATE_CMD_PARSED: + if(j == 0) { + state = CONSOLE_EXEC_STATE_INITIAL; + continue; + } + + // Create exec + assertNull(exec, "Existing command parsing?"); + + exec = &CONSOLE.execBuffer[CONSOLE.execBufferCount]; + memoryZero(exec, sizeof(consolecmdexec_t)); + + buffer[j] = '\0'; + stringCopy(exec->command, buffer, CONSOLE_LINE_MAX); + state = CONSOLE_EXEC_STATE_FIND_ARG; + + j = 0;// Free up buffer + break; + + case CONSOLE_EXEC_STATE_FIND_ARG: + if(c == '\0' || c == ';') { + state = CONSOLE_EXEC_STATE_CMD_FINISHED; + continue; + } + + if(stringIsWhitespace(c)) { + i++; + continue; + } + + if(c == '"') { + state = CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED; + i++; + } else { + state = CONSOLE_EXEC_STATE_PARSE_ARG; + } + break; + + case CONSOLE_EXEC_STATE_PARSE_ARG: + if(stringIsWhitespace(c) || c == '\0' || c == ';') { + state = CONSOLE_EXEC_STATE_ARG_PARSED; + continue; + } + + buffer[j++] = c; + i++; + + if(j >= CONSOLE_LINE_MAX) { + consolePrint("Arg too long"); + state = CONSOLE_EXEC_STATE_FULLY_PARSED; + continue; + } + break; + + case CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED: + if(c == '"') { + state = CONSOLE_EXEC_STATE_ARG_PARSED; + i++; + continue; + } + + if(c == '\0' || c == ';') { + consolePrint("Unterminated quote"); + state = CONSOLE_EXEC_STATE_FULLY_PARSED; + continue; + } + + if(c == '\\') { + c = line[++i]; + + if(c == '\0' || c == ';') { + consolePrint("Unterminated quote"); + state = CONSOLE_EXEC_STATE_FULLY_PARSED; + continue; + } + } + + buffer[j++] = c; + i++; + + if(j >= CONSOLE_LINE_MAX) { + consolePrint("Arg too long"); + state = CONSOLE_EXEC_STATE_FULLY_PARSED; + continue; + } + break; + + case CONSOLE_EXEC_STATE_ARG_PARSED: + buffer[j] = '\0'; + stringCopy(exec->argv[exec->argc++], buffer, CONSOLE_LINE_MAX); + state = CONSOLE_EXEC_STATE_FIND_ARG; + j = 0;// Free up buffer + break; + + case CONSOLE_EXEC_STATE_CMD_FINISHED: + assertNotNull(exec, "No command found?"); + + // Now, is there a command that matches? + for(uint32_t k = 0; k < CONSOLE.commandCount; k++) { + consolecmd_t *cmd = &CONSOLE.commands[k]; + if(stringCompare(cmd->name, exec->command) != 0) continue; + exec->cmd = cmd; + break; + } + + if(exec->cmd == NULL) { + // Command wasn't found, is there a variable that matches? + for(uint32_t k = 0; k < CONSOLE.variableCount; k++) { + consolevar_t *var = &CONSOLE.variables[k]; + if(stringCompare(var->name, exec->command) != 0) continue; + + // Matching variable found, is this a GET or a SET? + if(exec->argc == 0) { + exec->cmd = CONSOLE.cmdGet; + stringCopy(exec->argv[0], exec->command, CONSOLE_LINE_MAX); + exec->argc = 1; + } else { + exec->cmd = CONSOLE.cmdSet; + stringCopy(exec->argv[1], exec->argv[0], CONSOLE_LINE_MAX); + stringCopy(exec->argv[0], exec->command, CONSOLE_LINE_MAX); + exec->argc = 2; + } + break; + } + + if(exec->cmd == NULL) { + consolePrint("Command not found", exec->command); + exec = NULL; + state = CONSOLE_EXEC_STATE_INITIAL; + break; + } + } + + // Prep for next command. + exec = NULL; + state = CONSOLE_EXEC_STATE_INITIAL; + CONSOLE.execBufferCount++; + break; + + default: + assertUnreachable("Invalid state."); + break; + } + } +} + +// May move these later +void consoleUpdate() { + #if DUSK_CONSOLE_TERMIOS + char_t c; + for(;;) { + if(!read(STDIN_FILENO, &c, 1)) break; + putchar(c); + } + #endif + + for(uint32_t i = 0; i < CONSOLE.execBufferCount; i++) { + consolecmdexec_t *exec = &CONSOLE.execBuffer[i]; + assertNotNull(exec->cmd, "Command execution has no command."); + exec->cmd->function(exec); + } + + // #if DUSK_KEYBOARD_SUPPORT == 1 + // uint8_t key; + // while((key = inputKeyboardPop()) != 0) { + // printf("Key pressed: %c\n", key); + // switch(key) { + // case 0: + // break; + + // case INPUT_KEY_ENTER: + // consoleExec(CONSOLE.inputBuffer); + // CONSOLE.inputIndex = 0; + // CONSOLE.inputBuffer[0] = '\0'; + // break; + + // case INPUT_KEY_BACKSPACE: + // if(CONSOLE.inputIndex > 0) { + // CONSOLE.inputIndex--; + // CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0'; + // } + // break; + + // default: + // if( + // key >= INPUT_KEY_ASCII_START && key <= INPUT_KEY_ASCII_END && + // CONSOLE.inputIndex < CONSOLE_LINE_MAX - 1 + // ) { + // CONSOLE.inputBuffer[CONSOLE.inputIndex++] = key; + // CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0'; + // } + // break; + + // } + // } + // #endif + + // Clear the exec buffer + CONSOLE.execBufferCount = 0; +} + +void consoleDispose(void) { + // Reset termios + #if DUSK_CONSOLE_TERMIOS + tcsetattr(STDIN_FILENO, TCSANOW, &CONSOLE.originalTermios); + #endif +} \ No newline at end of file diff --git a/src/console/console.h b/src/console/console.h new file mode 100644 index 0000000..6286a3e --- /dev/null +++ b/src/console/console.h @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "consolevar.h" +#include "consolecmd.h" + +#if DUSK_CONSOLE_TERMIOS + #include + #include + #include +#endif + +typedef enum { + CONSOLE_EXEC_STATE_INITIAL, + CONSOLE_EXEC_STATE_PARSE_CMD, + CONSOLE_EXEC_STATE_CMD_PARSED, + + CONSOLE_EXEC_STATE_FIND_ARG, + CONSOLE_EXEC_STATE_PARSE_ARG, + CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED, + CONSOLE_EXEC_STATE_ARG_PARSED, + + CONSOLE_EXEC_STATE_CMD_FINISHED, + CONSOLE_EXEC_STATE_FULLY_PARSED +} consoleexecstate_t; + +typedef struct { + consolecmd_t commands[CONSOLE_COMMANDS_MAX]; + uint32_t commandCount; + + consolevar_t variables[CONSOLE_VARIABLES_MAX]; + uint32_t variableCount; + + char_t line[CONSOLE_HISTORY_MAX][CONSOLE_LINE_MAX]; + + consolecmdexec_t execBuffer[CONSOLE_EXEC_BUFFER_MAX]; + uint32_t execBufferCount; + + consolecmd_t *cmdGet; + consolecmd_t *cmdSet; + + bool_t visible; + + #if DUSK_CONSOLE_TERMIOS + struct termios originalTermios; + char_t inputBuffer[CONSOLE_LINE_MAX]; + int32_t inputBufferLength; + #endif +} console_t; + +extern console_t CONSOLE; + +/** + * Initializes the console. + */ +void consoleInit(); + +/** + * Registers a console command. + * + * @param name The name of the command. + * @param function The function to execute when the command is called. + * @return The registered command. + */ +consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function); + +/** + * Registers a console variable. + * + * @param name The name of the variable. + * @param value The initial value of the variable. + * @param event The event to register. + * @return The registered variable. + */ +consolevar_t * consoleRegVar( + const char_t *name, + const char_t *value, + consolevarchanged_t event +); + +/** + * Sets the value of a console variable. + * + * @param name The name of the variable. + * @param value The new value of the variable. + */ +void consolePrint( + const char_t *message, + ... +); + +/** + * Executes a console command. + * + * @param line The line to execute. + */ +void consoleExec(const char_t *line); + +/** + * Processes the console's pending commands. + */ +void consoleUpdate(); + +/** + * Disposes of the console. + */ +void consoleDispose(void); \ No newline at end of file diff --git a/src/console/consolecmd.c b/src/console/consolecmd.c new file mode 100644 index 0000000..f2923b9 --- /dev/null +++ b/src/console/consolecmd.c @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "consolecmd.h" +#include "assert/assert.h" +#include "util/memory.h" +#include "util/string.h" + +void consoleCmdInit( + consolecmd_t *cmd, + const char_t *name, + consolecmdfunc_t function +) { + assertNotNull(cmd, "Command is NULL."); + assertNotNull(name, "Name is NULL."); + assertNotNull(function, "Function is NULL."); + assertStrLenMin(name, 1, "Name is empty."); + assertStrLenMax(name, CONSOLE_CMD_NAME_MAX, "Name is too long."); + + memoryZero(cmd, sizeof(consolecmd_t)); + stringCopy(cmd->name, name, CONSOLE_CMD_NAME_MAX); + cmd->function = function; +} \ No newline at end of file diff --git a/src/console/consolecmd.h b/src/console/consolecmd.h new file mode 100644 index 0000000..09a3c4f --- /dev/null +++ b/src/console/consolecmd.h @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "consoledefs.h" + +typedef struct consolecmd_s consolecmd_t; + +typedef struct { + consolecmd_t *cmd; + char_t command[CONSOLE_LINE_MAX]; + char_t argv[CONSOLE_CMD_ARGC_MAX][CONSOLE_LINE_MAX]; + uint32_t argc; +} consolecmdexec_t; + +typedef void (*consolecmdfunc_t)(const consolecmdexec_t *exec); + +typedef struct consolecmd_s { + char_t name[CONSOLE_CMD_NAME_MAX]; + consolecmdfunc_t function; +} consolecmd_t; + +/** + * Initializes a console command. + * + * @param cmd Pointer to the console command. + * @param name The name of the command. + * @param function The function to execute when the command is called. + */ +void consoleCmdInit( + consolecmd_t *cmd, + const char_t *name, + consolecmdfunc_t function +); \ No newline at end of file diff --git a/src/console/consoledefs.h b/src/console/consoledefs.h new file mode 100644 index 0000000..6e6df0d --- /dev/null +++ b/src/console/consoledefs.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once + +#define CONSOLE_CMD_NAME_MAX 32 +#define CONSOLE_CMD_ARGC_MAX 16 + +#define CONSOLE_COMMANDS_MAX 128 +#define CONSOLE_VARIABLES_MAX 128 +#define CONSOLE_LINE_MAX 256 +#define CONSOLE_HISTORY_MAX 32 +#define CONSOLE_EXEC_BUFFER_MAX 16 + +#define CONSOLE_VAR_NAME_MAX 32 +#define CONSOLE_VAR_VALUE_MAX 128 +#define CONSOLE_VAR_EVENTS_MAX 8 \ No newline at end of file diff --git a/src/console/consolevar.c b/src/console/consolevar.c new file mode 100644 index 0000000..e126c89 --- /dev/null +++ b/src/console/consolevar.c @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "consolevar.h" +#include "assert/assert.h" +#include "util/memory.h" +#include "util/string.h" + +void consoleVarInit( + consolevar_t *var, + const char_t *name, + const char_t *value +) { + assertNotNull(var, "var must not be NULL"); + assertNotNull(name, "name must not be NULL"); + assertNotNull(value, "value must not be NULL"); + + assertStrLenMin(name, 1, "name must not be empty"); + assertStrLenMax(name, CONSOLE_VAR_NAME_MAX, "name is too long"); + assertStrLenMax(value, CONSOLE_VAR_VALUE_MAX, "value is too long"); + + memoryZero(var, sizeof(consolevar_t)); + stringCopy(var->name, name, CONSOLE_VAR_NAME_MAX); + stringCopy(var->value, value, CONSOLE_VAR_VALUE_MAX); +} + +void consoleVarInitListener( + consolevar_t *var, + const char_t *name, + const char_t *value, + consolevarchanged_t event +) { + consoleVarInit(var, name, value); + if(event) consoleVarListen(var, event); +} + +void consoleVarSetValue(consolevar_t *var, const char_t *value) { + assertNotNull(var, "var must not be NULL"); + assertNotNull(value, "value must not be NULL"); + assertStrLenMax(value, CONSOLE_VAR_VALUE_MAX, "value is too long"); + + stringCopy(var->value, value, CONSOLE_VAR_VALUE_MAX); + + uint8_t i = 0; + while (i < var->eventCount) { + var->events[i](var); + i++; + } +} + +void consoleVarListen(consolevar_t *var, consolevarchanged_t event) { + assertNotNull(var, "var must not be NULL"); + assertNotNull(event, "event must not be NULL"); + assertTrue( + var->eventCount < CONSOLE_VAR_EVENTS_MAX, + "Event count is too high" + ); + var->events[var->eventCount++] = event; +} + diff --git a/src/console/consolevar.h b/src/console/consolevar.h new file mode 100644 index 0000000..af6a9df --- /dev/null +++ b/src/console/consolevar.h @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "consoledefs.h" + +typedef struct consolevar_s consolevar_t; + +typedef void (*consolevarchanged_t)(const consolevar_t *var); + +typedef struct consolevar_s { + char_t name[CONSOLE_VAR_NAME_MAX]; + char_t value[CONSOLE_VAR_VALUE_MAX]; + consolevarchanged_t events[CONSOLE_VAR_EVENTS_MAX]; + uint8_t eventCount; +} consolevar_t; + +/** + * Initializes a console variable. + * + * @param var Pointer to the console variable. + * @param name The name of the variable. + * @param value The initial value of the variable. + */ +void consoleVarInit( + consolevar_t *var, + const char_t *name, + const char_t *value +); + +/** + * Initializes a console variable with a listener. + * + * @param var Pointer to the console variable. + * @param name The name of the variable. + * @param value The initial value of the variable. + * @param event The event to register. + */ +void consoleVarInitListener( + consolevar_t *var, + const char_t *name, + const char_t *value, + consolevarchanged_t event +); + +/** + * Sets the value of a console variable. + * + * @param var Pointer to the console variable. + * @param value The new value of the variable. + */ +void consoleVarSetValue(consolevar_t *var, const char_t *value); + +/** + * Registers an event to be called when the value of a console variable changes. + * + * @param var Pointer to the console variable. + * @param event The event to register. + */ +void consoleVarListen(consolevar_t *var, consolevarchanged_t event); \ No newline at end of file diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt new file mode 100644 index 0000000..46c5dbd --- /dev/null +++ b/src/display/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + render.c +) \ No newline at end of file diff --git a/src/display/render.c b/src/display/render.c new file mode 100644 index 0000000..9331e01 --- /dev/null +++ b/src/display/render.c @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "display/render.h" \ No newline at end of file diff --git a/src/display/render.h b/src/display/render.h new file mode 100644 index 0000000..2039247 --- /dev/null +++ b/src/display/render.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "error/error.h" + +#ifndef RENDER_WIDTH + #define RENDER_WIDTH 320 +#endif +#ifndef RENDER_HEIGHT + #define RENDER_HEIGHT 240 +#endif + +/** + * Initializes the rendering system. + */ +errorret_t renderInit(void); + +/** + * Tells the rendering system to actually draw the frame. + */ +errorret_t renderDraw(void); + +/** + * Disposes of the rendering system. + */ +errorret_t renderDispose(void); \ No newline at end of file diff --git a/src/dusk.h b/src/dusk.h new file mode 100644 index 0000000..8dd5e00 --- /dev/null +++ b/src/dusk.h @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef bool bool_t; +typedef int int_t; +typedef float float_t; +typedef char char_t; \ No newline at end of file diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt new file mode 100644 index 0000000..48dfead --- /dev/null +++ b/src/engine/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + engine.c +) \ No newline at end of file diff --git a/src/engine/engine.c b/src/engine/engine.c new file mode 100644 index 0000000..84a72dc --- /dev/null +++ b/src/engine/engine.c @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "engine.h" +#include "util/memory.h" +#include "time/time.h" +#include "console/console.h" + +engine_t ENGINE; + +void engineInit(void) { + memoryZero(&ENGINE, sizeof(engine_t)); + ENGINE.running = true; + + // Init systems. Order is important. + timeInit(); + consoleInit(); +} + +void engineUpdate(void) { + timeUpdate(); + consoleUpdate(); +} + +void engineDispose(void) { +} \ No newline at end of file diff --git a/src/engine/engine.h b/src/engine/engine.h new file mode 100644 index 0000000..f4b1e37 --- /dev/null +++ b/src/engine/engine.h @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct { + bool_t running; +} engine_t; + +extern engine_t ENGINE; + +/** + * Initializes the engine. + */ +void engineInit(void); + +/** + * Updates the engine. + */ +void engineUpdate(void); + +/** + * Shuts down the engine. + */ +void engineDispose(void); \ No newline at end of file diff --git a/src/error/CMakeLists.txt b/src/error/CMakeLists.txt new file mode 100644 index 0000000..b246fdb --- /dev/null +++ b/src/error/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + error.c +) \ No newline at end of file diff --git a/src/error/error.c b/src/error/error.c new file mode 100644 index 0000000..c6371fc --- /dev/null +++ b/src/error/error.c @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assert/assert.h" +#include "error.h" +#include "util/memory.h" +#include "util/string.h" + +errorret_t errorThrowImpl( + errorstate_t *state, + errorcode_t code, + const char_t *file, + const char_t *function, + const int32_t line, + const char_t *message, + ... +) { + assertNotNull(state, "Error state cannot be NULL"); + assertTrue(code != ERROR_OK, "Error code must not be OK"); + assertNotNull(file, "File cannot be NULL"); + assertNotNull(function, "Function cannot be NULL"); + assertTrue(line >= 0, "File pointer must be valid"); + assertNotNull(message, "Message cannot be NULL"); + + memoryZero(state, sizeof(errorstate_t)); + state->code = code; + + // Format args. + va_list args; + va_start(args, message); + + // Get length of formatted message + va_list argsCopy; + va_copy(argsCopy, args); + int32_t len = stringFormatVA(NULL, 0, message, argsCopy); + va_end(argsCopy); + + // Create string to hold the formatted message + state->message = (char_t *)memoryAllocate(len + 1); + stringFormatVA(state->message, len + 1, message, args); + va_end(args); + + // Format lines + len = stringFormat(NULL, 0, ERROR_LINE_FORMAT, file, line, function); + assertTrue(len >= 0, "Line formatting failed"); + state->lines = (char_t *)memoryAllocate(len + 1); + stringFormat(state->lines, len + 1, ERROR_LINE_FORMAT, file, line, function); + + return (errorret_t) { + .code = code, + .state = state + }; +} + +errorret_t errorOkImpl() { + return (errorret_t) { + .code = ERROR_OK, + .state = NULL + }; +} + +errorret_t errorChainImpl( + const errorret_t retval, + const char_t *file, + const char_t *function, + const int32_t line +) { + if (retval.code == ERROR_OK) return retval; + + assertNotNull(retval.state, "Error state cannot be NULL"); + assertNotNull(retval.state->message, "Message cannot be NULL"); + + // Create a new line string. + int32_t newLineLen = snprintf(NULL, 0, ERROR_LINE_FORMAT, file, line, function); + assertTrue(newLineLen >= 0, "Line formatting failed"); + char_t *newLine = (char_t *)memoryAllocate(newLineLen + 1); + snprintf(newLine, newLineLen + 1, ERROR_LINE_FORMAT, file, line, function); + + // Resize the existing lines to accommodate the new line + size_t existingLen = strlen(retval.state->lines); + memoryResize( + (void**)&retval.state->lines, + existingLen, + existingLen + newLineLen + 1 + ); + + // Now append the new line to the existing lines + memoryCopy( + retval.state->lines + existingLen, + newLine, + newLineLen + 1 + ); + + // Cleanup the temporary new line + memoryFree(newLine); + return retval; +} + +void errorCatch(const errorret_t retval) { + if (retval.code == ERROR_OK) return; + + assertNotNull(retval.state, "Error state cannot be NULL"); + assertNotNull(retval.state->message, "Message cannot be NULL"); + + memoryFree((void*)retval.state->message); +} + +errorret_t errorPrint(const errorret_t retval) { + if (retval.code == ERROR_OK) return retval; + + assertNotNull(retval.state, "Error state cannot be NULL"); + assertNotNull(retval.state->message, "Message cannot be NULL"); + + printf( + ERROR_PRINT_FORMAT, + retval.state->code, + retval.state->message, + retval.state->lines + ); + return retval; +} \ No newline at end of file diff --git a/src/error/error.h b/src/error/error.h new file mode 100644 index 0000000..c83c7df --- /dev/null +++ b/src/error/error.h @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef uint8_t errorcode_t; + +typedef struct { + errorcode_t code; + char_t *message; + char_t *lines; +} errorstate_t; + +typedef struct { + errorcode_t code; + errorstate_t *state; +} errorret_t; + +static const errorcode_t ERROR_OK = 0; +static const errorcode_t ERROR_NOT_OK = 1; +static const char_t *ERROR_PRINT_FORMAT = "Error (%d): %s\n%s"; +static const char_t *ERROR_LINE_FORMAT = " at %s:%d in function %s\n"; +static errorstate_t ERROR_STATE = { + .code = ERROR_OK, + .message = NULL, + .lines = NULL +}; + +/** + * Sets the error state with the provided code and message. + * + * @param state The error state to initialize. + * @param code The error code to set. + * @param file The file where the error occurred. + * @param function The function where the error occurred. + * @param line The line number where the error occurred. + * @param message The error message. + * @param args The arguments for the error message. + * @return The error code. + */ +errorret_t errorThrowImpl( + errorstate_t *state, + errorcode_t code, + const char_t *file, + const char_t *function, + const int32_t line, + const char_t *message, + ... +); + +/** + * Returns an error state with no error. + * + * @return An error state with code ERROR_OK. + */ +errorret_t errorOkImpl(); + +/** + * Chains an error state, allowing for error propagation. + * + * @param retval The return value containing the error state. + * @param file The file where the error occurred. + * @param function The function where the error occurred. + * @param line The line number where the error occurred. + * @return The error code if an error occurred, otherwise continues execution. + */ +errorret_t errorChainImpl( + const errorret_t retval, + const char_t *file, + const char_t *function, + const int32_t line +); + +/** + * Catches an error and handles it. + * + * @param retval The return value containing the error state. + */ +void errorCatch(const errorret_t retval); + +/** + * Prints the error state to the console. + * + * @param retval The return value containing the error state. + * @return Passed retval for chaining. + */ +errorret_t errorPrint(const errorret_t retval); + +/** + * Throws an error with a formatted message. + * + * @param code The error code to throw. + * @param message The format string for the error message. + * @param ... Additional arguments for the format string. + * @return The error code. + */ +#define errorThrowWithCode(code, message, ... ) \ + return errorThrowImpl(\ + &ERROR_STATE, (code), __FILE__, __func__, __LINE__, (message), \ + __VA_ARGS__ \ + ) + +/** + * Throws an error with a default error code of ERROR_NOT_OK. + * + * @param message The format string for the error message. + * @param ... Additional arguments for the format string. + * @return The error code. + */ +#define errorThrow(message, ...) \ + return errorThrowImpl(\ + &ERROR_STATE, ERROR_NOT_OK, __FILE__, __func__, __LINE__, (message), \ + __VA_ARGS__ \ + ) + +/** + * Checks if a child method errored, and if it did, then send it up the chain. + * @param retval The return value containing the error state. + * @return The error code if an error occurred, otherwise continues execution. + */ +#define errorChain(retval) \ + if ((retval).code != ERROR_OK) { \ + return errorChainImpl(retval, __FILE__, __func__, __LINE__); \ + } + +/** + * Returns without an error. + */ +#define errorOk() \ + return errorOkImpl() + +// EOF \ No newline at end of file diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt new file mode 100644 index 0000000..2ee57d2 --- /dev/null +++ b/src/input/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + input.c +) \ No newline at end of file diff --git a/src/input/input.c b/src/input/input.c new file mode 100644 index 0000000..967d635 --- /dev/null +++ b/src/input/input.c @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "input.h" +#include "assert/assert.h" +#include "util/memory.h" + +input_t INPUT; + +void inputInit(void) { + memoryZero(&INPUT, sizeof(input_t)); +} + +void inputUpdate(void) { + INPUT.previous = INPUT.current; + INPUT.current = inputStateGet(); +} + +inputstate_t inputStateGet(void) { + return 0; +} + +bool_t inputIsDown(const inputbind_t bind) { + assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds"); + return (INPUT.current & bind) != 0; +} + +bool_t inputWasDown(const inputbind_t bind) { + assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds"); + return (INPUT.previous & bind) != 0; +} + +bool_t inputPressed(const inputbind_t bind) { + return inputIsDown(bind) && !inputWasDown(bind); +} + +bool_t inputReleased(const inputbind_t bind) { + return !inputIsDown(bind) && inputWasDown(bind); +} \ No newline at end of file diff --git a/src/input/input.h b/src/input/input.h new file mode 100644 index 0000000..5dc43ba --- /dev/null +++ b/src/input/input.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef uint8_t inputbind_t; +typedef inputbind_t inputstate_t; + +#define INPUT_BIND_UP (1 << 0) +#define INPUT_BIND_DOWN (1 << 1) +#define INPUT_BIND_LEFT (1 << 2) +#define INPUT_BIND_RIGHT (1 << 3) +#define INPUT_BIND_ACTION (1 << 4) +#define INPUT_BIND_CANCEL (1 << 5) +#define INPUT_BIND_CONSOLE (1 << 6) +#define INPUT_BIND_QUIT (1 << 7) + +#define INPUT_BIND_COUNT (INPUT_BIND_QUIT + 1) + +typedef struct { + uint8_t current; + uint8_t previous; +} input_t; + +extern input_t INPUT; + +/** + * Initialize the input system. + */ +void inputInit(void); + +/** + * Updates the input state. + */ +void inputUpdate(void); + +/** + * Gets the current input state as a bitmask. + * + * @return The current input state as a bitmask. + */ +inputstate_t inputStateGet(void); + +/** + * Checks if a specific input bind is currently pressed. + * + * @param bind The input bind to check. + * @return true if the bind is currently pressed, false otherwise. + */ +bool_t inputIsDown(const inputbind_t bind); + +/** + * Checks if a specific input bind was pressed in the last update. + * + * @param bind The input bind to check. + * @return true if the bind was pressed in the last update, false otherwise. + */ +bool_t inputWasDown(const inputbind_t bind); + +/** + * Checks if a specific input bind was down this frame but not in the the + * previous frame. + * + * @param bind The input bind to check. + * @return true if the bind is currently pressed, false otherwise. + */ +bool_t inputPressed(const inputbind_t bind); + +/** + * Checks if a specific input bind was released this frame. + * + * @param bind The input bind to check. + * @return true if the bind was released this frame, false otherwise. + */ +bool_t inputReleased(const inputbind_t bind); \ No newline at end of file diff --git a/src/locale/CMakeLists.txt b/src/locale/CMakeLists.txt new file mode 100644 index 0000000..ef60e6d --- /dev/null +++ b/src/locale/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + language.c +) \ No newline at end of file diff --git a/src/locale/language.c b/src/locale/language.c new file mode 100644 index 0000000..2c70fd1 --- /dev/null +++ b/src/locale/language.c @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "language.h" +#include "assert/assert.h" + +language_t LANGUAGE; + +void languageInit(void) { + LANGUAGE.current = LANGUAGE_EN; +} + +const char_t * languageGet(const char_t *key) { + assertNotNull(key, "Key cannot be NULL"); + assertTrue(LANGUAGE.current < LANGUAGE_COUNT, "Invalid language index"); + + int16_t keyIndex = -1; + for(uint16_t i = 0; i < LANGUAGE_COUNTS[LANGUAGE.current]; i++) { + if(strcmp(LANGUAGE_KEYS[LANGUAGE.current][i], key) != 0) continue; + keyIndex = i; + break; + } + assertTrue(keyIndex != -1, "Key not found in language"); + return LANGUAGE_VALUES[LANGUAGE.current][keyIndex]; +} + +uint16_t langaugeGetLength(const char_t *key) { + assertNotNull(key, "Key cannot be NULL"); + assertTrue(LANGUAGE.current < LANGUAGE_COUNT, "Invalid language index"); + + int16_t keyIndex = -1; + for(uint16_t i = 0; i < LANGUAGE_COUNTS[LANGUAGE.current]; i++) { + if(strcmp(LANGUAGE_KEYS[LANGUAGE.current][i], key) != 0) continue; + keyIndex = i; + break; + } + assertTrue(keyIndex != -1, "Key not found in language"); + return strlen(LANGUAGE_VALUES[LANGUAGE.current][keyIndex]); +} + +uint16_t languageFormat( + const char_t *key, + char_t *buffer, + uint16_t buffSize, + const char_t **keys, + const char_t **values, + const uint16_t valueCount +) { + if(buffer != NULL) { + assertTrue(buffSize > 0, "Buffer size must be greater than 0"); + } else { + assertTrue(buffSize == 0, "Buffer size must be 0 if buffer is NULL"); + } + + assertNotNull(key, "Key cannot be NULL"); + assertNotNull(keys, "Keys cannot be NULL"); + assertNotNull(values, "Values cannot be NULL"); + + const char_t *val = languageGet(key); + assertNotNull(val, "Value for key cannot be NULL"); + + char_t c; + uint16_t i = 0; + uint16_t j = 0; + uint8_t k = 0; + bool_t inBraces = false; + char_t braceBuffer[64] = {0}; + + #define bufferChar(c) ( \ + (buffer ? (buffer[j++] = c) : (j++)), \ + assertTrue(buffer ? j < buffSize : true, "Buffer overflow") \ + ) + + while((c = val[i++]) != '\0') { + if(c == '{' && val[i] == '{') { + goto startBraces; + } else if(c == '}' && val[i] == '}') { + goto endBraces; + } else if(inBraces) { + goto braceBuffering; + } else { + goto character; + } + + character: { + bufferChar(c); + continue; + } + + braceBuffering: { + assertFalse(val[i] == '\0', "Unexpected end of string."); + braceBuffer[k++] = c; + assertTrue(k < sizeof(braceBuffer), "Brace buffer overflow"); + if(val[i] == ' ') i++; + continue; + } + + startBraces: { + assertFalse(inBraces, "Nested braces are not allowed"); + + inBraces = true; + i++; + k = 0; + assertFalse(val[i] == '\0', "Unexpected end of string."); + if(val[i] == ' ') i++; + continue; + } + + endBraces: { + assertTrue(inBraces, "Unmatched closing brace found"); + + inBraces = false; + i++; + braceBuffer[k] = '\0'; + + uint16_t l; + for(l = 0; l < valueCount; l++) { + if(strcmp(braceBuffer, keys[l]) != 0) { + continue; + } + const char_t *replacement = values[l]; + + uint16_t r = 0; + while((c = replacement[r++]) != '\0') { + bufferChar(c); + } + break; + } + assertTrue(l < valueCount, "No string replacement found!"); + continue; + } + } + + if(buffer){ + assertTrue(j < buffSize, "Buffer overflow"); + buffer[j] = '\0'; + } + + assertFalse(inBraces, "Unmatched opening brace found"); + return j; +} \ No newline at end of file diff --git a/src/locale/language.h b/src/locale/language.h new file mode 100644 index 0000000..d80d925 --- /dev/null +++ b/src/locale/language.h @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "locale/language/languages.h" + +typedef struct { + uint8_t current; +} language_t; + +extern language_t LANGUAGE; + +/** + * Initializes the language system. + * + * This function sets up the language system, loading the default language + * and preparing any necessary resources for language handling. + */ +void languageInit(void); + +/** + * Gets a language string by its key. + * + * @param key The key for the language string. + * @return The language string associated with the key. + */ +const char_t * languageGet(const char_t *key); + +/** + * Gets the length of a language string by its key. + * + * @param key The key for the language string. + * @return The length of the language string associated with the key. + */ +uint16_t langaugeGetLength(const char_t *key); + +/** + * Formats a language string with given keys and values. + * + * This function replaces placeholders in the language string with the provided + * values based on the keys. + * + * If buffer is NULL, the function will instead calculate the length of the + * formatted string. + * + * @param key The key for the language string to format. + * @param buffer The buffer to store the formatted string. + * @param buffSize The size of the buffer. + * @param keys An array of keys to replace in the language string. + * @param values An array of values corresponding to the keys. + * @param valueCount The number of key-value pairs. + * @return The number of characters written to the buffer. + */ +uint16_t languageFormat( + const char_t *key, + char_t *buffer, + uint16_t buffSize, + const char_t **keys, + const char_t **values, + const uint16_t valueCount +); \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..b1d7f4d --- /dev/null +++ b/src/main.c @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "engine/engine.h" + +#include "thread/thread.h" +thread_t thread; +threadmutex_t mutex; + +void myCoolThread(thread_t *thread) { + printf("Hello from myCoolThread!\n"); +} + +int main(int argc, char **argv) { + threadInit(&thread, myCoolThread); + threadStart(&thread); + threadStop(&thread); + return 0; + + engineInit(); + for(;;) engineUpdate(); + engineDispose(); + return 0; +} \ No newline at end of file diff --git a/src/scene/scene.h b/src/scene/scene.h new file mode 100644 index 0000000..e2ebbbb --- /dev/null +++ b/src/scene/scene.h @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct { + int padding; +} scene_t; + +extern scene_t *SCENE; \ No newline at end of file diff --git a/src/thread/CMakeLists.txt b/src/thread/CMakeLists.txt new file mode 100644 index 0000000..c566069 --- /dev/null +++ b/src/thread/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + thread.c + threadmutex.c +) + +# Compiler flags. +if(DUSK_TARGET_SYSTEM STREQUAL "linux") + target_compile_definitions(${DUSK_TARGET_NAME} + PRIVATE + DUSK_THREAD_PTHREAD=1 + ) +endif() \ No newline at end of file diff --git a/src/thread/thread.c b/src/thread/thread.c new file mode 100644 index 0000000..2807ae6 --- /dev/null +++ b/src/thread/thread.c @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "thread.h" +#include "util/memory.h" +#include "assert/assert.h" + +void threadInit(thread_t *thread, const threadcallback_t callback) { + assertNotNull(thread, "Thread cannot be NULL."); + assertNotNull(callback, "Thread callback cannot be NULL."); + + memoryZero(thread, sizeof(thread_t)); + + thread->state = THREAD_STATE_STOPPED; + thread->callback = callback; + + #if DUSK_THREAD_PTHREAD + thread->threadId = 0; + #endif +} + +void threadStartRequest(thread_t *thread) { + assertNotNull(thread, "Thread cannot be NULL."); + + printf("Starting thread...\n"); + threadMutexLock(&thread->stateMutex); + thread->state = THREAD_STATE_STARTING; + threadMutexUnlock(&thread->stateMutex); + printf("Thread marked starting.\n"); + + #if DUSK_THREAD_PTHREAD + assertTrue(thread->threadId == 0, "Thread id not 0."); + + pthread_create( + &thread->threadId, + NULL, + (void * (*)(void *))threadHandler, + thread + ); + pthread_detach(thread->threadId); + #endif + + printf("Thread created.\n"); +} + +void threadStopRequest(thread_t *thread) { + assertNotNull(thread, "Thread cannot be NULL."); + + + threadMutexLock(&thread->stateMutex); + if(thread->state != THREAD_STATE_STOPPED) { + thread->state = THREAD_STATE_STOP_REQUESTED; + } + threadMutexUnlock(&thread->stateMutex); +} + +void threadStart(thread_t *thread) { + assertNotNull(thread, "Thread cannot be NULL."); + + threadStartRequest(thread); + threadMutexLock(&thread->stateMutex); + threadMutexWaitLock(&thread->stateMutex); + threadMutexUnlock(&thread->stateMutex); + printf("Thread is now running.\n"); +} + +void threadStop(thread_t *thread) { + assertNotNull(thread, "Thread cannot be NULL."); + + threadStopRequest(thread); + threadMutexLock(&thread->stateMutex); + while(thread->state != THREAD_STATE_STOPPED) { + threadMutexWaitLock(&thread->stateMutex); + } + threadMutexUnlock(&thread->stateMutex); +} + +#if DUSK_THREAD_PTHREAD + void * threadHandler(thread_t *thread) { + assertNotNull(thread, "Thread cannot be NULL."); + + threadMutexLock(&thread->stateMutex); + thread->state = THREAD_STATE_RUNNING; + threadMutexSignal(&thread->stateMutex); + threadMutexUnlock(&thread->stateMutex); + + // Send to callback. + thread->callback(thread); + + threadMutexLock(&thread->stateMutex); + thread->state = THREAD_STATE_STOPPED; + threadMutexSignal(&thread->stateMutex); + threadMutexUnlock(&thread->stateMutex); + thread->threadId = 0; + return NULL; + } +#endif \ No newline at end of file diff --git a/src/thread/thread.h b/src/thread/thread.h new file mode 100644 index 0000000..5f97e6d --- /dev/null +++ b/src/thread/thread.h @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "thread/threadmutex.h" + +#if DUSK_THREAD_PTHREAD + #include +#else + #error "At least one threading implementation must be defined." +#endif + +typedef struct thread_s thread_t; + +typedef void (*threadcallback_t)(thread_t *thread); + +typedef enum { + // Thread is definitely not running. + THREAD_STATE_STOPPED, + + // Start has been requested, it may even be started by the time you + // see this value. + THREAD_STATE_STARTING, + + // Thread has definitely started and is running. + THREAD_STATE_RUNNING, + + // Something has requested the thread to stop, but it may not have + // stopped yet. + THREAD_STATE_STOP_REQUESTED, +} threadstate_t; + +typedef struct thread_s { + threadstate_t state; + threadmutex_t stateMutex; + threadcallback_t callback; + void *data; + + #if DUSK_THREAD_PTHREAD + pthread_t threadId; + #endif +} thread_t; + +/** + * Initializes a thread structure. + * + * @param thread Pointer to the thread structure to initialize. + * @param callback The callback function to be called when the thread runs. + */ +void threadInit(thread_t *thread, const threadcallback_t callback); + +/** + * Starts the thread, does not wait for it to finish starting. + * + * @param thread Pointer to the thread structure to start. + */ +void threadStartRequest(thread_t *thread); + +/** + * Requests the thread to stop, does not block the calling thread. + * + * @param thread Pointer to the thread structure to stop. + */ +void threadStopRequest(thread_t *thread); + +/** + * Starts the thread, blocking until it has started. Does this as efficiently as + * possible depending on the threading implementation. Note that it is possible + * for the thread to fully COMPLETE before this function returns. + * + * @param thread Pointer to the thread structure to start. + */ +void threadStart(thread_t *thread); + +/** + * Stops the thread, blocking until it has stopped. Does this as efficiently as + * possible depending on the threading implementation. + * + * @param thread Pointer to the thread structure to stop. + */ +void threadStop(thread_t *thread); + +#if DUSK_THREAD_PTHREAD + /** + * Handles the thread's lifecycle for pthreads. + * @param thread Pointer to the thread structure to handle. + */ + void * threadHandler(thread_t *thread); +#endif \ No newline at end of file diff --git a/src/thread/threadmutex.c b/src/thread/threadmutex.c new file mode 100644 index 0000000..e0b4807 --- /dev/null +++ b/src/thread/threadmutex.c @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "threadmutex.h" + +void threadMutexInit(threadmutex_t *lock) { + #if DUSK_THREAD_PTHREAD + pthread_mutex_init(&lock->mutex, NULL); + #endif +} + +void threadMutexLock(threadmutex_t *lock) { + #if DUSK_THREAD_PTHREAD + pthread_mutex_lock(&lock->mutex); + #endif +} + +bool_t threadMutexTryLock(threadmutex_t *lock) { + #if DUSK_THREAD_PTHREAD + return pthread_mutex_trylock(&lock->mutex) == 0; + #endif +} + +void threadMutexUnlock(threadmutex_t *lock) { + #if DUSK_THREAD_PTHREAD + pthread_mutex_unlock(&lock->mutex); + #endif +} + +void threadMutexWaitLock(threadmutex_t *lock) { + #if DUSK_THREAD_PTHREAD + pthread_cond_wait(&lock->cond, &lock->mutex); + #endif +} + +void threadMutexSignal(threadmutex_t *lock) { + #if DUSK_THREAD_PTHREAD + pthread_cond_signal(&lock->cond); + #endif +} + +void threadMutexDispose(threadmutex_t *lock) { + #if DUSK_THREAD_PTHREAD + pthread_mutex_destroy(&lock->mutex); + #endif +} \ No newline at end of file diff --git a/src/thread/threadmutex.h b/src/thread/threadmutex.h new file mode 100644 index 0000000..8cd7e3c --- /dev/null +++ b/src/thread/threadmutex.h @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +#if DUSK_THREAD_PTHREAD + #include +#else + #error "At least one threading implementation must be defined." +#endif + +typedef struct threadlock_t { + #if DUSK_THREAD_PTHREAD + pthread_mutex_t mutex; + pthread_cond_t cond; + #endif +} threadmutex_t; + +/** + * Initializes a thread mutex. + * + * @param lock Pointer to the thread mutex structure to initialize. + */ +void threadMutexInit(threadmutex_t *lock); + +/** + * Locks the thread mutex. + * + * @param lock Pointer to the thread mutex structure to lock. + */ +void threadMutexLock(threadmutex_t *lock); + +/** + * Attempts to lock the thread mutex without blocking. + * + * @param lock Pointer to the thread mutex structure to try locking. + * @return true if the lock was acquired, false otherwise. + */ +bool_t threadMutexTryLock(threadmutex_t *lock); + +/** + * Unlocks the thread mutex. + * + * @param lock Pointer to the thread mutex structure to unlock. + */ +void threadMutexUnlock(threadmutex_t *lock); + +/** + * Releases the thread mutex and waits for it to be locked again. + * + * @param lock Pointer to the thread mutex structure to wait on. + */ +void threadMutexWaitLock(threadmutex_t *lock); + +/** + * Signals the thread mutex, allowing a waiting thread to proceed as soon as + * this mutex is unlocked. + * + * @param lock Pointer to the thread mutex structure to signal. + */ +void threadMutexSignal(threadmutex_t *lock); + +/** + * Disposes of the thread mutex. + * + * @param lock Pointer to the thread mutex structure to dispose. + */ +void threadMutexDispose(threadmutex_t *lock); \ No newline at end of file diff --git a/src/time/CMakeLists.txt b/src/time/CMakeLists.txt new file mode 100644 index 0000000..d8fd698 --- /dev/null +++ b/src/time/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + time.c +) \ No newline at end of file diff --git a/src/time/time.c b/src/time/time.c new file mode 100644 index 0000000..66416c2 --- /dev/null +++ b/src/time/time.c @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "time.h" +#include "util/memory.h" +#include "assert/assert.h" + +dusktime_t TIME; + +void timeInit(void) { + memoryZero(&TIME, sizeof(TIME)); + + // Set these to something non-zero. + TIME.lastTick = DUSK_TIME_STEP; + TIME.delta = TIME.realDelta = DUSK_TIME_STEP; + TIME.realTime = TIME.time = DUSK_TIME_STEP * 2; +} + +void timeUpdate(void) { + TIME.realDelta = timeDeltaGet(); + + #if DUSK_TIME_DYNAMIC + TIME.delta = TIME.realDelta; + #else + TIME.delta = DUSK_TIME_PLATFORM_STEP; + #endif + + assertTrue(TIME.delta >= 0.0f, "Time delta is negative"); + assertTrue(TIME.realDelta >= 0.0f, "Real time delta is negative"); + + TIME.time += TIME.delta; + TIME.realTime += TIME.realDelta; +} + +float_t timeDeltaGet(void) { + return 0.1f; +} \ No newline at end of file diff --git a/src/time/time.h b/src/time/time.h new file mode 100644 index 0000000..7c878c8 --- /dev/null +++ b/src/time/time.h @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct { + float_t delta; + float_t lastTick; + float_t time; + float_t realDelta; + float_t realTime; +} dusktime_t; + +extern dusktime_t TIME; + +#define DUSK_TIME_STEP (1.0f / 60.0f) // Default to 60FPS + +#ifndef DUSK_TIME_DYNAMIC + #define DUSK_TIME_DYNAMIC 1 +#endif + +#if DUSK_TIME_DYNAMIC == 0 + #ifndef DUSK_TIME_PLATFORM_STEP + #define DUSK_TIME_PLATFORM_STEP DUSK_TIME_STEP + #endif +#endif + +/** + * Initializes the time system. + */ +void timeInit(void); + +/** + * Updates the time system + */ +void timeUpdate(void); + +#if DUSK_TIME_DYNAMIC == 1 + /** + * Gets the time delta since the last frame, in seconds. Tied to the + * platform. + * + * This will only get called once per gameUpdate. + */ + float_t timeDeltaGet(void); +#endif + diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt new file mode 100644 index 0000000..75b1187 --- /dev/null +++ b/src/util/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + memory.c + string.c + math.c +) \ No newline at end of file diff --git a/src/util/math.c b/src/util/math.c new file mode 100644 index 0000000..ac538d1 --- /dev/null +++ b/src/util/math.c @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "math.h" + +uint32_t mathNextPowTwo(uint32_t value) { + if (value == 0) return 1; // Handle zero case + value--; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + return value + 1; +} \ No newline at end of file diff --git a/src/util/math.h b/src/util/math.h new file mode 100644 index 0000000..ac9bc07 --- /dev/null +++ b/src/util/math.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +/** + * Finds the next power of two greater than or equal to the given value. + * + * @param value The value to find the next power of two for. + * @return The next power of two greater than or equal to the value. + */ +uint32_t mathNextPowTwo(uint32_t value); \ No newline at end of file diff --git a/src/util/memory.c b/src/util/memory.c new file mode 100644 index 0000000..3e0fea8 --- /dev/null +++ b/src/util/memory.c @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "memory.h" +#include "assert/assert.h" + +void * memoryAllocate(const size_t size) { + assertTrue(size > 0, "Cannot allocate 0 bytes of memory."); + void *ptr = malloc(size); + assertNotNull(ptr, "Memory allocation failed."); + return ptr; +} + +void memoryFree(void *ptr) { + assertNotNull(ptr, "Cannot free NULL memory."); + free(ptr); +} + + +void memoryCopy(void *dest, const void *src, const size_t size) { + assertNotNull(dest, "Cannot copy to NULL memory."); + assertNotNull(src, "Cannot copy from NULL memory."); + assertTrue(size > 0, "Cannot copy 0 bytes of memory."); + assertTrue(dest != src, "Cannot copy memory to itself."); + memcpy(dest, src, size); +} + +void memorySet(void *dest, const uint8_t value, const size_t size) { + assertNotNull(dest, "Cannot set NULL memory."); + assertTrue(size > 0, "Cannot set 0 bytes of memory."); + memset(dest, value, size); +} + +void memoryZero(void *dest, const size_t size) { + memorySet(dest, 0, size); +} + +void memoryCopyRangeSafe( + void *dest, + const void *start, + const void *end, + const size_t sizeMax +) { + assertFalse(start == end, "Start and end pointers are the same."); + assertTrue(end > start, "End pointer is not after start pointer."); + + size_t copy = (size_t)end - (size_t)start; + assertTrue(copy <= sizeMax, "Size of memory to copy is too large."); + memoryCopy(dest, start, copy); +} + +void memoryMove(void *dest, const void *src, const size_t size) { + assertNotNull(dest, "Cannot move to NULL memory."); + assertNotNull(src, "Cannot move from NULL memory."); + assertTrue(size > 0, "Cannot move 0 bytes of memory."); + assertTrue(dest != src, "Cannot move memory to itself."); + memmove(dest, src, size); +} + +int_t memoryCompare( + const void *a, + const void *b, + const size_t size +) { + assertNotNull(a, "Cannot compare NULL memory."); + assertNotNull(b, "Cannot compare NULL memory."); + assertTrue(size > 0, "Cannot compare 0 bytes of memory."); + return memcmp(a, b, size); +} + +void memoryReallocate(void **ptr, const size_t size) { + assertNotNull(ptr, "Cannot reallocate NULL pointer."); + assertTrue(size > 0, "Cannot reallocate to 0 bytes of memory."); + void *newPointer = memoryAllocate(size); + assertNotNull(newPointer, "Memory reallocation failed."); + memoryFree(*ptr); + *ptr = newPointer; +} + +void memoryResize(void **ptr, const size_t oldSize, const size_t newSize) { + assertNotNull(ptr, "Cannot resize NULL pointer."); + if(newSize == oldSize) return; + if(oldSize == 0) return memoryReallocate(ptr, newSize); + + assertTrue(newSize > oldSize, "New size must be greater than old size."); + + void *newPointer = memoryAllocate(newSize); + assertNotNull(newPointer, "Memory resizing failed."); + memoryCopy(newPointer, *ptr, oldSize); + memoryFree(*ptr); + *ptr = newPointer; +} \ No newline at end of file diff --git a/src/util/memory.h b/src/util/memory.h new file mode 100644 index 0000000..1e08137 --- /dev/null +++ b/src/util/memory.h @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +/** + * Allocates memory. + * + * @param size The size of the memory to allocate. + * @return The allocated memory. + */ +void * memoryAllocate(const size_t size); + +/** + * Frees memory. + * + * @param ptr The memory to free. + */ +void memoryFree(void *ptr); + +/** + * Copies memory. + * + * @param dest The destination to copy to. + * @param src The source to copy from. + * @param size The size of the memory to copy. + */ +void memoryCopy(void *dest, const void *src, const size_t size); + +/** + * Sets memory. + * + * @param dest The destination to set. + * @param value The value to set. + * @param size The size of the memory to set. + */ +void memorySet(void *dest, const uint8_t value, const size_t size); + +/** + * Zeroes memory. + * + * @param dest The destination to zero. + * @param size The size of the memory to zero. + */ +void memoryZero(void *dest, const size_t size); + +/** + * Copies memory, ensuring that the memory range is as expected, typically this + * is done if you're trying to reshape data in a buffer. Extremely useful in + * copying data to a shader buffer. + * + * @param dest The destination to copy to. + * @param start The start of the source to copy from. + * @param end The end of the source to copy from. + * @param sizeMax The maximum size of the memory to copy. + */ +void memoryCopyRangeSafe( + void *dest, + const void *start, + const void *end, + const size_t sizeMax +); + +/** + * Moves memory. + * + * @param dest The destination to move to. + * @param src The source to move from. + * @param size The size of the memory to move. + */ +void memoryMove(void *dest, const void *src, const size_t size); + +/** + * Compares memory. + * + * @param a The first memory to compare. + * @param b The second memory to compare. + * @param size The size of the memory to compare. + * @return 0 if the memory is equal, < 0 if a < b, > 0 if a > b. + */ +int_t memoryCompare( + const void *a, + const void *b, + const size_t size +); + +/** + * Reallocates memory. + * + * @param ptr The pointer to the memory to reallocate. + * @param size The new size of the memory. + */ +void memoryReallocate(void **ptr, const size_t size); + +/** + * Reallocates memory, but copies existing data to the new memory. + * + * @param ptr The pointer to the memory to resize. + * @param oldSize The old size of the memory. + * @param newSize The new size of the memory. + */ +void memoryResize(void **ptr, const size_t oldSize, const size_t newSize); \ No newline at end of file diff --git a/src/util/string.c b/src/util/string.c new file mode 100644 index 0000000..264a158 --- /dev/null +++ b/src/util/string.c @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "string.h" +#include "assert/assert.h" +#include "util/memory.h" + +bool_t stringIsWhitespace(const char_t c) { + return isspace(c); +} + +void stringCopy(char_t *dest, const char_t *src, const size_t destSize) { + assertNotNull(dest, "dest must not be NULL"); + assertNotNull(src, "src must not be NULL"); + assertTrue(destSize > 0, "destSize must be greater than 0"); + assertStrLenMax(src, destSize, "src is too long"); + memoryCopy(dest, src, strlen(src) + 1); +} + +int stringCompare(const char_t *str1, const char_t *str2) { + assertNotNull(str1, "str1 must not be NULL"); + assertNotNull(str2, "str2 must not be NULL"); + return strcmp(str1, str2); +} + +void stringTrim(char_t *str) { + assertNotNull(str, "str must not be NULL"); + + // Trim leading whitespace + char_t *start = str; + while(stringIsWhitespace(*start)) start++; + + // Trim trailing whitespace + char_t *end = start + strlen(start) - 1; + while (end >= start && stringIsWhitespace(*end)) end--; + + // Null-terminate the string + *(end + 1) = '\0'; + + // Move trimmed string to the original buffer + if (start != str) memmove(str, start, end - start + 2); +} + +char_t * stringToken(char_t *str, const char_t *delim) { + assertNotNull(str, "str must not be NULL"); + assertNotNull(delim, "delim must not be NULL"); + return strtok(str, delim); +} + +int32_t stringFormat( + char_t *dest, + const size_t destSize, + const char_t *format, + ... +) { + va_list args; + va_start(args, format); + int32_t len = stringFormatVA(dest, destSize, format, args); + va_end(args); + return len; +} + +int32_t stringFormatVA( + char_t *dest, + const size_t destSize, + const char_t *format, + const va_list args +) { + assertNotNull(format, "format must not be NULL"); + + if(dest == NULL) { + int32_t ret = vsnprintf(NULL, 0, format, args); + assertTrue(ret >= 0, "Failed to format string."); + return ret; + } + + assertTrue(destSize > 0, "destSize must be greater than 0"); + int32_t ret = vsnprintf(dest, destSize, format, args); + assertTrue(ret >= 0, "Failed to format string."); + assertTrue(ret < destSize, "Formatted string is too long."); + return ret; +} + +bool_t stringToI32(const char_t *str, int32_t *out) { + assertNotNull(str, "str must not be NULL"); + assertNotNull(out, "out must not be NULL"); + + char_t *endptr; + errno = 0; + long int result = strtol(str, &endptr, 10); + if (errno != 0 || *endptr != '\0') { + return false; + } + *out = (int32_t)result; + return true; +} + +bool_t stringToI64(const char_t *str, int64_t *out) { + assertNotNull(str, "str must not be NULL"); + assertNotNull(out, "out must not be NULL"); + + char_t *endptr; + errno = 0; + long long int result = strtoll(str, &endptr, 10); + if (errno != 0 || *endptr != '\0') { + return false; + } + *out = (int64_t)result; + return true; +} + +bool_t stringToU16(const char_t *str, uint16_t *out) { + assertNotNull(str, "str must not be NULL"); + assertNotNull(out, "out must not be NULL"); + + char_t *endptr; + errno = 0; + unsigned long int result = strtoul(str, &endptr, 10); + if (errno != 0 || *endptr != '\0' || result > UINT16_MAX) { + return false; + } + *out = (uint16_t)result; + return true; +} \ No newline at end of file diff --git a/src/util/string.h b/src/util/string.h new file mode 100644 index 0000000..77c5fb0 --- /dev/null +++ b/src/util/string.h @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +/** + * Determines if a character is whitespace. + * + * @param c The character to check. + * @return TRUE if the character is whitespace, FALSE otherwise. + */ +bool_t stringIsWhitespace(const char_t c); + +/** + * Copies a string from src to dest, ensuring the dest string is null-terminated + * and does not exceed the specified size. + * + * @param dest The destination string. + * @param src The source string. + * @param destSize The size of the destination string exc. null terminator. + */ +void stringCopy(char_t *dest, const char_t *src, const size_t destSize); + +/** + * Compares two strings. + * + * @param str1 The first string. + * @param str2 The second string. + * @return 0 if the strings are equal, -1 if str1 is less than str2, 1 if str1 + * is greater than str2. + */ +int stringCompare(const char_t *str1, const char_t *str2); + +/** + * Trims whitespace from the beginning and end of a string. + * + * @param str The string to trim. + */ +void stringTrim(char_t *str); + +/** + * Gets the next token in a string using a delimiter. + * e.g. input: "Hello, World, Happy Monday!" with stringToken(input, ",") will + * return "Hello" then " World" then " Happy Monday!" on each subsequent call. + * + * @param str The string to split. + * @param delim The delimiter to split by. + * @return A pointer to the next token in the string. + */ +char_t * stringToken(char_t *str, const char_t *delim); + +/** + * Formats a string. + * + * @param dest The destination string, or NULL to get the length of the + * formatted string. + * @param destSize The size of the destination string exc. null terminator, can + * be anything if dest is NULL. + * @param format The format string. + * @param ... The arguments to format. + * @return The number of characters written. + */ +int32_t stringFormat( + char_t *dest, + const size_t destSize, + const char_t *format, + ... +); + +/** + * Formats a string using a va_list. + * + * @param dest The destination string, or NULL to get the length of the + * formatted string. + * @param destSize The size of the destination string exc. null terminator, can + * be anything if dest is NULL. + * @param format The format string. + * @param args The va_list of arguments. + * @return The number of characters written. + */ +int32_t stringFormatVA( + char_t *dest, + const size_t destSize, + const char_t *format, + const va_list args +); + +/** + * Converts a string to an integer. + * + * @param str The string to convert. + * @param out The output integer. + * @return TRUE if the conversion was successful, FALSE otherwise. + */ +bool_t stringToI32(const char_t *str, int32_t *out); + +/** + * Converts a string to a signed 16-bit integer. + * + * @param str The string to convert. + * @param out The output signed integer. + * @return TRUE if the conversion was successful, FALSE otherwise. + */ +bool_t stringToI16(const char_t *str, int16_t *out); + +/** + * Converts a string to an unsigned 16-bit integer. + * + * @param str The string to convert. + * @param out The output unsigned integer. + * @return TRUE if the conversion was successful, FALSE otherwise. + */ +bool_t stringToU16(const char_t *str, uint16_t *out); \ No newline at end of file