tuxanci2-engine
Game engine for tuxanci2
Log | Files | Refs | README | LICENSE
commit cd1fb6247221505b3e6dad39b048fbc083f197ae
parent 1ab919054d645f987fcc904e143868f13712dfec
Author: Connor Thomson <connor@gnufault.org>
Date: Sun, 25 Oct 2026 20:45:28 -0700
I am so done with this submodule stuff
Diffstat:
9 files changed, 163 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
@@ -1,5 +1,5 @@
-# Tuxánci 2 Engine
-Game engine for tuxanci2
+# Tuxánci 2
+Top down shooter game
## Platforms
Tuxánci currently supports:
diff --git a/game/.gitignore b/game/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/game/Makefile b/game/Makefile
@@ -0,0 +1,4 @@
+TARGET := tuxanci2
+SRCS := src
+
+include ../sdk/sdk.mk
diff --git a/game/src/main.c b/game/src/main.c
@@ -0,0 +1,9 @@
+#include "tuxanci2.h"
+
+void main(void) {
+ while (1) {
+ ta_yield();
+ }
+
+ ta_exit(0);
+}
diff --git a/sdk/LICENSE b/sdk/LICENSE
@@ -0,0 +1,18 @@
+MIT License
+
+Copyright (c) 2026 Connor Thomson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
+EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/sdk/crt0.S b/sdk/crt0.S
@@ -0,0 +1,14 @@
+ .section .text.start
+ .globl _start
+
+_start:
+ # Call the main function
+ call main
+
+ # If for some reason that returns, call the exit syscall
+ li a7, 0
+ ecall
+
+ # If for some reason that fails, go into a infinite loop
+.loop:
+ j .loop
diff --git a/sdk/linker.ld b/sdk/linker.ld
@@ -0,0 +1,34 @@
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+
+SECTIONS {
+ . = 0;
+
+ .magic_number : {
+ BYTE(0x54) /* T */
+ BYTE(0x41) /* A */
+ BYTE(0x42) /* B */
+ BYTE(0x43) /* C */
+ }
+
+ .text : {
+ KEEP(*(.text.start))
+ *(.text .text.*)
+ }
+
+ .rodata : {
+ *(.rodata .rodata.* .srodata .srodata.*)
+ }
+
+ .data : {
+ *(.data .data.* .sdata .sdata.*)
+ }
+
+ .bss : {
+ *(.bss .bss.* .sbss .sbss.* COMMON)
+ }
+
+ /DISCARD/ : {
+ *
+ }
+}
diff --git a/sdk/sdk.mk b/sdk/sdk.mk
@@ -0,0 +1,49 @@
+CROSS ?= riscv32-unknown-elf-
+
+CC := $(CROSS)gcc
+OBJCOPY := $(CROSS)objcopy
+
+BUILD := build
+SDK_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
+
+OPT := 2
+MARCH := rv32im
+MABI := ilp32
+
+LINKER_SCRIPT := linker.ld
+
+CFLAGS := -O$(OPT) -march=$(MARCH) -mabi=$(MABI) -ffreestanding -fno-builtin -fno-pic -fno-stack-protector -nostdlib -Wall -Wextra -I$(SDK_DIR)
+ASFLAGS := -march=$(MARCH) -mabi=$(MABI)
+LDFLAGS := -nostdlib -static -T $(SDK_DIR)$(LINKER_SCRIPT) -Wl,--gc-sections
+
+SRC_FILES := $(sort $(foreach s,$(SRCS),$(if $(wildcard $(s)/.),$(shell find $(patsubst %/,%,$(s)) -name '*.c'),$(s))))
+
+OBJS := $(BUILD)/crt0.o $(addprefix $(BUILD)/,$(SRC_FILES:.c=.o))
+DEPS := $(OBJS:.o=.d)
+
+all: $(BUILD)/$(TARGET).tab
+
+$(BUILD)/$(TARGET).tab: $(BUILD)/$(TARGET).elf
+ $(OBJCOPY) -O binary $< $@
+
+$(BUILD)/$(TARGET).elf: $(OBJS)
+ $(CC) $(LDFLAGS) $^ -o $@
+
+$(BUILD)/%.o: %.c
+ @mkdir -p $(@D)
+ $(CC) $(CFLAGS) -MMD -MP -c $< -o $@
+
+$(BUILD)/%.o: %.S
+ @mkdir -p $(@D)
+ $(CC) $(ASFLAGS) -MMD -MP -c $< -o $@
+
+$(BUILD)/%.o: $(SDK_DIR)%.S
+ @mkdir -p $(@D)
+ $(CC) $(ASFLAGS) -MMD -MP -c $< -o $@
+
+clean:
+ rm -rf $(BUILD)
+
+-include $(DEPS)
+
+.PHONY: all clean
diff --git a/sdk/tuxanci2.h b/sdk/tuxanci2.h
@@ -0,0 +1,32 @@
+#ifndef TUXANCI2_H
+#define TUXANCI2_H
+
+#include <stdint.h>
+
+#define TA_SYS_EXIT 0
+#define TA_SYS_YIELD 1
+
+static inline int32_t ta_syscall(uint32_t num, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4) {
+ register uint32_t r0 __asm__("a0") = a0;
+ register uint32_t r1 __asm__("a1") = a1;
+ register uint32_t r2 __asm__("a2") = a2;
+ register uint32_t r3 __asm__("a3") = a3;
+ register uint32_t r4 __asm__("a4") = a4;
+ register uint32_t r7 __asm__("a7") = num;
+
+ __asm__ volatile("ecall" : "+r"(r0) : "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7) : "memory");
+
+ return (int32_t)r0;
+}
+
+static inline void ta_exit(int32_t code) {
+ ta_syscall(TA_SYS_EXIT, (uint32_t)code, 0, 0, 0, 0);
+
+ while (1) {}
+}
+
+static inline void ta_yield(void) {
+ ta_syscall(TA_SYS_YIELD, 0, 0, 0, 0, 0);
+}
+
+#endif // TUXANCI2_H