Skip to content

Commit 9a26184

Browse files
committed
Harden the parser; add an error API; add web builds and a sample viewer; bump version to 1.1.0
That was quite a lot I've been dragging my feet on. Security and memory safety: * Fix discovered memory-safety bugs: signed-overflow in the warp grid expansion, an out-of-bounds read on negative keyframe indices, NULL+0 pointer arithmetic when the blend-key table is empty, NULL derefs on empty art-mesh bindings and missing key_count reads at the blend-window boundary, and an index underflow in psm__valid_range. * Improved fuzzing verification: PSM_DEBUG_MALLOC build mode that uses `malloc` for every model field. Public API: * Add per-model csmGetLastError / csmGetErrorString; record error codes in the MOC3 header's padding, and expose csmGetMocError so applications can receive detailed failure status. * Add csmGetExtendedVersionString() with embedded git hash to query the exact library build. * Misc. correctness fixes: propagate color to opacity-0 meshes and stop the v5.3 extended-modes bit masking constant-mode bits. Style / housekeeping: * .clang-format for the library (BSD-KNF) and samples/viewer (raylib layout), a clang-format pre-commit hook, make format/format-check targets, and a CI check. * Line wrapping, standardizing on `bool` for all booleans, remove VLAs, rename many symbols for consistency, and more! Sample viewer: * Implement a sample MOC3 viewer (both v5 and v6 ABI support) using Raylib. Supports all blend modes from v6. WASM port: * Web/WASM drop-in Live2DCubismCore.js for both v5 and v6. Build: * Makefile rewrite with per-OS shared rules and a proper platform matrix. WASM support also added. * Bundle now generated from a template (src/bundle.c.in) instead of manually by a script. * CMake build system added for cross-compilation. This should be easier to build on plain Windows. CI: * Misc improvements: cross-build is skipped on v* tag pushes (the release job rebuilds the matrix itself), and the release job verifies the tag matches PSM_TRUE_VERSION in the header before building. * Add WASM viewer build job.
1 parent 97dd2a5 commit 9a26184

83 files changed

Lines changed: 14259 additions & 2048 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.clang-format

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Purism Core house style: BSD KNF / OpenBSD style(9)-ish.
2+
# - return type on its own line for function definitions
3+
# - column-aligned declarations and #define values
4+
# - 2-space indent, control-statement braces attached, function braces on own line
5+
# - preprocessor directives indented after the '#'
6+
# Function-like "statement" macros (control-flow bodies) are hand-aligned and
7+
# fenced with `// clang-format off/on` where this config would reflow them.
8+
Language: Cpp
9+
BasedOnStyle: LLVM
10+
IndentWidth: 2
11+
UseTab: Never
12+
ContinuationIndentWidth: 4
13+
ColumnLimit: 0
14+
AlignAfterOpenBracket: DontAlign
15+
BreakBeforeBraces: Linux
16+
AlwaysBreakAfterReturnType: AllDefinitions
17+
PointerAlignment: Right
18+
AllowShortFunctionsOnASingleLine: None
19+
AllowShortIfStatementsOnASingleLine: WithoutElse
20+
AllowShortLoopsOnASingleLine: false
21+
SpaceBeforeParens: ControlStatements
22+
Cpp11BracedListStyle: false
23+
IndentCaseLabels: false
24+
KeepEmptyLinesAtTheStartOfBlocks: false
25+
SortIncludes: Never
26+
AlignEscapedNewlines: DontAlign
27+
AlignTrailingComments:
28+
Kind: Leave
29+
IndentPPDirectives: AfterHash
30+
AlignConsecutiveDeclarations: true
31+
AlignConsecutiveMacros: true

.githooks/pre-commit

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/sh
2+
# Pre-commit: reject staged C sources that aren't clang-format-clean.
3+
#
4+
# Enable once per clone: git config core.hooksPath .githooks (or: make hooks)
5+
# Override the binary: CLANG_FORMAT=clang-format-19 git commit ...
6+
#
7+
# Each file's nearest .clang-format decides the style; DisableFormat trees
8+
# (tests, samples, vendored) are no-ops. Checks the working-tree copy of the
9+
# staged files (the usual, fast approximation) -- if a file has both staged and
10+
# unstaged edits, format the whole file before committing.
11+
12+
CLANG_FORMAT="${CLANG_FORMAT:-clang-format}"
13+
14+
files=$(git diff --cached --name-only --diff-filter=ACM -- '*.c' '*.h')
15+
[ -z "$files" ] && exit 0
16+
17+
if ! command -v "$CLANG_FORMAT" >/dev/null 2>&1; then
18+
echo "pre-commit: $CLANG_FORMAT not found; skipping format check" >&2
19+
exit 0
20+
fi
21+
22+
if ! "$CLANG_FORMAT" --dry-run --Werror $files; then
23+
echo >&2
24+
echo "pre-commit: staged C sources need formatting." >&2
25+
echo " fix with: make format (then re-stage)" >&2
26+
exit 1
27+
fi
28+
exit 0

.github/workflows/ci.yml

