Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add C template #1981

Merged
merged 7 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ Makefile
!build/baremetalpi/Makefile
!build/baremetalpi/boot/Makefile
!build/baremetalpi/toolchain.cmake
!templates/c/Makefile
build/android/.gradle/
build/android/app/.externalNativeBuild/
build/android/app/build/
Expand Down Expand Up @@ -176,4 +177,4 @@ tic_mruby_wasm_build_config.rb.lock
build/mruby_vendor-prefix/
**/zig-cache
**/zig-out
.cache
.cache
71 changes: 71 additions & 0 deletions templates/c/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
ifndef WASI_SDK_PATH
$(error Download the WASI SDK (https://github.com/WebAssembly/wasi-sdk) and set $$WASI_SDK_PATH)
endif

CC = "$(WASI_SDK_PATH)/bin/clang" --sysroot="$(WASI_SDK_PATH)/share/wasi-sysroot"
CXX = "$(WASI_SDK_PATH)/bin/clang++" --sysroot="$(WASI_SDK_PATH)/share/wasi-sysroot"

# Optional dependency from binaryen for smaller builds
WASM_OPT = wasm-opt
WASM_OPT_FLAGS = -Oz --zero-filled-memory --strip-producers

# Whether to build for debugging instead of release
DEBUG = 0

# Compilation flags
CFLAGS = -W -Wall -Wextra -Werror -Wno-unused -Wconversion -Wsign-conversion -MMD -MP -fno-exceptions
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -O0 -g
else
CFLAGS += -DNDEBUG -Oz -flto
endif

# Linker flags
LDFLAGS = -Wl,-zstack-size=8192,--no-entry,--import-memory -mexec-model=reactor \
-Wl,--initial-memory=262144,--max-memory=262144,--global-base=98304
ifeq ($(DEBUG), 1)
LDFLAGS += -Wl,--export-all,--no-gc-sections
else
LDFLAGS += -Wl,--strip-all,--gc-sections,--lto-O3 -Oz
endif

OBJECTS = $(patsubst src/%.c, build/%.o, $(wildcard src/*.c))
OBJECTS += $(patsubst src/%.cpp, build/%.o, $(wildcard src/*.cpp))
DEPS = $(OBJECTS:.o=.d)

ifeq ($(OS), Windows_NT)
MKDIR_BUILD = if not exist build md build
RMDIR = rd /s /q
else
MKDIR_BUILD = mkdir -p build
RMDIR = rm -rf
endif

all: build/cart.wasm

# Link cart.wasm from all object files and run wasm-opt
build/cart.wasm: $(OBJECTS)
$(CXX) -o $@ $(OBJECTS) $(LDFLAGS)
ifneq ($(DEBUG), 1)
ifeq (, $(shell command -v $(WASM_OPT)))
@echo Tip: $(WASM_OPT) was not found. Install it from binaryen for smaller builds!
else
$(WASM_OPT) $(WASM_OPT_FLAGS) $@ -o $@
endif
endif

# Compile C sources
build/%.o: src/%.c
@$(MKDIR_BUILD)
$(CC) -c $< -o $@ $(CFLAGS)

# Compile C++ sources
build/%.o: src/%.cpp
@$(MKDIR_BUILD)
$(CXX) -c $< -o $@ $(CFLAGS)

.PHONY: clean
clean:
$(RMDIR) build

-include $(DEPS)
51 changes: 51 additions & 0 deletions templates/c/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# C Starter Project Template

## Pre-requisites

- [WASI SDK](https://github.com/WebAssembly/wasi-sdk)

## Files in this template

- ```buildcart.sh``` - convenience script to build and run the game cartridge
- ```buildwasm.sh``` - convenience script to build and run the Wasm program
- ```Makefile``` - convenience Makefile that builds the project
- ```wasmdemo.wasmp``` - TIC-80 Wasm 'script' file. Note the embedded game assets data at the end of the file.

## Building your game

Define the environment variable WASI_SDK_PATH; e.g., if you installed WASI
into ```$HOME/wasi-sdk```, then ```export WASI_SDK_PATH=$HOME/wasi-sdk```.

Edit ```src/main.c``` to implement your game. You are of course free to
organize your code in more than one C source file.

If you create sprites, map, music, etc., for your game, remember to
replace the game asset data at the end of ```wasmdemo.wasmp``` with
your creations.

To build the Wasm file, execute ```make```. This generates ```cart.wasm```
in the build directory. To run:

```
% tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary cart.wasm & run & exit'
```

The script ```buildwasm.sh``` contains above steps as a convenience.

To build a TIC-80 cartridge, first build the Wasm file, then build the
cartridge file:

```
% tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary cart.wasm & save game.tic & exit'
```

You can then run your cartridge as follows:

```
% tic80 --fs . --cmd 'load game.tic & run & exit'
```

The script ```buildcart.sh``` does the above steps as a convenience.

## Additional Notes
The TIC functions that provide standard library features are not added here. You should use the `memcpy` and `memset` functions provided by the C standard library instead.
Gota7 marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 6 additions & 0 deletions templates/c/buildcart.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
rm -f game.tic
make clean
make
tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary build/cart.wasm & save game.tic & exit'
tic80 --fs . --cmd 'load game.tic & run & exit'
4 changes: 4 additions & 0 deletions templates/c/buildwasm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
make clean
make
tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary build/cart.wasm & run & exit'
50 changes: 50 additions & 0 deletions templates/c/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "tic80.h"

#define max(a, b) (a > b) ? a : b
#define min(a, b) (a < b) ? a : b

// From WASI libc:
WASM_IMPORT("snprintf")
int snprintf(char* s, size_t n, const char* format, ...);

int t, x, y;
const char* m = "HELLO WORLD FROM C!";
int r = 0;
MouseData md;
uint8_t transcolors = { 14 };

WASM_EXPORT("BOOT")
void BOOT() {
t = 1;
x = 96;
y = 24;
}

WASM_EXPORT("TIC")
void TIC() {
cls(13);

// The standard demo.
if (btn(0) > 0) { y--; }
if (btn(1) > 0) { y++; }
if (btn(2) > 0) { x--; }
if (btn(3) > 0) { x++; }

spr(1+t%60/30*2, x, y, &transcolors, 1, 3, 0, 0, 2, 2);
print(m, 60, 84, 15, 1, 1, 0);
t++;

// Mouse example demonstrating use of libc function.
mouse(&md);
if (md.left) { r = r + 2; }
r--;
r = max(0, min(32, r));
line(md.x, 0, md.x, 136, 11);
line(0, md.y, 240, md.y, 11);
circ(md.x, md.y, r, 11);

const int BUFSIZ = 10;
char buf[BUFSIZ];
snprintf(buf, BUFSIZ, "(%03d,%03d)", md.x, md.y);
print(buf, 3, 3, 15, 0, 1, 1);
}
Loading