initial commit

This commit is contained in:
2026-04-06 13:27:44 -04:00
commit 5aaecdeac6
24 changed files with 2246 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
*.d
*.o
*.a
*.lib
*.dll
*.so
*.so.*
*.dylib
*.exe
*.out
*.dSYM/
*.su
*.idb
*.pdb
obj/
bin/
+373
View File
@@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
+4
View File
@@ -0,0 +1,4 @@
# skele
Generic game framework written in C99.
+178
View File
@@ -0,0 +1,178 @@
CLOCK_SRC = src/platform/clock/posix.c
INPUT_SRC = src/platform/client/input/sdl.c
.include "config.mk"
ENGINE_SRCS = src/skele.c ${CLOCK_SRC}
SOFT_PLAT_SRCS = src/platform/client/video/sdl.c ${INPUT_SRC}
GL_PLAT_SRCS = src/platform/client/video/gl.c ${INPUT_SRC}
SOFT_CLIENT_SRCS = example/client/main.c
GL_CLIENT_SRCS = example/gl_client/main.c
SERVER_EXAMPLE = example/server/main.c
LIBSKELE_SRCS = ${ENGINE_SRCS} ${SOFT_PLAT_SRCS}
LIBGLSKELE_SRCS = ${ENGINE_SRCS} ${GL_PLAT_SRCS}
LIBSKELE_SRV_SRCS = ${ENGINE_SRCS}
LIBSKELE = ${BIN_DIR}/debug/libskele.a
LIBGLSKELE = ${BIN_DIR}/debug/libglskele.a
LIBSKELE_SRV = ${BIN_DIR}/debug/libskeleserver.a
SKELE_BIN = ${BIN_DIR}/debug/skele_client
GLSKELE_BIN = ${BIN_DIR}/debug/glskele_client
SERVER_BIN = ${BIN_DIR}/debug/skele_server
LIBSKELE_R = ${BIN_DIR}/release/libskele.a
LIBGLSKELE_R = ${BIN_DIR}/release/libglskele.a
LIBSKELE_SRV_R = ${BIN_DIR}/release/libskeleserver.a
SKELE_BIN_R = ${BIN_DIR}/release/skele_client
GLSKELE_BIN_R = ${BIN_DIR}/release/glskele_client
SERVER_BIN_R = ${BIN_DIR}/release/skele_server
LDFLAGS_PLAT = -L/usr/local/lib
CFLAGS_PLAT = -I/usr/local/include
CFLAGS_BASE = -Wall -Wpedantic -I${.CURDIR}/${INC_DIR} -std=c99 ${CFLAGS_PLAT} ${DEBUG_FLAGS} \
-DGL_MAJOR=${GL_MAJOR} -DGL_MINOR=${GL_MINOR}
LINK_STK = -Wl,-Bstatic -lstk -Wl,-Bdynamic
LIBSKELE_DEBUG_OBJS = ${LIBSKELE_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/debug\/soft\//}
LIBGLSKELE_DEBUG_OBJS = ${LIBGLSKELE_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/debug\/gl\//}
LIBSKELE_SRV_DEBUG_OBJS = ${LIBSKELE_SRV_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/debug\/server\//}
SOFT_CLIENT_DEBUG_OBJS = ${SOFT_CLIENT_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/debug\/soft\//}
GL_CLIENT_DEBUG_OBJS = ${GL_CLIENT_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/debug\/gl\//}
SERVER_DEBUG_OBJS = ${SERVER_EXAMPLE:S/.c$/.o/:S/^/${.CURDIR}\/obj\/debug\/server\//}
LIBSKELE_RELEASE_OBJS = ${LIBSKELE_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/release\/soft\//}
LIBGLSKELE_RELEASE_OBJS = ${LIBGLSKELE_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/release\/gl\//}
LIBSKELE_SRV_RELEASE_OBJS = ${LIBSKELE_SRV_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/release\/server\//}
SOFT_CLIENT_RELEASE_OBJS = ${SOFT_CLIENT_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/release\/soft\//}
GL_CLIENT_RELEASE_OBJS = ${GL_CLIENT_SRCS:S/.c$/.o/:S/^/${.CURDIR}\/obj\/release\/gl\//}
SERVER_RELEASE_OBJS = ${SERVER_EXAMPLE:S/.c$/.o/:S/^/${.CURDIR}\/obj\/release\/server\//}
ALL_SOFT_SRCS = ${LIBSKELE_SRCS} ${SOFT_CLIENT_SRCS}
ALL_GL_SRCS = ${LIBGLSKELE_SRCS} ${GL_CLIENT_SRCS}
ALL_SERVER_SRCS = ${LIBSKELE_SRV_SRCS} ${SERVER_EXAMPLE}
PREFIX ?= /usr/local
GL_MAJOR ?= 3
GL_MINOR ?= 3
.PHONY: all debug release skele glskele server libs install uninstall clean run run_gl
all: debug
debug: ${.CURDIR}/${LIBSKELE} ${.CURDIR}/${LIBGLSKELE} ${.CURDIR}/${LIBSKELE_SRV} \
${.CURDIR}/${SKELE_BIN} ${.CURDIR}/${GLSKELE_BIN} ${.CURDIR}/${SERVER_BIN}
release: ${.CURDIR}/${LIBSKELE_R} ${.CURDIR}/${LIBGLSKELE_R} ${.CURDIR}/${LIBSKELE_SRV_R} \
${.CURDIR}/${SKELE_BIN_R} ${.CURDIR}/${GLSKELE_BIN_R} ${.CURDIR}/${SERVER_BIN_R}
libs: ${.CURDIR}/${LIBSKELE} ${.CURDIR}/${LIBGLSKELE} ${.CURDIR}/${LIBSKELE_SRV}
skele: ${.CURDIR}/${LIBSKELE} ${.CURDIR}/${SKELE_BIN}
glskele: ${.CURDIR}/${LIBGLSKELE} ${.CURDIR}/${GLSKELE_BIN}
server: ${.CURDIR}/${LIBSKELE_SRV} ${.CURDIR}/${SERVER_BIN}
run: skele
${.CURDIR}/${SKELE_BIN}
run_gl: glskele
${.CURDIR}/${GLSKELE_BIN}
${.CURDIR}/${LIBSKELE}: ${LIBSKELE_DEBUG_OBJS}
@mkdir -p ${.TARGET:H}
ar rcs ${.TARGET} ${.ALLSRC}
${.CURDIR}/${LIBGLSKELE}: ${LIBGLSKELE_DEBUG_OBJS}
@mkdir -p ${.TARGET:H}
ar rcs ${.TARGET} ${.ALLSRC}
${.CURDIR}/${LIBSKELE_SRV}: ${LIBSKELE_SRV_DEBUG_OBJS}
@mkdir -p ${.TARGET:H}
ar rcs ${.TARGET} ${.ALLSRC}
${.CURDIR}/${LIBSKELE_R}: ${LIBSKELE_RELEASE_OBJS}
@mkdir -p ${.TARGET:H}
ar rcs ${.TARGET} ${.ALLSRC}
${.CURDIR}/${LIBGLSKELE_R}: ${LIBGLSKELE_RELEASE_OBJS}
@mkdir -p ${.TARGET:H}
ar rcs ${.TARGET} ${.ALLSRC}
${.CURDIR}/${LIBSKELE_SRV_R}: ${LIBSKELE_SRV_RELEASE_OBJS}
@mkdir -p ${.TARGET:H}
ar rcs ${.TARGET} ${.ALLSRC}
${.CURDIR}/${SKELE_BIN}: ${SOFT_CLIENT_DEBUG_OBJS} ${.CURDIR}/${LIBSKELE}
@mkdir -p ${.TARGET:H}
${CC} -o ${.TARGET} ${SOFT_CLIENT_DEBUG_OBJS} -L${.CURDIR}/${BIN_DIR}/debug -lskele ${LINK_STK} -lSDL3 ${LDFLAGS_PLAT}
${.CURDIR}/${GLSKELE_BIN}: ${GL_CLIENT_DEBUG_OBJS} ${.CURDIR}/${LIBGLSKELE}
@mkdir -p ${.TARGET:H}
${CC} -o ${.TARGET} ${GL_CLIENT_DEBUG_OBJS} -L${.CURDIR}/${BIN_DIR}/debug -lglskele ${LINK_STK} -lSDL3 -lGL ${LDFLAGS_PLAT}
${.CURDIR}/${SERVER_BIN}: ${SERVER_DEBUG_OBJS} ${.CURDIR}/${LIBSKELE_SRV}
@mkdir -p ${.TARGET:H}
${CC} -o ${.TARGET} ${SERVER_DEBUG_OBJS} -L${.CURDIR}/${BIN_DIR}/debug -lskeleserver ${LINK_STK} ${LDFLAGS_PLAT}
${.CURDIR}/${SKELE_BIN_R}: ${SOFT_CLIENT_RELEASE_OBJS} ${.CURDIR}/${LIBSKELE_R}
@mkdir -p ${.TARGET:H}
${CC} -s -o ${.TARGET} ${SOFT_CLIENT_RELEASE_OBJS} -L${.CURDIR}/${BIN_DIR}/release -lskele ${LINK_STK} -lSDL3 ${LDFLAGS_PLAT}
${.CURDIR}/${GLSKELE_BIN_R}: ${GL_CLIENT_RELEASE_OBJS} ${.CURDIR}/${LIBGLSKELE_R}
@mkdir -p ${.TARGET:H}
${CC} -s -o ${.TARGET} ${GL_CLIENT_RELEASE_OBJS} -L${.CURDIR}/${BIN_DIR}/release -lglskele ${LINK_STK} -lSDL3 -lGL ${LDFLAGS_PLAT}
${.CURDIR}/${SERVER_BIN_R}: ${SERVER_RELEASE_OBJS} ${.CURDIR}/${LIBSKELE_SRV_R}
@mkdir -p ${.TARGET:H}
${CC} -s -o ${.TARGET} ${SERVER_RELEASE_OBJS} -L${.CURDIR}/${BIN_DIR}/release -lskeleserver ${LINK_STK} ${LDFLAGS_PLAT}
.for _src in ${ALL_SOFT_SRCS}
${.CURDIR}/obj/debug/soft/${_src:S/.c$/.o/}: ${_src}
@mkdir -p ${.TARGET:H}
${CC} ${CFLAGS_BASE} -g -O0 -MMD -MP -MT ${.TARGET} -MF ${.TARGET:S/.o$/.d/} -c ${.ALLSRC} -o ${.TARGET}
${.CURDIR}/obj/release/soft/${_src:S/.c$/.o/}: ${_src}
@mkdir -p ${.TARGET:H}
${CC} ${CFLAGS_BASE} -O2 -MMD -MP -MT ${.TARGET} -MF ${.TARGET:S/.o$/.d/} -c ${.ALLSRC} -o ${.TARGET}
.endfor
.for _src in ${ALL_GL_SRCS}
${.CURDIR}/obj/debug/gl/${_src:S/.c$/.o/}: ${_src}
@mkdir -p ${.TARGET:H}
${CC} ${CFLAGS_BASE} -g -O0 -MMD -MP -MT ${.TARGET} -MF ${.TARGET:S/.o$/.d/} -c ${.ALLSRC} -o ${.TARGET}
${.CURDIR}/obj/release/gl/${_src:S/.c$/.o/}: ${_src}
@mkdir -p ${.TARGET:H}
${CC} ${CFLAGS_BASE} -O2 -MMD -MP -MT ${.TARGET} -MF ${.TARGET:S/.o$/.d/} -c ${.ALLSRC} -o ${.TARGET}
.endfor
.for _src in ${ALL_SERVER_SRCS}
${.CURDIR}/obj/debug/server/${_src:S/.c$/.o/}: ${_src}
@mkdir -p ${.TARGET:H}
${CC} ${CFLAGS_BASE} -g -O0 -MMD -MP -MT ${.TARGET} -MF ${.TARGET:S/.o$/.d/} -c ${.ALLSRC} -o ${.TARGET}
${.CURDIR}/obj/release/server/${_src:S/.c$/.o/}: ${_src}
@mkdir -p ${.TARGET:H}
${CC} ${CFLAGS_BASE} -O2 -MMD -MP -MT ${.TARGET} -MF ${.TARGET:S/.o$/.d/} -c ${.ALLSRC} -o ${.TARGET}
.endfor
.-include "obj/debug/soft/*.d"
.-include "obj/debug/gl/*.d"
.-include "obj/debug/server/*.d"
.-include "obj/release/soft/*.d"
.-include "obj/release/gl/*.d"
.-include "obj/release/server/*.d"
install: release
install -d ${PREFIX}/lib
install -d ${PREFIX}/include/skele
install -m 644 ${.CURDIR}/${LIBSKELE_R} ${PREFIX}/lib/libskele.a
install -m 644 ${.CURDIR}/${LIBGLSKELE_R} ${PREFIX}/lib/libglskele.a
install -m 644 ${.CURDIR}/${LIBSKELE_SRV_R} ${PREFIX}/lib/libskeleserver.a
cp -r ${.CURDIR}/include/ ${PREFIX}/include/skele/
install -d ${PREFIX}/bin
uninstall:
rm -f ${PREFIX}/lib/libskele.a
rm -f ${PREFIX}/lib/libglskele.a
rm -f ${PREFIX}/lib/libskeleserver.a
rm -rf ${PREFIX}/include/skele
clean:
rm -rf ${.CURDIR}/${OBJ_DIR} ${.CURDIR}/${BIN_DIR}
+10
View File
@@ -0,0 +1,10 @@
@echo off
if "%1"=="run" (
if "%2"=="" (
make -f gmake.mk run MODE=debug
) else (
make -f gmake.mk run MODE=%2
)
) else (
make -f gmake.mk %*
)
Executable
+51
View File
@@ -0,0 +1,51 @@
#!/bin/sh
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
if [ "$OS" = "freebsd" ]; then
MK_FILE="bmake.mk"
else
MK_FILE="gmake.mk"
fi
if grep -q "Raspberry Pi 5" /proc/device-tree/model 2>/dev/null; then
GL_MAJOR=3
GL_MINOR=1
else
GL_MAJOR=3
GL_MINOR=3
fi
HAS_INSTALL=0
HAS_UNINSTALL=0
for arg in "$@"; do
case "$arg" in
install) HAS_INSTALL=1 ;;
uninstall) HAS_UNINSTALL=1 ;;
esac
done
if [ "$HAS_INSTALL" = "1" ] || [ "$HAS_UNINSTALL" = "1" ]; then
if [ "$HAS_INSTALL" = "1" ]; then
make -f "$MK_FILE" release GL_MAJOR=$GL_MAJOR GL_MINOR=$GL_MINOR
fi
if [ "$(id -u)" = "0" ]; then
PRIV=""
elif command -v doas > /dev/null 2>&1; then
PRIV="doas"
elif command -v sudo > /dev/null 2>&1; then
PRIV="sudo"
else
echo "error: install requires root. neither doas nor sudo found." >&2
exit 1
fi
$PRIV make -f "$MK_FILE" "$@" GL_MAJOR=$GL_MAJOR GL_MINOR=$GL_MINOR
elif [ "$1" = "run" ]; then
make -f "$MK_FILE" run GL_MAJOR=$GL_MAJOR GL_MINOR=$GL_MINOR
elif [ "$1" = "run_gl" ]; then
make -f "$MK_FILE" run_gl GL_MAJOR=$GL_MAJOR GL_MINOR=$GL_MINOR
else
make -f "$MK_FILE" "$@" GL_MAJOR=$GL_MAJOR GL_MINOR=$GL_MINOR
fi
+6
View File
@@ -0,0 +1,6 @@
-std=c99
-Wall
-Wpedantic
-Iinclude
-I/usr/local/include
-I/usr/include
+13
View File
@@ -0,0 +1,13 @@
SRC_DIR = src
INC_DIR = include
OBJ_DIR = obj
BIN_DIR = bin
GL_MAJOR ?= 3
GL_MINOR ?= 3
ENGINE_SRCS = \
src/skele.c \
$(CLOCK_SRC)
DEBUG_FLAGS ?=
+82
View File
@@ -0,0 +1,82 @@
#include "client/blit.h"
#include "client/input.h"
#include "client/video.h"
#include "clock.h"
#include "skele.h"
#include <stdlib.h>
#include <stk/stk.h>
#include <string.h>
static uint8_t running = 1;
static void on_signal(void) { running = 0; }
int main(int argc, char *argv[])
{
skele_video_config_t video_cfg;
uint64_t last, now, elapsed;
uint8_t *pixels;
uint32_t total;
(void)argc;
(void)argv;
skele_clock_init(on_signal);
if (skele_stk_setup() != SKELE_INIT_SUCCESS)
return 1;
if (skele_init() != SKELE_INIT_SUCCESS) {
skele_stk_teardown();
return 1;
}
video_cfg.render_width = SKELE_DEFAULT_RENDER_WIDTH;
video_cfg.render_height = SKELE_DEFAULT_RENDER_HEIGHT;
video_cfg.window_width = 0;
video_cfg.window_height = 0;
video_cfg.flags = 0;
if (skele_video_init(video_cfg) != SKELE_INIT_SUCCESS) {
skele_stk_teardown();
skele_shutdown();
return 1;
}
total = (uint32_t)(video_cfg.render_width * video_cfg.render_height);
pixels = malloc(total);
if (!pixels) {
skele_video_shutdown();
skele_stk_teardown();
skele_shutdown();
return 1;
}
memset(pixels, 0, total);
last = skele_time_ns();
while (running) {
if (!skele_input_poll())
break;
stk_poll();
now = skele_time_ns();
elapsed = now - last;
if (elapsed >= skele_tick_ns) {
skele_tick();
last = now;
}
skele_video_blit(pixels);
skele_video_present();
}
free(pixels);
skele_video_shutdown();
skele_stk_teardown();
skele_shutdown();
return 0;
}
+68
View File
@@ -0,0 +1,68 @@
#include "client/input.h"
#include "client/video.h"
#include "clock.h"
#include "skele.h"
#include <SDL3/SDL.h>
#include <SDL3/SDL_opengl.h>
#include <stk/stk.h>
static uint8_t running = 1;
static void on_signal(void) { running = 0; }
int main(int argc, char *argv[])
{
skele_video_config_t video_cfg;
uint64_t last;
uint64_t now;
uint64_t elapsed;
skele_clock_init(on_signal);
if (skele_stk_setup() != SKELE_INIT_SUCCESS)
return 1;
if (skele_init() != SKELE_INIT_SUCCESS) {
skele_stk_teardown();
return 1;
}
video_cfg.render_width = SKELE_DEFAULT_RENDER_WIDTH;
video_cfg.render_height = SKELE_DEFAULT_RENDER_HEIGHT;
video_cfg.window_width = 0;
video_cfg.window_height = 0;
video_cfg.flags = 0;
if (skele_video_init(video_cfg) != SKELE_INIT_SUCCESS) {
skele_stk_teardown();
skele_shutdown();
return 1;
}
last = skele_time_ns();
while (running) {
if (!skele_input_poll())
break;
stk_poll();
now = skele_time_ns();
elapsed = now - last;
if (elapsed >= skele_tick_ns) {
skele_tick();
last = now;
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
skele_video_present();
}
skele_video_shutdown();
skele_stk_teardown();
skele_shutdown();
return 0;
}
+38
View File
@@ -0,0 +1,38 @@
#include "clock.h"
#include "skele.h"
#include <stk/stk.h>
static uint8_t running = 1;
static void on_signal(void) { running = 0; }
int main(int argc, char *argv[])
{
uint64_t tick_start;
uint64_t elapsed;
skele_clock_init(on_signal);
if (skele_stk_setup() != SKELE_INIT_SUCCESS)
return 1;
if (skele_init() != SKELE_INIT_SUCCESS) {
skele_stk_teardown();
return 1;
}
while (running) {
tick_start = skele_time_ns();
stk_poll();
skele_tick();
elapsed = skele_time_ns() - tick_start;
if (elapsed < skele_tick_ns)
skele_sleep_ns(skele_tick_ns - elapsed);
}
skele_stk_teardown();
skele_shutdown();
return 0;
}
+222
View File
@@ -0,0 +1,222 @@
ifeq ($(OS),Windows_NT)
CLOCK_SRC := src/platform/clock/win32.c
INPUT_SRC := src/platform/client/input/sdl.c
else
CLOCK_SRC := src/platform/clock/posix.c
INPUT_SRC := src/platform/client/input/sdl.c
endif
include config.mk
ENGINE_SRCS := src/skele.c $(CLOCK_SRC)
SOFT_PLAT_SRCS := src/platform/client/video/sdl.c $(INPUT_SRC)
GL_PLAT_SRCS := src/platform/client/video/gl.c $(INPUT_SRC)
SOFT_CLIENT_SRCS := example/client/main.c
GL_CLIENT_SRCS := example/gl_client/main.c
SERVER_EXAMPLE := example/server/main.c
LIBSKELE_SRCS := $(ENGINE_SRCS) $(SOFT_PLAT_SRCS)
LIBGLSKELE_SRCS := $(ENGINE_SRCS) $(GL_PLAT_SRCS)
LIBSKELE_SRV_SRCS := $(ENGINE_SRCS)
ifeq ($(OS),Windows_NT)
SHELL := cmd.exe
LIBSKELE := $(BIN_DIR)/debug/libskele.a
LIBGLSKELE := $(BIN_DIR)/debug/libglskele.a
LIBSKELE_SRV := $(BIN_DIR)/debug/libskeleserver.a
SKELE_BIN := $(BIN_DIR)/debug/skele_client.exe
GLSKELE_BIN := $(BIN_DIR)/debug/glskele_client.exe
SERVER_BIN := $(BIN_DIR)/debug/skele_server.exe
LIBSKELE_R := $(BIN_DIR)/release/libskele.a
LIBGLSKELE_R := $(BIN_DIR)/release/libglskele.a
LIBSKELE_SRV_R := $(BIN_DIR)/release/libskeleserver.a
SKELE_BIN_R := $(BIN_DIR)/release/skele_client.exe
GLSKELE_BIN_R := $(BIN_DIR)/release/glskele_client.exe
SERVER_BIN_R := $(BIN_DIR)/release/skele_server.exe
LDFLAGS_PLAT :=
CFLAGS_PLAT :=
MKDIR = if not exist $(subst /,\,$(1)) mkdir $(subst /,\,$(1))
RMDIR = if exist $(subst /,\,$(1)) rd /s /q $(subst /,\,$(1))
else
LIBSKELE := $(BIN_DIR)/debug/libskele.a
LIBGLSKELE := $(BIN_DIR)/debug/libglskele.a
LIBSKELE_SRV := $(BIN_DIR)/debug/libskeleserver.a
SKELE_BIN := $(BIN_DIR)/debug/skele_client
GLSKELE_BIN := $(BIN_DIR)/debug/glskele_client
SERVER_BIN := $(BIN_DIR)/debug/skele_server
LIBSKELE_R := $(BIN_DIR)/release/libskele.a
LIBGLSKELE_R := $(BIN_DIR)/release/libglskele.a
LIBSKELE_SRV_R := $(BIN_DIR)/release/libskeleserver.a
SKELE_BIN_R := $(BIN_DIR)/release/skele_client
GLSKELE_BIN_R := $(BIN_DIR)/release/glskele_client
SERVER_BIN_R := $(BIN_DIR)/release/skele_server
LDFLAGS_PLAT :=
CFLAGS_PLAT :=
MKDIR = mkdir -p $(1)
RMDIR = rm -rf $(1)
endif
ifeq ($(OS),Windows_NT)
GL_LIB := -lopengl32
LDFLAGS_PLAT :=
CFLAGS_PLAT :=
else ifeq ($(shell uname),FreeBSD)
GL_LIB := -lGL
LDFLAGS_PLAT := -L/usr/local/lib
CFLAGS_PLAT := -I/usr/local/include
else
GL_LIB := -lGL
LDFLAGS_PLAT :=
CFLAGS_PLAT :=
endif
LINK_STK := -Wl,-Bstatic -lstk -Wl,-Bdynamic
RELEASE_LDFLAGS := -s
CFLAGS_BASE := -Wall -Wpedantic -I$(INC_DIR) -std=c99 $(CFLAGS_PLAT) $(DEBUG_FLAGS) \
-DGL_MAJOR=$(GL_MAJOR) -DGL_MINOR=$(GL_MINOR)
LIBSKELE_DEBUG_OBJS := $(LIBSKELE_SRCS:%.c=obj/debug/soft/%.o)
LIBGLSKELE_DEBUG_OBJS := $(LIBGLSKELE_SRCS:%.c=obj/debug/gl/%.o)
LIBSKELE_SRV_DEBUG_OBJS := $(LIBSKELE_SRV_SRCS:%.c=obj/debug/server/%.o)
SOFT_CLIENT_DEBUG_OBJS := $(SOFT_CLIENT_SRCS:%.c=obj/debug/soft/%.o)
GL_CLIENT_DEBUG_OBJS := $(GL_CLIENT_SRCS:%.c=obj/debug/gl/%.o)
SERVER_DEBUG_OBJS := $(SERVER_EXAMPLE:%.c=obj/debug/server/%.o)
LIBSKELE_RELEASE_OBJS := $(LIBSKELE_SRCS:%.c=obj/release/soft/%.o)
LIBGLSKELE_RELEASE_OBJS := $(LIBGLSKELE_SRCS:%.c=obj/release/gl/%.o)
LIBSKELE_SRV_RELEASE_OBJS := $(LIBSKELE_SRV_SRCS:%.c=obj/release/server/%.o)
SOFT_CLIENT_RELEASE_OBJS := $(SOFT_CLIENT_SRCS:%.c=obj/release/soft/%.o)
GL_CLIENT_RELEASE_OBJS := $(GL_CLIENT_SRCS:%.c=obj/release/gl/%.o)
SERVER_RELEASE_OBJS := $(SERVER_EXAMPLE:%.c=obj/release/server/%.o)
PREFIX ?= /usr
MODE ?= debug
.PHONY: all debug release skele glskele server libs \
install uninstall clean run run_gl
all: debug
debug: \
$(LIBSKELE) \
$(LIBGLSKELE) \
$(LIBSKELE_SRV) \
$(SKELE_BIN) \
$(GLSKELE_BIN) \
$(SERVER_BIN)
release: \
$(LIBSKELE_R) \
$(LIBGLSKELE_R) \
$(LIBSKELE_SRV_R) \
$(SKELE_BIN_R) \
$(GLSKELE_BIN_R) \
$(SERVER_BIN_R)
libs: $(LIBSKELE) $(LIBGLSKELE) $(LIBSKELE_SRV)
skele: $(LIBSKELE) $(SKELE_BIN)
glskele: $(LIBGLSKELE) $(GLSKELE_BIN)
server: $(LIBSKELE_SRV) $(SERVER_BIN)
run: skele
$(SKELE_BIN)
run_gl: glskele
$(GLSKELE_BIN)
$(LIBSKELE): $(LIBSKELE_DEBUG_OBJS)
@$(call MKDIR,$(@D))
$(AR) rcs $@ $^
$(LIBGLSKELE): $(LIBGLSKELE_DEBUG_OBJS)
@$(call MKDIR,$(@D))
$(AR) rcs $@ $^
$(LIBSKELE_SRV): $(LIBSKELE_SRV_DEBUG_OBJS)
@$(call MKDIR,$(@D))
$(AR) rcs $@ $^
$(LIBSKELE_R): $(LIBSKELE_RELEASE_OBJS)
@$(call MKDIR,$(@D))
$(AR) rcs $@ $^
$(LIBGLSKELE_R): $(LIBGLSKELE_RELEASE_OBJS)
@$(call MKDIR,$(@D))
$(AR) rcs $@ $^
$(LIBSKELE_SRV_R): $(LIBSKELE_SRV_RELEASE_OBJS)
@$(call MKDIR,$(@D))
$(AR) rcs $@ $^
$(SKELE_BIN): $(SOFT_CLIENT_DEBUG_OBJS) $(LIBSKELE)
@$(call MKDIR,$(@D))
$(CC) -o $@ $(SOFT_CLIENT_DEBUG_OBJS) -L$(BIN_DIR)/debug -lskele $(LINK_STK) -lSDL3 $(LDFLAGS_PLAT)
$(GLSKELE_BIN): $(GL_CLIENT_DEBUG_OBJS) $(LIBGLSKELE)
@$(call MKDIR,$(@D))
$(CC) -o $@ $(GL_CLIENT_DEBUG_OBJS) -L$(BIN_DIR)/debug -lglskele $(LINK_STK) -lSDL3 $(GL_LIB) $(LDFLAGS_PLAT)
$(SERVER_BIN): $(SERVER_DEBUG_OBJS) $(LIBSKELE_SRV)
@$(call MKDIR,$(@D))
$(CC) -o $@ $(SERVER_DEBUG_OBJS) -L$(BIN_DIR)/debug -lskeleserver $(LINK_STK) $(LDFLAGS_PLAT)
$(SKELE_BIN_R): $(SOFT_CLIENT_RELEASE_OBJS) $(LIBSKELE_R)
@$(call MKDIR,$(@D))
$(CC) $(RELEASE_LDFLAGS) -o $@ $(SOFT_CLIENT_RELEASE_OBJS) -L$(BIN_DIR)/release -lskele $(LINK_STK) -lSDL3 $(LDFLAGS_PLAT)
$(GLSKELE_BIN_R): $(GL_CLIENT_RELEASE_OBJS) $(LIBGLSKELE_R)
@$(call MKDIR,$(@D))
$(CC) $(RELEASE_LDFLAGS) -o $@ $(GL_CLIENT_RELEASE_OBJS) -L$(BIN_DIR)/release -lglskele $(LINK_STK) -lSDL3 $(GL_LIB) $(LDFLAGS_PLAT)
$(SERVER_BIN_R): $(SERVER_RELEASE_OBJS) $(LIBSKELE_SRV_R)
@$(call MKDIR,$(@D))
$(CC) $(RELEASE_LDFLAGS) -o $@ $(SERVER_RELEASE_OBJS) -L$(BIN_DIR)/release -lskeleserver $(LINK_STK) $(LDFLAGS_PLAT)
obj/debug/soft/%.o: %.c
@$(call MKDIR,$(@D))
$(CC) $(CFLAGS_BASE) -g -O0 -MMD -MP -c $< -o $@
obj/debug/gl/%.o: %.c
@$(call MKDIR,$(@D))
$(CC) $(CFLAGS_BASE) -g -O0 -MMD -MP -c $< -o $@
obj/debug/server/%.o: %.c
@$(call MKDIR,$(@D))
$(CC) $(CFLAGS_BASE) -g -O0 -MMD -MP -c $< -o $@
obj/release/soft/%.o: %.c
@$(call MKDIR,$(@D))
$(CC) $(CFLAGS_BASE) -O2 -MMD -MP -c $< -o $@
obj/release/gl/%.o: %.c
@$(call MKDIR,$(@D))
$(CC) $(CFLAGS_BASE) -O2 -MMD -MP -c $< -o $@
obj/release/server/%.o: %.c
@$(call MKDIR,$(@D))
$(CC) $(CFLAGS_BASE) -O2 -MMD -MP -c $< -o $@
-include $(wildcard obj/debug/soft/*.d)
-include $(wildcard obj/debug/gl/*.d)
-include $(wildcard obj/debug/server/*.d)
-include $(wildcard obj/release/soft/*.d)
-include $(wildcard obj/release/gl/*.d)
-include $(wildcard obj/release/server/*.d)
install: release
install -d $(PREFIX)/lib
install -d $(PREFIX)/include/skele
install -m 644 $(LIBSKELE_R) $(PREFIX)/lib/libskele.a
install -m 644 $(LIBGLSKELE_R) $(PREFIX)/lib/libglskele.a
install -m 644 $(LIBSKELE_SRV_R) $(PREFIX)/lib/libskeleserver.a
cp -r include/* $(PREFIX)/include/skele/
install -d $(PREFIX)/bin
uninstall:
rm -f $(PREFIX)/lib/libskele.a
rm -f $(PREFIX)/lib/libglskele.a
rm -f $(PREFIX)/lib/libskeleserver.a
rm -rf $(PREFIX)/include/skele
clean:
@$(call RMDIR,$(OBJ_DIR))
@$(call RMDIR,$(BIN_DIR))
+16
View File
@@ -0,0 +1,16 @@
#ifndef SKELE_BLIT_H
#define SKELE_BLIT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void skele_video_blit(uint8_t *pixels);
#ifdef __cplusplus
}
#endif
#endif /* SKELE_BLIT_H */
+132
View File
@@ -0,0 +1,132 @@
#ifndef SKELE_INPUT_H
#define SKELE_INPUT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
SKELE_KEY_UNKNOWN = 0,
SKELE_KEY_A,
SKELE_KEY_B,
SKELE_KEY_C,
SKELE_KEY_D,
SKELE_KEY_E,
SKELE_KEY_F,
SKELE_KEY_G,
SKELE_KEY_H,
SKELE_KEY_I,
SKELE_KEY_J,
SKELE_KEY_K,
SKELE_KEY_L,
SKELE_KEY_M,
SKELE_KEY_N,
SKELE_KEY_O,
SKELE_KEY_P,
SKELE_KEY_Q,
SKELE_KEY_R,
SKELE_KEY_S,
SKELE_KEY_T,
SKELE_KEY_U,
SKELE_KEY_V,
SKELE_KEY_W,
SKELE_KEY_X,
SKELE_KEY_Y,
SKELE_KEY_Z,
SKELE_KEY_0,
SKELE_KEY_1,
SKELE_KEY_2,
SKELE_KEY_3,
SKELE_KEY_4,
SKELE_KEY_5,
SKELE_KEY_6,
SKELE_KEY_7,
SKELE_KEY_8,
SKELE_KEY_9,
SKELE_KEY_F1,
SKELE_KEY_F2,
SKELE_KEY_F3,
SKELE_KEY_F4,
SKELE_KEY_F5,
SKELE_KEY_F6,
SKELE_KEY_F7,
SKELE_KEY_F8,
SKELE_KEY_F9,
SKELE_KEY_F10,
SKELE_KEY_F11,
SKELE_KEY_F12,
SKELE_KEY_SPACE,
SKELE_KEY_ENTER,
SKELE_KEY_ESCAPE,
SKELE_KEY_TAB,
SKELE_KEY_BACKSPACE,
SKELE_KEY_LSHIFT,
SKELE_KEY_RSHIFT,
SKELE_KEY_LCTRL,
SKELE_KEY_RCTRL,
SKELE_KEY_LALT,
SKELE_KEY_RALT,
SKELE_KEY_UP,
SKELE_KEY_DOWN,
SKELE_KEY_LEFT,
SKELE_KEY_RIGHT,
SKELE_KEY_COUNT
} skele_key_t;
typedef enum {
SKELE_PAD_A,
SKELE_PAD_B,
SKELE_PAD_X,
SKELE_PAD_Y,
SKELE_PAD_LB,
SKELE_PAD_RB,
SKELE_PAD_LT,
SKELE_PAD_RT,
SKELE_PAD_LSTICK,
SKELE_PAD_RSTICK,
SKELE_PAD_START,
SKELE_PAD_BACK,
SKELE_PAD_DPAD_UP,
SKELE_PAD_DPAD_DOWN,
SKELE_PAD_DPAD_LEFT,
SKELE_PAD_DPAD_RIGHT,
SKELE_PAD_BUTTON_COUNT
} skele_pad_button_t;
typedef enum {
SKELE_PAD_AXIS_LX,
SKELE_PAD_AXIS_LY,
SKELE_PAD_AXIS_RX,
SKELE_PAD_AXIS_RY,
SKELE_PAD_AXIS_LT,
SKELE_PAD_AXIS_RT,
SKELE_PAD_AXIS_COUNT
} skele_pad_axis_t;
#define SKELE_MAX_PADS 4
uint8_t skele_input_poll(void);
uint8_t skele_key_down(skele_key_t key);
uint8_t skele_key_held(skele_key_t key);
uint8_t skele_pad_connected(uint8_t pad);
uint8_t skele_pad_button_down(uint8_t pad, skele_pad_button_t btn);
uint8_t skele_pad_button_held(uint8_t pad, skele_pad_button_t btn);
float skele_pad_axis(uint8_t pad, skele_pad_axis_t axis);
void skele_mouse_delta(int32_t *dx, int32_t *dy);
#ifdef __cplusplus
}
#endif
#endif /* SKELE_INPUT_H */
+21
View File
@@ -0,0 +1,21 @@
#ifndef SKELE_PALETTE_H
#define SKELE_PALETTE_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SKELE_PALETTE_COLORS 256
typedef uint32_t skele_palette_t[SKELE_PALETTE_COLORS];
void skele_palette_set(skele_palette_t pal);
void skele_palette_set_index(uint8_t index, uint32_t color);
#ifdef __cplusplus
}
#endif
#endif /* SKELE_PALETTE_H */
+38
View File
@@ -0,0 +1,38 @@
#ifndef SKELE_VIDEO_H
#define SKELE_VIDEO_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SKELE_VIDEO_FULLSCREEN 0x01
#define SKELE_VIDEO_BORDERLESS 0x02
#define SKELE_VIDEO_RESIZABLE 0x04
#define SKELE_VIDEO_HIGHDPI 0x08
#define SKELE_DEFAULT_RENDER_WIDTH 320
#define SKELE_DEFAULT_RENDER_HEIGHT 200
typedef struct {
uint16_t render_width;
uint16_t render_height;
uint16_t window_width;
uint16_t window_height;
uint8_t flags;
} skele_video_config_t;
uint8_t skele_video_init(skele_video_config_t cfg);
void skele_video_shutdown(void);
void skele_video_present(void);
void skele_video_set_title(const char *title);
void skele_video_toggle_fullscreen(void);
void skele_video_cycle_scale(void);
void skele_video_set_mouse_grab(uint8_t grab);
#ifdef __cplusplus
}
#endif
#endif /* SKELE_VIDEO_H */
+18
View File
@@ -0,0 +1,18 @@
#ifndef SKELE_CLOCK_H
#define SKELE_CLOCK_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void skele_clock_init(void (*on_signal)(void));
uint64_t skele_time_ns(void);
void skele_sleep_ns(uint64_t ns);
#ifdef __cplusplus
}
#endif
#endif /* SKELE_CLOCK_H */
+39
View File
@@ -0,0 +1,39 @@
#ifndef SKELE_H
#define SKELE_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SKELE_VERSION_MAJOR 0
#define SKELE_VERSION_MINOR 0
#define SKELE_VERSION_PATCH 0
#define SKELE_STR(x) #x
#define SKELE_XSTR(x) SKELE_STR(x)
#define SKELE_VERSION \
SKELE_XSTR(SKELE_VERSION_MAJOR) \
"." SKELE_XSTR(SKELE_VERSION_MINOR) "." SKELE_XSTR(SKELE_VERSION_PATCH)
#define SKELE_INIT_SUCCESS 1
#define SKELE_INIT_FAILURE 0
#define SKELE_DEFAULT_TICK_RATE 35
extern uint64_t skele_tick_ns;
void skele_set_tick_rate(uint8_t rate);
uint8_t skele_init(void);
void skele_shutdown(void);
void skele_tick(void);
uint8_t skele_stk_setup(void);
void skele_stk_teardown(void);
#ifdef __cplusplus
}
#endif
#endif /* SKELE_H */
+366
View File
@@ -0,0 +1,366 @@
#include "client/input.h"
#include "client/video.h"
#include <SDL3/SDL.h>
#include <string.h>
static uint8_t key_held[SKELE_KEY_COUNT];
static uint8_t key_down[SKELE_KEY_COUNT];
static SDL_Gamepad *pads[SKELE_MAX_PADS];
static uint8_t pad_btn_held[SKELE_MAX_PADS][SKELE_PAD_BUTTON_COUNT];
static uint8_t pad_btn_down[SKELE_MAX_PADS][SKELE_PAD_BUTTON_COUNT];
static float pad_axes[SKELE_MAX_PADS][SKELE_PAD_AXIS_COUNT];
static int32_t mouse_dx = 0;
static int32_t mouse_dy = 0;
static skele_key_t scancode_to_key(SDL_Scancode sc)
{
switch (sc) {
case SDL_SCANCODE_A:
return SKELE_KEY_A;
case SDL_SCANCODE_B:
return SKELE_KEY_B;
case SDL_SCANCODE_C:
return SKELE_KEY_C;
case SDL_SCANCODE_D:
return SKELE_KEY_D;
case SDL_SCANCODE_E:
return SKELE_KEY_E;
case SDL_SCANCODE_F:
return SKELE_KEY_F;
case SDL_SCANCODE_G:
return SKELE_KEY_G;
case SDL_SCANCODE_H:
return SKELE_KEY_H;
case SDL_SCANCODE_I:
return SKELE_KEY_I;
case SDL_SCANCODE_J:
return SKELE_KEY_J;
case SDL_SCANCODE_K:
return SKELE_KEY_K;
case SDL_SCANCODE_L:
return SKELE_KEY_L;
case SDL_SCANCODE_M:
return SKELE_KEY_M;
case SDL_SCANCODE_N:
return SKELE_KEY_N;
case SDL_SCANCODE_O:
return SKELE_KEY_O;
case SDL_SCANCODE_P:
return SKELE_KEY_P;
case SDL_SCANCODE_Q:
return SKELE_KEY_Q;
case SDL_SCANCODE_R:
return SKELE_KEY_R;
case SDL_SCANCODE_S:
return SKELE_KEY_S;
case SDL_SCANCODE_T:
return SKELE_KEY_T;
case SDL_SCANCODE_U:
return SKELE_KEY_U;
case SDL_SCANCODE_V:
return SKELE_KEY_V;
case SDL_SCANCODE_W:
return SKELE_KEY_W;
case SDL_SCANCODE_X:
return SKELE_KEY_X;
case SDL_SCANCODE_Y:
return SKELE_KEY_Y;
case SDL_SCANCODE_Z:
return SKELE_KEY_Z;
case SDL_SCANCODE_0:
return SKELE_KEY_0;
case SDL_SCANCODE_1:
return SKELE_KEY_1;
case SDL_SCANCODE_2:
return SKELE_KEY_2;
case SDL_SCANCODE_3:
return SKELE_KEY_3;
case SDL_SCANCODE_4:
return SKELE_KEY_4;
case SDL_SCANCODE_5:
return SKELE_KEY_5;
case SDL_SCANCODE_6:
return SKELE_KEY_6;
case SDL_SCANCODE_7:
return SKELE_KEY_7;
case SDL_SCANCODE_8:
return SKELE_KEY_8;
case SDL_SCANCODE_9:
return SKELE_KEY_9;
case SDL_SCANCODE_F1:
return SKELE_KEY_F1;
case SDL_SCANCODE_F2:
return SKELE_KEY_F2;
case SDL_SCANCODE_F3:
return SKELE_KEY_F3;
case SDL_SCANCODE_F4:
return SKELE_KEY_F4;
case SDL_SCANCODE_F5:
return SKELE_KEY_F5;
case SDL_SCANCODE_F6:
return SKELE_KEY_F6;
case SDL_SCANCODE_F7:
return SKELE_KEY_F7;
case SDL_SCANCODE_F8:
return SKELE_KEY_F8;
case SDL_SCANCODE_F9:
return SKELE_KEY_F9;
case SDL_SCANCODE_F10:
return SKELE_KEY_F10;
case SDL_SCANCODE_F11:
return SKELE_KEY_F11;
case SDL_SCANCODE_F12:
return SKELE_KEY_F12;
case SDL_SCANCODE_SPACE:
return SKELE_KEY_SPACE;
case SDL_SCANCODE_RETURN:
return SKELE_KEY_ENTER;
case SDL_SCANCODE_ESCAPE:
return SKELE_KEY_ESCAPE;
case SDL_SCANCODE_TAB:
return SKELE_KEY_TAB;
case SDL_SCANCODE_BACKSPACE:
return SKELE_KEY_BACKSPACE;
case SDL_SCANCODE_LSHIFT:
return SKELE_KEY_LSHIFT;
case SDL_SCANCODE_RSHIFT:
return SKELE_KEY_RSHIFT;
case SDL_SCANCODE_LCTRL:
return SKELE_KEY_LCTRL;
case SDL_SCANCODE_RCTRL:
return SKELE_KEY_RCTRL;
case SDL_SCANCODE_LALT:
return SKELE_KEY_LALT;
case SDL_SCANCODE_RALT:
return SKELE_KEY_RALT;
case SDL_SCANCODE_UP:
return SKELE_KEY_UP;
case SDL_SCANCODE_DOWN:
return SKELE_KEY_DOWN;
case SDL_SCANCODE_LEFT:
return SKELE_KEY_LEFT;
case SDL_SCANCODE_RIGHT:
return SKELE_KEY_RIGHT;
default:
return SKELE_KEY_UNKNOWN;
}
}
static skele_pad_button_t sdl_btn_to_pad(SDL_GamepadButton btn)
{
switch (btn) {
case SDL_GAMEPAD_BUTTON_SOUTH:
return SKELE_PAD_A;
case SDL_GAMEPAD_BUTTON_EAST:
return SKELE_PAD_B;
case SDL_GAMEPAD_BUTTON_WEST:
return SKELE_PAD_X;
case SDL_GAMEPAD_BUTTON_NORTH:
return SKELE_PAD_Y;
case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER:
return SKELE_PAD_LB;
case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER:
return SKELE_PAD_RB;
case SDL_GAMEPAD_BUTTON_LEFT_STICK:
return SKELE_PAD_LSTICK;
case SDL_GAMEPAD_BUTTON_RIGHT_STICK:
return SKELE_PAD_RSTICK;
case SDL_GAMEPAD_BUTTON_START:
return SKELE_PAD_START;
case SDL_GAMEPAD_BUTTON_BACK:
return SKELE_PAD_BACK;
case SDL_GAMEPAD_BUTTON_DPAD_UP:
return SKELE_PAD_DPAD_UP;
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
return SKELE_PAD_DPAD_DOWN;
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
return SKELE_PAD_DPAD_LEFT;
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
return SKELE_PAD_DPAD_RIGHT;
default:
return SKELE_PAD_BUTTON_COUNT;
}
}
static int8_t pad_slot(SDL_JoystickID id)
{
uint8_t i;
for (i = 0; i < SKELE_MAX_PADS; i++)
if (pads[i] && SDL_GetGamepadID(pads[i]) == id)
return (int8_t)i;
return -1;
}
static int8_t free_slot(void)
{
uint8_t i;
for (i = 0; i < SKELE_MAX_PADS; i++)
if (!pads[i])
return (int8_t)i;
return -1;
}
static void update_axes(uint8_t slot)
{
pad_axes[slot][SKELE_PAD_AXIS_LX] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_LEFTX) / 32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_LY] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_LEFTY) / 32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_RX] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_RIGHTX) / 32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_RY] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_RIGHTY) / 32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_LT] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_LEFT_TRIGGER) /
32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_RT] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) /
32767.0f;
}
uint8_t skele_input_poll(void)
{
SDL_Event e;
skele_key_t key;
int8_t slot;
uint8_t i;
skele_pad_button_t btn;
memset(key_down, 0, sizeof(key_down));
memset(pad_btn_down, 0, sizeof(pad_btn_down));
mouse_dx = 0;
mouse_dy = 0;
while (SDL_PollEvent(&e)) {
switch (e.type) {
case SDL_EVENT_QUIT:
return 0;
case SDL_EVENT_MOUSE_MOTION:
mouse_dx += (int32_t)e.motion.xrel;
mouse_dy += (int32_t)e.motion.yrel;
break;
case SDL_EVENT_KEY_DOWN:
if (e.key.repeat)
break;
switch (e.key.scancode) {
case SDL_SCANCODE_F11:
skele_video_toggle_fullscreen();
break;
case SDL_SCANCODE_F4:
skele_video_cycle_scale();
break;
default:
key = scancode_to_key(e.key.scancode);
if (key != SKELE_KEY_UNKNOWN) {
key_down[key] = 1;
key_held[key] = 1;
}
break;
}
break;
case SDL_EVENT_KEY_UP:
key = scancode_to_key(e.key.scancode);
if (key != SKELE_KEY_UNKNOWN)
key_held[key] = 0;
break;
case SDL_EVENT_GAMEPAD_ADDED:
slot = free_slot();
if (slot >= 0) {
pads[slot] = SDL_OpenGamepad(e.gdevice.which);
if (pads[slot])
memset(pad_btn_held[slot], 0,
sizeof(pad_btn_held[slot]));
}
break;
case SDL_EVENT_GAMEPAD_REMOVED:
slot = pad_slot(e.gdevice.which);
if (slot >= 0) {
SDL_CloseGamepad(pads[slot]);
pads[slot] = NULL;
memset(pad_btn_held[slot], 0,
sizeof(pad_btn_held[slot]));
memset(pad_axes[slot], 0,
sizeof(pad_axes[slot]));
}
break;
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
slot = pad_slot(e.gbutton.which);
btn =
sdl_btn_to_pad((SDL_GamepadButton)e.gbutton.button);
if (slot >= 0 && btn != SKELE_PAD_BUTTON_COUNT) {
pad_btn_down[slot][btn] = 1;
pad_btn_held[slot][btn] = 1;
}
break;
case SDL_EVENT_GAMEPAD_BUTTON_UP:
slot = pad_slot(e.gbutton.which);
btn =
sdl_btn_to_pad((SDL_GamepadButton)e.gbutton.button);
if (slot >= 0 && btn != SKELE_PAD_BUTTON_COUNT)
pad_btn_held[slot][btn] = 0;
break;
default:
break;
}
}
for (i = 0; i < SKELE_MAX_PADS; i++)
if (pads[i])
update_axes(i);
return 1;
}
uint8_t skele_key_down(skele_key_t key)
{
return key < SKELE_KEY_COUNT ? key_down[key] : 0;
}
uint8_t skele_key_held(skele_key_t key)
{
return key < SKELE_KEY_COUNT ? key_held[key] : 0;
}
uint8_t skele_pad_connected(uint8_t pad)
{
return pad < SKELE_MAX_PADS ? pads[pad] != NULL : 0;
}
uint8_t skele_pad_button_down(uint8_t pad, skele_pad_button_t btn)
{
return (pad < SKELE_MAX_PADS && btn < SKELE_PAD_BUTTON_COUNT)
? pad_btn_down[pad][btn]
: 0;
}
uint8_t skele_pad_button_held(uint8_t pad, skele_pad_button_t btn)
{
return (pad < SKELE_MAX_PADS && btn < SKELE_PAD_BUTTON_COUNT)
? pad_btn_held[pad][btn]
: 0;
}
float skele_pad_axis(uint8_t pad, skele_pad_axis_t axis)
{
return (pad < SKELE_MAX_PADS && axis < SKELE_PAD_AXIS_COUNT)
? pad_axes[pad][axis]
: 0.0f;
}
void skele_mouse_delta(int32_t *dx, int32_t *dy)
{
if (dx)
*dx = mouse_dx;
if (dy)
*dy = mouse_dy;
}
+179
View File
@@ -0,0 +1,179 @@
#include "client/video.h"
#include "skele.h"
#include <SDL3/SDL.h>
#include <stk/stk_log.h>
static SDL_Window *window = NULL;
static SDL_GLContext gl_ctx = NULL;
static uint16_t vid_w = 0;
static uint16_t vid_h = 0;
static uint8_t cur_scale = 1;
static uint8_t fullscreen = 0;
static uint8_t max_scale(uint16_t rw, uint16_t rh)
{
SDL_DisplayID display;
const SDL_DisplayMode *mode;
uint16_t aw, ah;
uint8_t scale;
display =
window ? SDL_GetDisplayForWindow(window) : SDL_GetPrimaryDisplay();
mode = SDL_GetCurrentDisplayMode(display);
if (!mode)
return 1;
aw = (uint16_t)((mode->w * 3) / 4);
ah = (uint16_t)((mode->h * 3) / 4);
scale = 1;
while ((rw * (scale + 1)) <= aw && (rh * (scale + 1)) <= ah)
scale++;
return scale;
}
static void set_scale(uint8_t scale)
{
SDL_DisplayID display;
cur_scale = scale;
display = SDL_GetDisplayForWindow(window);
SDL_SetWindowSize(window, (int)(vid_w * scale), (int)(vid_h * scale));
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
}
static void toggle_fullscreen(void)
{
fullscreen = !fullscreen;
SDL_SetWindowFullscreen(window, fullscreen);
}
static void cycle_scale(void)
{
uint8_t next;
if (fullscreen)
return;
next = cur_scale + 1;
if (next > max_scale(vid_w, vid_h))
next = 1;
set_scale(next);
}
uint8_t skele_video_init(skele_video_config_t cfg)
{
SDL_DisplayID display;
SDL_WindowFlags flags = 0;
const SDL_DisplayMode *mode;
uint16_t window_w, window_h, aw, ah;
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) {
stk_log(STK_LOG_ERROR, "video: SDL_Init failed: %s",
SDL_GetError());
return SKELE_INIT_FAILURE;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, GL_MAJOR);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, GL_MINOR);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
flags |= SDL_WINDOW_OPENGL;
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
flags |= SDL_WINDOW_FULLSCREEN;
if (cfg.flags & SKELE_VIDEO_BORDERLESS)
flags |= SDL_WINDOW_BORDERLESS;
if (cfg.flags & SKELE_VIDEO_RESIZABLE)
flags |= SDL_WINDOW_RESIZABLE;
if (cfg.flags & SKELE_VIDEO_HIGHDPI)
flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
display = SDL_GetPrimaryDisplay();
vid_w =
cfg.render_width ? cfg.render_width : SKELE_DEFAULT_RENDER_WIDTH;
vid_h =
cfg.render_height ? cfg.render_height : SKELE_DEFAULT_RENDER_HEIGHT;
if (cfg.window_width && cfg.window_height) {
window_w = cfg.window_width;
window_h = cfg.window_height;
cur_scale = 1;
} else {
mode = SDL_GetCurrentDisplayMode(display);
if (!mode) {
stk_log(STK_LOG_ERROR,
"video: SDL_GetCurrentDisplayMode failed: %s",
SDL_GetError());
SDL_Quit();
return SKELE_INIT_FAILURE;
}
aw = (uint16_t)((mode->w * 3) / 4);
ah = (uint16_t)((mode->h * 3) / 4);
cur_scale = 1;
while ((vid_w * (cur_scale + 1)) <= aw &&
(vid_h * (cur_scale + 1)) <= ah)
cur_scale++;
window_w = vid_w * cur_scale;
window_h = vid_h * cur_scale;
}
window = SDL_CreateWindow("skele", window_w, window_h,
flags | SDL_WINDOW_HIDDEN);
if (!window) {
stk_log(STK_LOG_ERROR, "video: SDL_CreateWindow failed: %s",
SDL_GetError());
SDL_Quit();
return SKELE_INIT_FAILURE;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
fullscreen = 1;
gl_ctx = SDL_GL_CreateContext(window);
if (!gl_ctx) {
stk_log(STK_LOG_ERROR, "video: SDL_GL_CreateContext failed: %s",
SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return SKELE_INIT_FAILURE;
}
SDL_GL_SetSwapInterval(1);
SDL_ShowWindow(window);
return SKELE_INIT_SUCCESS;
}
void skele_video_shutdown(void)
{
if (gl_ctx)
SDL_GL_DestroyContext(gl_ctx);
if (window)
SDL_DestroyWindow(window);
SDL_Quit();
gl_ctx = NULL;
window = NULL;
vid_w = 0;
vid_h = 0;
cur_scale = 1;
fullscreen = 0;
}
void skele_video_present(void) { SDL_GL_SwapWindow(window); }
void skele_video_toggle_fullscreen(void) { toggle_fullscreen(); }
void skele_video_cycle_scale(void) { cycle_scale(); }
void skele_video_set_mouse_grab(uint8_t grab)
{
SDL_SetWindowMouseGrab(window, grab ? true : false);
SDL_SetWindowRelativeMouseMode(window, grab ? true : false);
}
void skele_video_set_title(const char *title)
{
SDL_SetWindowTitle(window, title);
}
+253
View File
@@ -0,0 +1,253 @@
#include "client/blit.h"
#include "client/palette.h"
#include "client/video.h"
#include "skele.h"
#include <SDL3/SDL.h>
#include <stdint.h>
#include <stk/stk_log.h>
#include <string.h>
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static SDL_Palette *sdl_pal = NULL;
static uint16_t vid_w = 0;
static uint16_t vid_h = 0;
static uint32_t vid_total = 0;
static uint8_t cur_scale = 1;
static uint8_t fullscreen = 0;
static uint8_t max_scale(uint16_t rw, uint16_t rh)
{
SDL_DisplayID display;
const SDL_DisplayMode *mode;
uint16_t aw, ah;
uint8_t scale;
display =
window ? SDL_GetDisplayForWindow(window) : SDL_GetPrimaryDisplay();
mode = SDL_GetCurrentDisplayMode(display);
if (!mode)
return 1;
aw = (uint16_t)((mode->w * 3) / 4);
ah = (uint16_t)((mode->h * 3) / 4);
scale = 1;
while ((rw * (scale + 1)) <= aw && (rh * (scale + 1)) <= ah)
scale++;
return scale;
}
static void set_scale(uint8_t scale)
{
SDL_DisplayID display;
cur_scale = scale;
display = SDL_GetDisplayForWindow(window);
SDL_SetWindowSize(window, (int)(vid_w * scale), (int)(vid_h * scale));
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
}
static void toggle_fullscreen(void)
{
fullscreen = !fullscreen;
SDL_SetWindowFullscreen(window, fullscreen);
}
static void cycle_scale(void)
{
uint8_t next;
if (fullscreen)
return;
next = cur_scale + 1;
if (next > max_scale(vid_w, vid_h))
next = 1;
set_scale(next);
}
uint8_t skele_video_init(skele_video_config_t cfg)
{
SDL_DisplayID display;
SDL_WindowFlags flags = 0;
const SDL_DisplayMode *mode;
uint16_t window_w, window_h, aw, ah;
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) {
stk_log(STK_LOG_ERROR, "video: SDL_Init failed: %s",
SDL_GetError());
return SKELE_INIT_FAILURE;
}
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
flags |= SDL_WINDOW_FULLSCREEN;
if (cfg.flags & SKELE_VIDEO_BORDERLESS)
flags |= SDL_WINDOW_BORDERLESS;
if (cfg.flags & SKELE_VIDEO_RESIZABLE)
flags |= SDL_WINDOW_RESIZABLE;
if (cfg.flags & SKELE_VIDEO_HIGHDPI)
flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
display = SDL_GetPrimaryDisplay();
vid_w =
cfg.render_width ? cfg.render_width : SKELE_DEFAULT_RENDER_WIDTH;
vid_h =
cfg.render_height ? cfg.render_height : SKELE_DEFAULT_RENDER_HEIGHT;
vid_total = (uint32_t)(vid_w * vid_h);
if (cfg.window_width && cfg.window_height) {
window_w = cfg.window_width;
window_h = cfg.window_height;
cur_scale = 1;
} else {
mode = SDL_GetCurrentDisplayMode(display);
if (!mode) {
stk_log(STK_LOG_ERROR,
"video: SDL_GetCurrentDisplayMode failed: %s",
SDL_GetError());
SDL_Quit();
return SKELE_INIT_FAILURE;
}
aw = (uint16_t)((mode->w * 3) / 4);
ah = (uint16_t)((mode->h * 3) / 4);
cur_scale = 1;
while ((vid_w * (cur_scale + 1)) <= aw &&
(vid_h * (cur_scale + 1)) <= ah)
cur_scale++;
window_w = vid_w * cur_scale;
window_h = vid_h * cur_scale;
}
window = SDL_CreateWindow("skele", window_w, window_h,
flags | SDL_WINDOW_HIDDEN);
if (!window) {
stk_log(STK_LOG_ERROR, "video: SDL_CreateWindow failed: %s",
SDL_GetError());
SDL_Quit();
return SKELE_INIT_FAILURE;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
fullscreen = 1;
renderer = SDL_CreateRenderer(window, NULL);
if (!renderer) {
stk_log(STK_LOG_ERROR, "video: SDL_CreateRenderer failed: %s",
SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return SKELE_INIT_FAILURE;
}
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_INDEX8,
SDL_TEXTUREACCESS_STREAMING, vid_w, vid_h);
if (!texture) {
stk_log(STK_LOG_ERROR, "video: SDL_CreateTexture failed: %s",
SDL_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return SKELE_INIT_FAILURE;
}
sdl_pal = SDL_CreatePalette(SKELE_PALETTE_COLORS);
if (!sdl_pal) {
stk_log(STK_LOG_ERROR, "video: SDL_CreatePalette failed: %s",
SDL_GetError());
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return SKELE_INIT_FAILURE;
}
SDL_SetTexturePalette(texture, sdl_pal);
{
SDL_Color black[SKELE_PALETTE_COLORS];
uint16_t i;
memset(black, 0, sizeof(black));
for (i = 0; i < SKELE_PALETTE_COLORS; i++)
black[i].a = 255;
SDL_SetPaletteColors(sdl_pal, black, 0, SKELE_PALETTE_COLORS);
}
SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
SDL_SetRenderVSync(renderer, 1);
SDL_ShowWindow(window);
return SKELE_INIT_SUCCESS;
}
void skele_video_shutdown(void)
{
if (sdl_pal)
SDL_DestroyPalette(sdl_pal);
if (texture)
SDL_DestroyTexture(texture);
if (renderer)
SDL_DestroyRenderer(renderer);
if (window)
SDL_DestroyWindow(window);
SDL_Quit();
sdl_pal = NULL;
texture = NULL;
renderer = NULL;
window = NULL;
vid_w = 0;
vid_h = 0;
vid_total = 0;
cur_scale = 1;
fullscreen = 0;
}
void skele_video_present(void) { SDL_RenderPresent(renderer); }
void skele_video_toggle_fullscreen(void) { toggle_fullscreen(); }
void skele_video_cycle_scale(void) { cycle_scale(); }
void skele_video_set_mouse_grab(uint8_t grab)
{
SDL_SetWindowMouseGrab(window, grab ? true : false);
SDL_SetWindowRelativeMouseMode(window, grab ? true : false);
}
void skele_palette_set(skele_palette_t pal)
{
SDL_Color colors[SKELE_PALETTE_COLORS];
uint16_t i;
uint32_t c;
for (i = 0; i < SKELE_PALETTE_COLORS; i++) {
c = pal[i];
colors[i].r = (uint8_t)(c >> 16);
colors[i].g = (uint8_t)(c >> 8);
colors[i].b = (uint8_t)(c);
colors[i].a = 255;
}
SDL_SetPaletteColors(sdl_pal, colors, 0, SKELE_PALETTE_COLORS);
}
void skele_palette_set_index(uint8_t index, uint32_t color)
{
SDL_Color c;
c.r = (uint8_t)(color >> 16);
c.g = (uint8_t)(color >> 8);
c.b = (uint8_t)(color);
c.a = 255;
SDL_SetPaletteColors(sdl_pal, &c, index, 1);
}
void skele_video_blit(uint8_t *pixels)
{
SDL_UpdateTexture(texture, NULL, pixels, vid_w);
SDL_RenderTexture(renderer, texture, NULL, NULL);
}
void skele_video_set_title(const char *title)
{
SDL_SetWindowTitle(window, title);
}
+35
View File
@@ -0,0 +1,35 @@
#define _POSIX_C_SOURCE 199309L
#include "clock.h"
#include <signal.h>
#include <time.h>
static void (*signal_cb)(void) = NULL;
static void handle_signal(int sig)
{
(void)sig;
if (signal_cb)
signal_cb();
}
void skele_clock_init(void (*on_signal)(void))
{
signal_cb = on_signal;
signal(SIGINT, handle_signal);
signal(SIGTERM, handle_signal);
}
uint64_t skele_time_ns(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t)(ts.tv_sec * 1000000000ULL + ts.tv_nsec);
}
void skele_sleep_ns(uint64_t ns)
{
struct timespec ts;
ts.tv_sec = (time_t)(ns / 1000000000ULL);
ts.tv_nsec = (long)(ns % 1000000000ULL);
nanosleep(&ts, NULL);
}
+37
View File
@@ -0,0 +1,37 @@
#include "clock.h"
#include <windows.h>
static void (*signal_cb)(void) = NULL;
static LARGE_INTEGER perf_freq;
static BOOL WINAPI handle_ctrl(DWORD type)
{
(void)type;
if (signal_cb)
signal_cb();
return TRUE;
}
void skele_clock_init(void (*on_signal)(void))
{
signal_cb = on_signal;
QueryPerformanceFrequency(&perf_freq);
SetConsoleCtrlHandler(handle_ctrl, TRUE);
}
uint64_t skele_time_ns(void)
{
LARGE_INTEGER cnt;
QueryPerformanceCounter(&cnt);
return (uint64_t)(cnt.QuadPart * 1000000000ULL / perf_freq.QuadPart);
}
void skele_sleep_ns(uint64_t ns)
{
HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL);
LARGE_INTEGER li;
li.QuadPart = -(LONGLONG)(ns / 100);
SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE);
WaitForSingleObject(timer, INFINITE);
CloseHandle(timer);
}
+51
View File
@@ -0,0 +1,51 @@
#include "skele.h"
#include <stk/stk.h>
#include <stk/stk_log.h>
uint64_t skele_tick_ns = 1000000000ULL / SKELE_DEFAULT_TICK_RATE;
static uint8_t stk_initialized = 0;
const char *skele_version(void) { return "0.0.0"; }
void skele_set_tick_rate(uint8_t rate)
{
skele_tick_ns = 1000000000ULL / (rate ? rate : SKELE_DEFAULT_TICK_RATE);
}
uint8_t skele_init(void) { return SKELE_INIT_SUCCESS; }
void skele_shutdown(void) {}
void skele_tick(void) {}
uint8_t skele_stk_setup(void)
{
if (stk_initialized)
return SKELE_INIT_SUCCESS;
stk_set_log_prefix("skele");
stk_set_module_init_fn("skele_mod_init");
stk_set_module_shutdown_fn("skele_mod_shutdown");
stk_set_module_name_fn("skele_mod_name");
stk_set_module_version_fn("skele_mod_ver");
stk_set_module_description_fn("skele_mod_desc");
stk_set_module_deps_sym("skele_mod_deps");
if (stk_init() != STK_INIT_SUCCESS) {
stk_log(STK_LOG_ERROR, "failed to initialize stk");
return SKELE_INIT_FAILURE;
}
stk_initialized = 1;
stk_log(STK_LOG_INFO, "skele v%s", SKELE_VERSION);
return SKELE_INIT_SUCCESS;
}
void skele_stk_teardown(void)
{
if (!stk_initialized)
return;
stk_shutdown();
stk_initialized = 0;
}