Lines changed: 139 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,23 @@ on:
88
branches: [master]
99

1010
jobs:
11+
format:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: actions/setup-python@v5
17+
with:
18+
python-version: '3.x'
19+
20+
# Pinned: clang-format output drifts between major versions, so the gate
21+
# must use the same version the tree was formatted with.
22+
- name: Install clang-format
23+
run: pip install clang-format==19.1.7
24+
25+
- name: Check formatting
26+
run: make format-check
27+
1128
build-and-test:
1229
runs-on: ubuntu-latest
1330
steps:
@@ -28,41 +45,129 @@ jobs:
2845
cross-build:
2946
runs-on: ubuntu-latest
3047
needs: build-and-test
48+
# The release job rebuilds the whole matrix itself (and it is the only job
49+
# that can lipo a universal Viewer.app / dylib), so on a tag push the 7
50+
# cross-build targets + their artifact uploads are pure duplication -- skip
51+
# them and let release be the single build. (PR and branch pushes keep the
52+
# matrix, which uploads per-target artifacts for inspection.)
53+
if: github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/v')
3154
strategy:
3255
matrix:
3356
target:
34-
- linux-x64
35-
- linux-arm64
36-
- macos-x64
37-
- macos-arm64
38-
- win-x64
39-
- win-x86
40-
- win-arm64
57+
- zig-cross-linux-x86_64
58+
- zig-cross-linux-arm64
59+
- zig-cross-macos-x86_64
60+
- zig-cross-macos-arm64
61+
- zig-cross-windows-x86_64
62+
- zig-cross-windows-x86
63+
- zig-cross-windows-arm64
4164
steps:
4265
- uses: actions/checkout@v4
4366

4467
- uses: mlugg/setup-zig@v2
4568
with:
4669
version: 0.16.0
4770

71+
# raylib v6.0 release archive for this target (viewer-in-dist is opt-in
72+
# via RAYLIB_DIR_<PRESET> env vars; if a target has no archive -- e.g.
73+
# zig-cross-windows-arm64 only ships MSVC-built raylib -- the viewer is skipped and
74+
# the library still builds). Pinned to v6.0; bump here + in the release
75+
# job together when upgrading.
76+
- name: Fetch raylib v6.0 for ${{ matrix.target }}
77+
shell: bash
78+
run: |
79+
case "${{ matrix.target }}" in
80+
zig-cross-linux-x86_64) url=raylib-6.0_linux_amd64.tar.gz; var=RAYLIB_DIR_LINUX_AMD64; ext=tar.gz ;;
81+
zig-cross-linux-arm64) url=raylib-6.0_linux_arm64.tar.gz; var=RAYLIB_DIR_LINUX_ARM64; ext=tar.gz ;;
82+
zig-cross-macos-x86_64) url=raylib-6.0_macos.tar.gz; var=RAYLIB_DIR_MACOS; ext=tar.gz ;;
83+
zig-cross-macos-arm64) url=raylib-6.0_macos.tar.gz; var=RAYLIB_DIR_MACOS; ext=tar.gz ;;
84+
zig-cross-windows-x86_64) url=raylib-6.0_win64_mingw-w64.zip; var=RAYLIB_DIR_WINDOWS_AMD64; ext=zip ;;
85+
zig-cross-windows-x86) url=raylib-6.0_win32_mingw-w64.zip; var=RAYLIB_DIR_WINDOWS_X86; ext=zip ;;
86+
zig-cross-windows-arm64) echo "no raylib archive for windows-arm64"; exit 0 ;;
87+
esac
88+
mkdir -p build/raylib
89+
base="${url%.$ext}"
90+
if [ "$ext" = tar.gz ]; then
91+
curl -sL "https://github.com/raysan5/raylib/releases/download/6.0/$url" \
92+
-o "build/raylib/$url"
93+
tar -C build/raylib -xzf "build/raylib/$url"
94+
else
95+
curl -sL "https://github.com/raysan5/raylib/releases/download/6.0/$url" \
96+
-o "build/raylib/$url"
97+
( cd build/raylib && unzip -q "$url" )
98+
fi
99+
# Expose the extracted tree path to subsequent steps via GITHUB_ENV.
100+
echo "$var=$PWD/build/raylib/$base" >> "$GITHUB_ENV"
101+
48102
- name: Cross-build (${{ matrix.target }})
49-
run: ./scripts/zig-build.sh ${{ matrix.target }} --both
103+
run: ./scripts/build-dist.sh ${{ matrix.target }}
50104

51105
- name: Upload artifacts
52106
uses: actions/upload-artifact@v4
53107
with:
54108
name: ${{ matrix.target }}
55-
path: build/${{ matrix.target }}/
109+
path: dist/sdk/
110+
111+
wasm:
112+
runs-on: ubuntu-latest
113+
needs: build-and-test
114+
steps:
115+
- uses: actions/checkout@v4
116+
117+
# Pinned to the emsdk version raylib 6.0's own web build used, so the
118+
# archived libraylib.web.a stays ABI-compatible with this emcc.
119+
- uses: emscripten-core/setup-emsdk@v15
120+
with:
121+
version: 5.0.3
122+
123+
- name: Fetch raylib v6.0 (webassembly)
124+
run: |
125+
mkdir -p build/raylib
126+
curl -sL https://github.com/raysan5/raylib/releases/download/6.0/raylib-6.0_webassembly.zip \
127+
-o build/raylib/raylib-6.0_webassembly.zip
128+
( cd build/raylib && unzip -q raylib-6.0_webassembly.zip )
129+
echo "RAYLIB_WEB_DIR=$PWD/build/raylib/raylib-6.0_webassembly/include" >> "$GITHUB_ENV"
130+
echo "RAYLIB_WEB_LIB=$PWD/build/raylib/raylib-6.0_webassembly/lib/libraylib.web.a" >> "$GITHUB_ENV"
131+
132+
- name: Build web viewer (Emscripten)
133+
run: make viewer-web
134+
135+
- name: Upload artifacts
136+
uses: actions/upload-artifact@v4
137+
with:
138+
name: wasm
139+
path: |
140+
dist/Live2DCubismCore*.js
141+
dist/viewer.*
56142
57143
release:
58144
if: startsWith(github.ref, 'refs/tags/v')
59145
runs-on: ubuntu-latest
60-
needs: cross-build
146+
# Cross-build is skipped on tag pushes, so depend on build-and-test (which
147+
# always runs) rather than the matrix; release rebuilds the full matrix
148+
# itself anyway.
149+
needs: build-and-test
61150
permissions:
62151
contents: write
63152
steps:
64153
- uses: actions/checkout@v4
65154

155+
- name: Check tag matches PSM_TRUE_VERSION
156+
shell: bash
157+
run: |
158+
tag="${GITHUB_REF#refs/tags/}"; tag="${tag#v}"
159+
ver_hex=$(sed -n 's/^#define PSM_TRUE_VERSION[[:space:]]*\(0x[0-9A-Fa-f]*\).*/\1/p' include/PurismCore.h)
160+
[ -n "$ver_hex" ] || { echo "error: PSM_TRUE_VERSION not found in include/PurismCore.h" >&2; exit 1; }
161+
v_major=$(( ($ver_hex >> 24) & 0xFF ))
162+
v_minor=$(( ($ver_hex >> 16) & 0xFF ))
163+
v_patch=$(( $ver_hex & 0xFFFF ))
164+
version="$v_major.$v_minor.$v_patch"
165+
if [ "$tag" != "$version" ]; then
166+
echo "error: tag v$tag does not match PSM_TRUE_VERSION ($version)" >&2
167+
exit 1
168+
fi
169+
echo "ok: tag v$tag matches PSM_TRUE_VERSION ($version)"
170+
66171
- uses: mlugg/setup-zig@v2
67172
with:
68173
version: 0.16.0
@@ -73,6 +178,30 @@ jobs:
73178
-o /usr/local/bin/lipo
74179
chmod +x /usr/local/bin/lipo
75180
181+
# Download every raylib v6.0 archive the dist matrix needs (viewer-in-dist
182+
# is opt-in via RAYLIB_DIR_<PRESET>; without these env vars, build-dist.sh
183+
# silently skips the viewer and ships the libraries only).
184+
- name: Fetch raylib v6.0 (all targets)
185+
shell: bash
186+
run: |
187+
mkdir -p build/raylib
188+
fetch() { # <url> <top-dir-name> <ext> <env-var>
189+
url="$1"; top="$2"; ext="$3"; var="$4"
190+
curl -sL "https://github.com/raysan5/raylib/releases/download/6.0/$url" \
191+
-o "build/raylib/$url"
192+
if [ "$ext" = tar.gz ]; then
193+
tar -C build/raylib -xzf "build/raylib/$url"
194+
else
195+
( cd build/raylib && unzip -q "$url" )
196+
fi
197+
echo "$var=$PWD/build/raylib/$top" >> "$GITHUB_ENV"
198+
}
199+
fetch raylib-6.0_linux_amd64.tar.gz raylib-6.0_linux_amd64 tar.gz RAYLIB_DIR_LINUX_AMD64
200+
fetch raylib-6.0_linux_arm64.tar.gz raylib-6.0_linux_arm64 tar.gz RAYLIB_DIR_LINUX_ARM64
201+
fetch raylib-6.0_macos.tar.gz raylib-6.0_macos tar.gz RAYLIB_DIR_MACOS
202+
fetch raylib-6.0_win64_mingw-w64.zip raylib-6.0_win64_mingw-w64 zip RAYLIB_DIR_WINDOWS_AMD64
203+
fetch raylib-6.0_win32_mingw-w64.zip raylib-6.0_win32_mingw-w64 zip RAYLIB_DIR_WINDOWS_X86
204+
76205
- name: Build distribution
77206
run: ./scripts/build-dist.sh
78207

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ testdata/*
3232
# OS
3333
.DS_Store
3434
Thumbs.db
35+
/shot.png

0 commit comments

Comments
 (0)